fix setting and add rental policies
Test / Type Check (all packages) (push) Has been cancelled
Test / API Unit Tests (push) Has been cancelled
Test / Homepage Unit Tests (push) Has been cancelled
Test / Carplace Unit Tests (push) Has been cancelled
Test / Admin Unit Tests (push) Has been cancelled
Test / Dashboard Unit Tests (push) Has been cancelled
Test / API Integration Tests (push) Has been cancelled
Build & Push / Pipeline Tests (push) Waiting to run
Build & Push / Build & Push Docker Image (push) Blocked by required conditions
Test / Type Check (all packages) (push) Has been cancelled
Test / API Unit Tests (push) Has been cancelled
Test / Homepage Unit Tests (push) Has been cancelled
Test / Carplace Unit Tests (push) Has been cancelled
Test / Admin Unit Tests (push) Has been cancelled
Test / Dashboard Unit Tests (push) Has been cancelled
Test / API Integration Tests (push) Has been cancelled
Build & Push / Pipeline Tests (push) Waiting to run
Build & Push / Build & Push Docker Image (push) Blocked by required conditions
This commit is contained in:
@@ -294,6 +294,7 @@ type VehicleDetailDict = {
|
||||
saveLabel: string
|
||||
savingLabel: string
|
||||
dateRequired: string
|
||||
carMaintenance: string
|
||||
routineTypes: Record<string, string>
|
||||
}
|
||||
|
||||
@@ -532,11 +533,13 @@ const dictionaries: Record<DashboardLanguage, DashboardDictionary> = {
|
||||
saveLabel: 'Save',
|
||||
savingLabel: 'Saving…',
|
||||
dateRequired: 'Service date is required.',
|
||||
carMaintenance: 'Car Maintenance',
|
||||
routineTypes: {
|
||||
'Oil Change': 'Oil Change',
|
||||
'Technical Inspection': 'Technical Inspection',
|
||||
'Vehicle Registration': 'Vehicle Registration',
|
||||
'Car Tax': 'Car Tax',
|
||||
'Insurance': 'Insurance',
|
||||
'Tire Rotation': 'Tire Rotation',
|
||||
'Brake Inspection': 'Brake Inspection',
|
||||
'Air Filter': 'Air Filter',
|
||||
@@ -545,6 +548,15 @@ const dictionaries: Record<DashboardLanguage, DashboardDictionary> = {
|
||||
'Belt / Chain Service': 'Belt / Chain Service',
|
||||
'Coolant Flush': 'Coolant Flush',
|
||||
'Transmission Service': 'Transmission Service',
|
||||
'Wheel Alignment': 'Wheel Alignment',
|
||||
'Wheel Balancing': 'Wheel Balancing',
|
||||
'Spark Plugs': 'Spark Plugs',
|
||||
'Fuel Filter': 'Fuel Filter',
|
||||
'Wiper Blades': 'Wiper Blades',
|
||||
'AC Service': 'AC Service',
|
||||
'Suspension Check': 'Suspension Check',
|
||||
'Engine Diagnostic': 'Engine Diagnostic',
|
||||
'Brake Pads': 'Brake Pads',
|
||||
},
|
||||
},
|
||||
calendar: {
|
||||
@@ -890,11 +902,13 @@ const dictionaries: Record<DashboardLanguage, DashboardDictionary> = {
|
||||
saveLabel: 'Enregistrer',
|
||||
savingLabel: 'Enregistrement…',
|
||||
dateRequired: 'La date du service est requise.',
|
||||
carMaintenance: 'Entretien voiture',
|
||||
routineTypes: {
|
||||
'Oil Change': "Vidange d'huile",
|
||||
'Technical Inspection': 'Contrôle technique',
|
||||
'Vehicle Registration': 'Carte grise',
|
||||
'Car Tax': 'Vignette automobile',
|
||||
'Insurance': 'Assurance',
|
||||
'Tire Rotation': 'Rotation des pneus',
|
||||
'Brake Inspection': 'Contrôle des freins',
|
||||
'Air Filter': 'Filtre à air',
|
||||
@@ -903,6 +917,15 @@ const dictionaries: Record<DashboardLanguage, DashboardDictionary> = {
|
||||
'Belt / Chain Service': 'Courroie / Chaîne',
|
||||
'Coolant Flush': 'Liquide de refroidissement',
|
||||
'Transmission Service': 'Entretien transmission',
|
||||
'Wheel Alignment': 'Parallélisme',
|
||||
'Wheel Balancing': 'Équilibrage des roues',
|
||||
'Spark Plugs': 'Bougies',
|
||||
'Fuel Filter': 'Filtre à carburant',
|
||||
'Wiper Blades': "Balais d'essuie-glace",
|
||||
'AC Service': 'Climatisation',
|
||||
'Suspension Check': 'Contrôle suspension',
|
||||
'Engine Diagnostic': 'Diagnostic moteur',
|
||||
'Brake Pads': 'Plaquettes de frein',
|
||||
},
|
||||
},
|
||||
calendar: {
|
||||
@@ -1248,11 +1271,13 @@ const dictionaries: Record<DashboardLanguage, DashboardDictionary> = {
|
||||
saveLabel: 'حفظ',
|
||||
savingLabel: 'جارٍ الحفظ…',
|
||||
dateRequired: 'تاريخ الخدمة مطلوب.',
|
||||
carMaintenance: 'صيانة السيارة',
|
||||
routineTypes: {
|
||||
'Oil Change': 'تغيير الزيت',
|
||||
'Technical Inspection': 'الفحص التقني',
|
||||
'Vehicle Registration': 'تسجيل المركبة',
|
||||
'Car Tax': 'الضريبة السنوية',
|
||||
'Insurance': 'التأمين',
|
||||
'Tire Rotation': 'تدوير الإطارات',
|
||||
'Brake Inspection': 'فحص الفرامل',
|
||||
'Air Filter': 'فلتر الهواء',
|
||||
@@ -1261,6 +1286,15 @@ const dictionaries: Record<DashboardLanguage, DashboardDictionary> = {
|
||||
'Belt / Chain Service': 'خدمة السير / السلسلة',
|
||||
'Coolant Flush': 'تغيير سائل التبريد',
|
||||
'Transmission Service': 'خدمة ناقل الحركة',
|
||||
'Wheel Alignment': 'ضبط زوايا العجلات',
|
||||
'Wheel Balancing': 'ترصيص العجلات',
|
||||
'Spark Plugs': 'شمعات الإشعال',
|
||||
'Fuel Filter': 'فلتر الوقود',
|
||||
'Wiper Blades': 'مساحات الزجاج',
|
||||
'AC Service': 'صيانة المكيف',
|
||||
'Suspension Check': 'فحص نظام التعليق',
|
||||
'Engine Diagnostic': 'تشخيص المحرك',
|
||||
'Brake Pads': 'صفائح الفرامل',
|
||||
},
|
||||
},
|
||||
calendar: {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import Link from 'next/link'
|
||||
import { Bell, Search, Settings } from 'lucide-react'
|
||||
import { usePathname, useRouter } from 'next/navigation'
|
||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { io } from 'socket.io-client'
|
||||
import { EMPLOYEE_PROFILE_KEY, apiFetch } from '@/lib/api'
|
||||
@@ -33,11 +33,20 @@ function resolveSocketOrigin(): string | null {
|
||||
return window.location.origin
|
||||
}
|
||||
|
||||
const SEARCHABLE_ROUTES = ['/reservations', '/fleet', '/customers', '/contracts', '/billing']
|
||||
|
||||
function getSearchTarget(appPath: string): string {
|
||||
const match = SEARCHABLE_ROUTES.find((route) => appPath === route || appPath.startsWith(`${route}/`))
|
||||
return match ?? '/reservations'
|
||||
}
|
||||
|
||||
export default function TopBar() {
|
||||
const { dict } = useDashboardI18n()
|
||||
const pathname = usePathname()
|
||||
const appPath = toDashboardAppPath(pathname)
|
||||
const router = useRouter()
|
||||
const searchParams = useSearchParams()
|
||||
const [globalSearch, setGlobalSearch] = useState('')
|
||||
const [unreadCount, setUnreadCount] = useState(0)
|
||||
const [showNotifs, setShowNotifs] = useState(false)
|
||||
const [userInitials, setUserInitials] = useState('W')
|
||||
@@ -54,6 +63,10 @@ export default function TopBar() {
|
||||
const [mounted, setMounted] = useState(false)
|
||||
useEffect(() => { setMounted(true) }, [])
|
||||
|
||||
useEffect(() => {
|
||||
setGlobalSearch(searchParams.get('search') ?? '')
|
||||
}, [searchParams])
|
||||
|
||||
const title = (() => {
|
||||
if (!mounted) return dict.titles['/']
|
||||
if (dict.titles[appPath]) return dict.titles[appPath]
|
||||
@@ -193,18 +206,35 @@ export default function TopBar() {
|
||||
router.push('/notifications')
|
||||
}
|
||||
|
||||
function submitSearch(event: React.FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault()
|
||||
|
||||
const query = globalSearch.trim()
|
||||
const target = getSearchTarget(appPath)
|
||||
const params = new URLSearchParams()
|
||||
|
||||
if (query) {
|
||||
params.set('search', query)
|
||||
router.push(`${target}?${params.toString()}`)
|
||||
} else {
|
||||
router.push(target)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="relative z-[70] flex h-16 items-center justify-between border-b border-blue-200/70 bg-white/82 px-6 text-blue-950 backdrop-blur-xl transition-colors dark:border-blue-400/10 dark:bg-[#0a0f1a]/90 dark:text-slate-100">
|
||||
<div className="flex items-center gap-4 min-w-0">
|
||||
<h1 className="shrink-0 text-lg font-semibold text-blue-950 dark:text-slate-50">{title}</h1>
|
||||
<div className="relative hidden w-[min(380px,38vw)] sm:block">
|
||||
<form className="relative hidden w-[min(380px,38vw)] sm:block" onSubmit={submitSearch}>
|
||||
<Search className="pointer-events-none absolute left-3.5 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-500" />
|
||||
<input
|
||||
type="search"
|
||||
placeholder="Search vehicles, bookings, customers..."
|
||||
value={globalSearch}
|
||||
onChange={(event) => setGlobalSearch(event.target.value)}
|
||||
className="h-10 w-full rounded-lg border border-blue-200/80 bg-blue-50/70 pl-10 pr-4 text-sm text-blue-950 outline-none transition-all placeholder:text-slate-500 focus:border-blue-400/45 focus:bg-white focus:ring-4 focus:ring-blue-500/10 dark:border-blue-400/15 dark:bg-blue-500/[0.06] dark:text-slate-100 dark:focus:bg-blue-500/10"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<div className="hidden items-center gap-2 text-sm text-slate-400 xl:flex">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-emerald-400 shadow-[0_0_0_5px_rgba(16,185,129,0.10)]" />
|
||||
System operational
|
||||
|
||||
Reference in New Issue
Block a user