|
1 | | -<!-- BEGIN:nextjs-agent-rules --> |
| 1 | +You are an expert full-stack engineer specializing in the *FCF Tracker* application — Friends Cooperative Fund (AITS batch) — a financial contribution / loans / donations tracker with role-based access (admin/user). You build with Next.js App Router, Supabase Auth (Google-only allowlist), Tailwind v4, and TypeScript strict. |
| 2 | + |
| 3 | +## Commands |
| 4 | + |
| 5 | +- `npm run dev` — start dev server (default port 3000) |
| 6 | +- `npm run build` — production build; must pass before any PR |
| 7 | +- `npm run lint` — ESLint; auto-fixable issues should be fixed |
| 8 | + |
| 9 | +## Progressive context |
| 10 | + |
| 11 | +Load only the file matching the task; do not preload all of these. |
| 12 | + |
| 13 | +| Task | File | |
| 14 | +| :---------------------- | :----------------------- | |
| 15 | +| Supabase schema | docs/supabase-schema.sql | |
| 16 | +| Supabase setup guide | docs/supabase-setup.md | |
| 17 | +| Vercel deployment guide | docs/vercel-setup.md | |
| 18 | +| Design tokens & system | DESIGN.md | |
| 19 | + |
| 20 | +## Golden rules |
| 21 | + |
| 22 | +- **Authorization on every server action.** Never trust the client; re-check `getCurrentUser()` and role before any mutation. |
| 23 | +- **Supabase server client** (`@/lib/supabase/server`) in Server Components and actions; **browser client** (`@/lib/supabase/client`) only in client components that need it. |
| 24 | +- **Server Components by default.** Add `'use client'` only when interactivity is required (state, effects, event handlers). |
| 25 | +- **`useActionState` for form handling** in client components. |
| 26 | +- **Form actions are server actions in `@/lib/actions/`.** They never use `redirect()` for success — return `{ success: string }` instead, and let the client component navigate via `useRouter`. `redirect()` is OK for hard auth flows (e.g., `signInWithGoogle`, `signOut`, unauth fallback in layouts). |
| 27 | +- **💰 Currency:** all rupee values render via `formatRupees(n)` from `@/lib/format`. Locale is pinned to `en-IN` (e.g. `₹1,00,000`, not `₹100,000`). **Never use `$`** and never call `.toLocaleString()` without a locale — it causes hydration mismatches. |
| 28 | +- **🤝 Members are the canonical "person".** Bank accounts, transactions, and loans reference `public.members(id)`. `public.profiles` is the auth-linked row; not all members have a profile. |
| 29 | +- **Loan numbers and transaction IDs are auto-generated.** Postgres triggers fill `loan_number` (`YYYYMMDD-NNN`, running serial) and `transaction_id` (`YYYYMMDD-NNN`, per-date serial) on insert when the column is left empty. |
| 30 | +- **Interest rate is a global setting** stored at `public.app_settings.value` where `key = 'interest_per_lakh'`. Read with `getInterestPerLakh()`. Never hardcode the rate. |
| 31 | + |
| 32 | +## Stack |
| 33 | + |
| 34 | +| Layer | Version | |
| 35 | +| :----------- | :------------------ | |
| 36 | +| Next.js | 16.2 (App Router, Turbopack) | |
| 37 | +| React | 19.x | |
| 38 | +| TypeScript | 5.x — strict: true | |
| 39 | +| Tailwind CSS | v4 | |
| 40 | +| Database | Supabase (Postgres) | |
| 41 | +| Auth | Supabase Auth — Google OAuth + Before-User-Created allowlist hook | |
| 42 | +| Charts | Recharts | |
| 43 | +| Validation | Zod (when needed) | |
| 44 | + |
| 45 | +## File structure |
| 46 | + |
| 47 | +``` |
| 48 | +src/ |
| 49 | + proxy.ts # Auth session refresh |
| 50 | + app/ |
| 51 | + page.tsx # Landing |
| 52 | + layout.tsx # Root <html> + metadata |
| 53 | + icon.png # Browser favicon (Next convention) |
| 54 | + apple-icon.png # iOS home-screen icon |
| 55 | + auth/ |
| 56 | + login/page.tsx # Google sign-in (no email/password) |
| 57 | + callback/route.ts # OAuth callback |
| 58 | + (app)/ # ← Route group; URLs are unchanged |
| 59 | + layout.tsx # Sidebar + TopBar shell, requires auth |
| 60 | + dashboard/ |
| 61 | + page.tsx # KPI tiles + 3-color monthly chart + recent activity |
| 62 | + contributions/page.tsx # Member-filtered contributions table |
| 63 | + loans/page.tsx # Read-only loan list |
| 64 | + loans/[loan_number]/page.tsx # Read-only loan detail (KPIs + history) |
| 65 | + donations/page.tsx # Donations section view |
| 66 | + submit-payment-form.tsx # Inline on /dashboard |
| 67 | + bank-accounts-section.tsx # Inline on /dashboard |
| 68 | + admin/ |
| 69 | + page.tsx # Admin home (totals + nav cards) |
| 70 | + loans/page.tsx # Admin loan list (Manage link → detail) |
| 71 | + loans/new/page.tsx # Create loan (auto-numbered) |
| 72 | + loans/[loan_number]/page.tsx # Edit + Close/Reopen forms |
| 73 | + transactions/new/page.tsx # Create transaction |
| 74 | + pending/page.tsx # User-submitted payments to verify |
| 75 | + bank-accounts/page.tsx # Member bank account CRUD |
| 76 | + rules/ |
| 77 | + page.tsx # Overview |
| 78 | + v1/page.tsx # Original 2020 resolutions |
| 79 | + v2/page.tsx # Revised 2023 resolutions |
| 80 | +
|
| 81 | + components/ |
| 82 | + layout/sidebar.tsx # Blue gradient sidebar with emoji icons |
| 83 | + layout/top-bar.tsx # Sticky breadcrumb + centered logo + avatar |
| 84 | + charts/dashboard-bars.tsx # Recharts stacked bars + section single-series |
| 85 | + transactions-table.tsx # Shared table component |
| 86 | + section-view.tsx # Loans + Donations section page template |
| 87 | + kpi-tile.tsx # KPI card |
| 88 | + year-picker.tsx # URL-driven year filter |
| 89 | + searchable-select.tsx # Generic combobox with type-to-search |
| 90 | +
|
| 91 | + lib/ |
| 92 | + format.ts # formatRupees(), formatRupeesCompact() |
| 93 | + aggregate.ts # Server-side data shaping (months, sums) |
| 94 | + constants.ts # CONTRIBUTION_TYPES, PAYMENT_STATUS |
| 95 | + breadcrumbs.ts # Pathname → page title + crumbs |
| 96 | + transaction-groups.ts # Section → type mapping + chart palette |
| 97 | + seed-to-transactions.ts # Synthesize Excel rows into transactions |
| 98 | + supabase/client.ts # Browser Supabase client |
| 99 | + supabase/server.ts # Server Supabase client (cookies) |
| 100 | + supabase/proxy.ts # Proxy / session refresh client |
| 101 | + actions/auth.ts # signInWithGoogle, signOut, getCurrentUser |
| 102 | + actions/transactions.ts # createTransaction, getTransactions, stats |
| 103 | + actions/payments.ts # submit/approve/reject pending payments |
| 104 | + actions/loans.ts # CRUD, getInterestPerLakh, close/reopen |
| 105 | + actions/bank-accounts.ts # CRUD + getMembersForBankAccountForm |
| 106 | +
|
| 107 | + data/ |
| 108 | + seed.json # Excel → JSON (1.3K historical txns) |
| 109 | + seed.ts # Typed view of seed.json |
| 110 | +
|
| 111 | +scripts/ |
| 112 | + extract_data.py # Excel → seed.json |
| 113 | + generate-migration.mjs # seed.json → migrate-seed-to-db.sql |
| 114 | + generate-interest-fix.mjs # seed.json → fix-interest.sql |
| 115 | + migrate-seed-to-db.sql # One-shot seed: members + 1.3K transactions |
| 116 | + seed-loans.sql # Backfill loans table from seed |
| 117 | + loans-feature.sql # Loans schema + triggers + backfill |
| 118 | + bank-accounts-to-members.sql # Switch bank accounts off profiles |
| 119 | + dedupe-members.sql # Reduce 46 imported members → canonical 22 |
| 120 | + fix-interest.sql # Re-classify SEED-BANKINT/SEED-LOANINT rows |
| 121 | +
|
| 122 | +docs/ |
| 123 | + supabase-schema.sql # Authoritative schema |
| 124 | + supabase-setup.md # First-time Supabase + Google setup |
| 125 | + vercel-setup.md # Deploy guide |
| 126 | +``` |
| 127 | + |
| 128 | +## Database tables (Supabase) |
| 129 | + |
| 130 | +| Table | Purpose | |
| 131 | +| :----------------- | :---------------------------------------------------------------------- | |
| 132 | +| `auth.users` | Supabase-managed; we never write directly. | |
| 133 | +| `profiles` | 1:1 with auth.users. Holds `role` ('admin'/'user') and `full_name`. | |
| 134 | +| `allowed_emails` | Allowlist gating Google sign-in (via `enforce_email_allowlist` hook). | |
| 135 | +| `members` | 22 canonical contributors. Independent of auth — backfilled from Excel. | |
| 136 | +| `loans` | First-class loans. `loan_number` auto-generated. Per-loan history. | |
| 137 | +| `transactions` | All money movements. References `member_id` and (optionally) `loan_id`. | |
| 138 | +| `pending_payments` | User-submitted, awaiting admin verification → approves into transactions.| |
| 139 | +| `bank_accounts` | Per-member bank account details (admin-managed). | |
| 140 | +| `app_settings` | Global key/value config (e.g., `interest_per_lakh = 650`). | |
| 141 | + |
| 142 | +RLS is **disabled** project-wide — this is a small trusted group; write protection is enforced at the server-action layer. |
| 143 | + |
| 144 | +## Boundaries |
| 145 | + |
| 146 | +- ✅ *Always:* derive colors and spacing from Tailwind utility classes; match DESIGN.md tokens. |
| 147 | +- ✅ *Always:* render currency via `formatRupees(...)` from `@/lib/format` (never raw `${n.toLocaleString()}`). |
| 148 | +- ⚠️ *Ask first:* before adding a new dependency, changing the DB schema, or introducing a new top-level route segment. |
| 149 | +- 🚫 *Never:* hardcode hex colors *except* in `src/lib/transaction-groups.ts` (the data-viz palette is a documented exception — see DESIGN.md). |
| 150 | +- 🚫 *Never:* put business logic in client components (use server actions / server components). |
| 151 | +- 🚫 *Never:* use `redirect()` for form-action success (return `{ success }` and navigate from the client). |
| 152 | + |
2 | 153 | # This is NOT the Next.js you know |
3 | 154 |
|
4 | 155 | This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. |
5 | | -<!-- END:nextjs-agent-rules --> |
| 156 | + |
| 157 | +# userEmail |
| 158 | + |
| 159 | +The user's email address is pkorrakuti@mavvrik.ai. |
| 160 | + |
| 161 | +# currentDate |
| 162 | + |
| 163 | +Today's date is 2026-05-20. |
0 commit comments