- Maximum character limit for AI-generated conclusion remarks (100-2000 characters)
+ Maximum character length for AI-generated conclusion remarks (500-5000 characters)
+ These preferences control which notification channels you receive alerts through.
+ You'll still receive critical notifications regardless of these settings.
+
+ These preferences control which notification channels you receive alerts through.
+ You'll still receive critical notifications regardless of these settings.
+
diff --git a/src/pages/ApproverPerformance/components/ApproverPerformanceFilters.tsx b/src/pages/ApproverPerformance/components/ApproverPerformanceFilters.tsx
index b39b5d3..3734fd3 100644
--- a/src/pages/ApproverPerformance/components/ApproverPerformanceFilters.tsx
+++ b/src/pages/ApproverPerformance/components/ApproverPerformanceFilters.tsx
@@ -136,9 +136,12 @@ export function ApproverPerformanceFilters({
+ All TimeTodayThis WeekThis Month
+ Last 7 Days
+ Last 30 DaysCustom Range
@@ -219,7 +222,7 @@ export function ApproverPerformanceFilters({
onTempStartDateChange(customStartDate);
onTempEndDateChange(customEndDate);
if (!customStartDate || !customEndDate) {
- onDateRangeChange('month');
+ onDateRangeChange('all');
}
}}
data-testid="cancel-date-button"
diff --git a/src/pages/ApproverPerformance/components/ApproverPerformanceStatsCards.tsx b/src/pages/ApproverPerformance/components/ApproverPerformanceStatsCards.tsx
index 91aca29..330aaaa 100644
--- a/src/pages/ApproverPerformance/components/ApproverPerformanceStatsCards.tsx
+++ b/src/pages/ApproverPerformance/components/ApproverPerformanceStatsCards.tsx
@@ -6,20 +6,16 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress';
import { CheckCircle, Clock, Target, Timer } from 'lucide-react';
import type { ApproverPerformance } from '@/services/dashboard.service';
-import type { ApproverPerformanceStats } from '../types/approverPerformance.types';
interface ApproverPerformanceStatsCardsProps {
- approverStats: ApproverPerformance | null;
- calculatedStats: ApproverPerformanceStats;
+ approverStats: ApproverPerformance;
}
export function ApproverPerformanceStatsCards({
- approverStats,
- calculatedStats
+ approverStats
}: ApproverPerformanceStatsCardsProps) {
- if (!approverStats) return null;
- const tatCompliance = approverStats?.tatCompliancePercent ?? calculatedStats.tatComplianceRate;
+ const tatCompliance = approverStats?.tatCompliancePercent ?? 0;
return (
diff --git a/src/pages/ApproverPerformance/hooks/useApproverPerformanceData.ts b/src/pages/ApproverPerformance/hooks/useApproverPerformanceData.ts
index 365ff95..fe5d0b5 100644
--- a/src/pages/ApproverPerformance/hooks/useApproverPerformanceData.ts
+++ b/src/pages/ApproverPerformance/hooks/useApproverPerformanceData.ts
@@ -42,29 +42,40 @@ export function useApproverPerformanceData({
const isInitialMount = useRef(true);
- // Fetch approver performance stats
+ // Fetch stats for this approver (ONLY on date/priority/SLA changes)
const fetchApproverStats = useCallback(async () => {
- if (!approverId) return;
+ if (!approverId) {
+ return;
+ }
try {
- const result = await dashboardService.getApproverPerformance(
- dateRange,
- 1,
- 100,
+ const dateRangeToSend = dateRange === 'all' ? undefined : dateRange;
+ console.log('[Stats] Fetching with filters:', {
+ dateRange: dateRangeToSend,
customStartDate,
- customEndDate
+ customEndDate,
+ priority: priorityFilter,
+ sla: slaComplianceFilter
+ });
+
+ const stats = await dashboardService.getSingleApproverStats(
+ approverId,
+ dateRangeToSend,
+ customStartDate,
+ customEndDate,
+ priorityFilter !== 'all' ? priorityFilter : undefined,
+ slaComplianceFilter !== 'all' ? slaComplianceFilter : undefined
);
- const approver = result.performance.find((p: ApproverPerformance) => p.approverId === approverId);
- if (approver) {
- setApproverStats(approver);
- }
+ console.log('[Stats] Received stats:', stats);
+ setApproverStats(stats);
} catch (error) {
- console.error('Failed to fetch approver stats:', error);
+ console.error('[ApproverPerformance] Failed to fetch approver stats:', error);
+ setApproverStats(null);
}
- }, [approverId, dateRange, customStartDate, customEndDate]);
-
- // Fetch requests for this approver
+ }, [approverId, dateRange, customStartDate, customEndDate, priorityFilter, slaComplianceFilter]);
+
+ // Fetch requests for this approver (on ANY filter change)
const fetchRequests = useCallback(async (page: number = 1) => {
if (!approverId) {
setLoading(false);
@@ -79,7 +90,7 @@ export function useApproverPerformanceData({
approverId,
page,
itemsPerPage,
- dateRange,
+ dateRange === 'all' ? undefined : dateRange,
customStartDate,
customEndDate,
statusFilter !== 'all' ? statusFilter : undefined,
@@ -91,23 +102,8 @@ export function useApproverPerformanceData({
setRequests(result.requests);
setTotalRecords(result.pagination.totalRecords);
setTotalPages(result.pagination.totalPages);
- setCurrentPage(page);
-
- // For stats calculation, fetch ALL data (without pagination)
- const statsResult = await dashboardService.getRequestsByApprover(
- approverId,
- 1,
- 10000,
- dateRange,
- customStartDate,
- customEndDate,
- statusFilter !== 'all' ? statusFilter : undefined,
- priorityFilter !== 'all' ? priorityFilter : undefined,
- slaComplianceFilter !== 'all' ? slaComplianceFilter : undefined,
- searchTerm || undefined
- );
-
- setAllFilteredRequests(statsResult.requests);
+ setCurrentPage(result.pagination.currentPage);
+ setAllFilteredRequests(result.requests);
} catch (error) {
console.error('Failed to fetch requests:', error);
} finally {
@@ -130,15 +126,29 @@ export function useApproverPerformanceData({
useEffect(() => {
if (isInitialMount.current) {
isInitialMount.current = false;
- fetchApproverStats();
- fetchRequests(1);
+ fetchApproverStats(); // Fetch stats once on mount
+ fetchRequests(1); // Fetch requests once on mount
}
}, []); // Only run on mount
- // Refetch when filters change
+ // Refetch stats ONLY when date/priority/SLA changes (NOT status or search)
useEffect(() => {
if (!isInitialMount.current) {
fetchApproverStats();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [
+ dateRange,
+ customStartDate,
+ customEndDate,
+ priorityFilter,
+ slaComplianceFilter
+ // NO statusFilter, NO searchTerm - stats don't depend on these
+ ]);
+
+ // Refetch requests when ANY filter changes (including status and search)
+ useEffect(() => {
+ if (!isInitialMount.current) {
fetchRequests(1);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -150,35 +160,18 @@ export function useApproverPerformanceData({
priorityFilter,
slaComplianceFilter,
searchTerm
- // fetchApproverStats and fetchRequests excluded to prevent infinite loops
]);
const handleRefresh = useCallback(() => {
setRefreshing(true);
- fetchApproverStats();
- fetchRequests(1);
+ fetchApproverStats(); // Refresh stats
+ fetchRequests(1); // Refresh requests
}, [fetchApproverStats, fetchRequests]);
const handlePageChange = useCallback((page: number) => {
- setCurrentPage(page);
- // Use client-side pagination since we have allFilteredRequests
- const startIdx = (page - 1) * itemsPerPage;
- const endIdx = startIdx + itemsPerPage;
- const paginatedRequests = allFilteredRequests.slice(startIdx, endIdx);
- setRequests(paginatedRequests);
- }, [allFilteredRequests, itemsPerPage]);
-
- // Update paginated data when allFilteredRequests changes
- useEffect(() => {
- const startIdx = (currentPage - 1) * itemsPerPage;
- const endIdx = startIdx + itemsPerPage;
- const paginatedRequests = allFilteredRequests.slice(startIdx, endIdx);
- setRequests(paginatedRequests);
- setTotalPages(Math.ceil(allFilteredRequests.length / itemsPerPage));
- if (currentPage > Math.ceil(allFilteredRequests.length / itemsPerPage) && allFilteredRequests.length > 0) {
- setCurrentPage(1);
- }
- }, [allFilteredRequests, currentPage, itemsPerPage]);
+ // Use server-side pagination - fetch from backend
+ fetchRequests(page);
+ }, [fetchRequests]);
return {
requests,
diff --git a/src/pages/ApproverPerformance/hooks/useApproverPerformanceFilters.ts b/src/pages/ApproverPerformance/hooks/useApproverPerformanceFilters.ts
index 7eb0177..549bc39 100644
--- a/src/pages/ApproverPerformance/hooks/useApproverPerformanceFilters.ts
+++ b/src/pages/ApproverPerformance/hooks/useApproverPerformanceFilters.ts
@@ -13,7 +13,7 @@ export function useApproverPerformanceFilters() {
const [statusFilter, setStatusFilter] = useState(searchParams.get('status') || 'all');
const [priorityFilter, setPriorityFilter] = useState(searchParams.get('priority') || 'all');
const [slaComplianceFilter, setSlaComplianceFilter] = useState(searchParams.get('slaCompliance') || 'all');
- const [dateRange, setDateRange] = useState((searchParams.get('dateRange') as DateRange) || 'month');
+ const [dateRange, setDateRange] = useState((searchParams.get('dateRange') as DateRange) || 'all');
const [customStartDate, setCustomStartDate] = useState(
searchParams.get('startDate') ? new Date(searchParams.get('startDate')!) : undefined
);
@@ -29,7 +29,7 @@ export function useApproverPerformanceFilters() {
setStatusFilter('all');
setPriorityFilter('all');
setSlaComplianceFilter('all');
- setDateRange('month');
+ setDateRange('all');
setCustomStartDate(undefined);
setCustomEndDate(undefined);
setTempCustomStartDate(undefined);
diff --git a/src/pages/CreateRequest/utils/payloadBuilders.ts b/src/pages/CreateRequest/utils/payloadBuilders.ts
index 5688757..7b55d8a 100644
--- a/src/pages/CreateRequest/utils/payloadBuilders.ts
+++ b/src/pages/CreateRequest/utils/payloadBuilders.ts
@@ -17,7 +17,7 @@ import { buildApprovalLevels } from './approvalLevelBuilders';
export function buildCreatePayload(
formData: FormData,
selectedTemplate: RequestTemplate | null,
- user: any
+ _user: any
): CreateWorkflowPayload {
// Filter out spectators who are also approvers (backend will handle validation)
const approverEmails = new Set(
@@ -41,11 +41,13 @@ export function buildCreatePayload(
tat: a?.tat || '',
tatType: a?.tatType || 'hours',
})),
- spectators: filteredSpectators.map((s) => ({
+ spectators: filteredSpectators.map((s: any) => ({
+ userId: s?.userId || '',
+ name: s?.name || '',
email: s?.email || '',
})),
- // Note: participants array is auto-generated by backend
- // No need to send it from frontend
+ ccList: [], // Auto-generated by backend
+ participants: [], // Auto-generated by backend from approvers and spectators
};
}
@@ -55,7 +57,7 @@ export function buildCreatePayload(
*/
export function buildUpdatePayload(
formData: FormData,
- user: any,
+ _user: any,
documentsToDelete: string[]
): UpdateWorkflowPayload {
const approvalLevels = buildApprovalLevels(
@@ -68,7 +70,7 @@ export function buildUpdatePayload(
description: formData.description,
priority: formData.priority === 'express' ? 'EXPRESS' : 'STANDARD',
approvalLevels,
- // Note: participants array is auto-generated by backend
+ participants: [], // Auto-generated by backend from approval levels
deleteDocumentIds: documentsToDelete.length > 0 ? documentsToDelete : undefined,
};
}
diff --git a/src/pages/Dashboard/components/DashboardFiltersBar.tsx b/src/pages/Dashboard/components/DashboardFiltersBar.tsx
index 331699b..2c1b010 100644
--- a/src/pages/Dashboard/components/DashboardFiltersBar.tsx
+++ b/src/pages/Dashboard/components/DashboardFiltersBar.tsx
@@ -70,9 +70,12 @@ export function DashboardFiltersBar({
+ All TimeTodayThis WeekThis Month
+ Last 7 Days
+ Last 30 DaysCustom Range
@@ -169,9 +172,13 @@ export function DashboardFiltersBar({
+ All TimeTodayThis WeekThis Month
+ Last 7 Days
+ Last 30 Days
+ Custom Range
diff --git a/src/pages/Dashboard/components/sections/TATBreachReport.tsx b/src/pages/Dashboard/components/sections/TATBreachReport.tsx
index 46d19c7..b950782 100644
--- a/src/pages/Dashboard/components/sections/TATBreachReport.tsx
+++ b/src/pages/Dashboard/components/sections/TATBreachReport.tsx
@@ -11,6 +11,7 @@ import type { CriticalAlertData } from '@/components/dashboard/CriticalAlertCard
import { Pagination } from '@/components/common/Pagination';
import { formatBreachTime } from '../../utils/dashboardCalculations';
import { KPIClickFilters } from '../../components/types/dashboard.types';
+import { formatDateRangeDescription } from '../../utils/dateRangeFormatter';
interface TATBreachReportProps {
breachedRequests: (CriticalRequest | CriticalAlertData)[];
@@ -56,7 +57,7 @@ export function TATBreachReport({
TAT Breach Report
- Requests that breached defined turnaround time
+ Requests that breached TAT - {formatDateRangeDescription(dateRange, customStartDate, customEndDate)}
diff --git a/src/pages/Dashboard/hooks/useDashboardFilters.ts b/src/pages/Dashboard/hooks/useDashboardFilters.ts
index 26b23e3..8723aaa 100644
--- a/src/pages/Dashboard/hooks/useDashboardFilters.ts
+++ b/src/pages/Dashboard/hooks/useDashboardFilters.ts
@@ -6,7 +6,7 @@ import { useState, useCallback } from 'react';
import { DateRange } from '@/services/dashboard.service';
export function useDashboardFilters() {
- const [dateRange, setDateRange] = useState('month');
+ const [dateRange, setDateRange] = useState('all');
const [customStartDate, setCustomStartDate] = useState(undefined);
const [customEndDate, setCustomEndDate] = useState(undefined);
const [showCustomDatePicker, setShowCustomDatePicker] = useState(false);
@@ -42,7 +42,7 @@ export function useDashboardFilters() {
setCustomStartDate(undefined);
setCustomEndDate(undefined);
setShowCustomDatePicker(false);
- setDateRange('month');
+ setDateRange('all');
}, []);
return {
diff --git a/src/pages/Dashboard/utils/dateRangeFormatter.ts b/src/pages/Dashboard/utils/dateRangeFormatter.ts
new file mode 100644
index 0000000..e78694a
--- /dev/null
+++ b/src/pages/Dashboard/utils/dateRangeFormatter.ts
@@ -0,0 +1,61 @@
+import { format } from 'date-fns';
+import type { DateRange } from '@/services/dashboard.service';
+
+/**
+ * Format date range for display in dashboard components
+ * Returns a human-readable string describing the active date filter
+ */
+export function formatDateRangeText(
+ dateRange: DateRange,
+ customStartDate?: Date,
+ customEndDate?: Date,
+ prefix: string = 'for'
+): string {
+ if (dateRange === 'custom' && customStartDate && customEndDate) {
+ return `${prefix} ${format(customStartDate, 'MMM d, yyyy')} - ${format(customEndDate, 'MMM d, yyyy')}`;
+ }
+
+ const rangeMap: Record = {
+ 'all': '(All Time)',
+ 'today': `${prefix} Today`,
+ 'week': `${prefix} This Week`,
+ 'month': `${prefix} This Month`,
+ 'quarter': `${prefix} This Quarter`,
+ 'year': `${prefix} This Year`,
+ 'last30days': `${prefix} Last 30 Days`,
+ 'custom': `${prefix} Custom Range`
+ };
+
+ return rangeMap[dateRange] || `${prefix} Selected Period`;
+}
+
+/**
+ * Format date range for card descriptions
+ */
+export function formatDateRangeDescription(
+ dateRange: DateRange,
+ customStartDate?: Date,
+ customEndDate?: Date
+): string {
+ if (dateRange === 'all') {
+ return 'All historical data';
+ }
+
+ if (dateRange === 'custom' && customStartDate && customEndDate) {
+ return `Data from ${format(customStartDate, 'MMM d, yyyy')} to ${format(customEndDate, 'MMM d, yyyy')}`;
+ }
+
+ const rangeMap: Record = {
+ 'all': 'All historical data',
+ 'today': "Today's data",
+ 'week': 'This week data',
+ 'month': 'This month data',
+ 'quarter': 'This quarter data',
+ 'year': 'This year data',
+ 'last30days': 'Last 30 days data',
+ 'custom': 'Custom date range'
+ };
+
+ return rangeMap[dateRange] || 'Filtered data';
+}
+
diff --git a/src/pages/RequestDetail/components/QuickActionsSidebar.tsx b/src/pages/RequestDetail/components/QuickActionsSidebar.tsx
index 4271f44..8269c80 100644
--- a/src/pages/RequestDetail/components/QuickActionsSidebar.tsx
+++ b/src/pages/RequestDetail/components/QuickActionsSidebar.tsx
@@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { UserPlus, Eye, CheckCircle, XCircle, Share2, Pause, Play, AlertCircle } from 'lucide-react';
import { getSharedRecipients, type SharedRecipient } from '@/services/summaryApi';
+import { useAuth } from '@/contexts/AuthContext';
interface QuickActionsSidebarProps {
request: any;
@@ -42,16 +43,22 @@ export function QuickActionsSidebar({
summaryId,
refreshTrigger,
}: QuickActionsSidebarProps) {
+ const { user } = useAuth();
const [sharedRecipients, setSharedRecipients] = useState([]);
const [loadingRecipients, setLoadingRecipients] = useState(false);
const isClosed = request?.status === 'closed';
const isPaused = request?.pauseInfo?.isPaused || false;
+ const pausedByUserId = request?.pauseInfo?.pausedBy?.userId;
+ const currentUserId = (user as any)?.userId || '';
+
// Both approver AND initiator can pause (when not already paused and not closed)
const canPause = !isPaused && !isClosed && (currentApprovalLevel || isInitiator);
- // Both approver AND initiator can resume directly
+
+ // Resume: Can be done by the person who paused OR by both initiator and approver
const canResume = isPaused && onResume && (currentApprovalLevel || isInitiator);
- // Retrigger is no longer needed since initiator can resume directly
- const canRetrigger = false; // Disabled - kept for backwards compatibility
+
+ // Retrigger: Only for initiator when approver paused (initiator asks approver to resume)
+ const canRetrigger = isPaused && isInitiator && pausedByUserId && pausedByUserId !== currentUserId && onRetrigger;
// Fetch shared recipients when request is closed and summaryId is available
useEffect(() => {
diff --git a/src/pages/RequestDetail/components/tabs/OverviewTab.tsx b/src/pages/RequestDetail/components/tabs/OverviewTab.tsx
index 23bf306..aa94b26 100644
--- a/src/pages/RequestDetail/components/tabs/OverviewTab.tsx
+++ b/src/pages/RequestDetail/components/tabs/OverviewTab.tsx
@@ -8,6 +8,7 @@ import { RichTextEditor } from '@/components/ui/rich-text-editor';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { FormattedDescription } from '@/components/common/FormattedDescription';
import { User, FileText, Mail, Phone, CheckCircle, RefreshCw, Loader2, Pause, Play, AlertCircle } from 'lucide-react';
+import { useAuth } from '@/contexts/AuthContext';
import { formatDateTime, formatDateShort } from '@/utils/dateFormatter';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
@@ -48,18 +49,21 @@ export function OverviewTab({
onResume,
onRetrigger,
currentUserIsApprover = false,
- pausedByUserId,
- currentUserId,
+ pausedByUserId: _pausedByUserId,
+ currentUserId: _currentUserId,
}: OverviewTabProps) {
void _onPause; // Marked as intentionally unused - available for future use
- void pausedByUserId; // Kept for backwards compatibility
- void currentUserId; // Kept for backwards compatibility
+ const { user } = useAuth();
const pauseInfo = request?.pauseInfo;
const isPaused = pauseInfo?.isPaused || false;
- // Both approver AND initiator can resume directly
- const canResume = isPaused && (currentUserIsApprover || isInitiator);
- // Retrigger is no longer needed since initiator can resume directly
- const canRetrigger = false; // Disabled - kept for backwards compatibility
+ const pausedByUserId = pauseInfo?.pausedBy?.userId;
+ const currentUserId = (user as any)?.userId || '';
+
+ // Resume: Can be done by both initiator and approver
+ const canResume = isPaused && onResume && (currentUserIsApprover || isInitiator);
+
+ // Retrigger: Only for initiator when approver paused (initiator asks approver to resume)
+ const canRetrigger = isPaused && isInitiator && pausedByUserId && pausedByUserId !== currentUserId && onRetrigger;
return (
{/* Request Initiator Card */}
diff --git a/src/pages/Requests/Requests.tsx b/src/pages/Requests/Requests.tsx
index 5b50d9d..82e10e9 100644
--- a/src/pages/Requests/Requests.tsx
+++ b/src/pages/Requests/Requests.tsx
@@ -319,8 +319,8 @@ export function Requests({ onViewRequest }: RequestsProps) {
slaCompliance: filters.slaComplianceFilter !== 'all' ? filters.slaComplianceFilter : undefined
};
// All Requests (admin/normal user) should always have a date range
- // Default to 'month' if no date range is selected
- const statsDateRange = filters.dateRange || 'month';
+ // Default to 'all' if no date range is selected
+ const statsDateRange = filters.dateRange || 'all';
fetchBackendStatsRef.current(
statsDateRange,
@@ -660,9 +660,12 @@ export function Requests({ onViewRequest }: RequestsProps) {
+ All TimeTodayThis WeekThis Month
+ Last 7 Days
+ Last 30 DaysCustom Range
diff --git a/src/pages/Requests/UserAllRequests.tsx b/src/pages/Requests/UserAllRequests.tsx
index 7e6880f..b28a180 100644
--- a/src/pages/Requests/UserAllRequests.tsx
+++ b/src/pages/Requests/UserAllRequests.tsx
@@ -580,9 +580,12 @@ export function UserAllRequests({ onViewRequest }: RequestsProps) {
+ All TimeTodayThis WeekThis Month
+ Last 7 Days
+ Last 30 DaysCustom Range
diff --git a/src/pages/Requests/hooks/useRequestsFilters.ts b/src/pages/Requests/hooks/useRequestsFilters.ts
index 28b3d8e..46dc1fe 100644
--- a/src/pages/Requests/hooks/useRequestsFilters.ts
+++ b/src/pages/Requests/hooks/useRequestsFilters.ts
@@ -20,7 +20,7 @@ export function useRequestsFilters() {
const [approverFilterType, setApproverFilterType] = useState<'current' | 'any'>(
searchParams.get('approverType') === 'any' ? 'any' : 'current'
);
- const [dateRange, setDateRange] = useState((searchParams.get('dateRange') as DateRange) || 'month');
+ const [dateRange, setDateRange] = useState((searchParams.get('dateRange') as DateRange) || 'all');
const [customStartDate, setCustomStartDate] = useState(
searchParams.get('startDate') ? new Date(searchParams.get('startDate')!) : undefined
);
@@ -101,7 +101,7 @@ export function useRequestsFilters() {
setInitiatorFilter('all');
setApproverFilter('all');
setApproverFilterType('current');
- setDateRange('month');
+ setDateRange('all');
setCustomStartDate(undefined);
setCustomEndDate(undefined);
setShowCustomDatePicker(false);
@@ -138,7 +138,7 @@ export function useRequestsFilters() {
departmentFilter !== 'all' ||
initiatorFilter !== 'all' ||
approverFilter !== 'all' ||
- dateRange !== 'month' ||
+ dateRange !== 'all' ||
customStartDate ||
customEndDate
);
diff --git a/src/pages/Settings/Settings.tsx b/src/pages/Settings/Settings.tsx
index 2992e5c..8e50ab5 100644
--- a/src/pages/Settings/Settings.tsx
+++ b/src/pages/Settings/Settings.tsx
@@ -16,7 +16,9 @@ import { ConfigurationManager } from '@/components/admin/ConfigurationManager';
import { HolidayManager } from '@/components/admin/HolidayManager';
import { UserRoleManager } from '@/components/admin/UserRoleManager';
import { NotificationStatusModal } from '@/components/settings/NotificationStatusModal';
-import { useState } from 'react';
+import { NotificationPreferencesModal } from '@/components/settings/NotificationPreferencesModal';
+import { useState, useEffect } from 'react';
+import { getUserSubscriptions } from '@/services/notificationApi';
export function Settings() {
const { user } = useAuth();
@@ -25,6 +27,26 @@ export function Settings() {
const [notificationSuccess, setNotificationSuccess] = useState(false);
const [notificationMessage, setNotificationMessage] = useState();
const [isEnablingNotifications, setIsEnablingNotifications] = useState(false);
+ const [showPreferencesModal, setShowPreferencesModal] = useState(false);
+ const [hasSubscription, setHasSubscription] = useState(false);
+ const [checkingSubscription, setCheckingSubscription] = useState(true);
+
+ useEffect(() => {
+ checkSubscriptionStatus();
+ }, []);
+
+ const checkSubscriptionStatus = async () => {
+ try {
+ setCheckingSubscription(true);
+ const subscriptions = await getUserSubscriptions();
+ setHasSubscription(subscriptions.length > 0);
+ } catch (error) {
+ console.error('Failed to check subscription status:', error);
+ setHasSubscription(false);
+ } finally {
+ setCheckingSubscription(false);
+ }
+ };
const handleEnableNotifications = async () => {
setIsEnablingNotifications(true);
@@ -93,6 +115,8 @@ export function Settings() {
setNotificationSuccess(true);
setNotificationMessage('Push notifications have been successfully enabled! You will now receive notifications for workflow updates, approvals, and TAT alerts.');
setShowNotificationModal(true);
+ // Recheck subscription status
+ await checkSubscriptionStatus();
} catch (error: any) {
console.error('[Settings] Error enabling notifications:', error);
setNotificationSuccess(false);
@@ -177,7 +201,7 @@ export function Settings() {
{/* User Settings Tab */}