3d필드로 텍스트 변경
This commit is contained in:
@@ -57,7 +57,7 @@ import riskAlertRoutes from "./routes/riskAlertRoutes"; // 리스크/알림 관
|
||||
import todoRoutes from "./routes/todoRoutes"; // To-Do 관리
|
||||
import bookingRoutes from "./routes/bookingRoutes"; // 예약 요청 관리
|
||||
import mapDataRoutes from "./routes/mapDataRoutes"; // 지도 데이터 관리
|
||||
import yardLayoutRoutes from "./routes/yardLayoutRoutes"; // 야드 관리 3D
|
||||
import yardLayoutRoutes from "./routes/yardLayoutRoutes"; // 3D 필드
|
||||
//import materialRoutes from "./routes/materialRoutes"; // 자재 관리
|
||||
import digitalTwinRoutes from "./routes/digitalTwinRoutes"; // 디지털 트윈 (야드 관제)
|
||||
import flowRoutes from "./routes/flowRoutes"; // 플로우 관리
|
||||
@@ -222,7 +222,7 @@ app.use("/api/risk-alerts", riskAlertRoutes); // 리스크/알림 관리
|
||||
app.use("/api/todos", todoRoutes); // To-Do 관리
|
||||
app.use("/api/bookings", bookingRoutes); // 예약 요청 관리
|
||||
app.use("/api/map-data", mapDataRoutes); // 지도 데이터 조회
|
||||
app.use("/api/yard-layouts", yardLayoutRoutes); // 야드 관리 3D
|
||||
app.use("/api/yard-layouts", yardLayoutRoutes); // 3D 필드
|
||||
// app.use("/api/materials", materialRoutes); // 자재 관리 (임시 주석)
|
||||
app.use("/api/digital-twin", digitalTwinRoutes); // 디지털 트윈 (야드 관제)
|
||||
app.use("/api/flow-external-db", flowExternalDbConnectionRoutes); // 플로우 전용 외부 DB 연결
|
||||
|
||||
@@ -193,7 +193,7 @@ import { ListWidget } from "./widgets/ListWidget";
|
||||
import { X } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
// 야드 관리 3D 위젯
|
||||
// 3D 필드 위젯
|
||||
const YardManagement3DWidget = dynamic(() => import("./widgets/YardManagement3DWidget"), {
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
@@ -1085,7 +1085,7 @@ export function CanvasElement({
|
||||
<ListWidget element={element} />
|
||||
</div>
|
||||
) : element.type === "widget" && element.subtype === "yard-management-3d" ? (
|
||||
// 야드 관리 3D 위젯 렌더링
|
||||
// 3D 필드 위젯 렌더링
|
||||
<div className="widget-interactive-area h-full w-full">
|
||||
<YardManagement3DWidget
|
||||
isEditMode={true}
|
||||
|
||||
@@ -749,7 +749,7 @@ function getElementTitle(type: ElementType, subtype: ElementSubtype): string {
|
||||
case "document":
|
||||
return "문서 위젯";
|
||||
case "yard-management-3d":
|
||||
return "야드 관리 3D";
|
||||
return "3D 필드";
|
||||
case "work-history":
|
||||
return "작업 이력";
|
||||
case "transport-stats":
|
||||
|
||||
@@ -362,7 +362,7 @@ export function DashboardTopMenu({
|
||||
<SelectItem value="list-v2">리스트</SelectItem>
|
||||
<SelectItem value="custom-metric-v2">통계 카드</SelectItem>
|
||||
<SelectItem value="risk-alert-v2">리스크/알림</SelectItem>
|
||||
<SelectItem value="yard-management-3d">야드 관리 3D</SelectItem>
|
||||
<SelectItem value="yard-management-3d">3D 필드</SelectItem>
|
||||
{/* <SelectItem value="transport-stats">커스텀 통계 카드</SelectItem> */}
|
||||
{/* <SelectItem value="status-summary">커스텀 상태 카드</SelectItem> */}
|
||||
</SelectGroup>
|
||||
|
||||
@@ -93,7 +93,7 @@ const getWidgetTitle = (subtype: ElementSubtype): string => {
|
||||
chart: "차트",
|
||||
"map-summary-v2": "지도",
|
||||
"risk-alert-v2": "리스크 알림",
|
||||
"yard-management-3d": "야드 관리 3D",
|
||||
"yard-management-3d": "3D 필드",
|
||||
weather: "날씨 위젯",
|
||||
exchange: "환율 위젯",
|
||||
calculator: "계산기",
|
||||
@@ -449,7 +449,7 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 레이아웃 선택 (야드 관리 3D 위젯 전용) */}
|
||||
{/* 레이아웃 선택 (3D 필드 위젯 전용) */}
|
||||
{element.subtype === "yard-management-3d" && (
|
||||
<div className="bg-background rounded-lg p-3 shadow-sm">
|
||||
<Label htmlFor="layout-id" className="mb-2 block text-xs font-semibold">
|
||||
|
||||
@@ -49,7 +49,7 @@ export type ElementSubtype =
|
||||
| "maintenance"
|
||||
| "document"
|
||||
// | "list" // (구버전 - 주석 처리: 2025-10-28, list-v2로 대체)
|
||||
| "yard-management-3d" // 야드 관리 3D 위젯
|
||||
| "yard-management-3d" // 3D 필드 위젯
|
||||
| "work-history" // 작업 이력 위젯
|
||||
| "transport-stats"; // 커스텀 통계 카드 위젯
|
||||
// | "custom-metric"; // (구버전 - 주석 처리: 2025-10-28, custom-metric-v2로 대체)
|
||||
@@ -116,7 +116,7 @@ export interface DashboardElement {
|
||||
calendarConfig?: CalendarConfig; // 달력 설정
|
||||
driverManagementConfig?: DriverManagementConfig; // 기사 관리 설정
|
||||
listConfig?: ListWidgetConfig; // 리스트 위젯 설정
|
||||
yardConfig?: YardManagementConfig; // 야드 관리 3D 설정
|
||||
yardConfig?: YardManagementConfig; // 3D 필드 설정
|
||||
customMetricConfig?: CustomMetricConfig; // 사용자 커스텀 카드 설정
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ export interface ListColumn {
|
||||
visible?: boolean; // 표시 여부 (기본: true)
|
||||
}
|
||||
|
||||
// 야드 관리 3D 설정
|
||||
// 3D 필드 설정
|
||||
export interface YardManagementConfig {
|
||||
layoutId: number; // 선택된 야드 레이아웃 ID
|
||||
layoutName?: string; // 레이아웃 이름 (표시용)
|
||||
|
||||
@@ -42,14 +42,16 @@ export default function YardManagement3DWidget({
|
||||
setIsLoading(true);
|
||||
const response = await getLayouts();
|
||||
if (response.success && response.data) {
|
||||
setLayouts(response.data.map((layout: any) => ({
|
||||
id: layout.id,
|
||||
name: layout.layout_name,
|
||||
description: layout.description || "",
|
||||
placement_count: layout.object_count || 0,
|
||||
created_at: layout.created_at,
|
||||
updated_at: layout.updated_at,
|
||||
})));
|
||||
setLayouts(
|
||||
response.data.map((layout: any) => ({
|
||||
id: layout.id,
|
||||
name: layout.layout_name,
|
||||
description: layout.description || "",
|
||||
placement_count: layout.object_count || 0,
|
||||
created_at: layout.created_at,
|
||||
updated_at: layout.updated_at,
|
||||
})),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("야드 레이아웃 목록 조회 실패:", error);
|
||||
@@ -152,11 +154,7 @@ export default function YardManagement3DWidget({
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<DigitalTwinEditor
|
||||
layoutId={editingLayout.id}
|
||||
layoutName={editingLayout.name}
|
||||
onBack={handleEditComplete}
|
||||
/>
|
||||
<DigitalTwinEditor layoutId={editingLayout.id} layoutName={editingLayout.name} onBack={handleEditComplete} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -164,30 +162,31 @@ export default function YardManagement3DWidget({
|
||||
// 편집 모드: 레이아웃 선택 UI
|
||||
if (isEditMode) {
|
||||
return (
|
||||
<div className="widget-interactive-area flex h-full w-full flex-col bg-background">
|
||||
<div className="widget-interactive-area bg-background flex h-full w-full flex-col">
|
||||
<div className="flex items-center justify-between border-b p-4">
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-foreground">야드 레이아웃 선택</h3>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
{config?.layoutName ? `선택됨: ${config.layoutName}` : "표시할 야드 레이아웃을 선택하세요"}
|
||||
<h3 className="text-foreground text-sm font-semibold">3D 필드 선택</h3>
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
{config?.layoutName ? `선택됨: ${config.layoutName}` : "표시할 3D필드를 선택하세요"}
|
||||
</p>
|
||||
</div>
|
||||
<Button onClick={() => setIsCreateModalOpen(true)} size="sm">
|
||||
<Plus className="mr-1 h-4 w-4" />새로운 3d필드 생성
|
||||
<Plus className="mr-1 h-4 w-4" />
|
||||
새로운 3D필드 생성
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-auto p-4">
|
||||
{isLoading ? (
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<div className="text-sm text-muted-foreground">로딩 중...</div>
|
||||
<div className="text-muted-foreground text-sm">로딩 중...</div>
|
||||
</div>
|
||||
) : layouts.length === 0 ? (
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="mb-2 text-4xl">🏗️</div>
|
||||
<div className="text-sm text-foreground">생성된 야드 레이아웃이 없습니다</div>
|
||||
<div className="mt-1 text-xs text-muted-foreground">먼저 야드 레이아웃을 생성하세요</div>
|
||||
<div className="text-foreground text-sm">생성된 3D필드가 없습니다</div>
|
||||
<div className="text-muted-foreground mt-1 text-xs">먼저 3D필드가 생성하세요</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@@ -202,11 +201,11 @@ export default function YardManagement3DWidget({
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<button onClick={() => handleSelectLayout(layout)} className="flex-1 text-left hover:opacity-80">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-medium text-foreground">{layout.name}</span>
|
||||
{config?.layoutId === layout.id && <Check className="h-4 w-4 text-primary" />}
|
||||
<span className="text-foreground font-medium">{layout.name}</span>
|
||||
{config?.layoutId === layout.id && <Check className="text-primary h-4 w-4" />}
|
||||
</div>
|
||||
{layout.description && <p className="mt-1 text-xs text-muted-foreground">{layout.description}</p>}
|
||||
<div className="mt-2 text-xs text-muted-foreground">배치된 자재: {layout.placement_count}개</div>
|
||||
{layout.description && <p className="text-muted-foreground mt-1 text-xs">{layout.description}</p>}
|
||||
<div className="text-muted-foreground mt-2 text-xs">배치된 자재: {layout.placement_count}개</div>
|
||||
</button>
|
||||
<div className="flex gap-1">
|
||||
<Button
|
||||
@@ -257,12 +256,12 @@ export default function YardManagement3DWidget({
|
||||
<DialogTitle>야드 레이아웃 삭제</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm text-foreground">
|
||||
<p className="text-foreground text-sm">
|
||||
이 야드 레이아웃을 삭제하시겠습니까?
|
||||
<br />
|
||||
레이아웃 내의 모든 배치 정보도 함께 삭제됩니다.
|
||||
<br />
|
||||
<span className="font-semibold text-destructive">이 작업은 되돌릴 수 없습니다.</span>
|
||||
<span className="text-destructive font-semibold">이 작업은 되돌릴 수 없습니다.</span>
|
||||
</p>
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button variant="outline" onClick={() => setDeleteLayoutId(null)}>
|
||||
@@ -283,14 +282,12 @@ export default function YardManagement3DWidget({
|
||||
if (!config?.layoutId) {
|
||||
console.warn("⚠️ 야드관리 위젯: layoutId가 설정되지 않음", { config, isEditMode });
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center bg-muted">
|
||||
<div className="bg-muted flex h-full w-full items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="mb-2 text-4xl">🏗️</div>
|
||||
<div className="text-sm font-medium text-foreground">야드 레이아웃이 설정되지 않았습니다</div>
|
||||
<div className="mt-1 text-xs text-muted-foreground">대시보드 편집에서 레이아웃을 선택하세요</div>
|
||||
<div className="mt-2 text-xs text-destructive">
|
||||
디버그: config={JSON.stringify(config)}
|
||||
</div>
|
||||
<div className="text-foreground text-sm font-medium">3D필드가 설정되지 않았습니다</div>
|
||||
<div className="text-muted-foreground mt-1 text-xs">대시보드 편집에서 3D필드를 선택하세요</div>
|
||||
<div className="text-destructive mt-2 text-xs">디버그: config={JSON.stringify(config)}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function YardLayoutCreateModal({ isOpen, onClose, onCreate }: Yar
|
||||
<ResizableDialogContent className="sm:max-w-[500px]" onPointerDown={(e) => e.stopPropagation()}>
|
||||
<ResizableDialogHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<ResizableDialogTitle>새로운 3d필드 생성</ResizableDialogTitle>
|
||||
<ResizableDialogTitle>새로운 3D필드 생성</ResizableDialogTitle>
|
||||
<ResizableDialogDescription>필드 이름을 입력하세요</ResizableDialogDescription>
|
||||
</div>
|
||||
</ResizableDialogHeader>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 야드 관리 3D - 타입 정의
|
||||
// 3D 필드 - 타입 정의
|
||||
|
||||
import { ChartDataSource } from "../../types";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user