Files
sam-react-prod/src/components/hr/AttendanceManagement/ReasonInfoDialog.tsx
유병철 1d7b028693 feat(WEB): Phase 2-3 V2 마이그레이션 완료 및 ServerErrorPage 적용
Phase 2 완료 (4개):
- 노무관리, 단가관리(건설), 입금, 출금

Phase 3 라우팅 구조 변경 완료 (22개):
- 거래처(영업), 팝업관리, 공정관리, 게시판관리, 대손추심, Q&A
- 현장관리, 실행내역, 견적관리, 견적(테스트)
- 입찰관리, 이슈관리, 현장설명회, 견적서(건설)
- 협력업체, 시공관리, 기성관리, 품목관리(건설)
- 회계 도메인: 거래처, 매출, 세금계산서, 매입

신규 컴포넌트:
- ErrorCard: 에러 페이지 UI 통일
- ServerErrorPage: V2 페이지 에러 처리 필수
- V2 Client 컴포넌트 및 Config 파일들

총 47개 상세 페이지 중 28개 완료, 19개 제외/불필요

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 17:31:28 +09:00

175 lines
5.2 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Calendar } from '@/components/ui/calendar';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { CalendarIcon } from 'lucide-react';
import { format } from 'date-fns';
import { ko } from 'date-fns/locale';
import { cn } from '@/lib/utils';
import type {
ReasonInfoDialogProps,
ReasonFormData,
ReasonType,
} from './types';
import { REASON_TYPE_LABELS } from './types';
const initialFormData: ReasonFormData = {
employeeId: '',
baseDate: format(new Date(), 'yyyy-MM-dd'),
reasonType: '',
};
export function ReasonInfoDialog({
open,
onOpenChange,
employees,
onSubmit,
}: ReasonInfoDialogProps) {
const [formData, setFormData] = useState<ReasonFormData>(initialFormData);
const [selectedDate, setSelectedDate] = useState<Date | undefined>(new Date());
// 데이터 초기화
useEffect(() => {
if (open) {
setFormData(initialFormData);
setSelectedDate(new Date());
}
}, [open]);
// 입력 변경 핸들러
const handleChange = (field: keyof ReasonFormData, value: string) => {
setFormData(prev => ({ ...prev, [field]: value }));
};
// 날짜 변경 핸들러
const handleDateChange = (date: Date | undefined) => {
setSelectedDate(date);
if (date) {
setFormData(prev => ({ ...prev, baseDate: format(date, 'yyyy-MM-dd') }));
}
};
// 등록 (문서 작성 화면으로 이동)
const handleSubmit = () => {
onSubmit(formData);
onOpenChange(false);
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle> </DialogTitle>
</DialogHeader>
<div className="space-y-4 py-4">
{/* 대상 선택 */}
<div className="flex items-center justify-between">
<Label className="text-sm font-medium min-w-[80px]"></Label>
<Select
value={formData.employeeId}
onValueChange={(value) => handleChange('employeeId', value)}
>
<SelectTrigger className="w-[200px]">
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{employees.map((employee) => (
<SelectItem key={employee.id} value={employee.id}>
{[employee.department, employee.position, employee.rank, employee.name].filter(Boolean).join(' / ')}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* 기준일 */}
<div className="flex items-center justify-between">
<Label className="text-sm font-medium min-w-[80px]"></Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
className={cn(
'w-[200px] justify-start text-left font-normal',
!selectedDate && 'text-muted-foreground'
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{selectedDate ? format(selectedDate, 'yyyy-MM-dd') : '날짜 선택'}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="end">
<Calendar
mode="single"
selected={selectedDate}
onSelect={handleDateChange}
locale={ko}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
{/* 유형 선택 */}
<div className="flex items-center justify-between">
<Label className="text-sm font-medium min-w-[80px]"></Label>
<Select
value={formData.reasonType}
onValueChange={(value) => handleChange('reasonType', value)}
>
<SelectTrigger className="w-[200px]">
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{Object.entries(REASON_TYPE_LABELS).map(([value, label]) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
<DialogFooter className="gap-2">
<Button
variant="outline"
onClick={() => onOpenChange(false)}
className="bg-gray-900 text-white hover:bg-gray-800"
>
</Button>
<Button
onClick={handleSubmit}
className="bg-gray-900 text-white hover:bg-gray-800"
>
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}