update style
This commit is contained in:
@@ -45,7 +45,7 @@ type ManualPaymentMethod = 'CASH' | 'CHECK' | 'BANK_TRANSFER' | 'CARD' | 'PAYPAL
|
||||
const PAYMENT_STATUS_BADGE: Record<string, string> = {
|
||||
UNPAID: 'bg-rose-100 text-rose-700',
|
||||
PAID: 'bg-emerald-100 text-emerald-700',
|
||||
PARTIAL: 'bg-amber-100 text-amber-700',
|
||||
PARTIAL: 'bg-orange-100 text-orange-700',
|
||||
PENDING: 'bg-sky-100 text-sky-700',
|
||||
REFUNDED: 'bg-slate-100 text-slate-700',
|
||||
FAILED: 'bg-rose-100 text-rose-700',
|
||||
@@ -53,7 +53,7 @@ const PAYMENT_STATUS_BADGE: Record<string, string> = {
|
||||
}
|
||||
|
||||
const PAYMENT_EVENT_BADGE: Record<string, string> = {
|
||||
PENDING: 'bg-amber-100 text-amber-700',
|
||||
PENDING: 'bg-orange-100 text-orange-700',
|
||||
SUCCEEDED: 'bg-emerald-100 text-emerald-700',
|
||||
FAILED: 'bg-rose-100 text-rose-700',
|
||||
REFUNDED: 'bg-slate-100 text-slate-700',
|
||||
@@ -506,7 +506,7 @@ export default function BillingPage() {
|
||||
) : null}
|
||||
</td>
|
||||
<td className="px-6 py-4 text-right text-sm font-semibold text-emerald-700">{formatCurrency(row.paidAmount, 'MAD')}</td>
|
||||
<td className="px-6 py-4 text-right text-sm font-semibold text-amber-700">{formatCurrency(row.balanceDue, 'MAD')}</td>
|
||||
<td className="px-6 py-4 text-right text-sm font-semibold text-orange-700">{formatCurrency(row.balanceDue, 'MAD')}</td>
|
||||
<td className="px-6 py-4 text-sm">
|
||||
<span className={`inline-flex rounded-full px-2.5 py-0.5 text-xs font-medium ${PAYMENT_STATUS_BADGE[row.paymentStatus] ?? 'bg-slate-100 text-slate-700'}`}>
|
||||
{translateStatus(row.paymentStatus, copy.paymentStatusLabels)}
|
||||
@@ -566,7 +566,7 @@ export default function BillingPage() {
|
||||
</div>
|
||||
|
||||
{paymentModalRow ? (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30 backdrop-blur-sm" onClick={(event) => {
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-[#07101e]/30 backdrop-blur-sm" onClick={(event) => {
|
||||
if (event.target === event.currentTarget && !submittingPayment) setPaymentModalRow(null)
|
||||
}}>
|
||||
<div className="w-full max-w-lg rounded-3xl bg-white p-6 shadow-2xl">
|
||||
|
||||
@@ -476,7 +476,7 @@ export default function FleetDetailPage() {
|
||||
{tab === 'maintenance' && (
|
||||
<>
|
||||
<Wrench className="w-4 h-4" /> {vd.tabMaintenance}
|
||||
{maintenanceLogs.length === 0 && <span className="ml-1 inline-flex h-4 w-4 items-center justify-center rounded-full bg-amber-100 text-amber-700 text-[10px] font-bold">!</span>}
|
||||
{maintenanceLogs.length === 0 && <span className="ml-1 inline-flex h-4 w-4 items-center justify-center rounded-full bg-orange-100 text-orange-700 text-[10px] font-bold">!</span>}
|
||||
</>
|
||||
)}
|
||||
{tab === 'calendar' && <><CalendarDays className="w-4 h-4" /> {vd.tabCalendar}</>}
|
||||
@@ -513,7 +513,7 @@ export default function FleetDetailPage() {
|
||||
<img src={src} alt={`new photo ${i + 1}`} className="object-cover w-full h-full" />
|
||||
<button
|
||||
onClick={() => removeNewPhoto(i)}
|
||||
className="absolute top-2 right-2 p-1.5 bg-black/60 text-white rounded-lg opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
className="absolute top-2 right-2 p-1.5 bg-[#07101e]/60 text-white rounded-lg opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
>
|
||||
<X className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
|
||||
@@ -88,7 +88,7 @@ function MaintenanceModal({ vehicleId, vehicleName, open, onClose, onSaved }: Ma
|
||||
if (!open) return null
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40" onClick={(e) => { if (e.target === e.currentTarget) handleClose() }}>
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-[#07101e]/40" onClick={(e) => { if (e.target === e.currentTarget) handleClose() }}>
|
||||
<div className="bg-white rounded-2xl shadow-xl w-full max-w-md mx-4 p-6">
|
||||
<h2 className="text-lg font-semibold text-slate-900 mb-1">{f.logMaintenance}</h2>
|
||||
<p className="text-sm text-slate-500 mb-5">{f.maintenanceSubtitle(vehicleName)}</p>
|
||||
@@ -210,7 +210,7 @@ function StatusDropdown({ vehicleId, status, onStatusChange }: {
|
||||
<span className={`inline-block w-2 h-2 rounded-full flex-shrink-0 ${
|
||||
s === 'AVAILABLE' ? 'bg-green-500' :
|
||||
s === 'RENTED' ? 'bg-blue-500' :
|
||||
s === 'MAINTENANCE' ? 'bg-amber-500' : 'bg-red-500'
|
||||
s === 'MAINTENANCE' ? 'bg-orange-500' : 'bg-red-500'
|
||||
}`} />
|
||||
{f.statusLabels[s]}
|
||||
</button>
|
||||
@@ -333,7 +333,7 @@ function AddVehicleModal({ open, onClose, onSaved }: AddVehicleModalProps) {
|
||||
const presetModels = form.make && MODELS_BY_MAKE[form.make] ? MODELS_BY_MAKE[form.make] : null
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40" onClick={(e) => { if (e.target === e.currentTarget) handleClose() }}>
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-[#07101e]/40" onClick={(e) => { if (e.target === e.currentTarget) handleClose() }}>
|
||||
<div className="bg-white rounded-2xl shadow-xl w-full max-w-lg mx-4 p-6 max-h-[90vh] overflow-y-auto">
|
||||
<h2 className="text-lg font-semibold text-slate-900 mb-5">{f.addNewVehicle}</h2>
|
||||
{error && (
|
||||
@@ -485,7 +485,7 @@ function AddVehicleModal({ open, onClose, onSaved }: AddVehicleModalProps) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => removePhoto(i)}
|
||||
className="absolute top-1 right-1 p-0.5 bg-black/60 text-white rounded-full opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
className="absolute top-1 right-1 p-0.5 bg-[#07101e]/60 text-white rounded-full opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
|
||||
@@ -540,7 +540,7 @@ export default function OffersPage() {
|
||||
|
||||
{/* Create / Edit Modal */}
|
||||
{modalOpen && (
|
||||
<div className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/50 p-4">
|
||||
<div className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-[#07101e]/50 p-4">
|
||||
<div className="relative w-full max-w-2xl my-8 card p-6" dir={isRtl ? 'rtl' : 'ltr'}>
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-5">
|
||||
{editing ? t.editOffer : t.createOffer}
|
||||
@@ -778,7 +778,7 @@ export default function OffersPage() {
|
||||
|
||||
{/* Delete confirmation */}
|
||||
{deleteTarget && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-[#07101e]/50 p-4">
|
||||
<div className="card p-6 w-full max-w-sm" dir={isRtl ? 'rtl' : 'ltr'}>
|
||||
<h3 className="text-base font-semibold text-slate-900 mb-2">{t.deleteOffer}</h3>
|
||||
<p className="text-sm text-slate-600 mb-5">{t.confirmDelete}</p>
|
||||
|
||||
@@ -25,7 +25,7 @@ interface OnlineReservation {
|
||||
}
|
||||
|
||||
const STATUS_STYLE: Record<string, string> = {
|
||||
DRAFT: 'bg-amber-100 text-amber-800',
|
||||
DRAFT: 'bg-orange-100 text-orange-800',
|
||||
CONFIRMED: 'bg-emerald-100 text-emerald-700',
|
||||
CANCELLED: 'bg-rose-100 text-rose-700',
|
||||
ACTIVE: 'bg-blue-100 text-blue-700',
|
||||
@@ -45,7 +45,7 @@ const STATUS_LABEL: Record<string, string> = {
|
||||
function DeclineModal({ onConfirm, onCancel, loading }: { onConfirm: (reason: string) => void; onCancel: () => void; loading: boolean }) {
|
||||
const [reason, setReason] = useState('')
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4" onClick={onCancel}>
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-[#07101e]/40 p-4" onClick={onCancel}>
|
||||
<div className="w-full max-w-sm rounded-2xl bg-white p-6 shadow-xl" onClick={(e) => e.stopPropagation()}>
|
||||
<h3 className="text-base font-semibold text-slate-900">Decline reservation</h3>
|
||||
<p className="mt-1 text-sm text-slate-500">Optionally provide a reason — it will be visible in the reservation record.</p>
|
||||
@@ -183,7 +183,7 @@ export default function OnlineReservationsPage() {
|
||||
<Globe className="h-5 w-5 text-blue-600" />
|
||||
<h2 className="text-xl font-semibold text-slate-900">{copy.title}</h2>
|
||||
{pending.length > 0 && (
|
||||
<span className="rounded-full bg-amber-500 px-2.5 py-0.5 text-xs font-bold text-white">{pending.length}</span>
|
||||
<span className="rounded-full bg-orange-500 px-2.5 py-0.5 text-xs font-bold text-white">{pending.length}</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-slate-500">{copy.subtitle}</p>
|
||||
@@ -201,7 +201,7 @@ export default function OnlineReservationsPage() {
|
||||
<section>
|
||||
<h3 className="mb-3 flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-slate-500">
|
||||
<Clock className="h-4 w-4" /> {copy.pendingApproval}
|
||||
{pending.length > 0 && <span className="ml-1 text-amber-600">({pending.length})</span>}
|
||||
{pending.length > 0 && <span className="ml-1 text-orange-600">({pending.length})</span>}
|
||||
</h3>
|
||||
|
||||
{loading ? (
|
||||
@@ -238,7 +238,7 @@ function ReservationCard({ r, acting, onConfirm, onDecline }: {
|
||||
}) {
|
||||
const days = r.totalDays
|
||||
return (
|
||||
<div className="card overflow-hidden border-l-4 border-l-amber-400">
|
||||
<div className="card overflow-hidden border-l-4 border-l-orange-400">
|
||||
<div className="p-5">
|
||||
<div className="flex flex-wrap items-start justify-between gap-4">
|
||||
{/* Left: customer + vehicle + dates */}
|
||||
|
||||
@@ -80,7 +80,7 @@ function SubscriptionBanner({
|
||||
message: trialEndsAt ? trialEndsMsg(localeDate) : trialActiveMsg,
|
||||
},
|
||||
PAST_DUE: {
|
||||
bg: 'bg-amber-50 border-amber-200 text-amber-800',
|
||||
bg: 'bg-orange-50 border-orange-200 text-orange-800',
|
||||
icon: <AlertTriangle className="w-4 h-4" />,
|
||||
message: pastDueMsg,
|
||||
},
|
||||
@@ -197,8 +197,8 @@ export default function DashboardPage() {
|
||||
change={kpis.revenueChange}
|
||||
vsLastMonthLabel={d.vsLastMonth}
|
||||
icon={DollarSign}
|
||||
iconColor="text-amber-600"
|
||||
iconBg="bg-amber-50"
|
||||
iconColor="text-orange-600"
|
||||
iconBg="bg-orange-50"
|
||||
/>
|
||||
) : null}
|
||||
<StatCard
|
||||
|
||||
@@ -625,7 +625,7 @@ export default function ReservationDetailPage() {
|
||||
{reservation.pricingRulesApplied.map((rule) => (
|
||||
<div key={`${rule.name}-${rule.amount}`} className="flex items-center justify-between rounded-xl border border-slate-200 px-4 py-3 text-sm">
|
||||
<span className="text-slate-700">{rule.name}</span>
|
||||
<span className={rule.amount < 0 ? 'font-semibold text-emerald-700' : 'font-semibold text-amber-700'}>
|
||||
<span className={rule.amount < 0 ? 'font-semibold text-emerald-700' : 'font-semibold text-orange-700'}>
|
||||
{rule.amount < 0 ? '-' : '+'}{formatCurrency(Math.abs(rule.amount), 'MAD')}
|
||||
</span>
|
||||
</div>
|
||||
@@ -676,7 +676,7 @@ export default function ReservationDetailPage() {
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{driver.approvalNote && <p className="mt-2 text-xs text-amber-700">{driver.approvalNote}</p>}
|
||||
{driver.approvalNote && <p className="mt-2 text-xs text-orange-700">{driver.approvalNote}</p>}
|
||||
</div>
|
||||
))}
|
||||
{reservation.additionalDrivers.length === 0 && (
|
||||
|
||||
@@ -496,9 +496,9 @@ export default function NewReservationPage() {
|
||||
))}
|
||||
</select>
|
||||
{vehicles.length === 0 ? (
|
||||
<span className="text-xs text-amber-700">{copy.noVehicles}</span>
|
||||
<span className="text-xs text-orange-700">{copy.noVehicles}</span>
|
||||
) : availableVehicles.length === 0 ? (
|
||||
<span className="text-xs text-amber-700">
|
||||
<span className="text-xs text-orange-700">
|
||||
{language === 'fr'
|
||||
? 'Des véhicules existent dans la flotte, mais aucun n’est marqué Disponible.'
|
||||
: language === 'ar'
|
||||
|
||||
@@ -43,14 +43,14 @@ interface EmployeeProfile {
|
||||
const STATUS_BADGE: Record<string, string> = {
|
||||
TRIALING: 'bg-sky-100 text-sky-700',
|
||||
ACTIVE: 'bg-green-100 text-green-700',
|
||||
PAST_DUE: 'bg-amber-100 text-amber-700',
|
||||
PAST_DUE: 'bg-orange-100 text-orange-700',
|
||||
CANCELLED: 'bg-slate-100 text-slate-600',
|
||||
UNPAID: 'bg-red-100 text-red-700',
|
||||
}
|
||||
|
||||
const INVOICE_STATUS: Record<string, string> = {
|
||||
PAID: 'bg-green-100 text-green-700',
|
||||
PENDING: 'bg-amber-100 text-amber-700',
|
||||
PENDING: 'bg-orange-100 text-orange-700',
|
||||
FAILED: 'bg-red-100 text-red-700',
|
||||
REFUNDED: 'bg-slate-100 text-slate-600',
|
||||
}
|
||||
@@ -352,7 +352,7 @@ export default function SubscriptionPage() {
|
||||
{subscription.currentPeriodEnd && ` · ${copy.renews} ${new Date(subscription.currentPeriodEnd).toLocaleDateString()}`}
|
||||
</p>
|
||||
{subscription.cancelAtPeriodEnd && (
|
||||
<p className="mt-2 text-sm font-medium text-amber-700">
|
||||
<p className="mt-2 text-sm font-medium text-orange-700">
|
||||
{copy.cancelScheduled}{' '}
|
||||
<button onClick={handleResume} disabled={cancelling} className="underline">{copy.undo}</button>
|
||||
</p>
|
||||
@@ -374,7 +374,7 @@ export default function SubscriptionPage() {
|
||||
{/* Plan selector + checkout */}
|
||||
<div className="card p-6 space-y-6">
|
||||
{!providerAvailability.amanpay && !providerAvailability.paypal ? (
|
||||
<div className="rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-700">
|
||||
<div className="rounded-xl border border-orange-200 bg-orange-50 px-4 py-3 text-sm text-orange-700">
|
||||
{copy.noProviderConfigured}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@@ -40,7 +40,7 @@ const AVATAR_BG: string[] = [
|
||||
'bg-violet-100 dark:bg-violet-900/40 text-violet-700 dark:text-violet-300',
|
||||
'bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300',
|
||||
'bg-teal-100 dark:bg-teal-900/40 text-teal-700 dark:text-teal-300',
|
||||
'bg-amber-100 dark:bg-amber-900/40 text-amber-700 dark:text-amber-300',
|
||||
'bg-orange-100 dark:bg-orange-900/40 text-orange-700 dark:text-orange-300',
|
||||
'bg-pink-100 dark:bg-pink-900/40 text-pink-700 dark:text-pink-300',
|
||||
]
|
||||
|
||||
@@ -72,7 +72,7 @@ function RoleBadge({ role, language }: { role: string; language: 'en' | 'fr' | '
|
||||
function StatusBadge({ member, language }: { member: TeamMember; language: 'en' | 'fr' | 'ar' }) {
|
||||
if (member.invitationStatus === 'pending') {
|
||||
return (
|
||||
<span className="text-xs px-2 py-0.5 rounded-full border bg-amber-50 dark:bg-amber-950/30 text-amber-700 dark:text-amber-400 border-amber-100 dark:border-amber-900/50">
|
||||
<span className="text-xs px-2 py-0.5 rounded-full border bg-orange-50 dark:bg-orange-950/30 text-orange-700 dark:text-orange-400 border-orange-100 dark:border-orange-900/50">
|
||||
{language === 'fr' ? 'Invitation en attente' : language === 'ar' ? 'دعوة قيد الانتظار' : 'Pending invite'}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DashboardLanguageSwitcher, DashboardThemeSwitcher } from '@/components/
|
||||
|
||||
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex min-h-screen bg-[linear-gradient(180deg,#f8f5ef_0%,#f4efe6_28%,#fffdf8_58%,#ffffff_100%)] transition-colors dark:bg-[linear-gradient(180deg,#14110f_0%,#17120d_35%,#0c0a09_100%)] print:block print:min-h-0 print:bg-white">
|
||||
<div className="flex min-h-screen bg-[linear-gradient(180deg,#f8f5ef_0%,#f4efe6_28%,#fffdf8_58%,#ffffff_100%)] transition-colors dark:bg-[linear-gradient(180deg,#0a1128_0%,#0d1b38_35%,#07101e_100%)] print:block print:min-h-0 print:bg-white">
|
||||
<div className="print:hidden">
|
||||
<Sidebar />
|
||||
</div>
|
||||
@@ -13,7 +13,7 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
|
||||
<TopBar />
|
||||
</div>
|
||||
<main className="flex-1 overflow-y-auto p-6 print:p-0 print:overflow-visible">{children}</main>
|
||||
<footer className="border-t border-stone-200/80 bg-white/72 px-6 py-4 backdrop-blur-xl transition-colors dark:border-stone-800 dark:bg-stone-950/72 print:hidden">
|
||||
<footer className="border-t border-stone-200/80 bg-white/72 px-6 py-4 backdrop-blur-xl transition-colors dark:border-blue-900 dark:bg-[#07101e]/72 print:hidden">
|
||||
<div className="flex flex-col items-center justify-between gap-3 lg:flex-row">
|
||||
<p className="text-xs font-medium uppercase tracking-[0.16em] text-stone-400 dark:text-stone-500">
|
||||
Workspace preferences
|
||||
|
||||
@@ -85,7 +85,7 @@ export default function ForgotPasswordPageClient({ embedded = false }: { embedde
|
||||
width={104}
|
||||
height={104}
|
||||
priority
|
||||
className="h-24 w-24 rounded-[1.75rem] border border-stone-200 bg-white p-1.5 shadow-sm transition-colors dark:border-stone-700 dark:bg-stone-900"
|
||||
className="h-24 w-24 rounded-[1.75rem] border border-stone-200 bg-white p-1.5 shadow-sm transition-colors dark:border-blue-800 dark:bg-[#0d1b38]"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
@@ -93,7 +93,7 @@ export default function ForgotPasswordPageClient({ embedded = false }: { embedde
|
||||
<p className="mt-2 text-sm text-stone-500 dark:text-stone-400">{dict.subtitle}</p>
|
||||
</div>
|
||||
|
||||
<section className="rounded-[2rem] border border-stone-200 bg-white p-8 shadow-sm transition-colors dark:border-stone-800 dark:bg-stone-900">
|
||||
<section className="rounded-[2rem] border border-stone-200 bg-white p-8 shadow-sm transition-colors dark:border-blue-900 dark:bg-[#0d1b38]">
|
||||
{sent ? (
|
||||
<div className="space-y-4 text-center">
|
||||
<div className="mx-auto flex h-14 w-14 items-center justify-center rounded-full bg-emerald-100 dark:bg-emerald-950/50">
|
||||
@@ -130,7 +130,7 @@ export default function ForgotPasswordPageClient({ embedded = false }: { embedde
|
||||
</form>
|
||||
)}
|
||||
|
||||
<div className="mt-6 border-t border-stone-200 pt-6 text-center text-sm text-stone-500 dark:border-stone-800 dark:text-stone-400">
|
||||
<div className="mt-6 border-t border-stone-200 pt-6 text-center text-sm text-stone-500 dark:border-blue-900 dark:text-stone-400">
|
||||
<Link href="/sign-in" className="font-semibold text-stone-900 underline decoration-stone-300 underline-offset-4 dark:text-stone-100 dark:decoration-stone-700">
|
||||
{dict.backToLogin}
|
||||
</Link>
|
||||
|
||||
@@ -13,8 +13,8 @@ html.dark {
|
||||
:root {
|
||||
--primary: #2563eb;
|
||||
--primary-hover: #1d4ed8;
|
||||
--accent: #f59e0b;
|
||||
--sidebar-bg: #0f172a;
|
||||
--accent: #f97316;
|
||||
--sidebar-bg: #0a1128;
|
||||
--sidebar-text: #94a3b8;
|
||||
--sidebar-active: #ffffff;
|
||||
}
|
||||
@@ -25,9 +25,9 @@ html.dark {
|
||||
}
|
||||
|
||||
body {
|
||||
@apply text-stone-900 antialiased transition-colors dark:text-stone-100;
|
||||
@apply text-blue-950 antialiased transition-colors dark:text-slate-100;
|
||||
background-image:
|
||||
linear-gradient(180deg, #f8f5ef 0%, #f4efe6 28%, #fffdf8 58%, #ffffff 100%);
|
||||
linear-gradient(180deg, #ffffff 0%, #f5f8ff 28%, #eef4ff 58%, #ffffff 100%);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
@@ -37,16 +37,16 @@ html.dark {
|
||||
|
||||
html.dark body {
|
||||
background-image:
|
||||
linear-gradient(180deg, #14110f 0%, #17120d 35%, #0c0a09 100%);
|
||||
linear-gradient(180deg, #0a1128 0%, #0d1b38 35%, #07101e 100%);
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.btn-primary {
|
||||
@apply inline-flex items-center gap-2 rounded-full bg-stone-950 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-800 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-amber-400 dark:text-stone-950 dark:hover:bg-amber-300;
|
||||
@apply inline-flex items-center gap-2 rounded-full bg-orange-600 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-orange-700 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-orange-500 dark:hover:bg-orange-400;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply inline-flex items-center gap-2 rounded-full border border-stone-300 bg-white/85 px-5 py-2.5 text-sm font-semibold text-stone-700 transition hover:border-stone-950 hover:text-stone-950 dark:border-stone-700 dark:bg-stone-950/30 dark:text-stone-200 dark:hover:border-stone-200 dark:hover:text-white;
|
||||
@apply inline-flex items-center gap-2 rounded-full border border-stone-300 bg-white/85 px-5 py-2.5 text-sm font-semibold text-stone-700 transition hover:border-blue-900 hover:text-blue-900 dark:border-blue-800 dark:bg-blue-950/20 dark:text-blue-100 dark:hover:border-blue-400 dark:hover:text-white;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
@@ -54,18 +54,18 @@ html.dark body {
|
||||
}
|
||||
|
||||
.input-field {
|
||||
@apply w-full rounded-2xl border border-stone-200 bg-white px-4 py-3 text-sm text-stone-900 transition-colors placeholder:text-stone-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-amber-500 dark:border-stone-700 dark:bg-stone-950/80 dark:text-stone-100 dark:placeholder:text-stone-500;
|
||||
@apply w-full rounded-2xl border border-stone-200 bg-white px-4 py-3 text-sm text-stone-900 transition-colors placeholder:text-stone-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-orange-500 dark:border-blue-900 dark:bg-blue-950/50 dark:text-slate-100 dark:placeholder:text-slate-500 dark:focus:ring-orange-400;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply rounded-[1.75rem] border shadow-[0_30px_80px_rgba(28,25,23,0.08)] backdrop-blur transition-colors dark:shadow-[0_30px_80px_rgba(0,0,0,0.26)];
|
||||
@apply rounded-[1.75rem] border shadow-[0_30px_80px_rgba(28,25,23,0.08)] backdrop-blur transition-colors dark:shadow-[0_30px_80px_rgba(0,0,0,0.36)];
|
||||
border-color: rgb(231 229 228 / 0.8);
|
||||
background-color: rgb(255 255 255 / 0.82);
|
||||
}
|
||||
|
||||
html.dark .card {
|
||||
border-color: rgb(41 37 36 / 0.96);
|
||||
background-color: rgb(28 25 23 / 0.72);
|
||||
border-color: rgb(30 60 140 / 0.40);
|
||||
background-color: rgb(11 25 55 / 0.72);
|
||||
}
|
||||
|
||||
.badge-green {
|
||||
@@ -73,7 +73,7 @@ html.dark body {
|
||||
}
|
||||
|
||||
.badge-blue {
|
||||
@apply inline-flex items-center rounded-full bg-amber-100 px-2.5 py-0.5 text-xs font-medium text-amber-700 dark:bg-amber-950/40 dark:text-amber-300;
|
||||
@apply inline-flex items-center rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-950/40 dark:text-blue-300;
|
||||
}
|
||||
|
||||
.badge-amber {
|
||||
@@ -85,7 +85,7 @@ html.dark body {
|
||||
}
|
||||
|
||||
.badge-gray {
|
||||
@apply inline-flex items-center rounded-full bg-stone-100 px-2.5 py-0.5 text-xs font-medium text-stone-600 dark:bg-stone-800 dark:text-stone-300;
|
||||
@apply inline-flex items-center rounded-full bg-stone-100 px-2.5 py-0.5 text-xs font-medium text-stone-600 dark:bg-blue-950/40 dark:text-slate-300;
|
||||
}
|
||||
|
||||
.badge-purple {
|
||||
@@ -106,82 +106,46 @@ html.dark body {
|
||||
|
||||
@layer utilities {
|
||||
.dark .bg-slate-50 {
|
||||
background-color: rgb(12 10 9);
|
||||
background-color: rgb(7 16 46);
|
||||
}
|
||||
|
||||
.dark .bg-white {
|
||||
background-color: rgb(28 25 23);
|
||||
background-color: rgb(11 25 55);
|
||||
}
|
||||
|
||||
.dark .bg-white\/90 {
|
||||
background-color: rgb(28 25 23 / 0.9);
|
||||
background-color: rgb(11 25 55 / 0.9);
|
||||
}
|
||||
|
||||
.dark .border-slate-200,
|
||||
.dark .border-stone-200 {
|
||||
border-color: rgb(41 37 36);
|
||||
border-color: rgb(30 60 140 / 0.50);
|
||||
}
|
||||
|
||||
.dark .text-slate-900 {
|
||||
color: rgb(250 250 249);
|
||||
color: rgb(241 245 249);
|
||||
}
|
||||
|
||||
.dark .text-slate-700 {
|
||||
color: rgb(231 229 228);
|
||||
color: rgb(203 213 225);
|
||||
}
|
||||
|
||||
.dark .text-slate-600,
|
||||
.dark .text-stone-500 {
|
||||
color: rgb(168 162 158);
|
||||
color: rgb(148 163 184);
|
||||
}
|
||||
|
||||
.dark .text-slate-500,
|
||||
.dark .text-slate-400,
|
||||
.dark .text-stone-400 {
|
||||
color: rgb(120 113 108);
|
||||
color: rgb(100 116 139);
|
||||
}
|
||||
|
||||
.dark .hover\:bg-slate-100:hover {
|
||||
background-color: rgb(41 37 36);
|
||||
background-color: rgb(20 42 90);
|
||||
}
|
||||
|
||||
.dark .hover\:text-slate-900:hover {
|
||||
color: rgb(250 250 249);
|
||||
}
|
||||
|
||||
.bg-blue-600 {
|
||||
background-color: rgb(217 119 6);
|
||||
}
|
||||
|
||||
.hover\:bg-blue-700:hover {
|
||||
background-color: rgb(180 83 9);
|
||||
}
|
||||
|
||||
.bg-blue-500 {
|
||||
background-color: rgb(245 158 11);
|
||||
}
|
||||
|
||||
.bg-blue-50 {
|
||||
background-color: rgb(255 251 235);
|
||||
}
|
||||
|
||||
.text-blue-600 {
|
||||
color: rgb(180 83 9);
|
||||
}
|
||||
|
||||
.text-blue-800 {
|
||||
color: rgb(154 52 18);
|
||||
}
|
||||
|
||||
.border-blue-200 {
|
||||
border-color: rgb(253 230 138);
|
||||
}
|
||||
|
||||
.ring-blue-400 {
|
||||
--tw-ring-color: rgb(251 191 36 / 0.6);
|
||||
}
|
||||
|
||||
.focus\:ring-blue-500:focus {
|
||||
--tw-ring-color: rgb(217 119 6 / 0.45);
|
||||
color: rgb(241 245 249);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ function ResetPasswordContent({ embedded = false }: { embedded?: boolean }) {
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 border-t border-stone-200 pt-6 text-center text-sm text-stone-500 dark:border-stone-800 dark:text-stone-400">
|
||||
<div className="mt-6 border-t border-stone-200 pt-6 text-center text-sm text-stone-500 dark:border-blue-900 dark:text-stone-400">
|
||||
<Link href="/sign-in" className="font-semibold text-stone-900 underline decoration-stone-300 underline-offset-4 dark:text-stone-100 dark:decoration-stone-700">
|
||||
{dict.backToLogin}
|
||||
</Link>
|
||||
@@ -200,11 +200,11 @@ function ResetShell({
|
||||
<main className="flex min-h-[calc(100vh-80px)] items-center justify-center px-4 py-12">
|
||||
<div className="w-full max-w-md">
|
||||
<div className="mb-8 text-center">
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.24em] text-amber-700 dark:text-amber-400">RentalDriveGo</span>
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.24em] text-orange-700 dark:text-orange-400">RentalDriveGo</span>
|
||||
<h1 className="mt-3 text-3xl font-black tracking-tight text-stone-900 dark:text-stone-100">{title}</h1>
|
||||
{subtitle && <p className="mt-2 text-sm text-stone-500 dark:text-stone-400">{subtitle}</p>}
|
||||
</div>
|
||||
<section className="rounded-[2rem] border border-stone-200 bg-white p-8 shadow-sm transition-colors dark:border-stone-800 dark:bg-stone-900">
|
||||
<section className="rounded-[2rem] border border-stone-200 bg-white p-8 shadow-sm transition-colors dark:border-blue-900 dark:bg-[#0d1b38]">
|
||||
{children}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -149,14 +149,14 @@ export default function SignInPageClient({ embedded = false }: { embedded?: bool
|
||||
width={104}
|
||||
height={104}
|
||||
priority
|
||||
className="h-24 w-24 rounded-[1.75rem] border border-stone-200/80 bg-white/85 p-1.5 shadow-sm transition-colors dark:border-stone-700 dark:bg-stone-900/80"
|
||||
className="h-24 w-24 rounded-[1.75rem] border border-stone-200/80 bg-white/85 p-1.5 shadow-sm transition-colors dark:border-blue-800 dark:bg-[#0d1b38]/80"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<p className="mt-5 text-xs font-bold uppercase tracking-[0.28em] text-amber-700 dark:text-amber-300">
|
||||
<p className="mt-5 text-xs font-bold uppercase tracking-[0.28em] text-orange-700 dark:text-orange-300">
|
||||
RentalDriveGo
|
||||
</p>
|
||||
<h1 className="mt-3 text-3xl font-black tracking-[-0.03em] text-stone-950 dark:text-stone-50">
|
||||
<h1 className="mt-3 text-3xl font-black tracking-[-0.03em] text-blue-950 dark:text-stone-50">
|
||||
{dict.brandName}
|
||||
</h1>
|
||||
<p className="mt-2 text-sm text-stone-600 dark:text-stone-300">
|
||||
@@ -168,7 +168,7 @@ export default function SignInPageClient({ embedded = false }: { embedded?: bool
|
||||
key={lang}
|
||||
type="button"
|
||||
onClick={() => setLanguage(lang)}
|
||||
className={`rounded-full px-3 py-1 text-xs font-semibold uppercase tracking-wider transition-colors text-amber-700 dark:text-amber-300 ${
|
||||
className={`rounded-full px-3 py-1 text-xs font-semibold uppercase tracking-wider transition-colors text-orange-700 dark:text-orange-300 ${
|
||||
language === lang
|
||||
? 'ring-1 ring-current opacity-100'
|
||||
: 'opacity-45 hover:opacity-80'
|
||||
@@ -180,7 +180,7 @@ export default function SignInPageClient({ embedded = false }: { embedded?: bool
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section className="rounded-[2rem] border border-stone-200/80 bg-white/82 p-8 shadow-[0_30px_80px_rgba(28,25,23,0.08)] backdrop-blur transition-colors dark:border-stone-800 dark:bg-stone-900/78 dark:shadow-[0_30px_80px_rgba(0,0,0,0.26)]">
|
||||
<section className="rounded-[2rem] border border-stone-200/80 bg-white/82 p-8 shadow-[0_30px_80px_rgba(28,25,23,0.08)] backdrop-blur transition-colors dark:border-blue-900 dark:bg-[#0d1b38]/78 dark:shadow-[0_30px_80px_rgba(0,0,0,0.26)]">
|
||||
<LocalSignInForm dict={dict} />
|
||||
</section>
|
||||
</div>
|
||||
@@ -331,7 +331,7 @@ function LocalSignInForm({
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="owner@company.com"
|
||||
className="w-full rounded-2xl border border-stone-200 bg-white px-4 py-3 text-sm text-stone-900 transition-colors placeholder:text-stone-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-amber-500 dark:border-stone-700 dark:bg-stone-950/80 dark:text-stone-100 dark:placeholder:text-stone-500"
|
||||
className="w-full rounded-2xl border border-stone-200 bg-white px-4 py-3 text-sm text-stone-900 transition-colors placeholder:text-stone-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-orange-500 dark:border-blue-800 dark:bg-[#07101e]/80 dark:text-stone-100 dark:placeholder:text-stone-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -344,7 +344,7 @@ function LocalSignInForm({
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="••••••••"
|
||||
className="w-full rounded-2xl border border-stone-200 bg-white px-4 py-3 pr-10 text-sm text-stone-900 transition-colors placeholder:text-stone-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-amber-500 dark:border-stone-700 dark:bg-stone-950/80 dark:text-stone-100 dark:placeholder:text-stone-500"
|
||||
className="w-full rounded-2xl border border-stone-200 bg-white px-4 py-3 pr-10 text-sm text-stone-900 transition-colors placeholder:text-stone-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-orange-500 dark:border-blue-800 dark:bg-[#07101e]/80 dark:text-stone-100 dark:placeholder:text-stone-500"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@@ -369,7 +369,7 @@ function LocalSignInForm({
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="inline-flex w-full justify-center rounded-full bg-stone-950 px-6 py-3 text-sm font-semibold text-white transition hover:bg-stone-800 disabled:cursor-not-allowed disabled:opacity-60 dark:bg-amber-400 dark:text-stone-950 dark:hover:bg-amber-300"
|
||||
className="inline-flex w-full justify-center rounded-full bg-stone-950 px-6 py-3 text-sm font-semibold text-white transition hover:bg-stone-800 disabled:cursor-not-allowed disabled:opacity-60 dark:bg-orange-400 dark:text-white dark:hover:bg-orange-300"
|
||||
>
|
||||
{loading ? dict.signingIn : dict.signIn}
|
||||
</button>
|
||||
@@ -382,7 +382,7 @@ function LocalSignInForm({
|
||||
</form>
|
||||
) : (
|
||||
<form onSubmit={handleTotp} className="space-y-5">
|
||||
<div className="rounded-[1.5rem] border border-stone-200/80 bg-stone-50/90 px-4 py-4 text-center text-sm text-stone-600 dark:border-stone-700 dark:bg-stone-950/50 dark:text-stone-300">
|
||||
<div className="rounded-[1.5rem] border border-stone-200/80 bg-stone-50/90 px-4 py-4 text-center text-sm text-stone-600 dark:border-blue-800 dark:bg-[#07101e]/50 dark:text-stone-300">
|
||||
{dict.enterCode}
|
||||
</div>
|
||||
|
||||
@@ -397,14 +397,14 @@ function LocalSignInForm({
|
||||
value={totpCode}
|
||||
onChange={(e) => setTotpCode(e.target.value.replace(/\D/g, ''))}
|
||||
placeholder="000000"
|
||||
className="w-full rounded-2xl border border-stone-200 bg-white px-4 py-3 text-center text-xl tracking-[0.45em] text-stone-900 transition-colors placeholder:text-stone-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-amber-500 dark:border-stone-700 dark:bg-stone-950/80 dark:text-stone-100 dark:placeholder:text-stone-500"
|
||||
className="w-full rounded-2xl border border-stone-200 bg-white px-4 py-3 text-center text-xl tracking-[0.45em] text-stone-900 transition-colors placeholder:text-stone-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-orange-500 dark:border-blue-800 dark:bg-[#07101e]/80 dark:text-stone-100 dark:placeholder:text-stone-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="inline-flex w-full justify-center rounded-full bg-stone-950 px-6 py-3 text-sm font-semibold text-white transition hover:bg-stone-800 disabled:cursor-not-allowed disabled:opacity-60 dark:bg-amber-400 dark:text-stone-950 dark:hover:bg-amber-300"
|
||||
className="inline-flex w-full justify-center rounded-full bg-stone-950 px-6 py-3 text-sm font-semibold text-white transition hover:bg-stone-800 disabled:cursor-not-allowed disabled:opacity-60 dark:bg-orange-400 dark:text-white dark:hover:bg-orange-300"
|
||||
>
|
||||
{loading ? dict.verifying : dict.verify}
|
||||
</button>
|
||||
|
||||
@@ -426,7 +426,7 @@ export default function SignUpPage() {
|
||||
<span className="font-semibold text-slate-900"> {completedSignup.email}</span>.
|
||||
</p>
|
||||
{completedSignup.emailWarning ? (
|
||||
<div className="mt-6 rounded-2xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800">
|
||||
<div className="mt-6 rounded-2xl border border-orange-200 bg-orange-50 px-4 py-3 text-sm text-orange-800">
|
||||
{completedSignup.emailWarning}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@@ -1513,7 +1513,7 @@ export function DashboardLanguageSwitcher() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 rounded-full border border-stone-200/80 bg-white/95 px-2 py-1 shadow-sm transition-colors dark:border-stone-700 dark:bg-stone-900/85">
|
||||
<div className="flex items-center gap-1 rounded-full border border-stone-200/80 bg-white/95 px-2 py-1 shadow-sm transition-colors dark:border-blue-800 dark:bg-[#0d1b38]/85">
|
||||
<span className="px-2 text-[11px] font-semibold uppercase tracking-[0.16em] text-stone-500 dark:text-stone-400">
|
||||
{dict.language}
|
||||
</span>
|
||||
@@ -1526,8 +1526,8 @@ export function DashboardLanguageSwitcher() {
|
||||
onClick={() => handleLanguageChange(value)}
|
||||
className={`rounded-full px-3 py-1.5 text-xs font-semibold transition ${
|
||||
active
|
||||
? 'bg-stone-900 text-white dark:bg-amber-400 dark:text-stone-950'
|
||||
: 'text-stone-600 hover:bg-stone-100 dark:text-stone-300 dark:hover:bg-stone-800'
|
||||
? 'bg-blue-900 text-white dark:bg-orange-400 dark:text-white'
|
||||
: 'text-stone-600 hover:bg-stone-100 dark:text-stone-300 dark:hover:bg-[#162038]'
|
||||
}`}
|
||||
>
|
||||
{value.toUpperCase()}
|
||||
@@ -1549,7 +1549,7 @@ export function DashboardThemeSwitcher() {
|
||||
if (embedded) return null
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 rounded-full border border-stone-200/80 bg-white/95 px-2 py-1 shadow-sm transition-colors dark:border-stone-700 dark:bg-stone-900/85">
|
||||
<div className="flex items-center gap-1 rounded-full border border-stone-200/80 bg-white/95 px-2 py-1 shadow-sm transition-colors dark:border-blue-800 dark:bg-[#0d1b38]/85">
|
||||
{(['light', 'dark'] as DashboardTheme[]).map((value) => {
|
||||
const active = value === theme
|
||||
return (
|
||||
@@ -1559,8 +1559,8 @@ export function DashboardThemeSwitcher() {
|
||||
onClick={() => setTheme(value)}
|
||||
className={`rounded-full px-3 py-1.5 text-xs font-semibold transition ${
|
||||
active
|
||||
? 'bg-stone-900 text-white dark:bg-amber-400 dark:text-stone-950'
|
||||
: 'text-stone-600 hover:bg-stone-100 dark:text-stone-300 dark:hover:bg-stone-800'
|
||||
? 'bg-blue-900 text-white dark:bg-orange-400 dark:text-white'
|
||||
: 'text-stone-600 hover:bg-stone-100 dark:text-stone-300 dark:hover:bg-[#162038]'
|
||||
}`}
|
||||
>
|
||||
{value === 'light' ? dict.light : dict.dark}
|
||||
|
||||
@@ -22,7 +22,7 @@ interface Props {
|
||||
|
||||
const EVENT_STYLES: Record<EventType, { bg: string; text: string; border: string; dot: string }> = {
|
||||
RESERVATION: { bg: 'bg-blue-100', text: 'text-blue-800', border: 'border-blue-300', dot: 'bg-blue-500' },
|
||||
MAINTENANCE: { bg: 'bg-amber-100', text: 'text-amber-800', border: 'border-amber-300', dot: 'bg-amber-500' },
|
||||
MAINTENANCE: { bg: 'bg-orange-100', text: 'text-orange-800', border: 'border-orange-300', dot: 'bg-orange-500' },
|
||||
BLOCK: { bg: 'bg-red-100', text: 'text-red-800', border: 'border-red-300', dot: 'bg-red-500' },
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ export default function VehicleCalendar({ vehicleId }: Props) {
|
||||
{/* Legend */}
|
||||
<div className="flex flex-wrap gap-4 text-xs text-slate-600">
|
||||
<span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-full bg-blue-500 inline-block" />{c.legendReserved}</span>
|
||||
<span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-full bg-amber-500 inline-block" />{c.legendMaintenance}</span>
|
||||
<span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-full bg-orange-500 inline-block" />{c.legendMaintenance}</span>
|
||||
<span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-full bg-red-500 inline-block" />{c.legendBlocked}</span>
|
||||
<span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-full bg-emerald-500 inline-block" />{c.legendAvailable}</span>
|
||||
</div>
|
||||
@@ -336,7 +336,7 @@ export default function VehicleCalendar({ vehicleId }: Props) {
|
||||
|
||||
{/* Add Block Modal */}
|
||||
{showModal && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-sm" onClick={closeModal}>
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-[#07101e]/40 backdrop-blur-sm" onClick={closeModal}>
|
||||
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-md p-6 space-y-4" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="flex items-center justify-between">
|
||||
<h4 className="text-base font-semibold text-slate-900">{c.modalTitle}</h4>
|
||||
@@ -357,7 +357,7 @@ export default function VehicleCalendar({ vehicleId }: Props) {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setBlockType('MAINTENANCE')}
|
||||
className={`flex-1 flex items-center justify-center gap-2 py-2 rounded-lg border text-sm font-medium transition-colors ${blockType === 'MAINTENANCE' ? 'bg-amber-50 border-amber-300 text-amber-700' : 'border-slate-200 text-slate-600 hover:bg-slate-50'}`}
|
||||
className={`flex-1 flex items-center justify-center gap-2 py-2 rounded-lg border text-sm font-medium transition-colors ${blockType === 'MAINTENANCE' ? 'bg-orange-50 border-orange-300 text-orange-700' : 'border-slate-200 text-slate-600 hover:bg-slate-50'}`}
|
||||
>
|
||||
<Wrench className="w-3.5 h-3.5" /> {c.maintenanceBlock}
|
||||
</button>
|
||||
|
||||
@@ -111,7 +111,7 @@ export default function PublicFooter() {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<footer className="border-t border-stone-200/80 bg-white/72 px-4 py-8 text-stone-600 backdrop-blur-xl transition-colors dark:border-stone-800 dark:bg-stone-950/72 dark:text-stone-300">
|
||||
<footer className="border-t border-stone-200/80 bg-white/72 px-4 py-8 text-stone-600 backdrop-blur-xl transition-colors dark:border-blue-900 dark:bg-[#07101e]/72 dark:text-stone-300">
|
||||
<div className="mx-auto flex max-w-7xl flex-col items-center gap-5 px-0 text-center sm:px-2 lg:px-0">
|
||||
<nav className="flex flex-wrap items-center justify-center gap-y-3 text-sm">
|
||||
{footerContent.primary.map((item, index) => (
|
||||
@@ -135,7 +135,7 @@ export default function PublicFooter() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setLocaleMenuOpen((open) => !open)}
|
||||
className="inline-flex items-center gap-2 text-amber-700 transition hover:text-stone-950 dark:text-amber-300 dark:hover:text-stone-100"
|
||||
className="inline-flex items-center gap-2 text-orange-700 transition hover:text-blue-900 dark:text-orange-300 dark:hover:text-stone-100"
|
||||
aria-expanded={localeMenuOpen}
|
||||
aria-haspopup="menu"
|
||||
>
|
||||
@@ -144,7 +144,7 @@ export default function PublicFooter() {
|
||||
<ChevronDown className={`h-4 w-4 transition-transform ${localeMenuOpen ? 'rotate-180' : ''}`} />
|
||||
</button>
|
||||
{localeMenuOpen ? (
|
||||
<div className="absolute left-1/2 top-full z-20 mt-3 w-56 -translate-x-1/2 overflow-hidden rounded-2xl border border-stone-200 bg-white/95 text-left shadow-[0_20px_60px_rgba(0,0,0,0.12)] backdrop-blur dark:border-stone-800 dark:bg-stone-950/95 dark:shadow-[0_20px_60px_rgba(0,0,0,0.35)]">
|
||||
<div className="absolute left-1/2 top-full z-20 mt-3 w-56 -translate-x-1/2 overflow-hidden rounded-2xl border border-stone-200 bg-white/95 text-left shadow-[0_20px_60px_rgba(0,0,0,0.12)] backdrop-blur dark:border-blue-900 dark:bg-[#07101e]/95 dark:shadow-[0_20px_60px_rgba(0,0,0,0.35)]">
|
||||
{availableLocaleOptions.map((option) => (
|
||||
<button
|
||||
key={option.value}
|
||||
@@ -153,7 +153,7 @@ export default function PublicFooter() {
|
||||
setLanguage(option.value)
|
||||
setLocaleMenuOpen(false)
|
||||
}}
|
||||
className="flex w-full items-center gap-3 px-4 py-3 text-sm text-stone-700 transition hover:bg-stone-100 hover:text-stone-950 dark:text-stone-200 dark:hover:bg-stone-900 dark:hover:text-white"
|
||||
className="flex w-full items-center gap-3 px-4 py-3 text-sm text-stone-700 transition hover:bg-stone-100 hover:text-blue-900 dark:text-stone-200 dark:hover:bg-[#0d1b38] dark:hover:text-white"
|
||||
>
|
||||
<span aria-hidden="true" className="text-base leading-none">{option.flag}</span>
|
||||
<span>{option.label}</span>
|
||||
@@ -173,7 +173,7 @@ export default function PublicFooter() {
|
||||
}
|
||||
|
||||
function FooterNavItem({ item }: { item: FooterItem }) {
|
||||
const className = 'px-3 text-stone-600 transition hover:text-stone-950 dark:text-stone-300 dark:hover:text-white'
|
||||
const className = 'px-3 text-stone-600 transition hover:text-blue-900 dark:text-stone-300 dark:hover:text-white'
|
||||
|
||||
if (item.href) {
|
||||
return (
|
||||
|
||||
@@ -105,9 +105,9 @@ export default function PublicHeader() {
|
||||
const signUpHref = `/sign-up?${signUpParams.toString()}`
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-30 border-b border-stone-200/80 bg-white/78 backdrop-blur-xl shadow-[0_10px_30px_rgba(15,23,42,0.06)] transition-colors dark:border-stone-800 dark:bg-stone-950/76 dark:shadow-[0_10px_30px_rgba(0,0,0,0.28)]">
|
||||
<header className="sticky top-0 z-30 border-b border-stone-200/80 bg-white/78 backdrop-blur-xl shadow-[0_10px_30px_rgba(15,23,42,0.06)] transition-colors dark:border-blue-900 dark:bg-[#07101e]/76 dark:shadow-[0_10px_30px_rgba(0,0,0,0.28)]">
|
||||
<div className="mx-auto flex max-w-7xl flex-col gap-1.5 px-4 py-1.5 sm:px-6 lg:flex-row lg:items-center lg:justify-between lg:gap-3 lg:px-8 lg:py-2">
|
||||
<a href={marketplaceUrl} className="flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-[0.14em] text-stone-900 dark:text-stone-100 sm:text-sm sm:tracking-[0.2em]">
|
||||
<a href={marketplaceUrl} className="flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-[0.14em] text-blue-950 dark:text-slate-100 sm:text-sm sm:tracking-[0.2em]">
|
||||
<Image
|
||||
src={DASHBOARD_LOGO_SRC}
|
||||
alt="RentalDriveGo"
|
||||
@@ -121,26 +121,26 @@ export default function PublicHeader() {
|
||||
|
||||
<div className="flex flex-col gap-1.5 lg:flex-row lg:items-center lg:gap-3">
|
||||
<nav className="flex items-center gap-0.5 overflow-x-auto">
|
||||
<a href={marketplaceUrl} className="rounded-full px-2.5 py-1 text-[12px] font-medium text-stone-600 transition hover:bg-stone-100 hover:text-stone-900 dark:text-stone-300 dark:hover:bg-stone-800 dark:hover:text-stone-100 sm:px-4 sm:py-2 sm:text-sm">
|
||||
<a href={marketplaceUrl} className="rounded-full px-2.5 py-1 text-[12px] font-medium text-stone-600 transition hover:bg-stone-100 hover:text-blue-900 dark:text-stone-300 dark:hover:bg-[#162038] dark:hover:text-stone-100 sm:px-4 sm:py-2 sm:text-sm">
|
||||
{dict.home}
|
||||
</a>
|
||||
<a href={`${marketplaceUrl}/explore`} className="rounded-full px-2.5 py-1 text-[12px] font-medium text-stone-600 transition hover:bg-stone-100 hover:text-stone-900 dark:text-stone-300 dark:hover:bg-stone-800 dark:hover:text-stone-100 sm:px-4 sm:py-2 sm:text-sm">
|
||||
<a href={`${marketplaceUrl}/explore`} className="rounded-full px-2.5 py-1 text-[12px] font-medium text-stone-600 transition hover:bg-stone-100 hover:text-blue-900 dark:text-stone-300 dark:hover:bg-[#162038] dark:hover:text-stone-100 sm:px-4 sm:py-2 sm:text-sm">
|
||||
{dict.marketplace}
|
||||
</a>
|
||||
<a href={signInHref} className="rounded-full px-2.5 py-1 text-[12px] font-medium text-stone-600 transition hover:bg-stone-100 hover:text-stone-900 dark:text-stone-300 dark:hover:bg-stone-800 dark:hover:text-stone-100 sm:px-4 sm:py-2 sm:text-sm">
|
||||
<a href={signInHref} className="rounded-full px-2.5 py-1 text-[12px] font-medium text-stone-600 transition hover:bg-stone-100 hover:text-blue-900 dark:text-stone-300 dark:hover:bg-[#162038] dark:hover:text-stone-100 sm:px-4 sm:py-2 sm:text-sm">
|
||||
{dict.signIn}
|
||||
</a>
|
||||
<Link href={signUpHref} className="ml-1 rounded-full bg-stone-900 px-3 py-1 text-[12px] font-semibold text-white transition hover:bg-stone-700 dark:bg-amber-400 dark:text-stone-950 dark:hover:bg-amber-300 sm:ml-2 sm:px-5 sm:py-2 sm:text-sm">
|
||||
<Link href={signUpHref} className="ml-1 rounded-full bg-blue-900 px-3 py-1 text-[12px] font-semibold text-white transition hover:bg-orange-700 dark:bg-orange-400 dark:text-white dark:hover:bg-orange-300 sm:ml-2 sm:px-5 sm:py-2 sm:text-sm">
|
||||
{dict.createAccount}
|
||||
</Link>
|
||||
</nav>
|
||||
<div className="shrink-0">
|
||||
<div className="flex items-center self-start rounded-full border border-stone-200/80 bg-white/95 p-0.5 shadow-sm dark:border-stone-700 dark:bg-stone-900/85 sm:self-auto sm:p-1">
|
||||
<div className="flex items-center self-start rounded-full border border-stone-200/80 bg-white/95 p-0.5 shadow-sm dark:border-blue-800 dark:bg-[#0d1b38]/85 sm:self-auto sm:p-1">
|
||||
<div ref={localeMenuRef} className="relative">
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleLocaleMenu}
|
||||
className="inline-flex min-w-[4.75rem] items-center justify-center gap-1.5 rounded-full px-2.5 py-1.5 text-[11px] font-semibold text-stone-700 transition hover:bg-stone-100 dark:text-stone-200 dark:hover:bg-stone-800 sm:min-w-[5.25rem] sm:px-3 sm:py-2 sm:text-xs"
|
||||
className="inline-flex min-w-[4.75rem] items-center justify-center gap-1.5 rounded-full px-2.5 py-1.5 text-[11px] font-semibold text-stone-700 transition hover:bg-stone-100 dark:text-stone-200 dark:hover:bg-[#162038] sm:min-w-[5.25rem] sm:px-3 sm:py-2 sm:text-xs"
|
||||
aria-expanded={localeMenuOpen}
|
||||
aria-haspopup="menu"
|
||||
>
|
||||
@@ -149,7 +149,7 @@ export default function PublicHeader() {
|
||||
<ChevronDown className={`h-3.5 w-3.5 transition-transform ${localeMenuOpen ? 'rotate-180' : ''}`} />
|
||||
</button>
|
||||
{localeMenuOpen ? (
|
||||
<div className={`absolute top-full z-30 mt-2 w-48 max-w-[calc(100vw-2rem)] overflow-hidden rounded-2xl border border-stone-200 bg-white/95 text-left shadow-[0_20px_60px_rgba(0,0,0,0.12)] backdrop-blur dark:border-stone-800 dark:bg-stone-950/95 dark:shadow-[0_20px_60px_rgba(0,0,0,0.35)] ${localeMenuPositionClass}`}>
|
||||
<div className={`absolute top-full z-30 mt-2 w-48 max-w-[calc(100vw-2rem)] overflow-hidden rounded-2xl border border-stone-200 bg-white/95 text-left shadow-[0_20px_60px_rgba(0,0,0,0.12)] backdrop-blur dark:border-blue-900 dark:bg-[#07101e]/95 dark:shadow-[0_20px_60px_rgba(0,0,0,0.35)] ${localeMenuPositionClass}`}>
|
||||
{availableLanguages.map((option) => (
|
||||
<button
|
||||
key={option.value}
|
||||
@@ -158,7 +158,7 @@ export default function PublicHeader() {
|
||||
setLanguage(option.value)
|
||||
setLocaleMenuOpen(false)
|
||||
}}
|
||||
className="flex w-full items-center gap-3 px-4 py-3 text-sm text-stone-700 transition hover:bg-stone-100 hover:text-stone-950 dark:text-stone-200 dark:hover:bg-stone-900 dark:hover:text-white"
|
||||
className="flex w-full items-center gap-3 px-4 py-3 text-sm text-stone-700 transition hover:bg-stone-100 hover:text-blue-900 dark:text-stone-200 dark:hover:bg-[#0d1b38] dark:hover:text-white"
|
||||
>
|
||||
<span aria-hidden="true">{option.flag}</span>
|
||||
<span>{option.shortLabel}</span>
|
||||
@@ -172,17 +172,17 @@ export default function PublicHeader() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleThemeMenu}
|
||||
className="inline-flex items-center gap-1.5 rounded-full px-2 py-1 transition hover:bg-stone-100 dark:hover:bg-stone-800 sm:px-2.5 sm:py-1.5"
|
||||
className="inline-flex items-center gap-1.5 rounded-full px-2 py-1 transition hover:bg-stone-100 dark:hover:bg-[#162038] sm:px-2.5 sm:py-1.5"
|
||||
aria-expanded={themeMenuOpen}
|
||||
aria-haspopup="menu"
|
||||
>
|
||||
<span className="rounded-full bg-stone-900 px-3 py-1 text-[11px] font-semibold text-white dark:bg-amber-400 dark:text-stone-950 sm:px-3.5 sm:py-1.5 sm:text-xs">
|
||||
<span className="rounded-full bg-blue-900 px-3 py-1 text-[11px] font-semibold text-white dark:bg-orange-400 dark:text-white sm:px-3.5 sm:py-1.5 sm:text-xs">
|
||||
{currentTheme.label}
|
||||
</span>
|
||||
<ChevronDown className={`h-3.5 w-3.5 text-stone-500 transition-transform dark:text-stone-400 ${themeMenuOpen ? 'rotate-180' : ''}`} />
|
||||
</button>
|
||||
{themeMenuOpen ? (
|
||||
<div className={`absolute top-full z-30 mt-2 w-44 max-w-[calc(100vw-2rem)] overflow-hidden rounded-2xl border border-stone-200 bg-white/95 text-left shadow-[0_20px_60px_rgba(0,0,0,0.12)] backdrop-blur dark:border-stone-800 dark:bg-stone-950/95 dark:shadow-[0_20px_60px_rgba(0,0,0,0.35)] ${localeMenuPositionClass}`}>
|
||||
<div className={`absolute top-full z-30 mt-2 w-44 max-w-[calc(100vw-2rem)] overflow-hidden rounded-2xl border border-stone-200 bg-white/95 text-left shadow-[0_20px_60px_rgba(0,0,0,0.12)] backdrop-blur dark:border-blue-900 dark:bg-[#07101e]/95 dark:shadow-[0_20px_60px_rgba(0,0,0,0.35)] ${localeMenuPositionClass}`}>
|
||||
{themeOptions
|
||||
.filter((option) => option.value !== theme)
|
||||
.map((option) => (
|
||||
@@ -193,7 +193,7 @@ export default function PublicHeader() {
|
||||
setTheme(option.value)
|
||||
setThemeMenuOpen(false)
|
||||
}}
|
||||
className="flex w-full items-center justify-between px-4 py-3 text-sm text-stone-700 transition hover:bg-stone-100 hover:text-stone-950 dark:text-stone-200 dark:hover:bg-stone-900 dark:hover:text-white"
|
||||
className="flex w-full items-center justify-between px-4 py-3 text-sm text-stone-700 transition hover:bg-stone-100 hover:text-blue-900 dark:text-stone-200 dark:hover:bg-[#0d1b38] dark:hover:text-white"
|
||||
>
|
||||
<span>{option.label}</span>
|
||||
</button>
|
||||
|
||||
@@ -11,7 +11,7 @@ export default function PublicShell({
|
||||
embedded?: boolean
|
||||
}) {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col bg-[linear-gradient(180deg,#f8f5ef_0%,#f4efe6_28%,#fffdf8_58%,#ffffff_100%)] text-stone-900 transition-colors dark:bg-[linear-gradient(180deg,#14110f_0%,#17120d_35%,#0c0a09_100%)] dark:text-stone-100">
|
||||
<div className="flex min-h-screen flex-col bg-[linear-gradient(180deg,#ffffff_0%,#f5f8ff_28%,#eef4ff_58%,#ffffff_100%)] text-blue-950 transition-colors dark:bg-[linear-gradient(180deg,#0a1128_0%,#0d1b38_35%,#07101e_100%)] dark:text-slate-100">
|
||||
{embedded ? null : <PublicHeader />}
|
||||
<div className="flex flex-1 flex-col">{children}</div>
|
||||
{embedded ? null : <PublicFooter />}
|
||||
|
||||
@@ -169,7 +169,7 @@ export default function Sidebar() {
|
||||
{/* Mobile backdrop */}
|
||||
{open && (
|
||||
<div
|
||||
className="fixed inset-0 z-30 bg-black/50 lg:hidden"
|
||||
className="fixed inset-0 z-30 bg-[#07101e]/50 lg:hidden"
|
||||
onClick={() => setOpen(false)}
|
||||
/>
|
||||
)}
|
||||
@@ -180,7 +180,7 @@ export default function Sidebar() {
|
||||
onClick={() => setOpen(true)}
|
||||
aria-label="Open sidebar"
|
||||
className={[
|
||||
'fixed top-1/2 z-50 flex h-14 w-6 -translate-y-1/2 items-center justify-center bg-stone-950 text-white shadow-lg lg:hidden',
|
||||
'fixed top-1/2 z-50 flex h-14 w-6 -translate-y-1/2 items-center justify-center bg-[#0a1128] text-white shadow-lg lg:hidden',
|
||||
isRtl ? 'right-0 rounded-l-lg' : 'left-0 rounded-r-lg',
|
||||
].join(' ')}
|
||||
>
|
||||
@@ -190,19 +190,19 @@ export default function Sidebar() {
|
||||
|
||||
<aside
|
||||
className={[
|
||||
'fixed inset-y-0 z-40 flex w-64 flex-col border-r border-stone-800/80 bg-stone-950/94 backdrop-blur-xl transition-transform duration-300',
|
||||
'fixed inset-y-0 z-40 flex w-64 flex-col border-r border-blue-900/50 bg-[#0a1128]/94 backdrop-blur-xl transition-transform duration-300',
|
||||
isRtl ? 'right-0' : 'left-0',
|
||||
'lg:translate-x-0',
|
||||
open ? 'translate-x-0' : (isRtl ? 'translate-x-full' : '-translate-x-full'),
|
||||
].join(' ')}
|
||||
>
|
||||
<a href={marketplaceUrl} target="_top" className="flex items-center gap-3 border-b border-stone-800/80 px-6 py-5">
|
||||
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center overflow-hidden rounded-lg bg-amber-400">
|
||||
<a href={marketplaceUrl} target="_top" className="flex items-center gap-3 border-b border-blue-900/50 px-6 py-5">
|
||||
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center overflow-hidden rounded-lg bg-orange-400">
|
||||
{brand?.logoUrl ? (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img src={brand.logoUrl} alt={brand.displayName} className="h-8 w-8 object-cover" />
|
||||
) : (
|
||||
<Car className="h-4 w-4 text-stone-950" />
|
||||
<Car className="h-4 w-4 text-blue-950" />
|
||||
)}
|
||||
</div>
|
||||
<span className="truncate text-sm font-bold tracking-wide text-white">
|
||||
@@ -220,7 +220,7 @@ export default function Sidebar() {
|
||||
href={item.href}
|
||||
className={[
|
||||
'flex items-center gap-3 rounded-2xl px-3 py-2.5 text-sm font-medium transition-colors',
|
||||
active ? 'bg-amber-400 text-stone-950' : 'text-stone-400 hover:bg-stone-800 hover:text-white',
|
||||
active ? 'bg-orange-500 text-white' : 'text-slate-400 hover:bg-[#162038] hover:text-white',
|
||||
].join(' ')}
|
||||
>
|
||||
<Icon className="h-4 w-4 flex-shrink-0" />
|
||||
@@ -230,19 +230,19 @@ export default function Sidebar() {
|
||||
})}
|
||||
</nav>
|
||||
|
||||
<div className="border-t border-stone-800/80 px-3 py-4">
|
||||
<div className="border-t border-blue-900/50 px-3 py-4">
|
||||
<div className="flex items-center gap-3 rounded-2xl px-3 py-2">
|
||||
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-amber-400 text-xs font-semibold text-stone-950">
|
||||
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-orange-500 text-xs font-semibold text-white">
|
||||
{user.initials}
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="truncate text-sm font-medium text-white">{user.displayName}</p>
|
||||
<p className="truncate text-xs text-stone-400">{user.subtitle}</p>
|
||||
<p className="truncate text-xs text-slate-400">{user.subtitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={signOut}
|
||||
className="mt-2 flex w-full items-center gap-3 rounded-2xl px-3 py-2 text-sm text-stone-400 transition-colors hover:bg-stone-800 hover:text-white"
|
||||
className="mt-2 flex w-full items-center gap-3 rounded-2xl px-3 py-2 text-sm text-slate-400 transition-colors hover:bg-[#162038] hover:text-white"
|
||||
>
|
||||
<LogOut className="h-4 w-4" />
|
||||
{dict.signOut}
|
||||
@@ -254,7 +254,7 @@ export default function Sidebar() {
|
||||
onClick={() => setOpen(false)}
|
||||
aria-label="Close sidebar"
|
||||
className={[
|
||||
'absolute top-1/2 z-10 flex h-14 w-5 -translate-y-1/2 items-center justify-center bg-stone-950 text-white shadow-lg lg:hidden',
|
||||
'absolute top-1/2 z-10 flex h-14 w-5 -translate-y-1/2 items-center justify-center bg-[#0a1128] text-white shadow-lg lg:hidden',
|
||||
isRtl ? '-left-5 rounded-l-lg' : '-right-5 rounded-r-lg',
|
||||
].join(' ')}
|
||||
>
|
||||
|
||||
@@ -143,14 +143,14 @@ export default function TopBar() {
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="flex h-16 items-center justify-between border-b border-stone-200/80 bg-white/78 px-6 backdrop-blur-xl transition-colors dark:border-stone-800 dark:bg-stone-950/76">
|
||||
<h1 className="text-lg font-semibold text-stone-950 dark:text-stone-50">{title}</h1>
|
||||
<header className="flex h-16 items-center justify-between border-b border-stone-200/80 bg-white/78 px-6 backdrop-blur-xl transition-colors dark:border-blue-900 dark:bg-[#07101e]/76">
|
||||
<h1 className="text-lg font-semibold text-blue-950 dark:text-stone-50">{title}</h1>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="relative">
|
||||
<button
|
||||
onClick={() => setShowNotifs(!showNotifs)}
|
||||
className="relative rounded-2xl p-2 text-stone-500 transition-colors hover:bg-stone-100 hover:text-stone-700 dark:text-stone-400 dark:hover:bg-stone-800 dark:hover:text-stone-100"
|
||||
className="relative rounded-2xl p-2 text-stone-500 transition-colors hover:bg-stone-100 hover:text-stone-700 dark:text-stone-400 dark:hover:bg-[#162038] dark:hover:text-stone-100"
|
||||
>
|
||||
<Bell className="h-5 w-5" />
|
||||
{unreadCount > 0 ? (
|
||||
@@ -161,13 +161,13 @@ export default function TopBar() {
|
||||
</button>
|
||||
|
||||
{showNotifs ? (
|
||||
<div className="absolute right-0 top-full z-50 mt-2 w-80 rounded-[1.75rem] border border-stone-200/80 bg-white/95 p-4 shadow-[0_20px_60px_rgba(0,0,0,0.12)] backdrop-blur dark:border-stone-800 dark:bg-stone-950/95 dark:shadow-[0_20px_60px_rgba(0,0,0,0.35)]">
|
||||
<div className="absolute right-0 top-full z-50 mt-2 w-80 rounded-[1.75rem] border border-stone-200/80 bg-white/95 p-4 shadow-[0_20px_60px_rgba(0,0,0,0.12)] backdrop-blur dark:border-blue-900 dark:bg-[#07101e]/95 dark:shadow-[0_20px_60px_rgba(0,0,0,0.35)]">
|
||||
<div className="mb-2 flex items-center justify-between gap-2">
|
||||
<p className="text-sm font-medium text-stone-950 dark:text-stone-100">{dict.notifications}</p>
|
||||
<p className="text-sm font-medium text-blue-950 dark:text-stone-100">{dict.notifications}</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => openNotificationsInbox()}
|
||||
className="text-xs font-medium text-amber-700 hover:text-stone-950 dark:text-amber-300 dark:hover:text-white"
|
||||
className="text-xs font-medium text-orange-700 hover:text-blue-900 dark:text-orange-300 dark:hover:text-white"
|
||||
>
|
||||
View all
|
||||
</button>
|
||||
@@ -187,11 +187,11 @@ export default function TopBar() {
|
||||
type="button"
|
||||
onClick={() => openNotificationsInbox(notification.id)}
|
||||
className={[
|
||||
'w-full rounded-2xl px-3 py-2 text-left transition-colors hover:bg-stone-100 dark:hover:bg-stone-800',
|
||||
'w-full rounded-2xl px-3 py-2 text-left transition-colors hover:bg-stone-100 dark:hover:bg-[#162038]',
|
||||
notification.readAt ? 'opacity-80' : '',
|
||||
].join(' ')}
|
||||
>
|
||||
<p className="truncate text-sm font-medium text-stone-950 dark:text-stone-100">
|
||||
<p className="truncate text-sm font-medium text-blue-950 dark:text-stone-100">
|
||||
{notification.title}
|
||||
</p>
|
||||
<p className="truncate text-xs text-stone-500 dark:text-stone-400">
|
||||
@@ -205,7 +205,7 @@ export default function TopBar() {
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-amber-400 text-xs font-semibold text-stone-950">
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-orange-400 text-xs font-semibold text-blue-950">
|
||||
{userInitials}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -177,7 +177,7 @@ export default function EditMemberModal({
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-black/30 backdrop-blur-sm"
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-[#07101e]/30 backdrop-blur-sm"
|
||||
onClick={(e) => { if (e.target === e.currentTarget && !busy) onClose() }}
|
||||
>
|
||||
<div
|
||||
@@ -197,7 +197,7 @@ export default function EditMemberModal({
|
||||
</div>
|
||||
<div className="ml-auto">
|
||||
{isPending && (
|
||||
<span className="text-xs px-2 py-1 rounded-full bg-amber-50 dark:bg-amber-950/30 text-amber-700 dark:text-amber-400 border border-amber-100 dark:border-amber-900/50">
|
||||
<span className="text-xs px-2 py-1 rounded-full bg-orange-50 dark:bg-orange-950/30 text-orange-700 dark:text-orange-400 border border-orange-100 dark:border-orange-900/50">
|
||||
{t.pendingInvite}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -136,7 +136,7 @@ export default function InviteModal({ open, onClose, onInvite }: Props) {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-black/30 backdrop-blur-sm"
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-[#07101e]/30 backdrop-blur-sm"
|
||||
onClick={(e) => { if (e.target === e.currentTarget) onClose() }}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -151,9 +151,9 @@ function AccessCell({ access, label, limitedNote }: { access: Access; label: { f
|
||||
return (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="w-3.5 h-3.5 flex-shrink-0 flex items-center justify-center">
|
||||
<div className="w-2.5 h-0.5 rounded bg-amber-500" />
|
||||
<div className="w-2.5 h-0.5 rounded bg-orange-500" />
|
||||
</div>
|
||||
<span className="text-xs text-amber-700 dark:text-amber-400">{limitedNote || label.limited}</span>
|
||||
<span className="text-xs text-orange-700 dark:text-orange-400">{limitedNote || label.limited}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ export default function StatCard({
|
||||
change,
|
||||
vsLastMonthLabel = 'vs last month',
|
||||
icon: Icon,
|
||||
iconColor = 'text-amber-700 dark:text-amber-300',
|
||||
iconBg = 'bg-amber-50 dark:bg-amber-950/30',
|
||||
iconColor = 'text-orange-700 dark:text-orange-300',
|
||||
iconBg = 'bg-orange-50 dark:bg-orange-950/30',
|
||||
}: StatCardProps) {
|
||||
const isPositive = change !== undefined && change >= 0
|
||||
const isNegative = change !== undefined && change < 0
|
||||
@@ -27,7 +27,7 @@ export default function StatCard({
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-stone-500 dark:text-stone-400">{title}</p>
|
||||
<p className="mt-1 text-2xl font-bold text-stone-950 dark:text-stone-50">{value}</p>
|
||||
<p className="mt-1 text-2xl font-bold text-blue-950 dark:text-stone-50">{value}</p>
|
||||
{change !== undefined && (
|
||||
<div className="mt-2 flex items-center gap-1">
|
||||
<span
|
||||
|
||||
Reference in New Issue
Block a user