feat(guides) : add selectable target and team conditions
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import { Children, type ReactNode, useState } from "react";
|
||||
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||
|
||||
export function ConditionSwitcher({ children, label = "เลือก Condition" }: { children: ReactNode; label?: string }) {
|
||||
const items = Children.toArray(children);
|
||||
const [active, setActive] = useState("0");
|
||||
|
||||
if (items.length <= 1) return items[0] ?? null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<ToggleGroup aria-label={label} variant="outline" value={[active]} onValueChange={(values) => {
|
||||
if (values[0]) setActive(values[0]);
|
||||
}}>
|
||||
{items.map((_, index) => <ToggleGroupItem key={index} value={String(index)}>Condition {index + 1}</ToggleGroupItem>)}
|
||||
</ToggleGroup>
|
||||
{items[Number(active)]}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import { TeamArtifactIcon, TeamSearch } from "@/components/public/team-search";
|
||||
import { GuideImageExport } from "@/components/public/guide-image-export";
|
||||
import { GuideExportBranding } from "@/components/public/guide-export-branding";
|
||||
import { ConstellationImage } from "@/components/public/constellation-image";
|
||||
import { ConditionSwitcher } from "@/components/public/condition-switcher";
|
||||
import { MaterialPoster } from "@/components/public/material-poster";
|
||||
import { RichTextContent } from "@/components/rich-text-content";
|
||||
import { LiveRefresh } from "@/components/live-refresh";
|
||||
@@ -62,7 +63,10 @@ function hasSection(guide: PublicGuide, slug: string): boolean {
|
||||
guide.artifactProfile &&
|
||||
(guide.artifactProfile.sands.length ||
|
||||
guide.artifactProfile.goblet.length ||
|
||||
guide.artifactProfile.circlet.length),
|
||||
guide.artifactProfile.circlet.length ||
|
||||
guide.artifactProfile.substats.length ||
|
||||
guide.artifactProfile.targetConditions.some((group) => group.rows.length) ||
|
||||
guide.artifactProfile.talents.length),
|
||||
)
|
||||
);
|
||||
if (slug === "constellations") return guide.constellationGroups.some((group) => group.rows.length > 0);
|
||||
@@ -432,6 +436,7 @@ function WeaponSectionContent({
|
||||
) : null}
|
||||
</div>
|
||||
</header>
|
||||
<ConditionSwitcher label="เลือกเงื่อนไขอาวุธ">
|
||||
{weaponGroups.map((group, groupIndex, groups) => (
|
||||
<div key={group.id} className="relative z-10 flex flex-col gap-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
@@ -596,6 +601,7 @@ function WeaponSectionContent({
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</ConditionSwitcher>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -778,11 +784,14 @@ function ArtifactSectionContent({
|
||||
<CardHeader>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-5">
|
||||
{profile.targets.length ? (
|
||||
<div>
|
||||
{profile.targetConditions.some((group) => group.rows.length) ? (
|
||||
<ConditionSwitcher label="เลือกเงื่อนไขค่าสถานะเป้าหมาย">
|
||||
{profile.targetConditions.filter((group) => group.rows.length).map((group, groupIndex) => (
|
||||
<div key={groupIndex}>
|
||||
<p className="mb-2 text-sm font-medium">ค่าสถานะต่ำๆที่ควรจะปั้นไว้</p>
|
||||
{group.note ? <p className="mb-2 whitespace-pre-wrap text-sm text-muted-foreground">{group.note}</p> : null}
|
||||
<div className="flex flex-col gap-1">
|
||||
{profile.targets.map((target, index) => (
|
||||
{group.rows.map((target, index) => (
|
||||
<div
|
||||
key={`${target.stat}-${target.value}`}
|
||||
className={cn(
|
||||
@@ -812,6 +821,8 @@ function ArtifactSectionContent({
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</ConditionSwitcher>
|
||||
) : null}
|
||||
{profile.talents.length ? (
|
||||
<div>
|
||||
@@ -1137,7 +1148,7 @@ function TeamSection({ guide }: { guide: PublicGuide }) {
|
||||
<p className="text-sm font-medium text-primary">คำนวณความเสียหาย</p>
|
||||
<h1 className="font-heading text-4xl font-semibold">คำนวณทีม</h1>
|
||||
</header>
|
||||
<TeamSearch teams={guide.teams} />
|
||||
<TeamSearch groups={guide.teamGroups} />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -360,7 +360,10 @@ function TeamCard({
|
||||
);
|
||||
}
|
||||
|
||||
export function TeamSearch({ teams }: { teams: PublicGuide["teams"] }) {
|
||||
export function TeamSearch({ groups }: { groups: PublicGuide["teamGroups"] }) {
|
||||
const [activeCondition, setActiveCondition] = useState("0");
|
||||
const activeGroup = groups[Number(activeCondition)] ?? groups[0];
|
||||
const teams = useMemo(() => activeGroup?.teams ?? [], [activeGroup]);
|
||||
const [query, setQuery] = useState("");
|
||||
const [searchTarget, setSearchTarget] = useState<TeamSearchTarget>("all");
|
||||
const [dpsOrder, setDpsOrder] = useState<DpsOrder>(null);
|
||||
@@ -376,6 +379,14 @@ export function TeamSearch({ teams }: { teams: PublicGuide["teams"] }) {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{groups.length > 1 ? (
|
||||
<ToggleGroup aria-label="เลือกเงื่อนไขทีม" variant="outline" value={[activeCondition]} onValueChange={(values) => {
|
||||
if (values[0]) setActiveCondition(values[0]);
|
||||
}}>
|
||||
{groups.map((group, index) => <ToggleGroupItem key={group.id} value={String(index)}>Condition {index + 1}</ToggleGroupItem>)}
|
||||
</ToggleGroup>
|
||||
) : null}
|
||||
{activeGroup?.note ? <p className="whitespace-pre-wrap text-muted-foreground">{activeGroup.note}</p> : null}
|
||||
<div className="relative">
|
||||
<SearchIcon aria-hidden="true" className="pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input
|
||||
|
||||
Reference in New Issue
Block a user