From 20c871e66cfaed06ebe12ee239023b1a8a2d471a Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Thu, 22 Oct 2026 17:38:27 +0330 Subject: [PATCH] feat(convert,assets): convert page route and assets portfolio chart Add convert mobile/desktop views and assets chart from price history; polish calculator and wallet/home integration. Co-authored-by: Cursor --- .../abshode-domain-lookup/learned-notes.md | 1 + src/App.vue | 2 - src/assets/css/boursecu-theme.less | 4 +- src/assets/css/main.less | 4 +- src/components/BasicPacks/BasicInput.vue | 6 +- src/router/index.ts | 10 + src/utils/chartAreaPaths.ts | 107 ++++ .../composables/useAssetsPortfolioChart.ts | 87 ++++ src/views/base/assets/index.vue | 485 ++++++++++++++++++ .../components/CopperConvertCalculator.vue | 122 ++--- .../composables/useCopperConvertPage.ts | 14 +- .../convert/desktop/DesktopConvertView.vue | 77 +++ src/views/base/convert/index.vue | 24 + .../base/convert/mobile/MobileConvertView.vue | 15 + src/views/base/copper&silver/index.vue | 4 +- src/views/base/gold/index.vue | 4 +- .../base/home/composables/useHomePage.ts | 6 +- src/views/base/home/index.vue | 10 - .../layouts/configs/boursecuQuickActions.ts | 5 +- .../components/PhysicalReceiveCartRow.vue | 5 - .../base/wallet/composables/useWalletPage.ts | 5 +- .../base/wallet/desktop/DesktopWalletView.vue | 3 - .../base/wallet/mobile/MobileWalletView.vue | 3 - 23 files changed, 872 insertions(+), 131 deletions(-) create mode 100644 src/utils/chartAreaPaths.ts create mode 100644 src/views/base/assets/composables/useAssetsPortfolioChart.ts create mode 100644 src/views/base/assets/index.vue create mode 100644 src/views/base/convert/desktop/DesktopConvertView.vue create mode 100644 src/views/base/convert/index.vue create mode 100644 src/views/base/convert/mobile/MobileConvertView.vue diff --git a/.cursor/skills/abshode-domain-lookup/learned-notes.md b/.cursor/skills/abshode-domain-lookup/learned-notes.md index bf4c7ea..f0db15f 100644 --- a/.cursor/skills/abshode-domain-lookup/learned-notes.md +++ b/.cursor/skills/abshode-domain-lookup/learned-notes.md @@ -3,6 +3,7 @@ فرمت هر خط: - YYYY-MM-DD | موضوع | مسیر فایل(ها) | نکتهٔ ۱ خطی +- 2026-10-22 | addon اینپوت | `assets/css/main.less` | پس‌زمینه addon = secondary تم، نه primary (سبز tenant) - 2026-10-21 | نمودار خانه = لندینگ | `LandingLiveChartMain.vue` + `useLandingLiveChart` + `zaarboxPriceHistory`؛ جایگزین `PriceChart` در PriceChartSection/DesktopChart* | همان `dlanding-live__main` SVG؛ داده از zaarbox + `/api/price/last` - 2026-10-20 | ظاهر خرید اقساطی | `views/base/installment/InstallmentPanel.vue` | دسکتاپ کلاس‌های `dgift` مثل کارت هدیه؛ موبایل کارت `rounded-xl` و توضیح بالای فرم - 2026-10-20 | خرید اقساطی دیجی‌پی | سرور `DigipayInstallmentService` + تنظیمات `enable_digipay_installment`/`digipay_*`؛ اپ `views/base/installment`؛ ادمین `customers/digipayInstallment` | لینک احراز در تنظیمات؛ مانده اعتبار را ادمین با موبایل می‌نویسد؛ خرید مس را به کیف gold می‌نشاند diff --git a/src/App.vue b/src/App.vue index 9995b6e..62c5602 100644 --- a/src/App.vue +++ b/src/App.vue @@ -110,7 +110,6 @@ /> - + + diff --git a/src/views/base/convert/components/CopperConvertCalculator.vue b/src/views/base/convert/components/CopperConvertCalculator.vue index 364bc32..b47ca31 100644 --- a/src/views/base/convert/components/CopperConvertCalculator.vue +++ b/src/views/base/convert/components/CopperConvertCalculator.vue @@ -164,8 +164,9 @@ function formatRings(value: number) { .copper-convert { display: flex; flex-direction: column; - gap: 0.5rem; + gap: 0.75rem; text-align: right; + color: #334155; } .copper-convert__lead { @@ -175,28 +176,13 @@ function formatRings(value: number) { color: #64748b; } -.copper-convert__panel { - position: relative; - padding: 0.75rem 0.875rem 0.7rem; - border-radius: 1rem; - background: linear-gradient(145deg, #0f2744 0%, #152f4f 48%, #1a365d 100%); - border: 1px solid rgba(201, 160, 98, 0.35); - box-shadow: - 0 12px 28px rgba(15, 39, 68, 0.22), - inset 0 1px 0 rgba(255, 255, 255, 0.06); - overflow: hidden; -} - -.copper-convert__panel::before { - content: ''; - position: absolute; - top: -40px; - inset-inline-end: -30px; - width: 120px; - height: 120px; - border-radius: 50%; - background: radial-gradient(circle, rgba(232, 180, 140, 0.28) 0%, transparent 70%); - pointer-events: none; +.copper-convert__panel, +.copper-convert__form, +.copper-convert__result { + padding: 0.875rem; + border-radius: 0.875rem; + background: #fff; + border: 1px solid #e5e7eb; } .copper-convert__panel-head { @@ -208,17 +194,18 @@ function formatRings(value: number) { margin-bottom: 0.75rem; } -.copper-convert__panel-kicker { +.copper-convert__panel-kicker, +.copper-convert__result-kicker { font-size: 0.6875rem; font-weight: 700; - letter-spacing: 0.04em; - color: rgba(201, 160, 98, 0.95); + color: var(--colorPrimary, #2563eb); } -.copper-convert__panel-title { +.copper-convert__panel-title, +.copper-convert__result-title { font-size: 0.9375rem; font-weight: 800; - color: #f8fafc; + color: #0f172a; } .copper-convert__price-group { @@ -230,7 +217,7 @@ function formatRings(value: number) { .copper-convert__price-group--wire { margin-bottom: 0; padding-top: 0.65rem; - border-top: 1px solid rgba(255, 255, 255, 0.08); + border-top: 1px solid #f1f5f9; } .copper-convert__group-label { @@ -238,7 +225,7 @@ function formatRings(value: number) { margin-bottom: 0.45rem; font-size: 0.6875rem; font-weight: 600; - color: rgba(226, 232, 240, 0.75); + color: #64748b; } .copper-convert__price-grid { @@ -258,29 +245,29 @@ function formatRings(value: number) { min-width: 0; padding: 0.45rem 0.5rem; border-radius: 0.65rem; - background: rgba(255, 255, 255, 0.06); - border: 1px solid rgba(255, 255, 255, 0.1); + background: #f8fafc; + border: 1px solid #e5e7eb; } .copper-convert__chip--accent { - background: rgba(201, 160, 98, 0.12); - border-color: rgba(201, 160, 98, 0.35); + background: #eff5f3; + border-color: #d4e3de; } .copper-convert__chip--muted .copper-convert__chip-value { - color: rgba(248, 250, 252, 0.45); + color: #94a3b8; } .copper-convert__chip-label { font-size: 0.625rem; line-height: 1.45; - color: rgba(226, 232, 240, 0.85); + color: #64748b; } .copper-convert__chip-value { font-size: 0.6875rem; font-weight: 700; - color: #f8fafc; + color: #0f172a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -290,11 +277,6 @@ function formatRings(value: number) { display: flex; flex-direction: column; gap: 0.65rem; - margin-top: 0.125rem; - padding: 0.75rem 0.875rem; - border-radius: 1rem; - background: #faf8f5; - border: 1px solid rgba(201, 160, 98, 0.22); } .copper-convert__field-label { @@ -327,9 +309,9 @@ function formatRings(value: number) { } .copper-convert__pill--active { - color: #0f2744; + color: var(--colorPrimary, #2563eb); background: #fff; - box-shadow: 0 2px 8px rgba(15, 39, 68, 0.12); + box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08); } .copper-convert__weight-wrap { @@ -352,7 +334,7 @@ function formatRings(value: number) { background: transparent; font-size: 1.125rem; font-weight: 800; - color: #0f2744; + color: #0f172a; text-align: right; direction: ltr; } @@ -367,16 +349,13 @@ function formatRings(value: number) { flex-shrink: 0; font-size: 0.75rem; font-weight: 800; - color: #c9a062; + color: var(--colorPrimary, #2563eb); } .copper-convert__result { - margin-top: 0.125rem; - padding: 0.875rem; - border-radius: 1rem; - background: linear-gradient(180deg, #fff 0%, #faf8f5 100%); - border: 1px solid rgba(201, 160, 98, 0.35); - box-shadow: 0 8px 24px rgba(15, 39, 68, 0.08); + display: flex; + flex-direction: column; + gap: 0.75rem; } .copper-convert__result-head { @@ -386,17 +365,6 @@ function formatRings(value: number) { margin-bottom: 0.75rem; } -.copper-convert__result-kicker { - font-size: 0.6875rem; - font-weight: 700; - color: #c9a062; -} - -.copper-convert__result-title { - font-size: 0.9375rem; - font-weight: 800; - color: #0f2744; -} .copper-convert__rings { display: grid; @@ -410,23 +378,11 @@ function formatRings(value: number) { padding: 0.75rem 0.5rem; border-radius: 0.85rem; text-align: center; - background: linear-gradient(160deg, #0f2744 0%, #1a365d 100%); - border: 1px solid rgba(201, 160, 98, 0.4); + background: #eff5f3; + border: 1px solid #d4e3de; overflow: hidden; } -.copper-convert__ring-card::after { - content: ''; - position: absolute; - inset-inline-start: 50%; - bottom: -24px; - width: 80px; - height: 48px; - transform: translateX(-50%); - background: radial-gradient(ellipse, rgba(201, 160, 98, 0.35) 0%, transparent 70%); - pointer-events: none; -} - .copper-convert__ring-badge { display: inline-block; margin-bottom: 0.35rem; @@ -434,8 +390,8 @@ function formatRings(value: number) { border-radius: 999px; font-size: 0.625rem; font-weight: 700; - color: #0f2744; - background: rgba(201, 160, 98, 0.95); + color: var(--colorPrimary, #2563eb); + background: #fff; } .copper-convert__ring-count { @@ -443,20 +399,20 @@ function formatRings(value: number) { font-size: 1.5rem; font-weight: 800; line-height: 1.2; - color: #f8fafc; + color: #0f172a; } .copper-convert__ring-caption { margin: 0.15rem 0 0; font-size: 0.6875rem; font-weight: 600; - color: rgba(226, 232, 240, 0.85); + color: #64748b; } .copper-convert__ring-sub { margin: 0.35rem 0 0; font-size: 0.625rem; - color: rgba(201, 160, 98, 0.9); + color: #64748b; } .copper-convert__summary { @@ -479,7 +435,7 @@ function formatRings(value: number) { .copper-convert__summary-row strong { font-size: 0.8125rem; font-weight: 800; - color: #0f2744; + color: #0f172a; } .copper-convert__summary-row strong small { diff --git a/src/views/base/convert/composables/useCopperConvertPage.ts b/src/views/base/convert/composables/useCopperConvertPage.ts index 034cc71..e5071b6 100644 --- a/src/views/base/convert/composables/useCopperConvertPage.ts +++ b/src/views/base/convert/composables/useCopperConvertPage.ts @@ -1,6 +1,8 @@ import { computed, inject, + onMounted, + onUnmounted, provide, ref, type ComputedRef, @@ -144,14 +146,14 @@ export function useCopperConvertPage() { } } - async function refreshLivePrices() { + onMounted(() => { startLastPricePolling() - await loadCatalog() - } + void loadCatalog() + }) - function stopLivePrices() { + onUnmounted(() => { stopLastPricePolling() - } + }) const ctx: CopperConvertPageContext = { loading, @@ -163,7 +165,7 @@ export function useCopperConvertPage() { } provide(COPPER_CONVERT_PAGE_KEY, ctx) - return { ...ctx, refreshLivePrices, stopLivePrices, loadCatalog } + return ctx } export function useCopperConvertPageContext() { diff --git a/src/views/base/convert/desktop/DesktopConvertView.vue b/src/views/base/convert/desktop/DesktopConvertView.vue new file mode 100644 index 0000000..fce20ff --- /dev/null +++ b/src/views/base/convert/desktop/DesktopConvertView.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/src/views/base/convert/index.vue b/src/views/base/convert/index.vue new file mode 100644 index 0000000..136abd3 --- /dev/null +++ b/src/views/base/convert/index.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/src/views/base/convert/mobile/MobileConvertView.vue b/src/views/base/convert/mobile/MobileConvertView.vue new file mode 100644 index 0000000..bc9236d --- /dev/null +++ b/src/views/base/convert/mobile/MobileConvertView.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/views/base/copper&silver/index.vue b/src/views/base/copper&silver/index.vue index 293c8a6..a6a8761 100644 --- a/src/views/base/copper&silver/index.vue +++ b/src/views/base/copper&silver/index.vue @@ -42,14 +42,14 @@
- - diff --git a/src/views/base/gold/index.vue b/src/views/base/gold/index.vue index 77f0221..1a1ecee 100644 --- a/src/views/base/gold/index.vue +++ b/src/views/base/gold/index.vue @@ -74,14 +74,14 @@
- - diff --git a/src/views/base/home/composables/useHomePage.ts b/src/views/base/home/composables/useHomePage.ts index 80d7435..e53eee0 100644 --- a/src/views/base/home/composables/useHomePage.ts +++ b/src/views/base/home/composables/useHomePage.ts @@ -102,7 +102,7 @@ export function useHomePage() { icon: 'vuesax-linear:receipt-item', label: 'موجودی', handler: () => { - wholeBalanceVisible.value = true + router.push({ name: 'assets' }) }, }, { @@ -110,7 +110,7 @@ export function useHomePage() { icon: 'vuesax-linear:cup', label: 'دارایی ها', handler: () => { - wholeBalanceVisible.value = true + router.push({ name: 'assets' }) }, }, ] @@ -192,7 +192,7 @@ export function useHomePage() { } function openAssetsSheet() { - wholeBalanceVisible.value = true + router.push({ name: 'assets' }) } function handleBannerClick(banner: { typeClick?: string; modalText?: string; link?: string }) { diff --git a/src/views/base/home/index.vue b/src/views/base/home/index.vue index 01299d4..0b05717 100644 --- a/src/views/base/home/index.vue +++ b/src/views/base/home/index.vue @@ -4,12 +4,6 @@ - -
@@ -21,7 +15,6 @@