From 71e6655f909c0adbedec08af557eb9efc2733165 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Wed, 14 Oct 2026 17:02:10 +0330 Subject: [PATCH] feat(hamkar-ui): mobile preview and brandManaged for chrome colors Save sets brandManaged so header+menu share one color and body stays separate, without changing live apps until save. Co-authored-by: Cursor --- src/config/defaultHamkarUiConfig.ts | 9 ++++ src/config/hamkarEffectiveTheme.ts | 2 +- src/pages/HamkarUiConfigPage.vue | 81 ++++++++++++++++++++++------- 3 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/config/defaultHamkarUiConfig.ts b/src/config/defaultHamkarUiConfig.ts index f9c10a9..7651421 100644 --- a/src/config/defaultHamkarUiConfig.ts +++ b/src/config/defaultHamkarUiConfig.ts @@ -31,6 +31,12 @@ export type HamkarUiConfig = { * Laravel settings stay source of truth (prevents visual jumps). */ settingsManaged: boolean + /** + * When true, Hamkar applies brand colors to mobile chrome (header + bottom menu) + * and page body — including theme-two. Default false so live apps stay untouched + * until colors are saved from SuperAdmin. + */ + brandManaged: boolean /** Named CSS mode from live registry (Montpar, limangold, …) or dynamicMode */ registryMode: string brand: HamkarBrandColors @@ -103,6 +109,7 @@ export function createDefaultHamkarUiConfig(): HamkarUiConfig { return { kind: 'hamkar', settingsManaged: false, + brandManaged: false, registryMode: 'dynamicMode', brand: { primaryColor: '', @@ -151,6 +158,7 @@ export function normalizeHamkarUiConfig(raw: unknown): HamkarUiConfig { return { kind: 'hamkar', settingsManaged: Boolean(input.settingsManaged), + brandManaged: Boolean(input.brandManaged), registryMode, brand, settings, @@ -177,6 +185,7 @@ export function hamkarUiToApiPayload(config: HamkarUiConfig) { return { kind: 'hamkar' as const, settingsManaged: normalized.settingsManaged, + brandManaged: normalized.brandManaged, registryMode: normalized.registryMode, brand: { primaryColor: emptyToNull(normalized.brand.primaryColor), diff --git a/src/config/hamkarEffectiveTheme.ts b/src/config/hamkarEffectiveTheme.ts index e361bfb..1c78f03 100644 --- a/src/config/hamkarEffectiveTheme.ts +++ b/src/config/hamkarEffectiveTheme.ts @@ -75,6 +75,6 @@ export function resolveHamkarEffectiveTheme(input: { bg2: panel, colorPrimary: accent, }, - note: 'حالت dynamicMode: color → هدر (--bg2)، secondary_color → اکسنت (--colorPrimary)، background_color → پس‌زمینه (--bg).', + note: 'حالت dynamicMode: color → هدر و منوی موبایل (--bg2 / --theme-two-header)، secondary_color → اکسنت (--colorPrimary)، background_color → بدنه صفحه (--bg / --theme-two-background).', } } diff --git a/src/pages/HamkarUiConfigPage.vue b/src/pages/HamkarUiConfigPage.vue index c9c5462..6d1ca2e 100644 --- a/src/pages/HamkarUiConfigPage.vue +++ b/src/pages/HamkarUiConfigPage.vue @@ -80,6 +80,8 @@ const palette = computed(() => ({ const previewChrome = computed(() => { const p = palette.value const onHeader = textOn(p.header) + const headerEdge = + onHeader === '#ffffff' ? '1px solid rgba(255,255,255,0.12)' : '1px solid #e2e8f0' return { shell: { background: p.page, @@ -90,7 +92,12 @@ const previewChrome = computed(() => { header: { background: p.header, color: onHeader, - borderBottom: onHeader === '#ffffff' ? '1px solid rgba(255,255,255,0.12)' : '1px solid #e2e8f0', + borderBottom: headerEdge, + }, + footer: { + background: p.header, + color: onHeader, + borderTop: headerEdge, }, accent: p.accent, muted: onHeader === '#ffffff' ? 'rgba(255,255,255,0.72)' : '#616161', @@ -221,6 +228,8 @@ async function save() { saving.value = true try { config.registryMode = 'dynamicMode' + // Opt-in: live apps keep current chrome until colors are saved here. + config.brandManaged = true if (!config.defaultSnapshot) { ensureDefaultSnapshot(config, { notes: null, @@ -259,6 +268,8 @@ function resetToDefault() { config.brand.secondaryColor = snap.brand.secondaryColor config.brand.backgroundColor = snap.brand.backgroundColor config.settings = { ...snap.settings } + // Named factory modes must not keep brand chrome overrides. + config.brandManaged = snap.registryMode === 'dynamicMode' await persist(hamkarUiToApiPayload(config)) seedEditableColors(config) message.success('ظاهر اولیه بازیابی شد') @@ -294,9 +305,25 @@ onMounted(load)
-

پیش‌نمایش

+

پیش‌نمایش موبایل

+

هدر و منوی پایین یک رنگ‌اند؛ بدنه صفحه جداست.

+ علی منتظر +
+
+
+
خوش آمدگویی
+
+
+
+
+ نقد فردا + ۸۱٬۴۵۰٬۰۰۰ +
+
+
@@ -329,9 +345,12 @@ onMounted(load)

ظاهر پیش‌فرض ثبت‌شده: {{ defaultModeLabel }}

+

+ تا وقتی «ذخیره ظاهر همکار» نزنید، اپ‌های آنلاین عوض نمی‌شوند. +