diff --git a/src/components/common/index.ts b/src/components/common/index.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/ui/table/Table.stories.tsx b/src/components/ui/table/Table.stories.tsx index 152e2e7..04c4e95 100644 --- a/src/components/ui/table/Table.stories.tsx +++ b/src/components/ui/table/Table.stories.tsx @@ -3,7 +3,140 @@ import { TableRowProps } from '@/components/ui/table/TableRowProps'; import { UserRole, UserType } from '@/types/user'; import { Meta, StoryObj } from '@storybook/nextjs'; import { useEffect, useState } from 'react'; -import { fetchTableData } from './testApi'; + +const fetchTableData = async (userRole: UserRole) => { + return new Promise<{ headers: string[]; data: unknown[] }>(resolve => { + setTimeout(() => { + if (userRole === 'employer') { + resolve({ + headers: ['신청자', '소개', '전화번호', '상태'], + data: [ + { + name: '김강현', + bio: '최선을 다해 열심히 일합니다. 다수의 업무 경험을 바탕으로 확실한 일처리 보여드리겠습니다.', + phone: '010-1234-5678', + status: 'pending', + }, + { + name: '서혜진', + bio: '열심히 하겠습니다!', + phone: '010-1111-2222', + status: 'rejected', + }, + { + name: '주진혁', + bio: '성실한 자세로 열심히 일합니다.', + phone: '010-3333-4444', + status: 'approved', + }, + { + name: '장민혁', + bio: '일을 꼼꼼하게 하는 성격입니다.', + phone: '010-5555-5555', + status: 'approved', + }, + { + name: '고기훈', + bio: '하루라도 최선을 다해서 일하겠습니다!', + phone: '010-6666-6666', + status: 'rejected', + }, + { + name: '최현수', + bio: '열심히 하겠습니다!', + phone: '010-1123-5448', + status: 'pending', + }, + { + name: '강주하', + bio: '성실한 자세로 열심히 일합니다.', + phone: '010-4123-2323', + status: 'approved', + }, + { + name: '배수지', + bio: '열심히 배우고 일하겠습니다!', + phone: '010-3123-1111', + status: 'approved', + }, + { + name: '강규하', + bio: '꼼꼼한 일처리 보여드리겠습니다.', + phone: '010-5123-0098', + status: 'rejected', + }, + { + name: '고선영', + bio: '최선을 다해서 일하겠습니다!', + phone: '010-6662-6326', + status: 'peding', + }, + { + name: '박하연', + bio: '뽑아주시면 열심히 하겠습니다.', + phone: '010-1277-1385', + status: 'pending', + }, + { + name: '김연아', + bio: '잘 부탁드립니다!', + phone: '010-1232-6216', + status: 'rejected', + }, + ], + }); + } else { + resolve({ + headers: ['가게', '일자', '시급', '상태'], + data: [ + { + name: '너구리네 라면집', + startsAt: '2025-10-01T11:00', + workhour: 2, + hourlyPay: '12,500원', + status: 'pending', + }, + { + name: '너구리네 라면집', + startsAt: '2025-10-01T11:00', + workhour: 2, + hourlyPay: '12,500원', + status: 'rejected', + }, + { + name: '너구리네 라면집', + startsAt: '2025-10-01T11:00', + workhour: 2, + hourlyPay: '12,500원', + status: 'approved', + }, + { + name: '너구리네 라면집', + startsAt: '2025-10-01T11:00', + workhour: 2, + hourlyPay: '12,500원', + status: 'rejected', + }, + { + name: '너구리네 라면집', + startsAt: '2025-10-01T11:00', + workhour: 2, + hourlyPay: '12,500원', + status: 'approved', + }, + { + name: '너구리네 라면집', + startsAt: '2025-10-01T11:00', + workhour: 2, + hourlyPay: '12,500원', + status: 'approved', + }, + ], + }); + } + }); + }); +}; const meta: Meta = { title: 'UI/Table', diff --git a/src/components/ui/table/testApi.tsx b/src/components/ui/table/testApi.tsx deleted file mode 100644 index 137c2c7..0000000 --- a/src/components/ui/table/testApi.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import type { UserRole } from '@/types/user'; - -export const fetchTableData = async (userRole: UserRole) => { - return new Promise<{ headers: string[]; data: unknown[] }>(resolve => { - setTimeout(() => { - if (userRole === 'employer') { - resolve({ - headers: ['신청자', '소개', '전화번호', '상태'], - data: [ - { - name: '김강현', - bio: '최선을 다해 열심히 일합니다. 다수의 업무 경험을 바탕으로 확실한 일처리 보여드리겠습니다.', - phone: '010-1234-5678', - status: 'pending', - }, - { - name: '서혜진', - bio: '열심히 하겠습니다!', - phone: '010-1111-2222', - status: 'rejected', - }, - { - name: '주진혁', - bio: '성실한 자세로 열심히 일합니다.', - phone: '010-3333-4444', - status: 'approved', - }, - { - name: '장민혁', - bio: '일을 꼼꼼하게 하는 성격입니다.', - phone: '010-5555-5555', - status: 'approved', - }, - { - name: '고기훈', - bio: '하루라도 최선을 다해서 일하겠습니다!', - phone: '010-6666-6666', - status: 'rejected', - }, - { - name: '최현수', - bio: '열심히 하겠습니다!', - phone: '010-1123-5448', - status: 'pending', - }, - { - name: '강주하', - bio: '성실한 자세로 열심히 일합니다.', - phone: '010-4123-2323', - status: 'approved', - }, - { - name: '배수지', - bio: '열심히 배우고 일하겠습니다!', - phone: '010-3123-1111', - status: 'approved', - }, - { - name: '강규하', - bio: '꼼꼼한 일처리 보여드리겠습니다.', - phone: '010-5123-0098', - status: 'rejected', - }, - { - name: '고선영', - bio: '최선을 다해서 일하겠습니다!', - phone: '010-6662-6326', - status: 'peding', - }, - { - name: '박하연', - bio: '뽑아주시면 열심히 하겠습니다.', - phone: '010-1277-1385', - status: 'pending', - }, - { - name: '김연아', - bio: '잘 부탁드립니다!', - phone: '010-1232-6216', - status: 'rejected', - }, - ], - }); - } else { - resolve({ - headers: ['가게', '일자', '시급', '상태'], - data: [ - { - name: '너구리네 라면집', - startsAt: '2025-10-01T11:00', - workhour: 2, - hourlyPay: '12,500원', - status: 'pending', - }, - { - name: '너구리네 라면집', - startsAt: '2025-10-01T11:00', - workhour: 2, - hourlyPay: '12,500원', - status: 'rejected', - }, - { - name: '너구리네 라면집', - startsAt: '2025-10-01T11:00', - workhour: 2, - hourlyPay: '12,500원', - status: 'approved', - }, - { - name: '너구리네 라면집', - startsAt: '2025-10-01T11:00', - workhour: 2, - hourlyPay: '12,500원', - status: 'rejected', - }, - { - name: '너구리네 라면집', - startsAt: '2025-10-01T11:00', - workhour: 2, - hourlyPay: '12,500원', - status: 'approved', - }, - { - name: '너구리네 라면집', - startsAt: '2025-10-01T11:00', - workhour: 2, - hourlyPay: '12,500원', - status: 'approved', - }, - ], - }); - } - }); - }); -}; diff --git a/src/context/appProviderWrapper.tsx b/src/context/appProviderWrapper.tsx index 31e47bf..3839620 100644 --- a/src/context/appProviderWrapper.tsx +++ b/src/context/appProviderWrapper.tsx @@ -1,6 +1,6 @@ import { ReactNode } from 'react'; import AuthProvider from './authProvider'; -import { ToastProvider } from './toastContext'; +import ToastProvider from './toastContext'; import { UserApplicationsProvider } from './userApplicationsProvider'; const AppProviderWrapper = ({ children }: { children: ReactNode }) => { diff --git a/src/context/mockAuthProvider/authRolePreview.tsx b/src/context/mockAuthProvider/authRolePreview.tsx deleted file mode 100644 index f2ba3bc..0000000 --- a/src/context/mockAuthProvider/authRolePreview.tsx +++ /dev/null @@ -1,38 +0,0 @@ -// import useAuth from '@/hooks/useAuth'; - -// export default function AuthRolePreview() { -// const { role, user } = useAuth(); - -// if (role === 'employer') { -// return ( -//
-//

사장님 전용 화면

-//

role === 'employer'

-//

-// {user?.name}님의 가게 관리 화면 -//

-//
-// ); -// } - -// if (role === 'employee') { -// return ( -//
-//

알바생 전용 화면

-//

role === 'employee'

-//

-// {user?.name}님의 프로필 화면 -//

-//
-// ); -// } - -// return ( -//
-//
-//

비로그인 상태 (게스트 UI)

-//

role === 'guest'

-//
-//
-// ); -// } diff --git a/src/context/mockAuthProvider/authState_stories.tsx b/src/context/mockAuthProvider/authState_stories.tsx deleted file mode 100644 index 5e2b00e..0000000 --- a/src/context/mockAuthProvider/authState_stories.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// // import type { User } from '@/types/user'; -// // import type { Meta, StoryObj } from '@storybook/react'; -// // import AuthRolePreview from './authRolePreview'; -// // import { MockAuthProvider } from './mockAuthProvider'; - -// // const employerUser: User = { -// // id: '1', -// // email: 'boss@test.com', -// // type: 'employer', -// // name: '김사장', -// // shop: { -// // item: { -// // id: 'shop-1', -// // name: '김사장 카페', -// // category: '카페', -// // address1: '서울', -// // address2: '101호', -// // description: '테스트 카페', -// // imageUrl: 'https://picsum.photos/200', -// // originalHourlyPay: 10000, -// // }, -// // }, -// // }; - -// // const employeeUser: User = { -// // id: '2', -// // email: 'part@test.com', -// // type: 'employee', -// // name: '이알바', -// // shop: null, -// // }; - -// // interface PlaygroundArgs { -// // role: 'guest' | 'employer' | 'employee'; -// // } - -// // const meta: Meta = { -// // title: 'Auth/AuthRolePreview', -// // component: AuthRolePreview, -// // tags: ['autodocs'], -// // argTypes: { -// // role: { -// // control: 'select', -// // options: ['guest', 'employer', 'employee'], -// // }, -// // }, -// // }; -// // export default meta; - -// // type Story = StoryObj; - -// // export const Playground: Story = { -// // args: { -// // role: 'guest', // ✅ 기본값 지정 -// // }, -// // decorators: [ -// // (Story, context) => { -// // const { role } = context.args as PlaygroundArgs; - -// // const user = role === 'employer' ? employerUser : role === 'employee' ? employeeUser : null; - -// // return ( -// // -// // -// // -// // ); -// // }, -// // ], -// // }; -// export default {}; diff --git a/src/context/mockAuthProvider/mockAuthProvider.tsx b/src/context/mockAuthProvider/mockAuthProvider.tsx deleted file mode 100644 index ff67e49..0000000 --- a/src/context/mockAuthProvider/mockAuthProvider.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// import { AuthContext } from '@/context/authProvider'; -// import type { User, UserRole } from '@/types/user'; -// import { ReactNode } from 'react'; - -// interface MockAuthProviderProps { -// user: User | null; -// role?: UserRole; // guest | employer | employee -// children: ReactNode; -// } - -// export const MockAuthProvider = ({ user, role, children }: MockAuthProviderProps) => { -// const value = { -// user, -// isPending: false, -// isLogin: role !== 'guest', -// role: role ?? (user ? user.type : 'guest'), -// login: async () => {}, -// logout: () => {}, -// signup: async () => {}, -// getUser: async () => {}, -// updateUser: async () => {}, -// }; - -// return {children}; -// }; diff --git a/src/context/toastContext/toastContext.tsx b/src/context/toastContext.tsx similarity index 100% rename from src/context/toastContext/toastContext.tsx rename to src/context/toastContext.tsx diff --git a/src/context/toastContext/index.ts b/src/context/toastContext/index.ts deleted file mode 100644 index 683120c..0000000 --- a/src/context/toastContext/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as ToastProvider } from './toastContext'; diff --git a/src/pages/notices/[shopId]/[noticeId]/index.tsx b/src/pages/notices/[shopId]/[noticeId]/index.tsx index bf59aeb..ef1894e 100644 --- a/src/pages/notices/[shopId]/[noticeId]/index.tsx +++ b/src/pages/notices/[shopId]/[noticeId]/index.tsx @@ -1,7 +1,7 @@ import { RecentNoticeList } from '@/components/features'; import { useRecentNotice } from '@/components/features/noticeList/hooks/useRecentNotice'; import { Button, Modal, Notice } from '@/components/ui'; -import { useToast } from '@/context/toastContext/toastContext'; +import { useToast } from '@/context/toastContext'; import { useUserApplications } from '@/context/userApplicationsProvider'; import useAuth from '@/hooks/useAuth'; import axiosInstance from '@/lib/axios'; diff --git a/src/pages/testAuth.tsx b/src/pages/testAuth.tsx deleted file mode 100644 index c63f9e8..0000000 --- a/src/pages/testAuth.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import useAuth from '@/hooks/useAuth'; -import axios from '@/lib/axios'; -import { useRouter } from 'next/router'; -import { useEffect, useState } from 'react'; - -export default function TestAuthPage() { - const { isLogin, user, getUser, logout, login } = useAuth(); - const router = useRouter(); - // 하이드레이션 에러 방지: 마운트 이후에만 localStorage 값을 렌더 - const [mounted, setMounted] = useState(false); - const [lsToken, setLsToken] = useState(''); - const [lsUserId, setLsUserId] = useState(''); - - // 폼 상태(테스트 계정) - const [email, setEmail] = useState('test.employee@example.com'); - const [password, setPassword] = useState('Passw0rd!'); - const [type, setType] = useState<'employee' | 'employer'>('employee'); - - const [notices, setNotices] = useState(null); - const [msg, setMsg] = useState(''); - const [loading, setLoading] = useState(false); - - // 마운트 후에만 localStorage 접근 - useEffect(() => { - setMounted(true); - if (typeof window !== 'undefined') { - setLsToken(localStorage.getItem('thejulge_token') ?? ''); - setLsUserId(localStorage.getItem('thejulge_user_id') ?? ''); - } - }, []); - - // 에러 메시지 안전 추출 - const pickErrorMessage = (e: unknown) => - (e as { response?: { data?: { message?: string } } })?.response?.data?.message || - (e instanceof Error ? e.message : '요청 실패'); - - // 1) 회원가입: POST /users (인터셉터가 Authorization 안 붙임) - const signup = async () => { - setLoading(true); - setMsg(''); - try { - const { data } = await axios.post<{ item?: unknown }>('/users', { - email, - password, - type, - }); - setMsg('회원가입 성공: ' + JSON.stringify(data?.item ?? data)); - } catch (e: unknown) { - setMsg('회원가입 실패: ' + pickErrorMessage(e)); - } finally { - setLoading(false); - } - }; - - // 2) 로그인: Provider의 login 사용 → /token(헤더 없이) → 저장 → /users/{id} 동기화 - const loginViaProvider = async () => { - setLoading(true); - setMsg(''); - try { - await login({ email, password }); - if (typeof window !== 'undefined') { - setLsToken(localStorage.getItem('thejulge_token') ?? ''); - setLsUserId(localStorage.getItem('thejulge_user_id') ?? ''); - } - setMsg('login() 성공: 토큰/ID 저장 및 user 동기화 완료'); - } catch (e: unknown) { - setMsg('login() 실패: ' + pickErrorMessage(e)); - } finally { - setLoading(false); - } - }; - - // 3) getUser(): 전역 user 재동기화(보호 API → 인터셉터가 헤더 자동 첨부) - const callGetUser = async () => { - setLoading(true); - setMsg(''); - try { - // await getUser(); - setMsg('getUser() 호출 성공: user 상태 갱신'); - } catch (e: unknown) { - setMsg('getUser() 실패: ' + pickErrorMessage(e)); - } finally { - setLoading(false); - } - }; - - // 4) /notices: 보호 API 예시 → Authorization 자동 첨부 확인 - const callNotices = async () => { - setLoading(true); - setMsg(''); - try { - const { data } = await axios.get('/notices', { - params: { limit: 1, _: Date.now() }, // 캐시 방지(선택) - }); - setNotices(data); - setMsg('/notices 호출 성공(네트워크 탭에서 Authorization 헤더 확인)'); - } catch (e: unknown) { - setMsg('/notices 실패: ' + pickErrorMessage(e)); - } finally { - setLoading(false); - } - }; - - // 5) 로그아웃: Provider 상태/스토리지 초기화 - const doLogout = () => { - logout(); - if (typeof window !== 'undefined') { - localStorage.removeItem('thejulge_token'); - localStorage.removeItem('thejulge_user_id'); - setLsToken(''); - setLsUserId(''); - } - setMsg('로그아웃 및 localStorage 초기화 완료'); - }; - - // 6) 저장소만 비우기(새로고침 시 로그아웃 효과) - const clearStorageOnly = () => { - if (typeof window !== 'undefined') { - localStorage.removeItem('thejulge_token'); - localStorage.removeItem('thejulge_user_id'); - setLsToken(''); - setLsUserId(''); - } - setMsg('localStorage만 비움(새로고침 시 로그아웃 효과)'); - }; - - return ( -
- -

Test Auth (임시 테스트 전용)

- -
-

현재 상태

-
isLogin: {String(isLogin)}
-
user: {user ? JSON.stringify(user, null, 2) : 'null'}
-
localStorage token: {mounted ? lsToken : ''}
-
localStorage userId: {mounted ? lsUserId : ''}
-
- -
-

테스트 계정

-
- ) => setEmail(e.target.value)} - /> - ) => setPassword(e.target.value)} - /> -
- - -
-
-
- -
- - - - - - -
- - {msg &&

{msg}

} - {loading &&

요청 중…

} - -
-

/notices 응답(샘플)

-
-          {notices ? JSON.stringify(notices, null, 2) : '아직 호출 안 함'}
-        
-
- - {/* 확인 포인트 */} -
-

확인 포인트

-
    -
  1. - 회원가입 → 로그인(login)localStorage에 token/userId 저장 -
  2. -
  3. - getUser() 클릭 시 전역 user 상태가 채워지는지 -
  4. -
  5. - /notices 호출 후 DevTools Network → Authorization: Bearer … 확인 -
  6. -
  7. - 로그아웃 시 localStorageuser 상태 초기화 -
  8. -
-
-
- ); -}