feat: [dashboard] CEO 대시보드 모달 테이블 행 클릭 → 관련 페이지 이동

This commit is contained in:
유병철
2026-03-19 21:06:54 +09:00
parent 70f7341e64
commit eb121c3ce6
4 changed files with 30 additions and 4 deletions

View File

@@ -332,6 +332,25 @@ export function CEODashboard() {
}, [currentModalCardId, monthlyExpenseDetailData, cardManagementModals, dashboardSettings.entertainment, dashboardSettings.welfare]);
// 모달 테이블 행 클릭 → 관련 페이지 이동
const handleModalRowClick = useCallback((_row: Record<string, unknown>) => {
if (!currentModalCardId) return;
const routeMap: Record<string, string> = {
cm2: '/ko/accounting/card-transactions', // 가지급금 → 카드거래 목록
me1: '/ko/accounting/purchase', // 당월 매입 → 매입관리
me2: '/ko/accounting/card-transactions', // 당월 카드 → 카드거래 목록
me3: '/ko/accounting/bills', // 당월 발행어음 → 어음관리
me4: '/ko/accounting/expected-expenses', // 당월 지출 예상 → 지출예상
};
const targetPath = routeMap[currentModalCardId];
if (targetPath) {
handleDetailModalClose();
router.push(targetPath);
}
}, [currentModalCardId, handleDetailModalClose, router]);
// 카드/가지급금 관리 카드 클릭 → 모두 가지급금 상세(cm2) 모달
// 기획서 P52: 카드, 경조사, 상품권, 접대비, 총합계 모두 동일한 가지급금 상세 모달
const handleCardManagementCardClick = useCallback(async (_cardId: string) => {
@@ -842,6 +861,7 @@ export function CEODashboard() {
onClose={handleDetailModalClose}
config={detailModalConfig}
onDateFilterChange={handleDateFilterChange}
onRowClick={handleModalRowClick}
/>
)}
</PageLayout>

View File

@@ -203,6 +203,7 @@ export function transformCm2ModalConfig(
// 테이블 데이터 매핑 (백엔드 필드명 기준, 영문 키 → 한글 변환)
const tableData = (loans || []).map((item) => ({
id: item.id,
date: item.loan_date,
classification: CATEGORY_LABELS[item.category] || item.category || '카드',
category: item.status_label || '-',

View File

@@ -29,9 +29,10 @@ interface DetailModalProps {
onClose: () => void;
config: DetailModalConfig;
onDateFilterChange?: (params: { startDate: string; endDate: string; search: string }) => void;
onRowClick?: (row: Record<string, unknown>) => void;
}
export function DetailModal({ isOpen, onClose, config, onDateFilterChange }: DetailModalProps) {
export function DetailModal({ isOpen, onClose, config, onDateFilterChange, onRowClick }: DetailModalProps) {
return (
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()} >
<DialogContent className="!w-[95vw] sm:!w-[90vw] md:!w-[85vw] !max-w-[1600px] max-h-[90vh] overflow-auto p-0">
@@ -104,7 +105,7 @@ export function DetailModal({ isOpen, onClose, config, onDateFilterChange }: Det
)}
{/* 메인 테이블 영역 */}
{config.table && <TableSection key={config.title} config={config.table} />}
{config.table && <TableSection key={config.title} config={config.table} onRowClick={onRowClick} />}
{/* 참조 테이블 영역 (다중 - 테이블 아래 표시) */}
{config.referenceTables && config.referenceTables.length > 0 && (

View File

@@ -544,7 +544,7 @@ export const ReferenceTableSection = ({ config }: { config: ReferenceTableConfig
);
};
export const TableSection = ({ config }: { config: TableConfig }) => {
export const TableSection = ({ config, onRowClick }: { config: TableConfig; onRowClick?: (row: Record<string, unknown>) => void }) => {
const [filters, setFilters] = useState<Record<string, string>>(() => {
const initial: Record<string, string> = {};
config.filters?.forEach((filter) => {
@@ -662,7 +662,11 @@ export const TableSection = ({ config }: { config: TableConfig }) => {
{filteredData.map((row, rowIndex) => (
<tr
key={rowIndex}
className="border-t border-gray-100 hover:bg-gray-50"
className={cn(
"border-t border-gray-100 hover:bg-gray-50",
onRowClick && "cursor-pointer hover:bg-blue-50"
)}
onClick={onRowClick ? () => onRowClick(row) : undefined}
>
{config.columns.map((column) => {
const cellValue = column.key === 'no'