Add super-admin invoices: settings templates and per-business issue flow.

Platform invoice templates live under Settings; each business can list and issue invoices with optional name and a meshkee.com public link.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-07-24 20:59:34 +03:30
co-authored by Cursor
parent db52a83f98
commit 8f4af7a16c
20 changed files with 1839 additions and 7 deletions
@@ -0,0 +1,100 @@
import { apiRequest } from '../lib/api'
import type {
CreateInvoiceItemTemplatePayload,
CreateInvoicePayload,
Invoice,
InvoiceItemTemplate,
InvoiceStatus,
InvoiceTemplatesResponse,
InvoicesListResponse,
UpdateInvoiceItemTemplatePayload,
} from '../types/invoice'
export function listInvoiceItemTemplates(signal?: AbortSignal) {
return apiRequest<InvoiceTemplatesResponse>('/invoice-item-templates', {
auth: true,
signal,
})
}
export function createInvoiceItemTemplate(payload: CreateInvoiceItemTemplatePayload) {
return apiRequest<InvoiceItemTemplate>('/invoice-item-templates', {
method: 'POST',
auth: true,
body: payload,
})
}
export function updateInvoiceItemTemplate(
templateId: string,
payload: UpdateInvoiceItemTemplatePayload,
) {
return apiRequest<InvoiceItemTemplate>(`/invoice-item-templates/${templateId}`, {
method: 'PATCH',
auth: true,
body: payload,
})
}
export function deleteInvoiceItemTemplate(templateId: string) {
return apiRequest<{ ok: boolean }>(`/invoice-item-templates/${templateId}`, {
method: 'DELETE',
auth: true,
})
}
export interface ListBusinessInvoicesParams {
page?: number
pageSize?: number
status?: InvoiceStatus
}
export function listBusinessInvoices(
businessId: string,
params: ListBusinessInvoicesParams = {},
signal?: AbortSignal,
) {
const search = new URLSearchParams()
if (params.page) search.set('page', String(params.page))
if (params.pageSize) search.set('pageSize', String(params.pageSize))
if (params.status) search.set('status', params.status)
const qs = search.toString()
return apiRequest<InvoicesListResponse>(
`/businesses/${businessId}/invoices${qs ? `?${qs}` : ''}`,
{ auth: true, signal },
)
}
export function getBusinessInvoice(businessId: string, invoiceId: string, signal?: AbortSignal) {
return apiRequest<Invoice>(`/businesses/${businessId}/invoices/${invoiceId}`, {
auth: true,
signal,
})
}
export function createBusinessInvoice(businessId: string, payload: CreateInvoicePayload) {
return apiRequest<Invoice>(`/businesses/${businessId}/invoices`, {
method: 'POST',
auth: true,
body: payload,
})
}
export function updateBusinessInvoiceStatus(
businessId: string,
invoiceId: string,
payload: { status: InvoiceStatus; notes?: string },
) {
return apiRequest<Invoice>(`/businesses/${businessId}/invoices/${invoiceId}`, {
method: 'PATCH',
auth: true,
body: payload,
})
}
export function deleteBusinessInvoice(businessId: string, invoiceId: string) {
return apiRequest<{ ok: boolean }>(`/businesses/${businessId}/invoices/${invoiceId}`, {
method: 'DELETE',
auth: true,
})
}