Localize order modals, add dual logos, and improve admin order tools.

Farsi business order/variation UI, light/dark logo upload on business profile, payment order steps, variation editing, super-admin site links, and checkout/auth fixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-26 00:21:48 +03:30
co-authored by Cursor
parent dc570c1e7f
commit 5e799eddf9
30 changed files with 779 additions and 169 deletions
@@ -14,6 +14,7 @@ import { PageTitle } from '../components/PageTitle'
import { ImageCropper } from '../components/ImageCropper'
import { MultiSelectDropdown } from '../components/MultiSelectDropdown'
import { RichTextEditor } from '../components/RichTextEditor'
import { Switch } from '../components/Switch'
import { useToast } from '../context/ToastContext'
import { useT } from '../i18n/useT'
import { ApiError } from '../lib/api'
@@ -80,6 +81,9 @@ export function BusinessProfilePage() {
const [vision, setVision] = useState('')
const [logo, setLogo] = useState<string | null>(null)
const [logoMediaId, setLogoMediaId] = useState<string | null>(null)
const [logoDark, setLogoDark] = useState<string | null>(null)
const [logoDarkMediaId, setLogoDarkMediaId] = useState<string | null>(null)
const [logoModeDark, setLogoModeDark] = useState(false)
const [addresses, setAddresses] = useState<AddressDraft[]>([createEmptyAddressItem()])
const [phoneNumbers, setPhoneNumbers] = useState<BusinessPhoneNumber[]>([
createEmptyPhone(),
@@ -153,6 +157,8 @@ export function BusinessProfilePage() {
setVision(profileData.profile.vision)
setLogo(profileData.profile.logoUrl)
setLogoMediaId(profileData.profile.logoMediaId)
setLogoDark(profileData.profile.logoDarkUrl)
setLogoDarkMediaId(profileData.profile.logoDarkMediaId)
const nextAddresses =
profileData.addresses.length > 0
@@ -273,6 +279,11 @@ export function BusinessProfilePage() {
'business-logo.png',
logoMediaId,
)
const nextLogoDarkMediaId = await resolveDataUrlToMediaId(
logoDark,
'business-logo-dark.png',
logoDarkMediaId,
)
const payloadAddresses = addresses
.filter(
@@ -309,6 +320,7 @@ export function BusinessProfilePage() {
phoneNumbers: payloadPhones,
socialMedia,
logoMediaId: nextLogoMediaId,
logoDarkMediaId: nextLogoDarkMediaId,
categoryIds,
addresses: payloadAddresses,
})
@@ -358,9 +370,27 @@ export function BusinessProfilePage() {
<div className={formStyles.formGrid}>
<div className={`${formStyles.field} ${styles.logoCol}`}>
<label>{t('bizProfile.logo')}</label>
<div className={styles.logoModeRow}>
<span
className={`${styles.logoModeLabel} ${!logoModeDark ? styles.logoModeLabelActive : ''}`}
>
{t('bizProfile.logo.light')}
</span>
<Switch
checked={logoModeDark}
onChange={setLogoModeDark}
aria-label={t('bizProfile.logo.modeSwitch')}
/>
<span
className={`${styles.logoModeLabel} ${logoModeDark ? styles.logoModeLabelActive : ''}`}
>
{t('bizProfile.logo.dark')}
</span>
</div>
<ImageCropper
value={logo}
onChange={setLogo}
key={logoModeDark ? 'logo-dark' : 'logo-light'}
value={logoModeDark ? logoDark : logo}
onChange={logoModeDark ? setLogoDark : setLogo}
outputFormat="png"
accept="image/png"
uploadLabel={t('bizProfile.logo.upload')}