fix(extra) : add drag sorting and correct character links
This commit is contained in:
@@ -4,8 +4,6 @@ import dynamic from "next/dynamic";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import {
|
import {
|
||||||
ChartNoAxesCombinedIcon,
|
ChartNoAxesCombinedIcon,
|
||||||
ChevronDownIcon,
|
|
||||||
ChevronUpIcon,
|
|
||||||
ClipboardCopyIcon,
|
ClipboardCopyIcon,
|
||||||
ClipboardPasteIcon,
|
ClipboardPasteIcon,
|
||||||
CopyIcon,
|
CopyIcon,
|
||||||
@@ -3370,48 +3368,76 @@ function ExtraCatalogItemsEditor({
|
|||||||
artifacts: CatalogItem[];
|
artifacts: CatalogItem[];
|
||||||
onChange: (value: ExtraCatalogItem[]) => void;
|
onChange: (value: ExtraCatalogItem[]) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const sensors = useSensors(
|
||||||
|
useSensor(PointerSensor),
|
||||||
|
useSensor(KeyboardSensor, {
|
||||||
|
coordinateGetter: sortableKeyboardCoordinates,
|
||||||
|
}),
|
||||||
|
);
|
||||||
const [kind, setKind] = useState<ExtraCatalogItem["kind"]>("character");
|
const [kind, setKind] = useState<ExtraCatalogItem["kind"]>("character");
|
||||||
const [key, setKey] = useState("");
|
const [key, setKey] = useState("");
|
||||||
const catalogs = { character: characters, weapon: weapons, artifact: artifacts };
|
const catalogs = { character: characters, weapon: weapons, artifact: artifacts };
|
||||||
const labels = { character: "ตัวละคร", weapon: "อาวุธ", artifact: "อาร์ติแฟกต์" };
|
const labels = { character: "ตัวละคร", weapon: "อาวุธ", artifact: "อาร์ติแฟกต์" };
|
||||||
const items = catalogs[kind];
|
const items = catalogs[kind];
|
||||||
|
const itemId = (item: ExtraCatalogItem) => `${item.kind}:${item.key}`;
|
||||||
|
const handleDragEnd = ({ active, over }: DragEndEvent) => {
|
||||||
|
if (!over || active.id === over.id) return;
|
||||||
|
const from = value.findIndex((item) => itemId(item) === active.id);
|
||||||
|
const to = value.findIndex((item) => itemId(item) === over.id);
|
||||||
|
if (from !== -1 && to !== -1) onChange(arrayMove(value, from, to));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel>ตัวละคร อาวุธ และอาร์ติแฟกต์</FieldLabel>
|
<FieldLabel>ตัวละคร อาวุธ และอาร์ติแฟกต์</FieldLabel>
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
{value.length ? (
|
{value.length ? (
|
||||||
<div className="flex flex-col gap-2">
|
<DndContext
|
||||||
{value.map((reference, index) => {
|
sensors={sensors}
|
||||||
const item = catalogs[reference.kind].find(
|
collisionDetection={closestCenter}
|
||||||
(candidate) => candidate.key === reference.key,
|
onDragEnd={handleDragEnd}
|
||||||
);
|
>
|
||||||
return (
|
<SortableContext
|
||||||
<Card key={`${reference.kind}:${reference.key}`} size="sm">
|
items={value.map(itemId)}
|
||||||
<CardContent className="flex items-center gap-3">
|
strategy={verticalListSortingStrategy}
|
||||||
{item ? (
|
>
|
||||||
<div className={cn("relative size-12 shrink-0 overflow-hidden rounded-md", rarityGradientClass(item.rarity))}>
|
<div className="flex flex-col gap-2">
|
||||||
<Image src={item.imageUrl} alt="" fill className="object-contain" />
|
{value.map((reference, index) => {
|
||||||
</div>
|
const item = catalogs[reference.kind].find(
|
||||||
) : null}
|
(candidate) => candidate.key === reference.key,
|
||||||
<div className="min-w-0 flex-1">
|
);
|
||||||
<p className="truncate font-medium">{item?.name ?? reference.key}</p>
|
const label = item?.name ?? reference.key;
|
||||||
<p className="text-sm text-muted-foreground">{labels[reference.kind]}</p>
|
return (
|
||||||
</div>
|
<SortableExtraItem
|
||||||
<Button type="button" variant="ghost" size="icon-sm" disabled={index === 0} onClick={() => onChange(arrayMove(value, index, index - 1))} aria-label="เลื่อนขึ้น">
|
key={itemId(reference)}
|
||||||
<ChevronUpIcon />
|
id={itemId(reference)}
|
||||||
</Button>
|
label={`ลากเพื่อจัดลำดับ ${label}`}
|
||||||
<Button type="button" variant="ghost" size="icon-sm" disabled={index === value.length - 1} onClick={() => onChange(arrayMove(value, index, index + 1))} aria-label="เลื่อนลง">
|
>
|
||||||
<ChevronDownIcon />
|
{(dragHandle) => (
|
||||||
</Button>
|
<Card size="sm">
|
||||||
<Button type="button" variant="ghost" size="icon-sm" onClick={() => onChange(value.filter((_, itemIndex) => itemIndex !== index))} aria-label={`ลบ ${item?.name ?? reference.key}`}>
|
<CardContent className="flex items-center gap-3">
|
||||||
<XIcon />
|
{item ? (
|
||||||
</Button>
|
<div className={cn("relative size-12 shrink-0 overflow-hidden rounded-md", rarityGradientClass(item.rarity))}>
|
||||||
</CardContent>
|
<Image src={item.imageUrl} alt="" fill className="object-contain" />
|
||||||
</Card>
|
</div>
|
||||||
);
|
) : null}
|
||||||
})}
|
<div className="min-w-0 flex-1">
|
||||||
</div>
|
<p className="truncate font-medium">{label}</p>
|
||||||
|
<p className="text-sm text-muted-foreground">{labels[reference.kind]}</p>
|
||||||
|
</div>
|
||||||
|
{dragHandle}
|
||||||
|
<Button type="button" variant="ghost" size="icon-sm" onClick={() => onChange(value.filter((_, itemIndex) => itemIndex !== index))} aria-label={`ลบ ${label}`}>
|
||||||
|
<XIcon />
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</SortableExtraItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
<Select value={kind} onValueChange={(next) => { setKind(next as ExtraCatalogItem["kind"]); setKey(""); }}>
|
<Select value={kind} onValueChange={(next) => { setKind(next as ExtraCatalogItem["kind"]); setKey(""); }}>
|
||||||
|
|||||||
@@ -318,7 +318,8 @@ function lunarisItemUrl(
|
|||||||
kind: "character" | "weapon" | "artifact",
|
kind: "character" | "weapon" | "artifact",
|
||||||
key: string,
|
key: string,
|
||||||
): string {
|
): string {
|
||||||
return `https://lunaris.moe/${kind}/${encodeURIComponent(key)}`;
|
const path = kind === "character" ? "char" : kind;
|
||||||
|
return `https://lunaris.moe/${path}/${encodeURIComponent(key)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function WeaponSection({ guide }: { guide: PublicGuide }) {
|
function WeaponSection({ guide }: { guide: PublicGuide }) {
|
||||||
|
|||||||
Reference in New Issue
Block a user