summaryrefslogtreecommitdiff
path: root/components/vendor-data-plant/sidebar.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-12-01 00:58:23 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-12-01 00:58:23 +0000
commit8440ac29c7dcbef992039678ecc0fabff2fd04ec (patch)
tree59092b8dcd22135009bf70d5863ffde444e5bed2 /components/vendor-data-plant/sidebar.tsx
parent748f68bb7b5d02450664651ae5025c9a38fb71a5 (diff)
(대표님) S-EDP 관련 대표님 작업사항
Diffstat (limited to 'components/vendor-data-plant/sidebar.tsx')
-rw-r--r--components/vendor-data-plant/sidebar.tsx479
1 files changed, 220 insertions, 259 deletions
diff --git a/components/vendor-data-plant/sidebar.tsx b/components/vendor-data-plant/sidebar.tsx
index 31ee6dc7..b746e69d 100644
--- a/components/vendor-data-plant/sidebar.tsx
+++ b/components/vendor-data-plant/sidebar.tsx
@@ -10,304 +10,265 @@ import {
TooltipTrigger,
TooltipContent,
} from "@/components/ui/tooltip"
-import { Package2, FormInput } from "lucide-react"
-import { useRouter, usePathname } from "next/navigation"
+import { List, FormInput, FileText } from "lucide-react"
import { Skeleton } from "@/components/ui/skeleton"
-import { type FormInfo } from "@/lib/forms/services"
+import { getEngineeringForms, getIMForms } from "@/lib/tags-plant/service"
-interface PackageData {
- itemId: number
- itemName: string
+interface FormInfo {
+ formCode: string
+ formName: string
}
interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {
isCollapsed: boolean
- packages: PackageData[]
- selectedPackageId: number | null
- selectedProjectId: number | null
- selectedContractId: number | null
- onSelectPackage: (itemId: number) => void
- forms?: FormInfo[]
- onSelectForm: (formName: string) => void
- isLoadingForms?: boolean
- mode: "IM" | "ENG"
+ selectedPackageCode: string | null
+ selectedFormCode: string | null
+ currentMode: "master" | "engineering" | "im" | null
+ projectCode: string // 추가
+ onMasterTagListClick: () => void
+ onEngineeringFormClick: (formCode: string) => void
+ onIMFormClick: (formCode: string) => void
}
export function Sidebar({
className,
isCollapsed,
- packages,
- selectedPackageId,
- selectedProjectId,
- selectedContractId,
- onSelectPackage,
- forms,
- onSelectForm,
- isLoadingForms = false,
- mode = "IM",
+ selectedPackageCode,
+ selectedFormCode,
+ currentMode,
+ projectCode, // 추가
+ onMasterTagListClick,
+ onEngineeringFormClick,
+ onIMFormClick,
}: SidebarProps) {
- const router = useRouter()
- const rawPathname = usePathname()
- const pathname = rawPathname ?? ""
+ const [engineeringForms, setEngineeringForms] = React.useState<FormInfo[]>([])
+ const [imForms, setIMForms] = React.useState<FormInfo[]>([])
+ const [isLoadingEngineering, setIsLoadingEngineering] = React.useState(false)
+ const [isLoadingIM, setIsLoadingIM] = React.useState(false)
- /**
- * ---------------------------
- * 1) URL에서 현재 패키지 / 폼 코드 추출
- * ---------------------------
- */
- const segments = pathname.split("/").filter(Boolean)
-
- let currentItemId: number | null = null
- let currentFormCode: string | null = null
+ // Engineering 폼 로드
+ React.useEffect(() => {
+ if (!selectedPackageCode || !projectCode) {
+ setEngineeringForms([])
+ return
+ }
- const tagIndex = segments.indexOf("tag")
- if (tagIndex !== -1 && segments[tagIndex + 1]) {
- currentItemId = parseInt(segments[tagIndex + 1], 10)
- }
+ const loadEngineeringForms = async () => {
+ setIsLoadingEngineering(true)
+ try {
+ const result = await getEngineeringForms(projectCode, selectedPackageCode)
+ setEngineeringForms(result)
+ } catch (error) {
+ console.error("Engineering 폼 로딩 오류:", error)
+ setEngineeringForms([])
+ } finally {
+ setIsLoadingEngineering(false)
+ }
+ }
- const formIndex = segments.indexOf("form")
- if (formIndex !== -1) {
- const itemSegment = segments[formIndex + 1]
- const codeSegment = segments[formIndex + 2]
+ loadEngineeringForms()
+ }, [selectedPackageCode, projectCode])
- if (itemSegment) {
- currentItemId = parseInt(itemSegment, 10)
- }
- if (codeSegment) {
- currentFormCode = codeSegment
+ // IM 폼 로드
+ React.useEffect(() => {
+ if (!selectedPackageCode || !projectCode) {
+ setIMForms([])
+ return
}
- }
- /**
- * ---------------------------
- * 2) 패키지 클릭 핸들러 (IM 모드)
- * ---------------------------
- */
- const handlePackageClick = (itemId: number) => {
- // 상위 컴포넌트 상태 업데이트
- onSelectPackage(itemId)
-
- // 해당 태그 페이지로 라우팅
- // 예: /vendor-data-plant/tag/123
- const baseSegments = segments.slice(0, segments.indexOf("vendor-data-plant") + 1).join("/")
- router.push(`/${baseSegments}/tag/${itemId}`)
- }
+ const loadIMForms = async () => {
+ setIsLoadingIM(true)
+ try {
+ const result = await getIMForms(projectCode, selectedPackageCode)
+ setIMForms(result)
+ } catch (error) {
+ console.error("IM 폼 로딩 오류:", error)
+ setIMForms([])
+ } finally {
+ setIsLoadingIM(false)
+ }
+ }
- /**
- * ---------------------------
- * 3) 폼 클릭 핸들러 (IM 모드만 사용)
- * ---------------------------
- */
- const handleFormClick = (form: FormInfo) => {
- // IM 모드에서만 사용
- if (selectedPackageId === null) return;
-
- onSelectForm(form.formName)
-
- const baseSegments = segments.slice(0, segments.indexOf("vendor-data-plant") + 1).join("/")
- router.push(`/${baseSegments}/form/${selectedPackageId}/${form.formCode}/${selectedProjectId}/${selectedContractId}?mode=${mode}`)
- }
+ loadIMForms()
+ }, [selectedPackageCode, projectCode])
- /**
- * ---------------------------
- * 4) 패키지 클릭 핸들러 (ENG 모드)
- * ---------------------------
- */
- const handlePackageUnderFormClick = (form: FormInfo, pkg: PackageData) => {
- onSelectForm(form.formName)
- onSelectPackage(pkg.itemId)
-
- const baseSegments = segments.slice(0, segments.indexOf("vendor-data-plant") + 1).join("/")
- router.push(`/${baseSegments}/form/${pkg.itemId}/${form.formCode}/${selectedProjectId}/${selectedContractId}?mode=${mode}`)
- }
+ const isMasterActive = currentMode === "master"
+ const isPackageSelected = selectedPackageCode !== null
return (
<div className={cn("pb-12", className)}>
<div className="space-y-4 py-4">
- {/* ---------- 패키지(Items) 목록 - IM 모드에서만 표시 ---------- */}
- {mode === "IM" && (
- <>
- <div className="py-1">
- <h2 className="relative px-7 text-lg font-semibold tracking-tight">
- {isCollapsed ? "P" : "Package Lists"}
- </h2>
- <ScrollArea className="h-[150px] px-1">
- <div className="space-y-1 p-2">
- {packages.map((pkg) => {
- const isActive = pkg.itemId === currentItemId
+ {/* Master Tag List */}
+ <div className="py-1">
+ <h2 className="relative px-7 text-lg font-semibold tracking-tight">
+ {isCollapsed ? "M" : "Master"}
+ </h2>
+ <div className="space-y-1 p-2">
+ {isCollapsed ? (
+ <Tooltip delayDuration={0}>
+ <TooltipTrigger asChild>
+ <Button
+ variant="ghost"
+ className={cn(
+ "w-full justify-start font-normal",
+ isMasterActive && "bg-accent text-accent-foreground"
+ )}
+ onClick={onMasterTagListClick}
+ disabled={!isPackageSelected}
+ >
+ <List className="h-4 w-4" />
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent side="right">
+ Master Tag List
+ </TooltipContent>
+ </Tooltip>
+ ) : (
+ <Button
+ variant="ghost"
+ className={cn(
+ "w-full justify-start font-normal",
+ isMasterActive && "bg-accent text-accent-foreground"
+ )}
+ onClick={onMasterTagListClick}
+ disabled={!isPackageSelected}
+ >
+ <List className="mr-2 h-4 w-4" />
+ Master Tag List
+ </Button>
+ )}
+ </div>
+ </div>
- return (
- <div key={pkg.itemId}>
- {isCollapsed ? (
- <Tooltip delayDuration={0}>
- <TooltipTrigger asChild>
- <Button
- variant="ghost"
- className={cn(
- "w-full justify-start font-normal",
- isActive && "bg-accent text-accent-foreground"
- )}
- onClick={() => handlePackageClick(pkg.itemId)}
- >
- <Package2 className="mr-2 h-4 w-4" />
- </Button>
- </TooltipTrigger>
- <TooltipContent side="right">
- {pkg.itemName}
- </TooltipContent>
- </Tooltip>
- ) : (
- <Button
- variant="ghost"
- className={cn(
- "w-full justify-start font-normal",
- isActive && "bg-accent text-accent-foreground"
- )}
- onClick={() => handlePackageClick(pkg.itemId)}
- >
- <Package2 className="mr-2 h-4 w-4" />
- {pkg.itemName}
- </Button>
- )}
- </div>
- )
- })}
- </div>
- </ScrollArea>
- </div>
- <Separator />
- </>
- )}
+ <Separator />
- {/* ---------- 폼 목록 (IM 모드) / 패키지와 폼 목록 (ENG 모드) ---------- */}
+ {/* Engineering Forms */}
<div className="py-1">
<h2 className="relative px-7 text-lg font-semibold tracking-tight">
- {isCollapsed
- ? (mode === "IM" ? "F" : "P")
- : (mode === "IM" ? "Form Lists" : "Package Lists")
- }
+ {isCollapsed ? "E" : "Engineering"}
</h2>
- <ScrollArea className={cn(
- "px-1",
- mode === "IM" ? "h-[300px]" : "h-[450px]"
- )}>
+ <ScrollArea className="h-[250px] px-1">
<div className="space-y-1 p-2">
- {isLoadingForms ? (
+ {isLoadingEngineering ? (
Array.from({ length: 3 }).map((_, index) => (
- <div key={`form-skeleton-${index}`} className="px-2 py-1.5">
+ <div key={`eng-skeleton-${index}`} className="px-2 py-1.5">
<Skeleton className="h-8 w-full" />
</div>
))
- ) : mode === "IM" ? (
- // =========== IM 모드: 폼만 표시 ===========
- !forms || forms.length === 0 ? (
- <p className="text-sm text-muted-foreground px-2">
- (No forms loaded)
- </p>
- ) : (
- forms.map((form) => {
- const isFormActive = form.formCode === currentFormCode
- const isDisabled = currentItemId === null
+ ) : !isPackageSelected ? (
+ <p className="text-sm text-muted-foreground px-2">
+ Select a package first
+ </p>
+ ) : engineeringForms.length === 0 ? (
+ <p className="text-sm text-muted-foreground px-2">
+ No forms available
+ </p>
+ ) : (
+ engineeringForms.map((form) => {
+ const isActive =
+ currentMode === "engineering" &&
+ form.formCode === selectedFormCode
- return isCollapsed ? (
- <Tooltip key={form.formCode} delayDuration={0}>
- <TooltipTrigger asChild>
- <Button
- variant="ghost"
- className={cn(
- "w-full justify-start font-normal",
- isFormActive && "bg-accent text-accent-foreground"
- )}
- onClick={() => handleFormClick(form)}
- disabled={isDisabled}
- >
- <FormInput className="mr-2 h-4 w-4" />
- </Button>
- </TooltipTrigger>
- <TooltipContent side="right">
- {form.formName}
- </TooltipContent>
- </Tooltip>
- ) : (
- <Button
- key={form.formCode}
- variant="ghost"
- className={cn(
- "w-full justify-start font-normal",
- isFormActive && "bg-accent text-accent-foreground"
- )}
- onClick={() => handleFormClick(form)}
- disabled={isDisabled}
- >
- <FormInput className="mr-2 h-4 w-4" />
+ return isCollapsed ? (
+ <Tooltip key={form.formCode} delayDuration={0}>
+ <TooltipTrigger asChild>
+ <Button
+ variant="ghost"
+ className={cn(
+ "w-full justify-start font-normal",
+ isActive && "bg-accent text-accent-foreground"
+ )}
+ onClick={() => onEngineeringFormClick(form.formCode)}
+ >
+ <FormInput className="h-4 w-4" />
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent side="right">
{form.formName}
- </Button>
- )
- })
- )
+ </TooltipContent>
+ </Tooltip>
+ ) : (
+ <Button
+ key={form.formCode}
+ variant="ghost"
+ className={cn(
+ "w-full justify-start font-normal",
+ isActive && "bg-accent text-accent-foreground"
+ )}
+ onClick={() => onEngineeringFormClick(form.formCode)}
+ >
+ <FormInput className="mr-2 h-4 w-4" />
+ {form.formName}
+ </Button>
+ )
+ })
+ )}
+ </div>
+ </ScrollArea>
+ </div>
+
+ <Separator />
+
+ {/* IM Forms */}
+ <div className="py-1">
+ <h2 className="relative px-7 text-lg font-semibold tracking-tight">
+ {isCollapsed ? "I" : "IM"}
+ </h2>
+ <ScrollArea className="h-[250px] px-1">
+ <div className="space-y-1 p-2">
+ {isLoadingIM ? (
+ Array.from({ length: 3 }).map((_, index) => (
+ <div key={`im-skeleton-${index}`} className="px-2 py-1.5">
+ <Skeleton className="h-8 w-full" />
+ </div>
+ ))
+ ) : !isPackageSelected ? (
+ <p className="text-sm text-muted-foreground px-2">
+ Select a package first
+ </p>
+ ) : imForms.length === 0 ? (
+ <p className="text-sm text-muted-foreground px-2">
+ No forms available
+ </p>
) : (
- // =========== ENG 모드: 패키지 > 폼 계층 구조 ===========
- packages.length === 0 ? (
- <p className="text-sm text-muted-foreground px-2">
- (No packages loaded)
- </p>
- ) : (
- packages.map((pkg) => (
- <div key={pkg.itemId} className="space-y-1">
- {isCollapsed ? (
- <Tooltip delayDuration={0}>
- <TooltipTrigger asChild>
- <div className="px-2 py-1">
- <Package2 className="h-4 w-4" />
- </div>
- </TooltipTrigger>
- <TooltipContent side="right">
- {pkg.itemName}
- </TooltipContent>
- </Tooltip>
- ) : (
- <>
- {/* 패키지 이름 (클릭 불가능한 라벨) */}
- <div className="flex items-center px-2 py-1 text-sm font-medium">
- <Package2 className="mr-2 h-4 w-4" />
- {pkg.itemName}
- </div>
-
- {/* 폼 목록 바로 표시 */}
- <div className="ml-6 space-y-1">
- {!forms || forms.length === 0 ? (
- <p className="text-xs text-muted-foreground px-2 py-1">
- No forms available
- </p>
- ) : (
- forms.map((form) => {
- const isFormPackageActive =
- pkg.itemId === currentItemId &&
- form.formCode === currentFormCode
+ imForms.map((form) => {
+ const isActive =
+ currentMode === "im" &&
+ form.formCode === selectedFormCode
- return (
- <Button
- key={`${pkg.itemId}-${form.formCode}`}
- variant="ghost"
- size="sm"
- className={cn(
- "w-full justify-start font-normal text-sm",
- isFormPackageActive && "bg-accent text-accent-foreground"
- )}
- onClick={() => handlePackageUnderFormClick(form, pkg)}
- >
- <FormInput className="mr-2 h-3 w-3" />
- {form.formName}
- </Button>
- )
- })
- )}
- </div>
- </>
+ return isCollapsed ? (
+ <Tooltip key={form.formCode} delayDuration={0}>
+ <TooltipTrigger asChild>
+ <Button
+ variant="ghost"
+ className={cn(
+ "w-full justify-start font-normal",
+ isActive && "bg-accent text-accent-foreground"
+ )}
+ onClick={() => onIMFormClick(form.formCode)}
+ >
+ <FileText className="h-4 w-4" />
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent side="right">
+ {form.formName}
+ </TooltipContent>
+ </Tooltip>
+ ) : (
+ <Button
+ key={form.formCode}
+ variant="ghost"
+ className={cn(
+ "w-full justify-start font-normal",
+ isActive && "bg-accent text-accent-foreground"
)}
- </div>
- ))
- )
+ onClick={() => onIMFormClick(form.formCode)}
+ >
+ <FileText className="mr-2 h-4 w-4" />
+ {form.formName}
+ </Button>
+ )
+ })
)}
</div>
</ScrollArea>