summaryrefslogtreecommitdiff
path: root/lib/pq/pq-review-table-new
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-08-21 06:57:36 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-08-21 06:57:36 +0000
commit02b1cf005cf3e1df64183d20ba42930eb2767a9f (patch)
treee932c54d5260b0e6fda2b46be2a6ba1c3ee30434 /lib/pq/pq-review-table-new
parentd78378ecd7ceede1429359f8058c7a99ac34b1b7 (diff)
(대표님, 최겸) 설계메뉴추가, 작업사항 업데이트
설계메뉴 - 문서관리 설계메뉴 - 벤더 데이터 gtc 메뉴 업데이트 정보시스템 - 메뉴리스트 및 정보 업데이트 파일 라우트 업데이트 엑셀임포트 개선 기본계약 개선 벤더 가입과정 변경 및 개선 벤더 기본정보 - pq 돌체 오류 수정 및 개선 벤더 로그인 과정 이메일 오류 수정
Diffstat (limited to 'lib/pq/pq-review-table-new')
-rw-r--r--lib/pq/pq-review-table-new/edit-investigation-dialog.tsx124
-rw-r--r--lib/pq/pq-review-table-new/site-visit-dialog.tsx16
2 files changed, 137 insertions, 3 deletions
diff --git a/lib/pq/pq-review-table-new/edit-investigation-dialog.tsx b/lib/pq/pq-review-table-new/edit-investigation-dialog.tsx
index 7fd1c3f8..c5470e47 100644
--- a/lib/pq/pq-review-table-new/edit-investigation-dialog.tsx
+++ b/lib/pq/pq-review-table-new/edit-investigation-dialog.tsx
@@ -40,6 +40,9 @@ import {
PopoverTrigger,
} from "@/components/ui/popover"
import { z } from "zod"
+import { getInvestigationAttachments, deleteInvestigationAttachment } from "../service"
+import { downloadFile } from "@/lib/file-download"
+import { Download } from "lucide-react"
// Validation schema for editing investigation
const editInvestigationSchema = z.object({
@@ -74,6 +77,8 @@ export function EditInvestigationDialog({
}: EditInvestigationDialogProps) {
const [isPending, startTransition] = React.useTransition()
const [selectedFiles, setSelectedFiles] = React.useState<File[]>([])
+ const [existingAttachments, setExistingAttachments] = React.useState<any[]>([])
+ const [loadingAttachments, setLoadingAttachments] = React.useState(false)
const fileInputRef = React.useRef<HTMLInputElement>(null)
const form = useForm<EditInvestigationSchema>({
@@ -96,9 +101,67 @@ export function EditInvestigationDialog({
attachments: [],
})
setSelectedFiles([])
+
+ // 기존 첨부파일 로드
+ loadExistingAttachments(investigation.id)
}
}, [investigation, form])
+ // 기존 첨부파일 로드 함수
+ const loadExistingAttachments = async (investigationId: number) => {
+ setLoadingAttachments(true)
+ try {
+ const result = await getInvestigationAttachments(investigationId)
+ if (result.success) {
+ setExistingAttachments(result.attachments || [])
+ } else {
+ toast.error("첨부파일 목록을 불러오는데 실패했습니다.")
+ }
+ } catch (error) {
+ console.error("첨부파일 로드 실패:", error)
+ toast.error("첨부파일 목록을 불러오는 중 오류가 발생했습니다.")
+ } finally {
+ setLoadingAttachments(false)
+ }
+ }
+
+ // 첨부파일 삭제 함수
+ const handleDeleteAttachment = async (attachmentId: number) => {
+ if (!investigation) return
+
+ try {
+ const result = await deleteInvestigationAttachment(attachmentId)
+ if (result.success) {
+ toast.success("첨부파일이 삭제되었습니다.")
+ // 목록 새로고침
+ loadExistingAttachments(investigation.id)
+ } else {
+ toast.error(result.error || "첨부파일 삭제에 실패했습니다.")
+ }
+ } catch (error) {
+ console.error("첨부파일 삭제 오류:", error)
+ toast.error("첨부파일 삭제 중 오류가 발생했습니다.")
+ }
+ }
+
+ // 첨부파일 다운로드 함수
+ const handleDownloadAttachment = async (attachment: any) => {
+ if (!attachment.filePath || !attachment.fileName) {
+ toast.error("첨부파일 정보가 올바르지 않습니다.")
+ return
+ }
+
+ try {
+ await downloadFile(attachment.filePath, attachment.fileName, {
+ showToast: true,
+ action: 'download'
+ })
+ } catch (error) {
+ console.error("첨부파일 다운로드 오류:", error)
+ toast.error("첨부파일 다운로드 중 오류가 발생했습니다.")
+ }
+ }
+
// 파일 선택 핸들러
const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = Array.from(event.target.files || [])
@@ -145,7 +208,7 @@ export function EditInvestigationDialog({
return (
<Dialog open={isOpen} onOpenChange={onClose}>
- <DialogContent className="sm:max-w-[425px]">
+ <DialogContent className="sm:max-w-[600px] max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>실사 정보 수정</DialogTitle>
<DialogDescription>
@@ -246,6 +309,65 @@ export function EditInvestigationDialog({
<FormLabel>첨부파일</FormLabel>
<FormControl>
<div className="space-y-4">
+ {/* 기존 첨부파일 목록 */}
+ {(existingAttachments.length > 0 || loadingAttachments) && (
+ <div className="space-y-2">
+ <div className="text-sm font-medium text-muted-foreground">기존 첨부파일</div>
+ <div className="border rounded-md p-3 space-y-2 max-h-32 overflow-y-auto">
+ {loadingAttachments ? (
+ <div className="flex items-center justify-center py-4">
+ <Loader className="h-4 w-4 animate-spin" />
+ <span className="ml-2 text-sm text-muted-foreground">
+ 첨부파일 로딩 중...
+ </span>
+ </div>
+ ) : existingAttachments.length > 0 ? (
+ existingAttachments.map((attachment) => (
+ <div key={attachment.id} className="flex items-center justify-between text-sm">
+ <div className="flex items-center space-x-2 flex-1 min-w-0">
+ <span className="text-xs px-2 py-1 bg-muted rounded">
+ {attachment.attachmentType || 'FILE'}
+ </span>
+ <span className="truncate">{attachment.fileName}</span>
+ <span className="text-muted-foreground">
+ ({attachment.fileSize ? Math.round(attachment.fileSize / 1024) : 0}KB)
+ </span>
+ </div>
+ <div className="flex items-center gap-1">
+ <Button
+ type="button"
+ variant="ghost"
+ size="sm"
+ onClick={() => handleDownloadAttachment(attachment)}
+ className="text-blue-600 hover:text-blue-700"
+ disabled={isPending}
+ title="파일 다운로드"
+ >
+ <Download className="h-4 w-4" />
+ </Button>
+ <Button
+ type="button"
+ variant="ghost"
+ size="sm"
+ onClick={() => handleDeleteAttachment(attachment.id)}
+ className="text-destructive hover:text-destructive"
+ disabled={isPending}
+ title="파일 삭제"
+ >
+ <X className="h-4 w-4" />
+ </Button>
+ </div>
+ </div>
+ ))
+ ) : (
+ <div className="text-sm text-muted-foreground text-center py-2">
+ 첨부된 파일이 없습니다.
+ </div>
+ )}
+ </div>
+ </div>
+ )}
+
{/* 파일 선택 영역 */}
<div className="border-2 border-dashed border-gray-300 rounded-lg p-6 text-center">
<input
diff --git a/lib/pq/pq-review-table-new/site-visit-dialog.tsx b/lib/pq/pq-review-table-new/site-visit-dialog.tsx
index 172aed98..2b65d03e 100644
--- a/lib/pq/pq-review-table-new/site-visit-dialog.tsx
+++ b/lib/pq/pq-review-table-new/site-visit-dialog.tsx
@@ -138,7 +138,7 @@ interface SiteVisitDialogProps {
vendorCode: string
projectName?: string
projectCode?: string
- pqItems?: string | null
+ pqItems?: Array<{itemCode: string, itemName: string}> | null
}
}
@@ -315,7 +315,19 @@ export function SiteVisitDialog({
<div>
<FormLabel className="text-sm font-medium">대상품목</FormLabel>
<div className="mt-1 p-3 bg-muted rounded-md">
- <div className="font-medium">{investigation.pqItems || "-"}</div>
+ <div className="font-medium">
+ {investigation.pqItems && investigation.pqItems.length > 0
+ ? investigation.pqItems.map((item, index) => (
+ <div key={index} className="flex items-center gap-2">
+ <span className="text-xs px-2 py-1 bg-primary/10 rounded">
+ {item.itemCode}
+ </span>
+ <span>{item.itemName}</span>
+ </div>
+ ))
+ : "-"
+ }
+ </div>
</div>
</div>
</div>