From 2b490956c9752c1b756780a3461bc1c37b6fe0a7 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Mon, 15 Sep 2025 18:58:07 +0900
Subject: (김준회) AVL 관리 및 상세 - 기능 구현 1차 + docker compose 내 오류
 수정
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/avl/components/project-field-components.tsx | 113 ++++++++++++++++++++++++
 1 file changed, 113 insertions(+)
 create mode 100644 lib/avl/components/project-field-components.tsx

(limited to 'lib/avl/components/project-field-components.tsx')

diff --git a/lib/avl/components/project-field-components.tsx b/lib/avl/components/project-field-components.tsx
new file mode 100644
index 00000000..95505d08
--- /dev/null
+++ b/lib/avl/components/project-field-components.tsx
@@ -0,0 +1,113 @@
+"use client"
+
+import * as React from "react"
+import { Input } from "@/components/ui/input"
+import { Button } from "@/components/ui/button"
+import {
+  ProjectSearchStatus,
+  getLabelStatusClassName,
+  getDisplayElementStatusClassName,
+  getInputStatusClassName
+} from "./project-field-utils"
+
+// 타입 재내보내기
+export type { ProjectSearchStatus } from "./project-field-utils"
+
+// 재사용 가능한 필드 컴포넌트들
+export interface ProjectInputFieldProps {
+  label: string
+  value: string
+  onChange: (value: string) => void
+  placeholder: string
+  status: ProjectSearchStatus
+  statusText?: string
+  minWidth?: string
+}
+
+export const ProjectInputField: React.FC<ProjectInputFieldProps> = ({
+  label,
+  value,
+  onChange,
+  placeholder,
+  status,
+  statusText,
+  minWidth = "250px"
+}) => (
+  <div className="space-y-2 min-w-[250px] flex-shrink-0" style={{ minWidth }}>
+    <label className={`text-sm font-medium ${getLabelStatusClassName(status)}`}>
+      {label}
+      {statusText && <span className="ml-1 text-xs">{statusText}</span>}
+    </label>
+    <Input
+      value={value}
+      onChange={(e) => onChange(e.target.value)}
+      placeholder={placeholder}
+      className={`h-8 text-sm ${getInputStatusClassName(status)}`}
+    />
+  </div>
+)
+
+export interface ProjectDisplayFieldProps {
+  label: string
+  value: string
+  status: ProjectSearchStatus
+  minWidth?: string
+  formatter?: (value: string) => string
+}
+
+export const ProjectDisplayField: React.FC<ProjectDisplayFieldProps> = ({
+  label,
+  value,
+  status,
+  minWidth = "120px",
+  formatter
+}) => {
+  const displayValue = status === 'searching' ? '조회 중...' : (formatter ? formatter(value) : (value || '-'))
+
+  return (
+    <div className="space-y-2 flex-shrink-0" style={{ minWidth }}>
+      <label className={`text-sm font-medium ${getLabelStatusClassName(status)}`}>
+        {label}
+        {status === 'searching' && <span className="ml-1 text-xs">(조회 중...)</span>}
+      </label>
+      <div className={`text-sm font-medium min-h-[32px] flex items-center border rounded-md px-3 bg-background ${getDisplayElementStatusClassName(status)}`}>
+        {displayValue}
+      </div>
+    </div>
+  )
+}
+
+export interface ProjectFileFieldProps {
+  label: string
+  originalFile: string
+  onFileUpload: (event: React.ChangeEvent<HTMLInputElement>) => void
+  minWidth?: string
+}
+
+export const ProjectFileField: React.FC<ProjectFileFieldProps> = ({
+  label,
+  originalFile,
+  onFileUpload,
+  minWidth = "200px"
+}) => (
+  <div className="space-y-2 flex-shrink-0" style={{ minWidth }}>
+    <label className="text-sm font-medium text-muted-foreground">{label}</label>
+    <div className="flex items-center gap-2 min-h-[32px]">
+      {originalFile ? (
+        <span className="text-sm text-blue-600">{originalFile}</span>
+      ) : (
+        <div className="relative">
+          <input
+            type="file"
+            onChange={onFileUpload}
+            className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
+            accept=".xlsx,.xls,.csv"
+          />
+          <Button variant="outline" size="sm" className="text-xs">
+            파일 선택
+          </Button>
+        </div>
+      )}
+    </div>
+  </div>
+)
-- 
cgit v1.2.3

