2025-11-28 18:35:07 +09:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
|
|
|
import { Label } from "@/components/ui/label";
|
|
|
|
|
import { Input } from "@/components/ui/input";
|
|
|
|
|
import { Switch } from "@/components/ui/switch";
|
|
|
|
|
import {
|
|
|
|
|
Select,
|
|
|
|
|
SelectContent,
|
|
|
|
|
SelectItem,
|
|
|
|
|
SelectTrigger,
|
|
|
|
|
SelectValue,
|
|
|
|
|
} from "@/components/ui/select";
|
|
|
|
|
import { apiClient } from "@/lib/api/client";
|
|
|
|
|
|
|
|
|
|
interface LocationSwapSelectorConfigPanelProps {
|
|
|
|
|
config: any;
|
|
|
|
|
onChange: (config: any) => void;
|
|
|
|
|
tableColumns?: Array<{ columnName: string; columnLabel?: string; dataType?: string }>;
|
|
|
|
|
screenTableName?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* LocationSwapSelector 설정 패널
|
|
|
|
|
*/
|
|
|
|
|
export function LocationSwapSelectorConfigPanel({
|
|
|
|
|
config,
|
|
|
|
|
onChange,
|
|
|
|
|
tableColumns = [],
|
|
|
|
|
screenTableName,
|
|
|
|
|
}: LocationSwapSelectorConfigPanelProps) {
|
|
|
|
|
const [tables, setTables] = useState<Array<{ name: string; label: string }>>([]);
|
|
|
|
|
const [columns, setColumns] = useState<Array<{ name: string; label: string }>>([]);
|
|
|
|
|
const [codeCategories, setCodeCategories] = useState<Array<{ value: string; label: string }>>([]);
|
|
|
|
|
|
|
|
|
|
// 테이블 목록 로드
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const loadTables = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.get("/table-management/tables");
|
|
|
|
|
if (response.data.success && response.data.data) {
|
|
|
|
|
setTables(
|
|
|
|
|
response.data.data.map((t: any) => ({
|
|
|
|
|
name: t.tableName || t.table_name,
|
|
|
|
|
label: t.displayName || t.tableLabel || t.table_label || t.tableName || t.table_name,
|
|
|
|
|
}))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("테이블 목록 로드 실패:", error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
loadTables();
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
// 선택된 테이블의 컬럼 로드
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const loadColumns = async () => {
|
|
|
|
|
const tableName = config?.dataSource?.tableName;
|
|
|
|
|
if (!tableName) {
|
|
|
|
|
setColumns([]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.get(`/table-management/tables/${tableName}/columns`);
|
|
|
|
|
if (response.data.success) {
|
|
|
|
|
// API 응답 구조 처리: data가 배열이거나 data.columns가 배열일 수 있음
|
|
|
|
|
let columnData = response.data.data;
|
|
|
|
|
if (!Array.isArray(columnData) && columnData?.columns) {
|
|
|
|
|
columnData = columnData.columns;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(columnData)) {
|
|
|
|
|
setColumns(
|
|
|
|
|
columnData.map((c: any) => ({
|
|
|
|
|
name: c.columnName || c.column_name || c.name,
|
|
|
|
|
label: c.displayName || c.columnLabel || c.column_label || c.columnName || c.column_name || c.name,
|
|
|
|
|
}))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("컬럼 목록 로드 실패:", error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (config?.dataSource?.type === "table") {
|
|
|
|
|
loadColumns();
|
|
|
|
|
}
|
|
|
|
|
}, [config?.dataSource?.tableName, config?.dataSource?.type]);
|
|
|
|
|
|
|
|
|
|
// 코드 카테고리 로드
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const loadCodeCategories = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.get("/code-management/categories");
|
|
|
|
|
if (response.data.success && response.data.data) {
|
|
|
|
|
setCodeCategories(
|
|
|
|
|
response.data.data.map((c: any) => ({
|
|
|
|
|
value: c.category_code || c.categoryCode || c.code,
|
|
|
|
|
label: c.category_name || c.categoryName || c.name,
|
|
|
|
|
}))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("코드 카테고리 로드 실패:", error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
loadCodeCategories();
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const handleChange = (path: string, value: any) => {
|
|
|
|
|
const keys = path.split(".");
|
|
|
|
|
const newConfig = { ...config };
|
|
|
|
|
let current: any = newConfig;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
|
|
|
if (!current[keys[i]]) {
|
|
|
|
|
current[keys[i]] = {};
|
|
|
|
|
}
|
|
|
|
|
current = current[keys[i]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current[keys[keys.length - 1]] = value;
|
|
|
|
|
onChange(newConfig);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
{/* 데이터 소스 타입 */}
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>데이터 소스 타입</Label>
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.dataSource?.type || "static"}
|
|
|
|
|
onValueChange={(value) => handleChange("dataSource.type", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="선택" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
2025-12-01 11:07:16 +09:00
|
|
|
<SelectItem value="static">고정 옵션 (포항/광양 등)</SelectItem>
|
|
|
|
|
<SelectItem value="table">테이블에서 가져오기</SelectItem>
|
|
|
|
|
<SelectItem value="code">코드 관리에서 가져오기</SelectItem>
|
2025-11-28 18:35:07 +09:00
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-12-01 11:07:16 +09:00
|
|
|
{/* 고정 옵션 설정 (type이 static일 때) */}
|
|
|
|
|
{(!config?.dataSource?.type || config?.dataSource?.type === "static") && (
|
|
|
|
|
<div className="space-y-3 rounded-md bg-amber-50 p-3 dark:bg-amber-950">
|
|
|
|
|
<h4 className="text-sm font-medium">고정 옵션 설정</h4>
|
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>옵션 1 (값)</Label>
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.dataSource?.staticOptions?.[0]?.value || ""}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const options = config?.dataSource?.staticOptions || [];
|
|
|
|
|
const newOptions = [...options];
|
|
|
|
|
newOptions[0] = { ...newOptions[0], value: e.target.value };
|
|
|
|
|
handleChange("dataSource.staticOptions", newOptions);
|
|
|
|
|
}}
|
|
|
|
|
placeholder="예: pohang"
|
|
|
|
|
className="h-8 text-xs"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>옵션 1 (표시명)</Label>
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.dataSource?.staticOptions?.[0]?.label || ""}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const options = config?.dataSource?.staticOptions || [];
|
|
|
|
|
const newOptions = [...options];
|
|
|
|
|
newOptions[0] = { ...newOptions[0], label: e.target.value };
|
|
|
|
|
handleChange("dataSource.staticOptions", newOptions);
|
|
|
|
|
}}
|
|
|
|
|
placeholder="예: 포항"
|
|
|
|
|
className="h-8 text-xs"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>옵션 2 (값)</Label>
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.dataSource?.staticOptions?.[1]?.value || ""}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const options = config?.dataSource?.staticOptions || [];
|
|
|
|
|
const newOptions = [...options];
|
|
|
|
|
newOptions[1] = { ...newOptions[1], value: e.target.value };
|
|
|
|
|
handleChange("dataSource.staticOptions", newOptions);
|
|
|
|
|
}}
|
|
|
|
|
placeholder="예: gwangyang"
|
|
|
|
|
className="h-8 text-xs"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>옵션 2 (표시명)</Label>
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.dataSource?.staticOptions?.[1]?.label || ""}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const options = config?.dataSource?.staticOptions || [];
|
|
|
|
|
const newOptions = [...options];
|
|
|
|
|
newOptions[1] = { ...newOptions[1], label: e.target.value };
|
|
|
|
|
handleChange("dataSource.staticOptions", newOptions);
|
|
|
|
|
}}
|
|
|
|
|
placeholder="예: 광양"
|
|
|
|
|
className="h-8 text-xs"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<p className="text-xs text-amber-700 dark:text-amber-300">
|
|
|
|
|
고정된 2개 장소만 사용할 때 설정하세요. (예: 포항 ↔ 광양)
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
2025-11-28 18:35:07 +09:00
|
|
|
{/* 테이블 선택 (type이 table일 때) */}
|
|
|
|
|
{config?.dataSource?.type === "table" && (
|
|
|
|
|
<>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>테이블</Label>
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.dataSource?.tableName || ""}
|
|
|
|
|
onValueChange={(value) => handleChange("dataSource.tableName", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="테이블 선택" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{tables.map((table) => (
|
|
|
|
|
<SelectItem key={table.name} value={table.name}>
|
|
|
|
|
{table.label}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>값 필드</Label>
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.dataSource?.valueField || ""}
|
|
|
|
|
onValueChange={(value) => handleChange("dataSource.valueField", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="선택" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{columns.map((col) => (
|
|
|
|
|
<SelectItem key={col.name} value={col.name}>
|
|
|
|
|
{col.label}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>표시 필드</Label>
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.dataSource?.labelField || ""}
|
|
|
|
|
onValueChange={(value) => handleChange("dataSource.labelField", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="선택" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{columns.map((col) => (
|
|
|
|
|
<SelectItem key={col.name} value={col.name}>
|
|
|
|
|
{col.label}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* 코드 카테고리 선택 (type이 code일 때) */}
|
|
|
|
|
{config?.dataSource?.type === "code" && (
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>코드 카테고리</Label>
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.dataSource?.codeCategory || ""}
|
|
|
|
|
onValueChange={(value) => handleChange("dataSource.codeCategory", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="카테고리 선택" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{codeCategories.map((cat) => (
|
|
|
|
|
<SelectItem key={cat.value} value={cat.value}>
|
|
|
|
|
{cat.label}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* 필드 매핑 */}
|
|
|
|
|
<div className="space-y-2 border-t pt-4">
|
|
|
|
|
<h4 className="text-sm font-medium">필드 매핑 (저장 위치)</h4>
|
|
|
|
|
{screenTableName && (
|
|
|
|
|
<p className="text-xs text-muted-foreground">
|
|
|
|
|
현재 화면 테이블: <strong>{screenTableName}</strong>
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>출발지 저장 컬럼</Label>
|
|
|
|
|
{tableColumns.length > 0 ? (
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.departureField || ""}
|
|
|
|
|
onValueChange={(value) => handleChange("departureField", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="컬럼 선택" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{tableColumns.map((col) => (
|
|
|
|
|
<SelectItem key={col.columnName} value={col.columnName}>
|
|
|
|
|
{col.columnLabel || col.columnName}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
) : (
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.departureField || "departure"}
|
|
|
|
|
onChange={(e) => handleChange("departureField", e.target.value)}
|
|
|
|
|
placeholder="departure"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>도착지 저장 컬럼</Label>
|
|
|
|
|
{tableColumns.length > 0 ? (
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.destinationField || ""}
|
|
|
|
|
onValueChange={(value) => handleChange("destinationField", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="컬럼 선택" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{tableColumns.map((col) => (
|
|
|
|
|
<SelectItem key={col.columnName} value={col.columnName}>
|
|
|
|
|
{col.columnLabel || col.columnName}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
) : (
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.destinationField || "destination"}
|
|
|
|
|
onChange={(e) => handleChange("destinationField", e.target.value)}
|
|
|
|
|
placeholder="destination"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>출발지명 저장 컬럼 (선택)</Label>
|
|
|
|
|
{tableColumns.length > 0 ? (
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.departureLabelField || ""}
|
|
|
|
|
onValueChange={(value) => handleChange("departureLabelField", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="컬럼 선택 (선택사항)" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
<SelectItem value="">없음</SelectItem>
|
|
|
|
|
{tableColumns.map((col) => (
|
|
|
|
|
<SelectItem key={col.columnName} value={col.columnName}>
|
|
|
|
|
{col.columnLabel || col.columnName}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
) : (
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.departureLabelField || ""}
|
|
|
|
|
onChange={(e) => handleChange("departureLabelField", e.target.value)}
|
|
|
|
|
placeholder="departure_name"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>도착지명 저장 컬럼 (선택)</Label>
|
|
|
|
|
{tableColumns.length > 0 ? (
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.destinationLabelField || ""}
|
|
|
|
|
onValueChange={(value) => handleChange("destinationLabelField", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="컬럼 선택 (선택사항)" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
<SelectItem value="">없음</SelectItem>
|
|
|
|
|
{tableColumns.map((col) => (
|
|
|
|
|
<SelectItem key={col.columnName} value={col.columnName}>
|
|
|
|
|
{col.columnLabel || col.columnName}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
) : (
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.destinationLabelField || ""}
|
|
|
|
|
onChange={(e) => handleChange("destinationLabelField", e.target.value)}
|
|
|
|
|
placeholder="destination_name"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* UI 설정 */}
|
|
|
|
|
<div className="space-y-2 border-t pt-4">
|
|
|
|
|
<h4 className="text-sm font-medium">UI 설정</h4>
|
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>출발지 라벨</Label>
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.departureLabel || "출발지"}
|
|
|
|
|
onChange={(e) => handleChange("departureLabel", e.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>도착지 라벨</Label>
|
|
|
|
|
<Input
|
|
|
|
|
value={config?.destinationLabel || "도착지"}
|
|
|
|
|
onChange={(e) => handleChange("destinationLabel", e.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<Label>스타일</Label>
|
|
|
|
|
<Select
|
|
|
|
|
value={config?.variant || "card"}
|
|
|
|
|
onValueChange={(value) => handleChange("variant", value)}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
<SelectItem value="card">카드 (이미지 참고)</SelectItem>
|
|
|
|
|
<SelectItem value="inline">인라인</SelectItem>
|
|
|
|
|
<SelectItem value="minimal">미니멀</SelectItem>
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
|
<Label>교환 버튼 표시</Label>
|
|
|
|
|
<Switch
|
|
|
|
|
checked={config?.showSwapButton !== false}
|
|
|
|
|
onCheckedChange={(checked) => handleChange("showSwapButton", checked)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* 안내 */}
|
|
|
|
|
<div className="rounded-md bg-blue-50 p-3 dark:bg-blue-950">
|
|
|
|
|
<p className="text-xs text-blue-900 dark:text-blue-100">
|
|
|
|
|
<strong>사용 방법:</strong>
|
|
|
|
|
<br />
|
|
|
|
|
1. 데이터 소스에서 장소 목록을 가져올 위치를 선택합니다
|
|
|
|
|
<br />
|
|
|
|
|
2. 출발지/도착지 값이 저장될 필드를 지정합니다
|
|
|
|
|
<br />
|
|
|
|
|
3. 교환 버튼을 클릭하면 출발지와 도착지가 바뀝니다
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|