summaryrefslogtreecommitdiff
path: root/lib/avl/components/project-field-components.tsx
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-09-15 18:58:07 +0900
committerjoonhoekim <26rote@gmail.com>2025-09-15 18:58:07 +0900
commit2b490956c9752c1b756780a3461bc1c37b6fe0a7 (patch)
treeb0b8a03c8de5dfce4b6c7373a9d608306e9147c0 /lib/avl/components/project-field-components.tsx
parente7818a457371849e29519497ebf046f385f05ab6 (diff)
(김준회) AVL 관리 및 상세 - 기능 구현 1차
+ docker compose 내 오류 수정
Diffstat (limited to 'lib/avl/components/project-field-components.tsx')
-rw-r--r--lib/avl/components/project-field-components.tsx113
1 files changed, 113 insertions, 0 deletions
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>
+)