Skip to content
Closed
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
93 changes: 35 additions & 58 deletions app/(with-sidebar)/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,49 @@
'use client';

import BottomSection from '@/components/home/BottomSection';
import GraphSection from '@/components/home/GraphSection';
import HeaderSection from '@/components/home/HeaderSection';
import ProfileSection from '@/components/home/ProfileSection';
import GraphSection from '@/components/home/GraphSection';
import ButtonSection from '@/components/home/ButtonSection';
import BottomSection from '@/components/home/BottomSection';

import { useEffect, useState } from 'react';
import { useAuthUser } from '@/hooks/useAuthUser';

import {
Todo,
fetchTodos,
AddTodo,
toggleTodoStatus,
} from '@/services/home/todoService.service';
import { getProfile, Profile } from '@/services/home/profileService.service';
import { useTodos } from '@/hooks/useTodos';

const Page = () => {
// 현재 사용자 정보
const { user: currentUser, authLoading } = useAuthUser();

const [profile, setProfile] = useState<Profile | null>(null);
const [todos, setTodos] = useState<Todo[]>([]);
const [error, setError] = useState<string | null>(null);

// 1. 할 일 목록 불러오기
const loadTodos = async (uid: string) => {
try {
setError(null);

const fetchedTodos = await fetchTodos(uid);
setTodos(fetchedTodos);
} catch (err) {
console.error(err);
setError('데이터를 불러오는 데 실패하였습니다');
}
};

// 3. 할 일 상태 토글
const handleToggleTodo = async (id: string, currentStatus: boolean) => {
if (!currentUser) return;
try {
setError(null);

await toggleTodoStatus(currentUser.uid, id, currentStatus);
await loadTodos(currentUser.uid);
} catch (err) {
console.error(err);
setError('상태를 업데이트하는 데 실패하였습니다');
}
};

// 사용자가 존재하면 데이터 불러옴
const uid = currentUser?.uid;

const {
todos,
progressText,
toggleTodo,
createTodo,
removeTodo,
editTodoText,
loading: todosLoading,
error: todosError,
} = useTodos(uid);

useEffect(() => {
if (!currentUser) return;
if (!uid) return;

(async () => {
try {
const userProfile = await getProfile(currentUser.uid);
setError(null);
const userProfile = await getProfile(uid);
setProfile(userProfile);
await loadTodos(currentUser.uid);
} catch (err) {
console.error(err);
} catch (e) {
console.error(e);
setError('프로필 정보를 불러오는 데 실패하였습니다');
}
})();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}, [currentUser]);
}, [uid]);

// 유저 정보 로딩 처리
if (authLoading) {
return (
<div className="flex min-h-screen items-center justify-center">
Expand All @@ -76,7 +52,6 @@ const Page = () => {
);
}

// 유저 정보가 없을 시
if (!currentUser) {
return (
<div className="flex min-h-screen items-center justify-center">
Expand All @@ -85,30 +60,32 @@ const Page = () => {
);
}

// 유저 정보가 있을 시
const mergedError = error ?? todosError;

return (
<div className="bg-background flex min-h-screen flex-col gap-4 font-sans md:p-[137px]">
{/* 1. Header */}
<HeaderSection />

{/* 2-1. ProfileSection */}
<ProfileSection
className="grid grid-cols-1 gap-4 md:grid-cols-3"
profile={profile}
uid={currentUser.uid}
uid={uid!}
progressText={progressText}
/>

{/* 2-2. GraphSection */}
<GraphSection uid={currentUser.uid}></GraphSection>
<GraphSection uid={uid!} />

{/* 2-3. BottomSection */}
<BottomSection
className="grid grid-cols-1 gap-4 md:grid-cols-2"
uid={uid!}
todos={todos}
onToggleTodo={handleToggleTodo}
loading={todosLoading}
error={mergedError}
onToggleTodo={toggleTodo}
onAddTodo={createTodo}
onRemoveTodo={removeTodo}
onEditTodoText={editTodoText}
/>

{/* 3. ButtonSection */}
<ButtonSection />
</div>
);
Expand Down
74 changes: 28 additions & 46 deletions components/home/BottomSection.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,42 @@
'use client';

import { useState } from 'react';
import Card from './Card';
import CheckList from './CheckList';
import { Todo } from '@/services/home/todoService.service';
import TodoContainer from './TodoContainer';
import type { Todo } from '@/services/home/todoService.service';

interface BottomSectionProps {
className?: string;
todos: Todo[];
onToggleTodo: (id: string, currentStatus: boolean) => void;
}
uid: string;

// const TODAY_DUMMY = [
// { id: 't1', text: 'React Hooks 정리', isChecked: false },
// { id: 't2', text: 'GSAP ScrollTrigger 복습', isChecked: true },
// { id: 't3', text: '알고리즘 1문제 풀기', isChecked: false },
// ];
todos: Todo[];
loading?: boolean;
error?: string | null;

// const UPCOMING_DUMMY = [
// { id: 'u1', text: 'Next.js App Router 정리', isChecked: false },
// { id: 'u2', text: '포트폴리오 리팩토링', isChecked: false },
// ];
onToggleTodo: (id: string, currentStatus: boolean) => Promise<void> | void;
onAddTodo: (text: string) => Promise<void> | void;
onRemoveTodo: (id: string) => Promise<void> | void;
onEditTodoText: (id: string, text: string) => Promise<void> | void;
}

export default function BottomSection({
className,
uid,
todos,
loading,
error,
onToggleTodo,
onAddTodo,
onRemoveTodo,
onEditTodoText,
}: BottomSectionProps) {
// const [today, setToday] = useState<ChecklistItem[]>(TODAY_DUMMY);
// const [upcoming, setUpcoming] = useState<ChecklistItem[]>(UPCOMING_DUMMY);

// const toggleToday = (id: string) => {
// setToday((prev) =>
// prev.map((it) =>
// it.id === id ? { ...it, isChecked: !it.isChecked } : it
// )
// );
// };

// const toggleUpcoming = (id: string) => {
// setUpcoming((prev) =>
// prev.map((it) =>
// it.id === id ? { ...it, isChecked: !it.isChecked } : it
// )
// );
// };

return (
<div className={className}>
<Card title="오늘 할 일">
<CheckList
items={todos}
onToggleTodo={onToggleTodo}
emptyText="오늘 할 일이 없습니다"
/>
</Card>
<div>
<TodoContainer
uid={uid}
todos={todos}
loading={loading}
error={error}
onToggleTodo={onToggleTodo}
onAddTodo={onAddTodo}
onRemoveTodo={onRemoveTodo}
onEditTodoText={onEditTodoText}
></TodoContainer>
Comment on lines +30 to +39
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -name "TodoContainer.tsx" -o -name "TodoContainer.ts" -o -name "TodoContainer.jsx" -o -name "TodoContainer.js" 2>/dev/null | head -20

Repository: DeveloperBlog-Devflow/devflow

Length of output: 108


🏁 Script executed:

cat -n ./components/home/TodoContainer.tsx

Repository: DeveloperBlog-Devflow/devflow

Length of output: 2482


TodoContainer에서 uid prop이 전혀 사용되지 않고 있습니다.

TodoContainer 컴포넌트의 Props 타입에는 uid가 정의되어 있지만(10행), 함수 매개변수에서 구조 분해되지 않으며(23-31행) 컴포넌트 본문 어디에서도 사용되지 않습니다. uid prop을 Props 타입에서 제거하거나, 실제로 필요한 경우 사용해야 합니다.

🤖 Prompt for AI Agents
In `@components/home/BottomSection.tsx` around lines 30 - 39, TodoContainer의
Props에 정의된 uid가 함수 매개변수(예: TodoContainer(props) 또는 function TodoContainer({...})
선언)에서 구조분해되지 않고 컴포넌트 본문에서 전혀 사용되지 않으므로 Props 정의와 구현을 일치시켜야 합니다; 해결책은
TodoContainer의 Props 타입에서 uid를 제거 if unused, 또는 컴포넌트 선언(예: TodoContainer의 매개변수
목록)에서 uid를 구조분해하여 실제로 사용하도록 변경(예: 키, 사용자별 필터, API 호출에 전달 등)하고 사용처가 필요한 위치(렌더링 로직
또는 하위 컴포넌트에 전달)로 전달하는 것입니다.


{/* <Card title="다가오는 일정">
<CheckList
Expand Down
15 changes: 12 additions & 3 deletions components/home/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@ interface CardProps {
children: ReactNode; // 카드 내부 내용들
className?: string; // 추가 스타일링
title?: string; // 좌측 상단 제목이 있는 경우
rightSlot?: ReactNode;
}

const Card = ({ children, className = '', title }: CardProps) => {
const Card = ({ children, className = '', title, rightSlot }: CardProps) => {
return (
<div className={`bg-surface rounded-[10px] p-6 shadow-sm ${className}`}>
{title && (
<h2 className="mb-4 text-lg font-bold text-gray-900">{title}</h2>
{(title || rightSlot) && (
<div className="mb-4 flex items-center justify-between">
{title ? (
<h2 className="text-lg font-bold text-gray-900">{title}</h2>
) : (
<div />
)}

{rightSlot}
</div>
)}
{children}
</div>
Expand Down
Loading