feat: multi-popular toggle for pricing, BYN price field for master classes

- Replace single popular dropdown with per-item toggle switch in pricing admin
- Add PriceField component to master classes admin (strips/adds BYN suffix)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 20:03:41 +03:00
parent f5e80c792a
commit 340a1d2f7f
2 changed files with 76 additions and 49 deletions

View File

@@ -63,45 +63,28 @@ export default function PricingEditorPage() {
onChange={(v) => update({ ...data, subtitle: v })}
/>
{/* Popular & Featured selectors */}
{/* Featured selector */}
{(() => {
const itemOptions = data.items
.map((it, idx) => ({ value: String(idx), label: it.name }))
.filter((o) => o.label.trim() !== "");
const noneOption = { value: "", label: "— Нет —" };
const popularIdx = data.items.findIndex((it) => it.popular);
const featuredIdx = data.items.findIndex((it) => it.featured);
return (
<div className="grid gap-3 sm:grid-cols-2">
<SelectField
label="Популярный абонемент"
value={popularIdx >= 0 ? String(popularIdx) : ""}
onChange={(v) => {
const items = data.items.map((it, idx) => ({
...it,
popular: v ? idx === Number(v) : false,
}));
update({ ...data, items });
}}
options={[noneOption, ...itemOptions]}
placeholder="Выберите..."
/>
<SelectField
label="Выделенный абонемент (безлимит)"
value={featuredIdx >= 0 ? String(featuredIdx) : ""}
onChange={(v) => {
const items = data.items.map((it, idx) => ({
...it,
featured: v ? idx === Number(v) : false,
}));
update({ ...data, items });
}}
options={[noneOption, ...itemOptions]}
placeholder="Выберите..."
/>
</div>
<SelectField
label="Выделенный абонемент (безлимит)"
value={featuredIdx >= 0 ? String(featuredIdx) : ""}
onChange={(v) => {
const items = data.items.map((it, idx) => ({
...it,
featured: v ? idx === Number(v) : false,
}));
update({ ...data, items });
}}
options={[noneOption, ...itemOptions]}
placeholder="Выберите..."
/>
);
})()}
@@ -110,22 +93,42 @@ export default function PricingEditorPage() {
items={data.items}
onChange={(items) => update({ ...data, items })}
renderItem={(item, _i, updateItem) => (
<div className="grid gap-3 sm:grid-cols-3">
<InputField
label="Название"
value={item.name}
onChange={(v) => updateItem({ ...item, name: v })}
/>
<PriceField
label="Цена"
value={item.price}
onChange={(v) => updateItem({ ...item, price: v })}
/>
<InputField
label="Примечание"
value={item.note || ""}
onChange={(v) => updateItem({ ...item, note: v })}
/>
<div className="space-y-3">
<div className="grid gap-3 sm:grid-cols-3">
<InputField
label="Название"
value={item.name}
onChange={(v) => updateItem({ ...item, name: v })}
/>
<PriceField
label="Цена"
value={item.price}
onChange={(v) => updateItem({ ...item, price: v })}
/>
<InputField
label="Примечание"
value={item.note || ""}
onChange={(v) => updateItem({ ...item, note: v })}
/>
</div>
<label className="inline-flex items-center gap-2 cursor-pointer select-none">
<button
type="button"
role="switch"
aria-checked={!!item.popular}
onClick={() => updateItem({ ...item, popular: !item.popular })}
className={`relative h-5 w-9 rounded-full transition-colors ${
item.popular ? "bg-gold" : "bg-neutral-600"
}`}
>
<span
className={`absolute top-0.5 left-0.5 h-4 w-4 rounded-full bg-white transition-transform ${
item.popular ? "translate-x-4" : ""
}`}
/>
</button>
<span className="text-sm text-neutral-400">Популярный</span>
</label>
</div>
)}
createItem={() => ({ name: "", price: "", note: "" })}