From 664bb18126f24656f009ea43d3535d48193d0b06 Mon Sep 17 00:00:00 2001 From: seoyiju <166982000+seoyiju@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:11:54 +0900 Subject: [PATCH 1/9] Update UserContext.tsx --- src/context/UserContext.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/context/UserContext.tsx b/src/context/UserContext.tsx index e5d3f14..bce8ec6 100644 --- a/src/context/UserContext.tsx +++ b/src/context/UserContext.tsx @@ -5,7 +5,9 @@ import { createContext, ReactNode, useContext, useState } from "react"; // User interface User { - name: string; + userId: string; + age: number; + phoneNumber: string; // age: number // 추가하고 싶은 속성들 ... } @@ -22,7 +24,7 @@ export const UserContext = createContext( // 2. Provider 생성 export const UserProvider = ({ children }: { children: ReactNode }) => { - const [user, setUser] = useState({ name: "" }); + const [user, setUser] = useState({ userId: "202302561", age: 22, phoneNumber: "010-1234-5678" }); return ( {children} @@ -35,7 +37,7 @@ export const useUser = () => { const context = useContext(UserContext); // 에러처리 if (!context) { - throw new Error("error"); + throw new Error("useUser must be used within a UserProvider"); } return context; }; From 329ecb46ab31d05aee81a18f1a2cff7766514b1c Mon Sep 17 00:00:00 2001 From: seoyiju <166982000+seoyiju@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:16:42 +0900 Subject: [PATCH 2/9] Update layout.tsx layout fix : wrap children --- src/app/layout.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..b06b326 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; +import { UserProvider } from "@/context/UserContext"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -27,7 +28,10 @@ export default function RootLayout({ - {children} + {/* childeren을 감싸줌 */} + + {children} + ); From a99614a167acc8fbe43fdf0950442d2563d7637c Mon Sep 17 00:00:00 2001 From: seoyiju <166982000+seoyiju@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:18:29 +0900 Subject: [PATCH 3/9] Update page.tsx implement Mypage using UserContext --- src/app/mypage/page.tsx | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/app/mypage/page.tsx b/src/app/mypage/page.tsx index 93b3ba9..0c8913e 100644 --- a/src/app/mypage/page.tsx +++ b/src/app/mypage/page.tsx @@ -1,14 +1,28 @@ -// 과제 1: 마이페이지 구현 +"use client"; + +import { useUser } from "@/context/UserContext"; +import Link from "next/link"; +import Header from "@/components/Header"; // 이미 있는 컴포넌트일 경우 + export default function MyPage() { - // 1.1. UserContext를 활용한 Mypage 구현 (UserContext에 아이디(userId: string), 나이(age: number), 핸드폰번호(phoneNumber: string) 추가) + const { user } = useUser(); return ( -
- {/* 1.2. Header Component를 재활용하여 Mypage Header 표기 (title: 마이페이지) */} -

마이페이지

- {/* Mypage 정보를 UserContext 활용하여 표시 (이름, 아이디, 나이, 핸드폰번호 모두 포함) */} +
+ {/* Header 재사용 */} +
+ + {/* 유저 정보 출력 */} +
+

아이디: {user.userId}

+

나이: {user.age}

+

전화번호: {user.phoneNumber}

+
- {/* 1.3. 홈으로 가기 버튼 구현(Link or Router 활용) */} + {/* 홈으로 가기 버튼 */} + + 홈으로 가기 +
); } From d4726f19fcc8fd08431c52e388ee7a6ad70b92f3 Mon Sep 17 00:00:00 2001 From: seoyiju <166982000+seoyiju@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:39:24 +0900 Subject: [PATCH 4/9] Update SearchInput.tsx autofocus --- src/component/search/SearchInput.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/component/search/SearchInput.tsx b/src/component/search/SearchInput.tsx index aea7294..1f3c422 100644 --- a/src/component/search/SearchInput.tsx +++ b/src/component/search/SearchInput.tsx @@ -1,8 +1,18 @@ "use client"; import { useSearch } from "@/context/SearchContext"; +import { useEffect, useRef } from "react"; export default function SearchInput() { const { query, setQuery, setResult } = useSearch(); + const inputRef = useRef(null); + + useEffect(() => { + inputRef.current?.focus(); + }, []); + + const handleInputChange = (e: React.ChangeEvent) => { + setQuery(e.target.value); + }; // 검색 기능 const search = async () => { @@ -18,14 +28,14 @@ export default function SearchInput() { } }; - // 2.2. SearchInput 컴포넌트가 최초 렌더링 될 때, input tag에 포커스 되는 기능 - const handleInputChange = () => {}; + // 과제 1-2-3: 페이지 최초 렌더링 시, input에 포커스 되는 기능 (useRef) return (
Date: Sun, 15 Jun 2025 21:47:57 +0900 Subject: [PATCH 5/9] Update page.tsx handleRemoveFromCart --- src/app/search/page.tsx | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx index c3b6212..14a4bff 100644 --- a/src/app/search/page.tsx +++ b/src/app/search/page.tsx @@ -1,29 +1,46 @@ "use client"; +import { useEffect, useState } from "react"; import Header from "../../component/layout/Header"; import Footer from "../../component/layout/Footer"; import SearchInput from "../../component/search/SearchInput"; import ProductCart from "../../component/shopping/ProductCart"; +import CartList from "../../components/shopping/CartList"; import { useUser } from "../../context/UserContext"; -import { useEffect } from "react"; import { useSearch } from "../../context/SearchContext"; export default function SearchHome() { const { user, setUser } = useUser(); const { result } = useSearch(); + const [cart, setCart] = useState<{ [productId: string]: number }>({}); + // 페이지 최초 렌더링 될 때, setUser로 이름 설정 useEffect(() => { // 학번 + 이름 형태로 작성 (ex. 2025***** 내이름 ) - setUser({ name: "" }); + setUser({ userId: "202302544", age: 22, phoneNumber: "010-1234-5678" }); }, []); + const handleRemoveFromCart = (id: string) => { + const newCart = Object.fromEntries( + Object.entries(cart).filter(([key]) => key !== id) + ); + setCart(newCart); + }; + return (
-
+
+ + {/* 장바구니 표시 */} +
); From 1e1fe2fd66e583c871fbeaaa5e78b195e2b8af09 Mon Sep 17 00:00:00 2001 From: seoyiju <166982000+seoyiju@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:51:40 +0900 Subject: [PATCH 6/9] Update CartList.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 결제버튼, localStorage저장 및 checkout 이동구현 --- src/component/shopping/CartList.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/component/shopping/CartList.tsx b/src/component/shopping/CartList.tsx index adc8745..6b81c9b 100644 --- a/src/component/shopping/CartList.tsx +++ b/src/component/shopping/CartList.tsx @@ -1,4 +1,5 @@ "use client"; +import { useRouter } from "next/navigation"; import { ProductItem } from "@/types/Product"; interface Props { @@ -8,6 +9,7 @@ interface Props { } export default function CartList({ cart, products, onRemove }: Props) { + const router = useRouter(); const cartItems = Object.entries(cart) .map(([id, quantity]) => { const product = products.find((p) => p.productId === id); @@ -21,7 +23,17 @@ export default function CartList({ cart, products, onRemove }: Props) { ); // 2.4 결제하기: "결제하기" 버튼을 클릭하면, 현재 장바구니에 담긴 상품을 확인해 **localStorage**에 저장 후, 결제완료(/checkout) 페이지로 이동한다. - const handleCheckout = () => {}; + const handleCheckout = () => { + const checkoutItems = cartItems.map(({ productId, title, lprice, quantity }) => ({ + productId, + title, + lprice, + quantity, + })); + + localStorage.setItem("checkoutItems", JSON.stringify(checkoutItems)); + router.push("/checkout"); + }; return (
From c15450bfe25eb455686ad545df67d8850d4db595 Mon Sep 17 00:00:00 2001 From: seoyiju <166982000+seoyiju@users.noreply.github.com> Date: Sun, 15 Jun 2025 22:00:23 +0900 Subject: [PATCH 7/9] Update ProductCart.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 장바구니 담기, 삭제, 조건부렌더링, 결제기능 --- src/component/shopping/ProductCart.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/component/shopping/ProductCart.tsx b/src/component/shopping/ProductCart.tsx index a66c2b3..ba32559 100644 --- a/src/component/shopping/ProductCart.tsx +++ b/src/component/shopping/ProductCart.tsx @@ -12,16 +12,24 @@ export default function ProductCart({ items }: { items: ProductItem[] }) { const handleAddToCart = (item: ProductItem, quantity: number) => { setCart((prev) => ({ ...prev, - [item.productId]: quantity, + [item.productId]: (prev[item.productId] || 0) + quantity, })); - localStorage.setItem(item.productId, quantity + ""); - localStorage.getItem(item.productId); + // localStorage.setItem(item.productId, quantity + ""); + // localStorage.getItem(item.productId); }; /* 과제 2-3: Cart 아이템 지우기 */ - const handleRemoveFromCart = () => {}; + const handleRemoveFromCart = (productId: string) => { + const newCart = { ...cart }; + delete newCart[productId]; + setCart(newCart); + }; + useEffect(() => { + setShowCart(Object.keys(cart).length > 0); + }, [cart]); + return (
{/* 상품 리스트 */} From afde97dc803adcc6eb10bdd2b663bb7e18a15d65 Mon Sep 17 00:00:00 2001 From: seoyiju <166982000+seoyiju@users.noreply.github.com> Date: Sun, 15 Jun 2025 22:03:01 +0900 Subject: [PATCH 8/9] Update page.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 결제완료페이지, 홈으로가기 --- src/app/checkout/page.tsx | 60 ++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/app/checkout/page.tsx b/src/app/checkout/page.tsx index 0d40153..f56e49e 100644 --- a/src/app/checkout/page.tsx +++ b/src/app/checkout/page.tsx @@ -1,21 +1,67 @@ // CheckoutPage -import { useState } from "react"; +"use client"; + +import { useEffect, useState } from "react"; +import { useRouter } from "next/navigation"; import { ProductItem } from "@/types/Product"; interface CheckoutItem { - product: ProductItem; + productId: string; + title: string; + lprice: string; quantity: number; } -// 과제 3 + +// 과제 3 export default function CheckoutPage() { const [items, setItems] = useState([]); - // 3.1. 결제하기 구현 + const router = useRouter(); + + // 3.1. 결제하기 구현: localStorage에서 불러오기 + useEffect(() => { + const data = localStorage.getItem("checkoutItems"); + if (data) { + setItems(JSON.parse(data)); + } + }, []); + + const total = items.reduce( + (sum, item) => sum + Number(item.lprice) * item.quantity, + 0 + ); + return (
-

✅ 결제가 완료되었습니다!

- {/* 3.1. 결제하기 구현 */} -
+

결제가 완료되었습니다!

+ + {/* 3.1. 결제 목록 렌더링 */} +
    + {items.map((item) => ( +
  • +

    +

    + 수량: {item.quantity}개 / 개당 {Number(item.lprice).toLocaleString()}원 +

    +

    + 소계: {(Number(item.lprice) * item.quantity).toLocaleString()}원 +

    +
  • + ))} +
+ +
+ 총 합계: {total.toLocaleString()}원 +
+ {/* 3.2. 홈으로 가기 버튼 구현 */} +
+ +
); } From 8a1cca8305204ad61288f1f8f92d36056d2fd1ab Mon Sep 17 00:00:00 2001 From: seoyiju <166982000+seoyiju@users.noreply.github.com> Date: Sun, 15 Jun 2025 22:08:03 +0900 Subject: [PATCH 9/9] Update page.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 홈가기 --- src/app/mypage/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/mypage/page.tsx b/src/app/mypage/page.tsx index 0c8913e..f1e532a 100644 --- a/src/app/mypage/page.tsx +++ b/src/app/mypage/page.tsx @@ -2,7 +2,7 @@ import { useUser } from "@/context/UserContext"; import Link from "next/link"; -import Header from "@/components/Header"; // 이미 있는 컴포넌트일 경우 +import Header from "@/components/layout/Header"; // 이미 있는 컴포넌트일 경우 export default function MyPage() { const { user } = useUser(); @@ -20,7 +20,7 @@ export default function MyPage() {
{/* 홈으로 가기 버튼 */} - + 홈으로 가기