Ship invoice templates, public viewer, and print-ready show page.

Move template/issue editors to full pages, add public invoice SPA with PDF print, and local-aware public URLs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-07-26 11:04:29 +03:30
co-authored by Cursor
parent 8f4af7a16c
commit cbffb23ec3
20 changed files with 2501 additions and 564 deletions
@@ -2,16 +2,21 @@ import { apiRequest } from '../lib/api'
import type {
CreateInvoiceItemTemplatePayload,
CreateInvoicePayload,
CreateInvoiceTemplatePayload,
Invoice,
InvoiceItemTemplate,
InvoiceItemTemplatesResponse,
InvoiceStatus,
InvoiceTemplatesResponse,
InvoiceTemplate,
InvoiceTemplatesListResponse,
InvoicesListResponse,
PublicInvoice,
UpdateInvoiceItemTemplatePayload,
UpdateInvoiceTemplatePayload,
} from '../types/invoice'
export function listInvoiceItemTemplates(signal?: AbortSignal) {
return apiRequest<InvoiceTemplatesResponse>('/invoice-item-templates', {
return apiRequest<InvoiceItemTemplatesResponse>('/invoice-item-templates', {
auth: true,
signal,
})
@@ -43,6 +48,43 @@ export function deleteInvoiceItemTemplate(templateId: string) {
})
}
export function listInvoiceTemplates(signal?: AbortSignal) {
return apiRequest<InvoiceTemplatesListResponse>('/invoice-templates', {
auth: true,
signal,
})
}
export function getInvoiceTemplate(templateId: string, signal?: AbortSignal) {
return apiRequest<InvoiceTemplate>(`/invoice-templates/${templateId}`, {
auth: true,
signal,
})
}
export function createInvoiceTemplate(payload: CreateInvoiceTemplatePayload) {
return apiRequest<InvoiceTemplate>('/invoice-templates', {
method: 'POST',
auth: true,
body: payload,
})
}
export function updateInvoiceTemplate(templateId: string, payload: UpdateInvoiceTemplatePayload) {
return apiRequest<InvoiceTemplate>(`/invoice-templates/${templateId}`, {
method: 'PATCH',
auth: true,
body: payload,
})
}
export function deleteInvoiceTemplate(templateId: string) {
return apiRequest<{ ok: boolean }>(`/invoice-templates/${templateId}`, {
method: 'DELETE',
auth: true,
})
}
export interface ListBusinessInvoicesParams {
page?: number
pageSize?: number
@@ -98,3 +140,11 @@ export function deleteBusinessInvoice(businessId: string, invoiceId: string) {
auth: true,
})
}
/** Public show-page payload (no auth). */
export function getPublicInvoice(invoiceId: string, signal?: AbortSignal) {
return apiRequest<PublicInvoice>(`/public/invoices/${invoiceId}`, {
auth: false,
signal,
})
}