auth.server.ts: switch generateId to application-generated UUIDs so the ID is known before the insert, then move flagConfig assignment from create.after (a separate UPDATE) to create.before so it lands in the initial INSERT with no race window. FlagSvg.tsx: validate the config with parseFlagConfig before rendering; corrupt or missing data falls back to a neutral gray triband flag rather than silently rendering blank SVG shapes. https://claude.ai/code/session_01T7iTb9YZLuWJFtKV753tdB
121 lines
4.1 KiB
TypeScript
121 lines
4.1 KiB
TypeScript
import { cn } from "~/lib/utils";
|
|
import { parseFlagConfig, type FlagConfig } from "~/lib/flag-types";
|
|
|
|
interface FlagSvgProps {
|
|
config: FlagConfig;
|
|
size?: number;
|
|
className?: string;
|
|
title?: string;
|
|
}
|
|
|
|
const FALLBACK_FLAG: FlagConfig = { pattern: "triband-h", colors: ["#9ca3af", "#6b7280", "#4b5563"] };
|
|
|
|
export function FlagSvg({ config, size = 48, className, title }: FlagSvgProps) {
|
|
const safeConfig = parseFlagConfig(config) ?? FALLBACK_FLAG;
|
|
const [c0, c1, c2] = safeConfig.colors;
|
|
|
|
return (
|
|
<svg
|
|
viewBox="0 0 100 100"
|
|
width={size}
|
|
height={size}
|
|
role="img"
|
|
aria-label={title}
|
|
className={cn("block shrink-0 overflow-hidden", className)}
|
|
>
|
|
{title ? <title>{title}</title> : null}
|
|
{safeConfig.pattern === "triband-h" && (
|
|
<>
|
|
<rect width="100" height="34" fill={c0} />
|
|
<rect y="33" width="100" height="34" fill={c1} />
|
|
<rect y="66" width="100" height="34" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "triband-v" && (
|
|
<>
|
|
<rect width="34" height="100" fill={c0} />
|
|
<rect x="33" width="34" height="100" fill={c1} />
|
|
<rect x="66" width="34" height="100" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "diagonal" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<polygon points="0,0 100,0 0,100" fill={c1} />
|
|
<polygon points="100,100 100,28 28,100" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "nordic-cross" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<rect x="30" width="18" height="100" fill={c1} />
|
|
<rect y="40" width="100" height="18" fill={c1} />
|
|
<rect x="36" width="6" height="100" fill={c2} />
|
|
<rect y="46" width="100" height="6" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "cross" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<rect x="40" width="20" height="100" fill={c1} />
|
|
<rect y="40" width="100" height="20" fill={c1} />
|
|
<rect x="46" width="8" height="100" fill={c2} />
|
|
<rect y="46" width="100" height="8" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "canton" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<rect width="50" height="50" fill={c1} />
|
|
<rect x="12" y="12" width="26" height="26" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "triangle" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<polygon points="0,0 64,50 0,100" fill={c1} />
|
|
<polygon points="0,22 36,50 0,78" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "chevron" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<polygon points="0,0 56,50 0,100 28,100 84,50 28,0" fill={c1} />
|
|
<polygon points="0,22 32,50 0,78 0,62 14,50 0,38" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "quartered" && (
|
|
<>
|
|
<rect width="50" height="50" fill={c0} />
|
|
<rect x="50" width="50" height="50" fill={c1} />
|
|
<rect y="50" width="50" height="50" fill={c1} />
|
|
<rect x="50" y="50" width="50" height="50" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "bordered" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<rect x="12" y="12" width="76" height="76" fill={c1} />
|
|
<rect x="24" y="24" width="52" height="52" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "circle" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<circle cx="50" cy="50" r="30" fill={c1} />
|
|
<circle cx="50" cy="50" r="15" fill={c2} />
|
|
</>
|
|
)}
|
|
{safeConfig.pattern === "star" && (
|
|
<>
|
|
<rect width="100" height="100" fill={c0} />
|
|
<polygon
|
|
points="50,14 60,39 87,39 65,56 73,84 50,67 27,84 35,56 13,39 40,39"
|
|
fill={c1}
|
|
/>
|
|
<circle cx="50" cy="50" r="10" fill={c2} />
|
|
</>
|
|
)}
|
|
</svg>
|
|
);
|
|
}
|