feat(V2-3): Web App MVP — Next.js 15 + @d3ro/api-client

packages/api-client (@d3ro/api-client) 신규:
- types.ts: 12개 테이블 Row/Insert/Update 타입 + Database 형식
- client.ts: createD3roSupabaseClient 팩토리 (placeholder fallback)
- auth.ts: signInWithOAuth/signOut/getSession/onAuthStateChange
- meetings.ts: 회의 + 메모 + 문서 + 전사 CRUD
- history.ts: 음성 입력 이력 CRUD
- usage.ts: 일일 쿼터 + 구독 조회
- 루트 barrel은 types만 re-export, 함수는 subpath import 전용

apps/web (@d3ro/web) 신규 — Next.js 15 App Router:
- transpilePackages: @d3ro/core, ui, i18n, api-client
- ThemeProvider (MUI + AppRouterCacheProvider)
- I18nProvider (localStorage 어댑터)
- AuthProvider (Supabase session Context)
- 라우트 9개:
  - / (auth 상태 기반 리다이렉트)
  - /login (Google/GitHub OAuth, 미설정 경고)
  - /auth/callback (code -> session 교환)
  - /dashboard (요약 카드 + 최근 회의)
  - /meetings (카드 그리드 리스트)
  - /meetings/[id] (transcripts/memos/documents)
  - /record (getUserMedia + MediaRecorder + stt-proxy)
- Sidebar, 인증 가드, 9바 웨이브폼, 레벨 미터

packages/ui 확장:
- MetalCard가 BoxProps 상속 (sx/onClick 등 전달)
- theme.ts에 typoSx(key) 헬퍼 추가 (d3roTypo -> MUI sx 변환)
- d3roPalette.tag.blue 추가 (M5 정리 포함)
- DS 컴포넌트 9개에 'use client' directive
- MetalDial 미사용 import 제거

packages/i18n 확장:
- ko.json에 7개 새 키 (nav.meetings/record/logout, login.*)

설계 결정:
- Database 제네릭 현재는 기본 타입 (V2-4에서 supabase gen types로 자동화)
- api-client barrel은 타입만 노출해서 컴파일 전파 차단
- DS 컴포넌트 client 경계 명시
- env 없어도 Next.js 빌드 성공 (placeholder URL/key)

검증:
- web typecheck OK
- desktop typecheck OK (회귀 없음)
- web next build OK (9 라우트 정적/동적 생성)
- desktop build OK (회귀 없음)
This commit is contained in:
yunchan8804 2026-04-09 02:52:31 +09:00
parent 9742b2109a
commit d0c33ca259
190 changed files with 6167 additions and 18 deletions

View file

@ -1,3 +1,5 @@
'use client'
// src/renderer/components/ds/ButtonGroup.tsx
// 시안 A: 인셋 버튼 클러스터 — 레퍼런스의 .button-group 패턴
// 물리 버튼들을 인셋 패널 안에 배치하여 그룹화

View file

@ -1,3 +1,5 @@
'use client'
// src/renderer/components/ds/CrtDisplay.tsx
// 시안 A: CRT 디스플레이 — WebGL 셰이더 (스캔라인, 비네팅, 노이즈, 글리치, 파형)

View file

@ -1,3 +1,5 @@
'use client'
// src/renderer/components/ds/InstrumentPanel.tsx
// 시안 A: 메탈 섀시 컨테이너 — 노이즈 텍스처, 각인 텍스트, 물리적 존재감

View file

@ -1,3 +1,5 @@
'use client'
// src/renderer/components/ds/Led.tsx
// 시안 A: LED 인디케이터 — 물리적 LED, 활성 시 glow + pulse

View file

@ -1,18 +1,25 @@
// src/renderer/components/ds/MetalCard.tsx
'use client'
// packages/ui/src/components/ds/MetalCard.tsx
// 시안 A+B 융합: 메탈 카드 컨테이너 — 섀시 느낌의 인셋 패널
// 토큰 적용: d3roShadow, d3roRadius
import { Box } from '@mui/material'
import { Box, type BoxProps } from '@mui/material'
import { d3roPalette, d3roShadow, d3roRadius } from '../../theme'
interface MetalCardProps {
children: React.ReactNode
interface MetalCardProps extends Omit<BoxProps, 'component'> {
inset?: boolean
}
export function MetalCard({ children, inset = false }: MetalCardProps): React.ReactElement {
export function MetalCard({
children,
inset = false,
sx,
...boxProps
}: MetalCardProps): React.ReactElement {
return (
<Box
{...boxProps}
sx={{
bgcolor: inset ? d3roPalette.bg.inset : d3roPalette.bg.card,
borderRadius: inset ? d3roRadius.inner : d3roRadius.card,
@ -22,6 +29,7 @@ export function MetalCard({ children, inset = false }: MetalCardProps): React.Re
overflow: 'hidden',
transition: 'background-color 0.2s ease',
'&:hover': inset ? {} : { bgcolor: d3roPalette.bg.cardHover },
...sx,
}}
>
{children}

View file

@ -1,9 +1,11 @@
'use client'
// src/renderer/components/ds/MetalDial.tsx
// 시안 A: 메탈 다이얼 — 정밀기기 회전 노브, 동심원 그루브, 금속 광택, LED 인디케이터
// 보강: 레퍼런스의 conic-gradient 정적 라이팅 + 방향성 그림자 추가
import { Box } from '@mui/material'
import { d3roPalette, d3roFontMono, d3roTypo, d3roShadow } from '../../theme'
import { d3roPalette } from '../../theme'
import { PhosphorText } from './PhosphorText'
interface MetalDialProps {

View file

@ -1,3 +1,5 @@
'use client'
// src/renderer/components/ds/PhosphorText.tsx
// 시안 A: 인광 텍스트 — 앰버 glow, 모노 폰트, CRT 느낌
// 확장: title/stat/body/compact/meta/engrave/micro/nano 변형 추가

View file

@ -1,3 +1,5 @@
'use client'
// src/renderer/components/ds/PhysicalButton.tsx
// 시안 A: 물리 버튼 — 돌출 그림자, 눌림 피드백, 선택 상태
// 토큰 적용: d3roShadow, d3roRadius, d3roTypo

View file

@ -1,3 +1,5 @@
'use client'
// src/renderer/components/ds/ScreenPanel.tsx
// 시안 A: CRT 없는 순수 스크린 패널 — 인셋 베젤 + 글래스 반사 + 인광 텍스트용
// 레퍼런스의 .display-module > .screen-glass 패턴

View file

@ -263,6 +263,25 @@ export const d3roTypo = {
nano: { size: '7px', weight: 700, spacing: '0.5px', line: 1 },
} as const
/**
* d3roTypo의 `{ size, weight, spacing, line }` MUI `sx`
* `{ fontSize, fontWeight, letterSpacing, lineHeight }` .
*/
export function typoSx(key: keyof typeof d3roTypo): {
fontSize: string
fontWeight: number
letterSpacing: string
lineHeight: number
} {
const v = d3roTypo[key]
return {
fontSize: v.size,
fontWeight: v.weight,
letterSpacing: v.spacing,
lineHeight: v.line
}
}
// ── SSOT: 그림자 토큰 (CSS Custom Properties 기반, 테마 자동 전환) ───
export const d3roShadow = {
chassis: 'var(--d3-shadow-chassis)',