diff --git a/src/application/settings/SettingsPage.tsx b/src/application/settings/SettingsPage.tsx new file mode 100644 index 0000000..1be42fa --- /dev/null +++ b/src/application/settings/SettingsPage.tsx @@ -0,0 +1,107 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import { CustomDropdown, CustomConfirmationModal } from '../../components/custom'; +import { useAuth } from '../../context/AuthContext'; +import { languages } from '../../i18n/config'; +import type { SupportedLanguage } from '../../i18n/config'; +import { Globe } from 'lucide-react'; + +const SettingsPage: React.FC = () => { + const { t, i18n } = useTranslation('common'); + const { user, updateLanguage } = useAuth(); + const [isLoading, setIsLoading] = useState(false); + const [selectedLanguage] = useState( + (i18n.language as SupportedLanguage) || 'en' + ); + const [pendingLanguage, setPendingLanguage] = useState(null); + const [showConfirmation, setShowConfirmation] = useState(false); + + const handleLanguageChange = (newLanguage: SupportedLanguage) => { + if (newLanguage === selectedLanguage) return; + + setPendingLanguage(newLanguage); + setShowConfirmation(true); + }; + + const handleConfirmLanguageChange = async () => { + if (!pendingLanguage) return; + + setIsLoading(true); + setShowConfirmation(false); + + try { + localStorage.setItem('preferred_language', pendingLanguage); + + if (user) { + await updateLanguage(pendingLanguage); + } + + window.location.reload(); + } catch (error) { + console.error('Failed to update language:', error); + toast.error(t('messages.error')); + setIsLoading(false); + setPendingLanguage(null); + } + }; + + const handleCancelLanguageChange = () => { + setPendingLanguage(null); + setShowConfirmation(false); + }; + + return ( +
+ {/* Page Header */} +
+
+

+ {t('settings.title')} +

+
+
+ + {/* Language Settings Section */} +
+
+ +

+ {t('settings.language.title')} +

+
+ +

+ {t('settings.language.description')} +

+ +
+ ({ + label: languages[lang].name, + value: lang + }))} + value={selectedLanguage} + onChange={(e) => handleLanguageChange(e.target.value as SupportedLanguage)} + disabled={isLoading} + leftIcon={} + /> +
+
+ + {/* Confirmation Modal */} + +
+ ); +}; + +export default SettingsPage; \ No newline at end of file diff --git a/src/application/settings/SettingsTypes.ts b/src/application/settings/SettingsTypes.ts new file mode 100644 index 0000000..8c97840 --- /dev/null +++ b/src/application/settings/SettingsTypes.ts @@ -0,0 +1,9 @@ +export interface LanguageSettings { + code: string; + name: string; + dir: 'ltr' | 'rtl'; +} + +export interface SettingsFormData { + language: string; +} \ No newline at end of file diff --git a/src/components/layout/AppSidebar.tsx b/src/components/layout/AppSidebar.tsx index 4a4ee44..1324c4c 100644 --- a/src/components/layout/AppSidebar.tsx +++ b/src/components/layout/AppSidebar.tsx @@ -51,18 +51,18 @@ const navItems: NavItem[] = [ path: "/tenants", access: "superadmin.tenant.read", }, - { - icon: , - name: "Users", - path: "/users", - access: "admin.user.read", - }, { icon: , name: "Roles", path: "/roles", access: "admin.role.read", }, + { + icon: , + name: "Users", + path: "/users", + access: "admin.user.read", + }, { icon: , name: "Themes", diff --git a/src/routes/index.tsx b/src/routes/index.tsx index c69f7b1..a212ccb 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -9,6 +9,7 @@ import ProfilePage from "../application/profile/ProfilePage"; import Tenants from "../application/tenants"; import ProtectedRoutes from "./ProtectedRoutes"; import Theme from "../application/theme"; +import SettingsPage from "../application/settings/SettingsPage"; const AppRoutes = () => { return ( @@ -24,11 +25,10 @@ const AppRoutes = () => { } /> } /> } /> - {/* Redirect root to dashboard if logged in (ProtectedRoutes handles auth check usually, or we redirect to signin if not) */} + } /> } /> - {/* Catch all - Redirect to dashboard which will handle auth or show dashboard */} } /> );