fixed dashboard in night mode
This commit is contained in:
+206
-45
@@ -92,24 +92,22 @@
|
||||
</section>
|
||||
|
||||
<!-- Date filter -->
|
||||
<section
|
||||
class="mt-2 rounded-xl border border-slate-200 bg-white px-3 py-2 dark:border-slate-600 dark:bg-slate-900"
|
||||
>
|
||||
<section class="dashboard-panel mt-2">
|
||||
<DashboardSectionHeader title="بازه گزارش" :help="copy.dateRange" />
|
||||
<div class="mb-2 grid grid-cols-1 gap-2 sm:grid-cols-3">
|
||||
<div
|
||||
v-for="metric in dateRangeMetrics"
|
||||
:key="metric.label"
|
||||
class="rounded-lg bg-slate-50 px-2.5 py-2 dark:bg-slate-800/60"
|
||||
class="dashboard-inline-metric rounded-lg px-2.5 py-2"
|
||||
>
|
||||
<DashboardLabelWithHelp
|
||||
:label="metric.label"
|
||||
:help="metric.help"
|
||||
size="xs"
|
||||
text-class="text-[10px]"
|
||||
label-class="text-slate-600 dark:text-slate-400"
|
||||
label-class="dashboard-text-muted"
|
||||
/>
|
||||
<p class="text-sm font-bold text-slate-900 dark:text-slate-50">{{ metric.value }}</p>
|
||||
<p class="dashboard-text text-sm font-bold">{{ metric.value }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
@@ -119,7 +117,7 @@
|
||||
class="!w-44"
|
||||
size="small"
|
||||
/>
|
||||
<span class="text-xs text-slate-500 dark:text-slate-400">تا</span>
|
||||
<span class="dashboard-text-muted text-xs">تا</span>
|
||||
<BaseDatePicker
|
||||
v-model:value="endDate"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
@@ -147,7 +145,7 @@
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-44 items-center justify-center text-xs text-slate-500 dark:text-slate-400"
|
||||
class="dashboard-empty flex h-44 items-center justify-center text-xs"
|
||||
>
|
||||
در این بازه داده مالی ثبت نشده
|
||||
</div>
|
||||
@@ -181,7 +179,7 @@
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-44 items-center justify-center text-xs text-slate-500 dark:text-slate-400"
|
||||
class="dashboard-empty flex h-44 items-center justify-center text-xs"
|
||||
>
|
||||
دادهای برای نمودار نیست
|
||||
</div>
|
||||
@@ -218,7 +216,7 @@
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-40 items-center justify-center text-xs text-slate-500 dark:text-slate-400"
|
||||
class="flex h-40 items-center justify-center text-xs dashboard-empty"
|
||||
>
|
||||
داده نمودار قیمت در دسترس نیست
|
||||
</div>
|
||||
@@ -249,16 +247,14 @@
|
||||
v-if="peakHoursData?.peak_hour != null && peakHoursData.peak_count > 0"
|
||||
class="mb-3 flex flex-wrap items-center gap-1.5"
|
||||
>
|
||||
<span
|
||||
class="inline-flex items-center rounded-full bg-amber-50 px-2.5 py-1 text-[11px] font-semibold text-amber-800 dark:bg-amber-950/40 dark:text-amber-200"
|
||||
>
|
||||
<span class="dashboard-peak-badge dashboard-peak-badge--primary inline-flex items-center rounded-full px-2.5 py-1 text-[11px] font-semibold">
|
||||
شلوغترین: {{ formatPeakHourLabel(peakHoursData.peak_hour) }}
|
||||
<span class="mr-1 font-normal opacity-75">({{ peakHoursData.peak_count }} سفارش)</span>
|
||||
</span>
|
||||
<span
|
||||
v-for="slot in topPeakHours.slice(1)"
|
||||
:key="slot.hour"
|
||||
class="inline-flex items-center rounded-full bg-slate-100 px-2 py-0.5 text-[10px] text-slate-600 dark:bg-slate-800 dark:text-slate-300"
|
||||
class="dashboard-peak-badge dashboard-peak-badge--muted inline-flex items-center rounded-full px-2 py-0.5 text-[10px]"
|
||||
>
|
||||
{{ formatPeakHourLabel(slot.hour) }} · {{ slot.total }}
|
||||
</span>
|
||||
@@ -274,7 +270,7 @@
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-44 items-center justify-center text-xs text-slate-500 dark:text-slate-400"
|
||||
class="dashboard-empty flex h-44 items-center justify-center text-xs"
|
||||
>
|
||||
در این بازه سفارشی ثبت نشده
|
||||
</div>
|
||||
@@ -312,7 +308,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-44 items-center justify-center text-xs text-slate-500 dark:text-slate-400"
|
||||
class="dashboard-empty flex h-44 items-center justify-center text-xs"
|
||||
>
|
||||
در این بازه معاملهای برای محصولات ثبت نشده
|
||||
</div>
|
||||
@@ -332,9 +328,9 @@
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full min-w-[52rem] text-sm">
|
||||
<table class="dashboard-table w-full min-w-[52rem] text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-slate-200 text-xs text-slate-600 dark:border-slate-700 dark:text-slate-300">
|
||||
<tr class="border-b text-xs">
|
||||
<th class="px-2 py-2 text-right">کد</th>
|
||||
<th class="px-2 py-2 text-right">نوع</th>
|
||||
<th class="px-2 py-2 text-right">مشتری</th>
|
||||
@@ -351,7 +347,7 @@
|
||||
<tr
|
||||
v-for="order in recentOrders"
|
||||
:key="order.id"
|
||||
class="border-b border-slate-100 text-slate-800 hover:bg-slate-50 dark:border-slate-800 dark:text-slate-200 dark:hover:bg-slate-800/50"
|
||||
class="border-b hover:bg-[var(--admin-bg-hover)]"
|
||||
>
|
||||
<td class="px-2 py-2.5 font-medium">#{{ order.id }}</td>
|
||||
<td class="px-2 py-2.5">
|
||||
@@ -363,10 +359,10 @@
|
||||
<td class="px-2 py-2.5">{{ formatGram(order.amount) }}</td>
|
||||
<td class="px-2 py-2.5">{{ usePrice(order.price_original ?? 0, true, '') }}</td>
|
||||
<td class="px-2 py-2.5">{{ usePrice(order.price ?? 0, true, '') }}</td>
|
||||
<td class="px-2 py-2.5 text-emerald-700 dark:text-emerald-400">
|
||||
<td class="dashboard-profit px-2 py-2.5">
|
||||
{{ usePrice(order.fee ?? 0, true, '') }}
|
||||
</td>
|
||||
<td class="px-2 py-2.5 font-semibold text-emerald-700 dark:text-emerald-400">
|
||||
<td class="dashboard-profit px-2 py-2.5 font-semibold">
|
||||
{{ usePrice(order.total_fee ?? 0, true, '') }}
|
||||
</td>
|
||||
<td class="px-2 py-2.5">
|
||||
@@ -374,7 +370,7 @@
|
||||
{{ stsLabel(order) }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-2 py-2.5 text-xs text-slate-500 dark:text-slate-400">
|
||||
<td class="dashboard-text-muted whitespace-nowrap px-2 py-2.5 text-xs">
|
||||
{{ order.created_at ? toJalali(order.created_at) : '—' }}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -393,17 +389,17 @@
|
||||
v-for="item in customerMetricItems"
|
||||
:key="item.label"
|
||||
class="dashboard-metric-cell"
|
||||
:class="item.bgClass"
|
||||
:class="`dashboard-metric-cell--${item.variant}`"
|
||||
>
|
||||
<DashboardLabelWithHelp
|
||||
:label="item.label"
|
||||
:help="item.help"
|
||||
size="xs"
|
||||
text-class="text-[11px]"
|
||||
:label-class="item.labelClass"
|
||||
label-class="dashboard-text-muted"
|
||||
root-class="dashboard-metric-label"
|
||||
/>
|
||||
<p class="dashboard-metric-value" :class="item.valueClass">{{ item.value }}</p>
|
||||
<p class="dashboard-metric-value">{{ item.value }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -415,17 +411,17 @@
|
||||
v-for="item in walletMetricItems"
|
||||
:key="item.label"
|
||||
class="dashboard-metric-cell"
|
||||
:class="item.bgClass"
|
||||
:class="`dashboard-metric-cell--${item.variant}`"
|
||||
>
|
||||
<DashboardLabelWithHelp
|
||||
:label="item.label"
|
||||
:help="item.help"
|
||||
size="xs"
|
||||
text-class="text-[11px]"
|
||||
label-class="text-slate-600 dark:text-slate-400"
|
||||
label-class="dashboard-text-muted"
|
||||
root-class="dashboard-metric-label"
|
||||
/>
|
||||
<p class="dashboard-metric-value text-slate-900 dark:text-slate-50">{{ item.value }}</p>
|
||||
<p class="dashboard-metric-value">{{ item.value }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -553,33 +549,25 @@ const customerMetricItems = computed(() => [
|
||||
label: 'کل مشتریان',
|
||||
value: customerStats.value.total,
|
||||
help: dashboardCustomerMetrics.total,
|
||||
bgClass: 'bg-slate-50 dark:bg-slate-800/60',
|
||||
labelClass: 'text-slate-600 dark:text-slate-400',
|
||||
valueClass: 'text-slate-900 dark:text-slate-50',
|
||||
variant: 'default',
|
||||
},
|
||||
{
|
||||
label: 'جدید (۳ ماه)',
|
||||
value: customerStats.value.newCount,
|
||||
help: dashboardCustomerMetrics.new,
|
||||
bgClass: 'bg-slate-50 dark:bg-slate-800/60',
|
||||
labelClass: 'text-slate-600 dark:text-slate-400',
|
||||
valueClass: 'text-slate-900 dark:text-slate-50',
|
||||
variant: 'default',
|
||||
},
|
||||
{
|
||||
label: 'فعال',
|
||||
value: customerStats.value.active,
|
||||
help: dashboardCustomerMetrics.active,
|
||||
bgClass: 'bg-emerald-50 dark:bg-emerald-950/40',
|
||||
labelClass: 'text-emerald-800 dark:text-emerald-300',
|
||||
valueClass: 'text-emerald-800 dark:text-emerald-300',
|
||||
variant: 'success',
|
||||
},
|
||||
{
|
||||
label: 'بدون احراز',
|
||||
value: customerStats.value.notVerified,
|
||||
help: dashboardCustomerMetrics.notVerified,
|
||||
bgClass: 'bg-rose-50 dark:bg-rose-950/40',
|
||||
labelClass: 'text-rose-800 dark:text-rose-300',
|
||||
valueClass: 'text-rose-800 dark:text-rose-300',
|
||||
variant: 'danger',
|
||||
},
|
||||
])
|
||||
|
||||
@@ -588,30 +576,136 @@ const walletMetricItems = computed(() => [
|
||||
label: 'طلای مشتریان',
|
||||
value: formatGram(walletSums.value?.gold),
|
||||
help: dashboardWalletMetrics.gold,
|
||||
bgClass: 'bg-amber-50 dark:bg-amber-950/35',
|
||||
variant: 'amber',
|
||||
},
|
||||
{
|
||||
label: 'ریال مشتریان',
|
||||
value: usePrice(walletSums.value?.cash ?? 0, true, ''),
|
||||
help: dashboardWalletMetrics.cash,
|
||||
bgClass: 'bg-sky-50 dark:bg-sky-950/35',
|
||||
variant: 'sky',
|
||||
},
|
||||
{
|
||||
label: 'ارزش طلا به ریال',
|
||||
value: usePrice(walletSums.value?.goldToCash ?? 0, true, ''),
|
||||
help: dashboardWalletMetrics.goldToCash,
|
||||
bgClass: 'bg-violet-50 dark:bg-violet-950/35',
|
||||
variant: 'violet',
|
||||
},
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dashboard-panel {
|
||||
@apply rounded-xl border border-slate-200 bg-white p-4 dark:border-slate-600 dark:bg-slate-900;
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid var(--admin-border);
|
||||
background: var(--admin-bg-elevated);
|
||||
color: var(--admin-text);
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.dashboard-text {
|
||||
color: var(--admin-text);
|
||||
}
|
||||
|
||||
.dashboard-text-muted {
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-empty {
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-inline-metric {
|
||||
background: var(--admin-bg-muted);
|
||||
}
|
||||
|
||||
.dashboard-profit {
|
||||
color: #059669;
|
||||
}
|
||||
|
||||
.dashboard-metric-cell {
|
||||
@apply flex min-h-[4.75rem] flex-col justify-between rounded-lg px-3 py-3;
|
||||
display: flex;
|
||||
min-height: 4.75rem;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
background: var(--admin-bg-muted);
|
||||
color: var(--admin-text);
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--success {
|
||||
background: rgba(16, 185, 129, 0.12);
|
||||
border: 1px solid rgba(16, 185, 129, 0.18);
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--danger {
|
||||
background: rgba(244, 63, 94, 0.1);
|
||||
border: 1px solid rgba(244, 63, 94, 0.18);
|
||||
color: #be123c;
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--amber {
|
||||
background: rgba(245, 158, 11, 0.12);
|
||||
border: 1px solid rgba(245, 158, 11, 0.18);
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--sky {
|
||||
background: rgba(14, 165, 233, 0.12);
|
||||
border: 1px solid rgba(14, 165, 233, 0.18);
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--violet {
|
||||
background: rgba(139, 92, 246, 0.12);
|
||||
border: 1px solid rgba(139, 92, 246, 0.18);
|
||||
}
|
||||
|
||||
.dashboard-peak-badge--primary {
|
||||
background: rgba(245, 158, 11, 0.14);
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
.dashboard-peak-badge--muted {
|
||||
background: var(--admin-bg-muted);
|
||||
color: var(--admin-text-muted);
|
||||
}
|
||||
|
||||
.dashboard-table thead tr,
|
||||
.dashboard-table tbody tr {
|
||||
border-color: var(--admin-border);
|
||||
}
|
||||
|
||||
.dashboard-table thead tr {
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-table tbody tr {
|
||||
color: var(--admin-text);
|
||||
}
|
||||
|
||||
.dashboard-badge--buy {
|
||||
background: rgba(16, 185, 129, 0.14);
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.dashboard-badge--sell {
|
||||
background: rgba(244, 63, 94, 0.14);
|
||||
color: #be123c;
|
||||
}
|
||||
|
||||
.dashboard-badge--ok {
|
||||
background: rgba(16, 185, 129, 0.14);
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.dashboard-badge--open {
|
||||
background: rgba(245, 158, 11, 0.14);
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
.dashboard-badge--fail {
|
||||
background: rgba(244, 63, 94, 0.14);
|
||||
color: #be123c;
|
||||
}
|
||||
|
||||
.dashboard-metric-value {
|
||||
@@ -683,3 +777,70 @@ const walletMetricItems = computed(() => [
|
||||
transform: translateX(-2px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
html.is-dark {
|
||||
.dashboard-v2 {
|
||||
.dashboard-profit {
|
||||
color: #6ee7b7;
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--success {
|
||||
background: rgba(16, 185, 129, 0.16);
|
||||
border-color: rgba(16, 185, 129, 0.28);
|
||||
color: #6ee7b7;
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--danger {
|
||||
background: rgba(244, 63, 94, 0.16);
|
||||
border-color: rgba(244, 63, 94, 0.28);
|
||||
color: #fda4af;
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--amber {
|
||||
background: rgba(245, 158, 11, 0.16);
|
||||
border-color: rgba(245, 158, 11, 0.28);
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--sky {
|
||||
background: rgba(14, 165, 233, 0.16);
|
||||
border-color: rgba(14, 165, 233, 0.28);
|
||||
}
|
||||
|
||||
.dashboard-metric-cell--violet {
|
||||
background: rgba(139, 92, 246, 0.16);
|
||||
border-color: rgba(139, 92, 246, 0.28);
|
||||
}
|
||||
|
||||
.dashboard-peak-badge--primary {
|
||||
background: rgba(245, 158, 11, 0.18);
|
||||
color: #fcd34d;
|
||||
}
|
||||
|
||||
.dashboard-badge--buy {
|
||||
background: rgba(16, 185, 129, 0.2);
|
||||
color: #6ee7b7;
|
||||
}
|
||||
|
||||
.dashboard-badge--sell {
|
||||
background: rgba(244, 63, 94, 0.2);
|
||||
color: #fda4af;
|
||||
}
|
||||
|
||||
.dashboard-badge--open {
|
||||
background: rgba(245, 158, 11, 0.2);
|
||||
color: #fcd34d;
|
||||
}
|
||||
|
||||
.dashboard-badge--fail {
|
||||
background: rgba(244, 63, 94, 0.2);
|
||||
color: #fda4af;
|
||||
}
|
||||
|
||||
.dashboard-badge--ok {
|
||||
background: rgba(16, 185, 129, 0.2);
|
||||
color: #6ee7b7;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user