ui polish

This commit is contained in:
Pierre Wessman 2025-12-12 12:21:25 +01:00
parent a1c3c2f43c
commit d0826dc15a
8 changed files with 74 additions and 31 deletions

View File

@ -6,8 +6,7 @@
@theme inline { @theme inline {
--color-background: var(--background); --color-background: var(--background);
--color-foreground: var(--foreground); --color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans); --font-sans: var(--font-inter);
--font-mono: var(--font-geist-mono);
--color-sidebar-ring: var(--sidebar-ring); --color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border); --color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);

View File

@ -11,14 +11,15 @@ interface BarChartProps {
datasets: { datasets: {
label: string label: string
data: number[] data: number[]
backgroundColor?: string backgroundColor?: string | string[]
}[] }[]
} }
options?: ChartOptions<"bar"> options?: ChartOptions<"bar">
height?: number height?: number
showGrid?: boolean
} }
export function BarChart({ data, options, height = 300 }: BarChartProps) { export function BarChart({ data, options, height = 300, showGrid = true }: BarChartProps) {
const { theme } = useTheme() const { theme } = useTheme()
const colors = getChartColors(theme) const colors = getChartColors(theme)
@ -27,6 +28,8 @@ export function BarChart({ data, options, height = 300 }: BarChartProps) {
datasets: data.datasets.map((dataset) => ({ datasets: data.datasets.map((dataset) => ({
...dataset, ...dataset,
backgroundColor: dataset.backgroundColor || colors.primary, backgroundColor: dataset.backgroundColor || colors.primary,
borderRadius: 6,
borderSkipped: false,
})), })),
} }
@ -35,16 +38,19 @@ export function BarChart({ data, options, height = 300 }: BarChartProps) {
...options, ...options,
scales: { scales: {
y: { y: {
display: showGrid,
grid: { grid: {
display: showGrid,
color: colors.grid, color: colors.grid,
}, },
ticks: { ticks: {
display: showGrid,
color: colors.text, color: colors.text,
}, },
}, },
x: { x: {
grid: { grid: {
color: colors.grid, display: false,
}, },
ticks: { ticks: {
color: colors.text, color: colors.text,
@ -55,10 +61,7 @@ export function BarChart({ data, options, height = 300 }: BarChartProps) {
...defaultChartOptions.plugins, ...defaultChartOptions.plugins,
...options?.plugins, ...options?.plugins,
legend: { legend: {
...defaultChartOptions.plugins?.legend, display: false,
labels: {
color: colors.text,
},
}, },
}, },
} }

View File

@ -17,9 +17,11 @@ interface LineChartProps {
} }
options?: ChartOptions<"line"> options?: ChartOptions<"line">
height?: number height?: number
showGrid?: boolean
showPoints?: boolean
} }
export function LineChart({ data, options, height = 300 }: LineChartProps) { export function LineChart({ data, options, height = 300, showGrid = true, showPoints = true }: LineChartProps) {
const { theme } = useTheme() const { theme } = useTheme()
const colors = getChartColors(theme) const colors = getChartColors(theme)
@ -31,6 +33,9 @@ export function LineChart({ data, options, height = 300 }: LineChartProps) {
backgroundColor: dataset.backgroundColor || (index === 0 ? `${colors.primary}20` : `${colors.secondary}20`), backgroundColor: dataset.backgroundColor || (index === 0 ? `${colors.primary}20` : `${colors.secondary}20`),
tension: 0.4, tension: 0.4,
fill: true, fill: true,
borderWidth: 2,
pointRadius: showPoints ? 3 : 0,
pointHoverRadius: showPoints ? 5 : 0,
})), })),
} }
@ -39,16 +44,19 @@ export function LineChart({ data, options, height = 300 }: LineChartProps) {
...options, ...options,
scales: { scales: {
y: { y: {
display: showGrid,
grid: { grid: {
display: showGrid,
color: colors.grid, color: colors.grid,
}, },
ticks: { ticks: {
display: showGrid,
color: colors.text, color: colors.text,
}, },
}, },
x: { x: {
grid: { grid: {
color: colors.grid, display: false,
}, },
ticks: { ticks: {
color: colors.text, color: colors.text,
@ -59,10 +67,7 @@ export function LineChart({ data, options, height = 300 }: LineChartProps) {
...defaultChartOptions.plugins, ...defaultChartOptions.plugins,
...options?.plugins, ...options?.plugins,
legend: { legend: {
...defaultChartOptions.plugins?.legend, display: false,
labels: {
color: colors.text,
},
}, },
}, },
} }

View File

@ -1,17 +1,28 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { TrendingUp, TrendingDown } from "lucide-react" import { TrendingUp, TrendingDown, Users, ShoppingCart, DollarSign, CreditCard, LucideIcon } from "lucide-react"
import type { MetricCard as MetricCardType } from "@/types/dashboard" import type { MetricCard as MetricCardType } from "@/types/dashboard"
export function MetricCard({ title, value, change, changeLabel }: MetricCardType) { const iconMap: Record<string, LucideIcon> = {
Users,
ShoppingCart,
DollarSign,
CreditCard,
}
export function MetricCard({ title, value, change, changeLabel, icon }: MetricCardType) {
const isPositive = change >= 0 const isPositive = change >= 0
const Icon = iconMap[icon]
return ( return (
<Card> <Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-0">
<CardTitle className="text-sm font-medium">{title}</CardTitle> <CardTitle className="text-sm font-medium flex items-center gap-2">
{Icon && <Icon className="h-4 w-4 text-muted-foreground" />}
{title}
</CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="text-2xl font-bold">{value}</div> <div className="text-3xl font-bold pb-1">{value}</div>
<div className="flex items-center text-xs text-muted-foreground mt-1"> <div className="flex items-center text-xs text-muted-foreground mt-1">
{isPositive ? ( {isPositive ? (
<TrendingUp className="mr-1 h-4 w-4 text-green-500" /> <TrendingUp className="mr-1 h-4 w-4 text-green-500" />

View File

@ -1,6 +1,6 @@
"use client" "use client"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { LineChart } from "@/components/charts/line-chart" import { LineChart } from "@/components/charts/line-chart"
import type { ChartDataPoint } from "@/types/dashboard" import type { ChartDataPoint } from "@/types/dashboard"
@ -15,21 +15,26 @@ export function RevenueChart({ data }: RevenueChartProps) {
{ {
label: "Revenue", label: "Revenue",
data: data.map((d) => d.value), data: data.map((d) => d.value),
borderColor: "rgb(244, 114, 182)",
backgroundColor: "rgba(244, 114, 182, 0.2)",
}, },
{ {
label: "Subscriptions", label: "Subscriptions",
data: data.map((d) => d.secondaryValue || 0), data: data.map((d) => d.secondaryValue || 0),
borderColor: "rgb(94, 234, 212)",
backgroundColor: "rgba(94, 234, 212, 0.2)",
}, },
], ],
} }
return ( return (
<Card> <Card className="h-[300px] flex flex-col">
<CardHeader> <CardHeader className="flex-shrink-0">
<CardTitle>Revenue Overview</CardTitle> <CardTitle>Revenue Overview</CardTitle>
<CardDescription>Showing total revenue for the last 6 months</CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="flex-1 min-h-0">
<LineChart data={chartData} height={350} /> <LineChart data={chartData} height={180} showGrid={false} showPoints={false} />
</CardContent> </CardContent>
</Card> </Card>
) )

View File

@ -1,6 +1,6 @@
"use client" "use client"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { BarChart } from "@/components/charts/bar-chart" import { BarChart } from "@/components/charts/bar-chart"
import type { ChartDataPoint } from "@/types/dashboard" import type { ChartDataPoint } from "@/types/dashboard"
@ -9,23 +9,38 @@ interface SalesChartProps {
} }
export function SalesChart({ data }: SalesChartProps) { export function SalesChart({ data }: SalesChartProps) {
// Calculate total and change percentage
const total = data.reduce((sum, d) => sum + d.value, 0)
const lastMonthValue = data[data.length - 2]?.value || 0
const currentMonthValue = data[data.length - 1]?.value || 0
const changePercent = lastMonthValue > 0
? (((currentMonthValue - lastMonthValue) / lastMonthValue) * 100).toFixed(1)
: "0.0"
// Alternate colors for bars
const backgroundColors = data.map((_, index) =>
index % 2 === 0 ? "rgb(251, 113, 133)" : "rgb(94, 234, 212)"
)
const chartData = { const chartData = {
labels: data.map((d) => d.label), labels: data.map((d) => d.label),
datasets: [ datasets: [
{ {
label: "Sales", label: "Sales",
data: data.map((d) => d.value), data: data.map((d) => d.value),
backgroundColor: backgroundColors,
}, },
], ],
} }
return ( return (
<Card> <Card className="h-[300px] flex flex-col">
<CardHeader> <CardHeader className="flex-shrink-0">
<CardTitle>Sales Activity</CardTitle> <CardTitle>Subscriptions</CardTitle>
<CardDescription>+{changePercent}% from last month</CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="flex-1 min-h-0">
<BarChart data={chartData} height={350} /> <BarChart data={chartData} height={180} showGrid={false} />
</CardContent> </CardContent>
</Card> </Card>
) )

View File

@ -9,6 +9,7 @@ export function getDashboardData(): DashboardData {
value: "4,682", value: "4,682",
change: 15.54, change: 15.54,
changeLabel: "from last month", changeLabel: "from last month",
icon: "Users",
}, },
{ {
id: "2", id: "2",
@ -16,6 +17,7 @@ export function getDashboardData(): DashboardData {
value: "1,226", value: "1,226",
change: 40.2, change: 40.2,
changeLabel: "from last month", changeLabel: "from last month",
icon: "ShoppingCart",
}, },
{ {
id: "3", id: "3",
@ -23,6 +25,7 @@ export function getDashboardData(): DashboardData {
value: "$1,080", value: "$1,080",
change: 10.8, change: 10.8,
changeLabel: "from last month", changeLabel: "from last month",
icon: "DollarSign",
}, },
{ {
id: "4", id: "4",
@ -30,6 +33,7 @@ export function getDashboardData(): DashboardData {
value: "$15,231.89", value: "$15,231.89",
change: 20.1, change: 20.1,
changeLabel: "from last month", changeLabel: "from last month",
icon: "CreditCard",
}, },
], ],
revenueData: [ revenueData: [

View File

@ -4,6 +4,7 @@ export interface MetricCard {
value: string | number value: string | number
change: number change: number
changeLabel: string changeLabel: string
icon: string
} }
export interface Payment { export interface Payment {