Integrate time clock directly into invoices, remove standalone page

- Remove "Time Clock" from sidebar navigation
- Redirect /dashboard/time-clock to /dashboard/invoices
- Add InvoiceTimerCard to invoice detail page (shown for non-paid invoices)
- Timer started from an invoice is explicitly linked to that invoice at clock-in
- On clock-out, time is added directly to the linked invoice as a line item
- Active timer widget on dashboard now shows which invoice is being tracked
- Backend: clockIn accepts invoiceId; clockOut prefers explicit invoiceId over
  searching for the latest draft invoice for the client

https://claude.ai/code/session_014126WHVRT8mftmqkU6dajG
This commit is contained in:
Claude
2026-06-11 00:23:50 +00:00
parent 0d8efb0c5f
commit feb8f36ce7
6 changed files with 307 additions and 666 deletions
+9
View File
@@ -61,6 +61,7 @@ import type { StoredInvoiceStatus } from "~/types/invoice";
import { InvoiceDetailsSkeleton } from "./_components/invoice-details-skeleton";
import { PDFDownloadButton } from "./_components/pdf-download-button";
import { EnhancedSendInvoiceButton } from "~/components/forms/enhanced-send-invoice-button";
import { InvoiceTimerCard } from "./_components/invoice-timer-card";
const PAYMENT_METHODS = [
{ value: "cash", label: "Cash" },
@@ -521,6 +522,14 @@ function InvoiceViewContent({ invoiceId }: { invoiceId: string }) {
{/* Right Column - Actions */}
<div className="space-y-6">
{effectiveStatus !== "paid" && (
<InvoiceTimerCard
invoiceId={invoiceId}
clientId={invoice.clientId}
defaultRate={invoice.client?.defaultHourlyRate}
/>
)}
<Card className="lg:sticky lg:top-6">
<CardHeader>
<CardTitle className="flex items-center gap-2">