Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { useHomeTodosByDate } from "@/app/[locale]/(main)/(with-time-sidebar)/ho
import { useHomeViewMode } from "@/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-view-mode";
import { useHomeView } from "@/app/[locale]/(main)/(with-time-sidebar)/home/_queries/use-home-view";
import { DndSortableListProvider } from "@/providers/dnd/DndSortableListProvider";
import { formatDateKey } from "@/utils/date";
import { formatDateKey } from "@/utils/date/date";

const TAG_LABEL_KEYS = [
"dailyLife",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { ApiDayOfWeek } from "@/app/[locale]/(main)/(with-time-sidebar)/hom
import { DateInformation } from "@/app/[locale]/(main)/(with-time-sidebar)/_components/DateInformation";
import { CreateTodoModalContainer } from "@/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContainer";
import { convertDateToDateText } from "@/app/[locale]/(main)/(with-time-sidebar)/home/_utils/date";
import { getToday, parseDateKey } from "@/utils/date";
import { getToday, parseDateKey } from "@/utils/date/date";

export interface HomeDayHeaderContainerProps {
dateKey: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { useSearchParams } from "next/navigation";
import { useCallback, useMemo } from "react";

import { usePathname, useRouter } from "@/i18n/navigation";
import { addDays, formatDateKey, getToday, parseDateKey } from "@/utils/date";
import {
addDays,
formatDateKey,
getToday,
parseDateKey,
} from "@/utils/date/date";

const VIEW_PARAM = "view";
const DATE_PARAM = "date";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
getToday,
isSameDate,
parseDateKey,
} from "@/utils/date";
} from "@/utils/date/date";

const BASIC_RANGE_DAYS_BEFORE = 7;
const BASIC_RANGE_LENGTH = 15;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Todo } from "@/app/[locale]/(main)/(with-time-sidebar)/home/_types/todo-type";

import { formatDateKey, getToday, isSameDate } from "@/utils/date";
import { formatDateKey, getToday, isSameDate } from "@/utils/date/date";

type TodoTemplate = Omit<Todo, "todoId">;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatDateKey } from "@/utils/date";
import { formatDateKey } from "@/utils/date/date";

/**
* 날짜를 화면 표시용 텍스트로 변환한다. 매월 1일에는 "M.D" 형식을,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ApiDayOfWeek } from "@/app/[locale]/(main)/(with-time-sidebar)/home/_types/home-view-type";

import { getDayOfWeekKey } from "@/utils/get-day-of-week-key";
import { getDayOfWeekKey } from "@/utils/date/get-day-of-week-key";

/**
* 날짜를 홈 화면 API/i18n 키 형식의 요일 값으로 변환한다.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type { TodoMock } from "@/app/[locale]/(main)/(with-time-sidebar)/today/_
import { DateInformation } from "@/app/[locale]/(main)/(with-time-sidebar)/_components/DateInformation";
import { convertDateToDateText } from "@/app/[locale]/(main)/(with-time-sidebar)/home/_utils/date";
import { CreateTodoModalContainer } from "@/app/[locale]/(main)/(with-time-sidebar)/today/_containers/todo-modal/CreateTodoModalContainer";
import { getToday } from "@/utils/date";
import { getDayOfWeekKey } from "@/utils/get-day-of-week-key";
import { getToday } from "@/utils/date/date";
import { getDayOfWeekKey } from "@/utils/date/get-day-of-week-key";

interface TodayDateHeaderContainerProps {
completedCount: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import { TodayDateHeaderContainer } from "@/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayDateHeaderContainer";
import { TodayTodoCardContainer } from "@/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoCardContainer";
import { useTodayTodoList } from "@/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList";
import { convertDurationToTimeText } from "@/utils/convert-duration-to-time-text";
import { formatDate } from "@/utils/date";
import { formatDate } from "@/utils/date/date";
import { convertDurationToTimeText } from "@/utils/duration/convert-duration-to-time-text";

const PRIORITY_MAP = {
URGENT: "VERY_HIGH",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ import {
type TimerSessionControlsHandle,
} from "@/components/timer/TimerSessionControls";
import { AnimatedToast } from "@/components/toast/AnimatedToast";
import { convertDurationToMinutes } from "@/utils/convert-duration-to-minutes";
import { convertDurationToTimeText } from "@/utils/convert-duration-to-time-text";
import { formatDurationLabel } from "@/utils/format-duration-label";
import { convertDurationToMinutes } from "@/utils/duration/convert-duration-to-minutes";
import { convertDurationToTimeText } from "@/utils/duration/convert-duration-to-time-text";
import { formatDurationLabel } from "@/utils/duration/format-duration-label";

export const FocusSessionContainer = () => {
const queryClient = useQueryClient();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
"use client";

import { useQueryClient } from "@tanstack/react-query";
import { useTranslations } from "next-intl";
import { useState } from "react";
import { useForm } from "react-hook-form";

import type { BaseResponseUserProfileResponse } from "@/api/generated/models";
import type {
SettingsDefaultTagKey,
SettingsLanguage,
SettingsProfileFormValues,
} from "@/app/[locale]/(main)/settings/_types/profile-type";

import { useUpdateLanguage } from "@/api/generated/endpoints/user/user";
import {
getGetMyProfileQueryKey,
useUpdateLanguage,
} from "@/api/generated/endpoints/user/user";
import { UpdateLanguageRequestLanguage } from "@/api/generated/models";
import { useSettingsLanguageParam } from "@/app/[locale]/(main)/settings/_hooks/useSettingsLanguageParam";
import { useSettingsProfileQuery } from "@/app/[locale]/(main)/settings/_queries/use-settings-profile";
import { useMyProfile } from "@/queries/use-my-profile";

const LANGUAGE_REQUEST_MAP: Record<
SettingsLanguage,
Expand All @@ -38,11 +43,12 @@ export const useSettingsProfile = () => {
const { language, locale, setLanguage, commitLanguage } =
useSettingsLanguageParam();

const { data: profile } = useSettingsProfileQuery();
const { data: profile } = useMyProfile();
const [isCalendarConnected, setIsCalendarConnected] = useState(
profile.calendarConnected,
);
const { mutateAsync: updateLanguage } = useUpdateLanguage();
const queryClient = useQueryClient();

// TODO: 태그 목록 조회 API 연동 후 기본 태그 대신 실제 응답으로 교체
const { watch, setValue, handleSubmit, reset, formState } =
Expand Down Expand Up @@ -106,9 +112,22 @@ export const useSettingsProfile = () => {
const handleSave = handleSubmit(async (values) => {
try {
if (isLanguageDirty) {
await updateLanguage({
const { data } = await updateLanguage({
data: { language: LANGUAGE_REQUEST_MAP[language] },
});

if (data) {
queryClient.setQueryData(
getGetMyProfileQueryKey(),
(cached?: BaseResponseUserProfileResponse) =>
cached?.data
? {
...cached,
data: { ...cached.data, language: data.language },
}
: cached,
);
}
}
reset(values);
commitLanguage();
Expand Down

This file was deleted.

12 changes: 0 additions & 12 deletions apps/timo-web/app/[locale]/(main)/settings/_types/profile-type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { z } from "zod";

export type SettingsLanguage = "ko" | "en";

export type SettingsDefaultTagKey =
Expand All @@ -8,16 +6,6 @@ export type SettingsDefaultTagKey =
| "exercise"
| "dailyLife";

export const settingsProfileResponseSchema = z.object({
name: z.string(),
email: z.string(),
calendarConnected: z.boolean(),
});

export type SettingsProfileResponse = z.infer<
typeof settingsProfileResponseSchema
>;

export interface SettingsProfileFormValues {
tags: string[];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
getCalendarDates,
getFirstDayOffset,
} from "@/app/[locale]/(main)/statistics/_utils/statistics-calendar";
import { formatDateKey } from "@/utils/date";
import { formatDateKey } from "@/utils/date/date";

type CalendarIconStatus = "disabled" | "empty" | "outline" | "light" | "filled";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
MOCK_STATISTICS_MONTH_SUMMARY,
} from "@/app/[locale]/(main)/statistics/_mocks/statistics-calendar";
import { formatStatisticsSidePanelDate } from "@/app/[locale]/(main)/statistics/_utils/format-statistics-date";
import { formatDateKey } from "@/utils/date";
import { formatDateKey } from "@/utils/date/date";

export const StatisticsContainer = () => {
const locale = useLocale();
Expand Down
8 changes: 7 additions & 1 deletion apps/timo-web/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { setRequestLocale } from "next-intl/server";
import type { Metadata } from "next";

import { routing } from "@/i18n/routing";
import { AuthProvider } from "@/providers/auth/AuthProvider";
import { LanguageSyncProvider } from "@/providers/locale/LanguageSyncProvider";
import { OverlayProvider } from "@/providers/OverlayProvider";
import { QueryProvider } from "@/providers/query/QueryProvider";

Expand Down Expand Up @@ -48,7 +50,11 @@ export default async function RootLayout({
<body>
<NextIntlClientProvider>
<QueryProvider>
<OverlayProvider>{children}</OverlayProvider>
<AuthProvider>
<LanguageSyncProvider>
<OverlayProvider>{children}</OverlayProvider>
</LanguageSyncProvider>
</AuthProvider>
</QueryProvider>
</NextIntlClientProvider>
</body>
Expand Down
7 changes: 6 additions & 1 deletion apps/timo-web/app/[locale]/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { LoginContainer } from "@/app/[locale]/login/_containers/LoginContainer";
import { GuestGuardProvider } from "@/providers/auth/GuestGuardProvider";

export default function LoginPage() {
return <LoginContainer />;
return (
<GuestGuardProvider>
<LoginContainer />
</GuestGuardProvider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export const OauthCallbackContainer = () => {
const code = useSearchParams().get("code");
const router = useRouter();
const setAccessToken = useAuthStore((state) => state.setAccessToken);
const setOnboardingCompleted = useAuthStore(
(state) => state.setOnboardingCompleted,
);
const { mutate } = useToken();
const hasRequested = useRef(false);

Expand All @@ -32,14 +35,15 @@ export const OauthCallbackContainer = () => {
return;
}
setAccessToken(data.accessToken);
setOnboardingCompleted(data.user.onboardingCompleted);
router.replace(data.isNewUser ? ROUTES.ONBOARDING : ROUTES.HOME);
},
onError: () => {
router.replace(ROUTES.LOGIN);
},
},
);
}, [code, mutate, router, setAccessToken]);
}, [code, mutate, router, setAccessToken, setOnboardingCompleted]);

return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { LottiePlayer } from "@/components/lottie/LottiePlayer";
import { AnimatedToast } from "@/components/toast/AnimatedToast";
import { ROUTES } from "@/constants/routes";
import { useRouter } from "@/i18n/navigation";
import { useAuthStore } from "@/stores/auth/useAuthStore";

const STEP_NUMBER: Record<keyof OnboardingFunnelSteps, 1 | 2 | 3 | 4> = {
Language: 1,
Expand All @@ -33,6 +34,9 @@ const ONBOARDING_LANGUAGE_MAP: Record<"ko" | "en", OnboardingRequestLanguage> =
export const OnboardingFunnelContainer = () => {
const t = useTranslations("Toast");
const router = useRouter();
const setOnboardingCompleted = useAuthStore(
(state) => state.setOnboardingCompleted,
);
const [answers, setAnswers] = useState<
Partial<OnboardingFunnelSteps["CalendarConnect"]>
>({});
Expand Down Expand Up @@ -142,6 +146,7 @@ export const OnboardingFunnelContainer = () => {
},
{
onSuccess: () => {
setOnboardingCompleted(true);
router.replace(ROUTES.HOME, {
locale: answers.language,
});
Expand Down
5 changes: 4 additions & 1 deletion apps/timo-web/app/[locale]/onboarding/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { OnboardingFunnelContainer } from "@/app/[locale]/onboarding/_containers/OnboardingFunnelContainer";
import { AuthGuardProvider } from "@/providers/auth/AuthGuardProvider";
import { OnboardingCompletedGuardProvider } from "@/providers/auth/OnboardingCompletedGuardProvider";

export default function OnboardingPage() {
return (
<AuthGuardProvider>
<OnboardingFunnelContainer />
<OnboardingCompletedGuardProvider>
<OnboardingFunnelContainer />
</OnboardingCompletedGuardProvider>
</AuthGuardProvider>
);
}
21 changes: 19 additions & 2 deletions apps/timo-web/app/[locale]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
export default function Home() {
return <></>;
import { notFound } from "next/navigation";
import { hasLocale } from "next-intl";

import { ROUTES } from "@/constants/routes";
import { redirect } from "@/i18n/navigation";
import { routing } from "@/i18n/routing";

interface HomeProps {
params: Promise<{ locale: string }>;
}

export default async function Home({ params }: HomeProps) {
const { locale } = await params;

if (!hasLocale(routing.locales, locale)) {
notFound();
}

redirect({ href: ROUTES.HOME, locale });
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SidebarButton } from "@repo/timo-design-system/ui";
import { cn } from "@repo/timo-design-system/utils";
import { useTranslations } from "next-intl";

import { getDayOfWeekKey } from "@/utils/get-day-of-week-key";
import { getDayOfWeekKey } from "@/utils/date/get-day-of-week-key";

export interface TimeSidebarHeaderProps {
date: Date;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useEffect, useState } from "react";

import { getHourLabel } from "@/utils/get-hour-label";
import { getHourLabel } from "@/utils/date/get-hour-label";

const HOURS_IN_DAY = 24;
const HOUR_LINES = HOURS_IN_DAY + 1;
Expand Down
2 changes: 1 addition & 1 deletion apps/timo-web/components/timer/TimerCompleteModalPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Modal } from "@repo/timo-design-system/ui";
import { useTranslations } from "next-intl";

import { formatDurationLabel } from "@/utils/format-duration-label";
import { formatDurationLabel } from "@/utils/duration/format-duration-label";

export interface TimerCompleteModalPanelProps {
plannedMinutes: number;
Expand Down
2 changes: 1 addition & 1 deletion apps/timo-web/components/timer/TimerStopModalPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Modal, ModalButton } from "@repo/timo-design-system/ui";
import Image from "next/image";
import { useTranslations } from "next-intl";

import { formatDurationLabel } from "@/utils/format-duration-label";
import { formatDurationLabel } from "@/utils/duration/format-duration-label";

export interface TimerStopModalPanelProps {
minutes: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useIconField } from "@/hooks/todo-modal/use-icon-field";
import { useRepeatField } from "@/hooks/todo-modal/use-repeat-field";
import { useTagField } from "@/hooks/todo-modal/use-tag-field";
import { useTimeField } from "@/hooks/todo-modal/use-time-field";
import { formatDateKey } from "@/utils/date";
import { formatDateKey } from "@/utils/date/date";

const createDefaultValues = (defaultDate?: Date): CreateTodoRequest => ({
icon: null,
Expand Down
Loading
Loading