update ar currency
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import { formatCurrency } from '@rentaldrivego/types'
|
||||
import { formatCurrency, getCurrencyLabel } from '@rentaldrivego/types'
|
||||
import { apiFetch } from '@/lib/api'
|
||||
import { useDashboardI18n } from '@/components/I18nProvider'
|
||||
|
||||
@@ -296,11 +296,11 @@ const copy = {
|
||||
},
|
||||
}
|
||||
|
||||
function discountLabel(offer: Offer, t: typeof copy['en']): string {
|
||||
function discountLabel(offer: Offer, t: typeof copy['en'], language: 'en' | 'fr' | 'ar'): string {
|
||||
if (offer.type === 'PERCENTAGE') return `${offer.discountValue}%`
|
||||
if (offer.type === 'FIXED_AMOUNT') return formatCurrency(offer.discountValue, 'MAD')
|
||||
if (offer.type === 'FIXED_AMOUNT') return formatCurrency(offer.discountValue, 'MAD', language)
|
||||
if (offer.type === 'FREE_DAY') return t.freeDay
|
||||
if (offer.type === 'SPECIAL_RATE') return `${offer.specialRate ?? offer.discountValue} MAD/day`
|
||||
if (offer.type === 'SPECIAL_RATE') return `${offer.specialRate ?? offer.discountValue} ${getCurrencyLabel(language)}${language === 'fr' ? '/jour' : language === 'ar' ? '/يوم' : '/day'}`
|
||||
return String(offer.discountValue)
|
||||
}
|
||||
|
||||
@@ -507,7 +507,7 @@ export default function OffersPage() {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p className="text-2xl font-bold text-slate-900">{discountLabel(offer, t)}</p>
|
||||
<p className="text-2xl font-bold text-slate-900">{discountLabel(offer, t, language)}</p>
|
||||
|
||||
{offer.description && (
|
||||
<p className="text-sm text-slate-500 line-clamp-2">{offer.description}</p>
|
||||
|
||||
@@ -4,6 +4,7 @@ import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { useState } from 'react'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import { getCurrencyLabel } from '@rentaldrivego/types'
|
||||
import { useDashboardI18n } from '@/components/I18nProvider'
|
||||
import { apiFetch } from '@/lib/api'
|
||||
import PublicShell from '@/components/layout/PublicShell'
|
||||
@@ -739,7 +740,7 @@ export default function SignUpPage() {
|
||||
<div className="rounded-3xl border border-slate-200 bg-slate-50 p-5 text-sm text-slate-600">
|
||||
<p><span className="font-semibold text-slate-900">{dict.reviewWorkspace}:</span> {form.companyName.fr || form.companyName.ar || dict.companyFallback}{form.companyName.fr && form.companyName.ar ? <span className="ml-2 text-slate-400">/ {form.companyName.ar}</span> : null}</p>
|
||||
<p className="mt-2"><span className="font-semibold text-slate-900">{dict.reviewLegalName}:</span> {form.legalName || '—'}</p>
|
||||
<p className="mt-2"><span className="font-semibold text-slate-900">{dict.reviewPlan}:</span> {form.plan} · {dict.billingPeriodOptions[form.billingPeriod]} · MAD</p>
|
||||
<p className="mt-2"><span className="font-semibold text-slate-900">{dict.reviewPlan}:</span> {form.plan} · {dict.billingPeriodOptions[form.billingPeriod]} · {getCurrencyLabel(language)}</p>
|
||||
<p className="mt-2"><span className="font-semibold text-slate-900">{dict.reviewOwnerEmail}:</span> {form.email || '—'}</p>
|
||||
<p className="mt-2"><span className="font-semibold text-slate-900">{dict.reviewCompanyEmail}:</span> {form.companyEmail || '—'}</p>
|
||||
<p className="mt-2"><span className="font-semibold text-slate-900">{dict.reviewPhone}:</span> {form.companyPhone || '—'}</p>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Link from 'next/link'
|
||||
import { formatCurrency, type Locale } from '@rentaldrivego/types'
|
||||
|
||||
interface Vehicle {
|
||||
id: string
|
||||
@@ -38,8 +39,8 @@ interface Dict {
|
||||
availableVehicles: string
|
||||
}
|
||||
|
||||
function formatCents(cents: number) {
|
||||
return `${(cents / 100).toLocaleString('fr-MA', { minimumFractionDigits: 2 })} MAD`
|
||||
function formatCents(cents: number, language: Locale) {
|
||||
return formatCurrency(cents, 'MAD', language)
|
||||
}
|
||||
|
||||
function formatAvailabilityDate(value?: string | null) {
|
||||
@@ -55,7 +56,7 @@ function getStatusCopy(vehicle: Vehicle, dict: Dict) {
|
||||
return dict.available
|
||||
}
|
||||
|
||||
export default function ExploreVehicleGrid({ vehicles, dict }: { vehicles: Vehicle[]; dict: Dict }) {
|
||||
export default function ExploreVehicleGrid({ vehicles, dict, language }: { vehicles: Vehicle[]; dict: Dict; language: Locale }) {
|
||||
return (
|
||||
<section>
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -90,7 +91,7 @@ export default function ExploreVehicleGrid({ vehicles, dict }: { vehicles: Vehic
|
||||
<div className="mt-4 flex items-end justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">{dict.from}</p>
|
||||
<p className="truncate text-xl font-black text-stone-900 dark:text-stone-100">{formatCents(vehicle.dailyRate)}</p>
|
||||
<p className="truncate text-xl font-black text-stone-900 dark:text-stone-100">{formatCents(vehicle.dailyRate, language)}</p>
|
||||
</div>
|
||||
<Link
|
||||
href={`/explore/${vehicle.company.slug}/vehicles/${vehicle.id}`}
|
||||
|
||||
@@ -145,7 +145,7 @@ export default async function CompanyProfilePage({ params }: { params: { slug: s
|
||||
</p>
|
||||
)}
|
||||
<div className="mt-4 flex items-end justify-between gap-3">
|
||||
<p className="min-w-0 truncate text-xl font-black text-stone-900 dark:text-stone-100">{formatCurrency(vehicle.dailyRate, 'MAD')}</p>
|
||||
<p className="min-w-0 truncate text-xl font-black text-stone-900 dark:text-stone-100">{formatCurrency(vehicle.dailyRate, 'MAD', language)}</p>
|
||||
<Link href={`/explore/${params.slug}/vehicles/${vehicle.id}`} className="shrink-0 rounded-full bg-blue-900 px-4 py-2 text-sm font-semibold text-white transition hover:bg-orange-700 dark:bg-orange-500 dark:text-white dark:hover:bg-orange-400">{dict.viewVehicle}</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -247,7 +247,7 @@ export default async function VehicleDetailPage({ params }: { params: { slug: st
|
||||
<h1 className="text-3xl font-black text-stone-900 dark:text-stone-100">{vehicle.make} {vehicle.model}</h1>
|
||||
<p className="text-stone-500 dark:text-stone-400">{vehicle.year} · {vehicle.category}</p>
|
||||
<p className="text-3xl font-black text-stone-900 dark:text-stone-100">
|
||||
{formatCurrency(vehicle.dailyRate, 'MAD')}
|
||||
{formatCurrency(vehicle.dailyRate, 'MAD', language)}
|
||||
<span className="text-base font-medium text-stone-500 dark:text-stone-400"> {dict.perDay}</span>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -292,7 +292,7 @@ export default async function ExplorePage({ searchParams }: { searchParams?: Rec
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ExploreVehicleGrid vehicles={vehicles} dict={dict} />
|
||||
<ExploreVehicleGrid vehicles={vehicles} dict={dict} language={language} />
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-stone-900 dark:text-stone-100">{dict.browseByCategory}</h2>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { PLAN_FEATURES, PLAN_PRICES } from '@rentaldrivego/types'
|
||||
import { getCurrencyLabel, PLAN_FEATURES, PLAN_PRICES } from '@rentaldrivego/types'
|
||||
import { useMarketplacePreferences } from '@/components/MarketplaceShell'
|
||||
import { marketplaceFetchOrDefault } from '@/lib/api'
|
||||
import { resolveBrowserAppUrl } from '@/lib/appUrls'
|
||||
@@ -96,6 +96,7 @@ function annualSavingsPct(prices: PricingMatrix, plan: string): number {
|
||||
|
||||
export default function PricingClient({ initialPricing = DEFAULT_PRICING }: { initialPricing?: PlatformPricing }) {
|
||||
const { language } = useMarketplacePreferences()
|
||||
const currencyLabel = getCurrencyLabel(language)
|
||||
const dict = copy[language]
|
||||
const [billing, setBilling] = useState<Billing>('monthly')
|
||||
const [pricing, setPricing] = useState<PlatformPricing>(initialPricing)
|
||||
@@ -175,12 +176,12 @@ export default function PricingClient({ initialPricing = DEFAULT_PRICING }: { in
|
||||
<span className="text-4xl font-black text-stone-900 dark:text-stone-100">
|
||||
{displayPrice}
|
||||
</span>
|
||||
<span className="mb-1 text-lg font-semibold text-stone-500 dark:text-stone-400">MAD</span>
|
||||
<span className="mb-1 text-lg font-semibold text-stone-500 dark:text-stone-400">{currencyLabel}</span>
|
||||
<span className="mb-1 text-sm text-stone-400 dark:text-stone-500">{dict.perMonth}</span>
|
||||
</div>
|
||||
{billing === 'annual' && (
|
||||
<p className="mt-1 text-xs text-stone-400 dark:text-stone-500">
|
||||
{dict.billedAs} {annualPrice} MAD {dict.yearly}
|
||||
{dict.billedAs} {annualPrice} {currencyLabel} {dict.yearly}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { formatCurrency } from '@rentaldrivego/types'
|
||||
import { marketplacePost } from '@/lib/api'
|
||||
import { useMarketplacePreferences } from '@/components/MarketplaceShell'
|
||||
|
||||
@@ -507,7 +508,7 @@ export default function BookingForm({
|
||||
<p className="text-sm text-stone-600 dark:text-stone-400">
|
||||
{t.estimatedTotal}:{' '}
|
||||
<strong className="text-stone-900 dark:text-stone-100">
|
||||
{(dailyRate * totalDays).toLocaleString()} MAD
|
||||
{formatCurrency(dailyRate * totalDays, 'MAD', language)}
|
||||
</strong>{' '}
|
||||
({totalDays} {t.days})
|
||||
</p>
|
||||
|
||||
@@ -61,13 +61,37 @@ export const PLAN_FEATURES: Record<string, string[]> = {
|
||||
export type Locale = 'en' | 'fr' | 'ar'
|
||||
export type SupportedCurrency = 'MAD'
|
||||
|
||||
export function formatCurrency(amount: number, _currency: SupportedCurrency = 'MAD', locale: Locale = 'en'): string {
|
||||
function resolveLocale(locale?: Locale): Locale {
|
||||
if (locale) return locale
|
||||
|
||||
const lang =
|
||||
typeof globalThis === 'object' && 'document' in globalThis
|
||||
? (globalThis as { document?: { documentElement?: { lang?: string } } }).document?.documentElement?.lang
|
||||
: undefined
|
||||
|
||||
if (lang === 'en' || lang === 'fr' || lang === 'ar') {
|
||||
return lang
|
||||
}
|
||||
|
||||
return 'en'
|
||||
}
|
||||
|
||||
export function getCurrencyLabel(locale?: Locale, _currency: SupportedCurrency = 'MAD'): string {
|
||||
return resolveLocale(locale) === 'ar' ? 'درهم' : 'MAD'
|
||||
}
|
||||
|
||||
export function formatCurrency(amount: number, _currency: SupportedCurrency = 'MAD', locale?: Locale): string {
|
||||
const resolvedLocale = resolveLocale(locale)
|
||||
const divisor = 100
|
||||
const value = amount / divisor
|
||||
const localeMap: Record<Locale, string> = { en: 'en-US', fr: 'fr-FR', ar: 'ar-MA' }
|
||||
return new Intl.NumberFormat(localeMap[locale], {
|
||||
style: 'currency',
|
||||
currency: 'MAD',
|
||||
const formattedValue = new Intl.NumberFormat(localeMap[resolvedLocale], {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(value)
|
||||
const currencyLabel = getCurrencyLabel(resolvedLocale, _currency)
|
||||
|
||||
return resolvedLocale === 'en'
|
||||
? `${currencyLabel} ${formattedValue}`
|
||||
: `${formattedValue} ${currencyLabel}`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user