feat : big update
CI / Verify (push) Successful in 3m14s
CI / Build immutable images and deploy (push) Successful in 4m0s

This commit is contained in:
2026-10-01 18:37:15 +07:00 Unverified
parent c5037154cb
commit 0022625edb
76 changed files with 18671 additions and 29 deletions
+5
View File
@@ -9,6 +9,7 @@ import {
LayoutDashboardIcon,
BookOpenIcon,
ClipboardListIcon,
MessagesSquareIcon,
LogOutIcon,
PlusIcon,
UserPlusIcon,
@@ -33,6 +34,10 @@ export function AdminHeader() {
<span className="hidden sm:inline">ไกด์เกนชินไม่ใช่เกมมือถือ</span>
</Link>
<nav aria-label="Admin navigation" className="flex items-center gap-1">
<Button variant={pathname.startsWith("/admin/commission") ? "secondary" : "ghost"}
size="sm" nativeButton={false} render={<Link href="/admin/commission" />}>
<MessagesSquareIcon data-icon="inline-start" /><span className="hidden sm:inline">Commission</span>
</Button>
<Button
variant={pathname === "/admin/stygian" ? "secondary" : "ghost"}
size="sm"
+1 -1
View File
@@ -17,7 +17,7 @@ export function EditorPresence({ guideId, section }: { guideId: string; section:
{editors.map((editor) => (
<Badge key={editor.userId} variant="outline">
{editor.name}
{editor.sections.length ? ` · ${editor.sections.join(", ")}` : ""}
{editor.sections.length ? ` - ${editor.sections.join(", ")}` : ""}
</Badge>
))}
</div>
+2 -2
View File
@@ -414,7 +414,7 @@ export function GuideOverviewForm({
<div className="flex items-center justify-between gap-2">
<div>
<FieldLabel>YouTube videos</FieldLabel>
<FieldDescription>ไม่บังคับ รองรับ YouTube, youtu.be, Shorts และ Live · ลากเพื่อจัดลำดับ</FieldDescription>
<FieldDescription>ไม่บังคับ รองรับ YouTube, youtu.be, Shorts และ Live - ลากเพื่อจัดลำดับ</FieldDescription>
</div>
<Button type="button" variant="outline" size="sm" disabled={youtubeLinks.length >= 20} onClick={() => setYoutubeLinks((current) => [...current, { id: createVideoLinkId(), url: "" }])}>
<PlusIcon data-icon="inline-start" />
@@ -472,7 +472,7 @@ export function GuideOverviewForm({
<div className="flex items-center justify-between gap-2">
<div>
<FieldLabel>Bleeding layers</FieldLabel>
<p className="text-xs text-muted-foreground">ใช้ภาพตัวละครเดียวกันด้วย mix-blend-mode · รายการบนสุดจะแสดงก่อน</p>
<p className="text-xs text-muted-foreground">ใช้ภาพตัวละครเดียวกันด้วย mix-blend-mode - รายการบนสุดจะแสดงก่อน</p>
</div>
<Button type="button" variant="outline" size="sm" disabled={!posterArt.id || !posterArt.url} onClick={addBleedingEffect}>เพิ่ม effect</Button>
</div>
+1 -1
View File
@@ -233,7 +233,7 @@ export function StructuredDashboard({
{(presence?.editorsByGuide[guide.id] ?? []).map((editor) => (
<Badge key={editor.userId} variant="outline">
{editor.name}
{editor.sections.length ? ` · ${editor.sections.join(", ")}` : ""}
{editor.sections.length ? ` - ${editor.sections.join(", ")}` : ""}
</Badge>
))}
</div>
+8 -2
View File
@@ -57,6 +57,8 @@ type CatalogDropdownProps<Item extends AdminCatalogItem> = CommonSelectProps<Ite
value: string;
onValueChange: (value: string) => void;
showSelectedImage?: boolean;
showClear?: boolean;
label?: string;
};
export function CatalogDropdown<Item extends AdminCatalogItem>({
@@ -68,6 +70,8 @@ export function CatalogDropdown<Item extends AdminCatalogItem>({
invalid = false,
rarityBackground = false,
showSelectedImage = false,
showClear = true,
label,
searchNames = (item) => [item.name, ...(item.aliases ?? [])],
}: CatalogDropdownProps<Item>) {
const selected = items.find((item) => item.key === value) ?? null;
@@ -97,7 +101,8 @@ export function CatalogDropdown<Item extends AdminCatalogItem>({
<ComboboxInput
className="w-full"
placeholder={placeholder}
showClear
aria-label={label ?? placeholder}
showClear={showClear}
aria-invalid={invalid}
/>
<ComboboxContent className="min-w-72">
@@ -186,6 +191,7 @@ type DomainSelectProps<Item extends AdminCatalogItem> = CommonSelectProps<Item>
label?: string;
className?: string;
showSelectedImage?: boolean;
showClear?: boolean;
};
function DomainCatalogSelect<Item extends AdminCatalogItem>({
@@ -206,7 +212,7 @@ function DomainCatalogSelect<Item extends AdminCatalogItem>({
/>
);
}
return <CatalogDropdown {...props} rarityBackground={rarityBackground} showSelectedImage={showSelectedImage} />;
return <CatalogDropdown {...props} label={label} rarityBackground={rarityBackground} showSelectedImage={showSelectedImage} />;
}
export function CharacterSelect<Item extends AdminCatalogItem>(props: DomainSelectProps<Item>) {