summaryrefslogtreecommitdiff
path: root/lib/general-contracts/detail/general-contract-yard-entry-info.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/general-contracts/detail/general-contract-yard-entry-info.tsx')
-rw-r--r--lib/general-contracts/detail/general-contract-yard-entry-info.tsx232
1 files changed, 232 insertions, 0 deletions
diff --git a/lib/general-contracts/detail/general-contract-yard-entry-info.tsx b/lib/general-contracts/detail/general-contract-yard-entry-info.tsx
new file mode 100644
index 00000000..1fb1e310
--- /dev/null
+++ b/lib/general-contracts/detail/general-contract-yard-entry-info.tsx
@@ -0,0 +1,232 @@
+'use client'
+
+import React, { useState, useEffect } from 'react'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+import { Input } from '@/components/ui/input'
+import { Label } from '@/components/ui/label'
+import { Button } from '@/components/ui/button'
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
+import { Save, LoaderIcon } from 'lucide-react'
+import { toast } from 'sonner'
+import { useSession } from 'next-auth/react'
+import { getProjects, getYardEntryInfo, saveYardEntryInfo } from '../service'
+
+interface YardEntryInfo {
+ projectId: number | null
+ projectCode: string
+ projectName: string
+ managerName: string
+ managerDepartment: string
+ rehandlingContractor: string
+}
+
+interface ContractYardEntryInfoProps {
+ contractId: number
+ readOnly?: boolean
+}
+
+export function ContractYardEntryInfo({ contractId, readOnly = false }: ContractYardEntryInfoProps) {
+ const session = useSession()
+ const userId = session.data?.user?.id ? Number(session.data.user.id) : null
+ const [isLoading, setIsLoading] = useState(false)
+ const [isSaving, setIsSaving] = useState(false)
+ const [projects, setProjects] = useState<Array<{ id: number; code: string; name: string }>>([])
+ const [formData, setFormData] = useState<YardEntryInfo>({
+ projectId: null,
+ projectCode: '',
+ projectName: '',
+ managerName: '',
+ managerDepartment: '',
+ rehandlingContractor: ''
+ })
+
+ // 프로젝트 목록 로드
+ useEffect(() => {
+ const loadProjects = async () => {
+ try {
+ const projectList = await getProjects()
+ setProjects(projectList)
+ } catch (error) {
+ console.error('Error loading projects:', error)
+ }
+ }
+ loadProjects()
+ }, [])
+
+ // 데이터 로드
+ useEffect(() => {
+ const loadYardEntryInfo = async () => {
+ setIsLoading(true)
+ try {
+ const data = await getYardEntryInfo(contractId)
+ if (data) {
+ setFormData(data)
+ }
+ } catch (error) {
+ console.error('Error loading yard entry info:', error)
+ toast.error('사외업체 야드투입 정보를 불러오는 중 오류가 발생했습니다.')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ if (contractId) {
+ loadYardEntryInfo()
+ }
+ }, [contractId])
+
+ // 저장
+ const handleSave = async () => {
+ if (!userId) {
+ toast.error('사용자 정보를 찾을 수 없습니다.')
+ return
+ }
+
+ // 유효성 검사
+ if (!formData.projectId) {
+ toast.error('프로젝트를 선택해주세요.')
+ return
+ }
+
+ setIsSaving(true)
+ try {
+ await saveYardEntryInfo(contractId, formData, userId)
+ toast.success('사외업체 야드투입 정보가 저장되었습니다.')
+ } catch (error) {
+ console.error('Error saving yard entry info:', error)
+ toast.error('사외업체 야드투입 정보 저장 중 오류가 발생했습니다.')
+ } finally {
+ setIsSaving(false)
+ }
+ }
+
+ const selectedProject = projects.find(p => p.id === formData.projectId)
+
+ if (isLoading) {
+ return (
+ <Card>
+ <CardHeader>
+ <CardTitle>사외업체 야드투입 정보</CardTitle>
+ </CardHeader>
+ <CardContent>
+ <div className="flex items-center justify-center py-8">
+ <LoaderIcon className="w-6 h-6 animate-spin mr-2" />
+ <span>로딩 중...</span>
+ </div>
+ </CardContent>
+ </Card>
+ )
+ }
+
+ return (
+ <Card>
+ <CardHeader>
+ <div className="flex items-center justify-between">
+ <CardTitle>사외업체 야드투입 정보</CardTitle>
+ {!readOnly && (
+ <Button
+ onClick={handleSave}
+ disabled={isSaving}
+ >
+ {isSaving ? (
+ <>
+ <LoaderIcon className="w-4 h-4 mr-2 animate-spin" />
+ 저장 중...
+ </>
+ ) : (
+ <>
+ <Save className="w-4 h-4 mr-2" />
+ 저장
+ </>
+ )}
+ </Button>
+ )}
+ </div>
+ </CardHeader>
+ <CardContent>
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+ {/* 프로젝트 */}
+ <div className="flex flex-col gap-2">
+ <Label htmlFor="project">프로젝트 *</Label>
+ {readOnly ? (
+ <div className="text-sm">
+ {selectedProject ? `${selectedProject.code} - ${selectedProject.name}` : '-'}
+ </div>
+ ) : (
+ <Select
+ value={formData.projectId?.toString() || ''}
+ onValueChange={(value) => {
+ const projectId = parseInt(value)
+ const project = projects.find(p => p.id === projectId)
+ setFormData(prev => ({
+ ...prev,
+ projectId: projectId,
+ projectCode: project?.code || '',
+ projectName: project?.name || ''
+ }))
+ }}
+ >
+ <SelectTrigger>
+ <SelectValue placeholder="프로젝트 선택" />
+ </SelectTrigger>
+ <SelectContent>
+ {projects.map((project) => (
+ <SelectItem key={project.id} value={project.id.toString()}>
+ {project.code} - {project.name}
+ </SelectItem>
+ ))}
+ </SelectContent>
+ </Select>
+ )}
+ </div>
+
+ {/* 관리담당자 */}
+ <div className="flex flex-col gap-2">
+ <Label htmlFor="managerName">관리담당자</Label>
+ {readOnly ? (
+ <div className="text-sm">{formData.managerName || '-'}</div>
+ ) : (
+ <Input
+ id="managerName"
+ value={formData.managerName}
+ onChange={(e) => setFormData(prev => ({ ...prev, managerName: e.target.value }))}
+ placeholder="관리담당자 입력"
+ />
+ )}
+ </div>
+
+ {/* 관리부서 */}
+ <div className="flex flex-col gap-2">
+ <Label htmlFor="managerDepartment">관리부서</Label>
+ {readOnly ? (
+ <div className="text-sm">{formData.managerDepartment || '-'}</div>
+ ) : (
+ <Input
+ id="managerDepartment"
+ value={formData.managerDepartment}
+ onChange={(e) => setFormData(prev => ({ ...prev, managerDepartment: e.target.value }))}
+ placeholder="관리부서 입력"
+ />
+ )}
+ </div>
+
+ {/* 재하도협력사 */}
+ <div className="flex flex-col gap-2">
+ <Label htmlFor="rehandlingContractor">재하도협력사</Label>
+ {readOnly ? (
+ <div className="text-sm">{formData.rehandlingContractor || '-'}</div>
+ ) : (
+ <Input
+ id="rehandlingContractor"
+ value={formData.rehandlingContractor}
+ onChange={(e) => setFormData(prev => ({ ...prev, rehandlingContractor: e.target.value }))}
+ placeholder="재하도협력사 입력"
+ />
+ )}
+ </div>
+ </div>
+ </CardContent>
+ </Card>
+ )
+}
+