Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 31 additions & 1 deletion package-lock.json

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

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"lucide-react": "^0.525.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.7.0"
"react-router-dom": "^7.7.0",
"zustand": "^5.0.8"
},
"devDependencies": {
"@biomejs/biome": "^2.1.2",
Expand Down
63 changes: 30 additions & 33 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Route, Routes } from "react-router-dom";
import styles from "./App.module.css";
import { ChatWidget } from "./components/organisms";
import { MainTemplate } from "./components/templates";
import { AuthProvider } from "./contexts/AuthContext";
import { CategoryProvider } from "./contexts/CategoryContext";
import { ModalProvider } from "./contexts/ModalContext";
import { ToastProvider } from "./contexts/ToastContext";
Expand Down Expand Up @@ -55,39 +54,37 @@ export default function App() {
return (
<div className={styles.app}>
<ToastProvider>
<AuthProvider>
<CategoryProvider>
<ModalProvider>
<GlobalAppSetup />
<MainTemplate>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route path="/find-password" element={<FindPassword />} />
<Route path="/category/:cat" element={<Category />} />
<Route path="/products/:id" element={<ProductDetail />} />
<Route
path="/products/:id/inquiry"
element={<ProductInquiry />}
/>
<Route path="/cart" element={<Cart />} />
<Route path="/payment" element={<Payment />} />
<Route path="/mypage/:tab?" element={<Mypage />} />
</Routes>

<ChatWidget
isOpen={isChatOpen}
messages={messages}
newMessage={newMessage}
onToggle={() => setIsChatOpen(!isChatOpen)}
onChange={setNewMessage}
onSend={handleSendMessage}
<CategoryProvider>
<ModalProvider>
<GlobalAppSetup />
<MainTemplate>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route path="/find-password" element={<FindPassword />} />
<Route path="/category/:cat" element={<Category />} />
<Route path="/products/:id" element={<ProductDetail />} />
<Route
path="/products/:id/inquiry"
element={<ProductInquiry />}
/>
</MainTemplate>
</ModalProvider>
</CategoryProvider>
</AuthProvider>
<Route path="/cart" element={<Cart />} />
<Route path="/payment" element={<Payment />} />
<Route path="/mypage/:tab?" element={<Mypage />} />
</Routes>

<ChatWidget
isOpen={isChatOpen}
messages={messages}
newMessage={newMessage}
onToggle={() => setIsChatOpen(!isChatOpen)}
onChange={setNewMessage}
onSend={handleSendMessage}
/>
</MainTemplate>
</ModalProvider>
</CategoryProvider>
</ToastProvider>
</div>
);
Expand Down
6 changes: 6 additions & 0 deletions src/api/authApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,9 @@ export async function resetPassword(
const res = await api.post("/auth/password/reset", body);
return { message: res.data.message };
}

// 로그아웃 API 함수
export async function logout(): Promise<ApiSuccessMessage> {
const res = await api.post("/auth/logout");
return { message: res.data.message };
}
30 changes: 30 additions & 0 deletions src/components/molecules/UserNav/UserNav.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.container {
display: flex;
align-items: center;
gap: 1.5rem;
}

.navLink {
text-decoration: none;
color: var(--color-text);
font-size: 0.9rem;
font-weight: 500;
}

.navLink:hover {
text-decoration: underline;
}

.logoutButton {
border: none;
background-color: transparent;
color: var(--color-text);
font-size: 0.9rem;
font-weight: 500;
cursor: pointer;
padding: 0;
}

.logoutButton:hover {
text-decoration: underline;
}
21 changes: 21 additions & 0 deletions src/components/molecules/UserNav/UserNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useAuthStore } from "../../../store/authStore";
import { Button } from "../../atoms";
import styles from "./UserNav.module.css";

export default function UserNav() {
const { logout } = useAuthStore();

return (
<div className={styles.container}>
<a href="/mypage" className={styles.navLink}>
마이
</a>
<a href="/cart" className={styles.navLink}>
장바구니
</a>
<Button type="button" onClick={logout} className={styles.logoutButton}>
로그아웃
</Button>
</div>
);
}
1 change: 1 addition & 0 deletions src/components/molecules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ export { default as SearchBar } from "./SearchBar/SearchBar";
export { default as SidebarMenu } from "./SidebarMenu/SidebarMenu";
export { default as Table } from "./Table/Table";
export { default as UserMenu } from "./UserMenu/UserMenu";
export { default as UserNav } from "./UserNav/UserNav";
25 changes: 25 additions & 0 deletions src/components/organisms/Header/Header.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,28 @@
align-items: center;
gap: 1.5rem;
}

.navLink {
text-decoration: none;
color: var(--color-text);
font-size: 0.9rem;
font-weight: 500;
}

.navLink:hover {
text-decoration: underline;
}

.logoutButton {
border: none;
background-color: transparent;
color: var(--color-text);
font-size: 0.9rem;
font-weight: 500;
cursor: pointer;
padding: 0;
}

.logoutButton:hover {
text-decoration: underline;
}
36 changes: 7 additions & 29 deletions src/components/organisms/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { Heart, ShoppingCart } from "lucide-react";
import { CATEGORIES } from "../../../constants/categories";
import { useAuth } from "../../../contexts/AuthContext";
import { useAuthStore } from "../../../store/authStore";
import { Logo } from "../../atoms";
import {
AuthNav,
IconButton,
NavMenu,
SearchBar,
UserMenu,
} from "../../molecules";
import { AuthNav, NavMenu, SearchBar, UserNav } from "../../molecules";
import styles from "./Header.module.css";

type HeaderProps = {
Expand All @@ -24,7 +17,8 @@ export default function Header({
selectedCategory,
setSelectedCategory,
}: HeaderProps) {
const { isLoggedIn, user, wishlistCount, cartCount } = useAuth();
const { accessToken } = useAuthStore();
const isLoggedIn = !!accessToken;

return (
<header className={styles.header}>
Expand All @@ -38,25 +32,9 @@ export default function Header({
}
/>

{isLoggedIn ? (
<div className={styles.rightMenu}>
<UserMenu userName={user?.name ?? ""} />
<IconButton
icon={Heart}
size={20}
count={wishlistCount}
to="/mypage/wishlist"
/>
<IconButton
icon={ShoppingCart}
size={20}
count={cartCount}
to="/cart"
/>
</div>
) : (
<AuthNav />
)}
<div className={styles.rightMenu}>
{isLoggedIn ? <UserNav /> : <AuthNav />}
</div>
</div>

<NavMenu
Expand Down
50 changes: 0 additions & 50 deletions src/contexts/AuthContext.tsx

This file was deleted.

Loading