'use client'; import { useCallback, useEffect, useMemo, useState } from 'react'; import Link from 'next/link'; import { Search } from 'lucide-react'; import { fetchApi, getDateTime } from '@/lib/utils/client'; import Loading from '@/app/component/Loading'; import Pagination from '@/app/component/Pagination'; import NavTabs from '../navTabs'; import { ORDER_STATUS_LABEL, SHIPMENT_STATUS_LABEL, type OrderListResponse, type OrderListRow, type OrderStatus } from '@/types/store'; const PER_PAGE = 20; type FilterMode = 'recent6m' | number; function statusBadgeClass(status: OrderStatus): string { if (status === 5) { return 'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300'; } if (status === 6) { return 'bg-neutral-200 text-neutral-700 dark:bg-neutral-700 dark:text-neutral-300'; } if (status === 7 || status === 8) { return 'bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300'; } return 'bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300'; } export default function OrdersPage() { const [orders, setOrders] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [loading, setLoading] = useState(true); const [filterMode, setFilterMode] = useState('recent6m'); const [keywordInput, setKeywordInput] = useState(''); const [appliedKeyword, setAppliedKeyword] = useState(''); const yearChips = useMemo(() => { const current = new Date().getFullYear(); return Array.from({ length: 6 }, (_, i) => current - i); }, []); const load = useCallback(async () => { setLoading(true); const params = new URLSearchParams(); params.set('page', String(page)); params.set('perPage', String(PER_PAGE)); if (typeof filterMode === 'number') { params.set('year', String(filterMode)); } if (appliedKeyword) { params.set('keyword', appliedKeyword); } const res = await fetchApi(`/api/store/orders?${params.toString()}`, { silent: true }); if (res.success && res.data) { setOrders(res.data.list); setTotal(res.data.total); } else { setOrders([]); setTotal(0); } setLoading(false); }, [filterMode, appliedKeyword, page]); useEffect(() => { load(); }, [load]); useEffect(() => { setPage(1); }, [filterMode, appliedKeyword]); const handleSearch = () => { setAppliedKeyword(keywordInput.trim()); }; const handleKeywordKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault(); handleSearch(); } }; const handleChipClick = (mode: FilterMode) => { setFilterMode(mode); }; const chipClass = (active: boolean): string => active ? 'border border-blue-600 bg-blue-600 text-white' : 'border border-neutral-300 text-neutral-700 hover:bg-neutral-50 dark:border-neutral-700 dark:text-neutral-300 dark:hover:bg-neutral-800'; return ( <>

주문목록

{/* 상품 검색 */}
{ setKeywordInput(e.target.value); }} onKeyDown={handleKeywordKeyDown} placeholder="주문한 상품을 검색할 수 있어요!" className="w-full border border-neutral-300 dark:border-neutral-700 rounded-md px-4 py-2.5 pr-10 text-sm bg-white dark:bg-neutral-900" maxLength={100} />
{/* 기간 필터 칩 */}
{yearChips.map((y) => ( ))}
총 {total.toLocaleString()}건
{loading ? ( ) : orders.length === 0 ? (
주문 내역이 없습니다.
) : ( <>
{orders.map((o) => (
{o.orderNumber}
{ORDER_STATUS_LABEL[o.status]} {o.shipmentStatus !== null && o.shipmentStatus !== undefined && ( 배송 {SHIPMENT_STATUS_LABEL[o.shipmentStatus]} )} {o.hasActiveRefundRequest && ( 환불 요청 진행중 )}
{o.firstItemThumbnail ? ( // eslint-disable-next-line @next/next/no-img-element ) : ( no img )}
{o.firstItemName} {o.itemCount > 1 && 외 {o.itemCount - 1}건}
총 {o.itemCount}개 상품 {o.channelName && • 후원 {o.channelName}}
주문 {getDateTime(o.createdAt)}
결제 금액
{o.totalAmount.toLocaleString()}P
))}
)}
); }