Polish Hedena brand, home layout, and user-app chrome.

Switch the customer app to IRANSans, restyle home featured/newest and cart note sheet, refresh brand icons across apps, and add the PWA install prompt.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
s.esmaeili
2026-10-16 00:04:13 +03:30
co-authored by Cursor
parent be2c2ddf21
commit 3add0683b3
69 changed files with 1577 additions and 576 deletions
+7 -9
View File
@@ -14,10 +14,8 @@
and `third-color` were never real ant variables (confirmed dead in the old
LESS build) and stay only as the CSS custom properties in utilities.less.
ant derives its light "primary background" steps from colorPrimary; for a
navy this dark the generated steps are mid-greys (#8d9296, #81858a), which
painted every selected option / tree node / picker cell grey. Those steps
are pinned to light navy tints instead (see `themeTokens`).
Light primary steps are pinned to blue-600 tints so selected options /
tree nodes / picker cells stay on-brand (see `themeTokens`).
-->
<a-config-provider :locale="faIR" direction="rtl" :theme="{ token: themeTokens }">
<div id="app" :class="vueAppClasses">
@@ -43,14 +41,14 @@ import AppUpdateGate from './components/common/AppUpdateGate.vue';
import { userName } from './utils';
const themeTokens = {
colorPrimary: '#1c2d56',
colorPrimary: '#1d4ed8',
colorLink: '#1DA57A',
borderRadius: 6,
controlHeight: 36,
colorPrimaryBg: '#eef1f8',
colorPrimaryBgHover: '#e1e6f2',
colorPrimaryBorder: '#c5cde0',
colorPrimaryBorderHover: '#9ea9c6',
colorPrimaryBg: '#eff6ff',
colorPrimaryBgHover: '#dbeafe',
colorPrimaryBorder: '#bfdbfe',
colorPrimaryBorderHover: '#93c5fd',
};
const layout = useLayoutStore();
Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 14 KiB

@@ -3,7 +3,7 @@
// its forms): page header, main/side columns, section cards and a sticky
// action bar. Layout only — ant components keep their own design-system look.
@pf-primary: #1c2d56;
@pf-primary: #1d4ed8;
@pf-ink: #101828;
@pf-muted: #8a94a6;
@pf-line: #eef0f5;
@@ -106,7 +106,7 @@
border-radius: 11px;
font-size: 16px;
color: @pf-primary;
background: rgba(28, 45, 86, 0.07);
background: rgba(29, 78, 216, 0.07);
}
.pf-section__action {
flex-shrink: 0;
@@ -27,9 +27,9 @@
* Keep in sync with App.vue `antTheme` tokens.
*/
:root {
--selected-bg: rgba(28, 45, 86, 0.08);
--selected-bg-hover: rgba(28, 45, 86, 0.12);
--hover-bg: rgba(28, 45, 86, 0.04);
--selected-bg: rgba(29, 78, 216, 0.08);
--selected-bg-hover: rgba(29, 78, 216, 0.12);
--hover-bg: rgba(29, 78, 216, 0.04);
}
.ant-menu-light .ant-menu-item-selected,
@@ -42,7 +42,7 @@
.vertical-nav-menu .ant-menu-item-selected:hover,
.vertical-nav-menu .ant-menu-sub .ant-menu-item-selected,
.vertical-nav-menu .ant-menu-sub .ant-menu-item-selected:hover {
color: var(--primary-color, #1c2d56) !important;
color: var(--primary-color, #1d4ed8) !important;
background: var(--selected-bg) !important;
font-weight: 600;
}
@@ -50,7 +50,7 @@
.ant-menu-light .ant-menu-item-selected .anticon,
.ant-menu-inline .ant-menu-item-selected .anticon,
.vertical-nav-menu .ant-menu-item-selected .anticon {
color: var(--primary-color, #1c2d56) !important;
color: var(--primary-color, #1d4ed8) !important;
}
.ant-menu-light .ant-menu-item-selected::after,
@@ -63,7 +63,7 @@
/* Select / Cascader / TreeSelect / Transfer / Mentions / Dropdown */
.ant-select-item-option-selected:not(.ant-select-item-option-disabled),
.ant-select-item-option-active:not(.ant-select-item-option-disabled) {
color: var(--primary-color, #1c2d56) !important;
color: var(--primary-color, #1d4ed8) !important;
}
.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
@@ -84,7 +84,7 @@
.ant-dropdown-menu-submenu-title-selected,
.ant-transfer-list-content-item-checked,
.ant-mentions-dropdown-menu-item-active {
color: var(--primary-color, #1c2d56) !important;
color: var(--primary-color, #1d4ed8) !important;
background: var(--selected-bg) !important;
}
@@ -31,7 +31,7 @@
// LESS build to feed); nothing in the app should reference `--primary`/
// `--accent` any more — use the brand tokens below instead.
:root {
--primary-color: #1c2d56;
--primary-color: #1d4ed8;
--secondary-color: #836447;
--third-color: #f5cb55;
--success-color: #28c76f;
@@ -76,8 +76,8 @@ const iconComponent = computed(() => ICONS[props.icon ?? ''] ?? BarChartOutlined
border-radius: 8px;
font-size: 20px;
flex-shrink: 0;
background: rgba(28, 45, 86, 0.06);
color: #1c2d56;
background: rgba(29, 78, 216, 0.06);
color: #1d4ed8;
}
.stat-copy {
@@ -96,7 +96,7 @@ const iconComponent = computed(() => ICONS[props.icon ?? ''] ?? BarChartOutlined
margin: 0;
font-size: 20px;
font-weight: 600;
color: #1c2d56;
color: #1d4ed8;
line-height: 1.25;
word-break: break-word;
}
@@ -212,7 +212,7 @@ onBeforeUnmount(() => {
}
.gallery-upload__icon {
font-size: 16px;
color: #1c2d56;
color: #1d4ed8;
opacity: 0.75;
}
.gallery-upload__title {
@@ -279,7 +279,7 @@ onBeforeUnmount(() => {
border: none;
border-radius: 9px;
background: rgba(255, 255, 255, 0.92);
color: #1c2d56;
color: #1d4ed8;
font-size: 15px;
cursor: pointer;
transition: transform 0.15s ease;
@@ -318,6 +318,6 @@ onBeforeUnmount(() => {
display: inline-flex;
align-items: center;
gap: 6px;
color: #1c2d56;
color: #1d4ed8;
}
</style>
@@ -642,7 +642,7 @@ defineExpose({ fetch });
}
.x-card__name {
font-weight: 600;
color: #1c2d56;
color: #1d4ed8;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -26,7 +26,7 @@
<div class="nav-right">
<a-dropdown trigger="click" placement="bottomRight" :overlay-class-name="'user-dropdown-overlay'">
<span class="user-chip">
<a-avatar size="small" style="background-color: #1c2d56">
<a-avatar size="small" style="background-color: #1d4ed8">
{{ initial }}
</a-avatar>
<span class="user-name">{{ displayName }}</span>
@@ -34,7 +34,7 @@
<template #overlay>
<div class="user-card">
<div class="user-card__head">
<a-avatar size="large" style="background-color: #1c2d56">
<a-avatar size="large" style="background-color: #1d4ed8">
{{ initial }}
</a-avatar>
<div class="user-card__id">
@@ -135,7 +135,7 @@ async function onLogout() {
}
.page-title {
font-size: 16px;
color: #1c2d56;
color: #1d4ed8;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -191,7 +191,7 @@ async function onLogout() {
padding: 12px;
background: #fff;
border-radius: 10px;
box-shadow: 0 8px 28px -8px rgba(28, 45, 86, 0.28);
box-shadow: 0 8px 28px -8px rgba(29, 78, 216, 0.28);
}
.user-dropdown-overlay .user-card__head {
@@ -210,7 +210,7 @@ async function onLogout() {
.user-dropdown-overlay .user-card__name {
font-size: 14px;
font-weight: 600;
color: #1c2d56;
color: #1d4ed8;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -246,7 +246,7 @@ async function onLogout() {
.user-dropdown-overlay .user-card__menu .ant-menu-item:hover {
background: #f4f5f6;
color: #1c2d56;
color: #1d4ed8;
}
.user-dropdown-overlay .user-card__menu .anticon {
@@ -215,7 +215,7 @@ function onClick({ key }: { key: string | number }) {
border-radius: 11px;
background: #fff;
border: 1px solid #eef0f5;
box-shadow: 0 4px 12px -6px rgba(28, 45, 86, 0.35);
box-shadow: 0 4px 12px -6px rgba(29, 78, 216, 0.35);
}
.nav-logo img {
width: 64%;
@@ -229,7 +229,7 @@ function onClick({ key }: { key: string | number }) {
.nav-title {
font-size: 16px;
font-weight: 500;
color: #1c2d56;
color: #1d4ed8;
}
.nav-subtitle {
font-size: 11px;
@@ -308,22 +308,22 @@ function onClick({ key }: { key: string | number }) {
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item:not(.ant-menu-item-selected):hover,
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-title:hover {
background: #f5f7fb !important;
color: #1c2d56 !important;
color: #1d4ed8 !important;
}
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item:hover .ant-menu-item-icon,
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-title:hover .ant-menu-item-icon {
color: #1c2d56;
color: #1d4ed8;
}
/* active item */
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item-selected {
position: relative;
background: rgba(28, 45, 86, 0.08) !important;
color: #1c2d56 !important;
background: rgba(29, 78, 216, 0.08) !important;
color: #1d4ed8 !important;
font-weight: 500;
}
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item-selected .ant-menu-item-icon {
color: #1c2d56;
color: #1d4ed8;
}
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-inline .ant-menu-item-selected::after {
content: '';
@@ -335,13 +335,13 @@ function onClick({ key }: { key: string | number }) {
width: 3px;
border: none;
border-radius: 3px;
background: #1c2d56;
background: #1d4ed8;
opacity: 1;
transform: none;
}
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-selected > .ant-menu-submenu-title,
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-selected > .ant-menu-submenu-title .ant-menu-item-icon {
color: #1c2d56;
color: #1d4ed8;
font-weight: 500;
}
@@ -391,16 +391,16 @@ function onClick({ key }: { key: string | number }) {
.nav-popup .ant-menu-item:not(.ant-menu-item-selected):hover,
.nav-popup .ant-menu-submenu-title:hover {
background: #f5f7fb !important;
color: #1c2d56 !important;
color: #1d4ed8 !important;
}
.nav-popup .ant-menu-item-selected {
position: relative;
background: rgba(28, 45, 86, 0.08) !important;
color: #1c2d56 !important;
background: rgba(29, 78, 216, 0.08) !important;
color: #1d4ed8 !important;
font-weight: 500;
}
.nav-popup .ant-menu-item-selected .ant-menu-item-icon {
color: #1c2d56;
color: #1d4ed8;
}
.nav-popup .ant-menu-item-selected::after {
content: '';
@@ -412,19 +412,19 @@ function onClick({ key }: { key: string | number }) {
width: 3px;
border: none;
border-radius: 3px;
background: #1c2d56;
background: #1d4ed8;
opacity: 1;
transform: none;
}
.nav-popup .ant-menu-submenu-selected > .ant-menu-submenu-title {
color: #1c2d56;
color: #1d4ed8;
font-weight: 500;
}
/* collapsed rail: the icon of the group holding the active page */
#app .vertical-nav-menu .ant-menu-inline-collapsed .ant-menu-submenu-selected > .ant-menu-submenu-title,
#app .vertical-nav-menu .ant-menu-inline-collapsed > .ant-menu-item-selected {
background: rgba(28, 45, 86, 0.08) !important;
color: #1c2d56 !important;
background: rgba(29, 78, 216, 0.08) !important;
color: #1d4ed8 !important;
}
</style>
+1 -1
View File
@@ -5,7 +5,7 @@
// MAIN COLORS
export const colors = {
primary: '#1c2d56',
primary: '#1d4ed8',
secondary: '#836447',
third: '#f5cb55',
success: '#28C76F',
+5 -5
View File
@@ -349,7 +349,7 @@ const data = reactive<Record<string, any>>({
// ── colours matching the rest of the admin panel (StatisticsCardLine's own
// icon-color classes and ant's card chrome) ────────────────────────────────
const COLOR_PRIMARY = '#1c2d56';
const COLOR_PRIMARY = '#1d4ed8';
const COLOR_SUCCESS = '#28c76f';
const COLOR_WARNING = '#ff9f43';
const COLOR_DANGER = '#ea5455';
@@ -604,7 +604,7 @@ b {
font-weight: 500;
}
.dashboard {
--c-primary: #1c2d56;
--c-primary: #1d4ed8;
--c-success: #28c76f;
--c-warning: #ff9f43;
--c-danger: #ea5455;
@@ -686,7 +686,7 @@ b {
flex-shrink: 0;
padding: 4px 12px;
border-radius: 999px;
background: rgba(28, 45, 86, 0.06);
background: rgba(29, 78, 216, 0.06);
color: var(--c-primary);
font-size: 12px;
font-weight: 500;
@@ -717,7 +717,7 @@ b {
}
.kpi {
--tone: var(--c-primary);
--tone-bg: rgba(28, 45, 86, 0.08);
--tone-bg: rgba(29, 78, 216, 0.08);
position: relative;
overflow: hidden;
padding: 18px 18px 14px;
@@ -881,7 +881,7 @@ b {
color: var(--ink);
white-space: nowrap;
}
.tone-primary { color: var(--c-primary); background: rgba(28, 45, 86, 0.08); }
.tone-primary { color: var(--c-primary); background: rgba(29, 78, 216, 0.08); }
.tone-success { color: var(--c-success); background: rgba(40, 199, 111, 0.12); }
.tone-warning { color: var(--c-warning); background: rgba(255, 159, 67, 0.14); }
.tone-danger { color: var(--c-danger); background: rgba(234, 84, 85, 0.12); }
@@ -137,9 +137,9 @@ b {
border-color: #c9d0dd;
}
.kind-card.is-on {
border-color: #1c2d56;
background: rgba(28, 45, 86, 0.03);
box-shadow: 0 0 0 3px rgba(28, 45, 86, 0.08);
border-color: #1d4ed8;
background: rgba(29, 78, 216, 0.03);
box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.08);
}
.kind-card__icon {
width: 42px;
@@ -155,7 +155,7 @@ b {
}
.kind-card.is-on .kind-card__icon {
color: #fff;
background: #1c2d56;
background: #1d4ed8;
}
.kind-card__text {
display: flex;
@@ -174,7 +174,7 @@ b {
.kind-card__check {
margin-inline-start: auto;
font-size: 16px;
color: #1c2d56;
color: #1d4ed8;
}
@media (max-width: 575px) {
@@ -651,7 +651,7 @@ onMounted(async () => {
<style scoped>
.product-form-page {
--c-primary: #1c2d56;
--c-primary: #1d4ed8;
--ink: #101828;
--muted: #8a94a6;
--line: #eef0f5;
@@ -731,7 +731,7 @@ onMounted(async () => {
border-color: #b4bccb;
}
.variant-gallery__item.is-on {
border-color: #1c2d56;
border-color: #1d4ed8;
}
.variant-gallery__item img {
width: 100%;
@@ -779,7 +779,7 @@ onMounted(async () => {
margin: 0;
font-size: 20px;
font-weight: 600;
color: #1c2d56;
color: #1d4ed8;
line-height: 1.3;
}
.product-name-badge {
@@ -814,8 +814,8 @@ onMounted(async () => {
font-size: 13px;
}
.header-save-btn {
background: #1c2d56;
border-color: #1c2d56;
background: #1d4ed8;
border-color: #1d4ed8;
height: 38px;
padding: 0 18px;
border-radius: 8px;
@@ -849,7 +849,7 @@ onMounted(async () => {
border: 1px solid #edf0f5;
border-radius: 12px;
padding: 20px 22px 24px;
box-shadow: 0 1px 2px rgba(28, 45, 86, 0.02);
box-shadow: 0 1px 2px rgba(29, 78, 216, 0.02);
}
.form-section-head {
@@ -877,8 +877,8 @@ onMounted(async () => {
width: 38px;
height: 38px;
border-radius: 10px;
background: rgba(28, 45, 86, 0.05);
color: #1c2d56;
background: rgba(29, 78, 216, 0.05);
color: #1d4ed8;
font-size: 18px;
flex-shrink: 0;
}
@@ -892,7 +892,7 @@ onMounted(async () => {
margin: 0;
font-size: 15px;
font-weight: 600;
color: #1c2d56;
color: #1d4ed8;
line-height: 1.3;
}
.section-subtitle {
@@ -965,7 +965,7 @@ onMounted(async () => {
transition: all 0.2s ease;
}
.featured-upload-card:hover {
border-color: #1c2d56;
border-color: #1d4ed8;
background: #ffffff;
}
.featured-label {
@@ -998,8 +998,8 @@ onMounted(async () => {
/* ── جدول تنوع‌ها ── */
.add-variant-btn {
background: #1c2d56;
border-color: #1c2d56;
background: #1d4ed8;
border-color: #1d4ed8;
border-radius: 6px;
font-size: 13px;
}
@@ -1044,7 +1044,7 @@ onMounted(async () => {
font-size: 13px;
}
.weight-cell {
color: #1c2d56;
color: #1d4ed8;
font-weight: 500;
font-size: 13px;
}
@@ -1076,10 +1076,10 @@ onMounted(async () => {
border-radius: 4px;
}
.edit-btn {
color: #1c2d56;
color: #1d4ed8;
}
.edit-btn:hover {
background: rgba(28, 45, 86, 0.08);
background: rgba(29, 78, 216, 0.08);
}
.delete-btn {
color: #ea5455;
@@ -1105,8 +1105,8 @@ onMounted(async () => {
}
.empty-add-btn {
border-radius: 6px;
color: #1c2d56;
border-color: #1c2d56;
color: #1d4ed8;
border-color: #1d4ed8;
}
/* ── نوار اکشن پایین ── */
@@ -1119,8 +1119,8 @@ onMounted(async () => {
border-top: 1px solid #edf0f5;
}
.submit-btn {
background: #1c2d56;
border-color: #1c2d56;
background: #1d4ed8;
border-color: #1d4ed8;
height: 42px;
padding: 0 24px;
font-size: 14px;
@@ -1183,7 +1183,7 @@ onMounted(async () => {
transition: all 0.2s ease;
}
.variant-picker__item:hover {
border-color: #1c2d56;
border-color: #1d4ed8;
}
.variant-picker__item img {
width: 100%;
+1 -1
View File
@@ -229,7 +229,7 @@ async function loginJWT() {
<style scoped>
#page-login {
--bg: #060b1c;
--navy: #1c2d56;
--navy: #1d4ed8;
--gold-1: #fff1c1;
--gold-2: #f2c95c;
--gold-3: #c8902a;
@@ -97,7 +97,7 @@
<ul>
<li class="comment-item">
<span class="img">
<UserOutlined style="font-size: 48px; color: #1c2d56" />
<UserOutlined style="font-size: 48px; color: #1d4ed8" />
</span>
<div class="comment-body">
<h5>
+2 -2
View File
@@ -36,9 +36,9 @@ onMounted(async () => {
padding: 1rem 1.5rem;
border: 1px solid #f0f0f0;
border-radius: 6px;
color: #1c2d56;
color: #1d4ed8;
}
.link-card:hover { border-color: #1c2d56; }
.link-card:hover { border-color: #1d4ed8; }
@media (max-width: 575px) {
.links {