Merge branch 'iipbs/sn/dev'

This commit is contained in:
swcho
2025-08-26 18:47:33 +09:00
7 changed files with 111 additions and 33 deletions
@@ -1006,16 +1006,31 @@ const SearchModal: React.FC<SearchModalProps> = ({
};
const viewMultipleFeature = async () => {
if (!(tableData.length === 0)) {
setIsLoading(true);
if (activeTab === 'basic') {
if (!(tableData.length === 0)) {
setIsLoading(true);
const row = tableData[0];
const layerNm = row.lyrTypeNm;
const fids = tableData.map((item) => item.fid);
const core = GisApp.Module.layer as any;
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
setIsLoading(false);
onOpenChange(false);
const row = tableData[0];
const layerNm = row.lyrTypeNm;
const fids = tableData.map((item) => item.fid);
const core = GisApp.Module.layer as any;
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
setIsLoading(false);
onOpenChange(false);
}
} else if (activeTab === 'operation') {
if (!(detailTableData.length === 0)) {
setIsLoading(true);
const row = detailTableData[0];
console.log('row', row);
const layerNm = row.lyrTypeNm;
const fids = detailTableData.map((item) => item.fid);
const core = GisApp.Module.layer as any;
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
setIsLoading(false);
onOpenChange(false);
}
}
}
@@ -1159,7 +1174,10 @@ const SearchModal: React.FC<SearchModalProps> = ({
resetPageNo={isResetDetailPage}
resetSelection={isResetDetailSelection}
headButton={
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-lg font-medium green" size="sm" onClick={operationResultExcelDownload}>파일 다운로드</Button>
<div className='flex'>
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-lg font-medium primary" size="sm" onClick={viewMultipleFeature}>지도에서 보기</Button>
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-lg font-medium green" size="sm" onClick={operationResultExcelDownload}>파일 다운로드</Button>
</div>
}
/>
</div>
@@ -209,7 +209,7 @@ const TableModal: React.FC<TableModalProps> = ({ fileNm, atflId }) => {
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<div className="w-[1000%]">
<div className="min-w-[550%]">
<UiTable
headName={'관리SHEET'}
tableData={managementTableData}
@@ -19,6 +19,14 @@ const customStyles = {
} as CSSProperties,
};
const fncNumberFormet = (value : string | number) => {
return String(value).includes('.')?
String(parseFloat(value.toString().replace(/,/g, ''))).split('.').map((part, index) =>
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
).join('.')
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
type BarChartProps = {
chartConfig: ChartConfig | undefined;
chartData: any[] | undefined;
@@ -51,7 +59,7 @@ const CustomTooltip = ({
<div key={index} style={{ marginTop: "10px", display: "flex", alignItems: "center", gap: "8px" }}>
{/* 색상 박스 추가 (범례 색상과 동일) */}
<div style={{ width: "10px", height: "10px", backgroundColor: item.color, borderRadius: "50%" }}></div>
<span className="text-[11px] font-bold">{` ${item.name} : ${item.value}`}</span>
<span className="text-[11px] font-bold">{` ${item.name} : ${fncNumberFormet(item.value)}`}</span>
</div>
))}
</div>
@@ -6,6 +6,7 @@ import {
type ChartConfig
} from "./lib/chart";
import type { ContentType } from "recharts/types/component/DefaultLegendContent";
import type { set } from "date-fns";
// 툴크 커스텀 css
/** 차트 기본 스타일 */
@@ -29,6 +30,7 @@ type LineBarChartProps = {
yFieldText?: string | undefined;
yFieldText2?: string | undefined;
showLegend?: boolean;
setXAxisYearTick?: boolean;
}
type LegendEntry = {
@@ -86,7 +88,8 @@ export default function LineBarchart({
graphSize = 40,
yFieldText,
yFieldText2,
showLegend = true
showLegend = true,
setXAxisYearTick = false
}: LineBarChartProps) {
if (!chartData || chartData.length === 0) {
return <div>데이터가 없습니다.</div>;
@@ -105,6 +108,24 @@ export default function LineBarchart({
const lineMaxValue = getMaxValue(chartData, 'lineVal');
const barMaxValue = getMaxValue(chartData, 'barVal');
const getTicks = (data : any []) => {
const monthSet = new Set<string>();
const rtnData : string[] = [];
for(const item of data){
const month = String(item.label).slice(0,7);
if(!monthSet.has(month)){
monthSet.add(month);
rtnData.push(item.label);
}
}
return rtnData;
}
let monthTicks : string[] = [];
if(setXAxisYearTick){
monthTicks = getTicks(chartData);
}
return (
<div className={chartClassName}>
{chartTitle && chartTitle !== "" && chartTitle !== "undefined" ? (
@@ -121,7 +142,10 @@ export default function LineBarchart({
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="label" fontSize="8px" fontWeight="bold"/>
{setXAxisYearTick?
<XAxis dataKey="label" ticks={monthTicks} tickFormatter={(value) => value.slice(0,7)} fontSize="8px" fontWeight="bold"/> :
<XAxis dataKey="label" fontSize="8px" fontWeight="bold"/>
}
{/* 왼쪽 Y축: lineVal */}
{yFieldText && <YAxis
yAxisId="left"
@@ -15,6 +15,7 @@ type LineChartProps = {
graphSize?: number;
yFieldText?: string;
showLegend?: boolean;
setXAxisYearTick?: boolean;
}
/** 차트 기본 스타일 */
@@ -141,7 +142,8 @@ export default function Linechart({
chartClassName = 'w-full h-full',
graphSize = 40,
yFieldText,
showLegend = true
showLegend = true,
setXAxisYearTick = false,
}: LineChartProps) {
if (!chartData || Object.keys(chartData).length === 0) {
return <div>데이터가 없습니다.</div>;
@@ -164,18 +166,24 @@ export default function Linechart({
return acc;
}, []);
// 데이터의 최대값 계산
const getMaxValue = (data: ChartDataType): number => {
return Math.max(...Object.values(data).flatMap(dataset =>
dataset.map(entry => {
const val = parseFloat(entry.val);
return isNaN(val) ? 0 : val;
})
));
};
const lineMaxValue = getMaxValue(chartData);
const getTicks = (data : any []) => {
const monthSet = new Set<string>();
const rtnData : string[] = [];
for(const item of data){
const month = String(item.label).slice(0,7);
if(!monthSet.has(month)){
monthSet.add(month);
rtnData.push(item.label);
}
}
return rtnData;
}
let monthTicks : string[] = [];
if(setXAxisYearTick){
monthTicks = getTicks(mergedData);
}
return (
<div className={chartClassName}>
{chartTitle && chartTitle !== "" && chartTitle !== "undefined" ? (
@@ -192,8 +200,27 @@ export default function Linechart({
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
>
<CartesianGrid vertical={false} />
<XAxis dataKey="label" fontSize="8px" fontWeight="bold" />
<YAxis yAxisId="left" className="text-[12px] font-bold" tickFormatter={(value) => value.toLocaleString()} tickCount={6} orientation="left" label={{ value: yFieldText, className:"text-[12px] font-bold", angle: -90, position: 'insideLeft' }} />
{setXAxisYearTick ?
<XAxis
dataKey="label"
fontSize="8px"
fontWeight="bold"
ticks={monthTicks}
tickFormatter={(value) => value.slice(0,7)}
/> :
<XAxis
dataKey="label"
fontSize="8px"
fontWeight="bold"
/>
}
<YAxis
yAxisId="left"
className="text-[12px] font-bold"
orientation="left"
label={{ value: yFieldText, className:"text-[12px] font-bold", angle: -90, position: 'insideLeft' }} />
<Tooltip content={<CustomTooltip />} />
{showLegend && <Legend content={CustomLegend as ContentType}/>}
{Object.keys(chartData).map((key) => {
@@ -56,6 +56,7 @@ type MainChartProps = {
yFieldText? : string | undefined;
yFieldText2? : string | undefined;
showLegend? : boolean;
setXAxisYearTick ?: boolean;
}
function MainChart(props: MainChartProps) {
@@ -65,7 +66,7 @@ function MainChart(props: MainChartProps) {
);
} else if( props.chartForm == CHART_FORM.LINE ){
return (
<LineChart chartConfig={props.chartConfig} chartData={props.chartData} chartTitle={props.chartTitle} chartClassName={props.chartClassName} graphSize={props.graphSize} yFieldText={props.yFieldText} showLegend={props.showLegend}/>
<LineChart chartConfig={props.chartConfig} chartData={props.chartData} chartTitle={props.chartTitle} chartClassName={props.chartClassName} graphSize={props.graphSize} yFieldText={props.yFieldText} showLegend={props.showLegend} setXAxisYearTick={props.setXAxisYearTick}/>
);
} else if( props.chartForm == CHART_FORM.DN ){
return (
@@ -73,7 +74,7 @@ function MainChart(props: MainChartProps) {
);
} else if (props.chartForm == CHART_FORM.LINEBAR){
return (
<LineBarchart chartConfig={props.chartConfig} chartData={props.chartData} chartTitle={props.chartTitle} chartClassName={props.chartClassName} graphSize={props.graphSize} yFieldText={props.yFieldText} yFieldText2={props.yFieldText2} showLegend={props.showLegend}/>
<LineBarchart chartConfig={props.chartConfig} chartData={props.chartData} chartTitle={props.chartTitle} chartClassName={props.chartClassName} graphSize={props.graphSize} yFieldText={props.yFieldText} yFieldText2={props.yFieldText2} showLegend={props.showLegend} setXAxisYearTick={props.setXAxisYearTick}/>
);
} else if (props.chartForm == CHART_FORM.LINEBAR2){
return (
@@ -137,7 +137,7 @@ export function UiTable({
: cellClick
? "cursor-pointer"
: ""
} sticky top-20 z-40 bg-secondary !font-bold`}
} sticky top-20 z-40 bg-secondary !font-bold whitespace-pre-line`}
style={{ top: `${headerHeight + index * 32 - 4}px` }}
onClick={() => handleCellClick(index, head.id)}
key={`cell-${head.id}-${index}`}
@@ -168,7 +168,7 @@ export function UiTable({
: cellClick
? "cursor-pointer"
: ""
} mt-[${boldArray.length * 40}px]`}
} mt-[${boldArray.length * 40}px] whitespace-pre-line`}
onClick={() => handleCellClick(index, head.id)}
key={`cell-${head.id}-${index}`}
>