1
0
Fork 0
polaris-task-force/src/components/frontend/account/AwardCard.tsx

94 lines
3.3 KiB
TypeScript

import { Award, Media } from "@/payload-types";
import { Item, ItemContent, ItemDescription, ItemHeader, ItemTitle } from "@/components/ui/item";
import { convertLexicalToPlaintext } from "@payloadcms/richtext-lexical/plaintext";
import { RibbonViewer } from "@/components/frontend/account/RibbonViewer";
import { RibbonDesign } from "@/components/admin/awards/RibbonDesigner";
import { cn } from "@/lib/utils";
const getExperiencePointsClass = (experiencePoints: number) => {
if (experiencePoints >= 5000) return "award-xp-high";
if (experiencePoints >= 1000) return "text-emerald-400";
if (experiencePoints >= 501) return "text-lime-300";
if (experiencePoints >= 200) return "text-sky-300";
return "text-muted-foreground";
};
export default function AwardCard(props: { awardImage: Media | null; award: Award }) {
const isCommendation = props.award.type === "commendation" || !props.award.type;
const commendationColor =
isCommendation &&
typeof props.award.commendationColor === "string" &&
/^#[0-9a-f]{6}$/i.test(props.award.commendationColor)
? props.award.commendationColor
: null;
return (
<Item
variant="outline"
size={isCommendation ? "sm" : "default"}
className={cn("text-center", {
"medal-card": props.award.type === "medal",
"commendation-card": isCommendation,
})}
style={
commendationColor
? {
borderColor: commendationColor,
backgroundColor: `${commendationColor}33`,
}
: undefined
}
>
<ItemHeader className="flex flex-col items-center">
{props.award.ribbonDesign && (
<RibbonViewer
ribbonDesign={props.award.ribbonDesign as RibbonDesign}
showRibbonOnly={true}
/>
)}
<div className="flex items-center gap-2.5">
{props.awardImage?.url && (
<img
src={props.awardImage.url}
alt={props.award.name}
className={cn("object-contain", isCommendation ? "size-6" : "size-8")}
/>
)}
<div className="flex flex-col">
<ItemTitle
className={cn({
"text-xl text-shadow-lg text-shadow-white/15": props.award.type === "medal",
"text-xs": isCommendation,
})}
>
{props.award.name}
</ItemTitle>
<span className="text-[9px] uppercase tracking-wider text-muted-foreground font-mono">
{props.award.type ?? "commendation"}
</span>
</div>
</div>
</ItemHeader>
<ItemContent>
<ItemDescription
className={cn("text-center", isCommendation ? "line-clamp-none text-xs" : "line-clamp-3")}
>
{props.award.description
? convertLexicalToPlaintext({ data: props.award.description })
: "No description."}
</ItemDescription>
{props.award.experiencePoints != null && (
<span
className={cn(
"mt-1 font-mono",
getExperiencePointsClass(props.award.experiencePoints),
isCommendation ? "text-[10px]" : "text-xs",
)}
>
+{props.award.experiencePoints} XP
</span>
)}
</ItemContent>
</Item>
);
}