diff --git a/src/renderer/pages/home.tsx b/src/renderer/pages/home.tsx
index ab172ab..03046fa 100644
--- a/src/renderer/pages/home.tsx
+++ b/src/renderer/pages/home.tsx
@@ -6,6 +6,7 @@ import { useLocalStorage, useTimeout } from 'usehooks-ts';
import { useUser } from '@/features/user';
import appSymbolIcon from '@/shared/assets/svgs/app-symbol.svg';
import { LOCAL_STORAGE_KEY, PATH } from '@/shared/constants';
+import { SimpleLayout } from '@/shared/ui';
import { cn } from '@/shared/utils';
const Home = () => {
@@ -27,14 +28,16 @@ const Home = () => {
}, [isCompletedOnboarding, user]);
return (
-
-
-
+
+
+
+
+
);
};
diff --git a/src/renderer/pages/mycat.tsx b/src/renderer/pages/mycat.tsx
index 904dd08..2e2b4b2 100644
--- a/src/renderer/pages/mycat.tsx
+++ b/src/renderer/pages/mycat.tsx
@@ -7,7 +7,7 @@ import { useUser } from '@/features/user';
import catSelectMotionRiveFile from '@/shared/assets/rivs/cat_select_ver2.0.riv';
import { PATH } from '@/shared/constants';
import { userCatTypeAliasMap } from '@/shared/hooks';
-import { Button, Frame, Icon, Tooltip } from '@/shared/ui';
+import { Button, Frame, Icon, SimpleLayout, Tooltip } from '@/shared/ui';
const MyCat = () => {
const navigate = useNavigate();
@@ -39,39 +39,41 @@ const MyCat = () => {
}, [rive, user?.cat?.type]);
return (
-
-
navigate(PATH.MY_PAGE)} />
+
+
+ navigate(PATH.MY_PAGE)} />
-
-
-
+
+
+
-
+
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
);
};
diff --git a/src/renderer/pages/mypage.tsx b/src/renderer/pages/mypage.tsx
index 76dbd57..d25d6ee 100644
--- a/src/renderer/pages/mypage.tsx
+++ b/src/renderer/pages/mypage.tsx
@@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';
import { useFocusNotification } from '@/features/time';
import { useUser } from '@/features/user';
import { PATH } from '@/shared/constants';
-import { Frame, Icon, Toggle } from '@/shared/ui';
+import { SidebarLayout, Icon, Toggle } from '@/shared/ui';
const SURVEY_LINK =
'https://docs.google.com/forms/d/e/1FAIpQLSdoFxWJ7TFTU0-HKZEeqmDxz5ZprYtRz08FwrzNgDWnkNaOeA/viewform';
@@ -14,41 +14,52 @@ const MyPage = () => {
const { isEnabled, isUnavailable, changeEnabled } = useFocusNotification();
return (
-
-
navigate(PATH.POMODORO)} />
-
-
-
navigate(PATH.MY_CAT)}>
- 나의 고양이
- {user?.cat?.name}
-
+
+
+
+
+
나의 고양이
+
navigate(PATH.MY_CAT)}>
+ {user?.cat?.name}
+
+
-
+
+
통계
+
+
-
-
-
-
집중시간 알림받기
-
- 집중・휴식시간이 되면 고양이가 알려줘요
-
+
+
알림
+
+
+
+
집중시간 알림받기
+
+ 집중・휴식시간이 되면 고양이가 알려줘요
+
+
+
{
+ console.log('pressed', pressed);
+ changeEnabled(pressed);
+ }}
+ />
+
-
{
- console.log('pressed', pressed);
- changeEnabled(pressed);
- }}
- />
-
-
window.open(SURVEY_LINK, '_target')}>
- 의견 보내기
-
+
+
서비스
+
window.open(SURVEY_LINK, '_target')}>
+ 의견 보내기
+
+
+
-
+
);
};
@@ -67,10 +78,10 @@ const ActionButton = ({ children, onClick }: ActionButtonProps) => (
);
const ReadyForStat = () => (
-
+
-
통계 기능을 준비하고 있어요
+
통계 기능을 준비하고 있어요
집중시간을 모아보는 통계가
곧 업데이트될 예정이에요
diff --git a/src/renderer/pages/naming.tsx b/src/renderer/pages/naming.tsx
index 468d6b4..f2210d8 100644
--- a/src/renderer/pages/naming.tsx
+++ b/src/renderer/pages/naming.tsx
@@ -7,7 +7,7 @@ import { useUser } from '@/features/user';
import catHomeMotionRiveFile from '@/shared/assets/rivs/cat_home.riv';
import { PATH } from '@/shared/constants';
import { useRiveCat } from '@/shared/hooks';
-import { Button, Frame, Tooltip } from '@/shared/ui';
+import { Button, Frame, SimpleLayout, Tooltip } from '@/shared/ui';
const Naming = () => {
const location = useLocation();
@@ -41,47 +41,49 @@ const Naming = () => {
};
return (
-
-
-
-
-
-
{
- clickCatInput?.fire();
- }}
- />
-
-
-
setTypedCatName(e.target.value)}
+
+
+
+
+
+
- {errorMessage && (
-
-
- {errorMessage}
+
{
+ clickCatInput?.fire();
+ }}
+ />
+
+
+
setTypedCatName(e.target.value)}
+ />
+ {errorMessage && (
+
-
- )}
+ )}
+
-
-
-
-
-
+
+
+
+
+
);
};
diff --git a/src/renderer/pages/onboarding.tsx b/src/renderer/pages/onboarding.tsx
index 20de48e..74d5e00 100644
--- a/src/renderer/pages/onboarding.tsx
+++ b/src/renderer/pages/onboarding.tsx
@@ -7,7 +7,14 @@ import onboardingImage1 from '@/shared/assets/images/onboarding-1.png';
import onboardingImage2 from '@/shared/assets/images/onboarding-2.png';
import onboardingImage3 from '@/shared/assets/images/onboarding-3.png';
import { LOCAL_STORAGE_KEY, PATH } from '@/shared/constants';
-import { Button, Carousel, CarouselContent, CarouselItem, useCarousel } from '@/shared/ui';
+import {
+ Button,
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ SimpleLayout,
+ useCarousel,
+} from '@/shared/ui';
import { cn } from '@/shared/utils';
const Onboarding = () => {
@@ -45,56 +52,58 @@ const OnboardingContent = () => {
const [, setIsCompleted] = useLocalStorage(LOCAL_STORAGE_KEY.ONBOARDING_COMPLETED, false);
return (
-
-
-
- {contents.map(({ title, description, imageSrc }, index) => (
-
-
-
+
+
+
+
+ {contents.map(({ title, description, imageSrc }, index) => (
+
+
+
-
-
{title}
-
{description}
+
+
{title}
+
{description}
+
-
-
- ))}
-
+
+ ))}
+
-
- {contents.map((_, index) => (
-
- ))}
-
-
+
+ {contents.map((_, index) => (
+
+ ))}
+
+
-
-
+
+
+
-
+
);
};
diff --git a/src/renderer/pages/pomodoro.tsx b/src/renderer/pages/pomodoro.tsx
index 473c0c5..70ff98a 100644
--- a/src/renderer/pages/pomodoro.tsx
+++ b/src/renderer/pages/pomodoro.tsx
@@ -9,7 +9,7 @@ import { useFocusNotification } from '@/features/time';
import { useUser } from '@/features/user';
import { MINUTES_GAP } from '@/shared/constants';
import { useDisclosure } from '@/shared/hooks';
-import { useToast } from '@/shared/ui';
+import { SidebarLayout, SimpleLayout, useToast } from '@/shared/ui';
import {
createIsoDuration,
isoDurationToMs,
@@ -140,63 +140,69 @@ const Pomodoro = () => {
if (mode === 'focus')
return (
- {
- startRestWait();
- }}
- handleEnd={() => {
- endPomodoro();
- }}
- />
+
+ {
+ startRestWait();
+ }}
+ handleEnd={() => {
+ endPomodoro();
+ }}
+ />
+
);
if (mode === 'rest-wait')
return (
- {
- updateCategoryTime('focusTime', currentFocusMinutes);
- startRest();
- }}
- handleEnd={() => {
- updateCategoryTime('focusTime', currentFocusMinutes);
- endPomodoro();
- }}
- />
+
+ {
+ updateCategoryTime('focusTime', currentFocusMinutes);
+ startRest();
+ }}
+ handleEnd={() => {
+ updateCategoryTime('focusTime', currentFocusMinutes);
+ endPomodoro();
+ }}
+ />
+
);
if (mode === 'rest')
return (
- {
- updateCategoryTime('restTime', currentRestMinutes);
- startFocus();
- }}
- handleEnd={() => {
- updateCategoryTime('restTime', currentRestMinutes);
- endPomodoro();
- }}
- />
+
+ {
+ updateCategoryTime('restTime', currentRestMinutes);
+ startFocus();
+ }}
+ handleEnd={() => {
+ updateCategoryTime('restTime', currentRestMinutes);
+ endPomodoro();
+ }}
+ />
+
);
return (
- <>
+
{
description={timeoutMessageMap[timeoutMode].description}
/>
)}
- >
+
);
};
diff --git a/src/renderer/pages/selection.tsx b/src/renderer/pages/selection.tsx
index 702b6df..a6aed4c 100644
--- a/src/renderer/pages/selection.tsx
+++ b/src/renderer/pages/selection.tsx
@@ -9,7 +9,15 @@ import appIconImage from '@/shared/assets/images/app-icon.png';
import catSelectMotionRiveFile from '@/shared/assets/rivs/cat_select_ver2.0.riv';
import { PATH } from '@/shared/constants';
import { useNotification } from '@/shared/hooks';
-import { Button, Frame, Icon, IconName, SelectGroup, SelectGroupItem } from '@/shared/ui';
+import {
+ Button,
+ Frame,
+ Icon,
+ IconName,
+ SimpleLayout,
+ SelectGroup,
+ SelectGroupItem,
+} from '@/shared/ui';
import { cn } from '@/shared/utils';
const adjectiveMap: Record = {
@@ -83,75 +91,77 @@ const Selection = () => {
};
return (
-
-
-
-
-
-
어떤 고양이와 함께할까요?
-
언제든지 다른 고양이와 함께할 수 있어요
-
-
-
- {!selectedCatId &&
}
- {cats.map((cat) => (
-
- {selectedCatId === cat.id && }
-
- ))}
-
- {/* TODO: 아래를 선택한 고양이 이미지 에셋으로 변경 */}
-
-
-
-
{
- setSelectedCatId((prevCatId) => {
- const prevCat = cats.find((cat) => cat.id === prevCatId);
- const nextCat = cats.find((cat) => cat.id === nextCatId);
-
- // 다음 고양이 선택이 있으면 해당 input을 fire
- // 없으면 처음으로 돌아가기 위해 이전 고양이의 input을 fire
- if (nextCat) {
- catTypeInputMap[nextCat.type]?.fire();
- } else if (prevCat) {
- catTypeInputMap[prevCat.type]?.fire();
- }
-
- return nextCatId;
- });
- }}
- >
- {cats.map((cat) => (
-
-
- {cat.adjective}
-
-
+
+
+
+
+
+
어떤 고양이와 함께할까요?
+
언제든지 다른 고양이와 함께할 수 있어요
+
+
+
+ {!selectedCatId &&
}
+ {cats.map((cat) => (
+
+ {selectedCatId === cat.id && }
+
+ ))}
+
+ {/* TODO: 아래를 선택한 고양이 이미지 에셋으로 변경 */}
+
+
+
+
{
+ setSelectedCatId((prevCatId) => {
+ const prevCat = cats.find((cat) => cat.id === prevCatId);
+ const nextCat = cats.find((cat) => cat.id === nextCatId);
+
+ // 다음 고양이 선택이 있으면 해당 input을 fire
+ // 없으면 처음으로 돌아가기 위해 이전 고양이의 input을 fire
+ if (nextCat) {
+ catTypeInputMap[nextCat.type]?.fire();
+ } else if (prevCat) {
+ catTypeInputMap[prevCat.type]?.fire();
+ }
+
+ return nextCatId;
+ });
+ }}
+ >
+ {cats.map((cat) => (
+
- {cat.name}
-
-
- ))}
-
-
+
+ {cat.adjective}
+
+
+ {cat.name}
+
+
+ ))}
+
+
-
-
-
-
+
+
+
+
+
);
};
diff --git a/src/renderer/shared/assets/svgs/clock-line.svg b/src/renderer/shared/assets/svgs/clock-line.svg
new file mode 100644
index 0000000..7a1b751
--- /dev/null
+++ b/src/renderer/shared/assets/svgs/clock-line.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/renderer/shared/ui/icon.tsx b/src/renderer/shared/ui/icon.tsx
index 48c4472..ab78031 100644
--- a/src/renderer/shared/ui/icon.tsx
+++ b/src/renderer/shared/ui/icon.tsx
@@ -8,10 +8,11 @@ import CategoryWorkIcon from '@/shared/assets/svgs/category-work.svg';
import CheckIcon from '@/shared/assets/svgs/check.svg?react';
import CheerIcon from '@/shared/assets/svgs/cheer.svg';
import ChevronRightIcon from '@/shared/assets/svgs/chevron-right.svg';
+import ClockLineIcon from '@/shared/assets/svgs/clock-line.svg?react';
import ClockIcon from '@/shared/assets/svgs/clock.svg';
import CloseIcon from '@/shared/assets/svgs/close.svg';
import FocusTimeIcon from '@/shared/assets/svgs/focus-time.svg';
-import MenuIcon from '@/shared/assets/svgs/menu.svg';
+import MenuIcon from '@/shared/assets/svgs/menu.svg?react';
import MinusIcon from '@/shared/assets/svgs/minus.svg';
import MinusSvgIcon from '@/shared/assets/svgs/minus.svg?react';
import PenIcon from '@/shared/assets/svgs/pen.svg';
@@ -48,6 +49,7 @@ const icons = {
pen: PenIcon,
clock: ClockIcon,
readyForStat: ReadyForStatIcon,
+ clockLine: ClockLineIcon,
} as const;
const sizes = {
xs: 16,
diff --git a/src/renderer/shared/ui/index.ts b/src/renderer/shared/ui/index.ts
index adc1dfb..858b2eb 100644
--- a/src/renderer/shared/ui/index.ts
+++ b/src/renderer/shared/ui/index.ts
@@ -11,3 +11,4 @@ export * from './toggle';
export * from './frame';
export * from './guide';
export * from './dialog';
+export * from './layouts';
diff --git a/src/renderer/shared/ui/layouts.tsx b/src/renderer/shared/ui/layouts.tsx
new file mode 100644
index 0000000..fb351a0
--- /dev/null
+++ b/src/renderer/shared/ui/layouts.tsx
@@ -0,0 +1,63 @@
+import { useLocation, useNavigate } from 'react-router-dom';
+
+import { PATH } from '../constants';
+import { cn } from '../utils';
+
+import { Icon } from './icon';
+
+export type SimpleLayoutProps = {
+ children: React.ReactNode;
+};
+
+export const SimpleLayout = ({ children }: SimpleLayoutProps) => {
+ return {children}
;
+};
+
+export type SidebarLayoutProps = {
+ title?: string;
+ children: React.ReactNode;
+};
+
+export const SidebarLayout = ({ title, children }: SidebarLayoutProps) => {
+ return (
+
+
+
+
+
+
{title}
+
+
+ {children}
+
+
+ );
+};
+
+const DesktopSidebar = () => {
+ const location = useLocation();
+ const navigate = useNavigate();
+
+ return (
+
+
+
+
+ );
+};
diff --git a/src/renderer/widgets/pomodoro/ui/home-screen.tsx b/src/renderer/widgets/pomodoro/ui/home-screen.tsx
index 89af9cb..92b14ab 100644
--- a/src/renderer/widgets/pomodoro/ui/home-screen.tsx
+++ b/src/renderer/widgets/pomodoro/ui/home-screen.tsx
@@ -1,6 +1,5 @@
import { useEffect, useState } from 'react';
-import { useNavigate } from 'react-router-dom';
import { useLocalStorage } from 'usehooks-ts';
import { CatType } from '@/entities/cat';
@@ -8,7 +7,7 @@ import { useCategories, useUpdateCategory, ChangeCategoryDrawer } from '@/featur
import { ChangeTimeDialog } from '@/features/time';
import { useUser } from '@/features/user';
import catHomeMotionRiveFile from '@/shared/assets/rivs/cat_home.riv';
-import { LOCAL_STORAGE_KEY, PATH } from '@/shared/constants';
+import { LOCAL_STORAGE_KEY } from '@/shared/constants';
import { useDisclosure, useRiveCat } from '@/shared/hooks';
import { Button, Guide, Icon, Tooltip, useToast } from '@/shared/ui';
import { getCategoryIconName, createIsoDuration } from '@/shared/utils';
@@ -42,8 +41,6 @@ export const HomeScreen = ({
currentFocusMinutes,
currentRestMinutes,
}: HomeScreenProps) => {
- const navigate = useNavigate();
-
const [clickedMode, setClickedMode] = useState<'focus' | 'rest'>('focus');
const [showGuide, setShowGuide] = useLocalStorage(LOCAL_STORAGE_KEY.GUIDE_SHOWN, true);
@@ -77,16 +74,6 @@ export const HomeScreen = ({
return (
<>
-
-
-