feat(admin): Discounts and Website Settings sections

- /admin/discounts: list + create discount codes (kind, value, max uses, expiry)
  via /v1/discounts (backend has no edit/delete API yet)
- /admin/settings: key/value site settings with upsert + secret flag. The value
  column is jsonb, so values are JSON-encoded on save / decoded for display
- nav links + fa/en labels

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-02 15:20:07 +03:30
parent 163f0c9ec3
commit 9a1d60e9d0
7 changed files with 183 additions and 2 deletions
+34
View File
@@ -175,3 +175,37 @@ export const plansConfig: ResourceConfig = {
{ key: "is_active", label: "Active", render: (r) => badge(!!r.is_active, "active", "off") },
],
};
export const discountsConfig: ResourceConfig = {
title: "Discounts",
description: "Discount / coupon codes. (Codes are created here; the backend has no edit/delete API yet.)",
basePath: "discounts",
listKey: "data",
canCreate: true,
columns: [
{ key: "code", label: "Code" },
{ key: "kind", label: "Kind" },
{ key: "value", label: "Value" },
{ key: "used_count", label: "Used" },
{ key: "max_use_count", label: "Max uses" },
{ key: "is_active", label: "Active", render: (r) => badge(!!r.is_active, "active", "off") },
{ key: "expires_at", label: "Expires" },
],
fields: [
{ key: "name", label: "Name", required: true },
{ key: "code", label: "Code", required: true },
{
key: "kind", label: "Kind", type: "select", required: true,
options: [
{ value: "Percentage", label: "Percentage (%)" },
{ value: "FixedAmount", label: "Fixed amount" },
{ value: "FreeMonths", label: "Free months" },
{ value: "RenderCredits", label: "Render credits" },
],
defaultValue: "Percentage",
},
{ key: "value", label: "Value", type: "number", required: true },
{ key: "max_use_count", label: "Max use count (blank = unlimited)", type: "number" },
{ key: "expires_at", label: "Expires at (ISO date, optional)", placeholder: "2026-12-31T00:00:00Z" },
],
};