diff --git a/apps/miniapp/src/routes/settings.tsx b/apps/miniapp/src/routes/settings.tsx index 4e54ff9..d05d24b 100644 --- a/apps/miniapp/src/routes/settings.tsx +++ b/apps/miniapp/src/routes/settings.tsx @@ -20,7 +20,9 @@ import { updateMiniAppMemberStatus, promoteMiniAppMember, approveMiniAppPendingMember, - rejectMiniAppPendingMember + rejectMiniAppPendingMember, + upsertMiniAppUtilityCategory, + type MiniAppUtilityCategory } from '../miniapp-api' import { minorToMajorString } from '../lib/money' @@ -48,6 +50,16 @@ export default function SettingsRoute() { // ── Profile settings ───────────────────────────── const [profileEditorOpen, setProfileEditorOpen] = createSignal(false) + // ── Utility categories ─────────────────────────── + const [categoryEditorOpen, setCategoryEditorOpen] = createSignal(false) + const [editingCategorySlug, setEditingCategorySlug] = createSignal(null) + const [savingCategory, setSavingCategory] = createSignal(false) + const [categoryForm, setCategoryForm] = createSignal({ + name: '', + sortOrder: 0, + isActive: true + }) + // ── Billing settings form ──────────────────────── const [billingEditorOpen, setBillingEditorOpen] = createSignal(false) const [savingSettings, setSavingSettings] = createSignal(false) @@ -142,6 +154,60 @@ export default function SettingsRoute() { } } + // ── Utility Category Editing ───────────────────── + function openAddCategory() { + setEditingCategorySlug(null) + setCategoryForm({ + name: '', + sortOrder: adminSettings()?.categories.length ?? 0, + isActive: true + }) + setCategoryEditorOpen(true) + } + + function openEditCategory(category: MiniAppUtilityCategory) { + setEditingCategorySlug(category.slug) + setCategoryForm({ + name: category.name, + sortOrder: category.sortOrder, + isActive: category.isActive + }) + setCategoryEditorOpen(true) + } + + async function handleSaveCategory() { + const data = initData() + if (!data) return + + setSavingCategory(true) + try { + const form = categoryForm() + const slug = editingCategorySlug() + const category = await upsertMiniAppUtilityCategory(data, { + ...(slug ? { slug } : {}), + name: form.name, + sortOrder: form.sortOrder, + isActive: form.isActive + }) + + // Update local state + setAdminSettings((prev) => { + if (!prev) return prev + const existing = prev.categories.find((c) => c.slug === category.slug) + if (existing) { + return { + ...prev, + categories: prev.categories.map((c) => (c.slug === category.slug ? category : c)) + } + } + return { ...prev, categories: [...prev.categories, category] } + }) + setCategoryEditorOpen(false) + } finally { + setSavingCategory(false) + } + } + // ── Member Editing ────────────────────────────── const [editMemberId, setEditMemberId] = createSignal(null) const [savingMember, setSavingMember] = createSignal(false) @@ -447,6 +513,40 @@ export default function SettingsRoute() { )} + + {/* Utility Categories */} + + {copy().utilityCategoriesBody}

} + > + {(categories) => ( +
+ + {(category) => ( + +
openEditCategory(category)} + > +
+ {category.name} + + {category.isActive ? copy().onLabel : copy().offLabel} + +
+
+
+ )} +
+ +
+ )} +
+
{/* ── Billing Settings Editor Modal ────────────── */} @@ -862,6 +962,50 @@ export default function SettingsRoute() { + + {/* ── Category Editor Modal ────────────── */} + setCategoryEditorOpen(false)} + footer={ + + } + > +
+ + setCategoryForm((f) => ({ ...f, name: e.currentTarget.value }))} + /> + + +