sw-fe/src/components/Map/TemplateMarkerCard.jsx

78 lines
2.2 KiB
JavaScript

import React, { useMemo } from "react";
import CardRenderer from "../Cards/CardRenderer";
import { cardTokens } from "../../theme/cardTokens";
function normTheme(t) {
if (t === "dark" || t === "blue" || t === "light") return t;
return "dark";
}
export default function TemplateMarkerCard({
post,
template,
theme = "dark",
mode = "full", // "mini" or "full"
onOpenUrl,
}) {
const spec = mode === "mini" ? template?.mini_spec_json : template?.full_spec_json;
const data = useMemo(() => {
const rawImage =
mode === "mini"
? (post?.image_small || post?.image_medium || post?.thumbnail_url || "")
: (post?.image_medium || post?.image_large || post?.image_small || post?.image || post?.thumbnail_url || post?.media_url || "");
return {
headline: post?.title || "Untitled",
source: post?.source || (post?.author ? `by ${post.author}` : "") || (post?.sub_category || ""),
summary: post?.snippet || post?.body || post?.content || "",
url: post?.url || "",
image: normalizeImageUrl(rawImage),
};
}, [post]);
if (!spec) {
// fallback simple
return (
<div
style={{
minWidth: 260,
maxWidth: 320,
background: "rgba(8, 20, 40, 0.97)",
borderRadius: 14,
padding: "10px 12px",
border: "1px solid rgba(90, 190, 255, 0.9)",
color: "#e8f5ff",
}}
>
<div style={{ fontWeight: 900, fontSize: 13, marginBottom: 4 }}>{data.headline}</div>
<div style={{ opacity: 0.9, fontSize: 11 }}>{data.summary}</div>
</div>
);
}
const tokens = cardTokens[normTheme(theme)] || cardTokens.dark;
return (
<CardRenderer
spec={spec}
data={data}
themeTokens={tokens}
onAction={(action, value) => {
if (action?.type === "open_url" && value) {
if (onOpenUrl) onOpenUrl(value);
else window.open(value, "_blank", "noopener,noreferrer");
}
}}
className=""
/>
);
}
function normalizeImageUrl(raw) {
const value = (raw || "").toString().trim();
if (!value) return "";
if (value.startsWith("//")) return `https:${value}`;
if (value.startsWith("http://")) return `https://${value.slice(7)}`;
return value;
}