feat(guide) : improve extra cards and navigation
CI / Verify (push) Successful in 1m25s
CI / Build immutable images and deploy (push) Failing after 50s

This commit is contained in:
2026-09-04 22:40:27 +07:00 Unverified
parent 5f74ce1de6
commit ced9b41737
16 changed files with 3780 additions and 224 deletions
+210 -89
View File
@@ -260,7 +260,7 @@ type TeamValue = {
let clientIdCounter = 0;
const DEFAULT_EXTRA_BACKGROUND_COLOR = "#24232C";
const DEFAULT_EXTRA_TEXT_COLOR = "#F5F2EA";
const DEFAULT_EXTRA_HIGHLIGHT_COLOR = "#FF3B30";
function createClientId(prefix: string): string {
const browserCrypto = globalThis.crypto;
@@ -314,7 +314,7 @@ export interface GuideSectionEditorProps {
body: string;
percent: string | null;
backgroundColor: string | null;
textColor: string | null;
highlights: Array<{ text: string; color: string }>;
imageUrl: string | null;
imageWidth: number | null;
imageHeight: number | null;
@@ -3324,7 +3324,7 @@ function ExtraEditor({ guide, initial }: EditorBase) {
? null
: Number(row.percent),
backgroundColor: row.backgroundColor,
textColor: row.textColor,
highlights: row.highlights.map(({ text, color }) => ({ text, color })),
})),
})),
};
@@ -3354,7 +3354,7 @@ function ExtraEditor({ guide, initial }: EditorBase) {
...row,
id: row.id || createClientId("extra-row-record"),
backgroundColor: row.backgroundColor ?? null,
textColor: row.textColor ?? null,
highlights: row.highlights ?? [],
clientId: row.clientId || createClientId("extra-row"),
})),
})),
@@ -3701,101 +3701,53 @@ function ExtraEditor({ guide, initial }: EditorBase) {
/>
</Field>
<FieldSet>
<FieldLegend>สีการ์ด (optional)</FieldLegend>
<FieldLegend>สีพื้นหลังการ์ด (optional)</FieldLegend>
<FieldDescription>
สีจะใช้เฉพาะการ์ดนี้บนหน้า Guide
</FieldDescription>
<FieldGroup className="sm:grid sm:grid-cols-2">
<Field
data-invalid={extraIssue(
<Field
data-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"backgroundColor",
) || undefined}
>
<FieldLabel>สีพื้นหลัง</FieldLabel>
<Input
type="color"
value={row.backgroundColor ?? DEFAULT_EXTRA_BACKGROUND_COLOR}
aria-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"backgroundColor",
) || undefined}
>
<FieldLabel>สีพื้นหลัง</FieldLabel>
<Input
type="color"
value={row.backgroundColor ?? DEFAULT_EXTRA_BACKGROUND_COLOR}
aria-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"backgroundColor",
)}
onChange={(event) =>
setSections(
sections.map((item, index) =>
index === sectionIndex
? {
...item,
rows: item.rows.map((candidate, inner) =>
inner === rowIndex
? {
...candidate,
backgroundColor: event.target.value,
textColor: candidate.textColor ?? DEFAULT_EXTRA_TEXT_COLOR,
}
: candidate,
),
}
: item,
),
)
}
/>
</Field>
<Field
data-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"textColor",
) || undefined}
>
<FieldLabel>สีข้อความ</FieldLabel>
<Input
type="color"
value={row.textColor ?? DEFAULT_EXTRA_TEXT_COLOR}
aria-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"textColor",
)}
onChange={(event) =>
setSections(
sections.map((item, index) =>
index === sectionIndex
? {
...item,
rows: item.rows.map((candidate, inner) =>
inner === rowIndex
? {
...candidate,
backgroundColor: candidate.backgroundColor ?? DEFAULT_EXTRA_BACKGROUND_COLOR,
textColor: event.target.value,
}
: candidate,
),
}
: item,
),
)
}
/>
</Field>
</FieldGroup>
)}
onChange={(event) =>
setSections(
sections.map((item, index) =>
index === sectionIndex
? {
...item,
rows: item.rows.map((candidate, inner) =>
inner === rowIndex
? { ...candidate, backgroundColor: event.target.value }
: candidate,
),
}
: item,
),
)
}
/>
</Field>
<Button
type="button"
variant="outline"
size="sm"
disabled={row.backgroundColor === null && row.textColor === null}
disabled={row.backgroundColor === null}
onClick={() =>
setSections(
sections.map((item, index) =>
@@ -3804,7 +3756,7 @@ function ExtraEditor({ guide, initial }: EditorBase) {
...item,
rows: item.rows.map((candidate, inner) =>
inner === rowIndex
? { ...candidate, backgroundColor: null, textColor: null }
? { ...candidate, backgroundColor: null }
: candidate,
),
}
@@ -3817,6 +3769,175 @@ function ExtraEditor({ guide, initial }: EditorBase) {
ใช้สีตามธีม
</Button>
</FieldSet>
<FieldSet>
<FieldLegend>ไฮไลต์คำหรือวลี</FieldLegend>
<FieldDescription>
ระบุข้อความให้ตรงกับเนื้อหา ระบบจะเปลี่ยนสีทุกตำแหน่งที่พบ
</FieldDescription>
{row.highlights.map((highlight, highlightIndex) => (
<FieldGroup
key={highlightIndex}
className="sm:grid sm:grid-cols-[1fr_auto_auto] sm:items-end"
>
<Field
data-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"highlights",
highlightIndex,
"text",
) || undefined}
>
<FieldLabel>คำหรือวลี</FieldLabel>
<Input
value={highlight.text}
placeholder="MASSIVE"
aria-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"highlights",
highlightIndex,
"text",
)}
onChange={(event) =>
setSections(
sections.map((item, index) =>
index === sectionIndex
? {
...item,
rows: item.rows.map((candidate, inner) =>
inner === rowIndex
? {
...candidate,
highlights: candidate.highlights.map((rule, ruleIndex) =>
ruleIndex === highlightIndex
? { ...rule, text: event.target.value }
: rule,
),
}
: candidate,
),
}
: item,
),
)
}
/>
</Field>
<Field
data-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"highlights",
highlightIndex,
"color",
) || undefined}
>
<FieldLabel>สี</FieldLabel>
<Input
type="color"
value={highlight.color}
aria-invalid={extraIssue(
"sections",
sectionIndex,
"rows",
rowIndex,
"highlights",
highlightIndex,
"color",
)}
onChange={(event) =>
setSections(
sections.map((item, index) =>
index === sectionIndex
? {
...item,
rows: item.rows.map((candidate, inner) =>
inner === rowIndex
? {
...candidate,
highlights: candidate.highlights.map((rule, ruleIndex) =>
ruleIndex === highlightIndex
? { ...rule, color: event.target.value }
: rule,
),
}
: candidate,
),
}
: item,
),
)
}
/>
</Field>
<Button
type="button"
variant="ghost"
size="icon-sm"
aria-label={`ลบไฮไลต์ ${highlight.text || highlightIndex + 1}`}
onClick={() =>
setSections(
sections.map((item, index) =>
index === sectionIndex
? {
...item,
rows: item.rows.map((candidate, inner) =>
inner === rowIndex
? {
...candidate,
highlights: candidate.highlights.filter((_, ruleIndex) => ruleIndex !== highlightIndex),
}
: candidate,
),
}
: item,
),
)
}
>
<Trash2Icon />
</Button>
</FieldGroup>
))}
<Button
type="button"
variant="outline"
size="sm"
disabled={row.highlights.length >= 20}
onClick={() =>
setSections(
sections.map((item, index) =>
index === sectionIndex
? {
...item,
rows: item.rows.map((candidate, inner) =>
inner === rowIndex
? {
...candidate,
highlights: [
...candidate.highlights,
{ text: "", color: DEFAULT_EXTRA_HIGHLIGHT_COLOR },
],
}
: candidate,
),
}
: item,
),
)
}
>
<PlusIcon data-icon="inline-start" />
เพิ่มคำไฮไลต์
</Button>
</FieldSet>
</FieldGroup>
</CardContent>
</Card>
@@ -3846,7 +3967,7 @@ function ExtraEditor({ guide, initial }: EditorBase) {
body: "",
percent: null,
backgroundColor: null,
textColor: null,
highlights: [],
clientId: createClientId("extra-row"),
},
],