-
Notifications
You must be signed in to change notification settings - Fork 20
Next 유선향 sprint10 #86
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
The head ref may contain hidden characters: "Next-\uC720\uC120\uD5A5-sprint10"
Changes from all commits
8a1f4ee
042579a
5c2de85
e9964c8
7c790ab
9d8d6bf
9d4c23e
39a70f7
453588c
a056187
2bea901
480e75b
61ea555
52bd6dd
0040ece
cdebe22
dcc1a02
623cc0c
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,16 +1,28 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import clsx from "clsx"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ReactNode } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface Props { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick: onClick; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick?: onClick; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. 또한, 해당 타입은 필요 없을 수도 있겠네요 !
Suggested change
(이어서) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| children: ReactNode; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| disabled?: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default function Button({ onClick, children, ...props }: Props) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default function Button({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| children, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| disabled, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...props | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }: Props) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={onClick} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className="flex bg-blue-500 justify-center items-center w-full h-full rounded-[8px] border-none font-Pretendard text-H5Bold text-gray-100 bg-light-blue cursor-pointer" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={clsx( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "flex bg-blue-500 justify-center items-center w-full h-full rounded-[8px] border-none font-Pretendard text-H5Bold text-gray-100 bg-light-blue cursor-pointer", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| disabled ? "bg-gray-400" : "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+10
to
+25
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. (이어서)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default function Button({ | |
| onClick, | |
| children, | |
| className, | |
| disabled, | |
| ...props | |
| }: Props) { | |
| return ( | |
| <> | |
| <button | |
| onClick={onClick} | |
| className="flex bg-blue-500 justify-center items-center w-full h-full rounded-[8px] border-none font-Pretendard text-H5Bold text-gray-100 bg-light-blue cursor-pointer" | |
| className={clsx( | |
| "flex bg-blue-500 justify-center items-center w-full h-full rounded-[8px] border-none font-Pretendard text-H5Bold text-gray-100 bg-light-blue cursor-pointer", | |
| disabled ? "bg-gray-400" : "", | |
| className | |
| )} | |
| export default function Button({ | |
| children, | |
| className, | |
| disabled, | |
| ...props | |
| }: Props) { | |
| return ( | |
| <> | |
| <button | |
| className={clsx( | |
| "flex bg-blue-500 justify-center items-center w-full h-full rounded-[8px] border-none font-Pretendard text-H5Bold text-gray-100 bg-light-blue cursor-pointer", | |
| disabled ? "bg-gray-400" : "", | |
| className | |
| )} |
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.
추가로 disabled도 지워볼 수 있을 것 같네요 !:
export default function Button({
children,
className,
...props
}: Props) {
return (
<>
<button
disabled={disabled}
className={clsx(
"flex bg-blue-500 justify-center items-center w-full h-full rounded-[8px] border-none font-Pretendard text-H5Bold text-gray-100 bg-light-blue cursor-pointer disabled:bg-gray-400", className
)}disabled를 버튼의 속성으로 넣게 되면 덩달아 접근성도 좋아지겠어요 !
또한, disabled를 상태 선택자를 통해서 스타일도 입힐 수 있구요 😊😊
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,11 +2,13 @@ import PlusIcon from "@/public/assets/icons/plusIcon.svg"; | |||||||||
| import DeleteIcon from "@/public/assets/icons/DeleteIcon.svg"; | ||||||||||
| import SearchIcon from "@/public/assets/icons/search.icon.svg"; | ||||||||||
| import Image from "next/image"; | ||||||||||
| import { ChangeEvent, useRef, useState } from "react"; | ||||||||||
| import { useRef, useState } from "react"; | ||||||||||
| import { uploadImage } from "@/lib/image"; | ||||||||||
| import { renameFile } from "@/hooks/useRenameFile"; | ||||||||||
| // | ||||||||||
|
|
||||||||||
| interface Props { | ||||||||||
| onChange: (e: ChangeEvent<HTMLInputElement>) => void; | ||||||||||
| onChange: (value: string) => void; | ||||||||||
| label?: string; | ||||||||||
| placeholder?: string; | ||||||||||
| name: string; | ||||||||||
|
|
@@ -17,8 +19,16 @@ interface Props { | |||||||||
| $edit?: boolean; | ||||||||||
| onKeyUp?: (e: React.KeyboardEvent<HTMLInputElement>) => void; | ||||||||||
| type?: "text" | "number"; | ||||||||||
| isAsterisk?: boolean; | ||||||||||
| } | ||||||||||
| export function Input({ onChange, type = "text", ...props }: Props) { | ||||||||||
|
|
||||||||||
| export function Input({ | ||||||||||
| onChange, | ||||||||||
| placeholder, | ||||||||||
| type = "text", | ||||||||||
| isAsterisk, | ||||||||||
| ...props | ||||||||||
| }: Props) { | ||||||||||
| const { label, onKeyUp, $edit, $textArea, $comment } = props; | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
|
|
@@ -28,6 +38,7 @@ export function Input({ onChange, type = "text", ...props }: Props) { | |||||||||
| $comment && "text-H5Bold" | ||||||||||
| } w-full h-[26px] font-Pretendard text-gray-800 text-H4Bold`} | ||||||||||
| > | ||||||||||
| {isAsterisk && <span>*</span>} | ||||||||||
| {label} | ||||||||||
| </div> | ||||||||||
| <input | ||||||||||
|
|
@@ -37,78 +48,89 @@ export function Input({ onChange, type = "text", ...props }: Props) { | |||||||||
| $edit && "text-H7Regular h-[80px]" | ||||||||||
| }relative w-full h-[56px] bg-gray-100 font-Pretendard text-H6Regular border-none rounded-xl text-gray-800 px-4 py-6 placeholder-gray-400 placeholder:text-H5Regular placeholder:absolute focus:outline-none`} | ||||||||||
| type={type} | ||||||||||
| onChange={onChange} | ||||||||||
| onChange={(e) => { | ||||||||||
| if (e.nativeEvent.composed) return onChange(e.target.value); | ||||||||||
| }} | ||||||||||
| onKeyUp={onKeyUp || undefined} | ||||||||||
| placeholder={placeholder} | ||||||||||
| /> | ||||||||||
| </div> | ||||||||||
| ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // | ||||||||||
| interface ImgProps extends Omit<Props, "onChange"> { | ||||||||||
| onChange: (value: File | string) => void; | ||||||||||
| onChange: (value: null | string) => void; | ||||||||||
| } | ||||||||||
| export function ImgInput({ onChange, ...props }: ImgProps) { | ||||||||||
| export function ImgInput({ onChange, label, ...props }: ImgProps) { | ||||||||||
| const imgRef = useRef<HTMLInputElement>(null); | ||||||||||
| const [imgPreview, setImgPreview] = useState<string>(""); | ||||||||||
|
|
||||||||||
| const handlePreviewImg = () => { | ||||||||||
| if (!imgRef.current || !imgRef.current.files?.length) return; | ||||||||||
| const file = imgRef.current.files[0]; | ||||||||||
|
|
||||||||||
| const renamedFile = renameFile(file); | ||||||||||
|
|
||||||||||
| const reader = new FileReader(); | ||||||||||
| reader.readAsDataURL(file); | ||||||||||
| reader.onloadend = () => { | ||||||||||
| reader.readAsDataURL(renamedFile); | ||||||||||
|
|
||||||||||
| reader.onloadend = async () => { | ||||||||||
| if (typeof reader.result === "string") { | ||||||||||
| setImgPreview(reader.result); | ||||||||||
| onChange(file); | ||||||||||
| const formattedImage = await uploadImage(renamedFile); | ||||||||||
| onChange(formattedImage); | ||||||||||
| } | ||||||||||
| }; | ||||||||||
| }; | ||||||||||
| // | ||||||||||
|
|
||||||||||
| const handleClickImgDelete = () => { | ||||||||||
| setImgPreview(""); | ||||||||||
| onChange(""); | ||||||||||
| onChange(null); | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <div className="flex gap-6 mobile:gap-[10px] "> | ||||||||||
| <div className="mobile:w-[168px] w-[282px] h-[282px] bg-gray-100 rounded-xl border-none text-gray-800"> | ||||||||||
| <input | ||||||||||
| className="relative w-full h-full bg-gray-100 font-Pretendard text-H6Regular border-none rounded-xl text-gray-800 px-4 py-6 | ||||||||||
| <div className="flex flex-col gap-6 mobile:gap-[10px] "> | ||||||||||
| <p className="text-[18px] font-Pretendard text-H4Bold">{label}</p> | ||||||||||
|
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.
|
||||||||||
| <p className="text-[18px] font-Pretendard text-H4Bold">{label}</p> | |
| <label htmlFor="fileUpload" className="text-[18px] font-Pretendard text-H4Bold"> | |
| {label} | |
| </label> |
혹은 이 텍스트가 진짜 단순한 스타일용 텍스트라면 도 괜찮아요. 하지만 입력 폼의 설명이나 타이틀 역할을 하고 있다면 <label>을 쓰는 걸 추천드려요!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,9 +3,22 @@ import pandaLogo from "@/public/assets/Logo/pandaLogo.svg"; | |
| import textLogo from "@/public/assets/Logo/textLogo.svg"; | ||
| import myLogo from "@/public/assets/icons/default.profile.icon.svg"; | ||
| import Image from "next/image"; | ||
| import useWindowSize from "@/hooks/useWindowSize"; | ||
| import { useEffect, useState } from "react"; | ||
| import Button from "./Button"; | ||
| import { signIn } from "@/lib/auth"; | ||
|
|
||
| export default function Nav() { | ||
| const device: string = useWindowSize(); | ||
| const [isLogin, setIsLogin] = useState(false); | ||
| useEffect(() => { | ||
| const hasAccessToken = Boolean(localStorage.getItem("accessToken")); | ||
| setIsLogin(hasAccessToken); | ||
| }, []); | ||
|
|
||
| const handleClickLogin = async () => { | ||
| await signIn(); | ||
| setIsLogin(true); | ||
| }; | ||
|
Comment on lines
+12
to
+20
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.
|
||
|
|
||
| return ( | ||
| <div className="fixed top-0 left-0 w-screen h-[70px] bg-white py-[10px] px-[200px] NavPadding:px-[24px] NavPadding:py-[10px] mobile:px-[15px] mobile:py-[15px] z-50"> | ||
| <div className="flex justify-between w-screen max-w-full "> | ||
|
|
@@ -27,19 +40,23 @@ export default function Nav() { | |
| /> | ||
| </div> | ||
| <div className="flex w-auto gap-7 mobile:gap-2 font-Pretendard text-H4Bold"> | ||
| <Link href="/docs">자유게시판</Link> | ||
| <Link href="/items">중고마켓</Link> | ||
| <Link href="/">자유게시판</Link> | ||
| <Link href="/">중고마켓</Link> | ||
| </div> | ||
| </div> | ||
| <Link href="/mypage"> | ||
| {!isLogin ? ( | ||
| <div className="w-[128px] h-12"> | ||
| <Button onClick={() => handleClickLogin()}>로그인</Button> | ||
| </div> | ||
| ) : ( | ||
| <Image | ||
| className="w-10 h-10" | ||
| src={myLogo} | ||
| alt="프로필 이미지" | ||
| width={40} | ||
| height={40} | ||
| /> | ||
| </Link> | ||
| )} | ||
| </div> | ||
| </div> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| import { KeyboardEvent, useState } from "react"; | ||
| import Profile from "../common/Profile"; | ||
| import { EditSelect } from "../Select"; | ||
| import { deleteArticleComment, editArticleComment } from "@/lib/comments.api"; | ||
|
|
||
| interface Props { | ||
| comment: Comment; | ||
| } | ||
| export default function Comment({ comment }: Props) { | ||
| const [isEdit, setIsEdit] = useState(false); | ||
| const [currentValue, setCurrentValue] = useState(comment.content); | ||
| const handleSelect = async (option: string) => { | ||
| switch (option) { | ||
| case "수정하기": { | ||
| setIsEdit(true); | ||
| break; | ||
| } | ||
| case "삭제하기": { | ||
| await deleteArticleComment(comment.id); | ||
| break; | ||
| } | ||
| } | ||
| }; | ||
| const handleChange = async (e: KeyboardEvent<HTMLInputElement>) => { | ||
| if (e.key === "Enter") { | ||
| await editArticleComment(comment.id, currentValue); | ||
| setCurrentValue(currentValue); | ||
| } | ||
| }; | ||
| return ( | ||
| <> | ||
| <div className="flex flex-col w-full gap-6 mb-3 h-fit"> | ||
| <div className="flex justify-between w-full"> | ||
| {isEdit ? ( | ||
| <input | ||
| className="w-full" | ||
| value={currentValue} | ||
| onChange={(e) => { | ||
| setCurrentValue(e.currentTarget.value); | ||
| }} | ||
| onKeyDown={(e) => handleChange(e)} | ||
| /> | ||
| ) : ( | ||
| <p>{currentValue}</p> | ||
| )} | ||
| <EditSelect onChange={(option) => handleSelect(option)} /> | ||
| </div> | ||
| <div> | ||
| <Profile isComment value={comment} /> | ||
| </div> | ||
| </div> | ||
| <div className="w-full h-px bg-gray-300" /> | ||
| </> | ||
| ); | ||
| } |
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.
(선택) 타입은 보통 파스칼 케이스로 사용하는게 일반적이예요 !
global.d.ts에서 위와 같이 명칭을 바꾸는건 어떨까요?