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
+33 -12
View File
@@ -10,6 +10,7 @@ import {
RotateCcw,
Search,
ShieldPlus,
X,
} from 'lucide-react'
import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal'
import { DomainLinksOverflowMenu } from '../components/DomainLinksOverflowMenu'
@@ -107,6 +108,7 @@ export function WebsitesPage() {
const [removeTarget, setRemoveTarget] = useState<DomainListItem | null>(null)
const [togglingActiveId, setTogglingActiveId] = useState<number | null>(null)
const [deployingId, setDeployingId] = useState<DomainListItem['id'] | null>(null)
const [deployError, setDeployError] = useState('')
const [syncingSsl, setSyncingSsl] = useState(false)
const [issuingWebsiteSsl, setIssuingWebsiteSsl] = useState(false)
const [issuingSslId, setIssuingSslId] = useState<DomainListItem['id'] | null>(null)
@@ -356,7 +358,7 @@ export function WebsitesPage() {
flushSync(() => {
setDeployingId(domain.id)
})
setError('')
setDeployError('')
showToast(`Deploying "${domain.host}"…`, 'info')
try {
@@ -376,15 +378,17 @@ export function WebsitesPage() {
),
}
})
showToast(
result.lastDeployStatus === 'success'
? `Deploy succeeded for "${result.host}".`
: `Deploy finished for "${result.host}" (${result.lastDeployStatus ?? 'unknown'}).`,
result.lastDeployStatus === 'success' ? 'success' : 'info',
)
if (result.lastDeployStatus === 'success') {
showToast(`Deploy succeeded for "${result.host}".`, 'success')
return
}
const detail =
result.message?.trim() ||
`Deploy finished for "${result.host}" with status ${result.lastDeployStatus ?? 'unknown'}.`
setDeployError(`${result.host}: ${detail}`)
} catch (err) {
const message = err instanceof ApiError ? err.message : 'Deploy failed.'
setError(message)
setDeployError(`${domain.host}: ${message}`)
setData((prev) => {
if (!prev) return prev
return {
@@ -400,7 +404,6 @@ export function WebsitesPage() {
),
}
})
showToast(message, 'error')
} finally {
setDeployingId(null)
}
@@ -511,6 +514,24 @@ export function WebsitesPage() {
</form>
</div>
{deployError ? (
<div className={styles.deployErrorTip} role="alert">
<AlertTriangle size={18} className={styles.deployErrorIcon} aria-hidden />
<div className={styles.deployErrorBody}>
<p className={styles.deployErrorTitle}>Deploy failed</p>
<pre className={styles.deployErrorDetail}>{deployError}</pre>
</div>
<button
type="button"
className={styles.deployErrorDismiss}
onClick={() => setDeployError('')}
aria-label="Dismiss deploy error"
>
<X size={16} aria-hidden />
</button>
</div>
) : null}
<div className={tableStyles.tablePanel}>
<div className={tableStyles.tableWrap}>
<div className={tableStyles.tableHeader}>
@@ -527,10 +548,10 @@ export function WebsitesPage() {
</div>
{error && (
<div style={{ padding: 16 }}>
<div className={tableStyles.meta} style={{ color: '#b91c1c' }}>
<div className={styles.listErrorWrap}>
<p className={tableStyles.alertError} role="alert">
{error}
</div>
</p>
</div>
)}