refactor(i18n): 사용자 문구 참조를 중앙화
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import type { FormEvent } from 'react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { copy } from '@/shared/i18n';
|
||||
import { cn } from '@/shared/lib/cn';
|
||||
|
||||
interface GoalCompleteSheetProps {
|
||||
@@ -12,12 +13,7 @@ interface GoalCompleteSheetProps {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const GOAL_SUGGESTIONS = [
|
||||
'리뷰 코멘트 2개 처리',
|
||||
'문서 1문단 다듬기',
|
||||
'이슈 1개 정리',
|
||||
'메일 2개 회신',
|
||||
];
|
||||
const GOAL_SUGGESTIONS = copy.space.goalComplete.suggestions;
|
||||
|
||||
export const GoalCompleteSheet = ({
|
||||
open,
|
||||
@@ -53,10 +49,10 @@ export const GoalCompleteSheet = ({
|
||||
const trimmed = currentGoal.trim();
|
||||
|
||||
if (!trimmed) {
|
||||
return '다음 한 조각을 적어보세요';
|
||||
return copy.space.goalComplete.placeholderFallback;
|
||||
}
|
||||
|
||||
return `예: ${trimmed}`;
|
||||
return copy.space.goalComplete.placeholderExample(trimmed);
|
||||
}, [currentGoal]);
|
||||
|
||||
const canConfirm = draft.trim().length > 0;
|
||||
@@ -82,14 +78,14 @@ export const GoalCompleteSheet = ({
|
||||
<section className="pointer-events-auto w-[min(460px,94vw)] rounded-2xl border border-white/12 bg-black/26 px-3.5 py-3 text-white shadow-[0_14px_30px_rgba(2,6,23,0.28)] backdrop-blur-md">
|
||||
<header className="flex items-start justify-between gap-2">
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-white/92">좋아요. 다음 한 조각은?</h3>
|
||||
<p className="mt-0.5 text-[11px] text-white/58">너무 크게 잡지 말고, 바로 다음 한 조각만.</p>
|
||||
<h3 className="text-sm font-semibold text-white/92">{copy.space.goalComplete.title}</h3>
|
||||
<p className="mt-0.5 text-[11px] text-white/58">{copy.space.goalComplete.description}</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="inline-flex h-6 w-6 items-center justify-center rounded-full border border-white/16 bg-white/[0.05] text-[11px] text-white/72 transition-colors hover:bg-white/[0.12]"
|
||||
aria-label="닫기"
|
||||
aria-label={copy.space.goalComplete.closeAriaLabel}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
@@ -120,17 +116,17 @@ export const GoalCompleteSheet = ({
|
||||
<footer className="mt-3 flex items-center justify-end gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onRest}
|
||||
className="rounded-full border border-white/18 bg-white/[0.05] px-3 py-1.5 text-xs text-white/74 transition-colors hover:bg-white/[0.11]"
|
||||
>
|
||||
잠깐 쉬기
|
||||
</button>
|
||||
onClick={onRest}
|
||||
className="rounded-full border border-white/18 bg-white/[0.05] px-3 py-1.5 text-xs text-white/74 transition-colors hover:bg-white/[0.11]"
|
||||
>
|
||||
{copy.space.goalComplete.restButton}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!canConfirm}
|
||||
className="rounded-full border border-sky-200/42 bg-sky-300/84 px-3.5 py-1.5 text-xs font-semibold text-slate-900 transition-colors hover:bg-sky-300 disabled:cursor-not-allowed disabled:border-white/16 disabled:bg-white/[0.08] disabled:text-white/48"
|
||||
>
|
||||
바로 다음 조각 시작
|
||||
{copy.space.goalComplete.confirmButton}
|
||||
</button>
|
||||
</footer>
|
||||
</form>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { copy } from '@/shared/i18n';
|
||||
import type { HudStatusLinePayload } from '@/shared/lib/useHudStatusLine';
|
||||
import { SpaceTimerHudWidget } from '@/widgets/space-timer-hud';
|
||||
import { GoalCompleteSheet } from './GoalCompleteSheet';
|
||||
@@ -44,7 +45,7 @@ export const SpaceFocusHudWidget = ({
|
||||
const visibleRef = useRef(false);
|
||||
const playbackStateRef = useRef<'running' | 'paused'>(playbackState);
|
||||
const restReminderTimerRef = useRef<number | null>(null);
|
||||
const normalizedGoal = goal.trim().length > 0 ? goal.trim() : '집중을 시작해요.';
|
||||
const normalizedGoal = goal.trim().length > 0 ? goal.trim() : copy.space.focusHud.goalFallback;
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
@@ -58,7 +59,7 @@ export const SpaceFocusHudWidget = ({
|
||||
useEffect(() => {
|
||||
if (visible && !visibleRef.current && playbackState === 'running') {
|
||||
onStatusMessage({
|
||||
message: `이번 한 조각 · ${normalizedGoal}`,
|
||||
message: copy.space.focusHud.goalToast(normalizedGoal),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,7 +69,7 @@ export const SpaceFocusHudWidget = ({
|
||||
useEffect(() => {
|
||||
if (playbackStateRef.current === 'paused' && playbackState === 'running' && visible) {
|
||||
onStatusMessage({
|
||||
message: `이번 한 조각 · ${normalizedGoal}`,
|
||||
message: copy.space.focusHud.goalToast(normalizedGoal),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,7 +116,7 @@ export const SpaceFocusHudWidget = ({
|
||||
}
|
||||
|
||||
restReminderTimerRef.current = window.setTimeout(() => {
|
||||
onStatusMessage({ message: '5분이 지났어요. 다음 한 조각으로 돌아와요.' });
|
||||
onStatusMessage({ message: copy.space.focusHud.restReminder });
|
||||
restReminderTimerRef.current = null;
|
||||
}, 5 * 60 * 1000);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user