fix : correct color
This commit is contained in:
@@ -17,7 +17,7 @@ import { Field, FieldDescription, FieldGroup, FieldLabel } from "@/components/ui
|
||||
import { InputGroup, InputGroupAddon, InputGroupInput } from "@/components/ui/input-group";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { characterRarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type Character = { key: string; name: string; aliases: string[]; element: string | null; rarity: number | null; imageUrl: string };
|
||||
@@ -85,7 +85,7 @@ export function CreateGuideFlow({ characters, existingKeys }: { characters: Char
|
||||
const disabled = existing.has(character.key);
|
||||
return (
|
||||
<Card key={character.key} className="overflow-hidden py-0">
|
||||
<div className={cn("relative aspect-square", rarityGradientClass(character.rarity))}><Image src={character.imageUrl} alt={character.name} fill className="object-cover" /></div>
|
||||
<div className={cn("relative aspect-square", characterRarityGradientClass(character.key, character.rarity))}><Image src={character.imageUrl} alt={character.name} fill className="object-cover" /></div>
|
||||
<CardHeader className="pt-4">
|
||||
<CardTitle>{character.name}</CardTitle>
|
||||
<CardDescription>{character.element ?? "Unknown element"}</CardDescription>
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, Pagi
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import type { GlossaryKind } from "@/lib/glossary";
|
||||
import { rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { characterRarityGradientClass, rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type CatalogItem = { key: string; name: string; imageUrl: string; rarity?: number | null };
|
||||
@@ -113,6 +113,7 @@ export function GlossaryManager({
|
||||
onValueChange={(key) => setItem(catalogs[kind].find((value) => value.key === key) ?? null)}
|
||||
placeholder="ค้นหารายการ…"
|
||||
rarityBackground
|
||||
characterBackground={kind === "character"}
|
||||
/>
|
||||
</Field>
|
||||
<Field>
|
||||
@@ -154,7 +155,7 @@ export function GlossaryManager({
|
||||
{catalogItem ? (
|
||||
<span className={cn(
|
||||
"relative size-10 shrink-0 overflow-hidden rounded-md bg-muted",
|
||||
rarityGradientClass(catalogItem.rarity),
|
||||
entry.kind === "character" ? characterRarityGradientClass(catalogItem.key, catalogItem.rarity) : rarityGradientClass(catalogItem.rarity),
|
||||
)}>
|
||||
<Image src={catalogItem.imageUrl} alt="" fill sizes="40px" className="object-contain" />
|
||||
</span>
|
||||
|
||||
@@ -162,7 +162,7 @@ import {
|
||||
} from "@/lib/guides/stats";
|
||||
import { elementBackgroundColor, elementIconFilter } from "@/lib/catalog/element";
|
||||
import { supportsWeaponType } from "@/lib/catalog/lunaris";
|
||||
import { rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { characterRarityGradientClass, rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { isCustomTravelerKey } from "@/lib/catalog/travelers";
|
||||
import {
|
||||
applyPresetFields,
|
||||
@@ -3911,7 +3911,7 @@ function TeamEditor({
|
||||
return (
|
||||
<div key={member.characterKey} className="min-w-0 text-center">
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<div className={cn("relative size-16 shrink-0 overflow-hidden rounded-lg bg-muted", rarityGradientClass(isCustomTravelerKey(member.characterKey) ? 5 : character?.rarity))}>
|
||||
<div className={cn("relative size-16 shrink-0 overflow-hidden rounded-lg bg-muted", characterRarityGradientClass(member.characterKey, isCustomTravelerKey(member.characterKey) ? 5 : character?.rarity))}>
|
||||
{character ? <Image src={character.imageUrl} alt={character.name} fill sizes="64px" className="object-contain" /> : null}
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
@@ -4162,6 +4162,7 @@ function ExtraCatalogItemsEditor({
|
||||
placeholder={`เลือก${labels[kind]}`}
|
||||
showSelectedImage
|
||||
rarityBackground
|
||||
characterBackground={kind === "character"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -219,6 +219,7 @@ function ItemPicker({
|
||||
placeholder={`Search ${kind}…`}
|
||||
emptyLabel="No matches"
|
||||
rarityBackground
|
||||
characterBackground={kind === "character"}
|
||||
/>
|
||||
</Field>
|
||||
) : null}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
ComboboxTrigger,
|
||||
FuzzyCombobox,
|
||||
} from "@/components/ui/combobox";
|
||||
import { rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { characterRarityGradientClass, rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface AdminCatalogItem {
|
||||
@@ -50,6 +50,7 @@ type CommonSelectProps<Item extends AdminCatalogItem> = {
|
||||
emptyLabel?: string;
|
||||
invalid?: boolean;
|
||||
rarityBackground?: boolean;
|
||||
characterBackground?: boolean;
|
||||
searchNames?: (item: Item) => string[];
|
||||
};
|
||||
|
||||
@@ -69,6 +70,7 @@ export function CatalogDropdown<Item extends AdminCatalogItem>({
|
||||
emptyLabel = "ไม่พบรายการ",
|
||||
invalid = false,
|
||||
rarityBackground = false,
|
||||
characterBackground = false,
|
||||
showSelectedImage = false,
|
||||
showClear = true,
|
||||
label,
|
||||
@@ -82,7 +84,7 @@ export function CatalogDropdown<Item extends AdminCatalogItem>({
|
||||
<div
|
||||
className={cn(
|
||||
"relative size-10 shrink-0 overflow-hidden rounded-md",
|
||||
rarityBackground && rarityGradientClass(selected.rarity),
|
||||
rarityBackground && (characterBackground ? characterRarityGradientClass(selected.key, selected.rarity) : rarityGradientClass(selected.rarity)),
|
||||
)}
|
||||
>
|
||||
<Image src={selected.imageUrl} alt="" fill sizes="40px" className="object-contain" />
|
||||
@@ -110,7 +112,7 @@ export function CatalogDropdown<Item extends AdminCatalogItem>({
|
||||
<ComboboxList>
|
||||
{(item) => (
|
||||
<ComboboxItem key={item.key} value={item}>
|
||||
<CatalogOptionImage item={item} rarityBackground={rarityBackground} />
|
||||
<CatalogOptionImage item={item} rarityBackground={rarityBackground} characterBackground={characterBackground} />
|
||||
<span className="whitespace-nowrap">{item.name}</span>
|
||||
</ComboboxItem>
|
||||
)}
|
||||
@@ -138,6 +140,7 @@ function CatalogSlotSelect<Item extends AdminCatalogItem>({
|
||||
emptyLabel = "ไม่พบรายการ",
|
||||
invalid = false,
|
||||
rarityBackground = true,
|
||||
characterBackground = false,
|
||||
searchNames = (item) => [item.name, ...(item.aliases ?? [])],
|
||||
className,
|
||||
}: CatalogSlotSelectProps<Item>) {
|
||||
@@ -158,7 +161,7 @@ function CatalogSlotSelect<Item extends AdminCatalogItem>({
|
||||
aria-invalid={invalid}
|
||||
className={cn(
|
||||
"relative flex aspect-square w-full items-center justify-center overflow-hidden rounded-md border bg-muted p-0 outline-none focus-visible:ring-2 focus-visible:ring-ring aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 [&>svg]:hidden",
|
||||
rarityBackground && selected && rarityGradientClass(selected.rarity),
|
||||
rarityBackground && selected && (characterBackground ? characterRarityGradientClass(selected.key, selected.rarity) : rarityGradientClass(selected.rarity)),
|
||||
className,
|
||||
)}
|
||||
>
|
||||
@@ -174,7 +177,7 @@ function CatalogSlotSelect<Item extends AdminCatalogItem>({
|
||||
<ComboboxList>
|
||||
{(item) => (
|
||||
<ComboboxItem key={item.key} value={item}>
|
||||
<CatalogOptionImage item={item} rarityBackground={rarityBackground} />
|
||||
<CatalogOptionImage item={item} rarityBackground={rarityBackground} characterBackground={characterBackground} />
|
||||
<span className="whitespace-nowrap">{item.name}</span>
|
||||
</ComboboxItem>
|
||||
)}
|
||||
@@ -216,7 +219,7 @@ function DomainCatalogSelect<Item extends AdminCatalogItem>({
|
||||
}
|
||||
|
||||
export function CharacterSelect<Item extends AdminCatalogItem>(props: DomainSelectProps<Item>) {
|
||||
return <DomainCatalogSelect {...props} />;
|
||||
return <DomainCatalogSelect {...props} characterBackground />;
|
||||
}
|
||||
|
||||
export function WeaponSelect<Item extends AdminCatalogItem>(props: DomainSelectProps<Item>) {
|
||||
@@ -318,15 +321,17 @@ export function ArtifactSelect<Item extends AdminCatalogItem>(
|
||||
function CatalogOptionImage({
|
||||
item,
|
||||
rarityBackground,
|
||||
characterBackground = false,
|
||||
}: {
|
||||
item: AdminCatalogItem;
|
||||
rarityBackground: boolean;
|
||||
characterBackground?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"relative size-8 shrink-0 overflow-hidden rounded-md",
|
||||
rarityBackground && rarityGradientClass(item.rarity),
|
||||
rarityBackground && (characterBackground ? characterRarityGradientClass(item.key, item.rarity) : rarityGradientClass(item.rarity)),
|
||||
)}
|
||||
>
|
||||
<Image src={item.imageUrl} alt="" fill sizes="32px" className="object-contain" />
|
||||
|
||||
@@ -2,15 +2,15 @@ import Image from "next/image";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { elementBackgroundColor } from "@/lib/catalog/element";
|
||||
import { rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { characterRarityGradientClass, rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import type { CommissionRequest } from "@/lib/commission/request";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type Item = { key: string; name: string; imageUrl: string; rarity?: number | null; element?: string | null };
|
||||
type Catalog = { characters: Item[]; weapons: Item[]; artifacts: Item[] };
|
||||
|
||||
function ItemImage({ item, size = "small" }: { item: Item; size?: "small" | "large" }) {
|
||||
return <div title={item.name} className={cn("relative aspect-square min-w-0 overflow-hidden rounded-lg", rarityGradientClass(item.rarity))}>
|
||||
function ItemImage({ item, size = "small", character = false }: { item: Item; size?: "small" | "large"; character?: boolean }) {
|
||||
return <div title={item.name} className={cn("relative aspect-square min-w-0 overflow-hidden rounded-lg", character ? characterRarityGradientClass(item.key, item.rarity) : rarityGradientClass(item.rarity))}>
|
||||
<Image src={item.imageUrl} alt={item.name} fill sizes={size === "large" ? "160px" : "64px"} className="object-contain" />
|
||||
</div>;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ function CommissionTeamCard({ team, index, catalog }: { team: CommissionRequest[
|
||||
const artifact = artifacts.get(member.artifactKey);
|
||||
return <div key={memberIndex} className="min-w-0 rounded-lg p-1 lg:p-1.5" style={{ backgroundColor: elementBackgroundColor(character?.element) }}>
|
||||
<div className="grid grid-cols-1 gap-1 lg:grid-cols-[2fr_1fr]">
|
||||
{character ? <ItemImage item={character} size="large" /> : <div className="aspect-square rounded-lg bg-muted" />}
|
||||
{character ? <ItemImage item={character} size="large" character /> : <div className="aspect-square rounded-lg bg-muted" />}
|
||||
<div className="grid min-w-0 grid-cols-2 gap-0.5 lg:grid-cols-1 lg:grid-rows-2 lg:gap-1">
|
||||
{weapon ? <ItemImage item={weapon} /> : <div title={member.weaponKey} className="aspect-square rounded-lg bg-muted" />}
|
||||
{artifact ? <ItemImage item={artifact} /> : <div title={member.artifactKey} className="aspect-square rounded-lg bg-muted" />}
|
||||
@@ -77,7 +77,7 @@ export function CommissionRequestSummary({ request, catalog, amountBaht }: {
|
||||
: <p key={key} className="w-16 wrap-break-word text-xs">{key}</p>;
|
||||
})}
|
||||
</div>
|
||||
{character ? <div className="w-16 min-w-0"><ItemImage item={character} size="large" /><p className="mt-1 truncate text-center text-xs" title={character.name}>{character.name}</p></div> : null}
|
||||
{character ? <div className="w-16 min-w-0"><ItemImage item={character} size="large" character /><p className="mt-1 truncate text-center text-xs" title={character.name}>{character.name}</p></div> : null}
|
||||
</CardContent>
|
||||
</Card>;
|
||||
})}
|
||||
@@ -89,7 +89,7 @@ export function CommissionRequestSummary({ request, catalog, amountBaht }: {
|
||||
</CardHeader>
|
||||
<CardContent className="grid grid-cols-[minmax(0,1fr)_64px] items-center gap-3">
|
||||
<div className="flex min-w-0 flex-wrap gap-2">{set.levels.map((level) => <Badge key={level} variant="outline">C{level}</Badge>)}</div>
|
||||
{character ? <div className="w-16 min-w-0"><ItemImage item={character} size="large" /><p className="mt-1 truncate text-center text-xs" title={character.name}>{character.name}</p></div> : null}
|
||||
{character ? <div className="w-16 min-w-0"><ItemImage item={character} size="large" character /><p className="mt-1 truncate text-center text-xs" title={character.name}>{character.name}</p></div> : null}
|
||||
</CardContent>
|
||||
</Card>;
|
||||
})}
|
||||
|
||||
@@ -776,8 +776,24 @@ export function CommissionTicketChat({
|
||||
mine ? "items-end" : "items-start",
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"w-full px-1 text-center text-xs font-medium text-muted-foreground",
|
||||
mine ? "translate-x-5" : "-translate-x-5",
|
||||
)}
|
||||
>
|
||||
<time
|
||||
dateTime={sentAt.toISOString()}
|
||||
title={sentAt.toLocaleString("th-TH")}
|
||||
>
|
||||
{sentAt.toLocaleTimeString("th-TH", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
})}
|
||||
</time>
|
||||
</div>
|
||||
<MessageHeader className="px-1">
|
||||
{mine ? "คุณ" : message.authorName}
|
||||
{message.authorName}
|
||||
</MessageHeader>
|
||||
<div
|
||||
className={cn(
|
||||
@@ -947,22 +963,6 @@ export function CommissionTicketChat({
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<MessageFooter
|
||||
className={cn(
|
||||
"w-full justify-center gap-1 px-1 group-data-[align=end]/message:justify-center",
|
||||
mine ? "translate-x-5" : "-translate-x-5",
|
||||
)}
|
||||
>
|
||||
<time
|
||||
dateTime={sentAt.toISOString()}
|
||||
title={sentAt.toLocaleString("th-TH")}
|
||||
>
|
||||
{sentAt.toLocaleTimeString("th-TH", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
})}
|
||||
</time>
|
||||
</MessageFooter>
|
||||
</MessageContent>
|
||||
</Message>
|
||||
);
|
||||
@@ -970,7 +970,6 @@ export function CommissionTicketChat({
|
||||
{visibleOptimisticMessages.map((message) => (
|
||||
<Message key={message.localId} align="end">
|
||||
<MessageContent className="w-full items-end gap-1">
|
||||
<MessageHeader className="px-1">คุณ</MessageHeader>
|
||||
<Bubble
|
||||
variant={message.imageUrl ? "ghost" : "muted"}
|
||||
className="max-w-[min(82%,36rem)]"
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function CommissionTicketDetail({ id, admin }: { id: string; admin:
|
||||
const catalog = await getCommissionLabels(data.checkout.request);
|
||||
return <div className="flex min-h-0 flex-1 flex-col gap-3">
|
||||
<CommissionTicketPanels summary={
|
||||
<Card className="h-full min-h-0"><CardHeader className="shrink-0"><CardTitle>คำขอที่ชำระเงินแล้ว - ฿{data.checkout.amountBaht}</CardTitle></CardHeader>
|
||||
<Card className="h-full min-h-0"><CardHeader className="shrink-0"><CardTitle>รายละเอียดคำขอ - ฿{data.checkout.amountBaht}</CardTitle></CardHeader>
|
||||
<CardContent className="flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto">{catalog && <CommissionRequestSummary request={data.checkout.request} catalog={catalog} amountBaht={data.checkout.amountBaht} />}
|
||||
<p className="text-sm text-muted-foreground">การชำระเงิน: {data.payment.transRef} - {data.payment.transferredAt.toLocaleString("th-TH")}</p>
|
||||
<CommissionSlipDialog src={publicMediaUrl(data.payment.slipObjectKey)} />
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
StygianBossTab,
|
||||
} from "@/components/stygian/stygian-boss-display";
|
||||
import { elementIconFilter } from "@/lib/catalog/element";
|
||||
import { rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { characterRarityGradientClass, rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import type { getActiveCatalog } from "@/lib/guides/queries";
|
||||
import type { getStygianSchedule } from "@/lib/stygian/repository";
|
||||
import { cn } from "@/lib/utils";
|
||||
@@ -47,7 +47,7 @@ function RecommendationIcon({ item, catalog, teamLayout = false }: { item: Item;
|
||||
return (
|
||||
<div className={cn("flex min-w-0 flex-col gap-1 rounded-lg border bg-card p-1", teamLayout && "w-full sm:p-2", teamLayout && hasEquipment && "sm:w-[164px]", teamLayout && !hasEquipment && "sm:w-[116px]", teamLayout && !hasEquipment && item.constellationLevel === null && "aspect-square justify-center")}>
|
||||
<div className={teamLayout && hasEquipment ? "flex flex-col gap-1 sm:grid sm:grid-cols-[100px_40px] sm:gap-2" : "flex flex-col gap-1"}>
|
||||
<div className={cn("relative aspect-square overflow-hidden rounded-lg", teamLayout && "sm:size-[100px]", teamLayout && hasEquipment && "sm:row-span-2", rarityGradientClass(value.rarity))}>
|
||||
<div className={cn("relative aspect-square overflow-hidden rounded-lg", teamLayout && "sm:size-[100px]", teamLayout && hasEquipment && "sm:row-span-2", characterRarityGradientClass(item.catalogKey, value.rarity))}>
|
||||
{value.imageUrl ? <Image src={value.imageUrl} alt={value.name} fill sizes={teamLayout ? "(min-width: 640px) 128px, 25vw" : "128px"} className="object-contain" /> : null}
|
||||
</div>
|
||||
{hasEquipment ? <div className={teamLayout ? "grid grid-cols-2 gap-1 sm:row-span-2 sm:grid-cols-1 sm:gap-2 sm:self-center" : "grid grid-cols-2 gap-1"}>
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||
import { elementBackgroundColor } from "@/lib/catalog/element";
|
||||
import { rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { characterRarityGradientClass, rarityGradientClass } from "@/lib/catalog/rarity";
|
||||
import { isCustomTravelerKey } from "@/lib/catalog/travelers";
|
||||
import type { PublicGuide } from "@/lib/guides/queries";
|
||||
import { teamConstellationLabel, teamRefinementLabel } from "@/lib/guides/team-tools";
|
||||
@@ -226,7 +226,7 @@ export function TeamExportImage({ team }: { team: TeamExportData }) {
|
||||
const percent = total > 0 ? damage / total * 100 : 0;
|
||||
return (
|
||||
<div key={member.position} className="flex h-43.5 items-center gap-6 rounded-3xl p-3.5" style={{ backgroundColor: elementBackgroundColor(member.character.element) }}>
|
||||
<div className={cn("relative size-35 shrink-0 overflow-hidden rounded-3xl border-[3px] border-white/20", rarityGradientClass(isCustomTravelerKey(member.character.key) ? 5 : member.character.rarity))}>
|
||||
<div className={cn("relative size-35 shrink-0 overflow-hidden rounded-3xl border-[3px] border-white/20", characterRarityGradientClass(member.character.key, isCustomTravelerKey(member.character.key) ? 5 : member.character.rarity))}>
|
||||
<Image src={member.character.imageUrl} alt="" fill loading="eager" sizes="140px" className="object-contain" />
|
||||
</div>
|
||||
<div className="grid w-44 shrink-0 grid-cols-2 gap-3">
|
||||
@@ -316,7 +316,8 @@ function TeamCard({
|
||||
exporting
|
||||
? "col-span-2 row-span-2"
|
||||
: "sm:col-span-2 sm:row-span-2",
|
||||
rarityGradientClass(
|
||||
characterRarityGradientClass(
|
||||
member.character.key,
|
||||
isCustomTravelerKey(member.character.key)
|
||||
? 5
|
||||
: member.character.rarity,
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { rarityGradient, rarityGradientClass, rarityTextClass, rarityTextColor } from "@/lib/catalog/rarity";
|
||||
import { characterRarityGradientClass, rarityGradient, rarityGradientClass, rarityTextClass, rarityTextColor } from "@/lib/catalog/rarity";
|
||||
|
||||
describe("catalog rarity backgrounds", () => {
|
||||
it("maps every weapon and artifact rarity to its Tailwind gradient", () => {
|
||||
expect(rarityGradientClass(1)).toContain("rgba(23,25,28,1)");
|
||||
expect(rarityGradientClass(2)).toContain("rgba(11,43,24,1)");
|
||||
expect(rarityGradientClass(1)).toBe("bg-[#697177] bg-[linear-gradient(90deg,rgba(105,113,119,1)_0%,rgba(137,144,147,1)_100%)]");
|
||||
expect(rarityGradientClass(2)).toBe("bg-[#5D8972] bg-[linear-gradient(90deg,rgba(93,137,114,1)_0%,rgba(121,167,127,1)_100%)]");
|
||||
expect(rarityGradient(1)).toBe("linear-gradient(90deg, rgba(105, 113, 119, 1) 0%, rgba(137, 144, 147, 1) 100%)");
|
||||
expect(rarityGradient(2)).toBe("linear-gradient(90deg, rgba(93, 137, 114, 1) 0%, rgba(121, 167, 127, 1) 100%)");
|
||||
expect(rarityGradientClass(3)).toBe("bg-[#4D7691] bg-[linear-gradient(90deg,rgba(77,118,145,1)_0%,rgba(71,135,165,1)_100%)]");
|
||||
expect(rarityGradientClass(4)).toBe("bg-[#6D6A9C] bg-[linear-gradient(90deg,rgba(109,106,156,1)_0%,rgba(150,122,179,1)_100%)]");
|
||||
expect(rarityGradientClass(5)).toBe("bg-[#A67B34] bg-[linear-gradient(90deg,rgba(166,123,52,1)_0%,rgba(178,123,44,1)_100%)]");
|
||||
@@ -26,4 +28,14 @@ describe("catalog rarity backgrounds", () => {
|
||||
expect(rarityTextClass(undefined)).toBeUndefined();
|
||||
expect(rarityTextColor(undefined)).toBe("#17171c");
|
||||
});
|
||||
|
||||
it("uses red for special characters without changing other rarity backgrounds", () => {
|
||||
for (const key of ["10000062", "10000117", "10000118"]) {
|
||||
expect(characterRarityGradientClass(key, 5)).toBe("bg-[#9A424E] bg-[linear-gradient(90deg,#9A424E_0%,#B85D67_100%)]");
|
||||
expect(characterRarityGradientClass(key, null)).toBe(characterRarityGradientClass(key, 5));
|
||||
}
|
||||
expect(characterRarityGradientClass("ordinary-character", 5)).toBe(rarityGradientClass(5));
|
||||
expect(characterRarityGradientClass("ordinary-character", 1)).toBe(rarityGradientClass(1));
|
||||
expect(characterRarityGradientClass("ordinary-character", 2)).toBe(rarityGradientClass(2));
|
||||
});
|
||||
});
|
||||
|
||||
+11
-4
@@ -1,14 +1,17 @@
|
||||
const rarityGradientClasses: Record<number, string> = {
|
||||
1: "bg-[linear-gradient(90deg,rgba(23,25,28,1)_0%,rgba(19,20,23,1)_100%)]",
|
||||
2: "bg-[linear-gradient(90deg,rgba(11,43,24,1)_0%,rgba(7,18,13,1)_100%)]",
|
||||
1: "bg-[#697177] bg-[linear-gradient(90deg,rgba(105,113,119,1)_0%,rgba(137,144,147,1)_100%)]",
|
||||
2: "bg-[#5D8972] bg-[linear-gradient(90deg,rgba(93,137,114,1)_0%,rgba(121,167,127,1)_100%)]",
|
||||
3: "bg-[#4D7691] bg-[linear-gradient(90deg,rgba(77,118,145,1)_0%,rgba(71,135,165,1)_100%)]",
|
||||
4: "bg-[#6D6A9C] bg-[linear-gradient(90deg,rgba(109,106,156,1)_0%,rgba(150,122,179,1)_100%)]",
|
||||
5: "bg-[#A67B34] bg-[linear-gradient(90deg,rgba(166,123,52,1)_0%,rgba(178,123,44,1)_100%)]",
|
||||
};
|
||||
|
||||
const specialCharacterKeys = new Set(["10000062", "10000117", "10000118"]);
|
||||
const specialCharacterGradientClass = "bg-[#9A424E] bg-[linear-gradient(90deg,#9A424E_0%,#B85D67_100%)]";
|
||||
|
||||
const rarityGradients: Record<number, string> = {
|
||||
1: "linear-gradient(90deg, rgba(23, 25, 28, 1) 0%, rgba(19, 20, 23, 1) 100%)",
|
||||
2: "linear-gradient(90deg, rgba(11, 43, 24, 1) 0%, rgba(7, 18, 13, 1) 100%)",
|
||||
1: "linear-gradient(90deg, rgba(105, 113, 119, 1) 0%, rgba(137, 144, 147, 1) 100%)",
|
||||
2: "linear-gradient(90deg, rgba(93, 137, 114, 1) 0%, rgba(121, 167, 127, 1) 100%)",
|
||||
3: "linear-gradient(90deg, rgba(77, 118, 145, 1) 0%, rgba(71, 135, 165, 1) 100%)",
|
||||
4: "linear-gradient(90deg, rgba(109, 106, 156, 1) 0%, rgba(150, 122, 179, 1) 100%)",
|
||||
5: "linear-gradient(90deg, rgba(166, 123, 52, 1) 0%, rgba(178, 123, 44, 1) 100%)",
|
||||
@@ -30,6 +33,10 @@ export function rarityGradientClass(rarity: number | null | undefined): string |
|
||||
return rarity ? rarityGradientClasses[rarity] : undefined;
|
||||
}
|
||||
|
||||
export function characterRarityGradientClass(key: string | null | undefined, rarity: number | null | undefined): string | undefined {
|
||||
return key && specialCharacterKeys.has(key) ? specialCharacterGradientClass : rarityGradientClass(rarity);
|
||||
}
|
||||
|
||||
export function rarityGradient(rarity: number | null | undefined): string {
|
||||
return (rarity && rarityGradients[rarity]) || "#17383d";
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ function rarity(value: string | undefined): number | null {
|
||||
QUALITY_BLUE: 3,
|
||||
QUALITY_PURPLE: 4,
|
||||
QUALITY_ORANGE: 5,
|
||||
QUALITY_ORANGE_SP: 5,
|
||||
}[value] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as z from "zod";
|
||||
|
||||
export const lunarisVersionSchema = z.string().regex(/^\d+(?:\.\d+)+$/u);
|
||||
export const catalogFormatVersion = 2;
|
||||
export const catalogFormatVersion = 3;
|
||||
|
||||
export interface LunarisVersionChange {
|
||||
previousVersion: string;
|
||||
|
||||
Reference in New Issue
Block a user