summaryrefslogtreecommitdiff
path: root/lib/general-contracts_old/detail/general-contract-offset-details.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/general-contracts_old/detail/general-contract-offset-details.tsx')
-rw-r--r--lib/general-contracts_old/detail/general-contract-offset-details.tsx314
1 files changed, 314 insertions, 0 deletions
diff --git a/lib/general-contracts_old/detail/general-contract-offset-details.tsx b/lib/general-contracts_old/detail/general-contract-offset-details.tsx
new file mode 100644
index 00000000..af4f2ef2
--- /dev/null
+++ b/lib/general-contracts_old/detail/general-contract-offset-details.tsx
@@ -0,0 +1,314 @@
+'use client'
+
+import React, { useState, useEffect } from 'react'
+import { useSession } from 'next-auth/react'
+import { Input } from '@/components/ui/input'
+import { Button } from '@/components/ui/button'
+import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
+import { Checkbox } from '@/components/ui/checkbox'
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
+import { Plus, Trash2, Save, LoaderIcon, RotateCcw } from 'lucide-react'
+import { getOffsetDetails, updateOffsetDetails } from '../service'
+import { toast } from 'sonner'
+
+interface OffsetDetailsProps {
+ contractId: number
+ contractType?: string
+}
+
+interface OffsetDetailItem {
+ id: string
+ project: string
+ poNumber: string
+ poItemDescription: string
+ offsetReason: string
+ contractCurrency: string
+ contractAmount: string
+ offsetDate: string
+ remark: string
+}
+
+export function OffsetDetails({ contractId }: OffsetDetailsProps) {
+ const session = useSession()
+ const [isLoading, setIsLoading] = useState(false)
+ const [isEnabled, setIsEnabled] = useState(true)
+
+ // 특정 계약종류를 제외한 일반계약은 Default로 표시
+ const isDisabled = false
+
+ const [offsetDetails, setOffsetDetails] = useState<OffsetDetailItem[]>([])
+
+ // 회입/상계사유 옵션
+ const offsetReasonOptions = [
+ '판매자 사양불만족',
+ '납기지연',
+ '품질불량',
+ '계약조건변경',
+ '기타'
+ ]
+
+ // 초기 데이터 로드
+ useEffect(() => {
+ const loadOffsetDetails = async () => {
+ try {
+ const data = await getOffsetDetails(contractId)
+ if (data && data.enabled !== undefined) {
+ setIsEnabled(data.enabled)
+ setOffsetDetails(data.offsetDetails || [])
+ } else {
+ }
+ } catch (error) {
+ console.error('회입/상계내역 데이터 로드 실패:', error)
+ toast.error('회입/상계내역 데이터를 불러오는데 실패했습니다.')
+ }
+ }
+
+ loadOffsetDetails()
+ }, [contractId])
+
+ const addOffsetDetailRow = () => {
+ const newRow: OffsetDetailItem = {
+ id: Date.now().toString(),
+ project: '',
+ poNumber: '',
+ poItemDescription: '',
+ offsetReason: '',
+ contractCurrency: 'KRW',
+ contractAmount: '',
+ offsetDate: '',
+ remark: ''
+ }
+ setOffsetDetails([...offsetDetails, newRow])
+ }
+
+ const removeOffsetDetailRow = (id: string) => {
+ setOffsetDetails(offsetDetails.filter(item => item.id !== id))
+ }
+
+ const updateOffsetDetailData = (id: string, field: keyof OffsetDetailItem, value: string) => {
+ setOffsetDetails(prev =>
+ prev.map(item =>
+ item.id === id ? { ...item, [field]: value } : item
+ )
+ )
+ }
+
+ const handleSaveOffsetDetails = async () => {
+ if (!session.data?.user?.id) {
+ toast.error('로그인이 필요합니다.')
+ return
+ }
+
+ setIsLoading(true)
+ try {
+ const offsetDetailsData = {
+ enabled: isEnabled,
+ offsetDetails: offsetDetails
+ }
+
+ await updateOffsetDetails(contractId, offsetDetailsData, Number(session.data.user.id))
+ toast.success('회입/상계내역이 성공적으로 저장되었습니다.')
+ } catch (error) {
+ console.error('회입/상계내역 저장 실패:', error)
+ toast.error('회입/상계내역 저장에 실패했습니다.')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+ <div className="w-full">
+ <Accordion type="single" collapsible className="w-full">
+ <AccordionItem value="offset-details">
+ <AccordionTrigger className="hover:no-underline">
+ <div className="flex items-center gap-3 w-full">
+ <RotateCcw className="w-5 h-5" />
+ <span className="font-medium">회입/상계내역</span>
+ </div>
+ </AccordionTrigger>
+ <AccordionContent>
+ <div className="space-y-6">
+ {/* 체크박스 */}
+ <div className="flex items-center gap-2">
+ <Checkbox
+ checked={isEnabled}
+ disabled={isDisabled}
+ onCheckedChange={(checked) => {
+ if (!isDisabled) {
+ setIsEnabled(checked as boolean)
+ }
+ }}
+ />
+ <span className="text-sm font-medium">회입/상계내역 활성화</span>
+ </div>
+
+ {/* 회입/상계내역 테이블 */}
+ <div className="space-y-4">
+ <div className="flex items-center justify-between">
+ <h3 className="text-lg font-medium">회입/상계내역</h3>
+ <div className="flex gap-2">
+ <Button
+ type="button"
+ variant="outline"
+ size="sm"
+ onClick={addOffsetDetailRow}
+ disabled={isDisabled || !isEnabled}
+ className="flex items-center gap-2"
+ >
+ <Plus className="w-4 h-4" />
+ 행 추가
+ </Button>
+ <Button
+ type="button"
+ variant="outline"
+ size="sm"
+ onClick={() => {
+ if (confirm('선택된 행들을 삭제하시겠습니까?')) {
+ // 선택된 행들 삭제 로직 (필요시 구현)
+ }
+ }}
+ disabled={isDisabled || !isEnabled}
+ className="flex items-center gap-2"
+ >
+ <Trash2 className="w-4 h-4" />
+ 행 삭제
+ </Button>
+ </div>
+ </div>
+
+ <div className="overflow-x-auto">
+ <table className={`w-full border-collapse border border-gray-300 ${!isEnabled ? 'opacity-50' : ''}`}>
+ <thead>
+ <tr className="bg-yellow-100">
+ <th className="border border-gray-300 p-2 w-16">No.</th>
+ <th className="border border-gray-300 p-2 w-32">프로젝트</th>
+ <th className="border border-gray-300 p-2 w-40">발주번호</th>
+ <th className="border border-gray-300 p-2">발주품목(Description)</th>
+ <th className="border border-gray-300 p-2 w-40">회입/상계사유</th>
+ <th className="border border-gray-300 p-2 w-32">계약통화</th>
+ <th className="border border-gray-300 p-2 w-32">계약금액</th>
+ <th className="border border-gray-300 p-2 w-32">회입/상계일</th>
+ <th className="border border-gray-300 p-2">비고</th>
+ <th className="border border-gray-300 p-2 w-20">Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ {offsetDetails.map((item, index) => (
+ <tr key={item.id} className="bg-yellow-50">
+ <td className="border border-gray-300 p-2 text-center">{index + 1}</td>
+ <td className="border border-gray-300 p-2">
+ <Input
+ value={item.project}
+ onChange={(e) => updateOffsetDetailData(item.id, 'project', e.target.value)}
+ disabled={isDisabled || !isEnabled}
+ className="border-0 bg-transparent p-0 h-auto"
+ />
+ </td>
+ <td className="border border-gray-300 p-2">
+ <Input
+ value={item.poNumber}
+ onChange={(e) => updateOffsetDetailData(item.id, 'poNumber', e.target.value)}
+ disabled={isDisabled || !isEnabled}
+ className="border-0 bg-transparent p-0 h-auto"
+ />
+ </td>
+ <td className="border border-gray-300 p-2">
+ <Input
+ value={item.poItemDescription}
+ onChange={(e) => updateOffsetDetailData(item.id, 'poItemDescription', e.target.value)}
+ disabled={isDisabled || !isEnabled}
+ className="border-0 bg-transparent p-0 h-auto"
+ />
+ </td>
+ <td className="border border-gray-300 p-2">
+ <Select
+ value={item.offsetReason}
+ onValueChange={(value) => updateOffsetDetailData(item.id, 'offsetReason', value)}
+ disabled={isDisabled || !isEnabled}
+ >
+ <SelectTrigger className="border-0 bg-transparent p-0 h-auto">
+ <SelectValue placeholder="선택하세요" />
+ </SelectTrigger>
+ <SelectContent>
+ {offsetReasonOptions.map((option) => (
+ <SelectItem key={option} value={option}>
+ {option}
+ </SelectItem>
+ ))}
+ </SelectContent>
+ </Select>
+ </td>
+ <td className="border border-gray-300 p-2">
+ <Input
+ value={item.contractCurrency}
+ onChange={(e) => updateOffsetDetailData(item.id, 'contractCurrency', e.target.value)}
+ disabled={isDisabled || !isEnabled}
+ className="border-0 bg-transparent p-0 h-auto"
+ />
+ </td>
+ <td className="border border-gray-300 p-2">
+ <Input
+ value={item.contractAmount}
+ onChange={(e) => updateOffsetDetailData(item.id, 'contractAmount', e.target.value)}
+ disabled={isDisabled || !isEnabled}
+ className="border-0 bg-transparent p-0 h-auto"
+ />
+ </td>
+ <td className="border border-gray-300 p-2">
+ <Input
+ type="date"
+ value={item.offsetDate}
+ onChange={(e) => updateOffsetDetailData(item.id, 'offsetDate', e.target.value)}
+ disabled={isDisabled || !isEnabled}
+ className="border-0 bg-transparent p-0 h-auto"
+ />
+ </td>
+ <td className="border border-gray-300 p-2">
+ <Input
+ value={item.remark}
+ onChange={(e) => updateOffsetDetailData(item.id, 'remark', e.target.value)}
+ disabled={isDisabled || !isEnabled}
+ className="border-0 bg-transparent p-0 h-auto"
+ />
+ </td>
+ <td className="border border-gray-300 p-2 text-center">
+ <Button
+ type="button"
+ variant="ghost"
+ size="sm"
+ onClick={() => removeOffsetDetailRow(item.id)}
+ disabled={isDisabled || !isEnabled}
+ className="h-8 w-8 p-0 text-red-600 hover:text-red-700"
+ >
+ <Trash2 className="w-4 h-4" />
+ </Button>
+ </td>
+ </tr>
+ ))}
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ {/* 저장 버튼 */}
+ <div className="flex justify-end pt-4 border-t">
+ <Button
+ onClick={handleSaveOffsetDetails}
+ disabled={isLoading || isDisabled || !isEnabled}
+ className="flex items-center gap-2"
+ >
+ {isLoading ? (
+ <LoaderIcon className="w-4 h-4 animate-spin" />
+ ) : (
+ <Save className="w-4 h-4" />
+ )}
+ 회입/상계내역 저장
+ </Button>
+ </div>
+ </div>
+ </AccordionContent>
+ </AccordionItem>
+ </Accordion>
+ </div>
+ )
+}