feat : update
CI / Verify (push) Successful in 1m6s
CI / Build immutable images and deploy (push) Successful in 2m16s

This commit is contained in:
2026-08-30 08:10:00 +00:00 Unverified
parent cba621a29b
commit ceaeba72c6
6 changed files with 12 additions and 8 deletions
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+2 -2
View File
@@ -20,8 +20,8 @@ const geistMono = Geist_Mono({
export const metadata: Metadata = {
title: {
default: "Buzz Sheet — คู่มือเกม",
template: "%s | Buzz Sheet",
default: "Buzz Guide",
template: "%s",
},
description: "คู่มือตัวละคร บิลด์ ทีม และโรเทชันที่อ่านง่ายในทุกหน้าจอ",
};
+4 -4
View File
@@ -30,10 +30,10 @@ export function CreateGuideFlow({ characters, existingKeys }: { characters: Char
if (selected) {
return (
<Card className="mx-auto max-w-2xl">
<Card className="mx-auto w-full max-w-4xl">
<CardHeader>
<CardTitle>ตั้งค่า Guide ของ {selected.name}</CardTitle>
<CardDescription>เพิ่มภาพหน้าปกและ Overview ก่อนสร้าง Guide สาธารณะ</CardDescription>
<CardDescription>เพิ่มภาพหน้าปก และใส่ Overview ได้หากต้องการ</CardDescription>
</CardHeader>
<CardContent>
<FieldGroup>
@@ -47,7 +47,7 @@ export function CreateGuideFlow({ characters, existingKeys }: { characters: Char
<MediaUploader onReady={setCover} />
</Field>
<Field>
<FieldLabel htmlFor="overview">Overview</FieldLabel>
<FieldLabel htmlFor="overview">Overview (optional)</FieldLabel>
<Textarea id="overview" value={overview} maxLength={500} onChange={(event) => setOverview(event.target.value)} placeholder="สรุปแนวทางเล่น จุดเด่น และสิ่งที่ผู้ชมจะพบใน Guide นี้" />
<FieldDescription>{overview.length}/500 ตัวอักษร</FieldDescription>
</Field>
@@ -55,7 +55,7 @@ export function CreateGuideFlow({ characters, existingKeys }: { characters: Char
</CardContent>
<CardFooter className="justify-between">
<Button type="button" variant="outline" onClick={() => setSelected(null)}><ArrowLeftIcon data-icon="inline-start" />เลือกใหม่</Button>
<Button disabled={pending || !cover || !overview.trim()} onClick={() => startTransition(async () => {
<Button disabled={pending || !cover} onClick={() => startTransition(async () => {
const result = await createStructuredGuide({ characterKey: selected.key, coverMediaId: cover?.id, overview });
if (result.status === "error") { toast.error(result.message); return; }
toast.success("สร้าง Guide แล้ว");
+5 -1
View File
@@ -1,9 +1,13 @@
import { describe, expect, it } from "vitest";
import { calculateTeamMetrics } from "@/lib/guides/calculations";
import { artifactSectionSchema, teamSectionSchema, weaponSectionSchema } from "@/lib/guides/schemas";
import { artifactSectionSchema, createGuideSchema, teamSectionSchema, weaponSectionSchema } from "@/lib/guides/schemas";
describe("structured guide validation", () => {
it("allows creating a guide without an overview", () => {
expect(createGuideSchema.safeParse({ characterKey: "1", coverMediaId: "550e8400-e29b-41d4-a716-446655440000", overview: "" }).success).toBe(true);
});
it("requires at least one weapon percentage", () => {
expect(weaponSectionSchema.safeParse({ expectedVersion: 1, rows: [{ weaponKey: "1", refinement: 5, overallPercent: null, personalPercent: null }] }).success).toBe(false);
expect(weaponSectionSchema.safeParse({ expectedVersion: 1, rows: [{ weaponKey: "1", refinement: 5, overallPercent: 104, personalPercent: null }] }).success).toBe(true);
+1 -1
View File
@@ -9,7 +9,7 @@ const catalogKey = z.string().trim().min(1).max(64);
export const createGuideSchema = z.strictObject({
characterKey: catalogKey,
coverMediaId: z.string().uuid(),
overview: z.string().trim().min(1).max(500),
overview: z.string().trim().max(500),
});
export const updateGuideSchema = z.strictObject({
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB