Icon refactor
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../../components/Icon.astro';
|
||||
import { db } from '../../../../db';
|
||||
import { clients } from '../../../../db/schema';
|
||||
import { eq, and } from 'drizzle-orm';
|
||||
@@ -30,7 +30,7 @@ if (!client) return Astro.redirect('/dashboard/clients');
|
||||
<div class="max-w-2xl mx-auto">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<a href={`/dashboard/clients/${client.id}`} class="btn btn-ghost btn-xs">
|
||||
<Icon name="heroicons:arrow-left" class="w-4 h-4" />
|
||||
<Icon name="arrow-left" class="w-4 h-4" />
|
||||
</a>
|
||||
<h1 class="text-2xl font-extrabold tracking-tight">Edit Client</h1>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../../components/Icon.astro';
|
||||
import { db } from '../../../../db';
|
||||
import { clients, timeEntries, tags, users } from '../../../../db/schema';
|
||||
import { eq, and, desc, sql } from 'drizzle-orm';
|
||||
@@ -64,7 +64,7 @@ const totalEntriesCount = totalEntriesResult?.count || 0;
|
||||
<DashboardLayout title={`${client.name} - Clients - Chronus`}>
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<a href="/dashboard/clients" class="btn btn-ghost btn-xs">
|
||||
<Icon name="heroicons:arrow-left" class="w-4 h-4" />
|
||||
<Icon name="arrow-left" class="w-4 h-4" />
|
||||
</a>
|
||||
<h1 class="text-2xl font-extrabold tracking-tight">{client.name}</h1>
|
||||
</div>
|
||||
@@ -79,19 +79,19 @@ const totalEntriesCount = totalEntriesResult?.count || 0;
|
||||
<div class="space-y-2 mb-4">
|
||||
{client.email && (
|
||||
<div class="flex items-center gap-2 text-base-content/60 text-sm">
|
||||
<Icon name="heroicons:envelope" class="w-4 h-4" />
|
||||
<Icon name="envelope" class="w-4 h-4" />
|
||||
<a href={`mailto:${client.email}`} class="link link-hover">{client.email}</a>
|
||||
</div>
|
||||
)}
|
||||
{client.phone && (
|
||||
<div class="flex items-center gap-2 text-base-content/60 text-sm">
|
||||
<Icon name="heroicons:phone" class="w-4 h-4" />
|
||||
<Icon name="phone" class="w-4 h-4" />
|
||||
<a href={`tel:${client.phone}`} class="link link-hover">{client.phone}</a>
|
||||
</div>
|
||||
)}
|
||||
{(client.street || client.city || client.state || client.zip || client.country) && (
|
||||
<div class="flex items-start gap-2 text-base-content/60">
|
||||
<Icon name="heroicons:map-pin" class="w-4 h-4 mt-0.5" />
|
||||
<Icon name="map-pin" class="w-4 h-4 mt-0.5" />
|
||||
<div class="text-sm space-y-0.5">
|
||||
{client.street && <div>{client.street}</div>}
|
||||
{(client.city || client.state || client.zip) && (
|
||||
@@ -107,12 +107,12 @@ const totalEntriesCount = totalEntriesResult?.count || 0;
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<a href={`/dashboard/clients/${client.id}/edit`} class="btn btn-primary btn-xs">
|
||||
<Icon name="heroicons:pencil" class="w-3 h-3" />
|
||||
<Icon name="pencil" class="w-3 h-3" />
|
||||
Edit
|
||||
</a>
|
||||
<form method="POST" action={`/api/clients/${client.id}/delete`} onsubmit="return confirm('Are you sure you want to delete this client? This will also delete all associated time entries.');">
|
||||
<button type="submit" class="btn btn-error btn-outline btn-xs">
|
||||
<Icon name="heroicons:trash" class="w-3 h-3" />
|
||||
<Icon name="trash" class="w-3 h-3" />
|
||||
Delete
|
||||
</button>
|
||||
</form>
|
||||
@@ -126,14 +126,14 @@ const totalEntriesCount = totalEntriesResult?.count || 0;
|
||||
title="Total Time Tracked"
|
||||
value={`${totalHours}h ${totalMinutes}m`}
|
||||
description="Across all projects"
|
||||
icon="heroicons:clock"
|
||||
icon="clock"
|
||||
color="text-primary"
|
||||
/>
|
||||
<StatCard
|
||||
title="Total Entries"
|
||||
value={String(totalEntriesCount)}
|
||||
description="Recorded entries"
|
||||
icon="heroicons:list-bullet"
|
||||
icon="list-bullet"
|
||||
color="text-secondary"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../components/Icon.astro';
|
||||
import StatCard from '../../components/StatCard.astro';
|
||||
import { db } from '../../db';
|
||||
import { organizations, members, timeEntries, clients, tags } from '../../db/schema';
|
||||
@@ -112,20 +112,20 @@ const hasMembership = userOrgs.length > 0;
|
||||
<p class="text-base-content/60 text-sm mt-1">Welcome back, {user.name}!</p>
|
||||
</div>
|
||||
<a href="/dashboard/organizations/new" class="btn btn-ghost btn-sm">
|
||||
<Icon name="heroicons:plus" class="w-4 h-4" />
|
||||
<Icon name="plus" class="w-4 h-4" />
|
||||
New Team
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{!hasMembership && (
|
||||
<div class="alert alert-info mb-6 text-sm">
|
||||
<Icon name="heroicons:information-circle" class="w-5 h-5" />
|
||||
<Icon name="information-circle" class="w-5 h-5" />
|
||||
<div>
|
||||
<h3 class="font-bold">Welcome to Chronus!</h3>
|
||||
<div class="text-xs">You're not part of any team yet. Create one or wait for an invitation.</div>
|
||||
</div>
|
||||
<a href="/dashboard/organizations/new" class="btn btn-primary btn-sm">
|
||||
<Icon name="heroicons:plus" class="w-4 h-4" />
|
||||
<Icon name="plus" class="w-4 h-4" />
|
||||
New Team
|
||||
</a>
|
||||
</div>
|
||||
@@ -139,28 +139,28 @@ const hasMembership = userOrgs.length > 0;
|
||||
title="This Week"
|
||||
value={formatDuration(stats.totalTimeThisWeek)}
|
||||
description="Total tracked time"
|
||||
icon="heroicons:clock"
|
||||
icon="clock"
|
||||
color="text-primary"
|
||||
/>
|
||||
<StatCard
|
||||
title="This Month"
|
||||
value={formatDuration(stats.totalTimeThisMonth)}
|
||||
description="Total tracked time"
|
||||
icon="heroicons:calendar"
|
||||
icon="calendar"
|
||||
color="text-secondary"
|
||||
/>
|
||||
<StatCard
|
||||
title="Active Timers"
|
||||
value={String(stats.activeTimers)}
|
||||
description="Currently running"
|
||||
icon="heroicons:play-circle"
|
||||
icon="play-circle"
|
||||
color="text-accent"
|
||||
/>
|
||||
<StatCard
|
||||
title="Clients"
|
||||
value={String(stats.totalClients)}
|
||||
description="Total active"
|
||||
icon="heroicons:building-office"
|
||||
icon="building-office"
|
||||
color="text-info"
|
||||
/>
|
||||
</div>
|
||||
@@ -170,20 +170,20 @@ const hasMembership = userOrgs.length > 0;
|
||||
<div class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2">
|
||||
<Icon name="heroicons:bolt" class="w-4 h-4 text-warning" />
|
||||
<Icon name="bolt" class="w-4 h-4 text-warning" />
|
||||
Quick Actions
|
||||
</h2>
|
||||
<div class="flex flex-col gap-2 mt-3">
|
||||
<a href="/dashboard/tracker" class="btn btn-primary btn-sm">
|
||||
<Icon name="heroicons:play" class="w-4 h-4" />
|
||||
<Icon name="play" class="w-4 h-4" />
|
||||
Start Timer
|
||||
</a>
|
||||
<a href="/dashboard/clients/new" class="btn btn-ghost btn-sm">
|
||||
<Icon name="heroicons:plus" class="w-4 h-4" />
|
||||
<Icon name="plus" class="w-4 h-4" />
|
||||
Add Client
|
||||
</a>
|
||||
<a href="/dashboard/reports" class="btn btn-ghost btn-sm">
|
||||
<Icon name="heroicons:chart-bar" class="w-4 h-4" />
|
||||
<Icon name="chart-bar" class="w-4 h-4" />
|
||||
View Reports
|
||||
</a>
|
||||
</div>
|
||||
@@ -194,7 +194,7 @@ const hasMembership = userOrgs.length > 0;
|
||||
<div class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2">
|
||||
<Icon name="heroicons:clock" class="w-4 h-4 text-success" />
|
||||
<Icon name="clock" class="w-4 h-4 text-success" />
|
||||
Recent Activity
|
||||
</h2>
|
||||
{stats.recentEntries.length > 0 ? (
|
||||
@@ -215,7 +215,7 @@ const hasMembership = userOrgs.length > 0;
|
||||
</ul>
|
||||
) : (
|
||||
<div class="flex flex-col items-center justify-center py-6 text-center mt-3">
|
||||
<Icon name="heroicons:clock" class="w-10 h-10 text-base-content/15 mb-2" />
|
||||
<Icon name="clock" class="w-10 h-10 text-base-content/15 mb-2" />
|
||||
<p class="text-base-content/40 text-sm">No recent time entries</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../components/Icon.astro';
|
||||
import { db } from '../../../db';
|
||||
import { invoices, invoiceItems, clients, members, organizations } from '../../../db/schema';
|
||||
import { eq, and } from 'drizzle-orm';
|
||||
@@ -60,7 +60,7 @@ const isDraft = invoice.status === 'draft';
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-1">
|
||||
<a href="/dashboard/invoices" class="btn btn-ghost btn-xs btn-square">
|
||||
<Icon name="heroicons:arrow-left" class="w-4 h-4" />
|
||||
<Icon name="arrow-left" class="w-4 h-4" />
|
||||
</a>
|
||||
<div class={`badge badge-xs ${
|
||||
invoice.status === 'paid' || invoice.status === 'accepted' ? 'badge-success' :
|
||||
@@ -79,7 +79,7 @@ const isDraft = invoice.status === 'draft';
|
||||
<form method="POST" action={`/api/invoices/${invoice.id}/status`}>
|
||||
<input type="hidden" name="status" value="sent" />
|
||||
<button type="submit" class="btn btn-primary btn-sm">
|
||||
<Icon name="heroicons:paper-airplane" class="w-4 h-4" />
|
||||
<Icon name="paper-airplane" class="w-4 h-4" />
|
||||
Mark Sent
|
||||
</button>
|
||||
</form>
|
||||
@@ -88,7 +88,7 @@ const isDraft = invoice.status === 'draft';
|
||||
<form method="POST" action={`/api/invoices/${invoice.id}/status`}>
|
||||
<input type="hidden" name="status" value="paid" />
|
||||
<button type="submit" class="btn btn-success btn-sm">
|
||||
<Icon name="heroicons:check" class="w-4 h-4" />
|
||||
<Icon name="check" class="w-4 h-4" />
|
||||
Mark Paid
|
||||
</button>
|
||||
</form>
|
||||
@@ -97,7 +97,7 @@ const isDraft = invoice.status === 'draft';
|
||||
<form method="POST" action={`/api/invoices/${invoice.id}/status`}>
|
||||
<input type="hidden" name="status" value="accepted" />
|
||||
<button type="submit" class="btn btn-success btn-sm">
|
||||
<Icon name="heroicons:check" class="w-4 h-4" />
|
||||
<Icon name="check" class="w-4 h-4" />
|
||||
Mark Accepted
|
||||
</button>
|
||||
</form>
|
||||
@@ -105,25 +105,25 @@ const isDraft = invoice.status === 'draft';
|
||||
{(invoice.type === 'quote' && invoice.status === 'accepted') && (
|
||||
<form method="POST" action={`/api/invoices/${invoice.id}/convert`}>
|
||||
<button type="submit" class="btn btn-primary btn-sm">
|
||||
<Icon name="heroicons:document-duplicate" class="w-4 h-4" />
|
||||
<Icon name="document-duplicate" class="w-4 h-4" />
|
||||
Convert to Invoice
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
<div class="dropdown dropdown-end">
|
||||
<div role="button" tabindex="0" class="btn btn-square btn-ghost btn-sm border border-base-200">
|
||||
<Icon name="heroicons:ellipsis-horizontal" class="w-4 h-4" />
|
||||
<Icon name="ellipsis-horizontal" class="w-4 h-4" />
|
||||
</div>
|
||||
<ul tabindex="0" class="dropdown-content z-1 menu p-2 bg-base-100 rounded-box w-52 border border-base-200">
|
||||
<li>
|
||||
<a href={`/dashboard/invoices/${invoice.id}/edit`}>
|
||||
<Icon name="heroicons:pencil-square" class="w-4 h-4" />
|
||||
<Icon name="pencil-square" class="w-4 h-4" />
|
||||
Edit Settings
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`/api/invoices/${invoice.id}/generate`} download>
|
||||
<Icon name="heroicons:arrow-down-tray" class="w-4 h-4" />
|
||||
<Icon name="arrow-down-tray" class="w-4 h-4" />
|
||||
Download PDF
|
||||
</a>
|
||||
</li>
|
||||
@@ -132,7 +132,7 @@ const isDraft = invoice.status === 'draft';
|
||||
<form method="POST" action={`/api/invoices/${invoice.id}/status`}>
|
||||
<input type="hidden" name="status" value="void" />
|
||||
<button type="submit" class="text-error">
|
||||
<Icon name="heroicons:x-circle" class="w-4 h-4" />
|
||||
<Icon name="x-circle" class="w-4 h-4" />
|
||||
Void
|
||||
</button>
|
||||
</form>
|
||||
@@ -142,7 +142,7 @@ const isDraft = invoice.status === 'draft';
|
||||
<form method="POST" action="/api/invoices/delete" onsubmit="return confirm('Are you sure?');">
|
||||
<input type="hidden" name="id" value={invoice.id} />
|
||||
<button type="submit" class="text-error">
|
||||
<Icon name="heroicons:trash" class="w-4 h-4" />
|
||||
<Icon name="trash" class="w-4 h-4" />
|
||||
Delete
|
||||
</button>
|
||||
</form>
|
||||
@@ -236,7 +236,7 @@ const isDraft = invoice.status === 'draft';
|
||||
<form method="POST" action={`/api/invoices/${invoice.id}/items/delete`}>
|
||||
<input type="hidden" name="itemId" value={item.id} />
|
||||
<button type="submit" class="btn btn-ghost btn-xs btn-square text-error opacity-50 hover:opacity-100">
|
||||
<Icon name="heroicons:trash" class="w-4 h-4" />
|
||||
<Icon name="trash" class="w-4 h-4" />
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
@@ -259,7 +259,7 @@ const isDraft = invoice.status === 'draft';
|
||||
{isDraft && (
|
||||
<div class="flex justify-end mb-4">
|
||||
<button onclick="document.getElementById('import_time_modal').showModal()" class="btn btn-sm btn-outline gap-2">
|
||||
<Icon name="heroicons:clock" class="w-4 h-4" />
|
||||
<Icon name="clock" class="w-4 h-4" />
|
||||
Import Time
|
||||
</button>
|
||||
</div>
|
||||
@@ -281,7 +281,7 @@ const isDraft = invoice.status === 'draft';
|
||||
</div>
|
||||
<div class="sm:col-span-1">
|
||||
<button type="submit" class="btn btn-sm btn-primary w-full">
|
||||
<Icon name="heroicons:plus" class="w-4 h-4" />
|
||||
<Icon name="plus" class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -310,7 +310,7 @@ const isDraft = invoice.status === 'draft';
|
||||
Tax ({invoice.taxRate ?? 0}%)
|
||||
{isDraft && (
|
||||
<button type="button" onclick="document.getElementById('tax_modal').showModal()" class="btn btn-ghost btn-xs btn-square opacity-0 group-hover:opacity-100 transition-opacity" title="Edit Tax Rate">
|
||||
<Icon name="heroicons:pencil" class="w-3 h-3" />
|
||||
<Icon name="pencil" class="w-3 h-3" />
|
||||
</button>
|
||||
)}
|
||||
</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../../components/Icon.astro';
|
||||
import { db } from '../../../../db';
|
||||
import { invoices, members } from '../../../../db/schema';
|
||||
import { eq, and } from 'drizzle-orm';
|
||||
@@ -48,7 +48,7 @@ const discountValueDisplay = invoice.discountType === 'fixed'
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<div class="mb-6">
|
||||
<a href={`/dashboard/invoices/${invoice.id}`} class="btn btn-ghost btn-xs gap-2 pl-0 hover:bg-transparent text-base-content/60">
|
||||
<Icon name="heroicons:arrow-left" class="w-4 h-4" />
|
||||
<Icon name="arrow-left" class="w-4 h-4" />
|
||||
Back to Invoice
|
||||
</a>
|
||||
<h1 class="text-2xl font-extrabold tracking-tight mt-2">Edit Details</h1>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../components/Icon.astro';
|
||||
import StatCard from '../../../components/StatCard.astro';
|
||||
import { db } from '../../../db';
|
||||
import { invoices, clients } from '../../../db/schema';
|
||||
@@ -108,7 +108,7 @@ const getStatusColor = (status: string) => {
|
||||
<p class="text-base-content/60 text-sm mt-1">Manage your billing and estimates</p>
|
||||
</div>
|
||||
<a href="/dashboard/invoices/new" class="btn btn-primary btn-sm">
|
||||
<Icon name="heroicons:plus" class="w-4 h-4" />
|
||||
<Icon name="plus" class="w-4 h-4" />
|
||||
Create New
|
||||
</a>
|
||||
</div>
|
||||
@@ -118,14 +118,14 @@ const getStatusColor = (status: string) => {
|
||||
title="Total Invoices"
|
||||
value={String(yearInvoices.filter(i => i.invoice.type === 'invoice').length)}
|
||||
description={selectedYear === 'current' ? `${currentYear} (YTD)` : String(selectedYear)}
|
||||
icon="heroicons:document-text"
|
||||
icon="document-text"
|
||||
color="text-primary"
|
||||
/>
|
||||
<StatCard
|
||||
title="Open Quotes"
|
||||
value={String(yearInvoices.filter(i => i.invoice.type === 'quote' && i.invoice.status === 'sent').length)}
|
||||
description="Waiting for approval"
|
||||
icon="heroicons:clipboard-document-list"
|
||||
icon="clipboard-document-list"
|
||||
color="text-secondary"
|
||||
/>
|
||||
<StatCard
|
||||
@@ -134,7 +134,7 @@ const getStatusColor = (status: string) => {
|
||||
.filter(i => i.invoice.type === 'invoice' && i.invoice.status === 'paid')
|
||||
.reduce((acc, curr) => acc + curr.invoice.total, 0), 'USD')}
|
||||
description={`Paid invoices (${selectedYear === 'current' ? `${currentYear} YTD` : selectedYear})`}
|
||||
icon="heroicons:currency-dollar"
|
||||
icon="currency-dollar"
|
||||
color="text-success"
|
||||
/>
|
||||
</div>
|
||||
@@ -191,7 +191,7 @@ const getStatusColor = (status: string) => {
|
||||
{(selectedYear !== 'current' || selectedType !== 'all' || selectedStatus !== 'all' || sortBy !== 'date-desc') && (
|
||||
<div class="mt-3">
|
||||
<a href="/dashboard/invoices" class="btn btn-ghost btn-xs">
|
||||
<Icon name="heroicons:x-mark" class="w-3 h-3" />
|
||||
<Icon name="x-mark" class="w-3 h-3" />
|
||||
Clear Filters
|
||||
</a>
|
||||
</div>
|
||||
@@ -260,24 +260,24 @@ const getStatusColor = (status: string) => {
|
||||
<td class="text-right">
|
||||
<div class="dropdown dropdown-end">
|
||||
<div role="button" tabindex="0" class="btn btn-ghost btn-xs btn-square">
|
||||
<Icon name="heroicons:ellipsis-vertical" class="w-4 h-4" />
|
||||
<Icon name="ellipsis-vertical" class="w-4 h-4" />
|
||||
</div>
|
||||
<ul tabindex="0" class="dropdown-content menu p-2 bg-base-100 rounded-box w-52 border border-base-200 z-100">
|
||||
<li>
|
||||
<a href={`/dashboard/invoices/${invoice.id}`}>
|
||||
<Icon name="heroicons:eye" class="w-4 h-4" />
|
||||
<Icon name="eye" class="w-4 h-4" />
|
||||
View Details
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`/dashboard/invoices/${invoice.id}/edit`}>
|
||||
<Icon name="heroicons:pencil-square" class="w-4 h-4" />
|
||||
<Icon name="pencil-square" class="w-4 h-4" />
|
||||
Edit
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`/api/invoices/${invoice.id}/generate`} download>
|
||||
<Icon name="heroicons:arrow-down-tray" class="w-4 h-4" />
|
||||
<Icon name="arrow-down-tray" class="w-4 h-4" />
|
||||
Download PDF
|
||||
</a>
|
||||
</li>
|
||||
@@ -286,7 +286,7 @@ const getStatusColor = (status: string) => {
|
||||
<form method="POST" action={`/api/invoices/${invoice.id}/status`} class="w-full">
|
||||
<input type="hidden" name="status" value="sent" />
|
||||
<button type="submit" class="w-full justify-start">
|
||||
<Icon name="heroicons:paper-airplane" class="w-4 h-4" />
|
||||
<Icon name="paper-airplane" class="w-4 h-4" />
|
||||
Mark as Sent
|
||||
</button>
|
||||
</form>
|
||||
@@ -297,7 +297,7 @@ const getStatusColor = (status: string) => {
|
||||
<form method="POST" action={`/api/invoices/delete`} onsubmit="return confirm('Are you sure? This action cannot be undone.');" class="w-full">
|
||||
<input type="hidden" name="id" value={invoice.id} />
|
||||
<button type="submit" class="w-full justify-start text-error hover:bg-error/10">
|
||||
<Icon name="heroicons:trash" class="w-4 h-4" />
|
||||
<Icon name="trash" class="w-4 h-4" />
|
||||
Delete
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../components/Icon.astro';
|
||||
import { db } from '../../../db';
|
||||
import { clients, invoices, organizations } from '../../../db/schema';
|
||||
import { eq, desc, and } from 'drizzle-orm';
|
||||
@@ -81,7 +81,7 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<div class="mb-6">
|
||||
<a href="/dashboard/invoices" class="btn btn-ghost btn-xs gap-2 pl-0 hover:bg-transparent text-base-content/60">
|
||||
<Icon name="heroicons:arrow-left" class="w-4 h-4" />
|
||||
<Icon name="arrow-left" class="w-4 h-4" />
|
||||
Back to Invoices
|
||||
</a>
|
||||
<h1 class="text-2xl font-extrabold tracking-tight mt-2">Create New Document</h1>
|
||||
@@ -89,7 +89,7 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
|
||||
|
||||
{teamClients.length === 0 ? (
|
||||
<div role="alert" class="alert alert-warning">
|
||||
<Icon name="heroicons:exclamation-triangle" class="w-5 h-5" />
|
||||
<Icon name="exclamation-triangle" class="w-5 h-5" />
|
||||
<div>
|
||||
<h3 class="font-semibold text-sm">No Clients Found</h3>
|
||||
<div class="text-xs">You need to add a client before you can create an invoice or quote.</div>
|
||||
@@ -187,7 +187,7 @@ const defaultDueDate = nextMonth.toISOString().split('T')[0];
|
||||
<a href="/dashboard/invoices" class="btn btn-ghost btn-sm">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary btn-sm">
|
||||
Create Draft
|
||||
<Icon name="heroicons:arrow-right" class="w-4 h-4" />
|
||||
<Icon name="arrow-right" class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../components/Icon.astro';
|
||||
import { db } from '../../../db';
|
||||
import { organizations, members } from '../../../db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
@@ -13,7 +13,7 @@ if (!user) return Astro.redirect('/login');
|
||||
<div class="max-w-2xl mx-auto">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<a href="/dashboard" class="btn btn-ghost btn-xs">
|
||||
<Icon name="heroicons:arrow-left" class="w-4 h-4" />
|
||||
<Icon name="arrow-left" class="w-4 h-4" />
|
||||
</a>
|
||||
<h1 class="text-2xl font-extrabold tracking-tight">Create New Team</h1>
|
||||
</div>
|
||||
@@ -21,7 +21,7 @@ if (!user) return Astro.redirect('/login');
|
||||
<form method="POST" action="/api/organizations/create" class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<div class="alert alert-info mb-4">
|
||||
<Icon name="heroicons:information-circle" class="w-4 h-4" />
|
||||
<Icon name="information-circle" class="w-4 h-4" />
|
||||
<span class="text-sm">Create a new team to manage separate projects and collaborators. You'll be the owner.</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../components/Icon.astro';
|
||||
import StatCard from '../../components/StatCard.astro';
|
||||
import TagChart from '../../components/TagChart.vue';
|
||||
import ClientChart from '../../components/ClientChart.vue';
|
||||
@@ -343,28 +343,28 @@ function getTimeRangeLabel(range: string) {
|
||||
title="Total Time"
|
||||
value={formatDuration(totalTime)}
|
||||
description={getTimeRangeLabel(timeRange)}
|
||||
icon="heroicons:clock"
|
||||
icon="clock"
|
||||
color="text-primary"
|
||||
/>
|
||||
<StatCard
|
||||
title="Total Entries"
|
||||
value={String(entries.length)}
|
||||
description={getTimeRangeLabel(timeRange)}
|
||||
icon="heroicons:list-bullet"
|
||||
icon="list-bullet"
|
||||
color="text-secondary"
|
||||
/>
|
||||
<StatCard
|
||||
title="Revenue"
|
||||
value={formatCurrency(revenueStats.total)}
|
||||
description={`${invoiceStats.paid} paid invoices`}
|
||||
icon="heroicons:currency-dollar"
|
||||
icon="currency-dollar"
|
||||
color="text-success"
|
||||
/>
|
||||
<StatCard
|
||||
title="Active Members"
|
||||
value={String(statsByMember.filter(s => s.entryCount > 0).length)}
|
||||
description={`of ${teamMembers.length} total`}
|
||||
icon="heroicons:user-group"
|
||||
icon="user-group"
|
||||
color="text-accent"
|
||||
/>
|
||||
</div>
|
||||
@@ -374,7 +374,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:document-text" class="w-4 h-4" />
|
||||
<Icon name="document-text" class="w-4 h-4" />
|
||||
Invoices Overview
|
||||
</h2>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
@@ -410,7 +410,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:clipboard-document-list" class="w-4 h-4" />
|
||||
<Icon name="clipboard-document-list" class="w-4 h-4" />
|
||||
Quotes Overview
|
||||
</h2>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
@@ -451,7 +451,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100 mb-6">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:banknotes" class="w-4 h-4" />
|
||||
<Icon name="banknotes" class="w-4 h-4" />
|
||||
Revenue by Client
|
||||
</h2>
|
||||
<div class="overflow-x-auto">
|
||||
@@ -493,7 +493,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:chart-pie" class="w-4 h-4" />
|
||||
<Icon name="chart-pie" class="w-4 h-4" />
|
||||
Tag Distribution
|
||||
</h2>
|
||||
<div class="h-64 w-full">
|
||||
@@ -515,7 +515,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:chart-bar" class="w-4 h-4" />
|
||||
<Icon name="chart-bar" class="w-4 h-4" />
|
||||
Time by Client
|
||||
</h2>
|
||||
<div class="h-64 w-full">
|
||||
@@ -537,7 +537,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100 mb-6">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:users" class="w-4 h-4" />
|
||||
<Icon name="users" class="w-4 h-4" />
|
||||
Time by Team Member
|
||||
</h2>
|
||||
<div class="h-64 w-full">
|
||||
@@ -560,7 +560,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100 mb-6">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:users" class="w-4 h-4" />
|
||||
<Icon name="users" class="w-4 h-4" />
|
||||
By Team Member
|
||||
</h2>
|
||||
<div class="overflow-x-auto">
|
||||
@@ -601,7 +601,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100 mb-6">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:tag" class="w-4 h-4" />
|
||||
<Icon name="tag" class="w-4 h-4" />
|
||||
By Tag
|
||||
</h2>
|
||||
<div class="overflow-x-auto">
|
||||
@@ -653,7 +653,7 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card card-border bg-base-100 mb-6">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-3">
|
||||
<Icon name="heroicons:building-office" class="w-4 h-4" />
|
||||
<Icon name="building-office" class="w-4 h-4" />
|
||||
By Client
|
||||
</h2>
|
||||
<div class="overflow-x-auto">
|
||||
@@ -698,12 +698,12 @@ function getTimeRangeLabel(range: string) {
|
||||
<div class="card-body p-4">
|
||||
<div class="flex justify-between items-center mb-3">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2">
|
||||
<Icon name="heroicons:document-text" class="w-4 h-4" />
|
||||
<Icon name="document-text" class="w-4 h-4" />
|
||||
Detailed Entries ({entries.length})
|
||||
</h2>
|
||||
{entries.length > 0 && (
|
||||
<a href={`/api/reports/export${url.search}`} class="btn btn-xs btn-ghost" target="_blank">
|
||||
<Icon name="heroicons:arrow-down-tray" class="w-3.5 h-3.5" />
|
||||
<Icon name="arrow-down-tray" class="w-3.5 h-3.5" />
|
||||
Export CSV
|
||||
</a>
|
||||
)}
|
||||
@@ -758,11 +758,11 @@ function getTimeRangeLabel(range: string) {
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex flex-col items-center justify-center py-10 text-center">
|
||||
<Icon name="heroicons:inbox" class="w-12 h-12 text-base-content/15 mb-3" />
|
||||
<Icon name="inbox" class="w-12 h-12 text-base-content/15 mb-3" />
|
||||
<h3 class="text-base font-semibold mb-1">No time entries found</h3>
|
||||
<p class="text-base-content/50 text-sm mb-4">Try adjusting your filters or select a different time range.</p>
|
||||
<a href="/dashboard/tracker" class="btn btn-primary btn-sm">
|
||||
<Icon name="heroicons:play" class="w-4 h-4" />
|
||||
<Icon name="play" class="w-4 h-4" />
|
||||
Start Tracking Time
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../components/Icon.astro';
|
||||
import { db } from '../../db';
|
||||
import { apiTokens, passkeys } from '../../db/schema';
|
||||
import { eq, desc } from 'drizzle-orm';
|
||||
@@ -37,14 +37,14 @@ const userPasskeys = await db.select()
|
||||
{/* Success Messages */}
|
||||
{successType === 'profile' && (
|
||||
<div class="alert alert-success mb-6">
|
||||
<Icon name="heroicons:check-circle" class="w-5 h-5 sm:w-6 sm:h-6 shrink-0" />
|
||||
<Icon name="check-circle" class="w-5 h-5 sm:w-6 sm:h-6 shrink-0" />
|
||||
<span class="text-sm sm:text-base">Profile updated successfully!</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{successType === 'password' && (
|
||||
<div class="alert alert-success mb-6">
|
||||
<Icon name="heroicons:check-circle" class="w-5 h-5 sm:w-6 sm:h-6 shrink-0" />
|
||||
<Icon name="check-circle" class="w-5 h-5 sm:w-6 sm:h-6 shrink-0" />
|
||||
<span class="text-sm sm:text-base">Password changed successfully!</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -72,7 +72,7 @@ const userPasskeys = await db.select()
|
||||
<div class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-4">
|
||||
<Icon name="heroicons:information-circle" class="w-4 h-4" />
|
||||
<Icon name="information-circle" class="w-4 h-4" />
|
||||
Account Information
|
||||
</h2>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
import DashboardLayout from '../../layouts/DashboardLayout.astro';
|
||||
import Avatar from '../../components/Avatar.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../components/Icon.astro';
|
||||
import { db } from '../../db';
|
||||
import { members, users } from '../../db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
@@ -36,7 +36,7 @@ const isAdmin = currentUserMember?.member.role === 'owner' || currentUserMember?
|
||||
{isAdmin && (
|
||||
<>
|
||||
<a href="/dashboard/team/settings" class="btn btn-ghost btn-sm">
|
||||
<Icon name="heroicons:cog-6-tooth" class="w-4 h-4" />
|
||||
<Icon name="cog-6-tooth" class="w-4 h-4" />
|
||||
Settings
|
||||
</a>
|
||||
<a href="/dashboard/team/invite" class="btn btn-primary btn-sm">Invite Member</a>
|
||||
@@ -88,7 +88,7 @@ const isAdmin = currentUserMember?.member.role === 'owner' || currentUserMember?
|
||||
{teamUser.id !== user.id && member.role !== 'owner' && (
|
||||
<div class="dropdown dropdown-end">
|
||||
<div role="button" tabindex="0" class="btn btn-ghost btn-xs btn-square">
|
||||
<Icon name="heroicons:ellipsis-vertical" class="w-4 h-4" />
|
||||
<Icon name="ellipsis-vertical" class="w-4 h-4" />
|
||||
</div>
|
||||
<ul tabindex="0" class="dropdown-content z-1 menu p-2 bg-base-100 rounded-box w-52 border border-base-200">
|
||||
<li>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../components/Icon.astro';
|
||||
import { db } from '../../../db';
|
||||
import { members } from '../../../db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
@@ -34,7 +34,7 @@ if (!isAdmin) return Astro.redirect('/dashboard/team');
|
||||
<form method="POST" action="/api/team/invite" class="card card-border bg-base-100">
|
||||
<div class="card-body p-4">
|
||||
<div class="alert alert-info mb-4">
|
||||
<Icon name="heroicons:information-circle" class="w-4 h-4 shrink-0" />
|
||||
<Icon name="information-circle" class="w-4 h-4 shrink-0" />
|
||||
<span class="text-sm">The user must already have an account. They'll be added to your organization.</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../../components/Icon.astro';
|
||||
import { db } from '../../../db';
|
||||
import { organizations, tags } from '../../../db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
@@ -38,7 +38,7 @@ const successType = url.searchParams.get('success');
|
||||
<DashboardLayout title="Team Settings - Chronus">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<a href="/dashboard/team" class="btn btn-ghost btn-xs">
|
||||
<Icon name="heroicons:arrow-left" class="w-4 h-4" />
|
||||
<Icon name="arrow-left" class="w-4 h-4" />
|
||||
</a>
|
||||
<h1 class="text-2xl font-extrabold tracking-tight">Team Settings</h1>
|
||||
</div>
|
||||
@@ -47,13 +47,13 @@ const successType = url.searchParams.get('success');
|
||||
<div class="card card-border bg-base-100 mb-6">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2 mb-4">
|
||||
<Icon name="heroicons:building-office-2" class="w-4 h-4" />
|
||||
<Icon name="building-office-2" class="w-4 h-4" />
|
||||
Team Settings
|
||||
</h2>
|
||||
|
||||
{successType === 'org-name' && (
|
||||
<div class="alert alert-success mb-4">
|
||||
<Icon name="heroicons:check-circle" class="w-4 h-4" />
|
||||
<Icon name="check-circle" class="w-4 h-4" />
|
||||
<span class="text-sm">Team information updated successfully!</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -79,7 +79,7 @@ const successType = url.searchParams.get('success');
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
name="heroicons:photo"
|
||||
name="photo"
|
||||
class="w-6 h-6 opacity-40 text-base-content"
|
||||
/>
|
||||
)}
|
||||
@@ -218,7 +218,7 @@ const successType = url.searchParams.get('success');
|
||||
</span>
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-sm w-full sm:w-auto">
|
||||
<Icon name="heroicons:check" class="w-4 h-4" />
|
||||
<Icon name="check" class="w-4 h-4" />
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
@@ -231,11 +231,11 @@ const successType = url.searchParams.get('success');
|
||||
<div class="card-body p-4">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2">
|
||||
<Icon name="heroicons:tag" class="w-4 h-4" />
|
||||
<Icon name="tag" class="w-4 h-4" />
|
||||
Tags & Rates
|
||||
</h2>
|
||||
<button onclick="document.getElementById('new_tag_modal').showModal()" class="btn btn-primary btn-xs">
|
||||
<Icon name="heroicons:plus" class="w-3 h-3" />
|
||||
<Icon name="plus" class="w-3 h-3" />
|
||||
Add Tag
|
||||
</button>
|
||||
</div>
|
||||
@@ -246,7 +246,7 @@ const successType = url.searchParams.get('success');
|
||||
|
||||
{allTags.length === 0 ? (
|
||||
<div class="alert alert-info">
|
||||
<Icon name="heroicons:information-circle" class="w-4 h-4" />
|
||||
<Icon name="information-circle" class="w-4 h-4" />
|
||||
<div>
|
||||
<div class="font-semibold text-sm">No tags yet</div>
|
||||
<div class="text-xs">Create tags to add context and rates to your time entries.</div>
|
||||
@@ -286,11 +286,11 @@ const successType = url.searchParams.get('success');
|
||||
onclick={`document.getElementById('edit_tag_modal_${tag.id}').showModal()`}
|
||||
class="btn btn-ghost btn-xs btn-square"
|
||||
>
|
||||
<Icon name="heroicons:pencil" class="w-3 h-3" />
|
||||
<Icon name="pencil" class="w-3 h-3" />
|
||||
</button>
|
||||
<form method="POST" action={`/api/tags/${tag.id}/delete`} onsubmit="return confirm('Are you sure you want to delete this tag?');">
|
||||
<button class="btn btn-ghost btn-xs btn-square text-error">
|
||||
<Icon name="heroicons:trash" class="w-3 h-3" />
|
||||
<Icon name="trash" class="w-3 h-3" />
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import DashboardLayout from '../../layouts/DashboardLayout.astro';
|
||||
import { Icon } from 'astro-icon/components';
|
||||
import Icon from '../../components/Icon.astro';
|
||||
import Timer from '../../components/Timer.vue';
|
||||
import ManualEntry from '../../components/ManualEntry.vue';
|
||||
import { db } from '../../db';
|
||||
@@ -147,7 +147,7 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
<div class="tab-content bg-base-100 border-base-300 p-6">
|
||||
{allClients.length === 0 ? (
|
||||
<div class="alert alert-warning flex flex-col sm:flex-row items-center gap-4">
|
||||
<Icon name="heroicons:exclamation-triangle" class="stroke-current shrink-0 h-6 w-6" />
|
||||
<Icon name="exclamation-triangle" class="stroke-current shrink-0 h-6 w-6" />
|
||||
<span class="flex-1 text-center sm:text-left">You need to create a client before tracking time.</span>
|
||||
<a href="/dashboard/clients/new" class="btn btn-sm btn-primary whitespace-nowrap">Add Client</a>
|
||||
</div>
|
||||
@@ -170,7 +170,7 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
<div class="tab-content bg-base-100 border-base-300 p-6">
|
||||
{allClients.length === 0 ? (
|
||||
<div class="alert alert-warning flex flex-col sm:flex-row items-center gap-4">
|
||||
<Icon name="heroicons:exclamation-triangle" class="stroke-current shrink-0 h-6 w-6" />
|
||||
<Icon name="exclamation-triangle" class="stroke-current shrink-0 h-6 w-6" />
|
||||
<span class="flex-1 text-center sm:text-left">You need to create a client before adding time entries.</span>
|
||||
<a href="/dashboard/clients/new" class="btn btn-sm btn-primary whitespace-nowrap">Add Client</a>
|
||||
</div>
|
||||
@@ -247,7 +247,7 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
<input type="hidden" name="page" value="1" />
|
||||
<div class="flex items-end md:col-span-2 lg:col-span-1">
|
||||
<button type="submit" class="btn btn-primary btn-sm w-full">
|
||||
<Icon name="heroicons:magnifying-glass" class="w-4 h-4" />
|
||||
<Icon name="magnifying-glass" class="w-4 h-4" />
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
@@ -259,12 +259,12 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
<div class="card-body p-4">
|
||||
<div class="flex justify-between items-center mb-3">
|
||||
<h2 class="text-sm font-semibold flex items-center gap-2">
|
||||
<Icon name="heroicons:list-bullet" class="w-4 h-4" />
|
||||
<Icon name="list-bullet" class="w-4 h-4" />
|
||||
Time Entries ({totalCount?.count || 0} total)
|
||||
</h2>
|
||||
{(filterClient || filterStatus || filterType || searchTerm) && (
|
||||
<a href="/dashboard/tracker" class="btn btn-xs btn-ghost">
|
||||
<Icon name="heroicons:x-mark" class="w-3 h-3" />
|
||||
<Icon name="x-mark" class="w-3 h-3" />
|
||||
Clear Filters
|
||||
</a>
|
||||
)}
|
||||
@@ -289,12 +289,12 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
<td>
|
||||
{entry.isManual ? (
|
||||
<span class="badge badge-info badge-xs gap-1" title="Manual Entry">
|
||||
<Icon name="heroicons:pencil" class="w-3 h-3" />
|
||||
<Icon name="pencil" class="w-3 h-3" />
|
||||
Manual
|
||||
</span>
|
||||
) : (
|
||||
<span class="badge badge-success badge-xs gap-1" title="Timed Entry">
|
||||
<Icon name="heroicons:clock" class="w-3 h-3" />
|
||||
<Icon name="clock" class="w-3 h-3" />
|
||||
Timed
|
||||
</span>
|
||||
)}
|
||||
@@ -328,7 +328,7 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
class="btn btn-ghost btn-xs text-error"
|
||||
onclick="return confirm('Are you sure you want to delete this entry?')"
|
||||
>
|
||||
<Icon name="heroicons:trash" class="w-3.5 h-3.5" />
|
||||
<Icon name="trash" class="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
@@ -345,7 +345,7 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
href={`?page=${Math.max(1, page - 1)}${filterClient ? `&client=${filterClient}` : ''}${filterStatus ? `&status=${filterStatus}` : ''}${filterType ? `&type=${filterType}` : ''}${sortBy ? `&sort=${sortBy}` : ''}${searchTerm ? `&search=${searchTerm}` : ''}`}
|
||||
class={`btn btn-xs ${page === 1 ? 'btn-disabled' : ''}`}
|
||||
>
|
||||
<Icon name="heroicons:chevron-left" class="w-3 h-3" />
|
||||
<Icon name="chevron-left" class="w-3 h-3" />
|
||||
Prev
|
||||
</a>
|
||||
|
||||
@@ -365,7 +365,7 @@ const paginationPages = getPaginationPages(page, totalPages);
|
||||
class={`btn btn-xs ${page === totalPages ? 'btn-disabled' : ''}`}
|
||||
>
|
||||
Next
|
||||
<Icon name="heroicons:chevron-right" class="w-3 h-3" />
|
||||
<Icon name="chevron-right" class="w-3 h-3" />
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user