feat(banners): make products hero slides addable and fix theme slots
Admins can add/remove any number of product banners, and profile/fund slots keep relative storage paths for refresh-safe previews. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+27
-21
@@ -12,9 +12,6 @@ export const LEGACY_SLIDER_BANNERS_CONST_KEY = 'header_banner'
|
||||
export type AppThemeBannerKey =
|
||||
| 'homeAsset'
|
||||
| 'piggyCreate'
|
||||
| 'productsHero1'
|
||||
| 'productsHero2'
|
||||
| 'productsHero3'
|
||||
| 'referral'
|
||||
| 'share'
|
||||
| 'invite'
|
||||
@@ -31,9 +28,8 @@ export interface AppBannersValue {
|
||||
slider: IBenefits[]
|
||||
homeAsset: ThemeImagePair
|
||||
piggyCreate: ThemeImagePair
|
||||
productsHero1: ThemeImagePair
|
||||
productsHero2: ThemeImagePair
|
||||
productsHero3: ThemeImagePair
|
||||
/** اسلایدر بنر بالای صفحهٔ محصولات — تعداد آزاد */
|
||||
productsHero: ThemeImagePair[]
|
||||
referral: ThemeImagePair
|
||||
share: ThemeImagePair
|
||||
invite: ThemeImagePair
|
||||
@@ -53,9 +49,7 @@ export function emptyAppBanners(): AppBannersValue {
|
||||
slider: [],
|
||||
homeAsset: emptyThemePair(),
|
||||
piggyCreate: emptyThemePair(),
|
||||
productsHero1: emptyThemePair(),
|
||||
productsHero2: emptyThemePair(),
|
||||
productsHero3: emptyThemePair(),
|
||||
productsHero: [],
|
||||
referral: emptyThemePair(),
|
||||
share: emptyThemePair(),
|
||||
invite: emptyThemePair(),
|
||||
@@ -76,6 +70,21 @@ function normalizePair(raw: unknown): ThemeImagePair {
|
||||
}
|
||||
}
|
||||
|
||||
function pairHasImage(pair: ThemeImagePair): boolean {
|
||||
return Boolean(pair.light || pair.dark)
|
||||
}
|
||||
|
||||
/** آرایهٔ جدید یا سه اسلات قدیمی productsHero1/2/3 */
|
||||
export function normalizeProductsHero(parsed: Record<string, unknown>): ThemeImagePair[] {
|
||||
if (Array.isArray(parsed.productsHero)) {
|
||||
return parsed.productsHero.map(normalizePair)
|
||||
}
|
||||
|
||||
return [parsed.productsHero1, parsed.productsHero2, parsed.productsHero3]
|
||||
.map(normalizePair)
|
||||
.filter(pairHasImage)
|
||||
}
|
||||
|
||||
function parseSlider(raw: unknown): IBenefits[] {
|
||||
if (!raw) return []
|
||||
if (Array.isArray(raw)) return raw as IBenefits[]
|
||||
@@ -102,16 +111,15 @@ export function parseAppBanners(value: string | Record<string, unknown> | null |
|
||||
return { ...fallback, slider: parsed as IBenefits[] }
|
||||
}
|
||||
|
||||
const obj = parsed as Record<string, unknown>
|
||||
return {
|
||||
slider: parseSlider(parsed.slider),
|
||||
homeAsset: normalizePair(parsed.homeAsset),
|
||||
piggyCreate: normalizePair(parsed.piggyCreate),
|
||||
productsHero1: normalizePair(parsed.productsHero1),
|
||||
productsHero2: normalizePair(parsed.productsHero2),
|
||||
productsHero3: normalizePair(parsed.productsHero3),
|
||||
referral: normalizePair(parsed.referral),
|
||||
share: normalizePair(parsed.share),
|
||||
invite: normalizePair(parsed.invite),
|
||||
slider: parseSlider(obj.slider),
|
||||
homeAsset: normalizePair(obj.homeAsset),
|
||||
piggyCreate: normalizePair(obj.piggyCreate),
|
||||
productsHero: normalizeProductsHero(obj),
|
||||
referral: normalizePair(obj.referral),
|
||||
share: normalizePair(obj.share),
|
||||
invite: normalizePair(obj.invite),
|
||||
}
|
||||
} catch {
|
||||
return fallback
|
||||
@@ -128,9 +136,7 @@ export function serializeAppBanners(data: AppBannersValue): string {
|
||||
slider: data.slider ?? [],
|
||||
homeAsset: { ...data.homeAsset },
|
||||
piggyCreate: { ...data.piggyCreate },
|
||||
productsHero1: { ...data.productsHero1 },
|
||||
productsHero2: { ...data.productsHero2 },
|
||||
productsHero3: { ...data.productsHero3 },
|
||||
productsHero: (data.productsHero ?? []).map((pair) => ({ ...pair })),
|
||||
referral: { ...data.referral },
|
||||
share: { ...data.share },
|
||||
invite: { ...data.invite },
|
||||
|
||||
Reference in New Issue
Block a user