Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
e20296e
📦 build: next 버전 변경 및 vulnerabilities 개선
Moon-ju-young Jun 11, 2025
c867e85
🐛 fix: 불필요 파일 제거
Moon-ju-young Jun 11, 2025
579aaba
✏️ chore: gitignore에 vscode 폴더 추가
Moon-ju-young Jun 11, 2025
c71f3d1
🐛 fix: 기본 page 파일들 코드 정리
Moon-ju-young Jun 11, 2025
f1fdbb0
✨ feat: global.css 파일 추가
Moon-ju-young Jun 11, 2025
4d5f610
✨ feat: color 변수 추가
Moon-ju-young Jun 11, 2025
ea0349a
💄 style: font 추가
Moon-ju-young Jun 12, 2025
95ca172
✨ feat: favicon.ico 추가
Moon-ju-young Jun 12, 2025
385a904
✨ feat: icons 추가
Moon-ju-young Jun 12, 2025
a3191c6
✨ feat: plus icon 추가 및 이름 변경
Moon-ju-young Jun 12, 2025
44da60d
✨ feat: images 추가
Moon-ju-young Jun 12, 2025
f30b467
✨ feat: Btn component 파일 생성
Moon-ju-young Jun 23, 2025
74bb553
💄 style: reset.css 추가
Moon-ju-young Jun 25, 2025
f044260
✨ feat: Btn component 기본 구조 형성
Moon-ju-young Jun 25, 2025
75c9fd0
✨ feat: Btn component props 추가
Moon-ju-young Jun 25, 2025
6717259
✨ feat: Btn component children prop 추가
Moon-ju-young Jun 25, 2025
3e6594b
✨ feat: Btn.module.css 파일 생성
Moon-ju-young Jun 25, 2025
40d431b
✨ feat: Btn.module.css import 및 className 적용
Moon-ju-young Jun 25, 2025
0b4fb70
♻️ refactor: Btn Props type 분리
Moon-ju-young Jun 25, 2025
c4f423e
✨ feat: Btn component size prop 추가
Moon-ju-young Jun 25, 2025
c554931
✨ feat: Btn component mode prop 추가
Moon-ju-young Jun 25, 2025
3ded6cb
🐛 fix: Btn component children prop 삭제
Moon-ju-young Jun 25, 2025
aadd37f
✨ feat: Btn component size 및 mode prop에 따른 내용 설정
Moon-ju-young Jun 25, 2025
9697015
💄 style: reset.css button style 초기화 추가
Moon-ju-young Jun 25, 2025
938c91f
♻️ refactor: Btn component CONTENT 상수 객체 추가
Moon-ju-young Jun 25, 2025
fb783fc
✨ feat: Btn component mode className 추가
Moon-ju-young Jun 25, 2025
3c025f7
💄 style: Btn component 색 제외 style 설정
Moon-ju-young Jun 26, 2025
a76152a
✨ feat: Gnb component 파일 생성
Moon-ju-young Jun 26, 2025
fa30291
✨ feat: Gnb component 구조 형성
Moon-ju-young Jun 26, 2025
26020d6
💄 style: Gnb component style 설정
Moon-ju-young Jun 26, 2025
1b146f8
✨ feat: CheckList component 파일 생성
Moon-ju-young Jun 26, 2025
939718c
✨ feat: CheckList component props type 설정 및 추가
Moon-ju-young Jun 26, 2025
b698315
✨ feat: CheckList component 구조 형성
Moon-ju-young Jun 26, 2025
044ce1f
✨ feat: CheckList component className prop 추가
Moon-ju-young Jun 26, 2025
46440e0
💄 style: CheckList component style 설정
Moon-ju-young Jun 26, 2025
e151c90
✨ feat: Search component 파일 생성
Moon-ju-young Jun 26, 2025
c247aae
📦 build: react version 19로 변경
Moon-ju-young Jun 26, 2025
85fa813
✨ feat: Search component 기본 구조 형성
Moon-ju-young Jun 26, 2025
b174173
✨ feat: Search component placeholder 추가
Moon-ju-young Jun 26, 2025
4020475
💄 style: Search component style 설정
Moon-ju-young Jun 26, 2025
1923ce7
✨ feat: Search component props 추가
Moon-ju-young Jun 26, 2025
31d1efe
✨ feat: index page에 Gnb 추가
Moon-ju-young Jun 26, 2025
698c608
📦 bulid: axios 추가
Moon-ju-young Jun 26, 2025
f407bfd
✨ feat: api 파일 생성
Moon-ju-young Jun 26, 2025
fd9eb58
✨ feat: axios 기본 instance 설정
Moon-ju-young Jun 27, 2025
93f35af
✨ feat: ResponseItems type 및 getItems api 함수 추가
Moon-ju-young Jun 27, 2025
d15717d
✨ feat: Responseitem type 추가
Moon-ju-young Jun 27, 2025
6ab3546
✨ feat: getItem api 함수 추가
Moon-ju-young Jun 27, 2025
21ea9e7
✨ feat: PostItem type 과 postItem api 함수 추가
Moon-ju-young Jun 27, 2025
5eb0ebf
✨ feat: PatchItem type 과 patchItem api 함수 추가
Moon-ju-young Jun 27, 2025
d6c2e50
✨ feat: ResponseDelete type 및 deleteItem api 함수 추가
Moon-ju-young Jun 27, 2025
185848a
✨ feat: api type들도 export
Moon-ju-young Jun 27, 2025
1ca3b9d
✨ feat: Btn component icon image 추가
Moon-ju-young Jun 27, 2025
3000359
✨ feat: Btn component plus_white icon 및 icon id 추가
Moon-ju-young Jun 27, 2025
3194f9a
♻️ refactor: Btn component shadow 구현 방식 변경
Moon-ju-young Jun 27, 2025
023cea0
✨ feat: Btn component className prop 처리 추가
Moon-ju-young Jun 27, 2025
ed34fef
✨ feat: Btn component Image width 추가
Moon-ju-young Jun 27, 2025
50a12be
💄 style: Btn component hover 상태와 mode에 따른 스타일 구현
Moon-ju-young Jun 27, 2025
3cbf9f0
💄 style: Gnb component 내부 div가 부모 요소를 초과하는 스타일 수정
Moon-ju-young Jun 27, 2025
36304ca
💄 style: Gnb component z-index 추가
Moon-ju-young Jun 27, 2025
ae74e76
✨ feat: Search component ref prop 추가
Moon-ju-young Jun 27, 2025
f2e818b
✨ feat: index page 외부 구조 형성
Moon-ju-young Jun 27, 2025
734ec8a
✨ feat: index page form 추가
Moon-ju-young Jun 27, 2025
55e32e4
🐛 fix: postItem api 함수 수정
Moon-ju-young Jun 27, 2025
f366683
✨ feat: index page form 기능 (할 일 추가) 추가
Moon-ju-young Jun 27, 2025
4066164
✨ feat: index page getServerSideProps
Moon-ju-young Jun 27, 2025
cd888c7
✨ feat: index page 체크리스트 추가
Moon-ju-young Jun 27, 2025
c6939fd
✨ feat: index page handleSubmit에서 실시간 변동사항 반영하도록 수정
Moon-ju-young Jun 27, 2025
be5129b
💄 style: NanumSquare 웹폰트 import url 변경
Moon-ju-young Jun 27, 2025
366f91e
💄 style: Search component padding 수정
Moon-ju-young Jun 27, 2025
3f74429
✨ feat: index page CheckList key 추가
Moon-ju-young Jun 27, 2025
bba28a8
♻️ refactor: ResponseItems type 분리 및 이름 변경
Moon-ju-young Jun 27, 2025
b30d4f1
🐛 fix: PatchItem type property optional로 수정
Moon-ju-young Jun 27, 2025
9130eba
🐛 fix: ResponseItem 수정 (null type 추가)
Moon-ju-young Jun 27, 2025
ba0b78e
✨ feat: index page changeIsCompleted 함수 및 CheckList 기능 추가
Moon-ju-young Jun 27, 2025
b69225e
🐛 fix: index page CheckList 잘못된 prop 수정
Moon-ju-young Jun 27, 2025
0d5284a
✨ feat: index page emtpy 요소 추가
Moon-ju-young Jun 27, 2025
7303a2e
✨ feat: index.module.css 파일 추가 및 연결
Moon-ju-young Jun 27, 2025
5fa190f
💄 style: index page main 스타일링
Moon-ju-young Jun 27, 2025
f809b1f
💄 style: index page form 스타일링
Moon-ju-young Jun 27, 2025
1f41f2b
🐛 fix: empty_done 이미지 크기 수정
Moon-ju-young Jun 27, 2025
ef9d6b7
💄 style: index page Image 크기 설정
Moon-ju-young Jun 27, 2025
b84166e
💄 style: index page section 스타일링
Moon-ju-young Jun 27, 2025
a0d53e7
💄 style: index page empty div 스타일링
Moon-ju-young Jun 27, 2025
f2a38c9
🐛 fix: index page 잘못된 렌더링 오류 수정
Moon-ju-young Jun 28, 2025
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# vscode
/.vscode
3 changes: 3 additions & 0 deletions assets/icons/check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icons/checkbox_checked.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 assets/icons/checkbox_empty.svg
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
체크박스의 경우 해당 이미지 없이도 구현이 가능하니, html과 css만으로 구현하시는 것이 성능이나 유지보수 측면에서 더 좋을 것 같아요!

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icons/cross.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 assets/icons/edit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icons/plus_big.svg
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
svg로 추출하셨으니 이미지 하나를 가지고 코드를 통해 이미지의 크기나 색을 변경하셔서 사용하시는 것을 추천드려요!

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icons/plus_black.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icons/plus_white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/done.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/empty_done.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/empty_todo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/logo_text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/memo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/todo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 77 additions & 0 deletions components/Btn.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
button.btn {
position: relative;
height: 56px;
}

button.btn.large {
width: 168px;
}

button.btn.small {
width: 56px;
}

button.btn div {
position: absolute;
height: 52px;
border: 2px solid var(--slate900);
border-radius: 24px;
}

button.btn.large div {
width: 164.35px;
}

button.btn.small div {
width: 54.78px;
}

button.btn div.content {
top: 0;
left: 0;
display: flex;
background-color: var(--slate200);
color: var(--slate900);
line-height: 18px;
font-size: 16px;
font-weight: 700;
}

button.btn div.content.delete {
background-color: var(--rose500);
color: white;
}

button.btn:hover div.content.add {
background-color: var(--violet600);
color: white;
}

button.btn:hover div.content.edit {
background-color: var(--lime300);
}

button.btn.large div.content {
align-items: center;
gap: 4px;
justify-content: center;
}

button.btn.small div.content {
padding: 16px;
}

button.btn div.content.add img#light,
button.btn:hover div.content.add img#dark {
display: none;
}

button.btn:hover div.content.add img#light {
display: initial;
}

button.btn div.shadow {
bottom: 0;
right: 0;
background-color: var(--slate900);
}
55 changes: 55 additions & 0 deletions components/Btn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ButtonHTMLAttributes, useMemo } from "react";
import Image from "next/image";
import ic_plus_black from "@/assets/icons/plus_black.svg";
import ic_plus_white from "@/assets/icons/plus_white.svg";
import ic_cross from "@/assets/icons/cross.svg";
import ic_check from "@/assets/icons/check.svg";
import styles from "./Btn.module.css";

interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 여담
컴포넌트의 props 타입은 외부에서 참조해야 하는 경우가 종종 있습니다.
이러한 상황을 대비해 공통 컴포넌트들의 경우 interface를 export 해두는 것을 추천드립니다.

물론 아래처럼 export 되지 않은 prop를 참조할 수 있습니다.

type BtnProps = ComponentProps<typeof Btn>;

size?: "large" | "small";
mode: "add" | "delete" | "edit";
}

const CONTENT: Record<Props["mode"], string> = {
add: "추가하기",
delete: "삭제하기",
edit: "수정 완료",
};

export default function Btn({
className = "",
size = "large",
mode,
...props
}: Props) {
const img = useMemo(() => {
switch (mode) {
case "add":
return { alt: "plus", src: ic_plus_black };
case "delete":
return { alt: "cross", src: ic_cross };
case "edit":
return { alt: "check", src: ic_check };
}
}, [mode]);

return (
<button className={`${styles.btn} ${styles[size]} ${className}`} {...props}>
<div className={styles.shadow}></div>
<div className={`${styles.content} ${styles[mode]}`}>
<Image height={16} width={16} id={styles.dark} {...img} />
{mode === "add" && (
<Image
height={16}
width={16}
id={styles.light}
alt="plus"
src={ic_plus_white}
/>
)}
{size === "large" && CONTENT[mode]}
</div>
</button>
);
}
26 changes: 26 additions & 0 deletions components/CheckList.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.check-list {
display: flex;
align-items: center;
gap: 16px;
height: 50px;
padding: 0 12px;
border: 2px solid var(--slate900);
border-radius: 9999px;
color: var(--slate800);
line-height: 18px;
font-size: 16px;
font-weight: 400;
}

.check-list.true {
background-color: var(--violet100);
text-decoration: line-through 1px;
}

.check-list.false {
background-color: white;
}

.check-list button {
line-height: 0;
}
32 changes: 32 additions & 0 deletions components/CheckList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { HTMLAttributes, MouseEventHandler } from "react";
import Image from "next/image";
import ic_checked from "@/assets/icons/checkbox_checked.svg";
import ic_empty from "@/assets/icons//checkbox_empty.svg";
import styles from "./CheckList.module.css";

interface Props extends HTMLAttributes<HTMLDivElement> {
isChecked: boolean;
onButtonClick: MouseEventHandler<HTMLButtonElement>;
}

export default function CheckList({
className = "",
children,
isChecked,
onButtonClick,
...props
}: Props) {
return (
<div
className={`${styles["check-list"]} ${
styles[String(isChecked)]
} ${className}`}
{...props}
>
<button type="button" onClick={onButtonClick}>
<Image alt="checkbox" src={isChecked ? ic_checked : ic_empty} />
</button>
{children}
</div>
);
}
22 changes: 22 additions & 0 deletions components/Gnb.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
nav.gnb {
z-index: 20;
position: sticky;
top: 0;
left: 0;
right: 0;
height: 60px;
border-bottom: 1px solid var(--slate200);
background-color: white;
}

nav.gnb > div {
max-width: 1200px;
margin: 0 auto;
padding: 10px 24px 9px;
line-height: 0;
}

nav.gnb > div a {
display: inline-block;
line-height: 0;
}
16 changes: 16 additions & 0 deletions components/Gnb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Link from "next/link";
import Image from "next/image";
import logo from "@/assets/images/logo_text.png";
import styles from "./Gnb.module.css";

export default function Gnb() {
return (
<nav className={styles.gnb}>
<div>
<Link href="/">
<Image height={40} alt="logo" src={logo} />
</Link>
</div>
</nav>
);
}
35 changes: 35 additions & 0 deletions components/Search.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.search {
position: relative;
display: block;
height: 56px;
}

.search > * {
width: calc(100% - 4px);
height: 52.5px;
border: 2px solid var(--slate900);
border-radius: 24px;
}

.search > input {
position: absolute;
top: 0;
left: 0;
padding: 15px 22px;
background-color: var(--slate100);
color: var(--slate900);
line-height: 18px;
font-size: 16px;
font-weight: 400;
}

.search > input::placeholder {
color: var(--slate500);
}

.search > div {
position: absolute;
bottom: 0;
right: 0;
background-color: var(--slate900);
}
15 changes: 15 additions & 0 deletions components/Search.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { InputHTMLAttributes, Ref } from "react";
import styles from "./Search.module.css";

interface Props extends InputHTMLAttributes<HTMLInputElement> {
ref?: Ref<HTMLInputElement>;
}

export default function Search({ className = "", style, ...props }: Props) {
return (
<label className={`${styles.search} ${className}`} style={style}>
<div />
<input placeholder="할 일을 입력해주세요" {...props} />
</label>
);
}
62 changes: 62 additions & 0 deletions lib/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import axios from "axios";

const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
});

export type SimpleItem = {
isCompleted: boolean;
name: string;
id: number;
};

export type ResponseSimpleItems = SimpleItem[];

export type ResponseItem = {
isCompleted: boolean;
imageUrl: string | null;
memo: string | null;
name: string;
tenantId: string;
id: number;
};

export type ResponseDelete = {
message: string;
};

export type PostItem = {
name: string;
};

export type PatchItem = {
name?: string;
memo?: string;
imageUrl?: string;
isCompleted?: boolean;
};

export async function getItems() {
const response = await api.get<ResponseSimpleItems>("/items");
return response.data;
}

export async function getItem(itemId: number) {
const response = await api.get<ResponseItem>("/items/" + itemId);
return response.data;
}

export async function postItem(body: PostItem) {
const response = await api.post<ResponseItem>("/items", body);
return response.data;
}

export async function patchItem(itemId: number, body: PatchItem) {
const response = await api.patch<ResponseItem>("/items/" + itemId, body);
return response.data;
}

export async function deleteItem(itemId: number) {
const response = await api.delete<ResponseDelete>("/items/" + itemId);
return response.data;
}
Loading
Loading