대시보드 위젯 수정사항 반영

This commit is contained in:
dohyeons 2025-10-21 17:14:04 +09:00
parent 8a2aa49910
commit d3c9a42525
3 changed files with 73 additions and 72 deletions

View File

@ -105,6 +105,8 @@ import { CalendarWidget } from "./widgets/CalendarWidget";
// 기사 관리 위젯 임포트
import { DriverManagementWidget } from "./widgets/DriverManagementWidget";
import { ListWidget } from "./widgets/ListWidget";
import { MoreHorizontal, X } from "lucide-react";
import { Button } from "@/components/ui/button";
// 야드 관리 3D 위젯
const YardManagement3DWidget = dynamic(() => import("./widgets/YardManagement3DWidget"), {
@ -546,22 +548,26 @@ export function CanvasElement({
<div className="flex gap-1">
{/* 설정 버튼 (기사관리 위젯만 자체 설정 UI 사용) */}
{onConfigure && !(element.type === "widget" && element.subtype === "driver-management") && (
<button
className="hover:bg-accent0 flex h-6 w-6 items-center justify-center rounded text-gray-400 transition-colors duration-200 hover:text-white"
<Button
variant="ghost"
size="icon"
className="h-6 w-6 text-gray-400"
onClick={() => onConfigure(element)}
title="설정"
>
</button>
<MoreHorizontal className="h-4 w-4" />
</Button>
)}
{/* 삭제 버튼 */}
<button
className="element-close hover:bg-destructive/100 flex h-6 w-6 items-center justify-center rounded text-gray-400 transition-colors duration-200 hover:text-white"
<Button
variant="ghost"
size="icon"
className="element-close hover:bg-destructive h-6 w-6 text-gray-400 hover:text-white"
onClick={handleRemove}
title="삭제"
>
×
</button>
<X className="h-4 w-4" />
</Button>
</div>
</div>

View File

@ -53,9 +53,9 @@ export function ElementConfigModal({ element, isOpen, onClose, onSave }: Element
element.subtype === "driver-management" ||
element.subtype === "work-history" || // 작업 이력 위젯 (쿼리 필요)
element.subtype === "transport-stats"; // 커스텀 통계 카드 위젯 (쿼리 필요)
// 자체 기능 위젯 (DB 연결 불필요, 헤더 설정만 가능)
const isSelfContainedWidget =
const isSelfContainedWidget =
element.subtype === "weather" || // 날씨 위젯 (외부 API)
element.subtype === "exchange" || // 환율 위젯 (외부 API)
element.subtype === "calculator"; // 계산기 위젯 (자체 기능)
@ -150,11 +150,9 @@ export function ElementConfigModal({ element, isOpen, onClose, onSave }: Element
if (!isOpen) return null;
// 시계, 달력, 날씨, 환율, 계산기 위젯은 헤더 설정만 가능
const isHeaderOnlyWidget =
element.type === "widget" &&
(element.subtype === "clock" ||
element.subtype === "calendar" ||
isSelfContainedWidget);
const isHeaderOnlyWidget =
element.type === "widget" &&
(element.subtype === "clock" || element.subtype === "calendar" || isSelfContainedWidget);
// 기사관리 위젯은 자체 설정 UI를 가지고 있으므로 모달 표시하지 않음
if (element.type === "widget" && element.subtype === "driver-management") {
@ -172,7 +170,7 @@ export function ElementConfigModal({ element, isOpen, onClose, onSave }: Element
// customTitle이 변경되었는지 확인
const isTitleChanged = customTitle.trim() !== (element.customTitle || "");
// showHeader가 변경되었는지 확인
const isHeaderChanged = showHeader !== (element.showHeader !== false);
@ -214,13 +212,6 @@ export function ElementConfigModal({ element, isOpen, onClose, onSave }: Element
<div className="flex items-center justify-between">
<div className="flex-1">
<h2 className="text-xl font-semibold text-gray-900">{element.title} </h2>
<p className="mt-1 text-sm text-gray-500">
{isSimpleWidget
? "데이터 소스를 설정하세요"
: currentStep === 1
? "데이터 소스를 선택하세요"
: "쿼리를 실행하고 차트를 설정하세요"}
</p>
</div>
<Button variant="ghost" size="icon" onClick={onClose} className="h-8 w-8">
<X className="h-5 w-5" />
@ -241,7 +232,9 @@ export function ElementConfigModal({ element, isOpen, onClose, onSave }: Element
placeholder="예: 정비 일정 목록, 창고 위치 현황 등 (비워두면 자동 생성)"
className="focus:border-primary focus:ring-primary w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-1 focus:outline-none"
/>
<p className="mt-1 text-xs text-gray-500"> (: "maintenance_schedules 목록")</p>
<p className="mt-1 text-xs text-gray-500">
(: "maintenance_schedules 목록")
</p>
</div>
{/* 헤더 표시 옵션 */}
@ -251,7 +244,7 @@ export function ElementConfigModal({ element, isOpen, onClose, onSave }: Element
id="showHeader"
checked={showHeader}
onChange={(e) => setShowHeader(e.target.checked)}
className="h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary"
className="text-primary focus:ring-primary h-4 w-4 rounded border-gray-300"
/>
<label htmlFor="showHeader" className="text-sm font-medium text-gray-700">
( + )
@ -278,61 +271,65 @@ export function ElementConfigModal({ element, isOpen, onClose, onSave }: Element
)}
{currentStep === 2 && (
<div className={`grid ${isSimpleWidget ? "grid-cols-1" : "grid-cols-2"} gap-6`}>
{/* 왼쪽: 데이터 설정 */}
<div className="space-y-6">
{dataSource.type === "database" ? (
<>
<DatabaseConfig dataSource={dataSource} onChange={handleDataSourceUpdate} />
<QueryEditor
<div className={`grid ${isSimpleWidget ? "grid-cols-1" : "grid-cols-2"} gap-6`}>
{/* 왼쪽: 데이터 설정 */}
<div className="space-y-6">
{dataSource.type === "database" ? (
<>
<DatabaseConfig dataSource={dataSource} onChange={handleDataSourceUpdate} />
<QueryEditor
dataSource={dataSource}
onDataSourceChange={handleDataSourceUpdate}
onQueryTest={handleQueryTest}
/>
</>
) : (
<ApiConfig
dataSource={dataSource}
onDataSourceChange={handleDataSourceUpdate}
onQueryTest={handleQueryTest}
onChange={handleDataSourceUpdate}
onTestResult={handleQueryTest}
/>
</>
) : (
<ApiConfig dataSource={dataSource} onChange={handleDataSourceUpdate} onTestResult={handleQueryTest} />
)}
</div>
)}
</div>
{/* 오른쪽: 설정 패널 */}
{!isSimpleWidget && (
<div>
{isMapWidget ? (
// 지도 위젯: 위도/경도 매핑 패널
{/* 오른쪽: 설정 패널 */}
{!isSimpleWidget && (
<div>
{isMapWidget ? (
// 지도 위젯: 위도/경도 매핑 패널
queryResult && queryResult.rows.length > 0 ? (
<VehicleMapConfigPanel
config={chartConfig}
queryResult={queryResult}
onConfigChange={handleChartConfigChange}
/>
) : (
<div className="flex h-full items-center justify-center rounded-lg border-2 border-dashed border-gray-300 bg-gray-50 p-8 text-center">
<div>
<div className="mt-1 text-xs text-gray-500"> </div>
</div>
</div>
)
) : // 차트: 차트 설정 패널
queryResult && queryResult.rows.length > 0 ? (
<VehicleMapConfigPanel
<ChartConfigPanel
config={chartConfig}
queryResult={queryResult}
onConfigChange={handleChartConfigChange}
chartType={element.subtype}
dataSourceType={dataSource.type}
query={dataSource.query}
/>
) : (
<div className="flex h-full items-center justify-center rounded-lg border-2 border-dashed border-gray-300 bg-gray-50 p-8 text-center">
<div>
<div className="mt-1 text-xs text-gray-500"> </div>
<div className="mt-1 text-xs text-gray-500"> </div>
</div>
</div>
)
) : // 차트: 차트 설정 패널
queryResult && queryResult.rows.length > 0 ? (
<ChartConfigPanel
config={chartConfig}
queryResult={queryResult}
onConfigChange={handleChartConfigChange}
chartType={element.subtype}
dataSourceType={dataSource.type}
query={dataSource.query}
/>
) : (
<div className="flex h-full items-center justify-center rounded-lg border-2 border-dashed border-gray-300 bg-gray-50 p-8 text-center">
<div>
<div className="mt-1 text-xs text-gray-500"> </div>
</div>
</div>
)}
</div>
)}
</div>
)}
</div>
)}
</div>
)}
</div>
)}
@ -376,4 +373,3 @@ export function ElementConfigModal({ element, isOpen, onClose, onSave }: Element
</div>
);
}

View File

@ -44,9 +44,9 @@ export function ClockSettings({ config, onSave, onClose }: ClockSettingsProps) {
<Label className="text-sm font-semibold"> </Label>
<div className="grid grid-cols-3 gap-2">
{[
{ value: "digital", label: "디지털", icon: "🔢" },
{ value: "analog", label: "아날로그", icon: "🕐" },
{ value: "both", label: "둘 다", icon: "⏰" },
{ value: "digital", label: "디지털" },
{ value: "analog", label: "아날로그" },
{ value: "both", label: "둘 다" },
].map((style) => (
<Button
key={style.value}
@ -56,7 +56,6 @@ export function ClockSettings({ config, onSave, onClose }: ClockSettingsProps) {
className="flex h-auto flex-col items-center gap-1 py-3"
size="sm"
>
<span className="text-2xl">{style.icon}</span>
<span className="text-xs">{style.label}</span>
</Button>
))}