-
Notifications
You must be signed in to change notification settings - Fork 1
Kim kiseong week2 #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,44 @@ | ||
| // src/App.tsx | ||
| import React from 'react'; | ||
|
|
||
| import TodoHeader from './components/TodoHeader'; | ||
| import TodoList from './components/TodoList'; | ||
| import './App.css'; | ||
|
|
||
| function App() { | ||
| const App = () => { | ||
| // 1. 위쪽에 보여줄 데이터 (꽉 찬 배열) | ||
| const populatedTodos = [ | ||
| { id: 1, content: "리액트 공식문서 읽기", isDone: true }, | ||
| { id: 2, content: "알고리즘 문제 풀기", isDone: true }, | ||
| { id: 3, content: "운동 30분 하기", isDone: false }, | ||
| { id: 4, content: "프로젝트 회의 준비", isDone: false }, | ||
| ]; | ||
|
|
||
| // 2. 아래쪽에 보여줄 데이터 (텅 빈 배열) | ||
| const emptyTodos: any[] = []; | ||
|
|
||
| return ( | ||
| <div className="app-layout"> | ||
| <div className="todo-container"> | ||
| <TodoHeader /> | ||
| <TodoList /> | ||
|
|
||
| {/* ========================================= */} | ||
| {/* 첫 번째 화면: 데이터가 있을 때 (체크박스 토글) */} | ||
| {/* ========================================= */} | ||
| <div className="section"> | ||
| <TodoHeader /> | ||
| <TodoList todos={populatedTodos} /> | ||
| </div> | ||
|
|
||
| {/* ========================================= */} | ||
| {/* 두 번째 화면: 데이터가 없을 때 (빈 상태) */} | ||
| {/* ========================================= */} | ||
| <div className="section" style={{ marginTop: '96px' }}> | ||
|
|
||
| <TodoHeader /> | ||
| <TodoList todos={emptyTodos} /> | ||
| </div> | ||
|
Comment on lines
+22
to
+37
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다음주에는 이 부분을 조건부 렌더링으로 처리해보면 좋을 것 같아요 |
||
|
|
||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| }; | ||
|
|
||
| export default App; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 파일이 현재 import 되는 곳이 보이지 않아서 한번 점검 해보시면 좋을 것같아요 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| .app-container { | ||
| padding: 20px; | ||
| background-color: #f5f5f5; /* Figma 배경색*/ | ||
| min-height: 100vh; | ||
| } | ||
|
|
||
| .todo-header h1 { | ||
| font-size: 36px; /* Figma Typography */ | ||
| font-weight: 700; | ||
| margin-bottom: 30px; /* Figma 간격 */ | ||
| align-self : stretch; | ||
| } | ||
|
|
||
| .todo-list { | ||
| display: flex; | ||
| padding: 16px; | ||
| align-items: center; | ||
| gap: 10px; | ||
| align-self: stretch; | ||
|
|
||
| } | ||
|
|
||
| .todo-card { | ||
| background: #ffffff; | ||
| border-radius: 12px; /* Figma Radius */ | ||
| padding: 16px; | ||
| display: flex; | ||
| justify-content: space-between; | ||
| align-items: center; | ||
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* Figma Shadow */ | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,31 @@ | ||
| // src/components/TodoCard.tsx | ||
| import React from 'react'; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| // props 타입을 정의합니다 (TypeScript용) | ||
| interface TodoCardProps { | ||
| content: string; | ||
| isDone: boolean; | ||
| } | ||
|
|
||
| const TodoCard = ({ content }: TodoCardProps) => { | ||
| const TodoCard = ({ content, isDone }: TodoCardProps) => { | ||
| return ( | ||
| <div className="todo-card"> | ||
| <p className="card-text">{content}</p> | ||
| <div className={`todo-card ${isDone ? 'done-card' : ''}`}> | ||
| <div className="checkbox-icon"> | ||
| {isDone ? ( | ||
| // 🔵 완료 상태 (파란색 채워진 원 + 흰색 체크) | ||
| <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
| <circle cx="12" cy="12" r="10" fill="#A4C5FD"/> | ||
| <path d="M7 12.5L10 15.5L17 8.5" stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/> | ||
| </svg> | ||
| ) : ( | ||
| // ⚪ 미완료 상태 (회색 테두리 빈 원) | ||
| <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
| <circle cx="12" cy="12" r="10" stroke="#E5E7EB" strokeWidth="2"/> | ||
| </svg> | ||
| )} | ||
| </div> | ||
|
|
||
| <p className={`card-text ${isDone ? 'done-text' : ''}`}> | ||
| {content} | ||
| </p> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,19 +2,42 @@ | |
| import React from 'react'; | ||
| import TodoCard from './TodoCard'; | ||
|
|
||
| const TodoList = () => { | ||
| const todo1 = "리액트 공식문서 읽기"; | ||
| const todo2 = "알고리즘 문제 풀기"; | ||
| const todo3 = "운동 30분 하기"; | ||
| const todo4 = "프로젝트 회의 준비";<q></q> | ||
| // 1. 부모에게서 받을 데이터의 타입을 정해줍니다. | ||
| interface Todo { | ||
| id: number; | ||
| content: string; | ||
| isDone: boolean; | ||
| } | ||
|
|
||
| interface TodoListProps { | ||
| todos: Todo[]; | ||
| } | ||
|
|
||
| // 2. 괄호 안에 { todos }: TodoListProps 를 넣어서 외부 데이터를 받아옵니다! | ||
| // 🚨 주의: 이 아래에 const todos = [...] 같은 코드가 절대 있으면 안 됩니다! | ||
| const TodoList = ({ todos }: TodoListProps) => { | ||
| return ( | ||
| <main className="todo-list"> | ||
| <TodoCard content={todo1} /> | ||
| <TodoCard content={todo2} /> | ||
| <TodoCard content={todo3} /> | ||
| <TodoCard content={todo4} /> | ||
| </main> | ||
| <div className="todo-list-wrapper"> | ||
|
|
||
| {/* 3. 받아온 todos 배열의 길이에 따라 빈 화면을 보여줄지 결정합니다 */} | ||
| {todos.length === 0 ? ( | ||
| <div className="empty-state"> | ||
| <span className="empty-icon">📋</span> | ||
| <p className="empty-text">아직 할 일이 없어요</p> | ||
| </div> | ||
| ) : ( | ||
| <div className="todo-list"> | ||
| {todos.map((todo) => ( | ||
| <TodoCard | ||
| key={todo.id} | ||
| content={todo.content} | ||
| isDone={todo.isDone} | ||
| /> | ||
| ))} | ||
| </div> | ||
|
Comment on lines
+29
to
+37
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 목록 구조가 |
||
| )} | ||
|
|
||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재
emptyTodos를any[]로 선언해서 빈 배열을 처리하고 있는데, 이런 방식은 TypeScript 타입 체크를 우회하게 됩니다.Todo타입을 공용으로 빼거나 같은 타입으로 명시해두면 빈 배열도 더 안전하게 다룰 수 있습니다.