feat(settings): add edit plan modal — name/type/speed/price inline edit (M9.4)
This commit is contained in:
@@ -399,6 +399,8 @@ function PlansSettings() {
|
||||
const [speedUp, setSpeedUp] = useState("");
|
||||
const [price, setPrice] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [editPlan, setEditPlan] = useState<Plan | null>(null);
|
||||
const [editForm, setEditForm] = useState({ name: "", type: "POSTPAID", speedDown: "", speedUp: "", price: "", description: "" });
|
||||
|
||||
const { data, isLoading, refetch } = useQuery<Plan[]>({
|
||||
queryKey: ["plans"],
|
||||
@@ -444,6 +446,38 @@ function PlansSettings() {
|
||||
onError: () => toast.error("Failed to update plan"),
|
||||
});
|
||||
|
||||
const editPlanMutation = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (!editPlan) return;
|
||||
await api.patch(`/api/v1/plans/${editPlan.id}`, {
|
||||
name: editForm.name,
|
||||
type: editForm.type,
|
||||
speedDownMbps: parseInt(editForm.speedDown),
|
||||
speedUpMbps: parseInt(editForm.speedUp),
|
||||
monthlyPrice: parseFloat(editForm.price),
|
||||
description: editForm.description || undefined,
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Plan updated");
|
||||
setEditPlan(null);
|
||||
refetch();
|
||||
},
|
||||
onError: () => toast.error("Failed to update plan"),
|
||||
});
|
||||
|
||||
function openEdit(p: Plan) {
|
||||
setEditPlan(p);
|
||||
setEditForm({
|
||||
name: p.name,
|
||||
type: p.type,
|
||||
speedDown: String(p.speedDownMbps),
|
||||
speedUp: String(p.speedUpMbps),
|
||||
price: String(Number(p.monthlyPrice)),
|
||||
description: p.description ?? "",
|
||||
});
|
||||
}
|
||||
|
||||
function resetAdd() {
|
||||
setPlanName(""); setPlanType("POSTPAID");
|
||||
setSpeedDown(""); setSpeedUp(""); setPrice(""); setDescription("");
|
||||
@@ -498,13 +532,22 @@ function PlansSettings() {
|
||||
</Badge>
|
||||
</Td>
|
||||
<Td>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => toggleActiveMutation.mutate({ id: p.id, isActive: p.isActive })}
|
||||
>
|
||||
{p.isActive ? "Archive" : "Restore"}
|
||||
</Button>
|
||||
<div className="flex items-center gap-1">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => openEdit(p)}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => toggleActiveMutation.mutate({ id: p.id, isActive: p.isActive })}
|
||||
>
|
||||
{p.isActive ? "Archive" : "Restore"}
|
||||
</Button>
|
||||
</div>
|
||||
</Td>
|
||||
</TableRow>
|
||||
))
|
||||
@@ -514,6 +557,34 @@ function PlansSettings() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Edit Plan Modal */}
|
||||
<Modal isOpen={!!editPlan} onClose={() => setEditPlan(null)} title="Edit Plan" className="max-w-lg">
|
||||
<form onSubmit={(e) => { e.preventDefault(); editPlanMutation.mutate(); }} className="space-y-4">
|
||||
<Input label="Plan Name" value={editForm.name} onChange={(e) => setEditForm(f => ({ ...f, name: e.target.value }))} />
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="text-sm font-medium text-gray-700">Type</label>
|
||||
<select
|
||||
className="block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||
value={editForm.type}
|
||||
onChange={(e) => setEditForm(f => ({ ...f, type: e.target.value }))}
|
||||
>
|
||||
<option value="POSTPAID">Postpaid</option>
|
||||
<option value="PREPAID">Prepaid</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<Input label="Download (Mbps)" type="number" min="1" value={editForm.speedDown} onChange={(e) => setEditForm(f => ({ ...f, speedDown: e.target.value }))} />
|
||||
<Input label="Upload (Mbps)" type="number" min="1" value={editForm.speedUp} onChange={(e) => setEditForm(f => ({ ...f, speedUp: e.target.value }))} />
|
||||
</div>
|
||||
<Input label="Monthly Price (₱)" type="number" min="0" step="0.01" value={editForm.price} onChange={(e) => setEditForm(f => ({ ...f, price: e.target.value }))} />
|
||||
<Input label="Description (optional)" value={editForm.description} onChange={(e) => setEditForm(f => ({ ...f, description: e.target.value }))} />
|
||||
<div className="flex justify-end gap-2 pt-1">
|
||||
<Button type="button" variant="outline" size="sm" onClick={() => setEditPlan(null)}>Cancel</Button>
|
||||
<Button type="submit" size="sm" isLoading={editPlanMutation.isPending}>Save Changes</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Modal>
|
||||
|
||||
{/* Add Plan Modal */}
|
||||
<Modal isOpen={showAdd} onClose={() => { setShowAdd(false); resetAdd(); }} title="Add Plan" className="max-w-lg">
|
||||
<form onSubmit={(e) => { e.preventDefault(); addPlanMutation.mutate(); }} className="space-y-4">
|
||||
|
||||
Reference in New Issue
Block a user