{"id":25635257,"url":"https://github.com/nascript/invoice-app","last_synced_at":"2025-07-01T14:31:32.422Z","repository":{"id":278122405,"uuid":"934586911","full_name":"nascript/invoice-app","owner":"nascript","description":null,"archived":false,"fork":false,"pushed_at":"2025-02-18T05:14:01.000Z","size":0,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-18T05:31:19.199Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nascript.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-18T04:37:00.000Z","updated_at":"2025-02-18T05:14:04.000Z","dependencies_parsed_at":"2025-02-18T05:41:48.797Z","dependency_job_id":null,"html_url":"https://github.com/nascript/invoice-app","commit_stats":null,"previous_names":["nascript/invoice-app"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nascript/invoice-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nascript%2Finvoice-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nascript%2Finvoice-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nascript%2Finvoice-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nascript%2Finvoice-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nascript","download_url":"https://codeload.github.com/nascript/invoice-app/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nascript%2Finvoice-app/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262981023,"owners_count":23394450,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-22T23:27:47.115Z","updated_at":"2025-07-01T14:31:32.391Z","avatar_url":"https://github.com/nascript.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Project Documentation\n\n## Overview\n\nThis project implements an **Add Invoice Page** and a **My Invoices Page** based on a **Figma design** and the initial challenge requirements. It uses **Next.js (App Router) v14**, **React Hook Form** + **Zod** for validation, **MUI** for UI components, and **TypeScript** in strict mode. Invoice data is stored in **localStorage** so that it persists upon page refresh.\n\n---\n\n## Project Structure\n\n```\nsrc/\n  app/\n    invoices/\n      add/\n        page.tsx\n      list/\n        page.tsx\n    layout.tsx\n    globals.css\n    page.tsx\n  components/\n    invoices/\n      InvoiceForm.tsx\n      InvoiceTable.tsx\n      FormField.tsx\n    layout/\n      Sidebar.tsx\n      Topbar.tsx\n  constants/\n    fieldstyles.ts\n  lib/\n    schemas/\n      invoiceSchema.ts\n    types/\n      invoice.ts\n  hooks/\n    useInvoices.ts\n  utils/\n    localStorage.ts\n    amountFormat.ts\n```\n\n---\n\n## Pages and Key Features\n\n### 1. Add Invoice Page (`/invoices/add`)\n\n- **`page.tsx`**:\n  - Initializes `useForm` (Zod + React Hook Form).\n  - Generates an invoice number automatically (`INVxxxxxx`).\n  - Calls **`InvoiceForm`** and shows a success banner after successful submission.\n\n- **`InvoiceForm.tsx`**:\n  - Fields:\n    1. **Name** (required, min length = 1)\n    2. **Number** (read-only, auto-generated)\n    3. **Due Date** (date input)\n    4. **Amount** (with `formatRupiah` and `parseRupiah`)\n    5. **Status** (Paid, Unpaid, Pending)\n  - Uses **Zod** for validation (`invoiceSchema`).\n  - On submit, it calls `addInvoice()` from **`useInvoices()`**.\n\n- **Success Notification**: A green banner below the form, showing “Invoice added successfully!” and extra info.\n\n### 2. My Invoices Page (`/invoices/list`)\n\n- **`page.tsx`**:\n  - Displays the **title** “My Invoices.”\n  - **Search** (rounded) and **Filter** (rounded) on the right, using MUI `\u003cSelect\u003e`.\n  - Wraps **`InvoiceTable`** in a card.\n  - Filters invoices by `searchValue` (name/number) and `statusValue` (Paid/Unpaid/Pending).\n  - Passes the filtered list to `\u003cInvoiceTable /\u003e`.\n\n- **`InvoiceTable.tsx`**:\n  - Columns: Invoice (name + number), Due Date, Status (colored chips), Amount (Rupiah), and Actions (3-dot menu).\n  - **Delete**: Calls `deleteInvoice(id)` from `useInvoices`.\n  - **Edit**: Optional (shows an alert “Edit invoice ID …”).\n  - **Search \u0026 Filter** states are stored in query params (`?search=xxx\u0026status=Paid`) so users can share the link.\n\n---\n\n## Supporting Components\n\n### **`Sidebar.tsx`**\n\n- Displays the “InvoiceHub” logo (Passion One font), plus “Add Invoice” and “My Invoices” menu items.\n- Uses `usePathname()` to detect active menu and highlight it (e.g., gray text).\n- **Fixed** on the left (`position: \"fixed\"`, `width: 280px`).\n\n### **`Topbar.tsx`**\n\n- A header bar showing user info (avatar, name, verified icon), plus optional icons (home, chat).\n- Some icons are circular with a mild background.\n\n### **`FormField.tsx`**\n\n- A reusable component for label + `\u003cTextField\u003e`.\n- Takes `labelText`, an optional `required` prop, etc.\n\n### **`useInvoices.ts`**\n\n- Loads invoice data from localStorage on mount.\n- Provides `addInvoice`, `deleteInvoice`, `updateInvoice`.\n- Data is stored in React state to be shared among pages.\n\n---\n\n## Zod Schema (`invoiceSchema.ts`)\n\n```ts\nimport { z } from \"zod\";\n\nexport const invoiceSchema = z.object({\n  name: z.string().min(1, \"Invoice name is required\"),\n  number: z.string().min(1, \"Invoice number is required\"),\n  dueDate: z.string().min(1, \"Due date is required\"),\n  amount: z.number().min(1, \"Amount must be greater than 0\"),\n  status: z.enum([\"Paid\", \"Unpaid\", \"Pending\"], {\n    errorMap: () =\u003e ({ message: \"Status is required\" }),\n  }),\n});\n\nexport type InvoiceFormData = z.infer\u003ctypeof invoiceSchema\u003e;\n```\n\n---\n\n## Technical Decisions\n\n1. **Next.js 14 App Router**: Facilitates nested routing in `app/` and a global `layout.tsx`.\n2. **React Hook Form + Zod**: Simplifies form validation, integrates strongly with TypeScript.\n3. **MUI**: Provides a robust set of UI components (TextField, Table, Select, etc.) plus theming.\n4. **Local Storage**: Keeps invoice data persisted across refreshes without needing a backend.\n5. **TypeScript**: Ensures type safety and fewer runtime errors.\n6. **Responsive**: MUI’s Grid (`xs={12} md={6}` etc.) handles different screen sizes well.\n\n---\n\n## Setup Instructions\n\n1. **Clone** the repository.\n2. **Install dependencies**:\n   ```bash\n   npm install\n   ```\n3. **Run** the development server:\n   ```bash\n   npm run dev\n   ```\n4. Open `http://localhost:3000` in your browser. You’ll be redirected to `/invoices/list`.\n\n---\n\n## Challenge Requirements \u0026 How They Are Met\n\n1. **Add Invoice Page**:\n   - A clean form with name, number (auto “INV...”), due date, amount (formatted “Rp x,xxx”), status.\n   - **Success banner** after submission.\n   - Zod validation + React Hook Form.\n\n2. **My Invoices Page**:\n   - **Table**: columns for name \u0026 number, due date, status (colored chips), amount (rupiah), actions (3-dot).\n   - **Search \u0026 status filter** → updates URL query params.\n   - **Delete** invoice.\n   - **Optional** edit (shows alert).\n   - Pastel chip colors for Paid, Unpaid, Pending.\n\n3. **Data Persistence**: localStorage prevents data loss on refresh.\n4. **Loading \u0026 Error**: Minimal loading in the custom hook, Zod form errors.\n5. **Responsive**: Uses MUI grid for layout.\n6. **UI**: Matches the Figma design with rounded search, filter, status chips, etc.\n\n---\n\n## Conclusion\n\nThis project fulfills the challenge by:\n\n- Providing **two main pages** (Add Invoice \u0026 My Invoices).\n- **Form** with auto-generated invoice number, currency formatting, and validations.\n- **Table** with searching, filtering, status chips, delete, optional edit.\n- Using **Next.js 14**, **React Hook Form + Zod**, **MUI**, and **TypeScript**.\n- Storing data in **localStorage** for persistence.\n- Ensuring a **responsive** layout that closely follows the Figma design.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnascript%2Finvoice-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnascript%2Finvoice-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnascript%2Finvoice-app/lists"}