Merge commit '7e9fb08e97df4f04e4d364384a35706c9537500f' into iipbs/wr/form_fuction

This commit is contained in:
leedj312
2025-04-24 14:41:12 +09:00
9 changed files with 468 additions and 102 deletions
@@ -42,6 +42,7 @@
"recharts": "^2.15.1",
"sonner": "^2.0.1",
"tailwind-merge": "^3.0.1",
"xlsx": "^0.18.5",
"zod": "^3.24.2"
},
"devDependencies": {
@@ -0,0 +1,16 @@
import * as XLSX from 'xlsx';
type ExcelDownloadProps = {
data : JSON | JSON[];
fileName : string;
sheetNameArray : string[];
}
export const downloadExcel = ({ data, fileName = new Date().getTime().toString()+'.xlsx', sheetNameArray = ["Sheet1"] }: ExcelDownloadProps) => {
const worksheet = XLSX.utils.json_to_sheet(Array.isArray(data) ? data : [data]);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, sheetNameArray[0]);
//let buffer = XLSX.write(workbook, { bookType: "xlsx", type: "buffer" });
//XLSX.write(workbook, { bookType: "xlsx", type: "binary" });
XLSX.writeFile(workbook, fileName+'.xlsx');
};
@@ -1,19 +1,21 @@
export * from "./chart";
export * from "./date_picker";
export * from "./dialog_ui";
export * from "./excel_download";
export * from "./file-upload";
export * from "./form";
export * from "./form_ui";
export * from "./list_div";
export * from "./main_content_div";
export * from "./scroll";
export * from "./search_base_form";
export * from "./search_form";
export * from "./search_form_left";
export * from "./search_form_right";
export * from "./search_input";
export * from "./search_input_select";
export * from "./select";
export * from "./table";
export * from "./main_content_div";
export * from "./title";
export * from "./search_form_left";
export * from "./search_form_right";
export * from "./table_div";
export * from "./list_div";
export * from "./tab";
export * from "./dialog_ui"
export * from "./table";
export * from "./table_div";
export * from "./title";
@@ -0,0 +1,140 @@
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useState } from "react";
import { SearchFormLeft, type EnvPartSelectDataType } from "../search_form_left";
import { SearchFormRight } from "../search_form_right";
import type { SelectDataType } from "../search_input_select";
type SearchBaseType = {
leftChildren:React.ReactNode;
rightChildren:React.ReactNode;
selectSidoData?: SelectDataType[] | [];
selectSigunData?: SelectDataType[] | [];
selectRegionData?: SelectDataType[] | [];
selectUnitWaterShedData?: SelectDataType[] | [];
selectMiddleRegionData?: SelectDataType[] | [];
selectEnvPartData?: EnvPartSelectDataType[] | [];
queryClick:(returnType:ReturnType) => void;
excelClick:(returnType:ReturnType) => void;
initClick:() => void;
btnClass:string;
ref:React.RefObject<ReturnType>;
}
export type ReturnType = {
partValue: string;
sidoValue: string;
sigunValue: string;
regionValue: string;
unitWaterShedValue: string;
middleRegionValue: string;
envPartValue: string;
}
function SearchBaseForm ({
leftChildren,
rightChildren,
selectSidoData,
selectSigunData,
selectRegionData,
selectUnitWaterShedData,
selectMiddleRegionData,
selectEnvPartData,
btnClass,
queryClick,
excelClick,
initClick,
ref
}: SearchBaseType) {
const [partValue, setPartValue] = useState<string>("A");
const [sidoValue, setSidoValue] = useState<string>("0");
const [sigunValue, setSigunValue] = useState<string>("0");
const [regionValue, setRegionValue] = useState<string>("0");
const [untitWaterShedValue, setUntitWaterShedValue] = useState<string>("0");
const [middleRegionValue, setMiddleRegionValue] = useState<string>("0");
const [envPartValue, setEnvPartValue] = useState<string>("0");
const [resetTrigger, setResetTrigger] = useState(false);
const queryVal = () => {
console.log("조회버튼 클릭");
queryClick({
partValue: partValue,
sidoValue: sidoValue,
sigunValue: sigunValue,
regionValue: regionValue,
unitWaterShedValue: untitWaterShedValue,
middleRegionValue: middleRegionValue,
envPartValue: envPartValue,
});
}
const initVal = useCallback(() => {
setResetTrigger(true);
initClick();
}, [setResetTrigger, initClick]);
useEffect(() => {
if (resetTrigger) {
setResetTrigger(false);
}
}, [resetTrigger]);
const excelDownload = () => {
excelClick({
partValue: partValue,
sidoValue: sidoValue,
sigunValue: sigunValue,
regionValue: regionValue,
unitWaterShedValue: untitWaterShedValue,
middleRegionValue: middleRegionValue,
envPartValue: envPartValue,
})
};
useEffect(() => {
if (ref && ref.current) {
const customRef = ref.current;
customRef.partValue = partValue;
customRef.sidoValue = sidoValue;
customRef.sigunValue = sigunValue;
customRef.regionValue = regionValue;
customRef.unitWaterShedValue = untitWaterShedValue;
customRef.middleRegionValue = middleRegionValue;
customRef.envPartValue = envPartValue;
}
}, [partValue, sidoValue, sigunValue, regionValue, untitWaterShedValue, middleRegionValue, envPartValue, ref]);
return (
<div className="flex card card-border !mt-6">
<SearchFormLeft isShowPart={true}
selectSidoData={selectSidoData}
selectSigunData={selectSigunData}
selectRegionData={selectRegionData}
selectUnitWaterShedData={selectUnitWaterShedData}
selectMiddleRegionData={selectMiddleRegionData}
selectEnvPartData={selectEnvPartData}
setRtnPartValue={setPartValue}
setRtnSidoValue={setSidoValue}
setRtnSigunValue={setSigunValue}
setRtnRegionValue={setRegionValue}
setRtnUnitWaterShedValue={setUntitWaterShedValue}
setRtnMiddleRegionValue={setMiddleRegionValue}
setRtnEnvPartValue={setEnvPartValue}
setRtnEnvPartSidoValue={setSidoValue}
setRtnEnvPartSigunValue={setSigunValue}
resetTrigger={resetTrigger}
>
{leftChildren}
</SearchFormLeft>
<SearchFormRight>
<Button className={btnClass} color="green" onClick={excelDownload}>
엑셀다운로드
</Button>
<div>
<Button className={btnClass} onClick={initVal}>
초기화
</Button>
<Button className={btnClass} onClick={queryVal}>
조회
</Button>
</div>
{rightChildren}
</SearchFormRight>
</div>
)
}
export { SearchBaseForm };
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import type { SelectDataType } from '../search_input_select';
import { SelectBox } from '../select';
@@ -38,40 +38,44 @@ type SearchFormLeftProps = {
setRtnEnvPartValue?: (value: string) => void;
setRtnEnvPartSidoValue?: (value: string) => void;
setRtnEnvPartSigunValue?: (value: string) => void;
resetTrigger?: boolean;
}
type EnvPartSelectDataType = SelectDataType & {
export type EnvPartSelectDataType = SelectDataType & {
adstDliStrCd: string,
}
const selectPartData:SelectDataType[] = [
{ text: "행정별", val: '0' },
{ text: "유역별", val: '01' },
{ text: "환경청별", val: '02' },
{ text: "행정별", val: 'A' },
{ text: "유역별", val: 'R' },
{ text: "환경청별", val: 'G' },
];
function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], selectSigunData = [], selectRegionData = [], selectUnitWaterShedData = [], selectMiddleRegionData = [], selectEnvPartData = [], setRtnPartValue, setRtnSidoValue, setRtnSigunValue, setRtnRegionValue, setRtnUnitWaterShedValue, setRtnMiddleRegionValue, setRtnEnvPartValue, setRtnEnvPartSidoValue, setRtnEnvPartSigunValue }: SearchFormLeftProps) {
const [partValue, setPartValue] = useState<string>('0');
const [showPart, setShowPart] = useState<string>('');
function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], selectSigunData = [], selectRegionData = [], selectUnitWaterShedData = [], selectMiddleRegionData = [], selectEnvPartData = [], setRtnPartValue, setRtnSidoValue, setRtnSigunValue, setRtnRegionValue, setRtnUnitWaterShedValue, setRtnMiddleRegionValue, setRtnEnvPartValue, setRtnEnvPartSidoValue, setRtnEnvPartSigunValue, resetTrigger = false }: SearchFormLeftProps) {
/******************선택된 데이터******************/
const [partValue, setPartValue] = useState<string>('A');
//행정별 시도 시군구
const [sidoValue, setSidoValue] = useState<string>('0');
const [sigunValue, setSigunValue] = useState<string>('0');
//유역별
const [regionValue, setRegionValue] = useState<string>('0');
const [unitWaterShedValue, setUnitWaterShedValue] = useState<string>('0');
const [middleRegionValue, setMiddleRegionValue] = useState<string>('0');
//환경청별 시도 시군구
const [envPartValue, setEnvPartValue] = useState<string>('0');
const [envPartSidoValue, setEnvPartSidoValue] = useState<string>('0');
const [envPartSigunValue, setEnvPartSigunValue] = useState<string>('0');
// 환경청
const [filteredEnvPartSigunDataSelected, setFilteredEnvPartSigunDataSelected] = useState<SelectDataType[]>([]);
/****************** 셀렉트 리스트 데이터. ******************/
// 조회된 조건에 맞는 시도 시군 유역
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
const [filteredUnitWaterShedData, setFilteredUnitWaterShedData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
const [filteredMiddleRegionData, setFilteredMiddleRegionData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
// 조회된 조건에 맞는 환경청 시도 시군
const [filteredEnvPartData, setFilteredEnvPartData] = useState<EnvPartSelectDataType[]>([{ text: "전체", val: '0', adstDliStrCd:'' }]);
const [filteredEnvPartSidoData, setFilteredEnvPartSidoData] = useState<EnvPartSelectDataType[]>([{ text: "전체", val: '0', adstDliStrCd:'' }]);
const [filteredEnvPartSigunData, setFilteredEnvPartSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
const [filteredEnvPartSigunDataSelected, setFilteredEnvPartSigunDataSelected] = useState<SelectDataType[]>([]);
// 시군구 세팅
const initializeSigunData = (sidoCd: string) => {
if (sidoCd === '0') {
@@ -153,12 +157,10 @@ function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], sel
setRtnPartValue(val);
}
// 구분
if(val == '01') {
setShowPart('01');
if(val == 'R') {
initializeMiddleRegionData('0');
initializeUnitWaterShedData('0');
} else if(val == '02') {
setShowPart('02');
} else if(val == 'G') {
setFilteredEnvPartData([
{ text: "전체", val: '0', adstDliStrCd:'' },
...selectEnvPartData.filter((item: EnvPartSelectDataType) => item.val !== null && item.adstDliStrCd !== '')
@@ -166,7 +168,6 @@ function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], sel
setEnvPartValue('0');
initializeCityDataByEnvPartSido('0');
} else {
setShowPart('0');
initializeSigunData('0');
onSelectValue(selectSigunData[0]?.val || '0', 'sigun');
}
@@ -224,7 +225,7 @@ function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], sel
onSelectValue(filteredEnvPartSidoData[0]?.val || '0', 'envPartSido');
break;
case 'envPartSido' :
setEnvPartSidoValue(val);
setSidoValue(val);
if (setRtnEnvPartSidoValue) {
setRtnEnvPartSidoValue(val);
}
@@ -232,29 +233,68 @@ function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], sel
onSelectValue(filteredEnvPartSigunData[0]?.val || '0', 'envPartSigun');
break;
case 'envPartSigun' :
setEnvPartSigunValue(val);
setSigunValue(val);
if (setRtnEnvPartSigunValue) {
setRtnEnvPartSigunValue(val);
}
break;
}
}
// 리셋 함수
const resetAllValues = () => {
setPartValue('A');
setSidoValue('0');
setSigunValue('0');
setRegionValue('0');
setUnitWaterShedValue('0');
setMiddleRegionValue('0');
setEnvPartValue('0');
setFilteredSigunData([{ text: "전체", val: '0' }]);
setFilteredUnitWaterShedData([{ text: "전체", val: '0' }]);
setFilteredMiddleRegionData([{ text: "전체", val: '0' }]);
setFilteredEnvPartData([{ text: "전체", val: '0', adstDliStrCd: '' }]);
setFilteredEnvPartSidoData([{ text: "전체", val: '0', adstDliStrCd: '' }]);
setFilteredEnvPartSigunData([{ text: "전체", val: '0' }]);
if (setRtnPartValue) setRtnPartValue('A');
if (setRtnSidoValue) setRtnSidoValue('0');
if (setRtnSigunValue) setRtnSigunValue('0');
if (setRtnRegionValue) setRtnRegionValue('0');
if (setRtnUnitWaterShedValue) setRtnUnitWaterShedValue('0');
if (setRtnMiddleRegionValue) setRtnMiddleRegionValue('0');
if (setRtnEnvPartValue) setRtnEnvPartValue('0');
if (setRtnEnvPartSidoValue) setRtnEnvPartSidoValue('0');
if (setRtnEnvPartSigunValue) setRtnEnvPartSigunValue('0');
};
// 리셋 트리거 변경 감지
useEffect(() => {
if (resetTrigger) {
resetAllValues();
// 리셋 후 트리거를 false로 설정
if (setRtnPartValue) {
setRtnPartValue('0');
}
}
}, [resetTrigger]);
return (
isShowPart ? (
<div className="grid grid-cols-12 gap-5 w-11/12 m-4">
<SelectBox className="col-span-3" label={'구분'} selectArray={selectPartData} onSelectValue={(val) => onSelectValue(val.toString(), 'part')} value={partValue} selectClass={undefined}/>
{showPart === '01' ? (
{partValue === 'R' ? (
<>
<SelectBox className="col-span-3" label={'유역'} selectArray={selectRegionData} onSelectValue={(val) => onSelectValue(val.toString(), 'region')} value={regionValue} selectClass={undefined}/>
<SelectBox className="col-span-3" label={'단위유역'} selectArray={filteredUnitWaterShedData} onSelectValue={(val) => onSelectValue(val.toString(), 'unitWaterShed')} value={unitWaterShedValue} selectClass={undefined}/>
<SelectBox className="col-span-3" label={'중권역'} selectArray={filteredMiddleRegionData} onSelectValue={(val) => onSelectValue(val.toString(), 'middleRegion')} value={middleRegionValue} selectClass={undefined}/>
</>
) : showPart === '02' ? (
) : partValue === 'G' ? (
<>
<SelectBox className="col-span-3" label={'환경청'} selectArray={filteredEnvPartData} onSelectValue={(val) => onSelectValue(val.toString(), 'envPart')} value={envPartValue} selectClass={undefined}/>
<SelectBox className="col-span-3" label={'시도'} selectArray={filteredEnvPartSidoData} onSelectValue={(val) => onSelectValue(val.toString(), 'envPartSido')} value={envPartSidoValue} selectClass={undefined}/>
<SelectBox className="col-span-3" label={'시군구'} selectArray={filteredEnvPartSigunData} onSelectValue={(val) => onSelectValue(val.toString(), 'envPartSigun')} value={envPartSigunValue} selectClass={undefined}/>
<SelectBox className="col-span-3" label={'시도'} selectArray={filteredEnvPartSidoData} onSelectValue={(val) => onSelectValue(val.toString(), 'envPartSido')} value={sidoValue} selectClass={undefined}/>
<SelectBox className="col-span-3" label={'시군구'} selectArray={filteredEnvPartSigunData} onSelectValue={(val) => onSelectValue(val.toString(), 'envPartSigun')} value={sigunValue} selectClass={undefined}/>
</>
) : (
<>
@@ -3,45 +3,41 @@
#### 1. 컴포넌트 호출방법
```js
import { SearchFormLeft } from "@common/business_components";
.....
<SearchFormLeft
isShowPart={true}
selectSidoData={selectSidoData}
selectSigunData={selectSigunData}
selectRegionData={selectRegionData}
selectUnitWaterShedData={selectUnitWaterShedData}
selectMiddleRegionData={selectMiddleRegionData}
selectEnvPartData={selectEnvPartData}
selectEnvPartSidoData={selectEnvPartSidoData}
selectEnvPartSigunData={selectEnvPartSigunData}
setRtnPartValue={(value) => {
setPartValue(value);
}}
setRtnSidoValue={(value) => {
setSidoValue(value);
}}
setRtnSigunValue={(value) => {
setSigunValue(value);
}}
setRtnRegionValue={(value) => {
setRegionValue(value);
}}
setRtnUnitWaterShedValue={(value) => {
setUntitWaterShedValue(value);
}}
setRtnMiddleRegionValue={(value) => {
setMiddleRegionValue(value);
}}
setRtnEnvPartValue={(value) => {
setEnvPartValue(value);
}}
setRtnEnvPartSidoValue={(value) => {
setEnvPartSidoValue(value);
}}
setRtnEnvPartSigunValue={(value) => {
setEnvPartSigunValue(value);
}}
// state 지정
const [partValue, setPartValue] = useState<string>("0");
const [sidoValue, setSidoValue] = useState<string>("0");
const [sigunValue, setSigunValue] = useState<string>("0");
const [regionValue, setRegionValue] = useState<string>("0");
const [untitWaterShedValue, setUntitWaterShedValue] = useState<string>("0");
const [middleRegionValue, setMiddleRegionValue] = useState<string>("0");
const [envPartValue, setEnvPartValue] = useState<string>("0");
const [envPartSidoValue, setEnvPartSidoValue] = useState<string>("0");
const [envPartSigunValue, setEnvPartSigunValue] = useState<string>("0");
const [resetTrigger, setResetTrigger] = useState<boolean>(false);
.....
<SearchFormLeft isShowPart={true}
selectSidoData={selectSidoData}
selectSigunData={selectSigunData}
selectRegionData={selectRegionData}
selectUnitWaterShedData={selectUnitWaterShedData}
selectMiddleRegionData={selectMiddleRegionData}
selectEnvPartData={selectEnvPartData}
setRtnPartValue={setPartValue}
setRtnSidoValue={setSidoValue}
setRtnSigunValue={setSigunValue}
setRtnRegionValue={setRegionValue}
setRtnUnitWaterShedValue={setUntitWaterShedValue}
setRtnMiddleRegionValue={setMiddleRegionValue}
setRtnEnvPartValue={setEnvPartValue}
setRtnEnvPartSidoValue={setEnvPartSidoValue}
setRtnEnvPartSigunValue={setEnvPartSigunValue}
resetTrigger={resetTrigger}
>
```
&emsp; ㆍisShowPart : 검색단에서 구분(행정별,유역별,환경청별) 세팅 여부(보일 경우 : Y, 아닐경우 : N 혹은 미첨부)
@@ -73,7 +69,11 @@ import { SearchFormLeft } from "@common/business_components";
&emsp; ㆍsetRtnEnvPartSidoValue : 선택한 환경청의 시도 set함수(조회시 페이지에서 사용)
&emsp; ㆍsetRtnEnvPartSidoValue : 선택한 환경청 시도의 시군구 set함수(조회시 페이지에서 사용)
&emsp; ㆍsetRtnEnvPartSigunValue : 선택한 환경청 시도의 시군구 set함수(조회시 페이지에서 사용)
&emsp; ㆍresetTrigger : 초기화 trigger 변수
#### 2. 세팅방법
```js
@@ -318,8 +318,58 @@ const [middleRegionValue, setMiddleRegionValue] = useState<string>("0");
const [envPartValue, setEnvPartValue] = useState<string>("0");
const [envPartSidoValue, setEnvPartSidoValue] = useState<string>("0");
const [envPartSigunValue, setEnvPartSigunValue] = useState<string>("0");
const [resetTrigger, setResetTrigger] = useState<boolean>(false);
<!-- 컴포넌트 호출 -->
<!-- 초기화 기능 -->
const resetVal = () => {
console.log('=== 초기화 ===');
console.log(selectSidoData);
// SelectBox 초기화 - 각 selectArray의 첫 번째 옵션 값 사용
const initialPartValue = selectPartData[0]?.val || "0";
const initialSidoValue = selectSidoData[0]?.val || "0";
const initialSigunValue = selectSigunData[0]?.val || "0";
const initialRegionValue = selectRegionData[0]?.val || "0";
const initialUnitWaterShedValue = selectUnitWaterShedData[0]?.val || "0";
const initialMiddleRegionValue = selectMiddleRegionData[0]?.val || "0";
const initialEnvPartValue = selectEnvPartData[0]?.val || "0";
const initialEnvPartSidoValue = selectEnvPartData[0]?.val || "0";
const initialEnvPartSigunValue = selectEnvPartData[0]?.val || "0";
// 상태값 설정
setPartValue(initialPartValue);
setSidoValue(initialSidoValue);
setSigunValue(initialSigunValue);
setRegionValue(initialRegionValue);
setUntitWaterShedValue(initialUnitWaterShedValue);
setMiddleRegionValue(initialMiddleRegionValue);
setEnvPartValue(initialEnvPartValue);
setEnvPartSidoValue(initialEnvPartSidoValue);
setEnvPartSigunValue(initialEnvPartSigunValue);
// 리셋 후 트리거를 false로 설정
setTimeout(() => {
setResetTrigger(false);
}, 0);
}
// 조회 함수
const chkVal = useCallback(() => {
setResetPage(true);
// 조회 funciton
searchFcltyQltyList(1);
}, [searchFcltyQltyList]);
// 그리드 page 넘어갈 때 필요한 함수
const handlePageChange = useCallback((page: number) => {
setResetPage(false);
searchFcltyQltyList(page);
}, [searchFcltyQltyList]);
// 테이블 호출 컴포넌트
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 수질현황"} tableData={mainList} headlist={upHeadList2} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange}>
<HeadMakeColSpan upHeadList={upHeadList2} layoutNum={layoutNum}/>
</UiTable>
```
@@ -0,0 +1,52 @@
import { TableHead, TableRow } from "@common/components/ui";
interface TableUpperProps {
id: string;
title: string;
upName?: string;
upSequnce?: number;
row? : number;
rowSpan?: number;
colSpan?: number;
}
const HeadMakeColSpan = ({ upHeadList }: { upHeadList: TableUpperProps[] }) => {
const maxRow = upHeadList.reduce((max, head) => Math.max(max, head.row || 0), 0);
return (
<>
{Array.from({ length: maxRow + 1 }, (_, rowIndex) => (
<TableRow key={rowIndex+ " headerRow"} className="bg-gray-50">
{upHeadList.map((head: TableUpperProps) => {
if (head.row === rowIndex) {
return (
<TableHead
key={head.id}
colSpan={head.colSpan || 1}
rowSpan={head.rowSpan || 1}
style={{ whiteSpace: 'pre-line' }}
className="bg-gray-50"
>
{head.title}
</TableHead>
);
}else{
return (
<TableHead
key={head.id}
colSpan={head.colSpan || 1}
rowSpan={head.rowSpan || 1}
style={{ whiteSpace: 'pre-line' }}
className="bg-gray-50"
>
{head.title}
</TableHead>
);
}
})}
</TableRow>
))}
</>
);
}
export { HeadMakeColSpan };
@@ -1,18 +1,19 @@
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components";
import { Table, TableBody, TableCell, TableHeader, TableRow } from "@common/components";
import { useEffect, useState } from "react";
import { HeadMakeColSpan } from "./HeadMakeColSpan";
import UiPageNations from "./uiPageNations";
type UiTableProps = {
headName: React.ReactNode | undefined;
tableData: { [key: string]: string | number | boolean | object}[];
tableData: { [key: string]:any}[];
headlist: UiHeadProps[];
pageSize: number;
total: number;
children: React.ReactNode | undefined;
cellClick : ((index:number|undefined, headId:string)=>void )| undefined;
onPageChange: (page: number) => void;
className?: string;
resetPageNo?: boolean;
children?: React.ReactNode | undefined;
}
type UiHeadProps = {
@@ -21,7 +22,7 @@ type UiHeadProps = {
align?: string;
}
export function UiTable({ tableData, headlist, pageSize, total, children, headName, cellClick, onPageChange, className = '', resetPageNo = false }: UiTableProps) {
export function UiTable({ tableData, headlist, pageSize, total, headName, children, cellClick, onPageChange, className = '', resetPageNo = false }: UiTableProps) {
const [cur, setCur] = useState<number>(1);
const [idx, setIdx] = useState<number>(-1);
@@ -43,7 +44,7 @@ export function UiTable({ tableData, headlist, pageSize, total, children, headNa
setIdx(index);
}
};
return (
<>
{headName ? <div className="card-header">
@@ -51,31 +52,32 @@ export function UiTable({ tableData, headlist, pageSize, total, children, headNa
</div> : <></>}
<div className={`card !m-[1.2rem] !p-0r ${className}`}>
<Table variant="secondary">
{children?children:
<TableHeader className="font-bold">
{children ? <>{children}</> : <TableRow>
{headlist?.map((head) => (
<TableHead key={head.id}>{head.title}</TableHead>
))}
</TableRow>}
</TableHeader>
<TableBody className='text-center'>
{tableData?.map((el: { [key: string]: string | number | boolean | object}, index) => (
<TableRow key={index + "row"}>
{headlist?.map((head) => (
<TableCell
className={`${head.align === 'right' ? 'text-right' : 'text-center'} ${
cellClick && idx === index ? '!font-[1000] cursor-pointer' :
cellClick ? 'cursor-pointer' : ''
}`}
onClick={() => handleCellClick(index, head.id)}
key={head.id + index}
>
{String(el[head.id] ?? '')}
</TableCell>
))}
</TableRow>
))}
</TableBody>
{children ? children : <HeadMakeColSpan upHeadList={headlist} />}
</TableHeader>
}
<TableBody className='text-center'>
{tableData.length > 0 ? tableData?.map((el: { [key: string]: any}, index) => (
<TableRow key={`row-${index}`}>
{headlist?.map((head) => (
head.id && head.id.length > 1 && (
<TableCell
className={`${head.align === 'right' ? 'text-right' : head.align === 'center' ? 'text-center' : typeof el[head.id] === 'number' ? 'text-right' : 'text-center'} ${
cellClick && idx === index ? '!font-[1000] cursor-pointer' :
cellClick ? 'cursor-pointer' : ''
}`}
onClick={() => handleCellClick(index, head.id)}
key={`cell-${head.id}-${index}`}
>
{typeof el[head.id] === 'number' ? String(el[head.id]).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : String(el[head.id] ?? '')}
</TableCell>
)
))}
</TableRow>
)) : <></>}
</TableBody>
</Table>
{total <= 0 ? <></> : <UiPageNations total={total} cur={cur} pageSize={pageSize} onPageChange={handlePageChange} />}
</div>
+64 -1
View File
@@ -266,6 +266,9 @@ importers:
tailwind-merge:
specifier: ^3.0.1
version: 3.0.2
xlsx:
specifier: ^0.18.5
version: 0.18.5
zod:
specifier: ^3.24.2
version: 3.24.2
@@ -325,7 +328,7 @@ importers:
specifier: ^15.14.0
version: 15.15.0
postcss:
specifier: ^8.5.1
specifier: ^8.5.3
version: 8.5.3
prettier:
specifier: ^3.4.2
@@ -3853,6 +3856,11 @@ packages:
hasBin: true
dev: true
/adler-32@1.3.1:
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
engines: {node: '>=0.8'}
dev: false
/ajv-formats@2.1.1(ajv@8.17.1):
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
@@ -4236,6 +4244,14 @@ packages:
/caniuse-lite@1.0.30001701:
resolution: {integrity: sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw==}
/cfb@1.2.2:
resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
engines: {node: '>=0.8'}
dependencies:
adler-32: 1.3.1
crc-32: 1.2.2
dev: false
/chai@5.2.0:
resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==}
engines: {node: '>=12'}
@@ -4325,6 +4341,11 @@ packages:
engines: {node: '>=6'}
dev: false
/codepage@1.15.0:
resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==}
engines: {node: '>=0.8'}
dev: false
/color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -4402,6 +4423,12 @@ packages:
typescript: 5.6.3
dev: true
/crc-32@1.2.2:
resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
engines: {node: '>=0.8'}
hasBin: true
dev: false
/cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
@@ -5516,6 +5543,11 @@ packages:
mime-types: 2.1.35
dev: false
/frac@1.1.2:
resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
engines: {node: '>=0.8'}
dev: false
/fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
dev: true
@@ -7571,6 +7603,13 @@ packages:
whatwg-url: 7.1.0
dev: true
/ssf@0.11.2:
resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==}
engines: {node: '>=0.8'}
dependencies:
frac: 1.1.2
dev: false
/stable-hash@0.0.4:
resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==}
dev: true
@@ -8535,11 +8574,21 @@ packages:
dependencies:
isexe: 2.0.0
/wmf@1.0.2:
resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==}
engines: {node: '>=0.8'}
dev: false
/word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
dev: true
/word@0.3.0:
resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==}
engines: {node: '>=0.8'}
dev: false
/wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -8569,6 +8618,20 @@ packages:
optional: true
dev: true
/xlsx@0.18.5:
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
engines: {node: '>=0.8'}
hasBin: true
dependencies:
adler-32: 1.3.1
cfb: 1.2.2
codepage: 1.15.0
crc-32: 1.2.2
ssf: 0.11.2
wmf: 1.0.2
word: 0.3.0
dev: false
/y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}