Re_Figma_Code/src/pages/Settings/Settings.tsx

402 lines
20 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import {
Settings as SettingsIcon,
Bell,
Shield,
Palette,
Lock,
Calendar,
Sliders
} from 'lucide-react';
import { setupPushNotifications } from '@/utils/pushNotifications';
import { useAuth, isAdmin as checkIsAdmin } from '@/contexts/AuthContext';
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';
export function Settings() {
const { user } = useAuth();
const isAdmin = checkIsAdmin(user);
const [showNotificationModal, setShowNotificationModal] = useState(false);
const [notificationSuccess, setNotificationSuccess] = useState(false);
const [notificationMessage, setNotificationMessage] = useState<string>();
const [isEnablingNotifications, setIsEnablingNotifications] = useState(false);
const handleEnableNotifications = async () => {
setIsEnablingNotifications(true);
setShowNotificationModal(false);
try {
// Check if notifications are supported
if (!('Notification' in window)) {
setNotificationSuccess(false);
setNotificationMessage('Notifications are not supported in this browser. Please use a modern browser like Chrome, Firefox, or Edge.');
setShowNotificationModal(true);
setIsEnablingNotifications(false);
return;
}
// Check current permission status BEFORE attempting to enable
let permission = Notification.permission;
// If permission was previously denied, show user-friendly instructions
if (permission === 'denied') {
setNotificationSuccess(false);
setNotificationMessage(
'Notification permission was previously denied. To enable notifications:\n\n' +
'1. Click the lock icon (🔒) or info icon () in your browser\'s address bar\n' +
'2. Find "Notifications" in the permissions list\n' +
'3. Change it from "Block" to "Allow"\n' +
'4. Refresh this page and try again\n\n' +
'Alternatively, you can enable notifications in your browser\'s site settings.'
);
setShowNotificationModal(true);
setIsEnablingNotifications(false);
return;
}
// If permission is 'default', request it first
if (permission === 'default') {
permission = await Notification.requestPermission();
// If user denied the permission request
if (permission === 'denied') {
setNotificationSuccess(false);
setNotificationMessage(
'Notification permission was denied. To enable notifications:\n\n' +
'1. Click the lock icon (🔒) or info icon () in your browser\'s address bar\n' +
'2. Find "Notifications" in the permissions list\n' +
'3. Change it from "Block" to "Allow"\n' +
'4. Refresh this page and try again'
);
setShowNotificationModal(true);
setIsEnablingNotifications(false);
return;
}
}
// Only proceed if permission is 'granted'
if (permission !== 'granted') {
setNotificationSuccess(false);
setNotificationMessage('Notification permission is required to enable push notifications. Please grant permission and try again.');
setShowNotificationModal(true);
setIsEnablingNotifications(false);
return;
}
// Permission is granted, proceed with setup
await setupPushNotifications();
setNotificationSuccess(true);
setNotificationMessage('Push notifications have been successfully enabled! You will now receive notifications for workflow updates, approvals, and TAT alerts.');
setShowNotificationModal(true);
} catch (error: any) {
console.error('[Settings] Error enabling notifications:', error);
setNotificationSuccess(false);
// Provide more specific error messages
const errorMessage = error?.message || 'Unknown error occurred';
setNotificationMessage(
errorMessage.includes('permission')
? 'Notification permission was denied. Please enable notifications in your browser settings and try again.'
: errorMessage.includes('Service worker')
? 'Service worker registration failed. Please refresh the page and try again.'
: errorMessage.includes('token')
? 'Authentication required. Please log in again and try enabling notifications.'
: `Unable to enable push notifications: ${errorMessage}`
);
setShowNotificationModal(true);
} finally {
setIsEnablingNotifications(false);
}
};
return (
<div className="min-h-screen pb-8">
<div className="max-w-7xl mx-auto space-y-6">
{/* Header Card */}
<Card className="relative overflow-hidden shadow-2xl border-0 rounded-2xl">
<div className="absolute inset-0 bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900"></div>
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top_right,_var(--tw-gradient-stops))] from-yellow-400/20 via-transparent to-transparent"></div>
<CardContent className="relative z-10 p-6 sm:p-8 lg:p-12">
<div className="flex items-center gap-4 sm:gap-6">
<div className="w-14 h-14 sm:w-16 sm:h-16 bg-gradient-to-br from-yellow-400 to-yellow-500 rounded-2xl flex items-center justify-center shadow-xl transform hover:scale-105 transition-transform">
<SettingsIcon className="w-7 h-7 sm:w-8 sm:h-8 text-slate-900" />
</div>
<div>
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-bold text-white mb-1 sm:mb-2">Settings</h1>
<p className="text-sm sm:text-base lg:text-lg text-gray-300">Manage your account and preferences</p>
</div>
</div>
</CardContent>
</Card>
{/* Tabs for Admin, Cards for Non-Admin */}
{isAdmin ? (
<Tabs defaultValue="user" className="w-full">
<TabsList className="grid w-full grid-cols-2 lg:grid-cols-4 mb-8 bg-slate-100 p-1 rounded-xl h-auto gap-1">
<TabsTrigger
value="user"
className="flex items-center justify-center gap-2 py-3 rounded-lg data-[state=active]:bg-white data-[state=active]:shadow-md transition-all"
>
<SettingsIcon className="w-4 h-4" />
<span className="hidden sm:inline">User Settings</span>
<span className="sm:hidden">User</span>
</TabsTrigger>
<TabsTrigger
value="roles"
className="flex items-center justify-center gap-2 py-3 rounded-lg data-[state=active]:bg-white data-[state=active]:shadow-md transition-all"
>
<Shield className="w-4 h-4" />
<span className="hidden sm:inline">User Roles</span>
<span className="sm:hidden">Roles</span>
</TabsTrigger>
<TabsTrigger
value="system"
className="flex items-center justify-center gap-2 py-3 rounded-lg data-[state=active]:bg-white data-[state=active]:shadow-md transition-all"
>
<Sliders className="w-4 h-4" />
<span className="hidden sm:inline">Configuration</span>
<span className="sm:hidden">Config</span>
</TabsTrigger>
<TabsTrigger
value="holidays"
className="flex items-center justify-center gap-2 py-3 rounded-lg data-[state=active]:bg-white data-[state=active]:shadow-md transition-all"
>
<Calendar className="w-4 h-4" />
<span className="hidden sm:inline">Holidays</span>
<span className="sm:hidden">Holidays</span>
</TabsTrigger>
</TabsList>
{/* Fixed width container to prevent layout shifts */}
<div className="w-full min-h-[600px]">
{/* User Settings Tab */}
<TabsContent value="user" className="mt-0 space-y-0">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 sm:gap-6">
{/* Notification Settings */}
<Card className="shadow-lg hover:shadow-xl transition-all duration-300 border-0 rounded-md group">
<CardHeader className="pb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-gradient-to-br from-slate-600 to-slate-700 rounded-md shadow-md group-hover:shadow-lg transition-shadow">
<Bell className="h-5 w-5 text-white" />
</div>
<div>
<CardTitle className="text-lg font-semibold text-gray-900">Notifications</CardTitle>
<CardDescription className="text-sm text-gray-600">Manage notification preferences</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<Button
onClick={handleEnableNotifications}
disabled={isEnablingNotifications}
className="w-full bg-re-green hover:bg-re-green/90 text-white shadow-md hover:shadow-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed"
>
<Bell className={`w-4 h-4 mr-2 ${isEnablingNotifications ? 'animate-pulse' : ''}`} />
{isEnablingNotifications ? 'Enabling...' : 'Enable Push Notifications'}
</Button>
</div>
</CardContent>
</Card>
{/* Security Settings */}
<Card className="shadow-lg hover:shadow-xl transition-all duration-300 border-0 rounded-md group">
<CardHeader className="pb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-gradient-to-br from-slate-600 to-slate-700 rounded-md shadow-md group-hover:shadow-lg transition-shadow">
<Lock className="h-5 w-5 text-white" />
</div>
<div>
<CardTitle className="text-lg font-semibold text-gray-900">Security</CardTitle>
<CardDescription className="text-sm text-gray-600">Password and security settings</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="p-4 bg-gradient-to-br from-gray-50 to-gray-100 rounded-md border border-gray-200">
<p className="text-sm text-gray-600 text-center">Security settings will be available soon</p>
</div>
</div>
</CardContent>
</Card>
{/* Appearance Settings */}
<Card className="shadow-lg hover:shadow-xl transition-all duration-300 border-0 rounded-md group">
<CardHeader className="pb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-gradient-to-br from-slate-600 to-slate-700 rounded-md shadow-md group-hover:shadow-lg transition-shadow">
<Palette className="h-5 w-5 text-white" />
</div>
<div>
<CardTitle className="text-lg font-semibold text-gray-900">Appearance</CardTitle>
<CardDescription className="text-sm text-gray-600">Theme and display preferences</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="p-4 bg-gradient-to-br from-gray-50 to-gray-100 rounded-md border border-gray-200">
<p className="text-sm text-gray-600 text-center">Appearance settings will be available soon</p>
</div>
</div>
</CardContent>
</Card>
{/* Preferences */}
<Card className="shadow-lg hover:shadow-xl transition-all duration-300 border-0 rounded-md group">
<CardHeader className="pb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-gradient-to-br from-slate-600 to-slate-700 rounded-md shadow-md group-hover:shadow-lg transition-shadow">
<Shield className="h-5 w-5 text-white" />
</div>
<div>
<CardTitle className="text-lg font-semibold text-gray-900">Preferences</CardTitle>
<CardDescription className="text-sm text-gray-600">Application preferences</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="p-4 bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl border border-gray-200">
<p className="text-sm text-gray-600 text-center">User preferences will be available soon</p>
</div>
</div>
</CardContent>
</Card>
</div>
</TabsContent>
{/* User Roles Tab (Admin Only) */}
<TabsContent value="roles" className="mt-0">
<UserRoleManager />
</TabsContent>
{/* System Configuration Tab (Admin Only) */}
<TabsContent value="system" className="mt-0">
<ConfigurationManager />
</TabsContent>
{/* Holiday Calendar Tab (Admin Only) */}
<TabsContent value="holidays" className="mt-0">
<HolidayManager />
</TabsContent>
</div>
</Tabs>
) : (
<>
{/* Non-Admin User Settings Only */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 sm:gap-6">
{/* Notification Settings */}
<Card className="shadow-lg hover:shadow-xl transition-all duration-300 border-0 rounded-md group">
<CardHeader className="pb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-gradient-to-br from-slate-600 to-slate-700 rounded-md shadow-md group-hover:shadow-lg transition-shadow">
<Bell className="h-5 w-5 text-white" />
</div>
<div>
<CardTitle className="text-lg font-semibold text-gray-900">Notifications</CardTitle>
<CardDescription className="text-sm text-gray-600">Manage notification preferences</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<Button
onClick={handleEnableNotifications}
disabled={isEnablingNotifications}
className="w-full bg-re-green hover:bg-re-green/90 text-white shadow-md hover:shadow-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed"
>
<Bell className={`w-4 h-4 mr-2 ${isEnablingNotifications ? 'animate-pulse' : ''}`} />
{isEnablingNotifications ? 'Enabling...' : 'Enable Push Notifications'}
</Button>
</div>
</CardContent>
</Card>
{/* Security Settings */}
<Card className="shadow-lg hover:shadow-xl transition-all duration-300 border-0 rounded-md group">
<CardHeader className="pb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-gradient-to-br from-slate-600 to-slate-700 rounded-md shadow-md group-hover:shadow-lg transition-shadow">
<Lock className="h-5 w-5 text-white" />
</div>
<div>
<CardTitle className="text-lg font-semibold text-gray-900">Security</CardTitle>
<CardDescription className="text-sm text-gray-600">Password and security settings</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="p-4 bg-gradient-to-br from-gray-50 to-gray-100 rounded-md border border-gray-200">
<p className="text-sm text-gray-600 text-center">Security settings will be available soon</p>
</div>
</div>
</CardContent>
</Card>
{/* Appearance Settings */}
<Card className="shadow-lg hover:shadow-xl transition-all duration-300 border-0 rounded-md group">
<CardHeader className="pb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-gradient-to-br from-slate-600 to-slate-700 rounded-md shadow-md group-hover:shadow-lg transition-shadow">
<Palette className="h-5 w-5 text-white" />
</div>
<div>
<CardTitle className="text-lg font-semibold text-gray-900">Appearance</CardTitle>
<CardDescription className="text-sm text-gray-600">Theme and display preferences</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="p-4 bg-gradient-to-br from-gray-50 to-gray-100 rounded-md border border-gray-200">
<p className="text-sm text-gray-600 text-center">Appearance settings will be available soon</p>
</div>
</div>
</CardContent>
</Card>
{/* Preferences */}
<Card className="shadow-lg hover:shadow-xl transition-all duration-300 border-0 rounded-md group">
<CardHeader className="pb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-gradient-to-br from-slate-600 to-slate-700 rounded-md shadow-md group-hover:shadow-lg transition-shadow">
<Shield className="h-5 w-5 text-white" />
</div>
<div>
<CardTitle className="text-lg font-semibold text-gray-900">Preferences</CardTitle>
<CardDescription className="text-sm text-gray-600">Application preferences</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="p-4 bg-gradient-to-br from-gray-50 to-gray-100 rounded-md border border-gray-200">
<p className="text-sm text-gray-600 text-center">User preferences will be available soon</p>
</div>
</div>
</CardContent>
</Card>
</div>
</>
)}
</div>
<NotificationStatusModal
open={showNotificationModal}
onClose={() => setShowNotificationModal(false)}
success={notificationSuccess}
message={notificationMessage}
/>
</div>
);
}