엑셀 상단 색상 넣는 부분 추가.

엑셀 선택시 모달 띄우는 부분 모듈화.
This commit is contained in:
truthwing
2025-04-30 15:57:59 +09:00
parent bf2eade311
commit 05daa4200d
7 changed files with 84 additions and 89 deletions
@@ -3,18 +3,15 @@
import { useWrStore } from "@/app/store";
import {
fcltDiv,
type chHeadType,
type rainChkZodType,
type rainChkZodType
} from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { excelDownload } from "@/components/lib/func/commom";
import ChkgdExcel from "@/components/ui/modal/chkgdExcel/chkgdExcel";
import ChkgdModal from "@/components/ui/modal/chkgdModal/chkgdModal";
import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable";
import RainChkgdTableModal from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal";
import RswtChkgdTable from "@/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable";
import {
ContentsDiv,
filePickedBlob,
SearchDiv,
SearchFormLeft,
SearchFormRight,
@@ -37,7 +34,10 @@ export default function Page() {
const [searchTxt, setSearchTxt] = useState<string>();
const [updateRainDetail, setUpdateRainDetail] = useState<rainChkZodType[]>([]);
const [selFcltDiv, setSelFcltDiv] = useState("RNB");
const [isModal, setIsModal] = useState({
open: false,
data: {},
});
const cellClick = () => {
if(searchTxt)
rainChkInit(searchTxt,'41')
@@ -54,13 +54,15 @@ export default function Page() {
useEffect(() => {
excelDownload(rainChkgdn.excelList ,'빗물이용시설 지도점검','sample_rainy.xlsx');
excelDownload(rainChkgdn.excelList ,'빗물이용시설 지도점검','sample_rainy.xlsx', 'A1:AN1');
}, [rainChkgdn.excelList]);
const excelClick= useCallback(()=>{
rainChkExcelDownload(code.cityCd, code.sggCd);
}, [excelDownload, code.cityCd, code.sggCd]);
}, [rainChkExcelDownload, code.cityCd, code.sggCd]);
const handleClick = useCallback((data:any) => {
if(data) setIsModal({ open: true, data: data });
}, [isModal]);
return (
<ContentsDiv>
@@ -122,12 +124,12 @@ export default function Page() {
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
{selFcltDiv === "RNB" ? <RainChkgdTable detailUp={setUpdateRainDetail} /> : <RswtChkgdTable />}
{selFcltDiv === "RNB" ? <RainChkgdTable detailUp={setUpdateRainDetail} handleClick={handleClick} /> : <RswtChkgdTable />}
</ListDiv>
</div>
</div>
<RainChkgdTableModal isModal={isModal} setIsModal={setIsModal}/>
<UiModal
open={isRegExcel}
onOpenChange={setIsRegExcel}
@@ -5,8 +5,16 @@ import {
import { fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api";
import type { SelectDataType } from "@common/business_components/ui";
import { z } from "zod";
import { buildingToExcelType, excelToRainChkData } from "./excel";
import { buildingToExcelType } from "./excel";
const guideDetail=z.object({
chkgdnFk: z.number().nullable(),
utztnUsgCd: z.string(),
chckYmd: z.string(),
ym: z.string(),
splyUswtrUtztnQnt: z.number(),
ruseFcltUtztnQnt: z.number(),
flg: z.string(),
})
export const rainChkZod = z.object({
chkgdnPk: z.number().nullable(),
bdstRuseFcltFk: z.number(),
@@ -19,15 +27,7 @@ export const rainChkZod = z.object({
mdfr: z.string().nullable(),
flg: z.string().nullable(),
guideDetails: z.array(
z.object({
chkgdnFk: z.number().nullable(),
utztnUsgCd: z.string(),
chckYmd: z.string(),
ym: z.string(),
splyUswtrUtztnQnt: z.number(),
ruseFcltUtztnQnt: z.number(),
flg: z.string(),
})
guideDetail
),
building: z.object({
bdstInfoPk: z.number(),
+2 -2
View File
@@ -1,14 +1,14 @@
const LOCAL_PORT = "3000";
const DEV_PORT = "11080";
const DEV_PORT_NEW="8882"
const DEV_PORT_NEW="11082"
export const LOCAL_URL_WR = `http://localhost:${LOCAL_PORT}/api/v1`;
export const DEV_URL_WR = `http://con.mind-one.co.kr:${DEV_PORT}/api/v1`;
//export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_FO}/api/v1`;
export const DEV_URL_FO = `http://192.168.1.193:${DEV_PORT_NEW}/api/v1`;
export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_NEW}/api/v1`;
+6 -11
View File
@@ -4,7 +4,7 @@ import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui";
export const rightTableData = (rainChk: rainChkZodType[]) => {
// 1. chkgdnFk + utztnUsgCd 기준 누계 정보 만들기
const maketotal = rainChk.map((item: any) => {
const maketotal = rainChk.map((item: rainChkZodType) => {
const selectTotal = item.guideDetails.reduce((acc: any, cur: any) => {
const code = cur.utztnUsgCd;
const fk = cur.chkgdnFk;
@@ -23,6 +23,8 @@ export const rightTableData = (rainChk: rainChkZodType[]) => {
return selectTotal; // 모든 키: `${chkgdnFk}_${utztnUsgCd}` 형태
});
console.log("maketotal", maketotal);
// 2. 누계 정보들을 하나의 객체로 합치기 (평탄화)
const flatTotalMap = Object.assign({}, ...maketotal);
@@ -30,8 +32,8 @@ export const rightTableData = (rainChk: rainChkZodType[]) => {
// 3. rainyDetails에 누계 정보 주입
const updatedRainyDetails: any[] = [];
rainChk.forEach((rd: any) => {
const details = rd.rainyDetails.forEach((rainyItem: any) => {
rainChk.forEach((rd: rainChkZodType) => {
rd.rainyDetails.forEach((rainyItem: any) => {
const key = `${rainyItem.chkgdnFk}_${rainyItem.utztnUsgCd}`;
const totals = flatTotalMap[key] || {
totalSplyUswtrUtztnQnt: 0,
@@ -51,10 +53,6 @@ export const rightTableData = (rainChk: rainChkZodType[]) => {
return updatedRainyDetails;
};
export const chRowspanTable = (
makeTableData: any[],
headList: TableUpperProps[],
@@ -67,10 +65,7 @@ export const chRowspanTable = (
selectedIds: number[],
handleCellClick: (index: number, headId: string) => void
) => {
console.log('chRowspanTable', makeTableData);
// rowspan된 셀 렌더링 여부 추적용
const renderedMap = new Map<string, Set<number>>();
return (
+2 -3
View File
@@ -41,7 +41,6 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => {
returnData= { ...item, sggText: sggText, cityText: cityText};
}
// console.log(" returnData ", returnData)
return returnData;
});
@@ -49,7 +48,7 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => {
export const excelDownload =(excelList: [][], fileNm:string ,sampleFile:string ) =>{
export const excelDownload =(excelList: [][], fileNm:string ,sampleFile:string, headerRange='A1:V3') =>{
if (excelList.length === 0) return;
fetch(`/${sampleFile}`, {})
.then(async (response) => {
@@ -59,7 +58,7 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => {
// 받은 파일 바인너리 처리
const blobRet = await response.arrayBuffer()
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlob(blobRet, excelList,fileNm, 4)
await filePickedBlob(blobRet, excelList,fileNm, 4,headerRange)
})
}
@@ -1,41 +1,29 @@
"use client";
import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead";
import { useWrStore } from "@/app/store";
import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import { tableData } from "@/components/lib/func/commom";
import { UiModal } from "@common/business_components/ui";
import {
chRowspanTable,
rightTableData
} from "@/components/lib/func/TableData";
import {
Table,
TableBody,
TableHeader,
} from "@common/components/ui";
import { useEffect, useState } from "react";
import ChkgdModal from "../../../modal/chkgdModal/chkgdModal";
import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead";
import {
chRowspanTable,
rightTableData,
} from "@/components/lib/func/TableData";
import { useCallback, useEffect, useState } from "react";
export default function RainChkgdTable({
detailUp,
detailUp, handleClick=() => {}
}: {
detailUp: (data: rainChkZodType[]) => void;
handleClick?: (data:any) => void;
}) {
const { code, rainChkgdn } = useWrStore((state) => state);
const [makeTableData, setMakeTableData] = useState<any[]>([]);
const { rainChk } = rainChkgdn;
const [selectedIds, setSelectedIds] = useState<number[]>([]);
const [upRaintDetail, setUpRaintDetail] = useState<rainChkZodType[]>([]);
const [isModal, setIsModal] = useState({ open: false, data: {} });
const handleCellClick = (index: number, headId: string) => {
if (
headId === "totalSplyUswtrUtztnQnt" ||
headId === "totalRuseFcltUtztnQnt"
) {
setIsModal({ open: true, data: makeTableData[index] });
}
};
const toggleSelection = (pk: number, checked: boolean) => {
setSelectedIds((prev) =>
checked ? [...prev, pk] : prev.filter((item) => item !== pk)
@@ -53,6 +41,15 @@ export default function RainChkgdTable({
);
};
const handleCellClick= useCallback((index: number, headId: string) => {
if (
headId === "totalSplyUswtrUtztnQnt" ||
headId === "totalRuseFcltUtztnQnt"
) {
handleClick(makeTableData[index])
}
},[makeTableData, handleClick]);
useEffect(() => {
@@ -65,8 +62,8 @@ export default function RainChkgdTable({
rowspan: item.rainyDetails?.length,
};
});
setMakeTableData(rightTableData(rainChg));
const tableTotalData = rightTableData(rainChg)
setMakeTableData(tableTotalData);
}, [rainChk, code]);
useEffect(() => {
@@ -117,35 +114,24 @@ export default function RainChkgdTable({
detailUp(upRaintDetail);
}, [upRaintDetail]);
return (
<>
<Table variant="secondary">
<TableHeader className="font-bold">
{headMakeprfmnc(
rainChkgdn?.rainChkgdnHeadList,
rainChkgdn?.rainHeadNm
)}
</TableHeader>
<Table variant="secondary">
<TableHeader className="font-bold">
{headMakeprfmnc(
rainChkgdn?.rainChkgdnHeadList,
rainChkgdn?.rainHeadNm
)}
</TableHeader>
<TableBody>
{chRowspanTable(
makeTableData,
rainChkgdn.rainChkgdnHeadList,
handleChange,
toggleSelection,
selectedIds,
handleCellClick
)}
</TableBody>
</Table>
<UiModal
open={isModal.open}
onOpenChange={() => {
setIsModal({ open: !open, data: {} });
}}
bodyClass={"w-[80vw] max-w-none"}
body={<ChkgdModal type={"RNB"} obj={isModal.data} />}
></UiModal>
</>
<TableBody>
{chRowspanTable(
makeTableData,
rainChkgdn.rainChkgdnHeadList,
handleChange,
toggleSelection,
selectedIds,
handleCellClick
)}
</TableBody>
</Table>
);
}
@@ -0,0 +1,13 @@
import ChkgdModal from "@/components/ui/modal/chkgdModal/chkgdModal";
import { UiModal } from "@common/business_components";
export default function RainChkgdTableModal({ isModal, setIsModal }: { isModal: { open: boolean; data: any }; setIsModal: (value: { open: boolean; data: any }) => void }) {
return (<UiModal
open={isModal.open}
onOpenChange={() => {
setIsModal({ open: !open, data: {} });
}}
bodyClass={"w-[80vw] max-w-none"}
body={<ChkgdModal type={"RNB"} obj={isModal.data} />}
></UiModal>)
}