import { useState, useMemo } from "react"; import PageHeader from "@/components/common/PageHeader"; import SearchInput from "@/components/common/SearchInput"; import FilterDropdown from "@/components/common/FilterDropdown"; import DateRangeInput from "@/components/common/DateRangeInput"; import FilterResetButton from "@/components/common/FilterResetButton"; import Pagination from "@/components/common/Pagination"; import EmptyState from "@/components/common/EmptyState"; import StatusBadge from "@/components/common/StatusBadge"; import CopyButton from "@/components/common/CopyButton"; import HistorySlidePanel from "../components/HistorySlidePanel"; import { formatNumber } from "@/utils/format"; import { SERVICE_FILTER_OPTIONS, STATUS_FILTER_OPTIONS, MOCK_SEND_HISTORY, } from "../types"; import type { SendHistory } from "../types"; const PAGE_SIZE = 10; const COLUMNS = [ "발송 ID", "템플릿명", "발송 시간", "대상 수", "성공", "실패", "오픈율", "상태", ]; /** 상태 → StatusBadge variant 매핑 */ function getStatusVariant(status: string): "success" | "info" | "error" { if (status === "완료") return "success"; if (status === "진행") return "info"; return "error"; } /** 오늘 날짜 YYYY-MM-DD */ function getToday() { return new Date().toISOString().slice(0, 10); } /** 1달 전 날짜 */ function getOneMonthAgo() { const d = new Date(); d.setMonth(d.getMonth() - 1); return d.toISOString().slice(0, 10); } export default function StatisticsHistoryPage() { // 필터 입력 상태 const [search, setSearch] = useState(""); const [serviceFilter, setServiceFilter] = useState("전체 서비스"); const [statusFilter, setStatusFilter] = useState("전체"); const [dateStart, setDateStart] = useState(getOneMonthAgo); const [dateEnd, setDateEnd] = useState(getToday); const [currentPage, setCurrentPage] = useState(1); const [loading, setLoading] = useState(false); // 적용된 필터 const [appliedSearch, setAppliedSearch] = useState(""); const [appliedService, setAppliedService] = useState("전체 서비스"); const [appliedStatus, setAppliedStatus] = useState("전체"); // 슬라이드 패널 const [panelOpen, setPanelOpen] = useState(false); const [selectedHistory, setSelectedHistory] = useState(null); // 조회 const handleQuery = () => { setLoading(true); setTimeout(() => { setAppliedSearch(search); setAppliedService(serviceFilter); setAppliedStatus(statusFilter); setCurrentPage(1); setLoading(false); }, 400); }; // 필터 초기화 const handleReset = () => { setSearch(""); setServiceFilter("전체 서비스"); setStatusFilter("전체"); setDateStart(getOneMonthAgo()); setDateEnd(getToday()); setAppliedSearch(""); setAppliedService("전체 서비스"); setAppliedStatus("전체"); setCurrentPage(1); }; // 필터링 const filtered = useMemo(() => { return MOCK_SEND_HISTORY.filter((d) => { if (appliedSearch) { const q = appliedSearch.toLowerCase(); if ( !d.id.toLowerCase().includes(q) && !d.template.toLowerCase().includes(q) ) return false; } if (appliedService !== "전체 서비스" && d.service !== appliedService) return false; if (appliedStatus !== "전체" && d.status !== appliedStatus) return false; return true; }); }, [appliedSearch, appliedService, appliedStatus]); // 페이지네이션 const totalItems = filtered.length; const totalPages = Math.max(1, Math.ceil(totalItems / PAGE_SIZE)); const paged = filtered.slice( (currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE, ); // 행 클릭 const handleRowClick = (item: SendHistory) => { setSelectedHistory(item); setPanelOpen(true); }; // 테이블 헤더 렌더링 const renderTableHead = () => ( {COLUMNS.map((col) => ( {col} ))} ); return (
download 엑셀 다운로드 } /> {/* 필터바 */}
{/* 1줄: 검색어 / 서비스 / 상태 */}
{/* 2줄: 날짜 범위 / 버튼 */}
{/* 테이블 */} {loading ? (
{renderTableHead()} {Array.from({ length: 5 }).map((_, i) => ( {Array.from({ length: 8 }).map((_, j) => ( ))} ))}
) : paged.length > 0 ? (
{renderTableHead()} {paged.map((item, idx) => ( handleRowClick(item)} > {/* 발송 ID */} {/* 템플릿명 */} {/* 발송 시간 */} {/* 대상 수 */} {/* 성공 */} {/* 실패 */} {/* 오픈율 */} {/* 상태 */} ))}
e.stopPropagation()} > {item.id} {item.template} {item.sentAt} {formatNumber(item.total)} {formatNumber(item.success)} 0 ? "text-red-500" : "text-gray-400"}`}> {formatNumber(item.fail)} {item.openRate}%
{/* 페이지네이션 */}
) : ( )} {/* 슬라이드 패널 */} setPanelOpen(false)} history={selectedHistory} />
); }