팝업 수정 가능하게 수정
This commit is contained in:
@@ -919,7 +919,7 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
|
||||
// 첫 번째 데이터 소스의 새로고침 간격 사용 (초)
|
||||
const firstDataSource = dataSources[0];
|
||||
const refreshInterval = firstDataSource?.refreshInterval ?? 5;
|
||||
|
||||
|
||||
// 0이면 자동 새로고침 비활성화
|
||||
if (refreshInterval === 0) {
|
||||
return;
|
||||
@@ -1123,12 +1123,12 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
|
||||
// 첫 번째 데이터 소스의 마커 종류 가져오기
|
||||
const firstDataSource = dataSources?.[0];
|
||||
const markerType = firstDataSource?.markerType || "circle";
|
||||
|
||||
|
||||
let markerIcon: any;
|
||||
if (typeof window !== "undefined") {
|
||||
const L = require("leaflet");
|
||||
const heading = marker.heading || 0;
|
||||
|
||||
|
||||
if (markerType === "arrow") {
|
||||
// 화살표 마커
|
||||
markerIcon = L.divIcon({
|
||||
@@ -1216,63 +1216,117 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
|
||||
return (
|
||||
<Marker key={marker.id} position={[marker.lat, marker.lng]} icon={markerIcon}>
|
||||
<Popup maxWidth={350}>
|
||||
<div className="max-w-[350px] min-w-[250px]">
|
||||
{/* 제목 */}
|
||||
<div className="mb-2 border-b pb-2">
|
||||
<div className="text-base font-bold">{marker.name}</div>
|
||||
{marker.source && <div className="text-muted-foreground mt-1 text-xs">📡 {marker.source}</div>}
|
||||
</div>
|
||||
<div className="max-w-[350px] min-w-[250px]" dir="ltr">
|
||||
{/* 데이터 소스명만 표시 */}
|
||||
{marker.source && (
|
||||
<div className="mb-2 border-b pb-2">
|
||||
<div className="text-muted-foreground text-xs">📡 {marker.source}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 상세 정보 */}
|
||||
<div className="space-y-2">
|
||||
{marker.description && (
|
||||
<div className="bg-muted rounded p-2">
|
||||
<div className="text-foreground mb-1 text-xs font-semibold">상세 정보</div>
|
||||
<div className="text-muted-foreground text-xs whitespace-pre-wrap">
|
||||
{(() => {
|
||||
try {
|
||||
const parsed = JSON.parse(marker.description);
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
{parsed.incidenteTypeCd === "1" && (
|
||||
<div className="text-destructive font-semibold">🚨 교통사고</div>
|
||||
)}
|
||||
{parsed.incidenteTypeCd === "2" && (
|
||||
<div className="text-warning font-semibold">🚧 도로공사</div>
|
||||
)}
|
||||
{parsed.addressJibun && <div>📍 {parsed.addressJibun}</div>}
|
||||
{parsed.addressNew && parsed.addressNew !== parsed.addressJibun && (
|
||||
<div>📍 {parsed.addressNew}</div>
|
||||
)}
|
||||
{parsed.roadName && <div>🛣️ {parsed.roadName}</div>}
|
||||
{parsed.linkName && <div>🔗 {parsed.linkName}</div>}
|
||||
{parsed.incidentMsg && (
|
||||
<div className="mt-2 border-t pt-2">💬 {parsed.incidentMsg}</div>
|
||||
)}
|
||||
{parsed.eventContent && (
|
||||
<div className="mt-2 border-t pt-2">📝 {parsed.eventContent}</div>
|
||||
)}
|
||||
{parsed.startDate && <div className="text-[10px]">🕐 {parsed.startDate}</div>}
|
||||
{parsed.endDate && <div className="text-[10px]">🕐 종료: {parsed.endDate}</div>}
|
||||
</div>
|
||||
);
|
||||
} catch {
|
||||
return marker.description;
|
||||
}
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{marker.description &&
|
||||
(() => {
|
||||
const firstDataSource = dataSources?.[0];
|
||||
const popupFields = firstDataSource?.popupFields;
|
||||
|
||||
{marker.status && (
|
||||
<div className="text-xs">
|
||||
<span className="font-semibold">상태:</span> {marker.status}
|
||||
</div>
|
||||
)}
|
||||
// popupFields가 설정되어 있으면 설정된 필드만 표시
|
||||
if (popupFields && popupFields.length > 0) {
|
||||
try {
|
||||
const parsed = JSON.parse(marker.description);
|
||||
return (
|
||||
<div className="bg-muted rounded p-2">
|
||||
<div className="text-foreground mb-1 text-xs font-semibold">상세 정보</div>
|
||||
<div className="space-y-2">
|
||||
{popupFields.map((field, idx) => {
|
||||
const value = parsed[field.fieldName];
|
||||
if (value === undefined || value === null) return null;
|
||||
|
||||
// 포맷팅 적용
|
||||
let formattedValue = value;
|
||||
if (field.format === "date" && value) {
|
||||
formattedValue = new Date(value).toLocaleDateString("ko-KR");
|
||||
} else if (field.format === "datetime" && value) {
|
||||
formattedValue = new Date(value).toLocaleString("ko-KR");
|
||||
} else if (field.format === "number" && typeof value === "number") {
|
||||
formattedValue = value.toLocaleString();
|
||||
} else if (
|
||||
field.format === "url" &&
|
||||
typeof value === "string" &&
|
||||
value.startsWith("http")
|
||||
) {
|
||||
return (
|
||||
<div key={idx} className="text-xs">
|
||||
<span className="text-muted-foreground font-medium">{field.label}:</span>{" "}
|
||||
<a
|
||||
href={value}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
링크 열기
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={idx} className="text-xs">
|
||||
<span className="text-muted-foreground font-medium">{field.label}:</span>{" "}
|
||||
<span className="text-foreground">{String(formattedValue)}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} catch (error) {
|
||||
return (
|
||||
<div className="bg-muted rounded p-2">
|
||||
<div className="text-foreground mb-1 text-xs font-semibold">상세 정보</div>
|
||||
<div className="text-muted-foreground text-xs">{marker.description}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// popupFields가 없으면 전체 데이터 표시 (기본 동작)
|
||||
try {
|
||||
const parsed = JSON.parse(marker.description);
|
||||
return (
|
||||
<div className="bg-muted rounded p-2">
|
||||
<div className="text-foreground mb-1 text-xs font-semibold">상세 정보</div>
|
||||
<div className="space-y-2">
|
||||
{Object.entries(parsed).map(([key, value], idx) => {
|
||||
if (value === undefined || value === null) return null;
|
||||
|
||||
// 좌표 필드는 제외 (하단에 별도 표시)
|
||||
if (["lat", "lng", "latitude", "longitude", "x", "y"].includes(key)) return null;
|
||||
|
||||
return (
|
||||
<div key={idx} className="text-xs">
|
||||
<span className="text-muted-foreground font-medium">{key}:</span>{" "}
|
||||
<span className="text-foreground">{String(value)}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} catch (error) {
|
||||
return (
|
||||
<div className="bg-muted rounded p-2">
|
||||
<div className="text-foreground mb-1 text-xs font-semibold">상세 정보</div>
|
||||
<div className="text-muted-foreground text-xs">{marker.description}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
})()}
|
||||
|
||||
{/* 좌표 */}
|
||||
<div className="text-muted-foreground border-t pt-2 text-[10px]">
|
||||
📍 {marker.lat.toFixed(6)}, {marker.lng.toFixed(6)}
|
||||
{marker.lat.toFixed(6)}, {marker.lng.toFixed(6)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1280,7 +1334,6 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
|
||||
</Marker>
|
||||
);
|
||||
})}
|
||||
|
||||
</MapContainer>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user