import { createResource, createSignal, Show, For } from 'solid-js'; import AdminShell from '~/components/AdminShell'; const API = '/api/gateway'; const ROLE_OPTIONS = [ 'company', 'customer', 'job_seeker', 'photographer', 'video_editor', 'graphic_designer', 'social_media_manager', 'fitness_trainer', 'catering_services', 'makeup_artist', 'tutor', 'developer', ]; type Coupon = { id: string; code: string; title: string; type: 'PERCENT' | 'FIXED'; value: number; min_order_amount: number; used_count: number; usage_limit?: number; is_active: boolean; role_keys: string[]; }; async function loadCoupons(): Promise { try { const res = await fetch(`${API}/api/admin/coupons`); if (!res.ok) throw new Error('Failed to load'); const data = await res.json(); return Array.isArray(data) ? data : (data.coupons || []); } catch { return []; } } const defaultForm = () => ({ id: '', code: '', title: '', type: 'PERCENT' as 'PERCENT' | 'FIXED', value: 10, min_order_amount: 0, max_uses: '', role_keys: ['company', 'customer'] as string[], }); export default function CouponPage() { const [coupons, { refetch }] = createResource(loadCoupons); const [activeTab, setActiveTab] = createSignal<'list' | 'create'>('list'); const [form, setForm] = createSignal(defaultForm()); const [saving, setSaving] = createSignal(false); const [toggling, setToggling] = createSignal(''); const [formError, setFormError] = createSignal(''); const resetForm = () => { setForm(defaultForm()); setFormError(''); }; const startEdit = (coupon: Coupon) => { setForm({ id: coupon.id, code: coupon.code, title: coupon.title || '', type: coupon.type, value: coupon.value, min_order_amount: coupon.min_order_amount || 0, max_uses: coupon.usage_limit != null ? String(coupon.usage_limit) : '', role_keys: Array.isArray(coupon.role_keys) ? coupon.role_keys : [], }); setActiveTab('create'); }; const toggleRole = (role: string) => { const current = form().role_keys; if (current.includes(role)) { setForm({ ...form(), role_keys: current.filter((r) => r !== role) }); } else { setForm({ ...form(), role_keys: [...current, role] }); } }; const handleSave = async (e: Event) => { e.preventDefault(); try { setSaving(true); setFormError(''); const f = form(); const body: Record = { code: f.code.toUpperCase(), title: f.title, type: f.type, value: Number(f.value), min_order_amount: Number(f.min_order_amount), role_keys: f.role_keys, }; if (f.max_uses) body.max_uses = Number(f.max_uses); const url = f.id ? `${API}/api/admin/coupons/${f.id}` : `${API}/api/admin/coupons`; const method = f.id ? 'PATCH' : 'POST'; const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); if (!res.ok) throw new Error('Failed to save coupon'); resetForm(); refetch(); setActiveTab('list'); } catch (err: unknown) { setFormError(err instanceof Error ? err.message : 'Failed to save'); } finally { setSaving(false); } }; const handleToggle = async (coupon: Coupon) => { try { setToggling(coupon.id); const res = await fetch(`${API}/api/admin/coupons/${coupon.id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ is_active: !coupon.is_active }), }); if (!res.ok) throw new Error('Failed to toggle'); refetch(); } catch { // ignore } finally { setToggling(''); } }; return (

Coupon Management

Reusable coupon codes for package checkout

{/* Tabs */}
0}> {(item) => ( )}
Code Title Type Value Max Uses Status Actions
Loading...
Failed to load. Is the backend running?
No coupons found.
{item.code} {item.title || '—'} {item.type} {item.type === 'PERCENT' ? `${item.value}%` : `₹${item.value}`} {item.usage_limit != null ? item.usage_limit : '—'} {item.is_active ? 'Active' : 'Inactive'}

{form().id ? 'Edit Coupon' : 'Create Coupon'}

{formError()}
setForm({ ...form(), code: e.currentTarget.value.toUpperCase() })} required placeholder="e.g. SAVE10" style="text-transform:uppercase" />
setForm({ ...form(), title: e.currentTarget.value })} required placeholder="e.g. 10% off for companies" />
setForm({ ...form(), value: Number(e.currentTarget.value) })} required min="1" />
setForm({ ...form(), min_order_amount: Number(e.currentTarget.value) })} min="0" placeholder="0" />
setForm({ ...form(), max_uses: e.currentTarget.value })} min="1" placeholder="Unlimited" />

Applicable Roles

{(role) => { const active = () => form().role_keys.includes(role); return ( ); }}
); }