Files
buzz-sheet/components/public/constellation-image.tsx
T
gunshiz db554228bc
CI / Verify (push) Successful in 1m29s
CI / Build immutable images and deploy (push) Failing after 1m42s
feat(admin-images) : add standalone export generators
2026-09-29 17:13:24 +07:00

109 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Image from "next/image";
import { GuideExportBranding } from "@/components/public/guide-export-branding";
import { ExportText } from "@/components/public/export-language";
import type { PublicGuide } from "@/lib/guides/queries";
import { constellationChartRows } from "@/lib/guides/export-image";
import { cn } from "@/lib/utils";
export type ConstellationImageGuide = Pick<PublicGuide, "coverUrl"> & {
character: Pick<PublicGuide["character"], "name" | "splashImageUrl">;
};
export interface ConstellationImageGroup {
note: string | null;
rows: Array<{
level: number;
cumulativePercent: string;
isGreat: boolean;
}>;
}
function percentage(value: number): string {
return `${value.toLocaleString("en-US", { maximumFractionDigits: 2 })}%`;
}
export function ConstellationImage({
guide,
group,
}: {
guide: ConstellationImageGuide;
group: ConstellationImageGroup;
}) {
const rows = constellationChartRows(group.rows);
const background = guide.character.splashImageUrl ?? guide.coverUrl;
const footer = group.note;
return (
<div className="relative isolate size-375 overflow-hidden bg-[#070b20] font-heading text-white">
<GuideExportBranding backgroundUrl={background} variant="constellation" />
<div className="absolute inset-x-20 top-7 z-10 flex items-start justify-center gap-5">
<Image
src="/icon/nav/Constellations.webp"
alt=""
width={112}
height={112}
loading="eager"
className="size-28 shrink-0 object-contain drop-shadow-[0_5px_4px_rgba(0,0,0,0.8)]"
/>
<div className="flex flex-col items-center text-center drop-shadow-[0_5px_4px_rgba(0,0,0,0.8)]">
<h2
className={cn(
"whitespace-nowrap leading-none font-bold",
guide.character.name.length > 16
? "text-[60px]"
: "text-[76px]",
)}
>
<ExportText
th={`กลุ่มดาว ${guide.character.name}`}
en={`${guide.character.name}’s Constellations`}
/>
</h2>
<p className="mt-3 line-clamp-2 max-w-275 whitespace-pre-line text-[42px] leading-tight font-bold text-[#f1badd]">
<ExportText th="ดาเมจทั้งทีม" en="Team Damage" />
</p>
</div>
</div>
<div className="absolute top-40 bottom-28.75 left-38.5 z-20 w-1 bg-black/90" />
<div className="absolute inset-x-14 top-51.25 bottom-36.25 z-20 flex flex-col justify-between">
{rows.map((row) => (
<div
key={row.level}
className="grid grid-cols-[82px_1fr] items-center gap-4"
>
<div className="text-right text-[58px] leading-none font-bold drop-shadow-[0_5px_4px_rgba(0,0,0,0.9)]">
C{row.level}
</div>
<div className="flex h-25 items-center">
<div
className={cn(
"h-full shrink-0 rounded-r-xl",
row.isGreat ? "bg-warning" : "bg-white",
)}
style={{ width: `${row.widthPercent * 8.5}px` }}
/>
<span
className={cn(
"ml-3 text-[42px] leading-none font-bold drop-shadow-[0_4px_3px_rgba(0,0,0,0.9)]",
row.isGreat ? "text-[#f0c76a]" : "text-[#f1badd]",
)}
>
{percentage(row.percent)}
</span>
</div>
</div>
))}
</div>
{footer ? (
<p data-export-note className="absolute bottom-10 left-38.5 z-30 max-w-275 truncate text-[28px] font-semibold drop-shadow-[0_4px_3px_rgba(0,0,0,0.9)]">
{footer}
</p>
) : null}
</div>
);
}