| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- 'use client';
- import { useCallback, useEffect, useState } from 'react';
- import Link from 'next/link';
- import { Gamepad2, Ticket } from 'lucide-react';
- import { fetchApi } from '@/lib/utils/client';
- import Loading from '@/app/component/Loading';
- import Pagination from '@/app/component/Pagination';
- import NavTabs from '../navTabs';
- import type { InventoryGroupRow, InventoryGroupsResponse } from '@/types/store';
- const PER_PAGE = 24;
- function TypeBadgeCoupon()
- {
- return (
- <span
- title='쿠폰'
- aria-label='쿠폰'
- className='inline-flex items-center justify-center p-1 rounded bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300'
- >
- <Ticket className='size-3' />
- </span>
- );
- }
- export default function InventoryGroupsPage()
- {
- const [groups, setGroups] = useState<InventoryGroupRow[]>([]);
- const [total, setTotal] = useState(0);
- const [page, setPage] = useState(1);
- const [loading, setLoading] = useState(true);
- const load = useCallback(async () => {
- setLoading(true);
- const res = await fetchApi<InventoryGroupsResponse>(`/api/store/inventory/groups?page=${page}&perPage=${PER_PAGE}`, { silent: true });
- if (res.success && res.data) {
- setGroups(res.data.list);
- setTotal(res.data.total);
- }
- else {
- setGroups([]);
- setTotal(0);
- }
- setLoading(false);
- }, [page]);
- useEffect(() => {
- load();
- }, [load]);
- return (
- <>
- <NavTabs />
- <div className='mx-auto px-4 sm:px-8 pb-8'>
- <h1 className='text-2xl font-bold mb-1'>보관함</h1>
- <p className='text-sm text-neutral-500 mb-4'>구매한 쿠폰을 상품별로 확인하실 수 있습니다. 상품을 클릭하면 쿠폰 코드를 확인 / 관리할 수 있어요.</p>
- <div className='text-sm text-neutral-500 mb-3'>총 {total.toLocaleString()}종</div>
- {loading ? (
- <Loading />
- ) : groups.length === 0 ? (
- <div className='text-center py-20 text-neutral-500'>보관함이 비어있습니다.</div>
- ) : (
- <>
- <div className='grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4'>
- {groups.map((g) => {
- const allUsed = g.unusedCount === 0;
- return (
- <Link
- key={g.productID}
- href={`/inventory/${g.productID}`}
- className={`group block rounded-lg border border-neutral-200 dark:border-neutral-800 overflow-hidden hover:shadow-lg transition-shadow bg-white dark:bg-neutral-900 ${allUsed ? 'opacity-70' : ''}`}
- >
- <div className='aspect-square bg-neutral-100 dark:bg-neutral-800 overflow-hidden flex items-center justify-center relative'>
- {g.productThumbnail ? (
- // eslint-disable-next-line @next/next/no-img-element
- <img
- src={g.productThumbnail}
- alt={g.productName}
- className='w-full h-full max-w-[calc(100%/1.6)] object-scale-down group-hover:scale-105 transition-transform duration-300'
- />
- ) : (
- <span className='text-neutral-400 text-xs'>이미지 없음</span>
- )}
- {allUsed && (
- <div className='absolute inset-0 bg-black/50 flex items-center justify-center'>
- <span className='text-white text-sm font-bold tracking-widest'>사용 완료</span>
- </div>
- )}
- </div>
- <div className='p-3'>
- <div className='flex items-center gap-1.5 mb-1.5'>
- <TypeBadgeCoupon />
- <Gamepad2 className='size-3.5 shrink-0 text-purple-600 dark:text-purple-400' />
- <span className='text-xs font-semibold truncate text-purple-600 dark:text-purple-400' title={g.gameName}>
- {g.gameName}
- </span>
- </div>
- <div className='text-sm font-semibold mb-1.5 line-clamp-2 min-h-[1.6rem]' title={g.productName}>
- {g.productName}
- </div>
- <div className='text-lg font-extrabold text-red-600 dark:text-red-400'>
- {allUsed ? '사용 완료' : `잔여 ${g.unusedCount}장`}
- <span className='text-xs text-neutral-500 dark:text-neutral-400 font-medium ml-1'>
- / 총 {g.totalCount}장
- </span>
- </div>
- </div>
- </Link>
- );
- })}
- </div>
- <hr className='my-4 border-neutral-200 dark:border-neutral-800' />
- <Pagination total={total} page={page} perPage={PER_PAGE} onChange={setPage} />
- </>
- )}
- </div>
- </>
- );
- }
|