-
Notifications
You must be signed in to change notification settings - Fork 79
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
[김지윤] Sprint10 #650
The head ref may contain hidden characters: "Next.js-\uAE40\uC9C0\uC724-sprint10"
[김지윤] Sprint10 #650
Changes from all commits
93a0e93
b2e37bd
6f8bbb0
e11e25f
212e864
4dc5dd0
d4ef766
62264ef
39bbe6f
8b8561b
53b529b
34bb0f0
f4168b6
76bffb7
55b315c
c8ce65a
2501aef
0156895
84019f0
7be262b
2daaa19
f9d91dc
de37216
d05224c
74d5960
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 |
---|---|---|
|
@@ -2,8 +2,6 @@ | |
|
||
by NextJS & TypeScript | ||
|
||
<br/> | ||
|
||
## 프로젝트 구조 (`src/`) | ||
|
||
- `components/` : 전역으로 쓰이는 UI 컴포넌트 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,17 @@ | ||
@import "@/src/styles/_mixin"; | ||
@import "@/src/styles/_colors"; | ||
|
||
.button { | ||
@include font-style(16px, 600, var(--white)); | ||
@include font-style(16px, 600, $white); | ||
padding: 12px 24px; | ||
background-color: var(--blue); | ||
background-color: $blue; | ||
border-radius: 5px; | ||
width: max-content; | ||
cursor: pointer; | ||
|
||
transition: background-color 0.3s ease; | ||
|
||
&:hover { | ||
background-color: #0056b3; | ||
background-color: $dark-blue; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import React, { useState } from "react"; | ||
import React, { useState, useEffect, useCallback } from "react"; | ||
import Image from "next/image"; | ||
import styles from "./SearchBar.module.scss"; | ||
import searchIcon from "@/public/svgs/search.svg"; | ||
|
@@ -9,6 +9,25 @@ interface SearchBarProps { | |
|
||
const SearchBar: React.FC<SearchBarProps> = ({ keyword }) => { | ||
const [searchTerm, setSearchTerm] = useState(""); | ||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(""); | ||
|
||
// 디바운싱을 위한 useEffect | ||
useEffect(() => { | ||
const timer = setTimeout(() => { | ||
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. goood 💯 바로 디바운싱을 검색에 적용하셨다니! 아주 적절하게 디바운싱을 잘 사용하셨습니다 👍 |
||
setDebouncedSearchTerm(searchTerm); | ||
}, 2000); // 2초 딜레이가 지난 후 조회 API 호출 | ||
|
||
return () => { | ||
clearTimeout(timer); | ||
}; | ||
}, [searchTerm]); | ||
|
||
// 디바운싱된 검색어가 변경될 때 keyword 함수 호출 | ||
useEffect(() => { | ||
if (debouncedSearchTerm) { | ||
keyword(debouncedSearchTerm); | ||
} | ||
}, [debouncedSearchTerm, keyword]); | ||
|
||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
setSearchTerm(e.target.value); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
@import "@/src/styles/_mixin"; | ||
@import "@/src/styles/_colors"; | ||
|
||
.container { | ||
width: 100%; | ||
display: flex; | ||
flex-direction: column; | ||
margin: 64px 0 24px; | ||
gap: 16px; | ||
} | ||
|
||
.sectionTitle { | ||
@include font-style(16px, 600, $grey-900); | ||
cursor: default; | ||
} | ||
|
||
.commentContainer { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: flex-end; | ||
gap: 16px; | ||
} | ||
|
||
.commentInput { | ||
width: 100%; | ||
resize: none; | ||
background-color: $grey-100; | ||
border-radius: 12px; | ||
padding: 16px 24px; | ||
height: 104px; | ||
|
||
&:focus { | ||
outline: none; | ||
} | ||
|
||
&::placeholder { | ||
color: $grey-400; | ||
font-size: 16px; | ||
} | ||
} | ||
|
||
.submitButton { | ||
@include font-style(16px, 600, $white); | ||
padding: 12px 24px; | ||
background-color: $blue; | ||
border-radius: 8px; | ||
width: max-content; | ||
cursor: pointer; | ||
|
||
transition: background-color 0.3s ease; | ||
|
||
&:hover { | ||
background-color: $dark-blue; | ||
} | ||
|
||
&:disabled { | ||
background-color: $grey-400; | ||
cursor: not-allowed; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { useRouter } from "next/router"; | ||
import { useState } from "react"; | ||
import axios from "@/src/lib/axios"; | ||
import Spinner from "@/src/components/Spinner/Spinner"; | ||
|
||
import styles from "./AddComment.module.scss"; | ||
|
||
export default function AddComment() { | ||
const router = useRouter(); | ||
const { id } = router.query; | ||
const url = `/articles/${id}/comments`; | ||
|
||
const [comment, setComment] = useState<string>(""); | ||
const [isLoading, setIsLoading] = useState<boolean>(false); | ||
const [error, setError] = useState<string | null>(null); | ||
|
||
const handleSubmit = async (e: React.FormEvent) => { | ||
e.preventDefault(); | ||
setIsLoading(true); | ||
setError(null); | ||
|
||
try { | ||
await axios.post(url, { content: comment }); | ||
setComment(""); // 댓글이 성공적으로 추가된 후 input값 리셋 | ||
} catch (err) { | ||
setError("댓글을 작성할 수 없습니다."); | ||
} finally { | ||
setIsLoading(false); | ||
} | ||
}; | ||
|
||
// 버튼 활성화 여부 확인 | ||
const isButtonDisabled = comment.trim() === "" || isLoading; | ||
|
||
return ( | ||
<div className={styles.container}> | ||
<div className={styles.sectionTitle}>댓글 달기</div> | ||
<form onSubmit={handleSubmit} className={styles.commentContainer}> | ||
<textarea | ||
className={styles.commentInput} | ||
value={comment} | ||
onChange={(e) => setComment(e.target.value)} | ||
placeholder="댓글을 입력해주세요." | ||
required | ||
/> | ||
{isLoading ? ( | ||
<Spinner /> | ||
) : ( | ||
<button | ||
className={styles.submitButton} | ||
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. 이제 여기서 button이 disabled한 상태일때 css를 수정해주고 싶을 수 있어요 |
||
type="submit" | ||
disabled={isButtonDisabled} // 버튼 활성화 여부 설정 | ||
> | ||
등록 | ||
</button> | ||
)} | ||
{error && <div>{error}</div>} | ||
</form> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
@import "@/src/styles/_mixin"; | ||
@import "@/src/styles/_colors"; | ||
|
||
.container { | ||
width: 100%; | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: center; | ||
gap: 16px; | ||
} | ||
|
||
.titleSection { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
|
||
.title { | ||
@include font-style(20px, 700, $grey-800); | ||
} | ||
} | ||
|
||
.writerSection { | ||
display: flex; | ||
align-items: center; | ||
gap: 8px; | ||
cursor: default; | ||
|
||
.nickname { | ||
@include font-style(14px, 400, $grey-600); | ||
} | ||
|
||
.date { | ||
@include font-style(12px, 400, $grey-600); | ||
} | ||
|
||
.vectorBar { | ||
@include font-style(24px, 200, $grey-200); | ||
margin: 0 8px; | ||
} | ||
|
||
.likeCount { | ||
@include font-style(14px, 400, $grey-500); | ||
display: flex; | ||
align-items: center; | ||
gap: 4px; | ||
} | ||
} | ||
|
||
.hr { | ||
border: 1px solid $grey-200; | ||
} | ||
|
||
.contentSection { | ||
display: flex; | ||
flex-direction: column; | ||
gap: 20px; | ||
|
||
.content { | ||
@include font-style(16px, 400, $grey-800); | ||
} | ||
} |
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.
오! 점점 scss를 잘 활용하고 계시는데요 👍