From 532ceee18953442c4206c310181dd23ad4210845 Mon Sep 17 00:00:00 2001 From: "s.esmaeili" Date: Wed, 14 Oct 2026 13:31:20 +0330 Subject: [PATCH] feat: move brand name to one config and redesign the accounting card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit اپ: نام برند در همه‌ی صفحه‌ها و پیام‌ها یکسان شده و از یک تنظیم مرکزی خوانده می‌شود. اپ: کارت حسابداری در صفحه‌ی مشتری بازطراحی شد؛ مانده‌ها و وضعیت لینک واضح‌تر نمایش داده می‌شوند. پنل: کارت حسابداری در پرونده‌ی مشتری بازطراحی شد؛ مانده‌ها، آخرین ارسال و فرم لینک دستی واضح‌تر شده‌اند. پنل: ستون «کد» در جدول‌ها به‌طور پیش‌فرض پنهان است و از انتخاب ستون‌ها قابل نمایش است. پنل: تغییر نمایش ستون‌ها در جدول‌ها بلافاصله اعمال می‌شود. Co-Authored-By: Claude Haiku 5.5 --- .env.example | 10 + apps/admin-panel/index.html | 2 +- apps/admin-panel/src/App.vue | 3 +- ...ar-horizontal.png => brand-horizontal.png} | Bin .../logo/{montzar-icon.png => brand-icon.png} | Bin .../{montzar-icon.webp => brand-icon.webp} | Bin .../src/assets/styles/utilities.less | 2 +- apps/admin-panel/src/brand.ts | 2 + .../accounting/CustomerAccountingCard.vue | 234 ++++-- .../src/components/x-table/XTable.vue | 5 +- .../src/components/x-table/model.ts | 3 + .../layouts/components/VerticalNavMenu.vue | 5 +- apps/admin-panel/src/router/index.ts | 6 + apps/admin-panel/src/views/auth/Login.vue | 9 +- apps/admin-panel/src/views/branch/login.vue | 2 +- .../src/views/customer/Comments/Comments.vue | 9 +- .../src/views/customer/CustomerDetail.vue | 759 +++++++++++++++--- .../views/customer/omde/OmdeCustomerList.vue | 65 +- .../customer/omde/OmdeNonVerifiedList.vue | 4 +- .../views/customer/omde/ViewOmdeCustomer.vue | 1 + .../src/views/customer/omde/omdeListModel.ts | 22 + .../single-customer/ViewSingleCustomer.vue | 1 + apps/admin-panel/src/views/manage/Const.vue | 115 ++- .../src/views/manage/accounting.vue | 39 +- apps/admin-panel/vite.config.ts | 8 +- apps/api/prisma/insert-mock-products.js | 2 +- apps/api/prisma/seed.ts | 12 +- apps/api/scripts/legacy-import/index.ts | 2 +- apps/api/scripts/legacy-import/lib/context.ts | 2 +- apps/api/src/common/brand.ts | 16 + .../admin-customers.service.spec.ts | 5 +- .../admin-customers.service.ts | 75 +- .../admin-documents.service.ts | 5 +- .../admin-users/admin-users.service.ts | 16 +- .../customer-auth/customer-auth.controller.ts | 9 + .../customer-auth/customer-auth.service.ts | 105 ++- .../modules/customer-auth/dto/register.dto.ts | 44 + .../customer-profile.service.ts | 9 +- apps/api/src/modules/iam/iam.service.spec.ts | 4 +- .../src/modules/orders/orders.service.spec.ts | 2 +- apps/api/src/modules/orders/orders.service.ts | 11 +- apps/api/src/modules/sms/sms.service.spec.ts | 6 +- apps/user-app-v2/index.html | 2 +- .../img/{montzar-logo.png => brand-logo.png} | Bin .../{montzar-logo.webp => brand-logo.webp} | Bin apps/user-app-v2/src/api/client.ts | 18 + .../img/{montzar-logo.png => brand-logo.png} | Bin apps/user-app-v2/src/assets/styles/style.less | 18 + apps/user-app-v2/src/brand.ts | 2 + apps/user-app-v2/src/components/Spinner.vue | 3 +- .../src/components/home/HeroCarousel.vue | 30 +- .../src/components/product/ProductCard.vue | 4 +- .../src/components/product/SingleProduct.vue | 15 +- .../src/components/search/Filters.vue | 12 +- .../src/components/ui/DropDown.vue | 4 +- .../src/components/ui/IslandSheet.vue | 16 +- .../src/components/ui/SheetArt.vue | 14 +- .../src/components/ui/ToggleSwitch.vue | 8 +- apps/user-app-v2/src/stores/configStore.ts | 7 +- apps/user-app-v2/src/views/CartView.vue | 16 +- apps/user-app-v2/src/views/HomeView.vue | 60 +- .../src/views/expert/ChildOrdersView.vue | 4 +- .../src/views/expert/CustomerChoiceView.vue | 4 +- .../src/views/search/SearchView.vue | 10 +- .../src/views/user/AppearanceView.vue | 6 +- .../src/views/user/DashboardView.vue | 9 +- .../src/views/user/FavoritesView.vue | 4 +- apps/user-app-v2/src/views/user/LoginView.vue | 11 +- .../user-app-v2/src/views/user/OrdersView.vue | 16 +- .../src/views/user/RegisterView.vue | 79 +- apps/user-app-v2/themeConfig/appearance.ts | 2 +- apps/user-app-v2/themeConfig/colors.dark.json | 10 +- apps/user-app-v2/themeConfig/colors.json | 8 +- apps/user-app-v2/themeConfig/themeConfig.ts | 2 +- apps/user-app-v2/vite.config.ts | 9 +- apps/user-app/index.html | 2 +- .../img/{montzar-logo.png => brand-logo.png} | Bin .../{montzar-logo.webp => brand-logo.webp} | Bin apps/user-app/src/api/client.ts | 18 + .../img/{montzar-logo.png => brand-logo.png} | Bin apps/user-app/src/brand.ts | 2 + apps/user-app/src/components/Spinner.vue | 3 +- .../src/components/home/ShowcaseSlider.vue | 21 +- .../src/components/product/SingleProduct.vue | 3 +- apps/user-app/src/main.ts | 4 +- apps/user-app/src/stores/configStore.ts | 7 +- apps/user-app/src/views/HomeView.vue | 77 +- .../user-app/src/views/user/DashboardView.vue | 3 +- apps/user-app/src/views/user/LoginView.vue | 5 +- apps/user-app/src/views/user/RegisterView.vue | 34 +- apps/user-app/themeConfig/themeConfig.ts | 2 +- apps/user-app/tsconfig.tsbuildinfo | 2 +- apps/user-app/vite.config.ts | 9 +- brand.ts | 25 + docker-compose.yml | 5 + docs/ACCOUNTING-BALANCE-COLUMNS-PLAN.md | 67 ++ docs/ADMIN-PORT-PLAN.md | 2 +- docs/BRAND-COLOR-SWAP-PLAN.md | 61 ++ docs/BRANDING.md | 51 ++ ...ntzar-icons.py => generate-brand-icons.py} | 12 +- 100 files changed, 1870 insertions(+), 579 deletions(-) rename apps/admin-panel/src/assets/images/logo/{montzar-horizontal.png => brand-horizontal.png} (100%) rename apps/admin-panel/src/assets/images/logo/{montzar-icon.png => brand-icon.png} (100%) rename apps/admin-panel/src/assets/images/logo/{montzar-icon.webp => brand-icon.webp} (100%) create mode 100644 apps/admin-panel/src/brand.ts create mode 100644 apps/api/src/common/brand.ts create mode 100644 apps/api/src/modules/customer-auth/dto/register.dto.ts rename apps/user-app-v2/public/img/{montzar-logo.png => brand-logo.png} (100%) rename apps/user-app-v2/public/img/{montzar-logo.webp => brand-logo.webp} (100%) rename apps/user-app-v2/src/assets/img/{montzar-logo.png => brand-logo.png} (100%) create mode 100644 apps/user-app-v2/src/brand.ts rename apps/user-app/public/img/{montzar-logo.png => brand-logo.png} (100%) rename apps/user-app/public/img/{montzar-logo.webp => brand-logo.webp} (100%) rename apps/user-app/src/assets/img/{montzar-logo.png => brand-logo.png} (100%) create mode 100644 apps/user-app/src/brand.ts create mode 100644 brand.ts create mode 100644 docs/ACCOUNTING-BALANCE-COLUMNS-PLAN.md create mode 100644 docs/BRAND-COLOR-SWAP-PLAN.md create mode 100644 docs/BRANDING.md rename scripts/{generate-montzar-icons.py => generate-brand-icons.py} (71%) diff --git a/.env.example b/.env.example index 4b39060..96d0c9e 100644 --- a/.env.example +++ b/.env.example @@ -162,3 +162,13 @@ PROFILE_ADMIN_MOBILES= # Api/ApiMobileController::setOrder:740-743). Blank means nobody is notified — # the order, the customer's SMS and the sales expert's SMS still go through. ORDER_ADMIN_MOBILES= + +# --------------------------------------------------------------------------- +# Brand +# --------------------------------------------------------------------------- +# The name at the top of every SMS («زرتاج\n…») and the site link in the +# welcome SMS. Blank = the defaults in apps/api/src/common/brand.ts. The +# frontends take their brand from the repo-root brand.ts instead; the full +# rebrand checklist is docs/BRANDING.md. +BRAND_NAME= +BRAND_SITE_URL= diff --git a/apps/admin-panel/index.html b/apps/admin-panel/index.html index 65c0db5..04ce988 100644 --- a/apps/admin-panel/index.html +++ b/apps/admin-panel/index.html @@ -4,7 +4,7 @@ - منتزر — پنل مدیریت + %BRAND_TITLE%
diff --git a/apps/admin-panel/src/App.vue b/apps/admin-panel/src/App.vue index 8628286..ea0b843 100644 --- a/apps/admin-panel/src/App.vue +++ b/apps/admin-panel/src/App.vue @@ -37,6 +37,7 @@ import { onMounted, onUnmounted, ref, watch } from 'vue'; import { notification } from 'ant-design-vue'; import faIR from 'ant-design-vue/es/locale/fa_IR'; import themeConfig from './themeConfig'; +import { brand } from './brand'; import { useLayoutStore } from './stores/layout'; import AppUpdateGate from './components/common/AppUpdateGate.vue'; import { userName } from './utils'; @@ -96,7 +97,7 @@ onMounted(() => { notification.open({ message: `${user && user.name ? user.name : ' کاربر '} عزیز `, placement: 'topLeft', - description: 'به منتزر خوش آمدید', + description: `به ${brand.name} خوش آمدید`, style: { color: 'var(--primary-color)', marginLeft: `20px`, diff --git a/apps/admin-panel/src/assets/images/logo/montzar-horizontal.png b/apps/admin-panel/src/assets/images/logo/brand-horizontal.png similarity index 100% rename from apps/admin-panel/src/assets/images/logo/montzar-horizontal.png rename to apps/admin-panel/src/assets/images/logo/brand-horizontal.png diff --git a/apps/admin-panel/src/assets/images/logo/montzar-icon.png b/apps/admin-panel/src/assets/images/logo/brand-icon.png similarity index 100% rename from apps/admin-panel/src/assets/images/logo/montzar-icon.png rename to apps/admin-panel/src/assets/images/logo/brand-icon.png diff --git a/apps/admin-panel/src/assets/images/logo/montzar-icon.webp b/apps/admin-panel/src/assets/images/logo/brand-icon.webp similarity index 100% rename from apps/admin-panel/src/assets/images/logo/montzar-icon.webp rename to apps/admin-panel/src/assets/images/logo/brand-icon.webp diff --git a/apps/admin-panel/src/assets/styles/utilities.less b/apps/admin-panel/src/assets/styles/utilities.less index 0b3c205..6a3f7d3 100644 --- a/apps/admin-panel/src/assets/styles/utilities.less +++ b/apps/admin-panel/src/assets/styles/utilities.less @@ -29,7 +29,7 @@ // ant-design-pro boilerplate in Vue's own palette, inherited verbatim from // legacy and used as `@border-color-base`. That file is deleted (ADV4 has no // LESS build to feed); nothing in the app should reference `--primary`/ -// `--accent` any more — use the Montzar tokens below instead. +// `--accent` any more — use the brand tokens below instead. :root { --primary-color: #1c2d56; --secondary-color: #836447; diff --git a/apps/admin-panel/src/brand.ts b/apps/admin-panel/src/brand.ts new file mode 100644 index 0000000..0fc3747 --- /dev/null +++ b/apps/admin-panel/src/brand.ts @@ -0,0 +1,2 @@ +// The brand lives in the repo-root brand.ts, shared by all three frontends. +export { brand } from '../../../brand'; diff --git a/apps/admin-panel/src/components/accounting/CustomerAccountingCard.vue b/apps/admin-panel/src/components/accounting/CustomerAccountingCard.vue index 6c54ac0..053d6e8 100644 --- a/apps/admin-panel/src/components/accounting/CustomerAccountingCard.vue +++ b/apps/admin-panel/src/components/accounting/CustomerAccountingCard.vue @@ -4,50 +4,86 @@ linked to, and both balances side by side (the customer sees the accounting one; the credit limit is checked against the app's own). --> - +
+
+

حسابداری

+ لینک شده + لینک نشده +
+ - - +
+
+ کد حساب - لینک نشده - - - — - - - {{ num(info?.internal?.gold, 3) }} / - {{ num(info?.internal?.rial, 0) }} -
مبنای سقف اعتبار
-
- +
-
- آخرین ارسال: {{ STATUS[lastJob.status] ?? lastJob.status }} — {{ jdt(lastJob.updatedAt) }} - — {{ lastJob.lastError }} +
+
+
مانده‌ی حسابداری
+ + +
+
+
مانده‌ی دفتر اپ
+
+ {{ num(info?.internal?.gold, 3) }} + گرم +
+
+ {{ num(info?.internal?.rial, 0) }} + ریال +
+
مبنای سقف اعتبار
+
+
+ +
+ + آخرین ارسال: {{ STATUS[lastJob.status] ?? lastJob.status }} — {{ jdt(lastJob.updatedAt) }} +
{{ lastJob.lastError }}
+
+ +
- - - - لینک دستی - - حذف لینک - - - +
diff --git a/apps/admin-panel/src/components/x-table/XTable.vue b/apps/admin-panel/src/components/x-table/XTable.vue index 7ffca72..1554ff1 100644 --- a/apps/admin-panel/src/components/x-table/XTable.vue +++ b/apps/admin-panel/src/components/x-table/XTable.vue @@ -293,7 +293,10 @@ const opOptions = [ { value: 'between', label: 'بین' }, ]; -const cols = computed(() => props.model?.cols ?? []); +// The model is a plain class instance (see model.ts), so its columns are not +// reactive on their own. Wrapping it here lets the column picker's `col.show` +// checkbox toggles re-run visibleCols / antColumns. +const cols = computed(() => (props.model ? (reactive(props.model) as XTbl).cols : [])); const visibleCols = computed(() => cols.value.filter((c) => c.show)); const filterableOptions = computed(() => cols.value.filter((c) => c.filtered).map((c) => ({ value: c.__fkey ?? c.key, label: c.title })), diff --git a/apps/admin-panel/src/components/x-table/model.ts b/apps/admin-panel/src/components/x-table/model.ts index 6467829..e251dbb 100644 --- a/apps/admin-panel/src/components/x-table/model.ts +++ b/apps/admin-panel/src/components/x-table/model.ts @@ -42,6 +42,9 @@ export class Xtc { this.key = key; this.title = title; this.dataIndex = key; + // The record id ('کد') is kept out of every table by default. It can still be + // turned on from the column picker. + if (key === 'id') this.show = false; } private __filter() { diff --git a/apps/admin-panel/src/layouts/components/VerticalNavMenu.vue b/apps/admin-panel/src/layouts/components/VerticalNavMenu.vue index 5a14960..4c54541 100644 --- a/apps/admin-panel/src/layouts/components/VerticalNavMenu.vue +++ b/apps/admin-panel/src/layouts/components/VerticalNavMenu.vue @@ -19,7 +19,7 @@ > - طلای منتزر + %BRAND_TITLE%
diff --git a/apps/user-app-v2/public/img/montzar-logo.png b/apps/user-app-v2/public/img/brand-logo.png similarity index 100% rename from apps/user-app-v2/public/img/montzar-logo.png rename to apps/user-app-v2/public/img/brand-logo.png diff --git a/apps/user-app-v2/public/img/montzar-logo.webp b/apps/user-app-v2/public/img/brand-logo.webp similarity index 100% rename from apps/user-app-v2/public/img/montzar-logo.webp rename to apps/user-app-v2/public/img/brand-logo.webp diff --git a/apps/user-app-v2/src/api/client.ts b/apps/user-app-v2/src/api/client.ts index 17c6b2a..65a4e83 100644 --- a/apps/user-app-v2/src/api/client.ts +++ b/apps/user-app-v2/src/api/client.ts @@ -260,6 +260,17 @@ export interface GoldPriceQuote { quotedAt: string; } +/** Body of POST customer/auth/register — the app register form, field for field. */ +export interface RegisterBody { + fname: string; + lname: string; + mobile: string; + store_name: string; + phone: string; + address: string; + city: string; +} + /** One admin-uploaded home banner slide — raw shape as saved by the admin * panel's manage/Const.vue "اسلایدر موبایل" tab (image + optional link). */ export interface AdminSlide { @@ -444,6 +455,13 @@ export const api = { * which used to be derived by scanning the whole catalogue in the browser. */ getCatalogFacets: () => request('/catalog/products/facets'), + /** App self-registration. The new customer waits for admin approval before signing in. */ + register: (body: RegisterBody) => + request<{ ok: boolean }>('/customer/auth/register', { + method: 'POST', + body: JSON.stringify(body), + }), + /** * Step 1 of login — ports henza_server ApiMobileController::userAuth. * Always resolves `{ sent: true }`, even for an unregistered number, so the diff --git a/apps/user-app-v2/src/assets/img/montzar-logo.png b/apps/user-app-v2/src/assets/img/brand-logo.png similarity index 100% rename from apps/user-app-v2/src/assets/img/montzar-logo.png rename to apps/user-app-v2/src/assets/img/brand-logo.png diff --git a/apps/user-app-v2/src/assets/styles/style.less b/apps/user-app-v2/src/assets/styles/style.less index ee301d0..d7e9dde 100644 --- a/apps/user-app-v2/src/assets/styles/style.less +++ b/apps/user-app-v2/src/assets/styles/style.less @@ -704,6 +704,24 @@ html.motion-reduced .toast { background: alpha(@canvas, 97%) !important; } +/* Browser autofill paints its own pale-blue fill (and dark text) over the + field, which can't be overridden with `background`. Cover it with an inset + shadow in the field's own colour instead. Inside an ant affix wrapper only + the inner gets autofilled, so without this it shows as a blue box + floating inside the bordered wrapper. */ +input:-webkit-autofill, +input:-webkit-autofill:hover, +input:-webkit-autofill:focus, +textarea:-webkit-autofill, +textarea:-webkit-autofill:hover, +textarea:-webkit-autofill:focus { + -webkit-text-fill-color: @ink; + caret-color: @ink; + -webkit-box-shadow: 0 0 0 1000px @canvas inset !important; + box-shadow: 0 0 0 1000px @canvas inset !important; + transition: background-color 9999s ease-out 0s; +} + /* ── Dark theme: third-party surfaces ────────────────────────── ant-design-vue compiles its theme at build time with black text (fade(@black, 85%)) and white fills; only its surface backgrounds were diff --git a/apps/user-app-v2/src/brand.ts b/apps/user-app-v2/src/brand.ts new file mode 100644 index 0000000..0fc3747 --- /dev/null +++ b/apps/user-app-v2/src/brand.ts @@ -0,0 +1,2 @@ +// The brand lives in the repo-root brand.ts, shared by all three frontends. +export { brand } from '../../../brand'; diff --git a/apps/user-app-v2/src/components/Spinner.vue b/apps/user-app-v2/src/components/Spinner.vue index 76e0eb0..765576b 100644 --- a/apps/user-app-v2/src/components/Spinner.vue +++ b/apps/user-app-v2/src/components/Spinner.vue @@ -2,7 +2,7 @@