| import Dn from '../Dn' |
| import type { WeeklyActivity } from '../../lib/database.types' |
|
|
| interface Props { |
| data: WeeklyActivity[] |
| |
| metric?: 'cups' | 'co2_kg' |
| } |
|
|
| |
| |
| |
| export default function WeeklyChart({ data, metric = 'cups' }: Props) { |
| const values = data.map((d) => (metric === 'cups' ? d.cups : d.co2_kg)) |
| const realMax = Math.max(...values, 0) |
| const max = realMax > 0 ? realMax : 1 |
|
|
| return ( |
| <div className="border border-border-default bg-paper-white divide-y divide-border-default rounded-lg overflow-hidden shadow-sm"> |
| {data.map((row) => { |
| const value = metric === 'cups' ? row.cups : row.co2_kg |
| const pct = (value / max) * 100 |
| const isZero = value === 0 |
| return ( |
| <div key={row.week_start} className="px-3 py-2 flex items-center gap-3"> |
| {/* Week label */} |
| <div className="w-16 flex-shrink-0"> |
| <p className="text-[10px] text-ink-medium font-mono"> |
| {formatWeekLabel(row.week_start)} |
| </p> |
| </div> |
| |
| {/* Bar track — borderless dash for zero, framed track for values */} |
| <div className="flex-1 h-5 relative flex items-center"> |
| {isZero ? ( |
| <div className="w-full border-t border-dashed border-border-default" /> |
| ) : ( |
| <> |
| <div className="absolute inset-0 border border-border-default bg-paper-cream rounded-sm" /> |
| <div |
| className="absolute inset-y-0 left-0 bg-accent-teal rounded-sm" |
| style={{ width: `${pct}%` }} |
| /> |
| </> |
| )} |
| </div> |
| |
| {/* Value */} |
| <div className="w-16 flex-shrink-0 text-right"> |
| <p className={`text-xs font-bold tabular-nums ${isZero ? 'text-ink-light' : 'text-ink-black'}`}> |
| {metric === 'cups' ? value : <Dn>{value.toFixed(2)}</Dn>} |
| </p> |
| {row.active_citizens > 0 && ( |
| <p className="text-[9px] text-ink-light"> |
| 시민 {row.active_citizens} |
| </p> |
| )} |
| </div> |
| </div> |
| ) |
| })} |
| </div> |
| ) |
| } |
|
|
| |
| function formatWeekLabel(iso: string): string { |
| const [, m, d] = iso.split('-') |
| return `${m}/${d}` |
| } |
|
|