This commit is contained in:
@@ -54,8 +54,8 @@ if (!category) return Astro.redirect('/dashboard/categories');
|
||||
<input type="hidden" name="redirectTo" value="/dashboard/categories" />
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label pb-2" for="name">
|
||||
<span class="label-text font-medium">Category Name</span>
|
||||
<label class="label pb-2 font-medium" for="name">
|
||||
Category Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -69,8 +69,8 @@ if (!category) return Astro.redirect('/dashboard/categories');
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-4">
|
||||
<label class="label pb-2" for="color">
|
||||
<span class="label-text font-medium">Color (optional)</span>
|
||||
<label class="label pb-2 font-medium" for="color">
|
||||
Color (optional)
|
||||
</label>
|
||||
<input
|
||||
type="color"
|
||||
|
||||
@@ -19,8 +19,8 @@ if (!user) return Astro.redirect('/login');
|
||||
<input type="hidden" name="redirectTo" value="/dashboard/categories" />
|
||||
<div class="card-body">
|
||||
<div class="form-control">
|
||||
<label class="label pb-2" for="name">
|
||||
<span class="label-text font-medium">Category Name</span>
|
||||
<label class="label pb-2 font-medium" for="name">
|
||||
Category Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -33,8 +33,8 @@ if (!user) return Astro.redirect('/login');
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label pb-2" for="color">
|
||||
<span class="label-text font-medium">Color (optional)</span>
|
||||
<label class="label pb-2 font-medium" for="color">
|
||||
Color (optional)
|
||||
</label>
|
||||
<input
|
||||
type="color"
|
||||
|
||||
@@ -50,7 +50,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
<div class="card-body">
|
||||
<div class="form-control">
|
||||
<label class="label" for="name">
|
||||
<span class="label-text">Client Name</span>
|
||||
Client Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -65,7 +65,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="email">
|
||||
<span class="label-text">Email (optional)</span>
|
||||
Email (optional)
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
@@ -79,7 +79,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="phone">
|
||||
<span class="label-text">Phone (optional)</span>
|
||||
Phone (optional)
|
||||
</label>
|
||||
<input
|
||||
type="tel"
|
||||
@@ -95,7 +95,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="street">
|
||||
<span class="label-text">Street Address (optional)</span>
|
||||
Street Address (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -110,7 +110,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label" for="city">
|
||||
<span class="label-text">City (optional)</span>
|
||||
City (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -124,7 +124,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="state">
|
||||
<span class="label-text">State / Province (optional)</span>
|
||||
State / Province (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -140,7 +140,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label" for="zip">
|
||||
<span class="label-text">Zip / Postal Code (optional)</span>
|
||||
Zip / Postal Code (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -154,7 +154,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="country">
|
||||
<span class="label-text">Country (optional)</span>
|
||||
Country (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
|
||||
@@ -13,7 +13,7 @@ if (!user) return Astro.redirect('/login');
|
||||
<div class="card-body">
|
||||
<div class="form-control">
|
||||
<label class="label" for="name">
|
||||
<span class="label-text">Client Name</span>
|
||||
Client Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -27,7 +27,7 @@ if (!user) return Astro.redirect('/login');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="email">
|
||||
<span class="label-text">Email (optional)</span>
|
||||
Email (optional)
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
@@ -40,7 +40,7 @@ if (!user) return Astro.redirect('/login');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="phone">
|
||||
<span class="label-text">Phone (optional)</span>
|
||||
Phone (optional)
|
||||
</label>
|
||||
<input
|
||||
type="tel"
|
||||
@@ -55,7 +55,7 @@ if (!user) return Astro.redirect('/login');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="street">
|
||||
<span class="label-text">Street Address (optional)</span>
|
||||
Street Address (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -69,7 +69,7 @@ if (!user) return Astro.redirect('/login');
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label" for="city">
|
||||
<span class="label-text">City (optional)</span>
|
||||
City (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -82,7 +82,7 @@ if (!user) return Astro.redirect('/login');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="state">
|
||||
<span class="label-text">State / Province (optional)</span>
|
||||
State / Province (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -97,7 +97,7 @@ if (!user) return Astro.redirect('/login');
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label" for="zip">
|
||||
<span class="label-text">Zip / Postal Code (optional)</span>
|
||||
Zip / Postal Code (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -110,7 +110,7 @@ if (!user) return Astro.redirect('/login');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="country">
|
||||
<span class="label-text">Country (optional)</span>
|
||||
Country (optional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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..."
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -17,7 +17,7 @@ if (!user) return Astro.redirect('/login');
|
||||
</a>
|
||||
<h1 class="text-3xl font-bold">Create New Team</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<form method="POST" action="/api/organizations/create" class="card bg-base-200 shadow-xl border border-base-300">
|
||||
<div class="card-body">
|
||||
<div class="alert alert-info mb-4">
|
||||
@@ -26,16 +26,16 @@ if (!user) return Astro.redirect('/login');
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label pb-2" for="name">
|
||||
<span class="label-text font-medium">Team Name</span>
|
||||
<label class="label pb-2 font-medium" for="name">
|
||||
Team Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
placeholder="Acme Corp"
|
||||
class="input input-bordered w-full"
|
||||
required
|
||||
name="name"
|
||||
placeholder="Acme Corp"
|
||||
class="input input-bordered w-full"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -276,10 +276,10 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card-body">
|
||||
<form method="GET" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Time Range</span>
|
||||
<label class="label font-medium" for="reports-range">
|
||||
Time Range
|
||||
</label>
|
||||
<select name="range" class="select select-bordered" onchange="this.form.submit()">
|
||||
<select id="reports-range" name="range" class="select select-bordered" onchange="this.form.submit()">
|
||||
<option value="today" selected={timeRange === 'today'}>Today</option>
|
||||
<option value="week" selected={timeRange === 'week'}>Last 7 Days</option>
|
||||
<option value="month" selected={timeRange === 'month'}>Last 30 Days</option>
|
||||
@@ -293,11 +293,12 @@ function getTimeRangeLabel(range: string) {
|
||||
{timeRange === 'custom' && (
|
||||
<>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">From Date</span>
|
||||
<label class="label font-medium" for="reports-from">
|
||||
From Date
|
||||
</label>
|
||||
<input
|
||||
type="date"
|
||||
id="reports-from"
|
||||
name="from"
|
||||
class="input input-bordered w-full"
|
||||
value={customFrom || (startDate.getFullYear() + '-' + String(startDate.getMonth() + 1).padStart(2, '0') + '-' + String(startDate.getDate()).padStart(2, '0'))}
|
||||
@@ -305,11 +306,12 @@ function getTimeRangeLabel(range: string) {
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">To Date</span>
|
||||
<label class="label font-medium" for="reports-to">
|
||||
To Date
|
||||
</label>
|
||||
<input
|
||||
type="date"
|
||||
id="reports-to"
|
||||
name="to"
|
||||
class="input input-bordered w-full"
|
||||
value={customTo || (endDate.getFullYear() + '-' + String(endDate.getMonth() + 1).padStart(2, '0') + '-' + String(endDate.getDate()).padStart(2, '0'))}
|
||||
@@ -320,10 +322,10 @@ function getTimeRangeLabel(range: string) {
|
||||
)}
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Team Member</span>
|
||||
<label class="label font-medium" for="reports-member">
|
||||
Team Member
|
||||
</label>
|
||||
<select name="member" class="select select-bordered" onchange="this.form.submit()">
|
||||
<select id="reports-member" name="member" class="select select-bordered" onchange="this.form.submit()">
|
||||
<option value="">All Members</option>
|
||||
{teamMembers.map(member => (
|
||||
<option value={member.id} selected={selectedMemberId === member.id}>
|
||||
@@ -334,10 +336,10 @@ function getTimeRangeLabel(range: string) {
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Category</span>
|
||||
<label class="label font-medium" for="reports-category">
|
||||
Category
|
||||
</label>
|
||||
<select name="category" class="select select-bordered" onchange="this.form.submit()">
|
||||
<select id="reports-category" name="category" class="select select-bordered" onchange="this.form.submit()">
|
||||
<option value="">All Categories</option>
|
||||
{allCategories.map(category => (
|
||||
<option value={category.id} selected={selectedCategoryId === category.id}>
|
||||
@@ -348,10 +350,10 @@ function getTimeRangeLabel(range: string) {
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Client</span>
|
||||
<label class="label font-medium" for="reports-client">
|
||||
Client
|
||||
</label>
|
||||
<select name="client" class="select select-bordered" onchange="this.form.submit()">
|
||||
<select id="reports-client" name="client" class="select select-bordered" onchange="this.form.submit()">
|
||||
<option value="">All Clients</option>
|
||||
{allClients.map(client => (
|
||||
<option value={client.id} selected={selectedClientId === client.id}>
|
||||
|
||||
@@ -40,7 +40,7 @@ if (!isAdmin) return Astro.redirect('/dashboard/team');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="email">
|
||||
<span class="label-text">Email Address</span>
|
||||
Email Address
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
@@ -54,7 +54,7 @@ if (!isAdmin) return Astro.redirect('/dashboard/team');
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="role">
|
||||
<span class="label-text">Role</span>
|
||||
Role
|
||||
</label>
|
||||
<select id="role" name="role" class="select select-bordered" required>
|
||||
<option value="member">Member</option>
|
||||
|
||||
@@ -112,12 +112,13 @@ const successType = url.searchParams.get('success');
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="form-control">
|
||||
<div class="label">
|
||||
<span class="label-text font-medium">Team Name</span>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label font-medium" for="team-name">
|
||||
Team Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="team-name"
|
||||
name="name"
|
||||
value={organization.name}
|
||||
placeholder="Organization name"
|
||||
@@ -127,77 +128,82 @@ const successType = url.searchParams.get('success');
|
||||
<div class="label">
|
||||
<span class="label-text-alt text-base-content/60">This name is visible to all team members</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="divider">Address Information</div>
|
||||
|
||||
<label class="form-control">
|
||||
<div class="label">
|
||||
<span class="label-text font-medium">Street Address</span>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label font-medium" for="team-street">
|
||||
Street Address
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="team-street"
|
||||
name="street"
|
||||
value={organization.street || ''}
|
||||
placeholder="123 Main Street"
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<label class="form-control">
|
||||
<div class="label">
|
||||
<span class="label-text font-medium">City</span>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label font-medium" for="team-city">
|
||||
City
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="team-city"
|
||||
name="city"
|
||||
value={organization.city || ''}
|
||||
placeholder="City"
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="form-control">
|
||||
<div class="label">
|
||||
<span class="label-text font-medium">State/Province</span>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label font-medium" for="team-state">
|
||||
State/Province
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="team-state"
|
||||
name="state"
|
||||
value={organization.state || ''}
|
||||
placeholder="State/Province"
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<label class="form-control">
|
||||
<div class="label">
|
||||
<span class="label-text font-medium">Postal Code</span>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label font-medium" for="team-zip">
|
||||
Postal Code
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="team-zip"
|
||||
name="zip"
|
||||
value={organization.zip || ''}
|
||||
placeholder="12345"
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="form-control">
|
||||
<div class="label">
|
||||
<span class="label-text font-medium">Country</span>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label font-medium" for="team-country">
|
||||
Country
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="team-country"
|
||||
name="country"
|
||||
value={organization.country || ''}
|
||||
placeholder="Country"
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col sm:flex-row justify-between items-center gap-4 mt-6">
|
||||
|
||||
@@ -51,8 +51,8 @@ if (!category) return Astro.redirect('/dashboard/team/settings');
|
||||
<form method="POST" action={`/api/categories/${id}/update`} class="card bg-base-200 shadow-xl border border-base-300">
|
||||
<div class="card-body">
|
||||
<div class="form-control">
|
||||
<label class="label pb-2" for="name">
|
||||
<span class="label-text font-medium">Category Name</span>
|
||||
<label class="label pb-2 font-medium" for="name">
|
||||
Category Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -66,8 +66,8 @@ if (!category) return Astro.redirect('/dashboard/team/settings');
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label pb-2" for="color">
|
||||
<span class="label-text font-medium">Color (optional)</span>
|
||||
<label class="label pb-2 font-medium" for="color">
|
||||
Color (optional)
|
||||
</label>
|
||||
<input
|
||||
type="color"
|
||||
|
||||
@@ -14,32 +14,32 @@ if (!user) return Astro.redirect('/login');
|
||||
</a>
|
||||
<h1 class="text-3xl font-bold">Add New Category</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<form method="POST" action="/api/categories/create" class="card bg-base-200 shadow-xl border border-base-300">
|
||||
<div class="card-body">
|
||||
<div class="form-control">
|
||||
<label class="label pb-2" for="name">
|
||||
<span class="label-text font-medium">Category Name</span>
|
||||
<label class="label pb-2 font-medium" for="name">
|
||||
Category Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
placeholder="Development"
|
||||
class="input input-bordered w-full"
|
||||
required
|
||||
name="name"
|
||||
placeholder="Development"
|
||||
class="input input-bordered w-full"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label pb-2" for="color">
|
||||
<span class="label-text font-medium">Color (optional)</span>
|
||||
<label class="label pb-2 font-medium" for="color">
|
||||
Color (optional)
|
||||
</label>
|
||||
<input
|
||||
type="color"
|
||||
<input
|
||||
type="color"
|
||||
id="color"
|
||||
name="color"
|
||||
class="input input-bordered w-full h-12"
|
||||
name="color"
|
||||
class="input input-bordered w-full h-12"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -225,11 +225,12 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
<div class="card-body">
|
||||
<form method="GET" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Search</span>
|
||||
<label class="label font-medium" for="tracker-search">
|
||||
Search
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="tracker-search"
|
||||
name="search"
|
||||
placeholder="Search descriptions..."
|
||||
class="input input-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full"
|
||||
@@ -238,10 +239,10 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Client</span>
|
||||
<label class="label font-medium" for="tracker-client">
|
||||
Client
|
||||
</label>
|
||||
<select name="client" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<select id="tracker-client" name="client" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<option value="">All Clients</option>
|
||||
{allClients.map(client => (
|
||||
<option value={client.id} selected={filterClient === client.id}>
|
||||
@@ -252,10 +253,10 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Category</span>
|
||||
<label class="label font-medium" for="tracker-category">
|
||||
Category
|
||||
</label>
|
||||
<select name="category" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<select id="tracker-category" name="category" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<option value="">All Categories</option>
|
||||
{allCategories.map(category => (
|
||||
<option value={category.id} selected={filterCategory === category.id}>
|
||||
@@ -266,10 +267,10 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Status</span>
|
||||
<label class="label font-medium" for="tracker-status">
|
||||
Status
|
||||
</label>
|
||||
<select name="status" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<select id="tracker-status" name="status" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<option value="" selected={filterStatus === ''}>All Entries</option>
|
||||
<option value="completed" selected={filterStatus === 'completed'}>Completed</option>
|
||||
<option value="running" selected={filterStatus === 'running'}>Running</option>
|
||||
@@ -277,10 +278,10 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Entry Type</span>
|
||||
<label class="label font-medium" for="tracker-type">
|
||||
Entry Type
|
||||
</label>
|
||||
<select name="type" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<select id="tracker-type" name="type" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<option value="" selected={filterType === ''}>All Types</option>
|
||||
<option value="timed" selected={filterType === 'timed'}>Timed</option>
|
||||
<option value="manual" selected={filterType === 'manual'}>Manual</option>
|
||||
@@ -288,10 +289,10 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-medium">Sort By</span>
|
||||
<label class="label font-medium" for="tracker-sort">
|
||||
Sort By
|
||||
</label>
|
||||
<select name="sort" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<select id="tracker-sort" name="sort" class="select select-bordered bg-base-300/50 hover:bg-base-300 focus:bg-base-300 border-base-300/50 focus:border-primary transition-colors w-full" onchange="this.form.submit()">
|
||||
<option value="start-desc" selected={sortBy === 'start-desc'}>Newest First</option>
|
||||
<option value="start-asc" selected={sortBy === 'start-asc'}>Oldest First</option>
|
||||
<option value="duration-desc" selected={sortBy === 'duration-desc'}>Longest Duration</option>
|
||||
|
||||
Reference in New Issue
Block a user