"use client"; import React, { useEffect, useState, useCallback } from "react"; import { ComponentRendererProps } from "@/types/component"; import { StatusCountConfig, StatusCountItem, STATUS_COLOR_MAP } from "./types"; import { apiClient } from "@/lib/api/client"; export interface StatusCountComponentProps extends ComponentRendererProps {} export const StatusCountComponent: React.FC = ({ component, isDesignMode = false, isSelected = false, formData, ...props }) => { const config = (component.componentConfig || {}) as StatusCountConfig; const [counts, setCounts] = useState>({}); const [loading, setLoading] = useState(false); const { title, tableName, statusColumn = "status", relationColumn, parentColumn, items = [], cardSize = "md", } = config; const parentValue = formData?.[parentColumn || relationColumn]; const fetchCounts = useCallback(async () => { if (!tableName || !parentValue || isDesignMode) return; setLoading(true); try { const res = await apiClient.post(`/table-management/tables/${tableName}/data`, { page: 1, size: 9999, search: relationColumn ? { [relationColumn]: parentValue } : {}, }); const responseData = res.data?.data; let rows: any[] = []; if (Array.isArray(responseData)) { rows = responseData; } else if (responseData && typeof responseData === "object") { rows = Array.isArray(responseData.data) ? responseData.data : Array.isArray(responseData.rows) ? responseData.rows : []; } const grouped: Record = {}; for (const row of rows) { const val = row[statusColumn] || "UNKNOWN"; grouped[val] = (grouped[val] || 0) + 1; } setCounts(grouped); } catch (err) { console.error("[v2-status-count] 데이터 조회 실패:", err); setCounts({}); } finally { setLoading(false); } }, [tableName, statusColumn, relationColumn, parentValue, isDesignMode]); useEffect(() => { fetchCounts(); }, [fetchCounts]); const getColorClasses = (color: string) => { if (STATUS_COLOR_MAP[color]) return STATUS_COLOR_MAP[color]; return { bg: "bg-gray-50", text: "text-gray-600", border: "border-gray-200" }; }; const getCount = (item: StatusCountItem) => { if (item.value === "__TOTAL__" || item.value === "__ALL__") { return Object.values(counts).reduce((sum, c) => sum + c, 0); } const values = item.value.split(",").map((v) => v.trim()); return values.reduce((sum, v) => sum + (counts[v] || 0), 0); }; const sizeClasses = { sm: { card: "px-3 py-2", number: "text-xl", label: "text-[10px]" }, md: { card: "px-4 py-3", number: "text-2xl", label: "text-xs" }, lg: { card: "px-6 py-4", number: "text-3xl", label: "text-sm" }, }; const sz = sizeClasses[cardSize] || sizeClasses.md; if (isDesignMode && !parentValue) { return (
{title &&
{title}
}
{(items.length > 0 ? items : [{ label: "상태1", color: "green" }, { label: "상태2", color: "blue" }, { label: "상태3", color: "orange" }]).map( (item: any, i: number) => { const colors = getColorClasses(item.color || "gray"); return (
0 {item.label}
); } )}
); } return (
{title &&
{title}
}
{items.map((item, i) => { const colors = getColorClasses(item.color); const count = getCount(item); return (
{loading ? "-" : count} {item.label}
); })}
); }; export const StatusCountWrapper: React.FC = (props) => { return ; };