diff --git a/.cursorrules b/.cursorrules index 47707cb..dca8759 100644 --- a/.cursorrules +++ b/.cursorrules @@ -425,4 +425,10 @@ export const exampleRouter = createTRPCRouter({ - Document emergency procedures ## Remember -This is a business application where reliability, security, and professional user experience are critical. Every decision should prioritize these values over development convenience or flashy features. \ No newline at end of file +This is a business application where reliability, security, and professional user experience are critical. Every decision should prioritize these values over development convenience or flashy features. + +- Don't create demo pages unless absolutely necessary. +- Don't create unnecessary complexity. +- Don't run builds unless absolutely necessary, if you do, kill the dev servers. +- Don't start new dev servers unless asked. +- Don't start drizzle studio- you cannot do anything with it. \ No newline at end of file diff --git a/src/app/dashboard/businesses/_components/businesses-data-table.tsx b/src/app/dashboard/businesses/_components/businesses-data-table.tsx index 5b66ed0..5bd32ce 100644 --- a/src/app/dashboard/businesses/_components/businesses-data-table.tsx +++ b/src/app/dashboard/businesses/_components/businesses-data-table.tsx @@ -1,6 +1,7 @@ "use client"; import Link from "next/link"; +import { useRouter } from "next/navigation"; import type { ColumnDef } from "@tanstack/react-table"; import { Button } from "~/components/ui/button"; import { DataTable, DataTableColumnHeader } from "~/components/data/data-table"; @@ -55,6 +56,7 @@ const formatAddress = (business: Business) => { export function BusinessesDataTable({ businesses: initialBusinesses, }: BusinessesDataTableProps) { + const router = useRouter(); const [businesses, setBusinesses] = useState(initialBusinesses); const [businessToDelete, setBusinessToDelete] = useState( null, @@ -79,6 +81,10 @@ export function BusinessesDataTable({ deleteBusinessMutation.mutate({ id: businessToDelete.id }); }; + const handleRowClick = (business: Business) => { + router.push(`/dashboard/businesses/${business.id}`); + }; + const columns: ColumnDef[] = [ { accessorKey: "name", @@ -153,6 +159,7 @@ export function BusinessesDataTable({ target="_blank" rel="noopener noreferrer" className="text-primary hidden hover:underline sm:inline" + data-action-button="true" > {website} @@ -162,6 +169,7 @@ export function BusinessesDataTable({ size="sm" className="h-8 w-8 p-0 sm:hidden" asChild + data-action-button="true" > @@ -178,7 +186,12 @@ export function BusinessesDataTable({ return (
- @@ -186,6 +199,7 @@ export function BusinessesDataTable({ variant="ghost" size="sm" className="h-8 w-8 p-0" + data-action-button="true" onClick={() => setBusinessToDelete(business)} > @@ -203,6 +217,7 @@ export function BusinessesDataTable({ data={businesses} searchKey="name" searchPlaceholder="Search businesses..." + onRowClick={handleRowClick} /> {/* Delete confirmation dialog */} @@ -215,8 +230,7 @@ export function BusinessesDataTable({ Are you sure? This action cannot be undone. This will permanently delete the - business "{businessToDelete?.name}" and remove all associated - data. + business "{businessToDelete?.name}" and remove all associated data. diff --git a/src/app/dashboard/clients/_components/clients-data-table.tsx b/src/app/dashboard/clients/_components/clients-data-table.tsx index e68d7e0..d10b7c8 100644 --- a/src/app/dashboard/clients/_components/clients-data-table.tsx +++ b/src/app/dashboard/clients/_components/clients-data-table.tsx @@ -1,6 +1,7 @@ "use client"; import Link from "next/link"; +import { useRouter } from "next/navigation"; import type { ColumnDef } from "@tanstack/react-table"; import { Button } from "~/components/ui/button"; import { DataTable, DataTableColumnHeader } from "~/components/data/data-table"; @@ -52,6 +53,7 @@ const formatAddress = (client: Client) => { export function ClientsDataTable({ clients: initialClients, }: ClientsDataTableProps) { + const router = useRouter(); const [clients, setClients] = useState(initialClients); const [clientToDelete, setClientToDelete] = useState(null); @@ -74,6 +76,10 @@ export function ClientsDataTable({ deleteClientMutation.mutate({ id: clientToDelete.id }); }; + const handleRowClick = (client: Client) => { + router.push(`/dashboard/clients/${client.id}`); + }; + const columns: ColumnDef[] = [ { accessorKey: "name", @@ -123,12 +129,12 @@ export function ClientsDataTable({ ), cell: ({ row }) => { - const date = row.getValue("createdAt") as Date; + const date = row.getValue("createdAt"); return new Intl.DateTimeFormat("en-US", { month: "short", day: "2-digit", year: "numeric", - }).format(new Date(date)); + }).format(new Date(date as Date)); }, meta: { headerClassName: "hidden xl:table-cell", @@ -142,7 +148,12 @@ export function ClientsDataTable({ return (
- @@ -150,6 +161,7 @@ export function ClientsDataTable({ variant="ghost" size="sm" className="h-8 w-8 p-0" + data-action-button="true" onClick={() => setClientToDelete(client)} > @@ -167,6 +179,7 @@ export function ClientsDataTable({ data={clients} searchKey="name" searchPlaceholder="Search clients..." + onRowClick={handleRowClick} /> {/* Delete confirmation dialog */} diff --git a/src/app/dashboard/invoices/[id]/edit/page.tsx b/src/app/dashboard/invoices/[id]/edit/page.tsx index d19cc93..6640a22 100644 --- a/src/app/dashboard/invoices/[id]/edit/page.tsx +++ b/src/app/dashboard/invoices/[id]/edit/page.tsx @@ -1,770 +1,11 @@ "use client"; -import { - ArrowLeft, - Building, - DollarSign, - Edit3, - Eye, - FileText, - Hash, - Loader2, - Plus, - Save, - Send, - Trash2, - User, -} from "lucide-react"; -import Link from "next/link"; -import { useParams, useRouter } from "next/navigation"; -import { useEffect, useRef, useState } from "react"; -import { toast } from "sonner"; -import { FloatingActionBar } from "~/components/layout/floating-action-bar"; -import { PageHeader } from "~/components/layout/page-header"; -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, - AlertDialogTrigger, -} from "~/components/ui/alert-dialog"; -import { Badge } from "~/components/ui/badge"; -import { Button } from "~/components/ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; -import { DatePicker } from "~/components/ui/date-picker"; -import { Label } from "~/components/ui/label"; -import { NumberInput } from "~/components/ui/number-input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "~/components/ui/select"; -import { Separator } from "~/components/ui/separator"; -import { Textarea } from "~/components/ui/textarea"; -import { api } from "~/trpc/react"; - -interface InvoiceItem { - id?: string; - tempId: string; - date: Date; - description: string; - hours: number; - rate: number; - amount: number; -} - -interface InvoiceFormData { - invoiceNumber: string; - businessId: string | undefined; - clientId: string; - issueDate: Date; - dueDate: Date; - notes: string; - taxRate: number; - items: InvoiceItem[]; - status: "draft" | "sent" | "paid" | "overdue"; -} - -function InvoiceItemCard({ - item, - index, - onUpdate, - onDelete, - _isLast, -}: { - item: InvoiceItem; - index: number; - onUpdate: ( - index: number, - field: keyof InvoiceItem, - value: string | number | Date, - ) => void; - onDelete: (index: number) => void; - _isLast: boolean; -}) { - const handleFieldChange = ( - field: keyof InvoiceItem, - value: string | number | Date, - ) => { - onUpdate(index, field, value); - }; - - return ( - -
- {/* Header with item number and delete */} -
- - Item {index + 1} - - - - - - - - Delete Item - - Are you sure you want to delete this line item? This action - cannot be undone. - - - - Cancel - onDelete(index)} - className="bg-red-600 hover:bg-red-700" - > - Delete - - - - -
- - {/* Description */} -