From f21041b95056659cb2d5867fb383e39781a7e532 Mon Sep 17 00:00:00 2001 From: Alireza Hassani Date: Tue, 11 Aug 2026 15:46:18 +0330 Subject: [PATCH] Make public invoices RTL for Farsi businesses and fix invoice back-arrow direction. Also add optional English name fields on the add-customer modal to match the API. Co-authored-by: Cursor --- .../components/AddCustomerModal.module.css | 28 +++- .../src/components/AddCustomerModal.tsx | 63 +++++++-- .../src/components/InvoiceForm.module.css | 4 + apps/business/src/i18n/messages.ts | 18 +++ apps/business/src/services/customerService.ts | 2 + .../src/pages/PublicInvoicePage.module.css | 23 +++- .../src/pages/PublicInvoicePage.tsx | 130 ++++++++++++++---- apps/super-admin/src/types/invoice.ts | 6 +- docs/PROJECT_CONTEXT.md | 1 + 9 files changed, 231 insertions(+), 44 deletions(-) diff --git a/apps/business/src/components/AddCustomerModal.module.css b/apps/business/src/components/AddCustomerModal.module.css index fe43099..03d018f 100644 --- a/apps/business/src/components/AddCustomerModal.module.css +++ b/apps/business/src/components/AddCustomerModal.module.css @@ -1,3 +1,7 @@ +.wideModal { + max-width: min(800px, calc(100vw - 32px)); +} + .formGrid { display: grid; grid-template-columns: repeat(2, 1fr); @@ -8,15 +12,29 @@ grid-column: 1 / -1; } -.hint { - margin-bottom: 12px; - font-size: 12px; - line-height: 1.45; +.keyPoints { + margin: 0 0 14px; + padding-inline-start: 1.15em; + list-style: disc; + font-size: 12.5px; + line-height: 1.5; color: var(--text-secondary); } -@media (max-width: 520px) { +.keyPoints li { + white-space: nowrap; +} + +.keyPoints li + li { + margin-top: 4px; +} + +@media (max-width: 640px) { .formGrid { grid-template-columns: 1fr; } + + .keyPoints li { + white-space: normal; + } } diff --git a/apps/business/src/components/AddCustomerModal.tsx b/apps/business/src/components/AddCustomerModal.tsx index 1c290a0..d3bdcd5 100644 --- a/apps/business/src/components/AddCustomerModal.tsx +++ b/apps/business/src/components/AddCustomerModal.tsx @@ -28,6 +28,8 @@ export function AddCustomerModal({ open, onClose, onCreated }: AddCustomerModalP const [closing, setClosing] = useState(false) const [firstName, setFirstName] = useState('') const [lastName, setLastName] = useState('') + const [firstNameEn, setFirstNameEn] = useState('') + const [lastNameEn, setLastNameEn] = useState('') const [cellNumber, setCellNumber] = useState('') const [password, setPassword] = useState('') const [passwordConfirm, setPasswordConfirm] = useState('') @@ -40,6 +42,8 @@ export function AddCustomerModal({ open, onClose, onCreated }: AddCustomerModalP setClosing(false) setFirstName('') setLastName('') + setFirstNameEn('') + setLastNameEn('') setCellNumber('') setPassword('') setPasswordConfirm('') @@ -86,6 +90,16 @@ export function AddCustomerModal({ open, onClose, onCreated }: AddCustomerModalP } } + const trimmedFirstEn = firstNameEn.trim() + const trimmedLastEn = lastNameEn.trim() + if ( + (trimmedFirstEn && trimmedFirstEn.length < 2) || + (trimmedLastEn && trimmedLastEn.length < 2) + ) { + setError(t('customers.addModal.errorNameEnLength')) + return + } + setIsSubmitting(true) setError('') try { @@ -93,6 +107,8 @@ export function AddCustomerModal({ open, onClose, onCreated }: AddCustomerModalP cellNumber: normalizedCell, firstName: firstName.trim(), lastName: lastName.trim(), + ...(trimmedFirstEn ? { firstNameEn: trimmedFirstEn } : {}), + ...(trimmedLastEn ? { lastNameEn: trimmedLastEn } : {}), ...(trimmedPassword ? { password: trimmedPassword } : {}), }) onCreated({ @@ -119,7 +135,7 @@ export function AddCustomerModal({ open, onClose, onCreated }: AddCustomerModalP onClick={onClose} >
e.stopPropagation()} role="dialog" aria-modal="true" @@ -132,7 +148,6 @@ export function AddCustomerModal({ open, onClose, onCreated }: AddCustomerModalP

{t('customers.addModal.title')}

-

{t('customers.addModal.subtitle')}

) : null} diff --git a/apps/super-admin/src/types/invoice.ts b/apps/super-admin/src/types/invoice.ts index f76f9c1..fc44795 100644 --- a/apps/super-admin/src/types/invoice.ts +++ b/apps/super-admin/src/types/invoice.ts @@ -91,7 +91,11 @@ export type PublicInvoice = { name: string | null topText: string | null issuedAt: string - business?: Invoice['business'] + /** Business dashboard default locale — drives public invoice RTL/LTR. */ + locale?: 'en' | 'fa' + business?: Invoice['business'] & { + displayName?: string + } user?: { firstName: string | null lastName: string | null diff --git a/docs/PROJECT_CONTEXT.md b/docs/PROJECT_CONTEXT.md index 1121605..276f660 100644 --- a/docs/PROJECT_CONTEXT.md +++ b/docs/PROJECT_CONTEXT.md @@ -395,6 +395,7 @@ Auth: platform template routes → super-admin. Business routes → `BusinessPer **Public invoice viewer:** - Super-admin SPA `/invoices/:publicId` (`PublicInvoicePage`) — print-to-PDF; opaque 12-digit `publicId` +- Payload includes `locale` (`fa` | `en` from business `settings.branding.defaultLocale`) — page is RTL + Farsi chrome when `fa` - Platform invoices: `https://{INVOICE_PUBLIC_DOMAIN}/invoices/{publicId}` (default `meshkee.com`) - Business invoices: `https://{primaryBusinessDomain}/invoices/{publicId}` (e.g. `sanihome.ir`)