OOOOOPS
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m56s

This commit is contained in:
2026-01-19 23:39:00 -07:00
parent effc6ac37e
commit 54cac49b70
22 changed files with 350 additions and 280 deletions

View File

@@ -267,16 +267,16 @@ const isDraft = invoice.status === 'draft';
<h4 class="text-sm font-bold mb-3">Add Item</h4>
<div class="grid grid-cols-1 sm:grid-cols-12 gap-4 items-end">
<div class="sm:col-span-6">
<label class="label label-text text-xs pt-0">Description</label>
<input type="text" name="description" class="input input-sm input-bordered w-full" required placeholder="Service or product..." />
<label class="label text-xs pt-0" for="item-description">Description</label>
<input type="text" id="item-description" name="description" class="input input-sm input-bordered w-full" required placeholder="Service or product..." />
</div>
<div class="sm:col-span-2">
<label class="label label-text text-xs pt-0">Qty</label>
<input type="number" name="quantity" step="0.01" class="input input-sm input-bordered w-full" required value="1" />
<label class="label text-xs pt-0" for="item-quantity">Qty</label>
<input type="number" id="item-quantity" name="quantity" step="0.01" class="input input-sm input-bordered w-full" required value="1" />
</div>
<div class="sm:col-span-3">
<label class="label label-text text-xs pt-0">Unit Price ({invoice.currency})</label>
<input type="number" name="unitPrice" step="0.01" class="input input-sm input-bordered w-full" required placeholder="0.00" />
<label class="label text-xs pt-0" for="item-unit-price">Unit Price ({invoice.currency})</label>
<input type="number" id="item-unit-price" name="unitPrice" step="0.01" class="input input-sm input-bordered w-full" required placeholder="0.00" />
</div>
<div class="sm:col-span-1">
<button type="submit" class="btn btn-sm btn-primary w-full">
@@ -349,11 +349,12 @@ const isDraft = invoice.status === 'draft';
<p class="py-4">Enter the tax percentage to apply to the subtotal.</p>
<form method="POST" action={`/api/invoices/${invoice.id}/update-tax`}>
<div class="form-control mb-6">
<label class="label">
<span class="label-text">Tax Rate (%)</span>
<label class="label" for="tax-rate">
Tax Rate (%)
</label>
<input
type="number"
id="tax-rate"
name="taxRate"
step="0.01"
min="0"

View File

@@ -60,11 +60,12 @@ const discountValueDisplay = invoice.discountType === 'fixed'
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Number -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Number</span>
<label class="label font-semibold" for="invoice-number">
Number
</label>
<input
type="text"
id="invoice-number"
name="number"
class="input input-bordered font-mono"
value={invoice.number}
@@ -74,10 +75,10 @@ const discountValueDisplay = invoice.discountType === 'fixed'
<!-- Currency -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Currency</span>
<label class="label font-semibold" for="invoice-currency">
Currency
</label>
<select name="currency" class="select select-bordered w-full">
<select id="invoice-currency" name="currency" class="select select-bordered w-full">
<option value="USD" selected={invoice.currency === 'USD'}>USD ($)</option>
<option value="EUR" selected={invoice.currency === 'EUR'}>EUR (€)</option>
<option value="GBP" selected={invoice.currency === 'GBP'}>GBP (£)</option>
@@ -88,11 +89,12 @@ const discountValueDisplay = invoice.discountType === 'fixed'
<!-- Issue Date -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Issue Date</span>
<label class="label font-semibold" for="invoice-issue-date">
Issue Date
</label>
<input
type="date"
id="invoice-issue-date"
name="issueDate"
class="input input-bordered"
value={issueDateStr}
@@ -102,13 +104,12 @@ const discountValueDisplay = invoice.discountType === 'fixed'
<!-- Due Date -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">
{invoice.type === 'quote' ? 'Valid Until' : 'Due Date'}
</span>
<label class="label font-semibold" for="invoice-due-date">
{invoice.type === 'quote' ? 'Valid Until' : 'Due Date'}
</label>
<input
type="date"
id="invoice-due-date"
name="dueDate"
class="input input-bordered"
value={dueDateStr}
@@ -118,16 +119,17 @@ const discountValueDisplay = invoice.discountType === 'fixed'
<!-- Discount -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Discount</span>
<label class="label font-semibold" for="invoice-discount-type">
Discount
</label>
<div class="join w-full">
<select name="discountType" class="select select-bordered join-item">
<select id="invoice-discount-type" name="discountType" class="select select-bordered join-item">
<option value="percentage" selected={!invoice.discountType || invoice.discountType === 'percentage'}>%</option>
<option value="fixed" selected={invoice.discountType === 'fixed'}>Fixed</option>
</select>
<input
type="number"
id="invoice-discount-value"
name="discountValue"
step="0.01"
min="0"
@@ -139,27 +141,29 @@ const discountValueDisplay = invoice.discountType === 'fixed'
<!-- Tax Rate -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Tax Rate (%)</span>
</label>
<input
type="number"
name="taxRate"
step="0.01"
min="0"
max="100"
class="input input-bordered"
value={invoice.taxRate}
/>
</div>
<label class="label font-semibold" for="invoice-tax-rate">
Tax Rate (%)
</label>
<input
type="number"
id="invoice-tax-rate"
name="taxRate"
step="0.01"
min="0"
max="100"
class="input input-bordered"
value={invoice.taxRate}
/>
</div>
</div>
<!-- Notes -->
<div class="form-control flex flex-col">
<label class="label">
<span class="label-text font-semibold">Notes / Terms</span>
<label class="label font-semibold" for="invoice-notes">
Notes / Terms
</label>
<textarea
id="invoice-notes"
name="notes"
class="textarea textarea-bordered h-32 font-mono text-sm"
placeholder="Payment terms, bank details, or thank you notes..."

View File

@@ -108,17 +108,17 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
<!-- Document Type -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Document Type</span>
<label class="label font-semibold" for="document-type-invoice">
Document Type
</label>
<div class="flex gap-4">
<label class="label cursor-pointer justify-start gap-2 border border-base-300 rounded-lg p-3 flex-1 hover:border-primary has-checked:border-primary has-checked:bg-primary/5 transition-all">
<input type="radio" name="type" value="invoice" class="radio radio-primary" checked />
<span class="label-text font-medium">Invoice</span>
<label class="label cursor-pointer justify-start gap-2 border border-base-300 rounded-lg p-3 flex-1 hover:border-primary has-checked:border-primary has-checked:bg-primary/5 transition-all font-medium" for="document-type-invoice">
<input type="radio" id="document-type-invoice" name="type" value="invoice" class="radio radio-primary" checked />
Invoice
</label>
<label class="label cursor-pointer justify-start gap-2 border border-base-300 rounded-lg p-3 flex-1 hover:border-primary has-checked:border-primary has-checked:bg-primary/5 transition-all">
<input type="radio" name="type" value="quote" class="radio radio-primary" />
<span class="label-text font-medium">Quote / Estimate</span>
<label class="label cursor-pointer justify-start gap-2 border border-base-300 rounded-lg p-3 flex-1 hover:border-primary has-checked:border-primary has-checked:bg-primary/5 transition-all font-medium" for="document-type-quote">
<input type="radio" id="document-type-quote" name="type" value="quote" class="radio radio-primary" />
Quote / Estimate
</label>
</div>
</div>
@@ -126,10 +126,10 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Client -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Client</span>
<label class="label font-semibold" for="invoice-client">
Client
</label>
<select name="clientId" class="select select-bordered w-full" required>
<select id="invoice-client" name="clientId" class="select select-bordered w-full" required>
<option value="" disabled selected>Select a client...</option>
{teamClients.map(client => (
<option value={client.id}>{client.name}</option>
@@ -139,8 +139,8 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
<!-- Number -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Number</span>
<label class="label font-semibold" for="documentNumber">
Number
</label>
<input
type="text"
@@ -156,11 +156,12 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
<!-- Issue Date -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Issue Date</span>
<label class="label font-semibold" for="invoice-issue-date">
Issue Date
</label>
<input
type="date"
id="invoice-issue-date"
name="issueDate"
class="input input-bordered"
value={today}
@@ -170,11 +171,12 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
<!-- Due Date -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold" id="dueDateLabel">Due Date</span>
<label class="label font-semibold" for="invoice-due-date" id="dueDateLabel">
Due Date
</label>
<input
type="date"
id="invoice-due-date"
name="dueDate"
class="input input-bordered"
value={defaultDueDate}
@@ -184,10 +186,10 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
<!-- Currency -->
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Currency</span>
<label class="label font-semibold" for="invoice-currency">
Currency
</label>
<select name="currency" class="select select-bordered w-full">
<select id="invoice-currency" name="currency" class="select select-bordered w-full">
<option value="USD">USD ($)</option>
<option value="EUR">EUR (€)</option>
<option value="GBP">GBP (£)</option>