fixing platform admin

This commit is contained in:
root
2026-05-06 22:58:23 -04:00
parent 695a7f7cc7
commit 750ae56a29
175 changed files with 31249 additions and 328 deletions
+129
View File
@@ -0,0 +1,129 @@
'use client'
import { createContext, useContext, useEffect, useMemo, useState } from 'react'
export type AdminLanguage = 'en' | 'fr' | 'ar'
type AdminDictionary = {
nav: Record<string, string>
logout: string
language: string
overview: string
admin: string
platform: string
loading: string
}
const dictionaries: Record<AdminLanguage, AdminDictionary> = {
en: {
nav: {
overview: 'Overview',
companies: 'Companies',
renters: 'Renters',
auditLogs: 'Audit Logs',
adminUsers: 'Admin Users',
},
logout: 'Logout',
language: 'Language',
overview: 'Platform overview',
admin: 'Admin',
platform: 'Platform',
loading: 'Loading',
},
fr: {
nav: {
overview: 'Vue densemble',
companies: 'Entreprises',
renters: 'Locataires',
auditLogs: 'Journaux daudit',
adminUsers: 'Utilisateurs admin',
},
logout: 'Déconnexion',
language: 'Langue',
overview: 'Vue plateforme',
admin: 'Admin',
platform: 'Plateforme',
loading: 'Chargement',
},
ar: {
nav: {
overview: 'نظرة عامة',
companies: 'الشركات',
renters: 'المستأجرون',
auditLogs: 'سجلات التدقيق',
adminUsers: 'مستخدمو الإدارة',
},
logout: 'تسجيل الخروج',
language: 'اللغة',
overview: 'نظرة عامة على المنصة',
admin: 'الإدارة',
platform: 'المنصة',
loading: 'جارٍ التحميل',
},
}
type AdminI18nContext = {
language: AdminLanguage
setLanguage: (value: AdminLanguage) => void
dict: AdminDictionary
}
const Context = createContext<AdminI18nContext | null>(null)
export function AdminI18nProvider({ children }: { children: React.ReactNode }) {
const [language, setLanguage] = useState<AdminLanguage>('en')
useEffect(() => {
const stored = window.localStorage.getItem('admin-language')
if (stored === 'en' || stored === 'fr' || stored === 'ar') {
setLanguage(stored)
}
}, [])
useEffect(() => {
document.documentElement.lang = language
document.documentElement.dir = language === 'ar' ? 'rtl' : 'ltr'
window.localStorage.setItem('admin-language', language)
}, [language])
const value = useMemo(() => ({ language, setLanguage, dict: dictionaries[language] }), [language])
return <Context.Provider value={value}>{children}</Context.Provider>
}
export function useAdminI18n() {
const context = useContext(Context)
if (!context) throw new Error('useAdminI18n must be used within AdminI18nProvider')
return context
}
export function AdminLanguageSwitcher() {
const { language, setLanguage, dict } = useAdminI18n()
const [embedded, setEmbedded] = useState(false)
useEffect(() => {
setEmbedded(window.self !== window.top)
}, [])
if (embedded) return null
return (
<div className="flex items-center gap-1 rounded-full border border-zinc-700 bg-zinc-900 px-2 py-1 shadow-sm">
<span className="px-2 text-[11px] font-semibold uppercase tracking-[0.16em] text-zinc-500">{dict.language}</span>
{(['en', 'fr', 'ar'] as AdminLanguage[]).map((value) => {
const active = value === language
return (
<button
key={value}
type="button"
onClick={() => setLanguage(value)}
className={`rounded-full px-3 py-1.5 text-xs font-semibold transition ${
active ? 'bg-zinc-100 text-zinc-950' : 'text-zinc-300 hover:bg-zinc-800'
}`}
>
{value.toUpperCase()}
</button>
)
})}
</div>
)
}
+54
View File
@@ -0,0 +1,54 @@
'use client'
import Link from 'next/link'
import { AdminLanguageSwitcher, useAdminI18n } from '@/components/I18nProvider'
export default function PublicShell({ children }: { children: React.ReactNode }) {
const { language } = useAdminI18n()
const dict = {
en: {
admin: 'Admin Console',
signIn: 'Sign in',
preferences: 'Admin preferences',
},
fr: {
admin: 'Console admin',
signIn: 'Connexion',
preferences: 'Preferences admin',
},
ar: {
admin: 'لوحة الإدارة',
signIn: 'تسجيل الدخول',
preferences: 'تفضيلات الإدارة',
},
}[language]
return (
<div className="min-h-screen bg-zinc-950 text-zinc-100">
<header className="sticky top-0 z-30 border-b border-zinc-800 bg-zinc-950/90 backdrop-blur-md">
<div className="mx-auto flex max-w-6xl items-center justify-between gap-4 px-4 py-4">
<Link href="/" className="flex items-center gap-3">
<span className="text-xs font-semibold uppercase tracking-[0.24em] text-emerald-400">RentalDriveGo</span>
<span className="hidden text-sm font-semibold text-zinc-400 sm:inline">{dict.admin}</span>
</Link>
<nav className="flex items-center gap-2">
<Link href="/login" className="rounded-full bg-zinc-100 px-4 py-2 text-sm font-semibold text-zinc-950 transition hover:bg-zinc-300">
{dict.signIn}
</Link>
</nav>
</div>
</header>
<div>{children}</div>
<footer className="border-t border-stone-200 bg-white/90 px-4 py-4 backdrop-blur-md transition-colors">
<div className="mx-auto flex max-w-6xl flex-col items-center justify-between gap-3 lg:flex-row">
<p className="text-xs font-medium uppercase tracking-[0.16em] text-stone-400">
{dict.preferences}
</p>
<div className="flex flex-col items-center gap-3 sm:flex-row">
<AdminLanguageSwitcher />
</div>
</div>
</footer>
</div>
)
}