Theme overhaul

This commit is contained in:
2025-07-31 18:37:33 -04:00
parent a1616b161d
commit 8a2565adad
79 changed files with 2722 additions and 3917 deletions
+21 -21
View File
@@ -73,7 +73,7 @@ export function ClientList() {
return (
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 3 }, (_, i: number) => (
<Card key={i} className="card-primary">
<Card key={i} className="bg-card border-border border">
<CardHeader>
<div className="h-4 animate-pulse rounded bg-gray-200" />
</CardHeader>
@@ -91,9 +91,9 @@ export function ClientList() {
if (!clients || clients.length === 0) {
return (
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader className="text-center">
<CardTitle className="text-brand-gradient text-2xl font-bold">
<CardTitle className="text-primary text-2xl font-bold">
No Clients Yet
</CardTitle>
<CardDescription className="text-lg">
@@ -142,20 +142,20 @@ export function ClientList() {
{filteredClients.map((client) => (
<Card
key={client.id}
className="group card-primary transition-all duration-300 hover:shadow-lg"
className="group bg-card border-border border transition-all duration-300 hover:shadow-lg"
>
<CardHeader>
<CardTitle className="flex items-center justify-between text-lg">
<span className="text-accent group-hover:text-icon-emerald font-semibold transition-colors">
<span className="text-foreground group-hover:text-primary font-semibold transition-colors">
{client.name}
</span>
<div className="flex space-x-1 opacity-0 transition-opacity group-hover:opacity-100">
<Link href={`/clients/${client.id}`}>
<Link href={`/dashboard/clients/${client.id}`}>
<Button variant="ghost" size="sm" className="h-8 w-8 p-0">
<Eye className="h-4 w-4" />
</Button>
</Link>
<Link href={`/clients/${client.id}/edit`}>
<Link href={`/dashboard/clients/${client.id}/edit`}>
<Button variant="ghost" size="sm" className="h-8 w-8 p-0">
<Edit className="h-4 w-4" />
</Button>
@@ -173,25 +173,25 @@ export function ClientList() {
</CardHeader>
<CardContent className="space-y-3">
{client.email && (
<div className="text-secondary flex items-center text-sm">
<div className="bg-brand-muted mr-3 rounded p-1.5">
<Mail className="text-icon-emerald h-3 w-3" />
<div className="text-muted-foreground flex items-center text-sm">
<div className="bg-muted mr-3 rounded p-1.5">
<Mail className="text-muted-foreground h-3 w-3" />
</div>
{client.email}
</div>
)}
{client.phone && (
<div className="text-secondary flex items-center text-sm">
<div className="bg-brand-muted-blue mr-3 rounded p-1.5">
<Phone className="text-icon-blue h-3 w-3" />
<div className="text-muted-foreground flex items-center text-sm">
<div className="bg-muted mr-3 rounded p-1.5">
<Phone className="text-muted-foreground h-3 w-3" />
</div>
{client.phone}
</div>
)}
{(client.addressLine1 ?? client.city ?? client.state) && (
<div className="text-secondary flex items-start text-sm">
<div className="bg-brand-muted-teal mt-0.5 mr-3 flex-shrink-0 rounded p-1.5">
<MapPin className="text-icon-teal h-3 w-3" />
<div className="text-muted-foreground flex items-start text-sm">
<div className="bg-muted mt-0.5 mr-3 flex-shrink-0 rounded p-1.5">
<MapPin className="text-muted-foreground h-3 w-3" />
</div>
<div className="min-w-0">
{client.addressLine1 && <div>{client.addressLine1}</div>}
@@ -213,12 +213,12 @@ export function ClientList() {
</div>
<Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
<DialogContent className="card-primary">
<DialogContent className="bg-card border-border border">
<DialogHeader>
<DialogTitle className="text-accent text-xl font-bold">
<DialogTitle className="text-foreground text-xl font-bold">
Delete Client
</DialogTitle>
<DialogDescription className="text-secondary">
<DialogDescription className="text-muted-foreground">
Are you sure you want to delete this client? This action cannot be
undone.
</DialogDescription>
@@ -227,14 +227,14 @@ export function ClientList() {
<Button
variant="outline"
onClick={() => setDeleteDialogOpen(false)}
className="text-secondary"
className="text-muted-foreground"
>
Cancel
</Button>
<Button
variant="destructive"
onClick={confirmDelete}
className="bg-red-600 hover:bg-red-700"
className="bg-destructive hover:bg-destructive/90"
>
Delete
</Button>
@@ -28,10 +28,10 @@ export function CurrentOpenInvoiceCard() {
if (isLoading) {
return (
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader className="pb-3">
<CardTitle className="card-title-secondary">
<FileText className="text-icon-emerald h-5 w-5" />
<CardTitle className="text-foreground flex items-center gap-2">
<FileText className="text-primary h-5 w-5" />
Current Open Invoice
</CardTitle>
</CardHeader>
@@ -49,10 +49,10 @@ export function CurrentOpenInvoiceCard() {
if (!currentInvoice) {
return (
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader className="pb-3">
<CardTitle className="card-title-secondary">
<FileText className="text-icon-emerald h-5 w-5" />
<CardTitle className="text-foreground flex items-center gap-2">
<FileText className="text-primary h-5 w-5" />
Current Open Invoice
</CardTitle>
</CardHeader>
@@ -80,10 +80,10 @@ export function CurrentOpenInvoiceCard() {
const totalAmount = currentInvoice.totalAmount;
return (
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader className="pb-3">
<CardTitle className="card-title-secondary">
<FileText className="text-icon-emerald h-5 w-5" />
<CardTitle className="text-foreground flex items-center gap-2">
<FileText className="text-primary h-5 w-5" />
Current Open Invoice
</CardTitle>
</CardHeader>
@@ -91,13 +91,13 @@ export function CurrentOpenInvoiceCard() {
<div className="space-y-3">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Badge className="badge-secondary text-xs">
<Badge className="bg-secondary text-secondary-foreground text-xs">
{currentInvoice.invoiceNumber}
</Badge>
<Badge className="badge-outline text-xs">Draft</Badge>
<Badge className="border text-xs">Draft</Badge>
</div>
<div className="text-right">
<p className="text-icon-emerald text-sm font-medium">
<p className="text-primary text-sm font-medium">
{formatCurrency(totalAmount)}
</p>
</div>
+11 -11
View File
@@ -215,12 +215,12 @@ export function DataTable<TData, TValue>({
{/* Filter Bar Card */}
{(showSearch || filterableColumns.length > 0 || showColumnVisibility) && (
<Card className="card-primary py-2">
<Card className="bg-card border-border border py-2">
<CardContent className="px-3 py-0">
<div className="flex items-center gap-2">
{showSearch && (
<div className="relative min-w-0 flex-1">
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
<Search className="text-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
<Input
placeholder={searchPlaceholder}
value={globalFilter ?? ""}
@@ -244,7 +244,7 @@ export function DataTable<TData, TValue>({
>
<SelectTrigger className="h-9 w-9 p-0 sm:w-[180px] sm:px-3 [&>svg]:hidden sm:[&>svg]:inline-flex">
<div className="flex w-full items-center justify-center">
<Filter className="h-4 w-4 sm:hidden" />
<Filter className="text-foreground h-4 w-4 sm:hidden" />
<span className="hidden sm:inline">
<SelectValue placeholder={column.title} />
</span>
@@ -272,7 +272,7 @@ export function DataTable<TData, TValue>({
>
<X className="h-4 w-4 sm:hidden" />
<span className="hidden sm:flex sm:items-center">
<Filter className="mr-2 h-3.5 w-3.5" />
<Filter className="text-foreground mr-2 h-3.5 w-3.5" />
Clear filters
</span>
</Button>
@@ -315,7 +315,7 @@ export function DataTable<TData, TValue>({
)}
{/* Table Content Card */}
<Card className="card-primary overflow-hidden p-0">
<Card className="bg-card border-border overflow-hidden border p-0">
<div className="w-full overflow-x-auto">
<Table>
<TableHeader>
@@ -400,7 +400,7 @@ export function DataTable<TData, TValue>({
{/* Pagination Bar Card */}
{showPagination && (
<Card className="card-primary py-2">
<Card className="bg-card border-border border py-2">
<CardContent className="px-3 py-0">
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2">
@@ -561,17 +561,17 @@ export function DataTableSkeleton({
return (
<div className="space-y-4">
{/* Filter bar skeleton */}
<Card className="card-primary py-2">
<Card className="bg-card border-border border py-2">
<CardContent className="px-3 py-0">
<div className="flex items-center gap-2">
<div className="bg-muted/30 h-9 w-full flex-1 animate-pulse rounded-md sm:max-w-sm"></div>
<div className="bg-muted/30 h-9 w-24 animate-pulse rounded-md"></div>
<div className="bg-muted/30 h-9 w-full flex-1 animate-pulse sm:max-w-sm"></div>
<div className="bg-muted/30 h-9 w-24 animate-pulse"></div>
</div>
</CardContent>
</Card>
{/* Table skeleton */}
<Card className="card-primary overflow-hidden p-0">
<Card className="bg-card border-border overflow-hidden border p-0">
<div className="w-full overflow-x-auto">
<Table>
<TableHeader>
@@ -632,7 +632,7 @@ export function DataTableSkeleton({
</Card>
{/* Pagination skeleton */}
<Card className="card-primary py-2">
<Card className="bg-card border-border border py-2">
<CardContent className="px-3 py-0">
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2">
@@ -87,7 +87,7 @@ function SortableItem({
<div
ref={setNodeRef}
style={style}
className={`card-secondary rounded-lg transition-colors ${
className={`card-secondary transition-colors ${
isDragging ? "opacity-50 shadow-lg" : ""
}`}
>
@@ -154,7 +154,7 @@ function SortableItem({
{/* Amount */}
<div className="col-span-1">
<div className="bg-muted/30 flex h-9 items-center rounded-md border px-3 font-medium text-emerald-600">
<div className="bg-muted/30 text-primary flex h-9 items-center border px-3 font-medium">
${item.amount.toFixed(2)}
</div>
</div>
@@ -166,7 +166,7 @@ function SortableItem({
onClick={() => onRemove(index)}
variant="ghost"
size="sm"
className="h-9 w-9 p-0 text-red-600 hover:bg-red-50 hover:text-red-700"
className="text-destructive hover:bg-destructive/10 hover:text-destructive/80 h-9 w-9 p-0"
>
<Trash2 className="h-4 w-4" />
</Button>
@@ -206,7 +206,7 @@ function SortableItem({
onClick={() => onRemove(index)}
variant="ghost"
size="sm"
className="h-6 w-6 p-0 text-red-600 hover:bg-red-50 hover:text-red-700"
className="text-destructive hover:bg-destructive/10 hover:text-destructive/80 h-6 w-6 p-0"
>
<Trash2 className="h-3 w-3" />
</Button>
@@ -266,10 +266,10 @@ function SortableItem({
</div>
{/* Amount */}
<div className="bg-muted/20 rounded-md border p-3">
<div className="bg-muted/20 border p-3">
<div className="flex items-center justify-between">
<span className="text-muted-foreground text-sm">Total Amount:</span>
<span className="font-mono text-lg font-bold text-emerald-600">
<span className="text-primary font-mono text-lg font-bold">
${item.amount.toFixed(2)}
</span>
</div>
@@ -362,7 +362,7 @@ export function EditableInvoiceItems({
{items.map((item, _index) => (
<div
key={item.id}
className="card-secondary animate-pulse rounded-lg p-4"
className="card-secondary animate-pulse p-4"
>
{/* Desktop Skeleton */}
<div className="hidden grid-cols-12 gap-3 md:grid">
+3 -3
View File
@@ -150,12 +150,12 @@ export function InvoiceList() {
<CardTitle className="flex items-center justify-between">
<span className="truncate">{invoice.invoiceNumber}</span>
<div className="flex space-x-1">
<Link href={`/dashboard/invoices/${invoice.id}/view`}>
<Link href={`/dashboard/invoices/${invoice.id}`}>
<Button variant="ghost" size="sm">
<Eye className="h-4 w-4" />
</Button>
</Link>
<Link href={`/dashboard/invoices/${invoice.id}`}>
<Link href={`/dashboard/invoices/${invoice.id}/edit`}>
<Button variant="ghost" size="sm">
<Edit className="h-4 w-4" />
</Button>
@@ -171,7 +171,7 @@ export function InvoiceList() {
</CardTitle>
<div className="flex items-center justify-between">
<StatusBadge status={invoice.status as StatusType} />
<span className="text-icon-green text-lg font-bold">
<span className="text-primary text-lg font-bold">
{formatCurrency(invoice.totalAmount)}
</span>
</div>
+45 -55
View File
@@ -148,7 +148,7 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
return (
<div className="py-12 text-center">
<FileText className="text-muted mx-auto mb-4 h-12 w-12" />
<h3 className="text-accent mb-2 text-lg font-medium">
<h3 className="text-foreground mb-2 text-lg font-medium">
Invoice not found
</h3>
<p className="text-muted mb-4">
@@ -169,9 +169,9 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
<div className="space-y-6">
{/* Status Alert */}
{isOverdue && (
<Card className="border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-900/20">
<Card className="border-destructive/20 bg-destructive/10">
<CardContent className="p-4">
<div className="text-error flex items-center gap-2">
<div className="text-destructive flex items-center gap-2">
<AlertCircle className="h-5 w-5" />
<span className="font-medium">This invoice is overdue</span>
</div>
@@ -183,13 +183,13 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
{/* Main Content */}
<div className="space-y-6 lg:col-span-2">
{/* Invoice Header Card */}
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardContent>
<div className="flex items-start justify-between">
<div className="space-y-4">
<div className="flex items-center gap-3">
<div className="rounded-lg bg-emerald-100 p-2 dark:bg-emerald-900/30">
<FileText className="h-6 w-6 text-emerald-600 dark:text-emerald-400" />
<div className="bg-primary/10 p-2">
<FileText className="text-primary h-6 w-6" />
</div>
<div>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
@@ -228,7 +228,7 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
>
<StatusIcon className="mr-1 h-3 w-3" />
</StatusBadge>
<div className="text-3xl font-bold text-emerald-600 dark:text-emerald-400">
<div className="text-primary text-3xl font-bold">
{formatCurrency(invoice.totalAmount)}
</div>
<Button
@@ -239,7 +239,7 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
>
{isExportingPDF ? (
<>
<div className="mr-2 h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" />
<div className="mr-2 h-4 w-4 animate-spin border-2 border-white border-t-transparent" />
Generating PDF...
</>
) : (
@@ -255,9 +255,9 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
</Card>
{/* Client Information */}
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-emerald-700 dark:text-emerald-400">
<CardTitle className="text-primary flex items-center gap-2">
<User className="h-5 w-5" />
Bill To
</CardTitle>
@@ -318,31 +318,31 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
</Card>
{/* Invoice Items */}
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-emerald-700 dark:text-emerald-400">
<CardTitle className="text-primary flex items-center gap-2">
<Clock className="h-5 w-5" />
Invoice Items
</CardTitle>
</CardHeader>
<CardContent>
<div className="overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700">
<div className="border-border overflow-hidden border">
<table className="w-full">
<thead className="bg-gray-50 dark:bg-gray-700">
<thead className="bg-muted">
<tr>
<th className="px-4 py-3 text-left text-sm font-semibold text-gray-700 dark:text-gray-300">
<th className="text-muted-foreground px-4 py-3 text-left text-sm font-semibold">
Date
</th>
<th className="px-4 py-3 text-left text-sm font-semibold text-gray-700 dark:text-gray-300">
<th className="text-muted-foreground px-4 py-3 text-left text-sm font-semibold">
Description
</th>
<th className="px-4 py-3 text-right text-sm font-semibold text-gray-700 dark:text-gray-300">
<th className="text-muted-foreground px-4 py-3 text-right text-sm font-semibold">
Hours
</th>
<th className="px-4 py-3 text-right text-sm font-semibold text-gray-700 dark:text-gray-300">
<th className="text-muted-foreground px-4 py-3 text-right text-sm font-semibold">
Rate
</th>
<th className="px-4 py-3 text-right text-sm font-semibold text-gray-700 dark:text-gray-300">
<th className="text-muted-foreground px-4 py-3 text-right text-sm font-semibold">
Amount
</th>
</tr>
@@ -351,21 +351,21 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
{invoice.items?.map((item, index) => (
<tr
key={item.id || index}
className="border-t border-gray-100 hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-gray-700"
className="border-border hover:bg-muted/50 border-t"
>
<td className="px-4 py-3 text-sm text-gray-900 dark:text-gray-300">
<td className="text-foreground px-4 py-3 text-sm">
{formatDate(item.date)}
</td>
<td className="px-4 py-3 text-sm text-gray-900 dark:text-gray-300">
<td className="text-foreground px-4 py-3 text-sm">
{item.description}
</td>
<td className="px-4 py-3 text-right text-sm text-gray-900 dark:text-gray-300">
<td className="text-foreground px-4 py-3 text-right text-sm">
{item.hours}
</td>
<td className="px-4 py-3 text-right text-sm text-gray-900 dark:text-gray-300">
<td className="text-foreground px-4 py-3 text-right text-sm">
{formatCurrency(item.rate)}
</td>
<td className="px-4 py-3 text-right text-sm font-medium text-gray-900 dark:text-gray-300">
<td className="text-foreground px-4 py-3 text-right text-sm font-medium">
{formatCurrency(item.amount)}
</td>
</tr>
@@ -378,11 +378,9 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
{/* Notes */}
{invoice.notes && (
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader>
<CardTitle className="text-emerald-700 dark:text-emerald-400">
Notes
</CardTitle>
<CardTitle className="text-primary">Notes</CardTitle>
</CardHeader>
<CardContent>
<p className="whitespace-pre-wrap text-gray-700 dark:text-gray-300">
@@ -396,18 +394,16 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
{/* Sidebar */}
<div className="space-y-6">
{/* Status Actions */}
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader>
<CardTitle className="text-emerald-700 dark:text-emerald-400">
Status Actions
</CardTitle>
<CardTitle className="text-primary">Status Actions</CardTitle>
</CardHeader>
<CardContent className="space-y-3">
{invoice.status === "draft" && (
<Button
onClick={() => handleStatusUpdate("sent")}
disabled={updateStatus.isPending}
className="w-full bg-blue-600 text-white hover:bg-blue-700"
className="bg-primary text-primary-foreground hover:bg-primary/90 w-full"
>
<Send className="mr-2 h-4 w-4" />
Mark as Sent
@@ -418,7 +414,7 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
<Button
onClick={() => handleStatusUpdate("paid")}
disabled={updateStatus.isPending}
className="w-full bg-green-600 text-white hover:bg-green-700"
className="bg-primary text-primary-foreground hover:bg-primary/90 w-full"
>
<DollarSign className="mr-2 h-4 w-4" />
Mark as Paid
@@ -429,7 +425,7 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
<Button
onClick={() => handleStatusUpdate("paid")}
disabled={updateStatus.isPending}
className="w-full bg-green-600 text-white hover:bg-green-700"
className="bg-primary text-primary-foreground hover:bg-primary/90 w-full"
>
<DollarSign className="mr-2 h-4 w-4" />
Mark as Paid
@@ -438,21 +434,17 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
{invoice.status === "paid" && (
<div className="py-4 text-center">
<DollarSign className="mx-auto mb-2 h-8 w-8 text-green-600 dark:text-green-400" />
<p className="font-medium text-green-600 dark:text-green-400">
Invoice Paid
</p>
<DollarSign className="text-primary mx-auto mb-2 h-8 w-8" />
<p className="text-primary font-medium">Invoice Paid</p>
</div>
)}
</CardContent>
</Card>
{/* Invoice Summary */}
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardHeader>
<CardTitle className="text-emerald-700 dark:text-emerald-400">
Summary
</CardTitle>
<CardTitle className="text-primary">Summary</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-3">
@@ -471,14 +463,14 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
<Separator />
<div className="flex justify-between text-lg font-bold">
<span className="dark:text-white">Total</span>
<span className="text-emerald-600 dark:text-emerald-400">
<span className="text-primary">
{formatCurrency(invoice.totalAmount)}
</span>
</div>
</div>
<div className="border-t border-gray-200 pt-4 text-center dark:border-gray-700">
<p className="text-sm text-gray-500 dark:text-gray-400">
<div className="border-border border-t pt-4 text-center">
<p className="text-muted-foreground text-sm">
{invoice.items?.length ?? 0} item
{invoice.items?.length !== 1 ? "s" : ""}
</p>
@@ -487,17 +479,15 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
</Card>
{/* Danger Zone */}
<Card className="card-primary border-red-200 dark:border-red-800">
<Card className="bg-card border-border border border-destructive/20">
<CardHeader>
<CardTitle className="text-red-700 dark:text-red-400">
Danger Zone
</CardTitle>
<CardTitle className="text-destructive">Danger Zone</CardTitle>
</CardHeader>
<CardContent>
<Button
onClick={handleDelete}
variant="outline"
className="w-full border-red-200 text-red-700 hover:bg-red-50 dark:border-red-800 dark:text-red-400 dark:hover:bg-red-900/20"
className="border-destructive/20 text-destructive hover:bg-destructive/10 w-full"
>
<Trash2 className="mr-2 h-4 w-4" />
Delete Invoice
@@ -509,7 +499,7 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
{/* Delete Confirmation Dialog */}
<Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
<DialogContent className="card-primary">
<DialogContent className="bg-card border-border border">
<DialogHeader>
<DialogTitle className="text-xl font-bold text-gray-800 dark:text-white">
Delete Invoice
@@ -524,7 +514,7 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
<Button
variant="outline"
onClick={() => setDeleteDialogOpen(false)}
className="border-gray-300 text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-800"
className="border-border text-muted-foreground hover:bg-muted"
>
Cancel
</Button>
@@ -532,7 +522,7 @@ export function InvoiceView({ invoiceId }: InvoiceViewProps) {
variant="destructive"
onClick={confirmDelete}
disabled={deleteInvoice.isPending}
className="bg-red-600 hover:bg-red-700"
className="bg-destructive hover:bg-destructive/90"
>
{deleteInvoice.isPending ? "Deleting..." : "Delete Invoice"}
</Button>
+5 -7
View File
@@ -22,8 +22,8 @@ const variantStyles = {
background: "bg-muted/50",
},
success: {
icon: "text-status-success",
background: "bg-status-success-muted",
icon: "text-primary",
background: "bg-primary/10",
},
warning: {
icon: "text-status-warning",
@@ -67,9 +67,7 @@ export function StatsCard({
<span
className={cn(
"text-sm font-medium",
trend.isPositive
? "text-status-success"
: "text-status-error",
trend.isPositive ? "text-primary" : "text-destructive",
)}
>
{trend.isPositive ? "+" : ""}
@@ -82,7 +80,7 @@ export function StatsCard({
)}
</div>
{Icon && (
<div className={cn("rounded-full p-3", styles.background)}>
<div className={cn(" p-3", styles.background)}>
<Icon className={cn("h-6 w-6", styles.icon)} />
</div>
)}
@@ -94,7 +92,7 @@ export function StatsCard({
export function StatsCardSkeleton() {
return (
<Card className="card-primary">
<Card className="bg-card border-border border">
<CardContent className="p-6">
<div className="animate-pulse">
<div className="bg-muted mb-2 h-4 w-1/2 rounded"></div>
+8 -12
View File
@@ -19,19 +19,15 @@ interface StatusBadgeProps
}
const statusClassMap: Record<StatusType, string> = {
draft:
"border-slate-400 bg-slate-100/90 text-slate-800 shadow-md dark:border-slate-600 dark:bg-slate-700/90 dark:text-slate-200",
sent: "border-blue-400 bg-blue-100/90 text-blue-800 shadow-md dark:border-blue-600 dark:bg-blue-700/90 dark:text-blue-200",
paid: "border-green-400 bg-green-100/90 text-green-800 shadow-md dark:border-green-600 dark:bg-green-700/90 dark:text-green-200",
overdue:
"border-red-400 bg-red-100/90 text-red-800 shadow-md dark:border-red-600 dark:bg-red-700/90 dark:text-red-200",
success:
"border-green-400 bg-green-100/90 text-green-800 shadow-md dark:border-green-600 dark:bg-green-700/90 dark:text-green-200",
draft: "border-muted-foreground/40 bg-muted text-muted-foreground shadow-sm",
sent: "border-primary/40 bg-primary/10 text-primary shadow-sm",
paid: "border-primary/40 bg-primary/10 text-primary shadow-sm",
overdue: "border-destructive/40 bg-destructive/10 text-destructive shadow-sm",
success: "border-primary/40 bg-primary/10 text-primary shadow-sm",
warning:
"border-yellow-400 bg-yellow-100/90 text-yellow-800 shadow-md dark:border-yellow-600 dark:bg-yellow-700/90 dark:text-yellow-200",
error:
"border-red-400 bg-red-100/90 text-red-800 shadow-md dark:border-red-600 dark:bg-red-700/90 dark:text-red-200",
info: "border-blue-400 bg-blue-100/90 text-blue-800 shadow-md dark:border-blue-600 dark:bg-blue-700/90 dark:text-blue-200",
"border-muted-foreground/40 bg-muted text-muted-foreground shadow-sm",
error: "border-destructive/40 bg-destructive/10 text-destructive shadow-sm",
info: "border-primary/40 bg-primary/10 text-primary shadow-sm",
};
const statusLabelMap: Record<StatusType, string> = {