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