feat(V2-6차): 테마 토글 + Mermaid + 오디오 재생 + Dashboard 차트

[A] Dark/Light/6종 + Auto 테마 토글
- theme-mode-context.tsx: localStorage 영속 + prefers-color-scheme
- theme-provider.tsx: 컨텍스트 기반 동적 getTheme
- sidebar.tsx: MUI Select 토글 (PaletteIcon)
- 12개 locale theme.* 키 추가 (label/dark/light/auto/nord/solarized/catppuccin/dracula)

[B] DocumentEditor Mermaid + Markdown 렌더
- markdown-preview.tsx: react-markdown + remark-gfm + lazy mermaid
  - mermaid 코드 블록 자동 SVG 렌더
  - dark theme + d3ro 폰트
- document-editor.tsx: Edit/Preview Tabs

[C] 회의 오디오 재생
- meeting-audio-player.tsx: Supabase Storage signed URL (1h) → <audio controls>
- meetings/[id] AUDIO 카드 추가

[D] Dashboard 14일 추이 차트
- meetings-trend-chart.tsx: recharts LineChart (회의/문서)
- dashboard/page.tsx: 14일 데이터 집계 + 이번 주 stat 자동 계산

[W] fix: Emotion key 'd3ro-mui' → 'mui'
- 'd3ro-mui'에 숫자 3이 포함돼 Emotion 키 검증 실패
- dev SSR /login 500 에러 차단했음

deps:
- react-markdown@10, remark-gfm@4, mermaid@11, recharts@3
This commit is contained in:
윤찬 2026-04-11 08:57:27 +09:00
parent 162a59dc47
commit 07c6d13c99
24 changed files with 2220 additions and 63 deletions

View file

@ -0,0 +1,83 @@
'use client'
// apps/web/src/components/dashboard/meetings-trend-chart.tsx
// recharts 기반 회의/문서 추이 차트 (최근 14일).
import {
ResponsiveContainer,
LineChart,
Line,
XAxis,
YAxis,
Tooltip,
CartesianGrid,
Legend
} from 'recharts'
import { Box } from '@mui/material'
import { d3roPalette } from '@d3ro/ui/theme'
export interface TrendPoint {
date: string
meetings: number
documents: number
}
interface MeetingsTrendChartProps {
points: TrendPoint[]
}
export function MeetingsTrendChart({ points }: MeetingsTrendChartProps): React.ReactElement {
return (
<Box sx={{ width: '100%', height: 260 }}>
<ResponsiveContainer width="100%" height="100%">
<LineChart data={points} margin={{ top: 5, right: 12, left: -12, bottom: 5 }}>
<CartesianGrid strokeDasharray="3 3" stroke={d3roPalette.border.subtle} />
<XAxis
dataKey="date"
stroke={d3roPalette.text.muted}
fontSize={11}
tickLine={false}
/>
<YAxis
stroke={d3roPalette.text.muted}
fontSize={11}
tickLine={false}
allowDecimals={false}
/>
<Tooltip
contentStyle={{
backgroundColor: d3roPalette.bg.elevated,
border: `1px solid ${d3roPalette.border.default}`,
borderRadius: 8,
color: d3roPalette.text.primary,
fontSize: 12
}}
labelStyle={{ color: d3roPalette.text.label }}
/>
<Legend
wrapperStyle={{ fontSize: 11, color: d3roPalette.text.secondary }}
iconType="circle"
/>
<Line
type="monotone"
dataKey="meetings"
name="Meetings"
stroke={d3roPalette.accent.amber}
strokeWidth={2}
dot={{ r: 3 }}
activeDot={{ r: 5 }}
/>
<Line
type="monotone"
dataKey="documents"
name="Documents"
stroke={d3roPalette.tag.purple}
strokeWidth={2}
dot={{ r: 3 }}
activeDot={{ r: 5 }}
/>
</LineChart>
</ResponsiveContainer>
</Box>
)
}