feat(weapon) : share public cards with inline admin editing
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import { CatalogItemImage, type CatalogItemImageData } from "@/components/catalog-item-image";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { rarityGradientClass, rarityTextClass } from "@/lib/catalog/rarity";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type DamageMetric = "overallPercent" | "personalPercent";
|
||||
|
||||
export function weaponComparisonPercent(value: string | null, exporting = false) {
|
||||
if (value === null) return null;
|
||||
return Number(value) === 0
|
||||
? exporting ? "-%" : "-"
|
||||
: `${Number(value).toLocaleString(undefined, { maximumFractionDigits: 2 })}%`;
|
||||
}
|
||||
|
||||
export function WeaponComparisonCard({
|
||||
weapon, rank, refinement, note, overallPercent, personalPercent,
|
||||
exporting = false, compactExportGrid = false, weaponHref,
|
||||
imageControl, refinementControl, noteControl, actions, renderMetric,
|
||||
}: {
|
||||
weapon: CatalogItemImageData & { name: string };
|
||||
rank: number;
|
||||
refinement: string;
|
||||
note: string | null;
|
||||
overallPercent: string | null;
|
||||
personalPercent: string | null;
|
||||
exporting?: boolean;
|
||||
compactExportGrid?: boolean;
|
||||
weaponHref?: string;
|
||||
imageControl?: ReactNode;
|
||||
refinementControl?: ReactNode;
|
||||
noteControl?: ReactNode;
|
||||
actions?: ReactNode;
|
||||
renderMetric?: (metric: DamageMetric) => ReactNode;
|
||||
}) {
|
||||
const Panel = weaponHref ? "a" : "div";
|
||||
const title = <p className={cn(
|
||||
"truncate font-semibold",
|
||||
compactExportGrid ? "text-sm" : exporting ? "text-lg" : "text-base sm:text-lg",
|
||||
)}>
|
||||
{rank}. {weapon.name}{refinementControl ? null : ` R${refinement}`}
|
||||
</p>;
|
||||
|
||||
return <Card size="sm" className="bg-white py-0">
|
||||
<CardContent className={cn(
|
||||
"grid p-0",
|
||||
compactExportGrid
|
||||
? "grid-cols-[minmax(0,3fr)_minmax(0,2fr)]"
|
||||
: exporting
|
||||
? "grid-cols-[minmax(0,3fr)_minmax(0,1fr)]"
|
||||
: renderMetric
|
||||
? "md:grid-cols-[minmax(0,5fr)_minmax(0,2fr)]"
|
||||
: "md:grid-cols-[minmax(0,3fr)_minmax(0,1fr)]",
|
||||
)}>
|
||||
<Panel
|
||||
href={weaponHref}
|
||||
target={weaponHref ? "_blank" : undefined}
|
||||
rel={weaponHref ? "noreferrer" : undefined}
|
||||
tabIndex={exporting ? -1 : undefined}
|
||||
aria-label={weaponHref ? `เปิดข้อมูลอาวุธ ${weapon.name} บน Lunaris` : undefined}
|
||||
className={cn(
|
||||
"flex min-h-28 min-w-0 items-center gap-4 rounded-br-[4rem] p-4 pr-10 text-white",
|
||||
compactExportGrid
|
||||
? "rounded-br-[8rem] pr-10"
|
||||
: exporting ? "rounded-br-[8rem] pr-16" : "md:rounded-br-[8rem] md:pr-16",
|
||||
rarityGradientClass(weapon.rarity),
|
||||
actions && "relative",
|
||||
)}
|
||||
>
|
||||
{imageControl ?? <CatalogItemImage
|
||||
item={weapon} kind="weapon" alt={weapon.name} rarityBackground={false}
|
||||
className="size-20 shrink-0" loading={exporting ? "eager" : undefined}
|
||||
sizes="(min-width: 768px) 5rem, 4rem"
|
||||
/>}
|
||||
<div className="flex min-w-0 flex-col gap-1">
|
||||
{refinementControl ? <div className="flex min-w-0 flex-wrap items-center gap-2">{title}{refinementControl}</div> : title}
|
||||
{noteControl ?? (note ? <p className={cn("whitespace-pre-wrap", compactExportGrid ? "text-xs" : "text-sm")}>{note}</p> : null)}
|
||||
</div>
|
||||
{actions}
|
||||
</Panel>
|
||||
<div className={cn(
|
||||
"flex items-center justify-around bg-white py-5 text-black",
|
||||
compactExportGrid ? "gap-1 px-2" : "gap-4 px-4",
|
||||
)}>
|
||||
{(["overallPercent", "personalPercent"] as const).map((metric) => {
|
||||
const value = metric === "overallPercent" ? overallPercent : personalPercent;
|
||||
if (!renderMetric && !value) return null;
|
||||
return <div key={metric} className="min-w-0 flex-1 text-center">
|
||||
<p className={cn(
|
||||
"whitespace-nowrap leading-none font-bold",
|
||||
compactExportGrid ? "text-2xl" : exporting ? "text-5xl" : "text-4xl sm:text-5xl",
|
||||
rarityTextClass(weapon.rarity),
|
||||
)}>
|
||||
{renderMetric ? renderMetric(metric) : weaponComparisonPercent(value, exporting)}
|
||||
</p>
|
||||
<p className={cn(
|
||||
"mt-1 whitespace-nowrap",
|
||||
compactExportGrid ? "text-[10px]" : exporting ? "text-base" : "text-sm sm:text-base",
|
||||
)}>
|
||||
{metric === "overallPercent" ? "ดาเมจทั้งทีม" : "ดาเมจส่วนตัว"}
|
||||
</p>
|
||||
</div>;
|
||||
})}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>;
|
||||
}
|
||||
Reference in New Issue
Block a user