feat(251): filter plan dropdown by billing type, hide archived plans

This commit is contained in:
2026-04-01 07:54:27 +00:00
parent 10531338d0
commit 95bbb198b5

View File

@@ -53,11 +53,21 @@ export default function ClientsPage() {
queryFn: async () => { const r = await api.get<Area[]>("/api/v1/areas"); return r.data; }, queryFn: async () => { const r = await api.get<Area[]>("/api/v1/areas"); return r.data; },
}); });
const { data: plans = [] } = useQuery<Plan[]>({ // Fetch only active plans, filter client-side by billing type
queryKey: ["plans"], const { data: allActivePlans = [] } = useQuery<(Plan & { type: string; isActive: boolean })[]>({
queryFn: async () => { const r = await api.get<Plan[]>("/api/v1/plans"); return Array.isArray(r.data) ? r.data : (r.data as any).data ?? []; }, queryKey: ["plans", "active"],
queryFn: async () => {
const r = await api.get("/api/v1/plans?isActive=true");
const raw = Array.isArray(r.data) ? r.data : (r.data as any).data ?? [];
return raw;
},
}); });
// Filter plans by selected billing type
const filteredPlans = allActivePlans.filter(p =>
!form.billingType || p.type === form.billingType
);
const createClient = useMutation({ const createClient = useMutation({
mutationFn: async () => { mutationFn: async () => {
const res = await api.post("/api/v1/clients", { const res = await api.post("/api/v1/clients", {
@@ -186,10 +196,11 @@ export default function ClientsPage() {
<div className="flex flex-col gap-1.5"> <div className="flex flex-col gap-1.5">
<label className="text-sm font-medium text-gray-700">Billing Type</label> <label className="text-sm font-medium text-gray-700">Billing Type</label>
<select className="border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" <select className="border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
value={form.billingType} onChange={e => setForm(f => ({ ...f, billingType: e.target.value }))}> value={form.billingType} onChange={e => setForm(f => ({ ...f, billingType: e.target.value, planId: "" }))}>
<option value="POSTPAID">Postpaid</option> <option value="POSTPAID">Postpaid</option>
<option value="PREPAID">Prepaid</option> <option value="PREPAID">Prepaid</option>
</select> </select>
<p className="text-xs text-gray-400">Plan list filters to match this type</p>
</div> </div>
</div> </div>
<div className="flex flex-col gap-1.5"> <div className="flex flex-col gap-1.5">
@@ -197,8 +208,11 @@ export default function ClientsPage() {
<select className="border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" <select className="border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
value={form.planId} onChange={e => setForm(f => ({ ...f, planId: e.target.value }))}> value={form.planId} onChange={e => setForm(f => ({ ...f, planId: e.target.value }))}>
<option value=""> Select plan </option> <option value=""> Select plan </option>
{plans.map(p => <option key={p.id} value={p.id}>{p.name} {Number(p.monthlyPrice).toLocaleString()}/mo</option>)} {filteredPlans.map(p => <option key={p.id} value={p.id}>{p.name} {Number(p.monthlyPrice).toLocaleString()}/mo</option>)}
</select> </select>
{filteredPlans.length === 0 && form.billingType && (
<p className="text-xs text-amber-600">No active {form.billingType.toLowerCase()} plans available.</p>
)}
</div> </div>
<div className="flex justify-end gap-2 pt-2"> <div className="flex justify-end gap-2 pt-2">
<Button variant="outline" onClick={() => setShowAdd(false)}>Cancel</Button> <Button variant="outline" onClick={() => setShowAdd(false)}>Cancel</Button>