- SelectValue children 조건부 렌더링 → placeholder prop으로 이동 - Radix UI Select 상태 관리 문제 해결 - @/lib/api barrel export 추가 (빌드 오류 해결) 수정 파일: - ApprovalLineSection.tsx: SelectValue 수정 - ReferenceSection.tsx: SelectValue 수정 - src/lib/api/index.ts: 신규 생성 빌드 검증: npm run build 성공 (349 페이지)
109 lines
3.4 KiB
TypeScript
109 lines
3.4 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { Plus, X } from 'lucide-react';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@/components/ui/select';
|
|
import type { ApprovalPerson } from './types';
|
|
import { getEmployees } from './actions';
|
|
|
|
interface ReferenceSectionProps {
|
|
data: ApprovalPerson[];
|
|
onChange: (data: ApprovalPerson[]) => void;
|
|
}
|
|
|
|
export function ReferenceSection({ data, onChange }: ReferenceSectionProps) {
|
|
const [employees, setEmployees] = useState<ApprovalPerson[]>([]);
|
|
|
|
// 직원 목록 로드
|
|
useEffect(() => {
|
|
getEmployees().then(setEmployees);
|
|
}, []);
|
|
|
|
const handleAdd = () => {
|
|
const newPerson: ApprovalPerson = {
|
|
id: `temp-${Date.now()}`,
|
|
department: '',
|
|
position: '',
|
|
name: '',
|
|
};
|
|
onChange([...data, newPerson]);
|
|
};
|
|
|
|
const handleRemove = (index: number) => {
|
|
onChange(data.filter((_, i) => i !== index));
|
|
};
|
|
|
|
const handleChange = (index: number, employeeId: string) => {
|
|
const employee = employees.find((e) => e.id === employeeId);
|
|
if (employee) {
|
|
const newData = [...data];
|
|
newData[index] = { ...employee };
|
|
onChange(newData);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="bg-white rounded-lg border p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="text-lg font-semibold">참조</h3>
|
|
<Button variant="outline" size="sm" onClick={handleAdd}>
|
|
<Plus className="w-4 h-4 mr-1" />
|
|
추가
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
<div className="text-sm text-gray-500 mb-2">부서 / 직책 / 이름</div>
|
|
|
|
{data.length === 0 ? (
|
|
<div className="text-center py-4 text-gray-400">
|
|
참조자를 추가해주세요
|
|
</div>
|
|
) : (
|
|
data.map((person, index) => (
|
|
<div key={`${person.id}-${index}`} className="flex items-center gap-2">
|
|
<span className="w-8 text-center text-sm text-gray-500">{index + 1}</span>
|
|
<Select
|
|
value={person.id.startsWith('temp-') ? undefined : person.id}
|
|
onValueChange={(value) => handleChange(index, value)}
|
|
>
|
|
<SelectTrigger className="flex-1">
|
|
<SelectValue
|
|
placeholder={
|
|
person.name && !person.id.startsWith('temp-')
|
|
? `${person.department || ''} / ${person.position || ''} / ${person.name}`
|
|
: "부서명 / 직책명 / 이름 ▼"
|
|
}
|
|
/>
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{employees.map((employee) => (
|
|
<SelectItem key={employee.id} value={employee.id}>
|
|
{employee.department || ''} / {employee.position || ''} / {employee.name}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-9 w-9 text-red-500 hover:text-red-700 hover:bg-red-50"
|
|
onClick={() => handleRemove(index)}
|
|
>
|
|
<X className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|