Add production-ready SuperAdmin API features for tenants, SMS, servers, and plugins.
Includes mobile auth, get_user/get_version, SMS wallet parity endpoints, appearance backfill, and related Prisma migrations. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
/** Shared appearance helpers for import/backfill scripts (no Vue deps). */
|
||||
|
||||
export type RegistryUser = {
|
||||
avatar?: string | null
|
||||
color?: string | null
|
||||
secondary_color?: string | null
|
||||
background_color?: string | null
|
||||
name?: string | null
|
||||
name_fa?: string | null
|
||||
theme?: string | null
|
||||
mode?: string | null
|
||||
node_server?: string | null
|
||||
app_ui_config?: unknown
|
||||
user?: RegistryUser
|
||||
}
|
||||
|
||||
export function pickRegistryPayload(raw: any): RegistryUser {
|
||||
if (raw?.user && typeof raw.user === 'object') {
|
||||
return { ...raw, ...raw.user }
|
||||
}
|
||||
return raw || {}
|
||||
}
|
||||
|
||||
export function resolveAvatarUrl(raw: string | null | undefined, registryBase: string) {
|
||||
if (!raw) return null
|
||||
if (/^https?:\/\//i.test(raw)) return raw
|
||||
if (/^data:/i.test(raw)) return raw
|
||||
const base = registryBase.replace(/\/get_user\/?$/i, '').replace(/\/+$/, '')
|
||||
return `${base}/${String(raw).replace(/^\/+/, '')}`
|
||||
}
|
||||
|
||||
export function buildHamkarUiFromBrand(input: {
|
||||
primaryColor?: string | null
|
||||
secondaryColor?: string | null
|
||||
backgroundColor?: string | null
|
||||
settingsManaged?: boolean
|
||||
registryMode?: string | null
|
||||
settings?: {
|
||||
pricing_box_theme?: string
|
||||
price_font_size?: string
|
||||
orderUI?: string
|
||||
}
|
||||
}) {
|
||||
return {
|
||||
kind: 'hamkar' as const,
|
||||
settingsManaged: Boolean(input.settingsManaged),
|
||||
registryMode: input.registryMode || 'dynamicMode',
|
||||
brand: {
|
||||
// Keep nulls — do NOT invent #1d4ed8 (causes wrong accent vs live registry)
|
||||
primaryColor: input.primaryColor || null,
|
||||
secondaryColor: input.secondaryColor || null,
|
||||
backgroundColor: input.backgroundColor || null,
|
||||
},
|
||||
settings: {
|
||||
pricing_box_theme: String(input.settings?.pricing_box_theme || '1'),
|
||||
price_font_size: String(input.settings?.price_font_size || 'بزرگ'),
|
||||
orderUI: String(input.settings?.orderUI || 'old'),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function buildKhanegiUiFromColors(input: {
|
||||
primary?: string | null
|
||||
secondary?: string | null
|
||||
background?: string | null
|
||||
existing?: any
|
||||
}) {
|
||||
if (
|
||||
input.existing &&
|
||||
typeof input.existing === 'object' &&
|
||||
(input.existing.schemaId === 'ui-config' || input.existing.app)
|
||||
) {
|
||||
return input.existing
|
||||
}
|
||||
|
||||
const primary = input.primary || '#0A1B37'
|
||||
const secondary = input.secondary || '#e3b056'
|
||||
const pageBg = input.background || '#121216'
|
||||
const surface = '#222228'
|
||||
|
||||
const dark = {
|
||||
primary,
|
||||
secondary,
|
||||
tertiary: secondary,
|
||||
background: '#ffffff',
|
||||
surface,
|
||||
surfaceHover: '#2c2c34',
|
||||
textPrimary: '#ffffff',
|
||||
textSecondary: 'rgba(255, 255, 255, 0.45)',
|
||||
textSubtle: 'rgba(255, 255, 255, 0.35)',
|
||||
border: 'rgba(255, 255, 255, 0.16)',
|
||||
borderSubtle: 'rgba(255, 255, 255, 0.12)',
|
||||
pageBg,
|
||||
pageBgMobile: pageBg,
|
||||
onAccent: '#0a0a0a',
|
||||
success: '#16A34A',
|
||||
warning: '#F59E0B',
|
||||
danger: '#DC2626',
|
||||
}
|
||||
|
||||
const light = {
|
||||
...dark,
|
||||
surface: '#ffffff',
|
||||
surfaceHover: '#fffefb',
|
||||
textPrimary: '#1c1916',
|
||||
textSecondary: '#5c564d',
|
||||
textSubtle: '#8a8278',
|
||||
border: 'rgba(0, 0, 0, 0.08)',
|
||||
borderSubtle: 'rgba(0, 0, 0, 0.06)',
|
||||
pageBg: pageBg === '#121216' ? '#f5f2ed' : pageBg,
|
||||
pageBgMobile: pageBg === '#121216' ? '#faf8f5' : pageBg,
|
||||
onAccent: '#ffffff',
|
||||
}
|
||||
|
||||
return {
|
||||
schemaId: 'ui-config',
|
||||
version: '1.0.0',
|
||||
app: {
|
||||
schemaId: 'app',
|
||||
version: '1.0.0',
|
||||
direction: 'rtl',
|
||||
locale: 'fa-IR',
|
||||
startRoute: 'home',
|
||||
theme: {
|
||||
presetId: 'custom',
|
||||
mode: 'dark',
|
||||
colors: { ...dark },
|
||||
schemes: { dark: { ...dark }, light: { ...light } },
|
||||
borderRadius: { sm: 8, md: 12, lg: 16 },
|
||||
},
|
||||
navigation: {
|
||||
type: 'sidebar+bottom',
|
||||
sidebar: [
|
||||
{ id: 'home', label: 'داشبورد', icon: 'vuesax-linear:chart', route: 'home', order: 1, visible: true },
|
||||
{ id: 'products', label: 'معاملات', icon: 'vuesax-linear:shop', route: 'products', order: 2, visible: true },
|
||||
{ id: 'transactions', label: 'تراکنشها', icon: 'vuesax-linear:receipt-item', route: 'transactions', order: 3, visible: true },
|
||||
{ id: 'wallet', label: 'کیف پول', icon: 'vuesax-linear:wallet-2', route: 'wallet', order: 4, visible: true },
|
||||
{ id: 'user', label: 'حساب کاربری', icon: 'vuesax-linear:user', route: 'user', order: 5, visible: true },
|
||||
],
|
||||
bottom: [
|
||||
{ id: 'home', label: 'خانه', icon: 'vuesax-linear:home-2', route: 'home', order: 1, visible: true },
|
||||
{ id: 'products', label: 'معامله', icon: 'vuesax-linear:shop', route: 'products', order: 2, visible: true },
|
||||
{ id: 'transactions', label: 'سوابق', icon: 'vuesax-linear:receipt-item', route: 'transactions', order: 3, visible: true },
|
||||
{ id: 'wallet', label: 'کیف پول', icon: 'vuesax-linear:wallet-2', route: 'wallet', order: 4, visible: true },
|
||||
{ id: 'user', label: 'پروفایل', icon: 'vuesax-linear:user', route: 'user', order: 5, visible: true },
|
||||
],
|
||||
sidebarReferral: {
|
||||
visible: true,
|
||||
title: 'دعوت از دوستان',
|
||||
subtitle: 'کسب درآمد',
|
||||
route: 'earnMoney',
|
||||
},
|
||||
},
|
||||
header: {
|
||||
visible: true,
|
||||
showLogo: true,
|
||||
showNotifications: true,
|
||||
showProfile: true,
|
||||
brandSubtitle: 'پنل کاربری',
|
||||
},
|
||||
},
|
||||
pages: {},
|
||||
_backfill: 'colors-from-live-registry',
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user