feat: 입고 장바구니 독립 페이지 (/pop/inbound/cart)

- InboundCartPage: cart_items DB 영속 저장, 탭 이동해도 유지
- 상단: 입고일자(날짜피커) + 창고(터치선택) + 입고번호(자동채번)
- 품목: 체크박스, 수량수정(키패드), 삭제, 포장정보
- 검사: 필수→완료필수, 비필수→패스버튼, 미완료시 확정차단
- 전량 입고 원칙: 불량 포함 전체 입고 (팀장 규칙)
- PurchaseInbound: 장바구니 아이콘→독립페이지 이동 (모달 제거)
This commit is contained in:
SeongHyun Kim
2026-04-01 21:46:22 +09:00
parent b6c1b08049
commit d20b65bd12
5 changed files with 1181 additions and 30 deletions

View File

@@ -0,0 +1,12 @@
"use client";
import { PopShell } from "@/components/pop/hardcoded";
import { InboundCartPage } from "@/components/pop/hardcoded/inbound/InboundCartPage";
export default function InboundCartRoute() {
return (
<PopShell showBanner={false} title="입고 장바구니">
<InboundCartPage />
</PopShell>
);
}

View File

@@ -1,12 +1,13 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { PopShell } from "@/components/pop/hardcoded";
import { PurchaseInbound } from "@/components/pop/hardcoded/inbound";
export default function PurchaseInboundPage() {
const router = useRouter();
const [cartCount, setCartCount] = useState(0);
const [openCart, setOpenCart] = useState(false);
return (
<PopShell
@@ -14,7 +15,7 @@ export default function PurchaseInboundPage() {
title="구매입고"
headerRight={
<button
onClick={() => setOpenCart(true)}
onClick={() => router.push("/pop/inbound/cart")}
className="relative w-11 h-11 rounded-xl bg-white/10 flex items-center justify-center text-white hover:bg-white/20 active:scale-95 transition-all"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24">
@@ -30,8 +31,6 @@ export default function PurchaseInboundPage() {
>
<PurchaseInbound
onCartCountChange={setCartCount}
externalCartOpen={openCart}
onExternalCartClose={() => setOpenCart(false)}
/>
</PopShell>
);

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ import React, { useState, useCallback, useEffect, useMemo, useRef } from "react"
import { useRouter } from "next/navigation";
import { apiClient } from "@/lib/api/client";
import { SupplierModal, type Supplier, matchChosung } from "./SupplierModal";
import { InboundCart, type CartItem } from "./InboundCart";
import type { CartItem } from "./InboundCart";
import { NumberPadModal, type PackageEntry } from "./NumberPadModal";
import { BarcodeScanModal } from "../common/BarcodeScanModal";
@@ -86,19 +86,14 @@ const DUMMY_ORDERS: PurchaseOrder[] = [
interface PurchaseInboundProps {
onCartCountChange?: (count: number) => void;
externalCartOpen?: boolean;
onExternalCartClose?: () => void;
}
export function PurchaseInbound({ onCartCountChange, externalCartOpen, onExternalCartClose }: PurchaseInboundProps = {}) {
export function PurchaseInbound({ onCartCountChange }: PurchaseInboundProps = {}) {
const router = useRouter();
/* State */
const [selectedSupplier, setSelectedSupplier] = useState<Supplier | null>(null);
const [supplierModalOpen, setSupplierModalOpen] = useState(false);
const [_cartOpen, _setCartOpen] = useState(false);
const cartOpen = externalCartOpen || _cartOpen;
const setCartOpen = (v: boolean) => { _setCartOpen(v); if (!v && onExternalCartClose) onExternalCartClose(); };
const [cartItems, _setCartItems] = useState<CartItem[]>([]);
const setCartItems: typeof _setCartItems = (val) => {
_setCartItems(val);
@@ -300,14 +295,13 @@ export function PurchaseInbound({ onCartCountChange, externalCartOpen, onExterna
/* Remove from cart (cancel) */
const handleRemoveFromCart = (id: string) => {
setCartItems((prev) => prev.filter((c) => c.id !== id));
};
/* Cart operations */
const handleUpdateCartQty = (id: string, qty: number) => {
setCartItems((prev) => prev.map((c) => c.id === id ? { ...c, inbound_qty: qty } : c));
};
const handleClearCart = () => {
setCartItems([]);
// Delete from cart_items DB (background)
apiClient.post("/pop/execute-action", {
tasks: [{ type: "cart-save" }],
cartChanges: {
toDelete: [id],
},
}).catch(() => {});
};
/* Search */
@@ -617,17 +611,6 @@ export function PurchaseInbound({ onCartCountChange, externalCartOpen, onExterna
onSelect={(s) => setSelectedSupplier(s)}
/>
<InboundCart
open={cartOpen}
onClose={() => setCartOpen(false)}
items={cartItems}
onUpdateQty={handleUpdateCartQty}
onRemove={handleRemoveFromCart}
onClear={handleClearCart}
supplierName={selectedSupplier?.customer_name}
onUpdateItems={setCartItems}
/>
<NumberPadModal
open={numpadOpen}
onClose={() => { setNumpadOpen(false); setNumpadTarget(null); }}

View File

@@ -5,3 +5,4 @@ export { InboundCart } from "./InboundCart";
export { NumberPadModal } from "./NumberPadModal";
export { PackagingModal } from "./PackagingModal";
export { InspectionModal } from "./InspectionModal";
export { InboundCartPage } from "./InboundCartPage";