diff --git a/src/app/[locale]/(protected)/hr/documents/new/page.tsx b/src/app/[locale]/(protected)/hr/documents/new/page.tsx new file mode 100644 index 00000000..324ca682 --- /dev/null +++ b/src/app/[locale]/(protected)/hr/documents/new/page.tsx @@ -0,0 +1,270 @@ +/** + * 사유 문서 등록 페이지 (HR Document Creation) + * + * 근태관리에서 사유 등록 시 이동하는 페이지 + * - 출장신청 (businessTripRequest) + * - 휴가신청 (vacationRequest) + * - 외근신청 (fieldWorkRequest) + * - 연장근무신청 (overtimeRequest) + */ + +'use client'; + +import { useSearchParams, useRouter } from 'next/navigation'; +import { useState, useEffect, useMemo, Suspense } from 'react'; +import { FileText, ArrowLeft, Calendar, User, Clock, MapPin, FileCheck } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Textarea } from '@/components/ui/textarea'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { ContentLoadingSpinner } from '@/components/ui/loading-spinner'; +import { format } from 'date-fns'; +import { ko } from 'date-fns/locale'; +import { toast } from 'sonner'; + +// 문서 유형 라벨 +const DOCUMENT_TYPE_LABELS: Record = { + businessTripRequest: '출장신청', + vacationRequest: '휴가신청', + fieldWorkRequest: '외근신청', + overtimeRequest: '연장근무신청', +}; + +// 문서 유형 아이콘 +const DOCUMENT_TYPE_ICONS: Record = { + businessTripRequest: MapPin, + vacationRequest: Calendar, + fieldWorkRequest: MapPin, + overtimeRequest: Clock, +}; + +// 문서 유형 설명 +const DOCUMENT_TYPE_DESCRIPTIONS: Record = { + businessTripRequest: '업무상 출장이 필요한 경우 작성합니다', + vacationRequest: '연차, 병가 등 휴가 신청 시 작성합니다', + fieldWorkRequest: '사업장 외 근무가 필요한 경우 작성합니다', + overtimeRequest: '정규 근무시간 외 연장근무 시 작성합니다', +}; + +function DocumentNewContent() { + const router = useRouter(); + const searchParams = useSearchParams(); + const documentType = searchParams.get('type') || 'businessTripRequest'; + + // 폼 상태 + const [formData, setFormData] = useState({ + title: '', + startDate: format(new Date(), 'yyyy-MM-dd'), + endDate: format(new Date(), 'yyyy-MM-dd'), + startTime: '09:00', + endTime: '18:00', + destination: '', + purpose: '', + content: '', + }); + const [isSubmitting, setIsSubmitting] = useState(false); + + // 문서 유형 정보 + const typeInfo = useMemo(() => ({ + label: DOCUMENT_TYPE_LABELS[documentType] || '문서 등록', + description: DOCUMENT_TYPE_DESCRIPTIONS[documentType] || '문서를 작성합니다', + Icon: DOCUMENT_TYPE_ICONS[documentType] || FileText, + }), [documentType]); + + // 입력 핸들러 + const handleChange = (field: string, value: string) => { + setFormData(prev => ({ ...prev, [field]: value })); + }; + + // 제출 핸들러 + const handleSubmit = async () => { + setIsSubmitting(true); + try { + // TODO: 백엔드 API 구현 필요 + // const result = await createHrDocument({ + // type: documentType, + // ...formData, + // }); + + // 임시: 성공 메시지 표시 후 이전 페이지로 이동 + toast.success(`${typeInfo.label}이 등록되었습니다`); + router.back(); + } catch (error) { + console.error('Document creation error:', error); + toast.error('문서 등록에 실패했습니다'); + } finally { + setIsSubmitting(false); + } + }; + + // 취소 핸들러 + const handleCancel = () => { + router.back(); + }; + + return ( +
+ {/* 헤더 */} +
+ + +
+
+ +
+
+

{typeInfo.label}

+

{typeInfo.description}

+
+
+
+ + {/* 폼 */} + + + + + 신청 정보 + + + 필수 정보를 입력해주세요 + + + + {/* 제목 */} +
+ + handleChange('title', e.target.value)} + /> +
+ + {/* 날짜 (출장/휴가/외근) */} + {['businessTripRequest', 'vacationRequest', 'fieldWorkRequest'].includes(documentType) && ( +
+
+ + handleChange('startDate', e.target.value)} + /> +
+
+ + handleChange('endDate', e.target.value)} + /> +
+
+ )} + + {/* 시간 (연장근무) */} + {documentType === 'overtimeRequest' && ( +
+
+ + handleChange('startTime', e.target.value)} + /> +
+
+ + handleChange('endTime', e.target.value)} + /> +
+
+ )} + + {/* 목적지/장소 (출장/외근) */} + {['businessTripRequest', 'fieldWorkRequest'].includes(documentType) && ( +
+ + handleChange('destination', e.target.value)} + /> +
+ )} + + {/* 목적/사유 */} +
+ + handleChange('purpose', e.target.value)} + /> +
+ + {/* 상세 내용 */} +
+ +