import { create } from "zustand"; import { persist } from "zustand/middleware"; /** * [UI 상태 인터페이스] */ interface UIState { // ========== 테마 ========== theme: "light" | "dark" | "system"; setTheme: (theme: "light" | "dark" | "system") => void; // ========== 사이드바 ========== isSidebarOpen: boolean; toggleSidebar: () => void; setSidebarOpen: (isOpen: boolean) => void; // ========== 모달 ========== isModalOpen: boolean; modalContent: React.ReactNode | null; openModal: (content: React.ReactNode) => void; closeModal: () => void; // ========== 토스트/알림 ========== toasts: Toast[]; addToast: (toast: Omit) => void; removeToast: (id: string) => void; } /** * [토스트 메시지 타입] */ export interface Toast { id: string; type: "success" | "error" | "warning" | "info"; message: string; duration?: number; } /** * [UI 스토어] * * 전역 UI 상태를 관리합니다. * - 테마 설정 (다크/라이트 모드) * - 사이드바 열림/닫힘 * - 모달 상태 * - 토스트 알림 * * @example * ```tsx * import { useUIStore } from '@/stores/ui-store'; * * function Header() { * const { theme, setTheme, toggleSidebar } = useUIStore(); * * return ( *
* * *
* ); * } * ``` */ export const useUIStore = create()( persist( (set) => ({ // ========== 테마 ========== theme: "system", setTheme: (theme) => set({ theme }), // ========== 사이드바 ========== isSidebarOpen: true, toggleSidebar: () => set((state) => ({ isSidebarOpen: !state.isSidebarOpen })), setSidebarOpen: (isOpen) => set({ isSidebarOpen: isOpen }), // ========== 모달 ========== isModalOpen: false, modalContent: null, openModal: (content) => set({ isModalOpen: true, modalContent: content }), closeModal: () => set({ isModalOpen: false, modalContent: null }), // ========== 토스트 ========== toasts: [], addToast: (toast) => set((state) => ({ toasts: [ ...state.toasts, { ...toast, id: `toast-${Date.now()}-${Math.random()}`, }, ], })), removeToast: (id) => set((state) => ({ toasts: state.toasts.filter((toast) => toast.id !== id), })), }), { name: "ui-storage", // localStorage 키 이름 // 일부 상태는 지속하지 않음 (모달, 토스트) partialize: (state) => ({ theme: state.theme, isSidebarOpen: state.isSidebarOpen, }), }, ), );