// pages/plans/plan-request.tsx import { useState } from 'react'; import { PageTemplate } from '@/components/page-template'; import { usePage, router } from '@inertiajs/react'; import { Button } from '@/components/ui/button'; import { CrudTable } from '@/components/CrudTable'; import { toast } from '@/components/custom-toast'; import { useTranslation } from 'react-i18next'; import { Pagination } from '@/components/ui/pagination'; import { SearchAndFilterBar } from '@/components/ui/search-and-filter-bar'; import { CheckCircle, XCircle } from 'lucide-react'; import { getImagePath } from '@/utils/helpers'; export default function PlanRequestsPage() { const { t } = useTranslation(); const { planRequests, filters: pageFilters = {}, auth, globalSettings } = usePage().props as any; const permissions = auth?.permissions || []; // State const [searchTerm, setSearchTerm] = useState(pageFilters.search || ''); const [selectedStatus, setSelectedStatus] = useState(pageFilters.status || '_empty_'); const [showFilters, setShowFilters] = useState(false); // Check if any filters are active const hasActiveFilters = () => { return selectedStatus !== '_empty_' || searchTerm !== ''; }; // Count active filters const activeFilterCount = () => { return (selectedStatus !== '_empty_' ? 1 : 0) + (searchTerm !== '' ? 1 : 0); }; const handleSearch = (e: React.FormEvent) => { e.preventDefault(); applyFilters(); }; const applyFilters = () => { router.get(route('plan-requests.index'), { page: 1, search: searchTerm || undefined, status: selectedStatus !== '_empty_' ? selectedStatus : undefined, date_from: dateFrom || undefined, date_to: dateTo || undefined, per_page: pageFilters.per_page }, { preserveState: true, preserveScroll: true }); }; const handleSort = (field: string) => { const direction = pageFilters.sort_field === field && pageFilters.sort_direction === 'asc' ? 'desc' : 'asc'; router.get(route('plan-requests.index'), { sort_field: field, sort_direction: direction, page: 1, search: searchTerm || undefined, status: selectedStatus !== '_empty_' ? selectedStatus : undefined, date_from: dateFrom || undefined, date_to: dateTo || undefined, per_page: pageFilters.per_page }, { preserveState: true, preserveScroll: true }); }; const handleAction = (action: string, item: any) => { if (action === 'approve') { if (!globalSettings?.is_demo) { toast.loading(t('Approving plan request...')); } router.post(route('plan-requests.approve', item.id), {}, { onSuccess: (page) => { if (!globalSettings?.is_demo) { toast.dismiss(); } if (page.props.flash.success) { toast.success(t(page.props.flash.success)); } else if (page.props.flash.error) { toast.error(t(page.props.flash.error)); } }, onError: (errors) => { if (!globalSettings?.is_demo) { toast.dismiss(); } if (typeof errors === 'string') { toast.error(t(errors)); } else { toast.error(t('Failed to approve plan request: {{errors}}', { errors: Object.values(errors).join(', ') })); } } }); } else if (action === 'reject') { if (!globalSettings?.is_demo) { toast.loading(t('Rejecting plan request...')); } router.post(route('plan-requests.reject', item.id), {}, { onSuccess: (page) => { if (!globalSettings?.is_demo) { toast.dismiss(); } if (page.props.flash.success) { toast.success(t(page.props.flash.success)); } else if (page.props.flash.error) { toast.error(t(page.props.flash.error)); } }, onError: (errors) => { if (!globalSettings?.is_demo) { toast.dismiss(); } if (typeof errors === 'string') { toast.error(t(errors)); } else { toast.error(t('Failed to reject plan request: {{errors}}', { errors: Object.values(errors).join(', ') })); } } }); } }; const handleResetFilters = () => { setSearchTerm(''); setSelectedStatus('_empty_'); setDateFrom(''); setDateTo(''); setShowFilters(false); router.get(route('plan-requests.index'), { page: 1, per_page: pageFilters.per_page }, { preserveState: true, preserveScroll: true }); }; const breadcrumbs = [ { title: t('Dashboard'), href: route('dashboard') }, { title: t('Plans'), href: route('plans.index') }, { title: t('Plan Requests') } ]; // Define table columns const columns = [ { key: 'user.name', label: t('Company'), render: (_, row) => { const avatarUrl = row.user?.avatar ? getImagePath(row.user.avatar) : getImagePath('avatars/avatar.png'); return (