Skip to content
Merged
95 changes: 95 additions & 0 deletions public/Logomark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icon/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className={`${pretendard.variable} font-pretendard pretendard`}>
<body className={`${pretendard.variable} font-pretendard pretendard bg-[#1C1C1E]`}>
<MSWClientProvider>
<ToastProvider>{children}</ToastProvider>
</MSWClientProvider>
Expand Down
17 changes: 17 additions & 0 deletions src/app/main/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Goal } from '@/shared/type/goal';
import { apiClient } from '@/shared/lib/apiClient';
import { CommonResponse } from '@/shared/type/response';
import { GoalFormData } from '@/app/main/create-goal/page';

interface GoalListResponse extends CommonResponse<{ goals: Goal[] }> {}

interface CreateGoalRequest extends GoalFormData {}

export async function getGoalList() {
const { data } = await apiClient.get<GoalListResponse>('/goals');
return data.data.goals;
}

export async function postCreateGoal(req: CreateGoalRequest) {
return await apiClient.post<CreateGoalRequest>('/goal', req);
}
61 changes: 61 additions & 0 deletions src/app/main/components/ConfirmGoalBottomBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import FlexBox from '@/shared/components/layout/FlexBox';
import Button from '@/shared/components/navigation/Button';
import { motion } from 'framer-motion';

interface ProgressBarProps {
doneTask?: number;
totalTask?: number;
isLoading: boolean;
percentage: number;
onComplete: () => void;
isComplete: boolean;
isError?: boolean;
}

export const ConfirmGoalBottomBar = ({
isLoading,
doneTask,
totalTask,
percentage,
onComplete,
isComplete,
isError = false,
}: ProgressBarProps) => {
const isButtonEnabled = !isLoading && (isComplete || isError);

const getButtonText = () => {
if (isLoading) return '로딩중';
if (isError) return '다시 시도';
return '목표 작성 완료';
};

return (
<div className="w-full flex items-center px-[40px] pt-[12px] pb-[16px] gap-[95px] border-t border-line-normal">
<div className="flex flex-col gap-2 items-start w-full">
<FlexBox className="w-full justify-between">
<div className="body-1-medium text-primary-normal">
<span className="title-3-bold text-accent-violet">{percentage}%</span>
{/*<span className="ml-2 text-label-alternative">{`${Math.min(doneTask, totalTask)}/${totalTask}`}</span>*/}
</div>
</FlexBox>
<FlexBox className="relative w-full rounded-full h-3 bg-fill-normal">
<motion.div
className={`absolute h-full top-0 left-0 rounded-full bg-accent-fg-violet`}
initial={{ width: 0 }}
animate={{ width: `${percentage}%` }}
transition={{ duration: 0.4, ease: 'easeOut' }}
/>
</FlexBox>
</div>
<FlexBox className="min-w-[130px]">
<Button
size="ml"
text={getButtonText()}
onClick={onComplete}
disabled={!isButtonEnabled}
className={isButtonEnabled ? '' : 'opacity-50 cursor-not-allowed'}
/>
</FlexBox>
</div>
);
};
14 changes: 14 additions & 0 deletions src/app/main/components/LogoutButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useRouter } from 'next/navigation';
import { tokenController } from '@/shared/lib/token';
import Button from '@/shared/components/navigation/Button';

export const LogoutButton = () => {
const router = useRouter();

const handleLogout = () => {
tokenController.clearTokens();
router.push('/login');
};

return <Button size={'ml'} text={'로그아웃'} onClick={handleLogout} />;
};
16 changes: 16 additions & 0 deletions src/app/main/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use client';

import { useRouter } from 'next/navigation';
import Image from 'next/image';

export const Sidebar = ({ children }: { children?: React.ReactNode }) => {
const router = useRouter();
return (
<aside className="h-screen w-[88px] bg-fill-normal flex flex-col items-center py-8 shadow-lg">
<button onClick={() => router.push('/main')}>
<Image src="/Logomark.svg" alt="icon of growit" width={32} height={32} />
</button>
<div className="flex-1 w-full flex flex-col items-center">{children}</div>
</aside>
);
};
Loading