diff --git a/src/entities/user/index.ts b/src/entities/user/index.ts deleted file mode 100644 index 5d4d104..0000000 --- a/src/entities/user/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './model/mockUser'; -export * from './model/types'; -export * from './ui/MembershipTierBadge'; diff --git a/src/entities/user/model/mockUser.ts b/src/entities/user/model/mockUser.ts deleted file mode 100644 index 10b0b52..0000000 --- a/src/entities/user/model/mockUser.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { ViewerProfile } from './types'; - -export const MOCK_VIEWER: ViewerProfile = { - id: 'viewer-1', - name: '민서', - avatarLabel: 'MS', - membershipTier: 'pro', -}; diff --git a/src/entities/user/model/types.ts b/src/entities/user/model/types.ts deleted file mode 100644 index f8c314f..0000000 --- a/src/entities/user/model/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type MembershipTier = 'pro' | 'normal' | 'team'; - -export interface ViewerProfile { - id: string; - name: string; - avatarLabel: string; - membershipTier: MembershipTier; -} diff --git a/src/entities/user/ui/MembershipTierBadge.tsx b/src/entities/user/ui/MembershipTierBadge.tsx deleted file mode 100644 index e6b4564..0000000 --- a/src/entities/user/ui/MembershipTierBadge.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import type { MembershipTier } from '@/entities/user/model/types'; - -interface MembershipTierBadgeProps { - tier: MembershipTier; -} - -const TIER_META: Record< - MembershipTier, - { - label: string; - mobileLabel: string; - surfaceClass: string; - dotClass: string; - } -> = { - pro: { - label: 'PRO MEMBER', - mobileLabel: 'PRO', - surfaceClass: - 'border-[#af8b4c]/44 bg-[linear-gradient(138deg,rgba(255,251,240,0.98)_0%,rgba(248,235,206,0.92)_58%,rgba(236,214,166,0.9)_100%)] text-[#6e5326] ring-1 ring-white/56 shadow-[inset_0_1px_0_rgba(255,255,255,0.66),0_10px_22px_rgba(120,82,20,0.14)]', - dotClass: 'bg-[#8f6a2c]/72', - }, - normal: { - label: 'NORMAL', - mobileLabel: 'NORMAL', - surfaceClass: - 'border-slate-600/22 bg-[linear-gradient(135deg,rgba(255,255,255,0.94)_0%,rgba(241,245,249,0.86)_100%)] text-slate-700/84 ring-1 ring-white/50 shadow-[inset_0_1px_0_rgba(255,255,255,0.58),0_8px_18px_rgba(15,23,42,0.09)]', - dotClass: 'bg-slate-600/46', - }, - team: { - label: 'TEAM', - mobileLabel: 'TEAM', - surfaceClass: - 'border-teal-900/28 bg-[linear-gradient(140deg,rgba(236,253,250,0.95)_0%,rgba(204,251,241,0.82)_58%,rgba(186,230,253,0.76)_100%)] text-teal-900/84 ring-1 ring-white/52 shadow-[inset_0_1px_0_rgba(255,255,255,0.6),0_9px_18px_rgba(8,78,99,0.12)]', - dotClass: 'bg-teal-900/54', - }, -}; - -export const MembershipTierBadge = ({ tier }: MembershipTierBadgeProps) => { - const tierMeta = TIER_META[tier]; - - return ( - - - {tierMeta.mobileLabel} - {tierMeta.label} - - ); -}; diff --git a/src/features/check-in/index.ts b/src/features/check-in/index.ts deleted file mode 100644 index fcd1531..0000000 --- a/src/features/check-in/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './model/useCheckIn'; -export * from './ui/CompactCheckInChips'; -export * from './ui/CheckInChips'; diff --git a/src/features/check-in/model/useCheckIn.ts b/src/features/check-in/model/useCheckIn.ts deleted file mode 100644 index 0b92523..0000000 --- a/src/features/check-in/model/useCheckIn.ts +++ /dev/null @@ -1,16 +0,0 @@ -'use client'; - -import { useState } from 'react'; - -export const useCheckIn = () => { - const [lastCheckIn, setLastCheckIn] = useState(null); - - const recordCheckIn = (message: string) => { - setLastCheckIn(message); - }; - - return { - lastCheckIn, - recordCheckIn, - }; -}; diff --git a/src/features/check-in/ui/CheckInChips.tsx b/src/features/check-in/ui/CheckInChips.tsx deleted file mode 100644 index 3d5a3cb..0000000 --- a/src/features/check-in/ui/CheckInChips.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type { CheckInPhrase } from '@/entities/session'; -import { Chip } from '@/shared/ui'; - -interface CheckInChipsProps { - phrases: CheckInPhrase[]; - lastCheckIn: string | null; - onCheckIn: (message: string) => void; -} - -export const CheckInChips = ({ - phrases, - lastCheckIn, - onCheckIn, -}: CheckInChipsProps) => { - return ( -
-
- {phrases.map((phrase) => ( - onCheckIn(phrase.text)}> - {phrase.text} - - ))} -
-

- 마지막 체크인:{' '} - - {lastCheckIn ?? '아직 남기지 않았어요'} - -

-
- ); -}; diff --git a/src/features/check-in/ui/CompactCheckInChips.tsx b/src/features/check-in/ui/CompactCheckInChips.tsx deleted file mode 100644 index 44d03ed..0000000 --- a/src/features/check-in/ui/CompactCheckInChips.tsx +++ /dev/null @@ -1,53 +0,0 @@ -'use client'; - -import { useMemo, useState } from 'react'; -import type { CheckInPhrase } from '@/entities/session'; -import { Chip } from '@/shared/ui'; - -interface CompactCheckInChipsProps { - phrases: CheckInPhrase[]; - onCheckIn: (message: string) => void; - collapsedCount?: number; -} - -export const CompactCheckInChips = ({ - phrases, - onCheckIn, - collapsedCount = 3, -}: CompactCheckInChipsProps) => { - const [showAll, setShowAll] = useState(false); - - const visiblePhrases = useMemo(() => { - if (showAll) { - return phrases; - } - - return phrases.slice(0, collapsedCount); - }, [collapsedCount, phrases, showAll]); - - return ( -
-
- {visiblePhrases.map((phrase) => ( - onCheckIn(phrase.text)} - className="!px-2.5 !py-1 text-[11px]" - > - {phrase.text} - - ))} -
- - {phrases.length > collapsedCount ? ( - - ) : null} -
- ); -}; diff --git a/src/features/custom-entry-modal/index.ts b/src/features/custom-entry-modal/index.ts deleted file mode 100644 index f38b7fd..0000000 --- a/src/features/custom-entry-modal/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './model/useCustomEntryForm'; -export * from './ui/CustomEntryModal'; diff --git a/src/features/custom-entry-modal/model/useCustomEntryForm.ts b/src/features/custom-entry-modal/model/useCustomEntryForm.ts deleted file mode 100644 index c176b32..0000000 --- a/src/features/custom-entry-modal/model/useCustomEntryForm.ts +++ /dev/null @@ -1,70 +0,0 @@ -'use client'; - -import { useMemo, useState } from 'react'; -import { SOUND_PRESETS, TIMER_PRESETS } from '@/entities/session'; - -export type CustomEntryTab = 'theme' | 'sound' | 'timer'; - -export interface CustomEntrySelection { - soundId: string; - timerId: string; - timerLabel: string; -} - -const getSafeNumber = (value: string, fallback: number) => { - const parsed = Number(value); - - if (!Number.isFinite(parsed) || parsed <= 0) { - return fallback; - } - - return Math.round(parsed); -}; - -export const useCustomEntryForm = () => { - const [activeTab, setActiveTab] = useState('theme'); - const [selectedSoundId, setSelectedSoundId] = useState(SOUND_PRESETS[0].id); - const [selectedTimerId, setSelectedTimerId] = useState(TIMER_PRESETS[0].id); - const [customFocusMinutes, setCustomFocusMinutes] = useState('40'); - const [customBreakMinutes, setCustomBreakMinutes] = useState('10'); - - const timerLabel = useMemo(() => { - if (selectedTimerId !== 'custom') { - return TIMER_PRESETS.find((preset) => preset.id === selectedTimerId)?.label ?? - TIMER_PRESETS[0].label; - } - - const focus = getSafeNumber(customFocusMinutes, 25); - const breakMinutes = getSafeNumber(customBreakMinutes, 5); - - return `${focus}/${breakMinutes}`; - }, [customBreakMinutes, customFocusMinutes, selectedTimerId]); - - const buildSelection = (): CustomEntrySelection => { - return { - soundId: selectedSoundId, - timerId: selectedTimerId, - timerLabel, - }; - }; - - const resetTab = () => { - setActiveTab('theme'); - }; - - return { - activeTab, - selectedSoundId, - selectedTimerId, - customFocusMinutes, - customBreakMinutes, - timerLabel, - setActiveTab, - setSelectedSoundId, - setSelectedTimerId, - setCustomFocusMinutes, - setCustomBreakMinutes, - buildSelection, - resetTab, - }; -}; diff --git a/src/features/custom-entry-modal/ui/CustomEntryModal.tsx b/src/features/custom-entry-modal/ui/CustomEntryModal.tsx deleted file mode 100644 index dfeba61..0000000 --- a/src/features/custom-entry-modal/ui/CustomEntryModal.tsx +++ /dev/null @@ -1,183 +0,0 @@ -'use client'; - -import { ROOM_THEMES } from '@/entities/room'; -import { SOUND_PRESETS, TIMER_PRESETS } from '@/entities/session'; -import { Button, Modal, Tabs } from '@/shared/ui'; -import { cn } from '@/shared/lib/cn'; -import { - type CustomEntrySelection, - useCustomEntryForm, -} from '../model/useCustomEntryForm'; - -interface CustomEntryModalProps { - isOpen: boolean; - selectedRoomId: string; - onSelectRoom: (roomId: string) => void; - onClose: () => void; - onEnter: (selection: CustomEntrySelection) => void; -} - -export const CustomEntryModal = ({ - isOpen, - selectedRoomId, - onSelectRoom, - onClose, - onEnter, -}: CustomEntryModalProps) => { - const { - activeTab, - selectedSoundId, - selectedTimerId, - customFocusMinutes, - customBreakMinutes, - setActiveTab, - setSelectedSoundId, - setSelectedTimerId, - setCustomFocusMinutes, - setCustomBreakMinutes, - buildSelection, - resetTab, - } = useCustomEntryForm(); - - const tabOptions = [ - { value: 'theme', label: '공간' }, - { value: 'sound', label: '사운드 프리셋' }, - { value: 'timer', label: '타이머 프리셋' }, - ]; - - const handleClose = () => { - resetTab(); - onClose(); - }; - - const handleEnter = () => { - onEnter(buildSelection()); - resetTab(); - }; - - return ( - - - - - } - > -
- setActiveTab(value as 'theme' | 'sound' | 'timer')} /> - -
- {activeTab === 'theme' ? ( -
-
- {ROOM_THEMES.map((room) => ( - - ))} -
-
- ) : null} - - {activeTab === 'sound' ? ( -
-
- {SOUND_PRESETS.map((preset) => ( - - ))} -
-
- ) : null} - - {activeTab === 'timer' ? ( -
-
-
- {TIMER_PRESETS.map((preset) => ( - - ))} -
- - {selectedTimerId === 'custom' ? ( -
- - - -
- ) : null} -
-
- ) : null} -
-
-
- ); -}; diff --git a/src/features/distraction-dump/index.ts b/src/features/distraction-dump/index.ts deleted file mode 100644 index 34925d0..0000000 --- a/src/features/distraction-dump/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './model/useDistractionDump'; -export * from './model/useDistractionNotes'; -export * from './ui/DistractionDumpNotesContent'; -export * from './ui/DistractionDumpPanel'; diff --git a/src/features/distraction-dump/model/useDistractionDump.ts b/src/features/distraction-dump/model/useDistractionDump.ts deleted file mode 100644 index 3d4bda6..0000000 --- a/src/features/distraction-dump/model/useDistractionDump.ts +++ /dev/null @@ -1,38 +0,0 @@ -'use client'; - -import { useMemo, useState } from 'react'; -import { DISTRACTION_DUMP_PLACEHOLDER } from '@/entities/session'; - -export const useDistractionDump = () => { - const [isOpen, setIsOpen] = useState(false); - const [draft, setDraft] = useState(''); - const [items, setItems] = useState(DISTRACTION_DUMP_PLACEHOLDER); - - const hasDraft = useMemo(() => draft.trim().length > 0, [draft]); - - const toggle = () => { - setIsOpen((current) => !current); - }; - - const saveDraft = () => { - if (!hasDraft) { - return null; - } - - const value = draft.trim(); - setItems((current) => [value, ...current]); - setDraft(''); - - return value; - }; - - return { - isOpen, - draft, - items, - hasDraft, - setDraft, - toggle, - saveDraft, - }; -}; diff --git a/src/features/distraction-dump/model/useDistractionNotes.ts b/src/features/distraction-dump/model/useDistractionNotes.ts deleted file mode 100644 index 98e1eab..0000000 --- a/src/features/distraction-dump/model/useDistractionNotes.ts +++ /dev/null @@ -1,68 +0,0 @@ -'use client'; - -import { useMemo, useState } from 'react'; -import { DISTRACTION_DUMP_PLACEHOLDER } from '@/entities/session'; - -interface DistractionNote { - id: string; - text: string; - done: boolean; -} - -const createInitialNotes = (): DistractionNote[] => { - return DISTRACTION_DUMP_PLACEHOLDER.slice(0, 5).map((text, index) => ({ - id: `note-${index + 1}`, - text, - done: false, - })); -}; - -export const useDistractionNotes = () => { - const [draft, setDraft] = useState(''); - const [notes, setNotes] = useState(createInitialNotes); - - const canAdd = useMemo(() => draft.trim().length > 0, [draft]); - - const addNote = () => { - if (!canAdd) { - return null; - } - - const value = draft.trim(); - - setNotes((current) => [ - { - id: `note-${Date.now()}`, - text: value, - done: false, - }, - ...current, - ]); - - setDraft(''); - - return value; - }; - - const toggleDone = (noteId: string) => { - setNotes((current) => - current.map((note) => - note.id === noteId ? { ...note, done: !note.done } : note, - ), - ); - }; - - const removeNote = (noteId: string) => { - setNotes((current) => current.filter((note) => note.id !== noteId)); - }; - - return { - draft, - notes, - canAdd, - setDraft, - addNote, - toggleDone, - removeNote, - }; -}; diff --git a/src/features/distraction-dump/ui/DistractionDumpNotesContent.tsx b/src/features/distraction-dump/ui/DistractionDumpNotesContent.tsx deleted file mode 100644 index 315bc47..0000000 --- a/src/features/distraction-dump/ui/DistractionDumpNotesContent.tsx +++ /dev/null @@ -1,90 +0,0 @@ -'use client'; - -import { Button } from '@/shared/ui'; -import { cn } from '@/shared/lib/cn'; -import { useDistractionNotes } from '../model/useDistractionNotes'; - -interface DistractionDumpNotesContentProps { - onNoteAdded?: (note: string) => void; - onNoteRemoved?: () => void; -} - -export const DistractionDumpNotesContent = ({ - onNoteAdded, - onNoteRemoved, -}: DistractionDumpNotesContentProps) => { - const { draft, notes, canAdd, setDraft, addNote, toggleDone, removeNote } = - useDistractionNotes(); - - const handleAdd = () => { - const note = addNote(); - - if (note && onNoteAdded) { - onNoteAdded(note); - } - }; - - const handleRemove = (noteId: string) => { - removeNote(noteId); - - if (onNoteRemoved) { - onNoteRemoved(); - } - }; - - return ( -
-
-