Development rules and guidelines for AI assistants working on the AquaDealers codebase. Following these rules prevents regressions, duplicated code, and broken business logic.
App.tsx for routes. Check the feature directory structure under src/features/. Understand where the change belongs.src/components/ui/ (23 components). Button has 9 variants, Card has 5, Modal has focus trap + portal. Don't create new UI primitives.farmer.total_due (triggers), cash_book, payment_allocations, transaction_events. Map the full impact before editing.lg: (1024px). Billing has separate mobile (3-step wizard) and desktop (2-step side-by-side) flows. Test both.FeatureGate gates features by subscription plan. Staff permissions are JSONB-based. Both may need updating for new features.create_bill_v2, process_return, etc.). Never bypass RPCs with direct inserts — they skip validation, triggers, and audit trails.npm test (Vitest unit tests) and npm run test:e2e (Playwright). Test at both mobile and desktop viewports.public/documents/ current.SUPABASE_ANON_KEY in supabase.ts is intentionally public (it's a publishable key). The service_role key must never appear in client code.supabase.rpc() for writes. Direct table inserts/updates skip validation, triggers, and audit logging.sonner for toasts, Modal for dialogs, Button variants for actions. No one-off styled components.src/ ├── admin/ # Admin portal (separate layout, own routes) ├── components/ │ ├── layout/ # AppLayout, Sidebar, BottomNav, PageShell │ ├── ui/ # 23 shared UI components │ └── auth/ # ProtectedRoute, FeatureGate, PlanGate ├── features/ # Feature modules (one directory per domain) │ └── [feature]/ │ ├── pages/ # Route-level components (React.lazy loaded) │ ├── components/ # Feature-specific UI │ ├── hooks/ # Feature-specific React hooks │ ├── services/ # Supabase queries and RPC calls │ └── utils/ # PDF generators, formatters, helpers ├── hooks/ # Shared hooks (useAuth, useBranch, etc.) ├── lib/ # Shared utilities (supabase, telemetry, PDF, WhatsApp) ├── stores/ # Zustand stores (auth, cart, subscription, branch, staff) └── types/ # TypeScript type definitions
| File | Lines | Purpose |
|---|---|---|
ProductSelector.tsx | ~1519 | Product catalog + cart for billing. The most complex UI component. Handles search, categories, FIFO lot display, farmer-specific pricing. |
InventoryDetailPage.tsx | ~1444 | Stock detail view with individual lots, movement history, rate adjustments, and expiry tracking. |
NewBillPage.tsx | ~800 | Bill creation wizard. Orchestrates mobile 3-step and desktop 2-step flows. |
useCheckout.ts | ~300 | Bill save logic. Builds the RPC payload, handles offline queuing, manages optimistic updates. |
billPdfGenerator.ts | ~200 | PDF generation using html2canvas + jsPDF. Renders bill HTML to canvas, converts to PDF. |
whatsAppService.ts | ~150 | Phone number normalization, wa.me URL generation, API message sending via edge function. |
whatsAppMessages.ts | ~300 | 10 WhatsApp message templates (bill, payment, reminder, statement, etc.). |
telemetry.ts | ~80 | PostHog analytics + Sentry error tracking initialization and configuration. |
queryClient.ts | ~50 | React Query configuration: staleTime, gcTime, offline persistence with IndexedDB. |
supabase.ts | ~30 | Supabase client initialization with the publishable anon key. |
User selects products → useCheckout builds payload → supabase.rpc('create_bill_v2', payload) → RPC atomically: validates stock, consumes FIFO lots, creates bill + items, allocates payment, updates farmer.total_due via trigger, logs transaction event → React Query cache invalidated → PDF generated client-side → optional WhatsApp notification.
Bill created offline with client_ref UUID → stored in IndexedDB via React Query persistence → on reconnect, create_bill_v2 called with same client_ref → RPC checks for existing bill with that client_ref → returns existing if found (idempotent), creates new if not.