Files
road-monitoring-ui/src/app/(modules)/plans/page.tsx

202 lines
5.1 KiB
TypeScript

'use client';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { BadgeIndianRupee, Plus } from 'lucide-react';
import { PageHeader } from '@/components/page-header';
import { Button } from '@/components/ui/button';
import { PERMISSIONS } from '@/constants/permissions';
import { PermissionGuard } from '@/guards';
import type { Plan } from '@/types';
import { usePlanColumns } from './components/PlanColumns';
import { PlanFilters } from './components/PlanFilters';
import { PlanSheet } from './components/PlanSheet';
import { PlanTable } from './components/PlanTable';
import { usePlanFilters } from './hooks/usePlanFilters';
import { usePlanForm } from './hooks/usePlanForm';
import { usePlanStatusMutation } from './hooks/usePlanMutations';
import {
useOrganizationPermissionTreeQuery,
usePlansQuery,
} from './hooks/usePlanQueries';
export default function PlansPage() {
const [isSheetOpen, setIsSheetOpen] = useState(false);
const pendingPlanRef = useRef<Plan | null>(null);
const hasSyncedPermissionsRef = useRef(false);
const {
skip,
setSkip,
limit,
setLimit,
sorting,
setSorting,
searchTerm,
debouncedSearchTerm,
setSearchTerm,
statusFilter,
setStatusFilter,
} = usePlanFilters();
const plansQuery = usePlansQuery({
skip,
limit,
searchTerm: debouncedSearchTerm,
statusFilter,
sorting,
});
const permissionsQuery = useOrganizationPermissionTreeQuery(isSheetOpen);
const handleSheetOpenChange = useCallback((open: boolean) => {
if (!open) {
pendingPlanRef.current = null;
}
setIsSheetOpen(open);
}, []);
const planForm = usePlanForm({
permissionTree: permissionsQuery.permissionTree,
onSaved: () => handleSheetOpenChange(false),
});
const { openCreate: prepareCreatePlan, openEdit: prepareEditPlan } = planForm;
const {
register,
control,
onSubmit,
planId,
permissionIds,
setPermissionIds,
errors,
isSubmitted,
canSubmit,
isSaving,
} = planForm;
const statusMutation = usePlanStatusMutation();
const openCreate = useCallback(() => {
pendingPlanRef.current = null;
setIsSheetOpen(true);
prepareCreatePlan();
}, [prepareCreatePlan]);
const openEdit = useCallback(
(plan: Plan) => {
pendingPlanRef.current = plan;
setIsSheetOpen(true);
prepareEditPlan(plan);
},
[prepareEditPlan],
);
useEffect(() => {
if (!isSheetOpen) {
hasSyncedPermissionsRef.current = false;
return;
}
if (
hasSyncedPermissionsRef.current ||
permissionsQuery.isLoading ||
permissionsQuery.permissionTree.length === 0
) {
return;
}
hasSyncedPermissionsRef.current = true;
if (pendingPlanRef.current) {
prepareEditPlan(pendingPlanRef.current);
return;
}
if (!planId) {
prepareCreatePlan();
}
}, [
isSheetOpen,
permissionsQuery.isLoading,
permissionsQuery.permissionTree,
planId,
prepareCreatePlan,
prepareEditPlan,
]);
const toggleStatus = useCallback(
(plan: Plan) => {
statusMutation.mutate(plan);
},
[statusMutation],
);
const columns = usePlanColumns();
const plans = plansQuery.data?.items ?? [];
const total = plansQuery.data?.total ?? plansQuery.data?.totalItems ?? 0;
const toolbar = useMemo(
() => (
<PlanFilters
searchTerm={searchTerm}
statusFilter={statusFilter}
onSearchChange={setSearchTerm}
onStatusChange={setStatusFilter}
/>
),
[searchTerm, setSearchTerm, setStatusFilter, statusFilter],
);
return (
<>
<main className="relative z-10 space-y-5">
<PageHeader
title="Plan Management"
description="Manage subscription plans, limits, and permission access"
icon={BadgeIndianRupee}
actions={
<PermissionGuard permissions={PERMISSIONS.PLAN.CREATE}>
<Button onClick={openCreate}>
<Plus className="mr-2 size-4" />
Add Plan
</Button>
</PermissionGuard>
}
/>
<PlanTable
columns={columns}
plans={plans}
isLoading={plansQuery.isLoading}
toolbar={toolbar}
skip={skip}
limit={limit}
total={total}
sorting={sorting}
onPageChange={setSkip}
onLimitChange={setLimit}
onSortingChange={setSorting}
onEdit={openEdit}
onToggleStatus={toggleStatus}
pendingPlanId={statusMutation.variables?.id}
/>
</main>
<PlanSheet
open={isSheetOpen}
onOpenChange={handleSheetOpenChange}
planId={planId}
register={register}
control={control}
errors={errors}
isSubmitted={isSubmitted}
onSubmit={onSubmit}
canSubmit={canSubmit}
permissionTree={permissionsQuery.permissionTree}
permissionIds={permissionIds}
onPermissionIdsChange={setPermissionIds}
isPermissionsLoading={permissionsQuery.isLoading}
isSaving={isSaving}
/>
</>
);
}