feat: basic POS & invoicing (closes groombook/groombook#5)
- Add invoice_status and payment_method enums to schema - Add invoices table: appointmentId, clientId, subtotal/tax/tip/total cents, status (draft/pending/paid/void), paymentMethod, paidAt, notes - Add invoice_line_items table: invoiceId, description, qty, unitPrice, total - Migration 0002_invoices.sql with FK constraints and journal entry - POST /api/invoices — create invoice with line items - POST /api/invoices/from-appointment/:id — one-click invoice from appointment, pre-populated with service name and price; returns 409 if already invoiced - GET /api/invoices — list with optional ?status/clientId/appointmentId filters - GET /api/invoices/:id — invoice with line items - PATCH /api/invoices/:id — update status, payment method, tip, notes; auto-sets paidAt when marking paid; blocks edits on voided invoices - Add Invoice/InvoiceLineItem types to @groombook/types - InvoicesPage: list view with status filter, create from appointment modal, detail modal with tip input, payment method selector, Mark as Paid/Void actions - Add Invoices nav link in App.tsx Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -3,12 +3,14 @@ import { AppointmentsPage } from "./pages/Appointments.js";
|
||||
import { ClientsPage } from "./pages/Clients.js";
|
||||
import { ServicesPage } from "./pages/Services.js";
|
||||
import { StaffPage } from "./pages/Staff.js";
|
||||
import { InvoicesPage } from "./pages/Invoices.js";
|
||||
|
||||
const NAV_LINKS = [
|
||||
{ to: "/", label: "Appointments" },
|
||||
{ to: "/clients", label: "Clients" },
|
||||
{ to: "/services", label: "Services" },
|
||||
{ to: "/staff", label: "Staff" },
|
||||
{ to: "/invoices", label: "Invoices" },
|
||||
];
|
||||
|
||||
export function App() {
|
||||
@@ -54,6 +56,7 @@ export function App() {
|
||||
<Route path="/clients" element={<ClientsPage />} />
|
||||
<Route path="/services" element={<ServicesPage />} />
|
||||
<Route path="/staff" element={<StaffPage />} />
|
||||
<Route path="/invoices" element={<InvoicesPage />} />
|
||||
</Routes>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user