st: 기본 셋팅
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import useSWR from 'swr';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Label,
|
||||
Select,
|
||||
SelectTrigger,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectValue
|
||||
}
|
||||
from "@common/components";
|
||||
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
import { type SearchFormProps, type SearchFormValues, defaultSearchFormProps } from "../type/SearchForm.type";
|
||||
import { statisticsAPi } from "@/entities/statistics/api/statistics-service";
|
||||
import type { ApiResponse, Sido, Sgg } from "@/entities/statistics/model/statistics-interface";
|
||||
|
||||
const getSidoListFetcher = async (): Promise<ApiResponse<Sido[]>> => {
|
||||
return statisticsAPi.getSidoList();
|
||||
};
|
||||
|
||||
const getSggListFetcher = async ([_key, sidoName]: [string, string]): Promise<ApiResponse<Sgg[]>> => {
|
||||
return statisticsAPi.getSggList(sidoName);
|
||||
};
|
||||
|
||||
const SearchForm = (props: SearchFormProps = {}) => {
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const mergedProps = { ...defaultSearchFormProps, ...props };
|
||||
const [values, setValues] = useState<SearchFormValues>({
|
||||
sido: props.defaultValues?.sido || "",
|
||||
sgg: props.defaultValues?.sgg || "",
|
||||
year: props.defaultValues?.year || "",
|
||||
order: props.defaultValues?.order || "",
|
||||
fctName: props.defaultValues?.fctName || "",
|
||||
});
|
||||
|
||||
const { data: sidoList } = useSWR<ApiResponse<Sido[]>>(
|
||||
"sido-list",
|
||||
getSidoListFetcher,
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false,
|
||||
revalidateIfStale: false,
|
||||
dedupingInterval: 2000,
|
||||
shouldRetryOnError: false,
|
||||
onSuccess: (data) => {
|
||||
if (data.status !== 'success') {
|
||||
alert(`시도 목록을 불러오는데 실패했습니다.
|
||||
새로고침 후 다시 시도해주세요.`);
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
alert(`시도 목록을 불러오는데 실패했습니다.
|
||||
새로고침 후 다시 시도해주세요.`);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const { data: sggList } = useSWR<ApiResponse<Sgg[]>>(
|
||||
values.sido && values.sido !== "ALL" ? ["sgg-list", values.sido] : null,
|
||||
getSggListFetcher,
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false,
|
||||
revalidateIfStale: false,
|
||||
dedupingInterval: 2000,
|
||||
shouldRetryOnError: false,
|
||||
onSuccess: (data) => {
|
||||
if (data.status !== 'success') {
|
||||
alert(`시군구 목록을 불러오는데 실패했습니다.
|
||||
새로고침 후 다시 시도해주세요.`);
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
alert(`시군구 목록을 불러오는데 실패했습니다.
|
||||
새로고침 후 다시 시도해주세요.`);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
props.onSubmit?.(values);
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
const resetValues: SearchFormValues = {
|
||||
sido: "",
|
||||
sgg: "",
|
||||
year: "",
|
||||
order: "",
|
||||
fctName: "",
|
||||
};
|
||||
setValues(resetValues);
|
||||
props.onReset?.();
|
||||
props.onSubmit?.(resetValues);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="flex items-center gap-8 p-2">
|
||||
{mergedProps.sido &&
|
||||
<div className="flex items-center gap-2">
|
||||
<Label className="text-label">
|
||||
시도
|
||||
</Label>
|
||||
<Select value={values.sido} onValueChange={(value) => setValues((prev) => ({ ...prev, sido: value, sgg: 'ALL' }))}>
|
||||
<SelectTrigger className="w-[12rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</SelectItem>
|
||||
{sidoList?.data?.map((sido) => (
|
||||
<SelectItem key={sido.adstDstrCd} value={sido.sido}>
|
||||
{sido.sido}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
}
|
||||
{mergedProps.sgg &&
|
||||
<div className="flex items-center gap-2">
|
||||
<Label className="text-label">
|
||||
시군구
|
||||
</Label>
|
||||
<Select value={values.sgg} onValueChange={(value) => setValues({ ...values, sgg: value })}>
|
||||
<SelectTrigger className="w-[12rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</SelectItem>
|
||||
{sggList?.data?.map((sgg) => (
|
||||
<SelectItem key={sgg.adstDstrCd} value={sgg.gugun}>
|
||||
{sgg.gugun}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
}
|
||||
{mergedProps.year &&
|
||||
<div className="flex items-center gap-2">
|
||||
<Label className="text-label">
|
||||
년도
|
||||
</Label>
|
||||
<Select value={values.year} onValueChange={(value) => setValues({ ...values, year: value })}>
|
||||
<SelectTrigger className="w-[10rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
}
|
||||
{mergedProps.order &&
|
||||
<div className="flex items-center gap-2">
|
||||
<Label className="text-label">
|
||||
차수
|
||||
</Label>
|
||||
<Select value={values.order} onValueChange={(value) => setValues({ ...values, order: value })}>
|
||||
<SelectTrigger className="w-[10rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
}
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Button color="green" className="h-[3.2rem]" type="button" onClick={handleReset}>
|
||||
초기화
|
||||
</Button>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{(mergedProps.fctName || mergedProps.userMenual) &&
|
||||
<div className="flex items-center p-2">
|
||||
{mergedProps.fctName &&
|
||||
<div className="flex items-center gap-2">
|
||||
<Label htmlFor="liSnSearchInput" className="mr-2 text-label">
|
||||
시설명
|
||||
</Label>
|
||||
<Input
|
||||
className="h-[3.2rem] w-[14rem] rounded-sm !text-[1.3rem] mr-4"
|
||||
id="liSnSearchInput"
|
||||
value={values.fctName}
|
||||
onChange={(e) => setValues({ ...values, fctName: e.target.value })}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
{mergedProps.userMenual &&
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Button className="h-[3.2rem]" type="button">
|
||||
<i className="diveicon di-person-fill" />
|
||||
사용자 메뉴얼
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchForm;
|
||||
Reference in New Issue
Block a user