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