From 1adc21737540c4656b05ffa67bd4e0f5bda9bb2c Mon Sep 17 00:00:00 2001 From: Mahdi Date: Mon, 21 Sep 2026 17:55:05 +0330 Subject: [PATCH] Edit dashboard appearance --- .../web/src/components/dashboard/HomeHero.vue | 40 ++-------- .../components/dashboard/HomeMiniPipeline.vue | 47 ++++------- .../components/dashboard/HomePanelEmpty.vue | 77 +++++++++++++++++++ .../dashboard/HomeRecentActivities.vue | 48 ++++-------- .../components/dashboard/HomeSalesTrend.vue | 17 ++-- .../components/dashboard/HomeSourcesChart.vue | 29 ++++--- .../components/dashboard/HomeTopCustomers.vue | 34 +++++--- apps/web/src/styles/main.css | 6 ++ apps/web/src/views/TeamSettingsView.vue | 1 + 9 files changed, 169 insertions(+), 130 deletions(-) create mode 100644 apps/web/src/components/dashboard/HomePanelEmpty.vue diff --git a/apps/web/src/components/dashboard/HomeHero.vue b/apps/web/src/components/dashboard/HomeHero.vue index d2b4416..d6502c8 100644 --- a/apps/web/src/components/dashboard/HomeHero.vue +++ b/apps/web/src/components/dashboard/HomeHero.vue @@ -32,31 +32,8 @@ type HeroChip = { link: string; }; -const defaultChips: HeroChip[] = [ - { - key: 'demo-urgent', - tone: 'urgent', - title: 'شرکت آماده تصمیم‌گیریه', - subtitle: 'امروز تماس بگیر', - link: '/pipeline', - }, - { - key: 'demo-warning', - tone: 'warning', - title: '۳ معامله بیشتر از ۵ روزه', - subtitle: 'پیگیری نشدن', - link: '/pipeline', - }, - { - key: 'demo-success', - tone: 'success', - title: 'این ماه از تارگت جلوتری', - link: '/sales/forecast', - }, -]; - -const chips = computed(() => { - const fromApi = props.alerts.slice(0, 3).map((a) => { +const chips = computed(() => + props.alerts.slice(0, 3).map((a) => { const parts = a.text.split(/\s*[—\-–]\s*|\n/); const title = parts[0]?.trim() || a.text; const subtitle = parts.slice(1).join(' ').trim() || undefined; @@ -67,12 +44,8 @@ const chips = computed(() => { subtitle, link: a.link || '/', }; - }); - if (fromApi.length >= 3) return fromApi; - const usedTones = new Set(fromApi.map((c) => c.tone)); - const fillers = defaultChips.filter((c) => !usedTones.has(c.tone)); - return [...fromApi, ...fillers].slice(0, 3); -}); + }), +); function alertIcon(tone: string) { if (tone === 'urgent') return 'fire' as const; @@ -103,11 +76,12 @@ const shortcutLabel = computed(() =>

{{ greeting }} {{ firstName }} 👋

-

{{ brand.nameFa }} اینا رو برات پیدا کرده

+

{{ brand.nameFa }} اینا رو برات پیدا کرده

+

از {{ brand.nameFa }} بپرس یا کار امروز را شروع کن

-
+
(() => { - const stages = props.board?.stages.slice(0, 3) ?? []; + const stages = props.board?.stages ?? []; const hasDeals = stages.some((s) => s.deals.length); - if (!stages.length || !hasDeals) return demoCols; - return stages.map((stage) => ({ + if (!hasDeals) return []; + return stages.slice(0, 3).map((stage) => ({ id: stage.id, name: stage.name, count: stage.deals.length, @@ -73,7 +47,14 @@ const cols = computed(() => { نمایش همه -
+ +
{{ col.name }} ({{ toFaDigits(col.count) }}) @@ -83,7 +64,7 @@ const cols = computed(() => { v-for="card in col.cards" :key="card.id" class="pipe-card" - :to="card.id.length > 4 ? { name: 'deal-detail', params: { id: card.id } } : { name: 'pipeline' }" + :to="{ name: 'deal-detail', params: { id: card.id } }" > {{ card.name.slice(0, 1) }}
@@ -106,6 +87,8 @@ const cols = computed(() => { box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04); border: 1px solid #eef2f7; min-width: 0; + display: flex; + flex-direction: column; } .panel-head { diff --git a/apps/web/src/components/dashboard/HomePanelEmpty.vue b/apps/web/src/components/dashboard/HomePanelEmpty.vue new file mode 100644 index 0000000..0a8ab12 --- /dev/null +++ b/apps/web/src/components/dashboard/HomePanelEmpty.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/apps/web/src/components/dashboard/HomeRecentActivities.vue b/apps/web/src/components/dashboard/HomeRecentActivities.vue index 6dd41d2..4409323 100644 --- a/apps/web/src/components/dashboard/HomeRecentActivities.vue +++ b/apps/web/src/components/dashboard/HomeRecentActivities.vue @@ -2,6 +2,7 @@ import { computed } from 'vue'; import { RouterLink } from 'vue-router'; import UiIcon from '@/components/UiIcon.vue'; +import HomePanelEmpty from '@/components/dashboard/HomePanelEmpty.vue'; import type { ActivityDto } from '@mento/shared'; const props = defineProps<{ @@ -18,33 +19,6 @@ type Row = { label: string; }; -const demoRows: Row[] = [ - { - id: 'd1', - title: 'تماس با شرکت آریا', - when: 'امروز، ۱۰:۴۵', - type: 'call', - tone: 'done', - label: 'انجام شد', - }, - { - id: 'd2', - title: 'ارسال پیشنهاد قیمت به پارسیان', - when: 'دیروز، ۱۴:۴۰', - type: 'mail', - tone: 'pending', - label: 'در انتظار پاسخ', - }, - { - id: 'd3', - title: 'جلسه با مشتری جدید', - when: 'پریروز، ۱۱:۰۰', - type: 'meeting', - tone: 'held', - label: 'برگزار شد', - }, -]; - const typeLabel: Record = { call: 'تماس', meeting: 'جلسه', @@ -67,9 +41,8 @@ function activityIcon(type: string) { return 'mail' as const; } -const rows = computed(() => { - if (!props.activities.length) return demoRows; - return props.activities.slice(0, 3).map((act) => { +const rows = computed(() => + props.activities.slice(0, 3).map((act) => { const st = activityStatus(act); return { id: act.id, @@ -79,8 +52,8 @@ const rows = computed(() => { tone: st.tone, label: st.label, }; - }); -}); + }), +);