refactor: FSD 구조 강화 및 파일 500줄 제한에 따른 대규모 리팩토링

- SpaceWorkspaceWidget 로직을 전용 훅 및 유틸리티로 분리 (900줄 -> 300줄)
- useSpaceWorkspaceSelection 훅을 기능별(영속성, 진단 등) 소형 훅으로 분리
- SpaceToolsDockWidget의 상태 및 핸들러 로직 추출
- 거대 i18n 번역 파일(ko.ts)을 도메인별 메시지 파일로 구조화
- AdminConsoleWidget 누락분 추가 및 미디어 엔티티 타입 오류 수정
This commit is contained in:
2026-03-11 15:08:36 +09:00
parent 7867bd39ca
commit 35f1dfb92d
36 changed files with 3238 additions and 2611 deletions

View File

@@ -0,0 +1,241 @@
export const app = {
settings: {
title: 'Settings',
focusPreferencesApi: 'Focus Preferences API',
loading: '저장된 설정을 불러오는 중이에요.',
saving: '변경 사항을 저장하는 중이에요.',
synced: '변경 즉시 서버에 저장합니다.',
reduceMotionTitle: 'Reduce Motion',
reduceMotionDescription: '전환 애니메이션을 최소화합니다. (UI 토글 목업)',
notificationIntensityTitle: '알림 강도',
notificationIntensityDescription: '집중 시작/종료 신호의 존재감을 선택합니다.',
defaultPresetTitle: '기본 프리셋',
defaultPresetDescription: '입장 시 자동 선택될 추천 세트를 고릅니다.',
notificationIntensityOptions: ['조용함', '기본', '강함'],
defaultPresetOptions: [
{ id: 'balanced', label: 'Balanced 25/5 + Rain Focus' },
{ id: 'deep-work', label: 'Deep Work 50/10 + Deep White' },
{ id: 'gentle', label: 'Gentle 25/5 + Silent' },
],
},
stats: {
title: 'Stats',
apiLabel: 'API',
mockLabel: 'Mock',
sourceApi: 'API 통계 사용 중',
sourceMock: 'API 실패로 mock 통계 표시 중',
loading: '통계를 불러오는 중이에요.',
loadFailed: '통계를 불러오지 못했어요.',
synced: '화면 진입 시 최신 요약을 동기화합니다.',
refresh: '새로고침',
today: '오늘',
last7Days: '최근 7일',
chartTitle: '집중 흐름 그래프',
chartWithTrend: 'trend 응답으로 간단한 막대 그래프를 렌더링합니다.',
chartWithoutTrend: 'trend 응답이 비어 있어 플레이스홀더 상태입니다.',
todayFocus: '오늘 집중 시간',
completedCycles: '완료한 사이클',
sessionEntries: '입장 횟수',
last7DaysFocus: '최근 7일 집중 시간',
bestDay: '최고 몰입일',
streak: '연속 달성',
syncedApi: '동기화됨',
temporary: '임시값',
actualAggregate: '실집계',
mockAggregate: '목업',
streakActive: '유지 중',
streakStart: '시작 전',
countUnit: '회',
dayUnit: '일',
minuteUnit: '분',
barTitle: (date: string, minutes: number) => `${date} · ${minutes}`,
},
plan: {
proFeatureCards: [
{
id: 'scene-packs',
name: 'Scene Packs',
description: '프리미엄 공간 묶음과 장면 변주',
},
{
id: 'sound-packs',
name: 'Sound Packs',
description: '확장 사운드 프리셋 묶음',
},
{
id: 'profiles',
name: 'Profiles',
description: '내 기본 세팅 저장/불러오기',
},
],
},
session: {
todayOneLiner: '오늘의 한 줄: 완벽보다 시작, 한 조각이면 충분해요.',
goalChips: [
{ id: 'mail-3', label: '메일 3개' },
{ id: 'doc-1p', label: '문서 1p' },
{ id: 'code-1-function', label: '코딩 1함수' },
{ id: 'tidy-10m', label: '정리 10분' },
{ id: 'reading-15m', label: '독서 15분' },
{ id: 'resume-1paragraph', label: '이력서 1문단' },
],
checkInPhrases: [
{ id: 'arrived', text: '지금 들어왔어요' },
{ id: 'sprint-25', text: '25분만 달릴게요' },
{ id: 'on-break', text: '휴식 중' },
{ id: 'back-focus', text: '다시 집중!' },
{ id: 'slow-day', text: '오늘은 천천히' },
],
reactionOptions: [
{ id: 'thumbs-up', emoji: '👍', label: '응원해요' },
{ id: 'fire', emoji: '🔥', label: '집중 모드' },
{ id: 'clap', emoji: '👏', label: '잘하고 있어요' },
{ id: 'heart-hands', emoji: '🫶', label: '연결되어 있어요' },
],
soundPresets: [
{ id: 'deep-white', label: 'Deep White' },
{ id: 'rain-focus', label: 'Rain Focus' },
{ id: 'forest-birds', label: 'Forest Birds' },
{ id: 'cafe-work', label: 'Cafe Work' },
{ id: 'ocean-calm', label: 'Ocean Calm' },
{ id: 'fireplace', label: 'Fireplace' },
{ id: 'silent', label: 'Silent' },
],
timerPresets: [
{ id: '25-5', label: '25/5', focusMinutes: 25, breakMinutes: 5 },
{ id: '50-10', label: '50/10', focusMinutes: 50, breakMinutes: 10 },
{ id: '90-20', label: '90/20', focusMinutes: 90, breakMinutes: 20 },
{ id: 'custom', label: '커스텀' },
],
distractionDumpPlaceholder: ['디자인 QA 요청 확인', '세금계산서 발행 메모', '오후 미팅 질문 1개 정리'],
todayStats: [
{ id: 'today-focus', label: '오늘 집중 시간', value: '2h 40m', delta: '+35m' },
{ id: 'today-cycles', label: '완료한 사이클', value: '5회', delta: '+1' },
{ id: 'today-entry', label: '입장 횟수', value: '3회', delta: '유지' },
],
weeklyStats: [
{ id: 'week-focus', label: '최근 7일 집중 시간', value: '14h 20m', delta: '+2h 10m' },
{ id: 'week-best-day', label: '최고 몰입일', value: '수요일', delta: '3h 30m' },
{ id: 'week-consistency', label: '연속 달성', value: '4일', delta: '+1일' },
],
recentThoughts: [
{
id: 'thought-1',
text: '내일 미팅 전에 제안서 첫 문단만 다시 다듬기',
sceneName: '도서관',
capturedAt: '방금 전',
},
{
id: 'thought-2',
text: '기획 문서의 핵심 흐름을 한 문장으로 정리해두기',
sceneName: '비 오는 창가',
capturedAt: '24분 전',
},
{
id: 'thought-3',
text: '오후에 확인할 이슈 번호만 메모하고 지금 작업 복귀',
sceneName: '숲',
capturedAt: '1시간 전',
},
{
id: 'thought-4',
text: '리뷰 코멘트는 오늘 17시 이후에 한 번에 처리',
sceneName: '벽난로',
capturedAt: '어제',
},
],
justNow: '방금 전',
},
scenes: [
{
id: 'rain-window',
name: '비 오는 창가',
description: '빗소리 위로 스탠드 조명이 부드럽게 번집니다.',
tags: ['저자극', '감성'],
recommendedSound: 'Rain Focus',
recommendedTime: '밤',
vibeLabel: '잔잔함',
},
{
id: 'dawn-cafe',
name: '새벽 카페',
description: '첫 커피 향처럼 잔잔하고 따뜻한 좌석.',
tags: ['감성', '딥워크'],
recommendedSound: 'Cafe Murmur',
recommendedTime: '새벽',
vibeLabel: '포근함',
},
{
id: 'quiet-library',
name: '도서관',
description: '넘기는 종이 소리만 들리는 정돈된 책상.',
tags: ['저자극', '딥워크'],
recommendedSound: 'Deep White',
recommendedTime: '오후',
vibeLabel: '몰입',
},
{
id: 'wave-sound',
name: '파도 소리',
description: '잔잔한 해변 위로 호흡을 고르는 공간.',
tags: ['움직임 적음', '감성'],
recommendedSound: 'Ocean Breath',
recommendedTime: '밤',
vibeLabel: '차분함',
},
{
id: 'forest',
name: '숲',
description: '바람이 나뭇잎을 스치는 소리로 마음을 낮춥니다.',
tags: ['저자극', '움직임 적음'],
recommendedSound: 'Forest Birds',
recommendedTime: '오전',
vibeLabel: '맑음',
},
{
id: 'fireplace',
name: '벽난로',
description: '작은 불꽃이 주는 리듬으로 집중을 붙잡습니다.',
tags: ['감성', '저자극'],
recommendedSound: 'Fireplace',
recommendedTime: '밤',
vibeLabel: '온기',
},
{
id: 'city-night',
name: '도시 야경',
description: '유리창 너머 야경이 멀리 흐르는 고요한 밤.',
tags: ['딥워크', '감성'],
recommendedSound: 'Night Lo-fi',
recommendedTime: '심야',
vibeLabel: '고요함',
},
{
id: 'snow-mountain',
name: '설산',
description: '차분한 공기와 선명한 수평선이 머리를 맑게 합니다.',
tags: ['움직임 적음', '딥워크'],
recommendedSound: 'Cold Wind',
recommendedTime: '새벽',
vibeLabel: '선명함',
},
{
id: 'sun-window',
name: '창가',
description: '햇살이 들어오는 간결한 책상, 부담 없는 시작.',
tags: ['저자극', '딥워크'],
recommendedSound: 'Soft Daylight',
recommendedTime: '오후',
vibeLabel: '가벼움',
},
{
id: 'outer-space',
name: '우주',
description: '별빛만 남긴 어둠 속에서 깊게 잠수합니다.',
tags: ['딥워크', '감성'],
recommendedSound: 'Deep Drone',
recommendedTime: '심야',
vibeLabel: '깊음',
},
],
} as const;