import { useState, useEffect, useContext } from 'react' import { Settings as SettingsIcon, Play, CheckCircle, Languages, Coins, Upload, Tag, Plus, Pencil, Trash2, X, Mail } from 'lucide-react' import { api } from '../utils/api' import { useLanguage } from '../i18n/LanguageContext' import { useToast } from '../components/ToastContainer' import { CURRENCIES } from '../i18n/LanguageContext' import { AppContext } from '../App' import { useAuth } from '../contexts/AuthContext' import Modal from '../components/Modal' const ROLE_COLORS = [ '#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899', '#06B6D4', '#F97316', '#6366F1', '#14B8A6', ] export default function Settings() { const { t, lang, setLang, currency, setCurrency } = useLanguage() const toast = useToast() const { user } = useAuth() const { roles, loadRoles } = useContext(AppContext) const [restarting, setRestarting] = useState(false) const [success, setSuccess] = useState(false) const [maxSizeMB, setMaxSizeMB] = useState(50) const [sizeSaving, setSizeSaving] = useState(false) const [sizeSaved, setSizeSaved] = useState(false) const [ceoEmail, setCeoEmail] = useState('') const [ceoSaving, setCeoSaving] = useState(false) const [ceoSaved, setCeoSaved] = useState(false) useEffect(() => { api.get('/settings/app').then(s => { setMaxSizeMB(s.uploadMaxSizeMB || 50) if (s.ceoEmail) setCeoEmail(s.ceoEmail) }).catch(() => {}) }, []) const handleSaveMaxSize = async () => { setSizeSaving(true) setSizeSaved(false) try { const res = await api.patch('/settings/app', { uploadMaxSizeMB: maxSizeMB }) setMaxSizeMB(res.uploadMaxSizeMB) setSizeSaved(true) setTimeout(() => setSizeSaved(false), 2000) } catch (err) { toast.error(err.message || t('settings.saveFailed')) } finally { setSizeSaving(false) } } const handleRestartTutorial = async () => { setRestarting(true) setSuccess(false) try { await api.patch('/users/me/tutorial', { completed: false }) setSuccess(true) setTimeout(() => { window.location.reload() // Reload to trigger tutorial }, 1500) } catch (err) { console.error('Failed to restart tutorial:', err) toast.error(t('settings.restartTutorialFailed')) } finally { setRestarting(false) } } return (

{t('settings.preferences')}

{/* General Settings */}

{t('settings.general')}

{/* Language Selector */}
{/* Currency Selector */}

{t('settings.currencyHint')}

{/* Uploads Section */}

{t('settings.uploads')}

setMaxSizeMB(Number(e.target.value))} className="w-24 px-3 py-2.5 border border-border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-primary/20 focus:border-brand-primary bg-surface" /> {t('settings.mb')}

{t('settings.maxFileSizeHint')}

{/* Tutorial Section */}

{t('settings.onboardingTutorial')}

{t('settings.tutorialDesc')}

{success && (

{t('settings.reloadingPage')}

)}
{/* Budget Approval (Superadmin only) */} {user?.role === 'superadmin' && (

{t('settings.budgetApproval') || 'Budget Approval'}

setCeoEmail(e.target.value)} placeholder="ceo@company.com" className="flex-1 max-w-sm px-4 py-2.5 border border-border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-primary/20 focus:border-brand-primary bg-surface" />

{t('settings.ceoEmailHint')}

)} {/* Roles Management (Superadmin only) */} {user?.role === 'superadmin' && }
) } function RolesSection({ roles, loadRoles, t, toast }) { const [editingRole, setEditingRole] = useState(null) const [showAddModal, setShowAddModal] = useState(false) const [modalForm, setModalForm] = useState({ name: '', color: ROLE_COLORS[0] }) const [saving, setSaving] = useState(false) const openAddModal = () => { setModalForm({ name: '', color: ROLE_COLORS[roles.length % ROLE_COLORS.length] }) setShowAddModal(true) } const handleCreate = async () => { setSaving(true) try { await api.post('/roles', { name: modalForm.name, color: modalForm.color }) await loadRoles() setShowAddModal(false) } catch (err) { toast.error(err.message || t('common.error')) } finally { setSaving(false) } } const handleSave = async (role) => { setSaving(true) try { await api.patch(`/roles/${role.Id || role.id}`, { name: role.name, color: role.color }) await loadRoles() setEditingRole(null) } catch (err) { toast.error(err.message || t('common.error')) } finally { setSaving(false) } } const handleDelete = async (role) => { if (!confirm(t('settings.deleteRoleConfirm'))) return try { await api.delete(`/roles/${role.Id || role.id}`) await loadRoles() } catch (err) { toast.error(err.message || t('common.error')) } } return ( <>

{t('settings.roles')}

{t('settings.rolesDesc')}

{roles.map(role => (
{editingRole && (editingRole.Id || editingRole.id) === (role.Id || role.id) ? (
setEditingRole({ ...editingRole, color: e.target.value })} className="w-8 h-8 rounded-lg border border-border cursor-pointer" /> setEditingRole({ ...editingRole, name: e.target.value })} placeholder={t('settings.roleName')} autoFocus className="flex-1 px-3 py-1.5 text-sm border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-primary/20 focus:border-brand-primary" />
) : ( <>
{role.name} )}
))} {roles.length === 0 && (

{t('settings.noRoles')}

)}
setShowAddModal(false)} title={t('settings.addRole')} size="sm">
setModalForm(f => ({ ...f, name: e.target.value }))} className="w-full px-3 py-2 text-sm border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-primary/20 focus:border-brand-primary" placeholder={t('settings.roleName')} autoFocus />
setModalForm(f => ({ ...f, color: e.target.value }))} className="w-10 h-10 rounded-lg border border-border cursor-pointer" />
{ROLE_COLORS.map(c => (
) }