filer based on template_type added
This commit is contained in:
parent
ce90fcf9ef
commit
12f8affd15
@ -27,6 +27,7 @@ export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) {
|
||||
searchTerm: filters.searchTerm,
|
||||
statusFilter: filters.statusFilter,
|
||||
priorityFilter: filters.priorityFilter,
|
||||
templateTypeFilter: filters.templateTypeFilter,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
});
|
||||
@ -39,9 +40,10 @@ export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
});
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
});
|
||||
hasInitialFetchRun.current = true;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []); // Only on mount
|
||||
@ -55,6 +57,7 @@ export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) {
|
||||
prev.searchTerm !== filters.searchTerm ||
|
||||
prev.statusFilter !== filters.statusFilter ||
|
||||
prev.priorityFilter !== filters.priorityFilter ||
|
||||
prev.templateTypeFilter !== filters.templateTypeFilter ||
|
||||
prev.sortBy !== filters.sortBy ||
|
||||
prev.sortOrder !== filters.sortOrder;
|
||||
|
||||
@ -67,15 +70,17 @@ export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
});
|
||||
});
|
||||
|
||||
// Update previous values
|
||||
prevFiltersRef.current = {
|
||||
searchTerm: filters.searchTerm,
|
||||
statusFilter: filters.statusFilter,
|
||||
priorityFilter: filters.priorityFilter,
|
||||
templateTypeFilter: filters.templateTypeFilter,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
};
|
||||
@ -83,7 +88,7 @@ export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) {
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [filters.searchTerm, filters.statusFilter, filters.priorityFilter, filters.sortBy, filters.sortOrder]);
|
||||
}, [filters.searchTerm, filters.statusFilter, filters.priorityFilter, filters.templateTypeFilter, filters.sortBy, filters.sortOrder]);
|
||||
|
||||
// Page change handler
|
||||
const handlePageChange = useCallback(
|
||||
@ -94,6 +99,7 @@ export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
});
|
||||
@ -108,6 +114,7 @@ export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
});
|
||||
@ -128,12 +135,14 @@ export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) {
|
||||
searchTerm={filters.searchTerm}
|
||||
priorityFilter={filters.priorityFilter}
|
||||
statusFilter={filters.statusFilter}
|
||||
templateTypeFilter={filters.templateTypeFilter}
|
||||
sortBy={filters.sortBy}
|
||||
sortOrder={filters.sortOrder}
|
||||
activeFiltersCount={filters.activeFiltersCount}
|
||||
onSearchChange={filters.setSearchTerm}
|
||||
onPriorityChange={filters.setPriorityFilter}
|
||||
onStatusChange={filters.setStatusFilter}
|
||||
onTemplateTypeChange={filters.setTemplateTypeFilter}
|
||||
onSortByChange={filters.setSortBy}
|
||||
onSortOrderChange={() => filters.setSortOrder(filters.sortOrder === 'asc' ? 'desc' : 'asc')}
|
||||
onClearFilters={filters.clearFilters}
|
||||
|
||||
@ -71,7 +71,7 @@ export function ClosedRequestCard({ request, onViewRequest }: ClosedRequestCardP
|
||||
let templateColor = 'bg-purple-100 !text-purple-600 border-purple-200';
|
||||
|
||||
if (templateTypeUpper === 'DEALER CLAIM') {
|
||||
templateLabel = 'Claim Management';
|
||||
templateLabel = 'Dealer Claim';
|
||||
templateColor = 'bg-blue-100 !text-blue-700 border-blue-200';
|
||||
} else if (templateTypeUpper === 'TEMPLATE') {
|
||||
templateLabel = 'Template';
|
||||
|
||||
@ -12,12 +12,14 @@ interface ClosedRequestsFiltersProps {
|
||||
searchTerm: string;
|
||||
priorityFilter: string;
|
||||
statusFilter: string;
|
||||
templateTypeFilter: string;
|
||||
sortBy: 'created' | 'due' | 'priority';
|
||||
sortOrder: 'asc' | 'desc';
|
||||
activeFiltersCount: number;
|
||||
onSearchChange: (value: string) => void;
|
||||
onPriorityChange: (value: string) => void;
|
||||
onStatusChange: (value: string) => void;
|
||||
onTemplateTypeChange: (value: string) => void;
|
||||
onSortByChange: (value: 'created' | 'due' | 'priority') => void;
|
||||
onSortOrderChange: () => void;
|
||||
onClearFilters: () => void;
|
||||
@ -27,12 +29,14 @@ export function ClosedRequestsFilters({
|
||||
searchTerm,
|
||||
priorityFilter,
|
||||
statusFilter,
|
||||
templateTypeFilter,
|
||||
sortBy,
|
||||
sortOrder,
|
||||
activeFiltersCount,
|
||||
onSearchChange,
|
||||
onPriorityChange,
|
||||
onStatusChange,
|
||||
onTemplateTypeChange,
|
||||
onSortByChange,
|
||||
onSortOrderChange,
|
||||
onClearFilters,
|
||||
@ -71,7 +75,7 @@ export function ClosedRequestsFilters({
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3 sm:space-y-4 px-3 sm:px-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-3 sm:gap-4">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-3.5 h-3.5 sm:w-4 sm:h-4" />
|
||||
<Input
|
||||
@ -125,6 +129,17 @@ export function ClosedRequestsFilters({
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select value={templateTypeFilter} onValueChange={onTemplateTypeChange}>
|
||||
<SelectTrigger className="h-9 sm:h-10 md:h-11 text-sm sm:text-base bg-gray-50 border-gray-200 focus:bg-white" data-testid="closed-requests-template-type-filter">
|
||||
<SelectValue placeholder="All Templates" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Templates</SelectItem>
|
||||
<SelectItem value="CUSTOM">Custom</SelectItem>
|
||||
<SelectItem value="DEALER CLAIM">Dealer Claim</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Select value={sortBy} onValueChange={(value) => onSortByChange(value as 'created' | 'due' | 'priority')}>
|
||||
<SelectTrigger className="h-9 sm:h-10 md:h-11 text-sm sm:text-base bg-gray-50 border-gray-200 focus:bg-white" data-testid="closed-requests-sort-by">
|
||||
|
||||
@ -30,7 +30,7 @@ export function useClosedRequests({ itemsPerPage = 10 }: UseClosedRequestsOption
|
||||
});
|
||||
|
||||
const fetchRequests = useCallback(
|
||||
async (page: number = 1, filters?: { search?: string; status?: string; priority?: string; sortBy?: string; sortOrder?: string }) => {
|
||||
async (page: number = 1, filters?: { search?: string; status?: string; priority?: string; templateType?: string; sortBy?: string; sortOrder?: string }) => {
|
||||
try {
|
||||
if (page === 1) {
|
||||
setLoading(true);
|
||||
@ -51,6 +51,7 @@ export function useClosedRequests({ itemsPerPage = 10 }: UseClosedRequestsOption
|
||||
search: filters?.search,
|
||||
status: filters?.status && filters.status !== 'all' ? filters.status : undefined,
|
||||
priority: filters?.priority,
|
||||
templateType: filters?.templateType,
|
||||
sortBy: filters?.sortBy,
|
||||
sortOrder: filters?.sortOrder
|
||||
});
|
||||
@ -90,7 +91,7 @@ export function useClosedRequests({ itemsPerPage = 10 }: UseClosedRequestsOption
|
||||
// Initial fetch removed - component handles initial fetch using Redux stored page
|
||||
// This prevents duplicate fetches and allows page persistence
|
||||
|
||||
const handleRefresh = useCallback((filters?: { search?: string; status?: string; priority?: string; sortBy?: string; sortOrder?: string }) => {
|
||||
const handleRefresh = useCallback((filters?: { search?: string; status?: string; priority?: string; templateType?: string; sortBy?: string; sortOrder?: string }) => {
|
||||
setRefreshing(true);
|
||||
fetchRequests(pagination.currentPage, filters);
|
||||
}, [fetchRequests, pagination.currentPage]);
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
setSearchTerm as setSearchTermAction,
|
||||
setStatusFilter as setStatusFilterAction,
|
||||
setPriorityFilter as setPriorityFilterAction,
|
||||
setTemplateTypeFilter as setTemplateTypeFilterAction,
|
||||
setSortBy as setSortByAction,
|
||||
setSortOrder as setSortOrderAction,
|
||||
setCurrentPage as setCurrentPageAction,
|
||||
@ -26,12 +27,13 @@ export function useClosedRequestsFilters({ onFiltersChange, debounceMs = 500 }:
|
||||
const isInitialMount = useRef(true);
|
||||
|
||||
// Get filters from Redux
|
||||
const { searchTerm, statusFilter, priorityFilter, sortBy, sortOrder, currentPage } = useAppSelector((state) => state.closedRequests);
|
||||
const { searchTerm, statusFilter, priorityFilter, templateTypeFilter, sortBy, sortOrder, currentPage } = useAppSelector((state) => state.closedRequests);
|
||||
|
||||
// Create setters that dispatch Redux actions
|
||||
const setSearchTerm = useCallback((value: string) => dispatch(setSearchTermAction(value)), [dispatch]);
|
||||
const setStatusFilter = useCallback((value: string) => dispatch(setStatusFilterAction(value)), [dispatch]);
|
||||
const setPriorityFilter = useCallback((value: string) => dispatch(setPriorityFilterAction(value)), [dispatch]);
|
||||
const setTemplateTypeFilter = useCallback((value: string) => dispatch(setTemplateTypeFilterAction(value)), [dispatch]);
|
||||
const setSortBy = useCallback((value: 'created' | 'due' | 'priority') => dispatch(setSortByAction(value)), [dispatch]);
|
||||
const setSortOrder = useCallback((value: 'asc' | 'desc') => dispatch(setSortOrderAction(value)), [dispatch]);
|
||||
const setCurrentPage = useCallback((value: number) => dispatch(setCurrentPageAction(value)), [dispatch]);
|
||||
@ -41,10 +43,11 @@ export function useClosedRequestsFilters({ onFiltersChange, debounceMs = 500 }:
|
||||
search: searchTerm,
|
||||
status: statusFilter,
|
||||
priority: priorityFilter,
|
||||
templateType: templateTypeFilter !== 'all' ? templateTypeFilter : undefined,
|
||||
sortBy,
|
||||
sortOrder,
|
||||
};
|
||||
}, [searchTerm, statusFilter, priorityFilter, sortBy, sortOrder]);
|
||||
}, [searchTerm, statusFilter, priorityFilter, templateTypeFilter, sortBy, sortOrder]);
|
||||
|
||||
// Debounced filter change handler
|
||||
useEffect(() => {
|
||||
@ -71,7 +74,7 @@ export function useClosedRequestsFilters({ onFiltersChange, debounceMs = 500 }:
|
||||
clearTimeout(debounceTimeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, [searchTerm, statusFilter, priorityFilter, sortBy, sortOrder, onFiltersChange, getFilters, debounceMs]);
|
||||
}, [searchTerm, statusFilter, priorityFilter, templateTypeFilter, sortBy, sortOrder, onFiltersChange, getFilters, debounceMs]);
|
||||
|
||||
const clearFilters = useCallback(() => {
|
||||
dispatch(clearFiltersAction());
|
||||
@ -80,19 +83,22 @@ export function useClosedRequestsFilters({ onFiltersChange, debounceMs = 500 }:
|
||||
const activeFiltersCount = [
|
||||
searchTerm,
|
||||
priorityFilter !== 'all' ? priorityFilter : null,
|
||||
statusFilter !== 'all' ? statusFilter : null
|
||||
statusFilter !== 'all' ? statusFilter : null,
|
||||
templateTypeFilter !== 'all' ? templateTypeFilter : null
|
||||
].filter(Boolean).length;
|
||||
|
||||
return {
|
||||
searchTerm,
|
||||
priorityFilter,
|
||||
statusFilter,
|
||||
templateTypeFilter,
|
||||
sortBy,
|
||||
sortOrder,
|
||||
currentPage,
|
||||
setSearchTerm,
|
||||
setPriorityFilter,
|
||||
setStatusFilter,
|
||||
setTemplateTypeFilter,
|
||||
setSortBy,
|
||||
setSortOrder,
|
||||
setCurrentPage,
|
||||
|
||||
@ -4,6 +4,7 @@ export interface ClosedRequestsFiltersState {
|
||||
searchTerm: string;
|
||||
statusFilter: string;
|
||||
priorityFilter: string;
|
||||
templateTypeFilter: string;
|
||||
sortBy: 'created' | 'due' | 'priority';
|
||||
sortOrder: 'asc' | 'desc';
|
||||
currentPage: number;
|
||||
@ -13,6 +14,7 @@ const initialState: ClosedRequestsFiltersState = {
|
||||
searchTerm: '',
|
||||
statusFilter: 'all',
|
||||
priorityFilter: 'all',
|
||||
templateTypeFilter: 'all',
|
||||
sortBy: 'created',
|
||||
sortOrder: 'desc',
|
||||
currentPage: 1,
|
||||
@ -31,6 +33,9 @@ const closedRequestsSlice = createSlice({
|
||||
setPriorityFilter: (state, action: PayloadAction<string>) => {
|
||||
state.priorityFilter = action.payload;
|
||||
},
|
||||
setTemplateTypeFilter: (state, action: PayloadAction<string>) => {
|
||||
state.templateTypeFilter = action.payload;
|
||||
},
|
||||
setSortBy: (state, action: PayloadAction<'created' | 'due' | 'priority'>) => {
|
||||
state.sortBy = action.payload;
|
||||
},
|
||||
@ -44,6 +49,7 @@ const closedRequestsSlice = createSlice({
|
||||
state.searchTerm = '';
|
||||
state.statusFilter = 'all';
|
||||
state.priorityFilter = 'all';
|
||||
state.templateTypeFilter = 'all';
|
||||
state.currentPage = 1;
|
||||
},
|
||||
},
|
||||
@ -53,6 +59,7 @@ export const {
|
||||
setSearchTerm,
|
||||
setStatusFilter,
|
||||
setPriorityFilter,
|
||||
setTemplateTypeFilter,
|
||||
setSortBy,
|
||||
setSortOrder,
|
||||
setCurrentPage,
|
||||
|
||||
@ -28,6 +28,7 @@ export interface ClosedRequestsFilters {
|
||||
search: string;
|
||||
status: string;
|
||||
priority: string;
|
||||
templateType?: string;
|
||||
sortBy: 'created' | 'due' | 'priority';
|
||||
sortOrder: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
@ -72,12 +72,14 @@ export function useDashboardData({
|
||||
customEndDate?.toISOString(),
|
||||
undefined, // status
|
||||
undefined, // priority
|
||||
undefined, // templateType
|
||||
undefined, // department
|
||||
userId, // initiator - filter by user's ID to get ONLY their initiated requests
|
||||
undefined, // approver
|
||||
undefined, // approverType
|
||||
undefined, // search
|
||||
undefined // slaCompliance
|
||||
undefined, // slaCompliance
|
||||
viewAsUser // viewAsUser - treat as normal user even if admin
|
||||
)
|
||||
: null;
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
searchTerm: filters.searchTerm,
|
||||
statusFilter: filters.statusFilter,
|
||||
priorityFilter: filters.priorityFilter,
|
||||
templateTypeFilter: filters.templateTypeFilter,
|
||||
});
|
||||
const hasInitialFetchRun = useRef(false);
|
||||
|
||||
@ -47,6 +48,7 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
});
|
||||
hasInitialFetchRun.current = true;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@ -60,7 +62,8 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
const hasChanged =
|
||||
prev.searchTerm !== filters.searchTerm ||
|
||||
prev.statusFilter !== filters.statusFilter ||
|
||||
prev.priorityFilter !== filters.priorityFilter;
|
||||
prev.priorityFilter !== filters.priorityFilter ||
|
||||
prev.templateTypeFilter !== filters.templateTypeFilter;
|
||||
|
||||
if (!hasChanged) return; // No actual change, skip
|
||||
|
||||
@ -71,6 +74,7 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
});
|
||||
|
||||
// Update previous values
|
||||
@ -78,12 +82,13 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
searchTerm: filters.searchTerm,
|
||||
statusFilter: filters.statusFilter,
|
||||
priorityFilter: filters.priorityFilter,
|
||||
templateTypeFilter: filters.templateTypeFilter,
|
||||
};
|
||||
}, filters.searchTerm !== prev.searchTerm ? 500 : 0);
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [filters.searchTerm, filters.statusFilter, filters.priorityFilter]);
|
||||
}, [filters.searchTerm, filters.statusFilter, filters.priorityFilter, filters.templateTypeFilter]);
|
||||
|
||||
// State for backend stats (calculated from entire dataset via SQL queries)
|
||||
const [backendStats, setBackendStats] = useState<{
|
||||
@ -112,19 +117,21 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
// Even for admin users, we want to see only their own requests in "My Requests"
|
||||
// This calculates stats from entire dataset using SQL COUNT queries, not by fetching data
|
||||
// Note: status is undefined - stats should show all statuses, not filtered by status
|
||||
// Note: No date range filter - stats should match the list which shows all requests
|
||||
// Note: dateRange is 'all' - stats should match the list which shows all requests
|
||||
const stats = await dashboardService.getRequestStats(
|
||||
undefined, // dateRange - no date filter to match the list
|
||||
'all', // dateRange - 'all' means no date filter to match the list
|
||||
undefined, // startDate
|
||||
undefined, // endDate
|
||||
undefined, // status - My Requests stats show all statuses, not filtered by status (same as All Requests)
|
||||
filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined, // templateType
|
||||
undefined, // department
|
||||
user.userId, // initiator - explicitly filter by user's own userId to ensure only their requests
|
||||
undefined, // approver
|
||||
undefined, // approverType
|
||||
filters.searchTerm || undefined,
|
||||
undefined // slaCompliance
|
||||
undefined, // slaCompliance
|
||||
true // viewAsUser - treat as normal user even if admin
|
||||
);
|
||||
|
||||
setBackendStats({
|
||||
@ -142,7 +149,7 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
} finally {
|
||||
setLoadingStats(false);
|
||||
}
|
||||
}, [user?.userId, filters.searchTerm, filters.priorityFilter]); // Exclude statusFilter - stats don't change when only status changes
|
||||
}, [user?.userId, filters.searchTerm, filters.priorityFilter, filters.templateTypeFilter]); // Exclude statusFilter - stats don't change when only status changes
|
||||
|
||||
// Fetch stats when filters change (excluding status filter)
|
||||
// Stats should reflect priority and search filters, but NOT status filter
|
||||
@ -153,7 +160,7 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
}, filters.searchTerm ? 500 : 0);
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
}, [filters.searchTerm, filters.priorityFilter, fetchBackendStats]); // Exclude statusFilter - stats don't change when only status changes
|
||||
}, [filters.searchTerm, filters.priorityFilter, filters.templateTypeFilter, fetchBackendStats]); // Exclude statusFilter - stats don't change when only status changes
|
||||
|
||||
// Handle dynamic requests (fallback until API loads)
|
||||
const convertedDynamicRequests = transformRequests(dynamicRequests);
|
||||
@ -196,6 +203,7 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -230,9 +238,11 @@ export function MyRequests({ onViewRequest, dynamicRequests = [] }: MyRequestsPr
|
||||
searchTerm={filters.searchTerm}
|
||||
statusFilter={filters.statusFilter}
|
||||
priorityFilter={filters.priorityFilter}
|
||||
templateTypeFilter={filters.templateTypeFilter}
|
||||
onSearchChange={filters.setSearchTerm}
|
||||
onStatusChange={filters.setStatusFilter}
|
||||
onPriorityChange={filters.setPriorityFilter}
|
||||
onTemplateTypeChange={filters.setTemplateTypeFilter}
|
||||
/>
|
||||
|
||||
{/* Requests List */}
|
||||
|
||||
@ -11,18 +11,22 @@ interface MyRequestsFiltersProps {
|
||||
searchTerm: string;
|
||||
statusFilter: string;
|
||||
priorityFilter: string;
|
||||
templateTypeFilter: string;
|
||||
onSearchChange: (value: string) => void;
|
||||
onStatusChange: (value: string) => void;
|
||||
onPriorityChange: (value: string) => void;
|
||||
onTemplateTypeChange: (value: string) => void;
|
||||
}
|
||||
|
||||
export function MyRequestsFilters({
|
||||
searchTerm,
|
||||
statusFilter,
|
||||
priorityFilter,
|
||||
templateTypeFilter,
|
||||
onSearchChange,
|
||||
onStatusChange,
|
||||
onPriorityChange,
|
||||
onTemplateTypeChange,
|
||||
}: MyRequestsFiltersProps) {
|
||||
return (
|
||||
<Card className="border-gray-200" data-testid="my-requests-filters">
|
||||
@ -71,6 +75,20 @@ export function MyRequestsFilters({
|
||||
<SelectItem value="standard">Standard</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select value={templateTypeFilter} onValueChange={onTemplateTypeChange}>
|
||||
<SelectTrigger
|
||||
className="flex-1 md:w-28 lg:w-32 text-xs sm:text-sm bg-white border-gray-300 hover:border-gray-400 focus:border-blue-400 focus:ring-1 focus:ring-blue-200 h-9 sm:h-10"
|
||||
data-testid="template-type-filter"
|
||||
>
|
||||
<SelectValue placeholder="Template Type" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Templates</SelectItem>
|
||||
<SelectItem value="CUSTOM">Custom</SelectItem>
|
||||
<SelectItem value="DEALER CLAIM">Dealer Claim</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@ -107,7 +107,7 @@ export function RequestCard({ request, index, onViewRequest }: RequestCardProps)
|
||||
let templateColor = 'bg-purple-100 !text-purple-600 border-purple-200';
|
||||
|
||||
if (templateTypeUpper === 'DEALER CLAIM') {
|
||||
templateLabel = 'Claim Management';
|
||||
templateLabel = 'Dealer Claim';
|
||||
templateColor = 'bg-blue-100 !text-blue-700 border-blue-200';
|
||||
} else if (templateTypeUpper === 'TEMPLATE') {
|
||||
templateLabel = 'Template';
|
||||
|
||||
@ -13,6 +13,7 @@ interface UseMyRequestsOptions {
|
||||
search?: string;
|
||||
status?: string;
|
||||
priority?: string;
|
||||
templateType?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@ -28,7 +29,7 @@ export function useMyRequests({ itemsPerPage = 10 }: UseMyRequestsOptions = {})
|
||||
});
|
||||
|
||||
const fetchMyRequests = useCallback(
|
||||
async (page: number = 1, filters?: { search?: string; status?: string; priority?: string }) => {
|
||||
async (page: number = 1, filters?: { search?: string; status?: string; priority?: string; templateType?: string }) => {
|
||||
try {
|
||||
if (page === 1) {
|
||||
setLoading(true);
|
||||
@ -41,6 +42,7 @@ export function useMyRequests({ itemsPerPage = 10 }: UseMyRequestsOptions = {})
|
||||
search: filters?.search,
|
||||
status: filters?.status,
|
||||
priority: filters?.priority,
|
||||
templateType: filters?.templateType,
|
||||
});
|
||||
|
||||
// Extract data - workflowApi now returns { data: [], pagination: {} }
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
setSearchTerm as setSearchTermAction,
|
||||
setStatusFilter as setStatusFilterAction,
|
||||
setPriorityFilter as setPriorityFilterAction,
|
||||
setTemplateTypeFilter as setTemplateTypeFilterAction,
|
||||
setCurrentPage as setCurrentPageAction,
|
||||
clearFilters as clearFiltersAction,
|
||||
} from '../redux/myRequestsSlice';
|
||||
@ -24,12 +25,13 @@ export function useMyRequestsFilters({ onFiltersChange, debounceMs = 500 }: UseM
|
||||
const isInitialMount = useRef(true);
|
||||
|
||||
// Get filters from Redux
|
||||
const { searchTerm, statusFilter, priorityFilter, currentPage } = useAppSelector((state) => state.myRequests);
|
||||
const { searchTerm, statusFilter, priorityFilter, templateTypeFilter, currentPage } = useAppSelector((state) => state.myRequests);
|
||||
|
||||
// Create setters that dispatch Redux actions
|
||||
const setSearchTerm = useCallback((value: string) => dispatch(setSearchTermAction(value)), [dispatch]);
|
||||
const setStatusFilter = useCallback((value: string) => dispatch(setStatusFilterAction(value)), [dispatch]);
|
||||
const setPriorityFilter = useCallback((value: string) => dispatch(setPriorityFilterAction(value)), [dispatch]);
|
||||
const setTemplateTypeFilter = useCallback((value: string) => dispatch(setTemplateTypeFilterAction(value)), [dispatch]);
|
||||
const setCurrentPage = useCallback((value: number) => dispatch(setCurrentPageAction(value)), [dispatch]);
|
||||
|
||||
const getFilters = useCallback((): MyRequestsFilters => {
|
||||
@ -37,8 +39,9 @@ export function useMyRequestsFilters({ onFiltersChange, debounceMs = 500 }: UseM
|
||||
search: searchTerm,
|
||||
status: statusFilter,
|
||||
priority: priorityFilter,
|
||||
templateType: templateTypeFilter,
|
||||
};
|
||||
}, [searchTerm, statusFilter, priorityFilter]);
|
||||
}, [searchTerm, statusFilter, priorityFilter, templateTypeFilter]);
|
||||
|
||||
// Debounced filter change handler
|
||||
useEffect(() => {
|
||||
@ -65,7 +68,7 @@ export function useMyRequestsFilters({ onFiltersChange, debounceMs = 500 }: UseM
|
||||
clearTimeout(debounceTimeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, [searchTerm, statusFilter, priorityFilter, onFiltersChange, getFilters, debounceMs]);
|
||||
}, [searchTerm, statusFilter, priorityFilter, templateTypeFilter, onFiltersChange, getFilters, debounceMs]);
|
||||
|
||||
const resetFilters = useCallback(() => {
|
||||
dispatch(clearFiltersAction());
|
||||
@ -75,10 +78,12 @@ export function useMyRequestsFilters({ onFiltersChange, debounceMs = 500 }: UseM
|
||||
searchTerm,
|
||||
statusFilter,
|
||||
priorityFilter,
|
||||
templateTypeFilter,
|
||||
currentPage,
|
||||
setSearchTerm,
|
||||
setStatusFilter,
|
||||
setPriorityFilter,
|
||||
setTemplateTypeFilter,
|
||||
setCurrentPage,
|
||||
getFilters,
|
||||
resetFilters,
|
||||
|
||||
@ -4,6 +4,7 @@ export interface MyRequestsFiltersState {
|
||||
searchTerm: string;
|
||||
statusFilter: string;
|
||||
priorityFilter: string;
|
||||
templateTypeFilter: string;
|
||||
currentPage: number;
|
||||
}
|
||||
|
||||
@ -11,6 +12,7 @@ const initialState: MyRequestsFiltersState = {
|
||||
searchTerm: '',
|
||||
statusFilter: 'all',
|
||||
priorityFilter: 'all',
|
||||
templateTypeFilter: 'all',
|
||||
currentPage: 1,
|
||||
};
|
||||
|
||||
@ -28,6 +30,10 @@ const myRequestsSlice = createSlice({
|
||||
state.priorityFilter = action.payload;
|
||||
state.currentPage = 1; // Reset to page 1 when filter changes
|
||||
},
|
||||
setTemplateTypeFilter: (state, action: PayloadAction<string>) => {
|
||||
state.templateTypeFilter = action.payload;
|
||||
state.currentPage = 1; // Reset to page 1 when filter changes
|
||||
},
|
||||
setCurrentPage: (state, action: PayloadAction<number>) => {
|
||||
state.currentPage = action.payload;
|
||||
},
|
||||
@ -35,6 +41,7 @@ const myRequestsSlice = createSlice({
|
||||
state.searchTerm = '';
|
||||
state.statusFilter = 'all';
|
||||
state.priorityFilter = 'all';
|
||||
state.templateTypeFilter = 'all';
|
||||
state.currentPage = 1;
|
||||
},
|
||||
},
|
||||
@ -44,6 +51,7 @@ export const {
|
||||
setSearchTerm,
|
||||
setStatusFilter,
|
||||
setPriorityFilter,
|
||||
setTemplateTypeFilter,
|
||||
setCurrentPage,
|
||||
clearFilters,
|
||||
} = myRequestsSlice.actions;
|
||||
|
||||
@ -40,6 +40,7 @@ export interface MyRequestsFilters {
|
||||
search: string;
|
||||
status: string;
|
||||
priority: string;
|
||||
templateType?: string;
|
||||
}
|
||||
|
||||
export interface PaginationState {
|
||||
|
||||
@ -122,7 +122,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
// - An initiator (for approved requests awaiting closure)
|
||||
// This applies to ALL users including regular users, MANAGEMENT, and ADMIN roles
|
||||
// For organization-wide view, users should use the "All Requests" screen (/requests)
|
||||
const fetchRequests = useCallback(async (page: number = 1, filterParams?: { search?: string; status?: string; priority?: string; sortBy?: string; sortOrder?: string }) => {
|
||||
const fetchRequests = useCallback(async (page: number = 1, filterParams?: { search?: string; status?: string; priority?: string; templateType?: string; sortBy?: string; sortOrder?: string }) => {
|
||||
try {
|
||||
if (page === 1) {
|
||||
setLoading(true);
|
||||
@ -138,6 +138,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
search: filterParams?.search,
|
||||
status: filterParams?.status,
|
||||
priority: filterParams?.priority,
|
||||
templateType: filterParams?.templateType,
|
||||
sortBy: filterParams?.sortBy,
|
||||
sortOrder: filterParams?.sortOrder
|
||||
});
|
||||
@ -197,6 +198,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder
|
||||
});
|
||||
@ -209,6 +211,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder
|
||||
});
|
||||
@ -244,6 +247,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
});
|
||||
@ -263,6 +267,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined,
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
sortBy: filters.sortBy,
|
||||
sortOrder: filters.sortOrder,
|
||||
});
|
||||
@ -270,7 +275,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [filters.searchTerm, filters.statusFilter, filters.priorityFilter, filters.sortBy, filters.sortOrder]);
|
||||
}, [filters.searchTerm, filters.statusFilter, filters.priorityFilter, filters.templateTypeFilter, filters.sortBy, filters.sortOrder]);
|
||||
|
||||
// Backend handles both filtering and sorting - use items directly
|
||||
// No client-side sorting needed anymore
|
||||
@ -345,7 +350,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3 sm:space-y-4 px-3 sm:px-6">
|
||||
{/* Primary filters */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-3 sm:gap-4">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-3.5 h-3.5 sm:w-4 sm:h-4" />
|
||||
<Input
|
||||
@ -388,6 +393,17 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select value={filters.templateTypeFilter} onValueChange={filters.setTemplateTypeFilter}>
|
||||
<SelectTrigger className="h-9 sm:h-10 md:h-11 text-sm sm:text-base bg-gray-50 border-gray-200 focus:bg-white focus:border-blue-400 focus:ring-1 focus:ring-blue-200">
|
||||
<SelectValue placeholder="All Templates" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Templates</SelectItem>
|
||||
<SelectItem value="CUSTOM">Custom</SelectItem>
|
||||
<SelectItem value="DEALER CLAIM">Dealer Claim</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Select value={filters.sortBy} onValueChange={(value: any) => filters.setSortBy(value)}>
|
||||
<SelectTrigger className="h-9 sm:h-10 md:h-11 text-sm sm:text-base bg-gray-50 border-gray-200 focus:bg-white focus:border-blue-400 focus:ring-1 focus:ring-blue-200">
|
||||
@ -470,7 +486,7 @@ export function OpenRequests({ onViewRequest }: OpenRequestsProps) {
|
||||
let templateColor = 'bg-purple-100 !text-purple-600 border-purple-200';
|
||||
|
||||
if (templateTypeUpper === 'DEALER CLAIM') {
|
||||
templateLabel = 'Claim Management';
|
||||
templateLabel = 'Dealer Claim';
|
||||
templateColor = 'bg-blue-100 !text-blue-700 border-blue-200';
|
||||
} else if (templateTypeUpper === 'TEMPLATE') {
|
||||
templateLabel = 'Template';
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
setSearchTerm as setSearchTermAction,
|
||||
setStatusFilter as setStatusFilterAction,
|
||||
setPriorityFilter as setPriorityFilterAction,
|
||||
setTemplateTypeFilter as setTemplateTypeFilterAction,
|
||||
setSortBy as setSortByAction,
|
||||
setSortOrder as setSortOrderAction,
|
||||
setCurrentPage as setCurrentPageAction,
|
||||
@ -18,12 +19,13 @@ export function useOpenRequestsFilters() {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
// Get filters from Redux
|
||||
const { searchTerm, statusFilter, priorityFilter, sortBy, sortOrder, currentPage } = useAppSelector((state) => state.openRequests);
|
||||
const { searchTerm, statusFilter, priorityFilter, templateTypeFilter, sortBy, sortOrder, currentPage } = useAppSelector((state) => state.openRequests);
|
||||
|
||||
// Create setters that dispatch Redux actions
|
||||
const setSearchTerm = useCallback((value: string) => dispatch(setSearchTermAction(value)), [dispatch]);
|
||||
const setStatusFilter = useCallback((value: string) => dispatch(setStatusFilterAction(value)), [dispatch]);
|
||||
const setPriorityFilter = useCallback((value: string) => dispatch(setPriorityFilterAction(value)), [dispatch]);
|
||||
const setTemplateTypeFilter = useCallback((value: string) => dispatch(setTemplateTypeFilterAction(value)), [dispatch]);
|
||||
const setSortBy = useCallback((value: 'created' | 'due' | 'priority' | 'sla') => dispatch(setSortByAction(value)), [dispatch]);
|
||||
const setSortOrder = useCallback((value: 'asc' | 'desc') => dispatch(setSortOrderAction(value)), [dispatch]);
|
||||
const setCurrentPage = useCallback((value: number) => dispatch(setCurrentPageAction(value)), [dispatch]);
|
||||
@ -32,19 +34,22 @@ export function useOpenRequestsFilters() {
|
||||
const activeFiltersCount = [
|
||||
searchTerm,
|
||||
priorityFilter !== 'all' ? priorityFilter : null,
|
||||
statusFilter !== 'all' ? statusFilter : null
|
||||
statusFilter !== 'all' ? statusFilter : null,
|
||||
templateTypeFilter !== 'all' ? templateTypeFilter : null
|
||||
].filter(Boolean).length;
|
||||
|
||||
return {
|
||||
searchTerm,
|
||||
statusFilter,
|
||||
priorityFilter,
|
||||
templateTypeFilter,
|
||||
sortBy,
|
||||
sortOrder,
|
||||
currentPage,
|
||||
setSearchTerm,
|
||||
setStatusFilter,
|
||||
setPriorityFilter,
|
||||
setTemplateTypeFilter,
|
||||
setSortBy,
|
||||
setSortOrder,
|
||||
setCurrentPage,
|
||||
|
||||
@ -4,6 +4,7 @@ export interface OpenRequestsFiltersState {
|
||||
searchTerm: string;
|
||||
statusFilter: string;
|
||||
priorityFilter: string;
|
||||
templateTypeFilter: string;
|
||||
sortBy: 'created' | 'due' | 'priority' | 'sla';
|
||||
sortOrder: 'asc' | 'desc';
|
||||
currentPage: number;
|
||||
@ -13,6 +14,7 @@ const initialState: OpenRequestsFiltersState = {
|
||||
searchTerm: '',
|
||||
statusFilter: 'all',
|
||||
priorityFilter: 'all',
|
||||
templateTypeFilter: 'all',
|
||||
sortBy: 'created',
|
||||
sortOrder: 'desc',
|
||||
currentPage: 1,
|
||||
@ -31,6 +33,9 @@ const openRequestsSlice = createSlice({
|
||||
setPriorityFilter: (state, action: PayloadAction<string>) => {
|
||||
state.priorityFilter = action.payload;
|
||||
},
|
||||
setTemplateTypeFilter: (state, action: PayloadAction<string>) => {
|
||||
state.templateTypeFilter = action.payload;
|
||||
},
|
||||
setSortBy: (state, action: PayloadAction<'created' | 'due' | 'priority' | 'sla'>) => {
|
||||
state.sortBy = action.payload;
|
||||
},
|
||||
@ -44,6 +49,7 @@ const openRequestsSlice = createSlice({
|
||||
state.searchTerm = '';
|
||||
state.statusFilter = 'all';
|
||||
state.priorityFilter = 'all';
|
||||
state.templateTypeFilter = 'all';
|
||||
state.currentPage = 1;
|
||||
},
|
||||
},
|
||||
@ -53,6 +59,7 @@ export const {
|
||||
setSearchTerm,
|
||||
setStatusFilter,
|
||||
setPriorityFilter,
|
||||
setTemplateTypeFilter,
|
||||
setSortBy,
|
||||
setSortOrder,
|
||||
setCurrentPage,
|
||||
|
||||
@ -310,6 +310,7 @@ export function Requests({ onViewRequest }: RequestsProps) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
const filtersWithoutStatus = {
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
department: filters.departmentFilter !== 'all' ? filters.departmentFilter : undefined,
|
||||
initiator: filters.initiatorFilter !== 'all' ? filters.initiatorFilter : undefined,
|
||||
approver: filters.approverFilter !== 'all' ? filters.approverFilter : undefined,
|
||||
@ -337,6 +338,7 @@ export function Requests({ onViewRequest }: RequestsProps) {
|
||||
filters.customStartDate,
|
||||
filters.customEndDate,
|
||||
filters.priorityFilter,
|
||||
filters.templateTypeFilter,
|
||||
filters.departmentFilter,
|
||||
filters.initiatorFilter,
|
||||
filters.approverFilter,
|
||||
@ -351,6 +353,7 @@ export function Requests({ onViewRequest }: RequestsProps) {
|
||||
searchTerm: filters.searchTerm,
|
||||
statusFilter: filters.statusFilter,
|
||||
priorityFilter: filters.priorityFilter,
|
||||
templateTypeFilter: filters.templateTypeFilter,
|
||||
slaComplianceFilter: filters.slaComplianceFilter,
|
||||
departmentFilter: filters.departmentFilter,
|
||||
initiatorFilter: filters.initiatorFilter,
|
||||
@ -380,6 +383,7 @@ export function Requests({ onViewRequest }: RequestsProps) {
|
||||
prev.searchTerm !== filters.searchTerm ||
|
||||
prev.statusFilter !== filters.statusFilter ||
|
||||
prev.priorityFilter !== filters.priorityFilter ||
|
||||
prev.templateTypeFilter !== filters.templateTypeFilter ||
|
||||
prev.slaComplianceFilter !== filters.slaComplianceFilter ||
|
||||
prev.departmentFilter !== filters.departmentFilter ||
|
||||
prev.initiatorFilter !== filters.initiatorFilter ||
|
||||
@ -400,6 +404,7 @@ export function Requests({ onViewRequest }: RequestsProps) {
|
||||
searchTerm: filters.searchTerm,
|
||||
statusFilter: filters.statusFilter,
|
||||
priorityFilter: filters.priorityFilter,
|
||||
templateTypeFilter: filters.templateTypeFilter,
|
||||
slaComplianceFilter: filters.slaComplianceFilter,
|
||||
departmentFilter: filters.departmentFilter,
|
||||
initiatorFilter: filters.initiatorFilter,
|
||||
@ -419,6 +424,7 @@ export function Requests({ onViewRequest }: RequestsProps) {
|
||||
filters.searchTerm,
|
||||
filters.statusFilter,
|
||||
filters.priorityFilter,
|
||||
filters.templateTypeFilter,
|
||||
filters.slaComplianceFilter,
|
||||
filters.departmentFilter,
|
||||
filters.initiatorFilter,
|
||||
@ -513,7 +519,7 @@ export function Requests({ onViewRequest }: RequestsProps) {
|
||||
<Separator />
|
||||
|
||||
{/* Primary Filters */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-3 sm:gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-6 gap-3 sm:gap-4">
|
||||
<div className="relative md:col-span-3 lg:col-span-1">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
|
||||
<Input
|
||||
@ -550,6 +556,17 @@ export function Requests({ onViewRequest }: RequestsProps) {
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select value={filters.templateTypeFilter} onValueChange={filters.setTemplateTypeFilter}>
|
||||
<SelectTrigger className="h-10" data-testid="template-type-filter">
|
||||
<SelectValue placeholder="All Templates" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Templates</SelectItem>
|
||||
<SelectItem value="CUSTOM">Custom</SelectItem>
|
||||
<SelectItem value="DEALER CLAIM">Dealer Claim</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select
|
||||
value={filters.departmentFilter}
|
||||
onValueChange={filters.setDepartmentFilter}
|
||||
|
||||
@ -84,6 +84,7 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
statsEndDate?: Date,
|
||||
filtersWithoutStatus?: {
|
||||
priority?: string;
|
||||
templateType?: string;
|
||||
department?: string;
|
||||
initiator?: string;
|
||||
approver?: string;
|
||||
@ -100,6 +101,7 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
statsEndDate ? statsEndDate.toISOString() : undefined,
|
||||
undefined, // status - stats should show all statuses
|
||||
filtersWithoutStatus?.priority,
|
||||
filtersWithoutStatus?.templateType,
|
||||
filtersWithoutStatus?.department,
|
||||
filtersWithoutStatus?.initiator,
|
||||
filtersWithoutStatus?.approver,
|
||||
@ -216,6 +218,7 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
const filtersWithoutStatus = {
|
||||
priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined,
|
||||
templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined,
|
||||
department: filters.departmentFilter !== 'all' ? filters.departmentFilter : undefined,
|
||||
initiator: filters.initiatorFilter !== 'all' ? filters.initiatorFilter : undefined,
|
||||
approver: filters.approverFilter !== 'all' ? filters.approverFilter : undefined,
|
||||
@ -223,7 +226,8 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
search: filters.searchTerm || undefined,
|
||||
slaCompliance: filters.slaComplianceFilter !== 'all' ? filters.slaComplianceFilter : undefined
|
||||
};
|
||||
const statsDateRange = filters.dateRange || 'month';
|
||||
// Use 'all' if dateRange is 'all', otherwise use the selected dateRange or default to 'month'
|
||||
const statsDateRange = filters.dateRange === 'all' ? 'all' : (filters.dateRange || 'month');
|
||||
|
||||
fetchBackendStatsRef.current(
|
||||
statsDateRange,
|
||||
@ -245,7 +249,8 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
filters.approverFilterType,
|
||||
filters.dateRange,
|
||||
filters.customStartDate,
|
||||
filters.customEndDate
|
||||
filters.customEndDate,
|
||||
filters.templateTypeFilter
|
||||
// Note: statusFilter is NOT in dependencies - stats don't change when only status changes
|
||||
]);
|
||||
|
||||
@ -254,6 +259,7 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
searchTerm: filters.searchTerm,
|
||||
statusFilter: filters.statusFilter,
|
||||
priorityFilter: filters.priorityFilter,
|
||||
templateTypeFilter: filters.templateTypeFilter,
|
||||
slaComplianceFilter: filters.slaComplianceFilter,
|
||||
departmentFilter: filters.departmentFilter,
|
||||
initiatorFilter: filters.initiatorFilter,
|
||||
@ -282,6 +288,7 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
prev.searchTerm !== filters.searchTerm ||
|
||||
prev.statusFilter !== filters.statusFilter ||
|
||||
prev.priorityFilter !== filters.priorityFilter ||
|
||||
prev.templateTypeFilter !== filters.templateTypeFilter ||
|
||||
prev.slaComplianceFilter !== filters.slaComplianceFilter ||
|
||||
prev.departmentFilter !== filters.departmentFilter ||
|
||||
prev.initiatorFilter !== filters.initiatorFilter ||
|
||||
@ -301,6 +308,7 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
searchTerm: filters.searchTerm,
|
||||
statusFilter: filters.statusFilter,
|
||||
priorityFilter: filters.priorityFilter,
|
||||
templateTypeFilter: filters.templateTypeFilter,
|
||||
slaComplianceFilter: filters.slaComplianceFilter,
|
||||
departmentFilter: filters.departmentFilter,
|
||||
initiatorFilter: filters.initiatorFilter,
|
||||
@ -318,6 +326,7 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
filters.searchTerm,
|
||||
filters.statusFilter,
|
||||
filters.priorityFilter,
|
||||
filters.templateTypeFilter,
|
||||
filters.slaComplianceFilter,
|
||||
filters.departmentFilter,
|
||||
filters.initiatorFilter,
|
||||
@ -431,7 +440,7 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
<Separator />
|
||||
|
||||
{/* Primary Filters */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-3 sm:gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-6 gap-3 sm:gap-4">
|
||||
<div className="relative md:col-span-3 lg:col-span-1">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
|
||||
<Input
|
||||
@ -468,6 +477,17 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select value={filters.templateTypeFilter} onValueChange={filters.setTemplateTypeFilter}>
|
||||
<SelectTrigger className="h-10" data-testid="template-type-filter">
|
||||
<SelectValue placeholder="All Templates" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Templates</SelectItem>
|
||||
<SelectItem value="CUSTOM">Custom</SelectItem>
|
||||
<SelectItem value="DEALER CLAIM">Dealer Claim</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select
|
||||
value={filters.departmentFilter}
|
||||
onValueChange={filters.setDepartmentFilter}
|
||||
|
||||
@ -106,7 +106,7 @@ export function RequestCard({ request, index, onViewRequest }: RequestCardProps)
|
||||
let templateColor = 'bg-purple-100 !text-purple-600 border-purple-200';
|
||||
|
||||
if (templateTypeUpper === 'DEALER CLAIM') {
|
||||
templateLabel = 'Claim Management';
|
||||
templateLabel = 'Dealer Claim';
|
||||
templateColor = 'bg-blue-100 !text-blue-700 border-blue-200';
|
||||
} else if (templateTypeUpper === 'TEMPLATE') {
|
||||
templateLabel = 'Template';
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
setSearchTerm as setSearchTermAction,
|
||||
setStatusFilter as setStatusFilterAction,
|
||||
setPriorityFilter as setPriorityFilterAction,
|
||||
setTemplateTypeFilter as setTemplateTypeFilterAction,
|
||||
setSlaComplianceFilter as setSlaComplianceFilterAction,
|
||||
setDepartmentFilter as setDepartmentFilterAction,
|
||||
setInitiatorFilter as setInitiatorFilterAction,
|
||||
@ -32,6 +33,7 @@ export function useRequestsFilters() {
|
||||
searchTerm,
|
||||
statusFilter,
|
||||
priorityFilter,
|
||||
templateTypeFilter,
|
||||
slaComplianceFilter,
|
||||
departmentFilter,
|
||||
initiatorFilter,
|
||||
@ -48,6 +50,7 @@ export function useRequestsFilters() {
|
||||
const setSearchTerm = useCallback((value: string) => dispatch(setSearchTermAction(value)), [dispatch]);
|
||||
const setStatusFilter = useCallback((value: string) => dispatch(setStatusFilterAction(value)), [dispatch]);
|
||||
const setPriorityFilter = useCallback((value: string) => dispatch(setPriorityFilterAction(value)), [dispatch]);
|
||||
const setTemplateTypeFilter = useCallback((value: string) => dispatch(setTemplateTypeFilterAction(value)), [dispatch]);
|
||||
const setSlaComplianceFilter = useCallback((value: string) => dispatch(setSlaComplianceFilterAction(value)), [dispatch]);
|
||||
const setDepartmentFilter = useCallback((value: string) => dispatch(setDepartmentFilterAction(value)), [dispatch]);
|
||||
const setInitiatorFilter = useCallback((value: string) => dispatch(setInitiatorFilterAction(value)), [dispatch]);
|
||||
@ -64,6 +67,7 @@ export function useRequestsFilters() {
|
||||
search: searchTerm || undefined,
|
||||
status: statusFilter !== 'all' ? statusFilter : undefined,
|
||||
priority: priorityFilter !== 'all' ? priorityFilter : undefined,
|
||||
templateType: templateTypeFilter !== 'all' ? templateTypeFilter : undefined,
|
||||
slaCompliance: slaComplianceFilter !== 'all' ? slaComplianceFilter : undefined,
|
||||
department: departmentFilter !== 'all' ? departmentFilter : undefined,
|
||||
initiator: initiatorFilter !== 'all' ? initiatorFilter : undefined,
|
||||
@ -77,6 +81,7 @@ export function useRequestsFilters() {
|
||||
searchTerm,
|
||||
statusFilter,
|
||||
priorityFilter,
|
||||
templateTypeFilter,
|
||||
slaComplianceFilter,
|
||||
departmentFilter,
|
||||
initiatorFilter,
|
||||
@ -118,6 +123,7 @@ export function useRequestsFilters() {
|
||||
searchTerm ||
|
||||
statusFilter !== 'all' ||
|
||||
priorityFilter !== 'all' ||
|
||||
templateTypeFilter !== 'all' ||
|
||||
slaComplianceFilter !== 'all' ||
|
||||
departmentFilter !== 'all' ||
|
||||
initiatorFilter !== 'all' ||
|
||||
@ -132,6 +138,7 @@ export function useRequestsFilters() {
|
||||
searchTerm,
|
||||
statusFilter,
|
||||
priorityFilter,
|
||||
templateTypeFilter,
|
||||
slaComplianceFilter,
|
||||
departmentFilter,
|
||||
initiatorFilter,
|
||||
@ -147,6 +154,7 @@ export function useRequestsFilters() {
|
||||
setSearchTerm,
|
||||
setStatusFilter,
|
||||
setPriorityFilter,
|
||||
setTemplateTypeFilter,
|
||||
setSlaComplianceFilter,
|
||||
setDepartmentFilter,
|
||||
setInitiatorFilter,
|
||||
|
||||
@ -5,6 +5,7 @@ export interface RequestsFiltersState {
|
||||
searchTerm: string;
|
||||
statusFilter: string;
|
||||
priorityFilter: string;
|
||||
templateTypeFilter: string;
|
||||
slaComplianceFilter: string;
|
||||
departmentFilter: string;
|
||||
initiatorFilter: string;
|
||||
@ -21,6 +22,7 @@ const initialState: RequestsFiltersState = {
|
||||
searchTerm: '',
|
||||
statusFilter: 'all',
|
||||
priorityFilter: 'all',
|
||||
templateTypeFilter: 'all',
|
||||
slaComplianceFilter: 'all',
|
||||
departmentFilter: 'all',
|
||||
initiatorFilter: 'all',
|
||||
@ -46,6 +48,9 @@ const requestsSlice = createSlice({
|
||||
setPriorityFilter: (state, action: PayloadAction<string>) => {
|
||||
state.priorityFilter = action.payload;
|
||||
},
|
||||
setTemplateTypeFilter: (state, action: PayloadAction<string>) => {
|
||||
state.templateTypeFilter = action.payload;
|
||||
},
|
||||
setSlaComplianceFilter: (state, action: PayloadAction<string>) => {
|
||||
state.slaComplianceFilter = action.payload;
|
||||
},
|
||||
@ -80,6 +85,7 @@ const requestsSlice = createSlice({
|
||||
state.searchTerm = '';
|
||||
state.statusFilter = 'all';
|
||||
state.priorityFilter = 'all';
|
||||
state.templateTypeFilter = 'all';
|
||||
state.slaComplianceFilter = 'all';
|
||||
state.departmentFilter = 'all';
|
||||
state.initiatorFilter = 'all';
|
||||
@ -98,6 +104,7 @@ export const {
|
||||
setSearchTerm,
|
||||
setStatusFilter,
|
||||
setPriorityFilter,
|
||||
setTemplateTypeFilter,
|
||||
setSlaComplianceFilter,
|
||||
setDepartmentFilter,
|
||||
setInitiatorFilter,
|
||||
|
||||
@ -25,6 +25,7 @@ export async function fetchRequestsData({
|
||||
if (filters?.search) backendFilters.search = filters.search;
|
||||
if (filters?.status && filters.status !== 'all') backendFilters.status = filters.status;
|
||||
if (filters?.priority && filters.priority !== 'all') backendFilters.priority = filters.priority;
|
||||
if (filters?.templateType && filters.templateType !== 'all') backendFilters.templateType = filters.templateType;
|
||||
if (filters?.department && filters.department !== 'all') backendFilters.department = filters.department;
|
||||
if (filters?.initiator && filters.initiator !== 'all') backendFilters.initiator = filters.initiator;
|
||||
if (filters?.approver && filters.approver !== 'all') {
|
||||
@ -90,6 +91,7 @@ export async function fetchRequestsData({
|
||||
if (filters?.search) backendFilters.search = filters.search;
|
||||
if (filters?.status && filters.status !== 'all') backendFilters.status = filters.status;
|
||||
if (filters?.priority && filters.priority !== 'all') backendFilters.priority = filters.priority;
|
||||
if (filters?.templateType && filters.templateType !== 'all') backendFilters.templateType = filters.templateType;
|
||||
if (filters?.department && filters.department !== 'all') backendFilters.department = filters.department;
|
||||
if (filters?.initiator && filters.initiator !== 'all') backendFilters.initiator = filters.initiator;
|
||||
if (filters?.slaCompliance && filters.slaCompliance !== 'all') backendFilters.slaCompliance = filters.slaCompliance;
|
||||
|
||||
@ -30,6 +30,7 @@ export async function fetchUserParticipantRequestsData({
|
||||
if (filters?.search) backendFilters.search = filters.search;
|
||||
if (filters?.status && filters.status !== 'all') backendFilters.status = filters.status;
|
||||
if (filters?.priority && filters.priority !== 'all') backendFilters.priority = filters.priority;
|
||||
if (filters?.templateType && filters.templateType !== 'all') backendFilters.templateType = filters.templateType;
|
||||
if (filters?.department && filters.department !== 'all') backendFilters.department = filters.department;
|
||||
if (filters?.initiator && filters.initiator !== 'all') backendFilters.initiator = filters.initiator;
|
||||
if (filters?.approver && filters.approver !== 'all') {
|
||||
@ -101,6 +102,7 @@ export async function fetchAllRequestsForExport(filters?: RequestFilters): Promi
|
||||
if (filters?.search) backendFilters.search = filters.search;
|
||||
if (filters?.status && filters.status !== 'all') backendFilters.status = filters.status;
|
||||
if (filters?.priority && filters.priority !== 'all') backendFilters.priority = filters.priority;
|
||||
if (filters?.templateType && filters.templateType !== 'all') backendFilters.templateType = filters.templateType;
|
||||
if (filters?.department && filters.department !== 'all') backendFilters.department = filters.department;
|
||||
if (filters?.initiator && filters.initiator !== 'all') backendFilters.initiator = filters.initiator;
|
||||
if (filters?.approver && filters.approver !== 'all') {
|
||||
|
||||
@ -12,6 +12,7 @@ export interface RequestFilters {
|
||||
search?: string;
|
||||
status?: string;
|
||||
priority?: string;
|
||||
templateType?: string;
|
||||
slaCompliance?: string;
|
||||
department?: string;
|
||||
initiator?: string;
|
||||
|
||||
@ -196,6 +196,7 @@ class DashboardService {
|
||||
endDate?: string,
|
||||
status?: string,
|
||||
priority?: string,
|
||||
templateType?: string,
|
||||
department?: string,
|
||||
initiator?: string,
|
||||
approver?: string,
|
||||
@ -217,6 +218,9 @@ class DashboardService {
|
||||
if (priority && priority !== 'all') {
|
||||
params.priority = priority;
|
||||
}
|
||||
if (templateType && templateType !== 'all') {
|
||||
params.templateType = templateType;
|
||||
}
|
||||
if (department && department !== 'all') {
|
||||
params.department = department;
|
||||
}
|
||||
|
||||
@ -155,8 +155,8 @@ export async function createWorkflowMultipart(form: CreateWorkflowFromFormPayloa
|
||||
return { id: data?.requestId } as any;
|
||||
}
|
||||
|
||||
export async function listWorkflows(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; department?: string; initiator?: string; approver?: string; slaCompliance?: string; dateRange?: string; startDate?: string; endDate?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, department, initiator, approver, slaCompliance, dateRange, startDate, endDate } = params;
|
||||
export async function listWorkflows(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; templateType?: string; department?: string; initiator?: string; approver?: string; slaCompliance?: string; dateRange?: string; startDate?: string; endDate?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, templateType, department, initiator, approver, slaCompliance, dateRange, startDate, endDate } = params;
|
||||
const res = await apiClient.get('/workflows', {
|
||||
params: {
|
||||
page,
|
||||
@ -164,6 +164,7 @@ export async function listWorkflows(params: { page?: number; limit?: number; sea
|
||||
search,
|
||||
status,
|
||||
priority,
|
||||
templateType,
|
||||
department,
|
||||
initiator,
|
||||
approver,
|
||||
@ -178,8 +179,8 @@ export async function listWorkflows(params: { page?: number; limit?: number; sea
|
||||
|
||||
// List requests where user is a participant (not initiator) - for regular users' "All Requests" page
|
||||
// SEPARATE from listWorkflows (admin) to avoid interference
|
||||
export async function listParticipantRequests(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; department?: string; initiator?: string; approver?: string; approverType?: string; slaCompliance?: string; dateRange?: string; startDate?: string; endDate?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, department, initiator, approver, approverType, slaCompliance, dateRange, startDate, endDate } = params;
|
||||
export async function listParticipantRequests(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; templateType?: string; department?: string; initiator?: string; approver?: string; approverType?: string; slaCompliance?: string; dateRange?: string; startDate?: string; endDate?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, templateType, department, initiator, approver, approverType, slaCompliance, dateRange, startDate, endDate } = params;
|
||||
const res = await apiClient.get('/workflows/participant-requests', {
|
||||
params: {
|
||||
page,
|
||||
@ -187,6 +188,7 @@ export async function listParticipantRequests(params: { page?: number; limit?: n
|
||||
search,
|
||||
status,
|
||||
priority,
|
||||
templateType,
|
||||
department,
|
||||
initiator,
|
||||
approver,
|
||||
@ -195,7 +197,7 @@ export async function listParticipantRequests(params: { page?: number; limit?: n
|
||||
dateRange,
|
||||
startDate,
|
||||
endDate
|
||||
}
|
||||
}
|
||||
});
|
||||
// Response structure: { success, data: { data: [...], pagination: {...} } }
|
||||
return {
|
||||
@ -232,8 +234,8 @@ export async function listMyWorkflows(params: { page?: number; limit?: number; s
|
||||
}
|
||||
|
||||
// List requests where user is the initiator - for "My Requests" page
|
||||
export async function listMyInitiatedWorkflows(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; department?: string; slaCompliance?: string; dateRange?: string; startDate?: string; endDate?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, department, slaCompliance, dateRange, startDate, endDate } = params;
|
||||
export async function listMyInitiatedWorkflows(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; templateType?: string; department?: string; slaCompliance?: string; dateRange?: string; startDate?: string; endDate?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, templateType, department, slaCompliance, dateRange, startDate, endDate } = params;
|
||||
const res = await apiClient.get('/workflows/my-initiated', {
|
||||
params: {
|
||||
page,
|
||||
@ -241,6 +243,7 @@ export async function listMyInitiatedWorkflows(params: { page?: number; limit?:
|
||||
search,
|
||||
status,
|
||||
priority,
|
||||
templateType,
|
||||
department,
|
||||
slaCompliance,
|
||||
dateRange,
|
||||
@ -255,9 +258,9 @@ export async function listMyInitiatedWorkflows(params: { page?: number; limit?:
|
||||
};
|
||||
}
|
||||
|
||||
export async function listOpenForMe(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; sortBy?: string; sortOrder?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, sortBy, sortOrder } = params;
|
||||
const res = await apiClient.get('/workflows/open-for-me', { params: { page, limit, search, status, priority, sortBy, sortOrder } });
|
||||
export async function listOpenForMe(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; templateType?: string; sortBy?: string; sortOrder?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, templateType, sortBy, sortOrder } = params;
|
||||
const res = await apiClient.get('/workflows/open-for-me', { params: { page, limit, search, status, priority, templateType, sortBy, sortOrder } });
|
||||
// Response structure: { success, data: { data: [...], pagination: {...} } }
|
||||
return {
|
||||
data: res.data?.data?.data || res.data?.data || [],
|
||||
@ -265,9 +268,9 @@ export async function listOpenForMe(params: { page?: number; limit?: number; sea
|
||||
};
|
||||
}
|
||||
|
||||
export async function listClosedByMe(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; sortBy?: string; sortOrder?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, sortBy, sortOrder } = params;
|
||||
const res = await apiClient.get('/workflows/closed-by-me', { params: { page, limit, search, status, priority, sortBy, sortOrder } });
|
||||
export async function listClosedByMe(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; templateType?: string; sortBy?: string; sortOrder?: string } = {}) {
|
||||
const { page = 1, limit = 20, search, status, priority, templateType, sortBy, sortOrder } = params;
|
||||
const res = await apiClient.get('/workflows/closed-by-me', { params: { page, limit, search, status, priority, templateType, sortBy, sortOrder } });
|
||||
// Response structure: { success, data: { data: [...], pagination: {...} } }
|
||||
return {
|
||||
data: res.data?.data?.data || res.data?.data || [],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user