Files
frontend/apps/fo/app/components/common/FacilityTermModalHeader.tsx
T
2025-07-15 20:54:38 +09:00

279 lines
12 KiB
TypeScript

import { useFoStore } from '@/app/store';
import { DatePickerRange, SelectBox } from '@common/business_components/ui';
import ListDiv from '@common/business_components/ui/list_div';
import { Table, TableCell, TableHead, TableRow } from '@common/components/ui';
import { useCallback, useEffect, useRef, useState } from 'react';
type FacilityTermModalHeaderProps<T extends { msrDt: string }> = {
fcltyCd : string;
fcltyName: string;
tabName: string;
searchYear: string;
searchList: T[];
ref: React.RefObject<ReturnType<T>>;
queryClick:(returnType:ReturnType<T>) => void;
}
export type ReturnType<T> = {
startDate: Date;
endDate: Date;
tabName: string;
filteredList: T[];
}
export default function FacilityTermModalHeader<T extends { msrDt: string }>({
searchList,
fcltyName,
tabName,
searchYear,
queryClick,
ref
}: FacilityTermModalHeaderProps<T & { msrDt: string }>) {
const {Common} = useFoStore((state) => state);
const { selectFlowPanel } = Common;
const [startDate, setStartDate] = useState<Date>(new Date(Number(searchYear), 0, 1));
const [endDate, setEndDate] = useState<Date>(new Date(Number(searchYear), 11, 31));
const startPickerRef = useRef<HTMLDivElement>(null);
const endPickerRef = useRef<HTMLDivElement>(null);
const [flowPanel, setFlowPanel] = useState<string>(selectFlowPanel[0]?.val ?? '00');
const [copySearchList, setCopySearchList] = useState<T[]>(searchList);
const [standSearchList, setStandSearchList] = useState<T[]>(searchList);
const isDateInRanges = (date: Date) => {
const standYear = parseInt(searchYear);
const dateRanges = [];
if (tabName.includes("_summer")) {
dateRanges.push({
start: new Date(standYear, 5, 1),
end: new Date(standYear, 7, 31)
});
} else if (tabName.includes("_winter")) {
dateRanges.push({
start: new Date(standYear, 0, 1),
end: new Date(standYear, 1, 28)
});
} else {
dateRanges.push({
start: new Date(standYear, 0, 1),
end: new Date(standYear, 11, 31)
});
}
return dateRanges.some(range => {
const start = new Date(range.start);
const end = new Date(range.end);
return date >= start && date <= end;
});
};
useEffect(() => {
let startDate = new Date(Number(searchYear), 0, 1);
let endDate = new Date(Number(searchYear), 11, 31);
if(tabName.includes("_summer")) {
startDate = new Date(Number(searchYear), 5, 1);
endDate = new Date(Number(searchYear), 7, 31);
setStartDate(startDate);
setEndDate(endDate);
} else if (tabName.includes("_winter")) {
startDate = new Date(Number(searchYear), 0, 1);
endDate = new Date(Number(searchYear), 1, 28);
setStartDate(startDate);
setEndDate(endDate);
} else {
startDate = new Date(Number(searchYear), 0, 1);
endDate = new Date(Number(searchYear), 11, 31);
setStartDate(startDate);
setEndDate(endDate);
}
let filteredData: T[] = [];
if(tabName.includes("_rain")) {
filteredData = searchList.filter((item) => {
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
if(flowPanel === '1') {
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay>0 && infoRnDay < 3;
} else if(flowPanel === '2'){
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10;
} else if(flowPanel === '3'){
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 10 && infoRnDay < 20;
} else if(flowPanel === '4'){
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 20 && infoRnDay < 30;
} else if(flowPanel === '5'){
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 30 && infoRnDay < 40;
} else if(flowPanel === '6'){
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 40 && infoRnDay < 50;
} else if(flowPanel === '7'){
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 50 && infoRnDay < 60;
} else if(flowPanel === '8'){
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60;
} else {
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (infoRnDay>0 || rainEffectDay ===1);
}
});
} else if(tabName.includes("_chuncheon")) {
filteredData = searchList.filter((item) => {
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay==0;
});
} else {
filteredData = searchList.filter((item) => {
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
});
}
setCopySearchList(filteredData);
setStandSearchList(filteredData);
}, [searchList, searchYear, tabName, flowPanel]);
const handleStartDateSelect = (day: Date | undefined) => {
if(day && day > endDate) {
alert('종료일은 시작일 이전일 수 없습니다.');
return;
}
const selectedDate = day ?? startDate;
setStartDate(selectedDate);
const button = startPickerRef.current?.querySelector('button');
if (button) {
setTimeout(() => button.click(), 0);
}
const filteredData = standSearchList.filter((item) => {
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
const startDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
});
setCopySearchList(filteredData);
};
const handleEndDateSelect = (day: Date | undefined) => {
if(day && day < startDate) {
alert('종료일은 시작일 이후일 수 없습니다.');
return;
}
const selectedDate = day ?? endDate;
setEndDate(selectedDate);
const button = endPickerRef.current?.querySelector('button');
if (button) {
setTimeout(() => button.click(), 0);
}
const filteredData = standSearchList.filter((item) => {
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
const endDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
});
setCopySearchList(filteredData);
};
const fncSetFilteredList = useCallback(() => {
queryClick({
startDate: startDate,
endDate: endDate,
tabName: tabName,
filteredList: copySearchList
});
}, [queryClick, startDate, endDate, tabName, copySearchList]);
useEffect(() => {
fncSetFilteredList();
}, [fncSetFilteredList]);
useEffect(() => {
if(ref && ref.current) {
const customRef = ref.current;
customRef.startDate = startDate;
customRef.endDate = endDate;
customRef.tabName = tabName;
customRef.filteredList = copySearchList;
}
}, [startDate, endDate, tabName, copySearchList, ref]);
return (
<ListDiv className="!h-[80px]">
<div className="!m-[0.5rem] max-h-[40rem] overflow-auto">
<Table>
<thead>
<TableRow className="!h-[20px]">
<TableHead className="w-[120px]">{'시설명'}</TableHead>
{tabName === "tab_term_rain" ? <TableCell className="w-[300px]">{fcltyName}</TableCell> :
<TableCell className="w-[380px]">{fcltyName}</TableCell>}
{tabName === "tab_term_rain" && (
<>
<TableHead className="w-[120px]">{'강수구분'}</TableHead>
<TableCell className="w-[250px]">
<div className="justify-center">
<SelectBox
selectArray={selectFlowPanel}
value={flowPanel}
onSelectValue={(val) => setFlowPanel(val.toString())}
className="mx-3 w-[150px]"
label=""
selectClass="w-full p-1 border rounded bg-white"
/>
</div>
</TableCell>
</>
)}
<TableHead className="w-[120px]">{'년/월'}</TableHead>
<TableCell className="">
<div className="flex">
<div ref={startPickerRef} className="flex justify-center">
<DatePickerRange
mode="single"
selected={startDate}
onSelect={(date) => handleStartDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
disabled={(date) => !isDateInRanges(date)}
defaultMonth={startDate}
/>
</div>
<h3 className="justify-center px-5">~</h3>
<div ref={endPickerRef} className="flex justify-center">
<DatePickerRange
mode="single"
selected={endDate}
onSelect={(date) => handleEndDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
disabled={(date) => !isDateInRanges(date)}
defaultMonth={endDate}
/>
</div>
</div>
</TableCell>
</TableRow>
</thead>
</Table>
</div>
</ListDiv>
);
}