polish
This commit is contained in:
parent
4bdddaa7e7
commit
08a3132bec
@ -2,7 +2,9 @@
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(cat:*)",
|
||||
"Bash(tree:*)"
|
||||
"Bash(tree:*)",
|
||||
"Bash(pnpm run build:*)",
|
||||
"Bash(pnpm run dev:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,12 +6,14 @@ import { MetricCard } from "@/components/dashboard/metric-card"
|
||||
import { RevenueChart } from "@/components/dashboard/revenue-chart"
|
||||
import { SalesChart } from "@/components/dashboard/sales-chart"
|
||||
import { PaymentsTable } from "@/components/dashboard/payments-table"
|
||||
import { UnclassifiedPaymentsTable } from "@/components/dashboard/unclassified-payments-table"
|
||||
import { TeamTable } from "@/components/dashboard/team-table"
|
||||
import { getDashboardData } from "@/lib/mock-data"
|
||||
|
||||
export default function Home() {
|
||||
const data = getDashboardData()
|
||||
|
||||
// <TeamTable team={data.team} />
|
||||
return (
|
||||
<>
|
||||
<AppSidebar />
|
||||
@ -40,7 +42,7 @@ export default function Home() {
|
||||
<PaymentsTable payments={data.payments} />
|
||||
</div>
|
||||
<div className="col-span-3">
|
||||
<TeamTable team={data.team} />
|
||||
<UnclassifiedPaymentsTable transactions={data.transactions} />
|
||||
</div>
|
||||
</div>
|
||||
</DashboardTabs>
|
||||
|
||||
@ -30,14 +30,22 @@ interface PaymentsTableProps {
|
||||
}
|
||||
|
||||
export function PaymentsTable({ payments }: PaymentsTableProps) {
|
||||
const getStatusColor = (status: Payment["status"]) => {
|
||||
switch (status) {
|
||||
case "success":
|
||||
return "bg-green-500/10 text-green-500 hover:bg-green-500/20"
|
||||
case "processing":
|
||||
return "bg-yellow-500/10 text-yellow-500 hover:bg-yellow-500/20"
|
||||
case "failed":
|
||||
return "bg-red-500/10 text-red-500 hover:bg-red-500/20"
|
||||
const getCategoryColor = (category: Payment["category"]) => {
|
||||
switch (category) {
|
||||
case "groceries":
|
||||
return "bg-green-500/15 text-green-500 hover:bg-green-500/20"
|
||||
case "utilities":
|
||||
return "bg-blue-500/15 text-blue-500 hover:bg-blue-500/20"
|
||||
case "transport":
|
||||
return "bg-purple-500/15 text-purple-500 hover:bg-purple-500/20"
|
||||
case "entertainment":
|
||||
return "bg-pink-500/15 text-pink-500 hover:bg-pink-500/20"
|
||||
case "shopping":
|
||||
return "bg-orange-500/15 text-orange-500 hover:bg-orange-500/20"
|
||||
case "insurance":
|
||||
return "bg-red-500/15 text-red-500 hover:bg-red-500/20"
|
||||
case "housing":
|
||||
return "bg-yellow-500/15 text-yellow-500 hover:bg-yellow-500/20"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@ -54,8 +62,8 @@ export function PaymentsTable({ payments }: PaymentsTableProps) {
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Email</TableHead>
|
||||
<TableHead>Category</TableHead>
|
||||
<TableHead>Description</TableHead>
|
||||
<TableHead className="text-right">Amount</TableHead>
|
||||
<TableHead className="text-right">Actions</TableHead>
|
||||
</TableRow>
|
||||
@ -64,11 +72,11 @@ export function PaymentsTable({ payments }: PaymentsTableProps) {
|
||||
{payments.map((payment) => (
|
||||
<TableRow key={payment.id}>
|
||||
<TableCell>
|
||||
<Badge className={getStatusColor(payment.status)} variant="secondary">
|
||||
{payment.status}
|
||||
<Badge className={getCategoryColor(payment.category)} variant="secondary">
|
||||
{payment.category}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">{payment.email}</TableCell>
|
||||
<TableCell className="font-medium">{payment.description}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
${payment.amount.toFixed(2)}
|
||||
</TableCell>
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import { useTheme } from "next-themes"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { LineChart } from "@/components/charts/line-chart"
|
||||
import { getChartColors } from "@/lib/chart-config"
|
||||
import type { ChartDataPoint } from "@/types/dashboard"
|
||||
|
||||
interface RevenueChartProps {
|
||||
@ -9,32 +11,35 @@ interface RevenueChartProps {
|
||||
}
|
||||
|
||||
export function RevenueChart({ data }: RevenueChartProps) {
|
||||
const { theme } = useTheme()
|
||||
const colors = getChartColors(theme)
|
||||
|
||||
const chartData = {
|
||||
labels: data.map((d) => d.label),
|
||||
datasets: [
|
||||
{
|
||||
label: "Revenue",
|
||||
data: data.map((d) => d.value),
|
||||
borderColor: "rgb(244, 114, 182)",
|
||||
backgroundColor: "rgba(244, 114, 182, 0.2)",
|
||||
borderColor: colors.blue,
|
||||
backgroundColor: `${colors.blue.replace('rgb', 'rgba').replace(')', ', 0.2)')}`,
|
||||
},
|
||||
{
|
||||
label: "Subscriptions",
|
||||
data: data.map((d) => d.secondaryValue || 0),
|
||||
borderColor: "rgb(94, 234, 212)",
|
||||
backgroundColor: "rgba(94, 234, 212, 0.2)",
|
||||
borderColor: colors.orange,
|
||||
backgroundColor: `${colors.orange.replace('rgb', 'rgba').replace(')', ', 0.2)')}`,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="h-[300px] flex flex-col">
|
||||
<Card className="h-[350px] flex flex-col">
|
||||
<CardHeader className="flex-shrink-0">
|
||||
<CardTitle>Revenue Overview</CardTitle>
|
||||
<CardDescription>Showing total revenue for the last 6 months</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex-1 min-h-0">
|
||||
<LineChart data={chartData} height={180} showGrid={false} showPoints={false} />
|
||||
<LineChart data={chartData} height={230} showGrid={false} showPoints={false} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import { useTheme } from "next-themes"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { BarChart } from "@/components/charts/bar-chart"
|
||||
import { getChartColors } from "@/lib/chart-config"
|
||||
import type { ChartDataPoint } from "@/types/dashboard"
|
||||
|
||||
interface SalesChartProps {
|
||||
@ -9,6 +11,9 @@ interface SalesChartProps {
|
||||
}
|
||||
|
||||
export function SalesChart({ data }: SalesChartProps) {
|
||||
const { theme } = useTheme()
|
||||
const colors = getChartColors(theme)
|
||||
|
||||
// Calculate total and change percentage
|
||||
const total = data.reduce((sum, d) => sum + d.value, 0)
|
||||
const lastMonthValue = data[data.length - 2]?.value || 0
|
||||
@ -17,16 +22,16 @@ export function SalesChart({ data }: SalesChartProps) {
|
||||
? (((currentMonthValue - lastMonthValue) / lastMonthValue) * 100).toFixed(1)
|
||||
: "0.0"
|
||||
|
||||
// Alternate colors for bars
|
||||
// Alternate colors for bars using centralized palette
|
||||
const backgroundColors = data.map((_, index) =>
|
||||
index % 2 === 0 ? "rgb(251, 113, 133)" : "rgb(94, 234, 212)"
|
||||
index % 2 === 0 ? colors.darkBlue : colors.orange
|
||||
)
|
||||
|
||||
const chartData = {
|
||||
labels: data.map((d) => d.label),
|
||||
datasets: [
|
||||
{
|
||||
label: "Sales",
|
||||
label: "Expenditure",
|
||||
data: data.map((d) => d.value),
|
||||
backgroundColor: backgroundColors,
|
||||
},
|
||||
@ -34,13 +39,13 @@ export function SalesChart({ data }: SalesChartProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="h-[300px] flex flex-col">
|
||||
<Card className="h-[350px] flex flex-col">
|
||||
<CardHeader className="flex-shrink-0">
|
||||
<CardTitle>Subscriptions</CardTitle>
|
||||
<CardTitle>Expenditure</CardTitle>
|
||||
<CardDescription>+{changePercent}% from last month</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex-1 min-h-0">
|
||||
<BarChart data={chartData} height={180} showGrid={false} />
|
||||
<BarChart data={chartData} height={230} showGrid={false} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
|
||||
78
components/dashboard/unclassified-payments-table.tsx
Normal file
78
components/dashboard/unclassified-payments-table.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { MoreHorizontal } from "lucide-react"
|
||||
import type { Transaction } from "@/types/dashboard"
|
||||
|
||||
interface TransactionsTableProps {
|
||||
transactions: Transaction[]
|
||||
}
|
||||
|
||||
export function UnclassifiedPaymentsTable({ transactions }: TransactionsTableProps) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Unclassified Transactions</CardTitle>
|
||||
<CardDescription>You have {transactions.length} transactions that need to be labeled.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="overflow-x-auto">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Description</TableHead>
|
||||
<TableHead className="text-right">Amount</TableHead>
|
||||
<TableHead className="text-right">Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{transactions.map((transaction) => (
|
||||
<TableRow key={transaction.id}>
|
||||
<TableCell className="font-medium">{transaction.description}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
${transaction.amount.toFixed(2)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>View details</DropdownMenuItem>
|
||||
<DropdownMenuItem>Categorize</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -27,9 +27,21 @@ export function getChartColors(theme: string | undefined) {
|
||||
const isDark = theme === "dark"
|
||||
|
||||
return {
|
||||
primary: isDark ? "rgb(96, 165, 250)" : "rgb(59, 130, 246)",
|
||||
secondary: isDark ? "rgb(168, 85, 247)" : "rgb(147, 51, 234)",
|
||||
success: isDark ? "rgb(74, 222, 128)" : "rgb(34, 197, 94)",
|
||||
// Primary colors for chart elements
|
||||
primary: isDark ? "rgb(96, 165, 250)" : "rgb(59, 130, 246)", // blue
|
||||
secondary: isDark ? "rgb(168, 85, 247)" : "rgb(147, 51, 234)", // purple
|
||||
success: isDark ? "rgb(74, 222, 128)" : "rgb(34, 197, 94)", // green
|
||||
|
||||
// Additional chart colors
|
||||
orange: isDark ? "rgb(237, 152, 95)" : "rgb(237, 152, 95)",
|
||||
pink: isDark ? "rgb(236, 72, 153)" : "rgb(236, 72, 153)",
|
||||
amber: isDark ? "rgb(251, 191, 36)" : "rgb(251, 191, 36)",
|
||||
teal: isDark ? "rgb(94, 234, 212)" : "rgb(94, 234, 212)",
|
||||
rose: isDark ? "rgb(244, 114, 182)" : "rgb(244, 114, 182)",
|
||||
blue: isDark ? "rgb(96, 123, 143)": "rgb(96, 123, 143)",
|
||||
darkBlue: isDark ? "rgb(67, 78, 120)" : "rgb(67, 78, 120)",
|
||||
|
||||
// UI colors
|
||||
grid: isDark ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.1)",
|
||||
text: isDark ? "rgba(255, 255, 255, 0.7)" : "rgba(0, 0, 0, 0.7)",
|
||||
}
|
||||
|
||||
159
lib/mock-data.ts
159
lib/mock-data.ts
@ -5,35 +5,35 @@ export function getDashboardData(): DashboardData {
|
||||
metrics: [
|
||||
{
|
||||
id: "1",
|
||||
title: "New Subscriptions",
|
||||
value: "4,682",
|
||||
change: 15.54,
|
||||
title: "Income",
|
||||
value: "45,682",
|
||||
change: -1.54,
|
||||
changeLabel: "from last month",
|
||||
icon: "Users",
|
||||
icon: "DollarSign",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "New Orders",
|
||||
value: "1,226",
|
||||
change: 40.2,
|
||||
title: "Expenditure",
|
||||
value: "34,226",
|
||||
change: 4.2,
|
||||
changeLabel: "from last month",
|
||||
icon: "ShoppingCart",
|
||||
icon: "CreditCard",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Avg Order Revenue",
|
||||
value: "$1,080",
|
||||
change: 10.8,
|
||||
title: "Saving",
|
||||
value: "10,000",
|
||||
change: 0,
|
||||
changeLabel: "from last month",
|
||||
icon: "DollarSign",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Total Revenue",
|
||||
value: "$15,231.89",
|
||||
change: 20.1,
|
||||
title: "Pension",
|
||||
value: "1,500,231",
|
||||
change: 2.1,
|
||||
changeLabel: "from last month",
|
||||
icon: "CreditCard",
|
||||
icon: "DollarSign",
|
||||
},
|
||||
],
|
||||
revenueData: [
|
||||
@ -45,93 +45,150 @@ export function getDashboardData(): DashboardData {
|
||||
{ label: "Jun", value: 5800, secondaryValue: 3100 },
|
||||
],
|
||||
salesData: [
|
||||
{ label: "Jan", value: 1200 },
|
||||
{ label: "Feb", value: 1900 },
|
||||
{ label: "Mar", value: 1600 },
|
||||
{ label: "Apr", value: 2100 },
|
||||
{ label: "May", value: 1800 },
|
||||
{ label: "Jun", value: 2400 },
|
||||
{ label: "Jul", value: 2200 },
|
||||
{ label: "Aug", value: 2600 },
|
||||
{ label: "Sep", value: 2300 },
|
||||
{ label: "Oct", value: 2800 },
|
||||
{ label: "Nov", value: 2500 },
|
||||
{ label: "Dec", value: 3100 },
|
||||
{ label: "Housing", value: 22000 },
|
||||
{ label: "Groceries", value: 13200 },
|
||||
{ label: "Transport", value: 3600 },
|
||||
{ label: "Entertainment", value: 4100 },
|
||||
{ label: "Shopping", value: 5200 },
|
||||
{ label: "Insurance", value: 4900 },
|
||||
{ label: "Other", value: 5800 },
|
||||
],
|
||||
payments: [
|
||||
{
|
||||
id: "1",
|
||||
status: "success",
|
||||
email: "olivia.martin@email.com",
|
||||
category: "groceries",
|
||||
description: "Costco - Groceries & Household",
|
||||
amount: 316.0,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
status: "processing",
|
||||
email: "jackson.lee@email.com",
|
||||
category: "transport",
|
||||
description: "BP Gas Station",
|
||||
amount: 242.0,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
status: "success",
|
||||
email: "isabella.nguyen@email.com",
|
||||
category: "housing",
|
||||
description: "Mortgage Payment - Wells Fargo",
|
||||
amount: 837.0,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
status: "failed",
|
||||
email: "william.kim@email.com",
|
||||
category: "insurance",
|
||||
description: "Insurance Premium - State Farm",
|
||||
amount: 874.0,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
status: "success",
|
||||
email: "sofia.davis@email.com",
|
||||
category: "utilities",
|
||||
description: "Internet Service - Comcast",
|
||||
amount: 721.0,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
status: "processing",
|
||||
email: "alexander.chen@email.com",
|
||||
category: "entertainment",
|
||||
description: "Amazon Prime - Annual Subscription",
|
||||
amount: 456.0,
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
status: "success",
|
||||
email: "emily.wilson@email.com",
|
||||
category: "shopping",
|
||||
description: "Best Buy - Laptop Purchase",
|
||||
amount: 592.0,
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
status: "success",
|
||||
email: "michael.brown@email.com",
|
||||
category: "groceries",
|
||||
description: "Trader Joe's - Groceries",
|
||||
amount: 389.0,
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
status: "failed",
|
||||
email: "sarah.johnson@email.com",
|
||||
category: "transport",
|
||||
description: "Car Repair - AutoZone",
|
||||
amount: 1250.0,
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
status: "success",
|
||||
email: "daniel.garcia@email.com",
|
||||
category: "entertainment",
|
||||
description: "Spotify Premium - Family Plan",
|
||||
amount: 675.0,
|
||||
},
|
||||
{
|
||||
id: "11",
|
||||
status: "processing",
|
||||
email: "jessica.martinez@email.com",
|
||||
category: "transport",
|
||||
description: "Delta Airlines - Flight Tickets",
|
||||
amount: 943.0,
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
status: "success",
|
||||
email: "james.rodriguez@email.com",
|
||||
category: "shopping",
|
||||
description: "Home Depot - Home Improvement",
|
||||
amount: 528.0,
|
||||
},
|
||||
],
|
||||
transactions: [
|
||||
{
|
||||
id: "1",
|
||||
description: "Whole Foods Market - Groceries",
|
||||
amount: 127.43,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
description: "Shell Gas Station",
|
||||
amount: 52.18,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
description: "Netflix Subscription",
|
||||
amount: 15.99,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
description: "Amazon.com - Electronics",
|
||||
amount: 243.67,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
description: "Starbucks Coffee",
|
||||
amount: 6.75,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
description: "Electric Company - Monthly Bill",
|
||||
amount: 89.32,
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
description: "Target - Household Items",
|
||||
amount: 94.21,
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
description: "Uber Ride",
|
||||
amount: 18.50,
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
description: "Restaurant - Dinner",
|
||||
amount: 67.89,
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
description: "Gym Membership",
|
||||
amount: 45.00,
|
||||
},
|
||||
{
|
||||
id: "11",
|
||||
description: "Phone Bill - AT&T",
|
||||
amount: 72.15,
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
description: "Apple Store - App Purchase",
|
||||
amount: 4.99,
|
||||
},
|
||||
],
|
||||
team: [
|
||||
{
|
||||
id: "1",
|
||||
|
||||
@ -9,8 +9,14 @@ export interface MetricCard {
|
||||
|
||||
export interface Payment {
|
||||
id: string
|
||||
status: "success" | "processing" | "failed"
|
||||
email: string
|
||||
category: "groceries" | "utilities" | "transport" | "entertainment" | "shopping" | "insurance" | "housing"
|
||||
description: string
|
||||
amount: number
|
||||
}
|
||||
|
||||
export interface Transaction {
|
||||
id: string
|
||||
description: string
|
||||
amount: number
|
||||
}
|
||||
|
||||
@ -33,5 +39,6 @@ export interface DashboardData {
|
||||
revenueData: ChartDataPoint[]
|
||||
salesData: ChartDataPoint[]
|
||||
payments: Payment[]
|
||||
transactions: Transaction[]
|
||||
team: TeamMember[]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user