Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3984e27
chore: ts 설정 추가
626-ju Jul 7, 2025
1bbd3b5
feat: 미션 1-4 추론되지 않는 타입 추가하기
Jul 8, 2025
9313a6d
refactor: FormValues 인덱스 시그니처로 정의
Jul 8, 2025
9f3c1db
refactor: useValidate(지금은 사용x)도 타입스크립트로 바꿔보기
Jul 8, 2025
6b75205
refactor: useValidator.ts 위주 리팩토링
626-ju Jul 9, 2025
84dcde2
refactor: 미션1-4 clsx사용해보기
626-ju Jul 9, 2025
eb05a66
fix: useFormState(RHF)에서 추론 이상하게 하는 거 수정
626-ju Jul 9, 2025
e67d8ad
refactor: useFormState에 제네릭 단언하지말고 infer로 찾아서 넣어주기
626-ju Jul 9, 2025
bd67dc1
refactor: inferredT -> InferredT로 이름 변경
626-ju Jul 9, 2025
4f1cf3b
chore: 설명 주석 추가
626-ju Jul 10, 2025
f341598
chore: 주석 수정
626-ju Jul 10, 2025
91fb445
chore: 주석 수정
626-ju Jul 10, 2025
2a08e50
refactor: useValidate.ts(안쓰는파일) key:string말고 InputName으로
626-ju Jul 10, 2025
32f81a1
fix: useValidate.ts 이상한 부분 수정
626-ju Jul 10, 2025
f775b03
chore: 주석 추가
626-ju Jul 10, 2025
e98b529
fix: useValidate.ts수정
626-ju Jul 11, 2025
32dafd3
refactor: prop으로 넘겨주는 비밀번호확인 함수 제거+
626-ju Jul 11, 2025
025fb7f
chore:불필요한 주석 제거
626-ju Jul 11, 2025
3d4f8d6
refactor(mentor): 타입 직관적으로 사용하기(useValidate.ts)
626-ju Jul 11, 2025
1bd46ab
refactor(mentor): inferredT 꼭 필요한지 다시 생각하기
626-ju Jul 11, 2025
b65c5c2
refactor(mentor): RHF에 zod스키마,리졸버 적용+
Jul 12, 2025
13347ac
chore: 불필요한 주석 삭제
Jul 12, 2025
4d84617
refactor: 불필요한 제네릭제거
626-ju Jul 12, 2025
d91ece5
refactor: 미션7 useOutsideClick 분리하기
626-ju Jul 14, 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
68 changes: 68 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@
"format": "prettier --write \"src/**/*.{js,jsx,css,json}\""
},
"dependencies": {
"@hookform/resolvers": "^5.1.1",
"clsx": "^2.1.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.59.0",
"react-router-dom": "^7.6.0",
"sass": "^1.88.0",
"styled-components": "^6.1.18",
"zod": "^4.0.5",
"zustand": "^5.0.5"
},
"devDependencies": {
"@eslint/js": "^9.25.0",
"@types/node": "^24.0.10",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@vitejs/plugin-react": "^4.4.1",
Expand All @@ -35,6 +39,7 @@
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^16.0.0",
"prettier": "^3.5.3",
"typescript": "^5.8.3",
"vite": "^6.3.5"
}
}
6 changes: 3 additions & 3 deletions src/App.jsx → src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Header from './components/Header/Header';
import AddItem from './pages/AddItem/AddItem';
import AddItem from './pages/AddItem/AddItem.jsx';
import Login from './pages/Auth/Login';
import SignUp from './pages/Auth/SignUp';
import Home from './pages/Home/Home';
import Items from './pages/Items/Items';
import ProductDetail from './pages/ProductDetail/ProductDetail';
import Items from './pages/Items/Items.jsx';
import ProductDetail from './pages/ProductDetail/ProductDetail.jsx';
import './styles/reset.css';
import './styles/global.css';
import './App.css';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import HeaderAuth from './HeaderAuth';
import Navigations from './Navigations';

function Header() {
const [isLoggedIn] = useState(sessionStorage.getItem('loggedIn'));
const [isLoggedIn] = useState(!!sessionStorage.getItem('loggedIn'));

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import userImg from '@assets/icon/ic_user.png';
import styles from '@styles/Header.module.css';
import { Link } from 'react-router-dom';

function HeaderAuth({ isLoggedIn }) {
interface Props {
isLoggedIn: boolean;
}

function HeaderAuth({ isLoggedIn }: Props) {
return (
<>
{isLoggedIn ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import styles from '@styles/Header.module.css';
import { Link, NavLink, useLocation } from 'react-router-dom';
import clsx from 'clsx';

function Navigations() {
const location = useLocation();
Expand All @@ -9,10 +10,10 @@ function Navigations() {

return (
<div className={styles.navCategory}>
<Link>자유게시판</Link>
<Link to={'/'}>자유게시판</Link>
<NavLink
to="/items"
className={() => (isMarketLocation ? `${styles.isActive}` : null)}
className={clsx({ [styles.isActive]: isMarketLocation })}
>
중고마켓
</NavLink>
Expand Down
23 changes: 9 additions & 14 deletions src/components/KebabMenu.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect, useRef, useState } from 'react';
import { useRef, useState } from 'react';
import kebabIcon from '@assets/icon/ic_kebab.png';
import useOutsideClick from '../hooks/useOutsideClick';
import styles from '../styles/KebabMenu.module.css';

function makeHtmlAttr(selector) {
Expand All @@ -24,28 +25,22 @@ function KebabMenu({ dropdownList, onSelect = () => {} }) {
setIsOpen(false);
}

useEffect(() => {
function closeDropDown(e) {
if (!kebabRef.current.contains(e.target)) {
setIsOpen(false);
}
}

window.addEventListener('click', closeDropDown);
function onCloseDropdown() {
setIsOpen(false);
}

return () => window.removeEventListener('click', closeDropDown);
}, []);
useOutsideClick(kebabRef, onCloseDropdown);

return (
<div className={styles.kebab}>
<button ref={kebabRef} onClick={handleToggleDropDown}>
<div className={styles.kebab} ref={kebabRef}>
<button onClick={handleToggleDropDown}>
<img src={kebabIcon} alt="케밥 아이콘" />
</button>
{isOpen && (
<ul role="listbox">
{dropdownList?.map((selector) => (
<li
key={`${selector}`}
key={selector}
{...makeHtmlAttr(selector)}
onClick={() => handleClick(selector)}
>
Expand Down
File renamed without changes.
17 changes: 17 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
declare module '*.png';

declare module '*.module.css' {
const classes: { [key: string]: string };
export default classes;
}

declare module '*.css' {
const classes: { [key: string]: string };
export default classes;
}

declare module '*.jsx' {
import * as React from 'react';
const component: React.FC<any>;
export default component;
}
17 changes: 17 additions & 0 deletions src/hooks/useOutsideClick.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useEffect } from 'react';

function useOutsideClick(ref, onCloseDropdown) {
useEffect(() => {
function closeDropdownHandler(e) {
if (ref.current && !ref.current.contains(e.target)) {
onCloseDropdown();
}
}

window.addEventListener('click', closeDropdownHandler);

return () => window.removeEventListener('click', closeDropdownHandler);
}, [ref, onCloseDropdown]);
}

export default useOutsideClick;
Loading
Loading