feat: implement complete invoicing application with CSV import and PDF export

- Add comprehensive CSV import system with drag-and-drop upload and validation
- Create UniversalTable component with advanced filtering, searching, and batch actions
- Implement invoice management (view, edit, delete) with professional PDF export
- Add client management with full CRUD operations
- Set up authentication with NextAuth.js and email/password login
- Configure database schema with users, clients, invoices, and invoice_items tables
- Build responsive UI with shadcn/ui components and emerald branding
- Add type-safe API layer with tRPC and Zod validation
- Include proper error handling and user feedback with toast notifications
- Set up development environment with Bun, TypeScript, and Tailwind CSS
This commit is contained in:
2025-07-10 04:07:19 -04:00
commit 2d217fab47
85 changed files with 17074 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
"use client"
import { format } from "date-fns"
import { Calendar as CalendarIcon } from "lucide-react"
import * as React from "react"
import { Button } from "~/components/ui/button"
import { Calendar } from "~/components/ui/calendar"
import { Label } from "~/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover"
import { cn } from "~/lib/utils"
interface DatePickerProps {
date?: Date
onDateChange: (date: Date | undefined) => void
label?: string
placeholder?: string
className?: string
disabled?: boolean
required?: boolean
id?: string
}
export function DatePicker({
date,
onDateChange,
label,
placeholder = "Select date",
className,
disabled = false,
required = false,
id
}: DatePickerProps) {
const [open, setOpen] = React.useState(false)
return (
<div className={cn("flex flex-col gap-2", className)}>
{label && (
<Label htmlFor={id} className="text-sm font-medium text-gray-700">
{label}
{required && <span className="text-red-500 ml-1">*</span>}
</Label>
)}
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id={id}
disabled={disabled}
className={cn(
"w-full justify-between font-normal h-9 border-gray-200 focus:border-emerald-500 focus:ring-emerald-500 text-sm",
!date && "text-gray-500"
)}
>
{date ? format(date, "PPP") : placeholder}
<CalendarIcon className="h-4 w-4 text-gray-400" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(selectedDate: Date | undefined) => {
onDateChange(selectedDate)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
)
}