Spaces:
Running
Running
| 'use client'; | |
| /** | |
| * @license | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import { useState, useEffect } from 'react'; | |
| import { SearchParams } from '../../types/diagnosis'; | |
| import { motion } from 'framer-motion'; | |
| import { SearchSelect, SearchRadioGroup, SearchInput } from './SearchComponents'; | |
| import { diagnosisService } from '../../services/diagnosisService'; | |
| export function SearchView({ | |
| params, | |
| setParams, | |
| onNext, | |
| onReset | |
| }: { | |
| params: SearchParams; | |
| setParams: (p: SearchParams) => void; | |
| onNext: () => void; | |
| onReset?: () => void; | |
| }) { | |
| const [options, setOptions] = useState<{ | |
| jobs: string[]; | |
| bms: string[]; | |
| sales: string[]; | |
| emps: string[]; | |
| userBases: string[]; | |
| }>({ | |
| jobs: [], | |
| bms: [], | |
| sales: [], | |
| emps: [], | |
| userBases: ['지급총액', '고정급'] | |
| }); | |
| useEffect(() => { | |
| async function fetchOpts() { | |
| try { | |
| const data = await diagnosisService.getOptions({ | |
| job: params.job, | |
| bm: params.bm, | |
| sales: params.sales | |
| }); | |
| setOptions(prev => ({ | |
| jobs: data.job_options?.length ? data.job_options : prev.jobs, | |
| bms: data.bm_options?.length ? data.bm_options : prev.bms, | |
| sales: data.sales_options?.length ? data.sales_options : prev.sales, | |
| emps: data.emp_options?.length ? data.emp_options : prev.emps, | |
| userBases: ['지급총액', '고정급'], | |
| })); | |
| let newParams = { ...params }; | |
| let modified = false; | |
| if (data.job_options?.length && newParams.job && !data.job_options.includes(newParams.job)) { | |
| newParams.job = ''; | |
| modified = true; | |
| } | |
| if (data.bm_options?.length && !data.bm_options.includes(newParams.bm)) { | |
| newParams.bm = data.bm_options[0]; | |
| modified = true; | |
| } | |
| if (data.sales_options?.length && !data.sales_options.includes(newParams.sales)) { | |
| newParams.sales = data.sales_options[0]; | |
| modified = true; | |
| } | |
| if (data.emp_options?.length && !data.emp_options.includes(newParams.emp)) { | |
| newParams.emp = data.emp_options[0]; | |
| modified = true; | |
| } | |
| if (modified && newParams.job) { | |
| setParams(newParams); | |
| } | |
| } catch (e) { | |
| console.error("Failed to load dynamic options", e); | |
| } | |
| } | |
| fetchOpts(); | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [params.job, params.bm, params.sales, setParams]); | |
| return ( | |
| <div className="w-screen sm:w-auto relative left-1/2 right-1/2 -ml-[50vw] -mr-[50vw] sm:static sm:left-auto sm:right-auto sm:mx-auto sm:my-0 sm:max-w-3xl py-6 sm:py-12 px-0 sm:px-6"> | |
| <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="space-y-10"> | |
| <div className="text-center space-y-4"> | |
| <h2 className="text-3xl font-bold text-slate-900 tracking-tight">상세 분석 조건 설정</h2> | |
| <p className="text-slate-500 font-medium">정확한 시장 임금 비교를 위해 현재 상태를 입력해주세요.</p> | |
| </div> | |
| <div className="bg-white p-4 sm:p-8 md:p-12 border border-slate-100 rounded-[2rem] sm:rounded-[2.5rem] shadow-2xl shadow-slate-100 space-y-7 sm:space-y-10"> | |
| <SearchRadioGroup | |
| label="직무 선택" | |
| name="job" | |
| value={params.job} | |
| options={options.jobs} | |
| onChange={val => setParams({ | |
| ...params, | |
| job: val, | |
| bm: '', | |
| sales: '', | |
| emp: '' | |
| })} | |
| /> | |
| <div className="space-y-10"> | |
| {/* 1row : 비즈니스 모델 */} | |
| <SearchSelect | |
| label="비즈니스 모델" | |
| value={params.bm} | |
| options={options.bms} | |
| onChange={val => setParams({ ...params, bm: val })} | |
| /> | |
| {/* 2row : 매출규모 + 직원규모 */} | |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> | |
| <SearchSelect | |
| label="매출 규모" | |
| value={params.sales} | |
| options={options.sales} | |
| onChange={val => setParams({ ...params, sales: val })} | |
| /> | |
| <SearchSelect | |
| label="직원 규모" | |
| value={params.emp} | |
| options={options.emps} | |
| onChange={val => setParams({ ...params, emp: val })} | |
| /> | |
| </div> | |
| {/* 3row : 보상단위 + 보상액 */} | |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-8 items-end"> | |
| <SearchSelect | |
| label="보상 단위" | |
| value={params.userBase} | |
| options={options.userBases} | |
| onChange={val => setParams({ ...params, userBase: val })} | |
| /> | |
| <SearchInput | |
| label="현재 보상액 (세전)" | |
| value={params.userValue} | |
| unit="만원" | |
| onChange={val => setParams({ ...params, userValue: val })} | |
| /> | |
| </div> | |
| </div> | |
| <div className="grid grid-cols-1 md:grid-cols-4 gap-3 sm:gap-4 mt-8"> | |
| <button | |
| onClick={() => { | |
| if (onReset) onReset(); | |
| setOptions(prev => ({ | |
| ...prev, | |
| bms: [], | |
| sales: [], | |
| emps: [], | |
| })); | |
| }} | |
| className="md:col-span-1 h-14 text-base bg-white text-slate-400 border border-slate-100 rounded-[1.5rem] font-bold hover:bg-slate-50 hover:text-slate-600 transition-all active:scale-[0.98]" | |
| > | |
| 초기화 | |
| </button> | |
| <button | |
| onClick={onNext} | |
| disabled={!params.job} | |
| className={`md:col-span-3 h-14 text-base rounded-[1.5rem] font-bold shadow-2xl transition-all active:scale-[0.98] ${!params.job | |
| ? 'bg-slate-200 text-slate-400 cursor-not-allowed' | |
| : 'bg-slate-900 text-white shadow-slate-200 hover:bg-cyan-600 hover:shadow-cyan-200' | |
| }`} | |
| > | |
| 진단 시작하기 | |
| </button> | |
| </div> | |
| </div> | |
| </motion.div> | |
| </div> | |
| ); | |
| } | |