# JSON Data Structure All UI data is now loaded from JSON files, making the application data-driven and easily configurable without code changes. ## Data Source **Primary Data File**: `/src/data/app-data.json` This file contains all sample data for the application, including: - Timesheets - Invoices - Payroll Runs - Workers - Compliance Documents - Expenses - Rate Cards - Clients ## How It Works ### 1. Data Loading Flow ``` app-data.json → use-sample-data hook → KV Storage → use-app-data hook → Components ``` 1. **app-data.json** - Static JSON file with initial/seed data 2. **use-sample-data** - Loads JSON data into KV storage on first run 3. **use-app-data** - Reads from KV storage and provides reactive state 4. **Components** - Use the reactive data from use-app-data ### 2. Initial Data Load When the application first loads (or when KV storage is empty), the `useSampleData` hook: - Checks if data has been initialized (`sample-data-initialized` flag) - If not initialized, loads data from `app-data.json` - Populates KV storage with all data entities - Sets the initialization flag to prevent re-loading ### 3. Persistent Storage All data is stored in KV storage, which persists between sessions. This means: - User modifications are preserved - Data survives page refreshes - Each user has their own data instance ## Data Schema ### Timesheets ```typescript { id: string // Unique timesheet ID workerId: string // Reference to worker workerName: string // Worker's name clientName: string // Client company name weekEnding: string // ISO date string totalHours: number // Total hours worked regularHours: number // Standard hours overtimeHours: number // Overtime hours status: string // "pending" | "approved" | "disputed" rate: number // Hourly rate total: number // Total amount submittedDate: string // ISO date-time string approvedDate?: string // Optional approval date shifts: Shift[] // Array of shift details } Shift: { date: string // ISO date string start: string // Time "HH:MM" end: string // Time "HH:MM" hours: number // Hours worked type: string // "regular" | "night" | "weekend" | "overtime" } ``` ### Invoices ```typescript { id: string // Unique invoice ID clientName: string // Client company name amount: number // Net amount vat: number // VAT/Tax amount total: number // Gross total status: string // "paid" | "pending" | "overdue" | "draft" dueDate: string // ISO date string invoiceDate: string // ISO date string paidDate?: string // Optional payment date items: InvoiceItem[] // Line items } InvoiceItem: { description: string // Item description quantity: number // Quantity rate: number // Unit rate amount: number // Total amount } ``` ### Payroll Runs ```typescript { id: string // Unique payroll run ID periodEnding: string // ISO date string status: string // "completed" | "pending" | "processing" totalGross: number // Total gross pay totalNet: number // Total net pay totalTax: number // Total tax withheld totalNI: number // Total National Insurance processedDate?: string // Optional processing date paymentDate?: string // Optional payment date workerCount: number // Number of workers entries: PayrollEntry[] // Individual worker entries } PayrollEntry: { workerId: string // Reference to worker workerName: string // Worker's name gross: number // Gross pay net: number // Net pay tax: number // Tax withheld ni: number // National Insurance } ``` ### Workers ```typescript { id: string // Unique worker ID name: string // Full name email: string // Email address phone: string // Phone number status: string // "active" | "inactive" | "onboarding" role: string // Job role/title startDate: string // ISO date string paymentType: string // "Limited Company" | "PAYE" | "CIS" currentClient: string // Current client assignment } ``` ### Compliance Documents ```typescript { id: string // Unique document ID workerId: string // Reference to worker workerName: string // Worker's name documentType: string // Document type name status: string // "valid" | "expiring" | "expired" expiryDate: string // ISO date string uploadDate: string // ISO date string verifiedDate: string // ISO date string } ``` ### Expenses ```typescript { id: string // Unique expense ID workerId: string // Reference to worker workerName: string // Worker's name category: string // "Travel" | "Accommodation" | "Meals" | "Equipment" amount: number // Expense amount date: string // ISO date string status: string // "approved" | "pending" | "rejected" description: string // Expense description receiptAttached: boolean// Receipt attachment status approvedDate?: string // Optional approval date rejectedDate?: string // Optional rejection date rejectionReason?: string// Optional rejection reason } ``` ### Rate Cards ```typescript { id: string // Unique rate card ID role: string // Job role/title clientName: string // Client company name payRate: number // Hourly pay rate chargeRate: number // Hourly charge rate margin: number // Margin amount marginPercent: number // Margin percentage currency: string // Currency code (e.g., "GBP") validFrom: string // ISO date string validUntil: string // ISO date string overtimeMultiplier: number // Overtime rate multiplier weekendMultiplier: number // Weekend rate multiplier nightMultiplier?: number // Optional night shift multiplier } ``` ### Clients ```typescript { id: string // Unique client ID name: string // Company name industry: string // Industry sector status: string // "active" | "inactive" | "suspended" creditLimit: number // Credit limit outstandingBalance: number // Current outstanding balance paymentTerms: number // Payment terms in days activeWorkers: number // Number of active workers address: string // Full address } ``` ## Hooks ### useJsonData() Direct access to JSON data (read-only). ```typescript import { useJsonData } from '@/hooks' function MyComponent() { const { data, isLoading, error } = useJsonData() if (isLoading) return