Add website schema settings, SEO meta overrides, and resilient bulk SMS.
Business admins can configure site-wide Schema.org and optional per-item SEO title/description; mass SMS continues on failures with an end report. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
15aad9f9d8
commit
c2ede07e73
@@ -11,6 +11,7 @@ import { CitySearchSelect } from '../components/CitySearchSelect'
|
||||
import { CategorySearchSelect } from '../components/CategorySearchSelect'
|
||||
import { ImageCropper } from '../components/ImageCropper'
|
||||
import { ImageUploader } from '../components/ImageUploader'
|
||||
import { SeoMetaFields } from '../components/SeoMetaFields'
|
||||
import { useT } from '../i18n/useT'
|
||||
import { translate } from '../i18n/messages'
|
||||
import { ApiError, isAbortError } from '../lib/api'
|
||||
@@ -34,6 +35,7 @@ import {
|
||||
} from '../services/userProductsService'
|
||||
import { galleryMediaIdsAfterChange, resolveDataUrlToMediaId, resolveDataUrlsToMediaIds } from '../services/mediaService'
|
||||
import { formatIrtInput, parseIrtInput } from '../utils/irtPrice'
|
||||
import { seoMetaPayload } from '../utils/seoMeta'
|
||||
import styles from './AddCustomerProductPage.module.css'
|
||||
|
||||
type StepId = 1 | 2 | 3
|
||||
@@ -110,6 +112,8 @@ export function AddCustomerProductPage() {
|
||||
const [titleFa, setTitleFa] = useState('')
|
||||
const [titleEn, setTitleEn] = useState('')
|
||||
const [description, setDescription] = useState('')
|
||||
const [seoMetaTitle, setSeoMetaTitle] = useState('')
|
||||
const [seoMetaDescription, setSeoMetaDescription] = useState('')
|
||||
const [priceInput, setPriceInput] = useState('')
|
||||
const [priceUnit, setPriceUnit] = useState<UserProductPriceCurrency>('IRT')
|
||||
const [priceByExpert, setPriceByExpert] = useState(false)
|
||||
@@ -207,6 +211,8 @@ export function AddCustomerProductPage() {
|
||||
setTitleFa(product.titleFa ?? product.title ?? '')
|
||||
setTitleEn(product.titleEn ?? '')
|
||||
setDescription(product.description ?? '')
|
||||
setSeoMetaTitle(product.seoMetaTitle ?? '')
|
||||
setSeoMetaDescription(product.seoMetaDescription ?? '')
|
||||
setPriceInput(
|
||||
product.price != null ? formatIrtInput(String(product.price)) : '',
|
||||
)
|
||||
@@ -376,6 +382,7 @@ export function AddCustomerProductPage() {
|
||||
titleFa: titleFa.trim(),
|
||||
titleEn: titleEn.trim() || undefined,
|
||||
description: description.trim() || undefined,
|
||||
...seoMetaPayload(seoMetaTitle, seoMetaDescription),
|
||||
categoryId,
|
||||
price: price ?? undefined,
|
||||
priceCurrency: priceUnit,
|
||||
@@ -617,6 +624,19 @@ export function AddCustomerProductPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<SeoMetaFields
|
||||
seoMetaTitle={seoMetaTitle}
|
||||
seoMetaDescription={seoMetaDescription}
|
||||
onTitleChange={setSeoMetaTitle}
|
||||
onDescriptionChange={setSeoMetaDescription}
|
||||
disabled={submitting}
|
||||
hint={t('seo.meta.hint')}
|
||||
titleLabel={t('seo.meta.title')}
|
||||
descriptionLabel={t('seo.meta.description')}
|
||||
titlePlaceholder={t('seo.meta.titlePlaceholder')}
|
||||
descriptionPlaceholder={t('seo.meta.descriptionPlaceholder')}
|
||||
/>
|
||||
|
||||
<div className={styles.priceRow}>
|
||||
<label
|
||||
className={`${styles.checkRow} ${styles.col6}`}
|
||||
|
||||
Reference in New Issue
Block a user