fixed dashboard in night mode
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
:label="title"
|
||||
:help="help"
|
||||
size="sm"
|
||||
label-class="font-bold text-slate-900 dark:text-slate-100"
|
||||
label-class="dashboard-section-title font-bold"
|
||||
root-class="dashboard-section-title"
|
||||
/>
|
||||
</div>
|
||||
@@ -19,3 +19,9 @@ defineProps<{
|
||||
help?: DashboardHelp
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dashboard-section-header :deep(.dashboard-section-title) {
|
||||
color: var(--admin-text);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex h-full min-h-[4.25rem] items-center gap-2 rounded-xl border border-slate-200/90 bg-white px-2.5 py-2 dark:border-slate-600 dark:bg-slate-900"
|
||||
>
|
||||
<div class="dashboard-stat-card flex h-full min-h-[4.25rem] items-center gap-2 rounded-xl px-2.5 py-2">
|
||||
<div
|
||||
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg"
|
||||
:class="iconBgClass"
|
||||
@@ -13,9 +11,9 @@
|
||||
:label="title"
|
||||
:help="help"
|
||||
size="xs"
|
||||
label-class="font-medium text-slate-600 dark:text-slate-300"
|
||||
label-class="dashboard-text-muted font-medium"
|
||||
/>
|
||||
<p class="truncate text-[15px] font-bold leading-snug text-slate-900 dark:text-slate-50">
|
||||
<p class="dashboard-text truncate text-[15px] font-bold leading-snug">
|
||||
{{ value }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -44,31 +42,123 @@ const props = withDefaults(
|
||||
|
||||
const toneMap: Record<Tone, { iconBg: string; iconText: string }> = {
|
||||
gold: {
|
||||
iconBg: 'bg-amber-100 dark:bg-amber-500/25',
|
||||
iconText: 'text-amber-700 dark:text-amber-300',
|
||||
iconBg: 'dashboard-stat-card__icon dashboard-stat-card__icon--amber',
|
||||
iconText: 'text-amber-700',
|
||||
},
|
||||
green: {
|
||||
iconBg: 'bg-emerald-100 dark:bg-emerald-500/25',
|
||||
iconText: 'text-emerald-700 dark:text-emerald-300',
|
||||
iconBg: 'dashboard-stat-card__icon dashboard-stat-card__icon--green',
|
||||
iconText: 'text-emerald-700',
|
||||
},
|
||||
blue: {
|
||||
iconBg: 'bg-sky-100 dark:bg-sky-500/25',
|
||||
iconText: 'text-sky-700 dark:text-sky-300',
|
||||
iconBg: 'dashboard-stat-card__icon dashboard-stat-card__icon--sky',
|
||||
iconText: 'text-sky-700',
|
||||
},
|
||||
rose: {
|
||||
iconBg: 'bg-rose-100 dark:bg-rose-500/25',
|
||||
iconText: 'text-rose-700 dark:text-rose-300',
|
||||
iconBg: 'dashboard-stat-card__icon dashboard-stat-card__icon--rose',
|
||||
iconText: 'text-rose-700',
|
||||
},
|
||||
violet: {
|
||||
iconBg: 'bg-violet-100 dark:bg-violet-500/25',
|
||||
iconText: 'text-violet-700 dark:text-violet-300',
|
||||
iconBg: 'dashboard-stat-card__icon dashboard-stat-card__icon--violet',
|
||||
iconText: 'text-violet-700',
|
||||
},
|
||||
amber: {
|
||||
iconBg: 'bg-orange-100 dark:bg-orange-500/25',
|
||||
iconText: 'text-orange-700 dark:text-orange-300',
|
||||
iconBg: 'dashboard-stat-card__icon dashboard-stat-card__icon--orange',
|
||||
iconText: 'text-orange-700',
|
||||
},
|
||||
}
|
||||
|
||||
const iconBgClass = computed(() => toneMap[props.tone].iconBg)
|
||||
const iconTextClass = computed(() => toneMap[props.tone].iconText)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dashboard-stat-card {
|
||||
border: 1px solid var(--admin-border);
|
||||
background: var(--admin-bg-elevated);
|
||||
color: var(--admin-text);
|
||||
}
|
||||
|
||||
.dashboard-text {
|
||||
color: var(--admin-text);
|
||||
}
|
||||
|
||||
.dashboard-text-muted {
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--amber {
|
||||
background: rgba(245, 158, 11, 0.14);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--green {
|
||||
background: rgba(16, 185, 129, 0.14);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--sky {
|
||||
background: rgba(14, 165, 233, 0.14);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--rose {
|
||||
background: rgba(244, 63, 94, 0.14);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--violet {
|
||||
background: rgba(139, 92, 246, 0.14);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--orange {
|
||||
background: rgba(249, 115, 22, 0.14);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
html.is-dark {
|
||||
.dashboard-stat-card__icon--amber {
|
||||
background: rgba(245, 158, 11, 0.22);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--green {
|
||||
background: rgba(16, 185, 129, 0.22);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--sky {
|
||||
background: rgba(14, 165, 233, 0.22);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--rose {
|
||||
background: rgba(244, 63, 94, 0.22);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--violet {
|
||||
background: rgba(139, 92, 246, 0.22);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__icon--orange {
|
||||
background: rgba(249, 115, 22, 0.22);
|
||||
}
|
||||
|
||||
.dashboard-stat-card .text-amber-700 {
|
||||
color: #fcd34d !important;
|
||||
}
|
||||
|
||||
.dashboard-stat-card .text-emerald-700 {
|
||||
color: #6ee7b7 !important;
|
||||
}
|
||||
|
||||
.dashboard-stat-card .text-sky-700 {
|
||||
color: #7dd3fc !important;
|
||||
}
|
||||
|
||||
.dashboard-stat-card .text-rose-700 {
|
||||
color: #fda4af !important;
|
||||
}
|
||||
|
||||
.dashboard-stat-card .text-violet-700 {
|
||||
color: #c4b5fd !important;
|
||||
}
|
||||
|
||||
.dashboard-stat-card .text-orange-700 {
|
||||
color: #fdba74 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,6 +25,7 @@ import { usePrice } from '@core/utils/usePrice'
|
||||
import { toJalali } from '@core/utils/useDataTime'
|
||||
import { isMobile } from '@core/utils/is'
|
||||
import { isStoreApp } from '@/utils/config'
|
||||
import { useAdminTheme } from '@core/composable/useAdminTheme'
|
||||
|
||||
function truncateChartLabel(label: string, maxLen: number) {
|
||||
const text = String(label ?? '').trim()
|
||||
@@ -66,6 +67,7 @@ function productActivityDateRange(range: ProductActivityRange) {
|
||||
}
|
||||
|
||||
export function useDashboardPage() {
|
||||
const { isDark } = useAdminTheme()
|
||||
const loading = ref(true)
|
||||
const flowLoading = ref(false)
|
||||
const productActivityLoading = ref(false)
|
||||
@@ -235,20 +237,31 @@ export function useDashboardPage() {
|
||||
return direction === 1 ? 'خرید' : direction === 2 ? 'فروش' : '—'
|
||||
}
|
||||
|
||||
function chartSurfaceOptions() {
|
||||
const dark = isDark.value
|
||||
const labelColor = dark ? 'rgba(255,255,255,0.55)' : 'rgba(0,0,0,0.55)'
|
||||
const gridColor = dark ? 'rgba(255,255,255,0.12)' : 'rgba(0,0,0,0.08)'
|
||||
|
||||
return {
|
||||
theme: { mode: dark ? 'dark' as const : 'light' as const },
|
||||
chart: { foreColor: labelColor },
|
||||
grid: { borderColor: gridColor },
|
||||
xaxis: { labels: { style: { colors: labelColor } } },
|
||||
yaxis: { labels: { style: { colors: labelColor } } },
|
||||
legend: { labels: { colors: labelColor } },
|
||||
}
|
||||
}
|
||||
|
||||
function directionClass(direction?: number) {
|
||||
return direction === 1
|
||||
? 'bg-emerald-100 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300'
|
||||
: 'bg-rose-100 text-rose-700 dark:bg-rose-500/20 dark:text-rose-300'
|
||||
if (direction === 1) return 'dashboard-badge dashboard-badge--buy rounded-md px-2 py-0.5 text-xs'
|
||||
if (direction === 2) return 'dashboard-badge dashboard-badge--sell rounded-md px-2 py-0.5 text-xs'
|
||||
return 'dashboard-badge rounded-md px-2 py-0.5 text-xs'
|
||||
}
|
||||
|
||||
function stsClass(sts?: number) {
|
||||
if (sts === 2) {
|
||||
return 'bg-emerald-100 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300'
|
||||
}
|
||||
if (sts === 1) {
|
||||
return 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300'
|
||||
}
|
||||
return 'bg-rose-100 text-rose-700 dark:bg-rose-500/20 dark:text-rose-300'
|
||||
if (sts === 2) return 'dashboard-badge dashboard-badge--ok rounded-md px-2 py-0.5 text-xs'
|
||||
if (sts === 1) return 'dashboard-badge dashboard-badge--open rounded-md px-2 py-0.5 text-xs'
|
||||
return 'dashboard-badge dashboard-badge--fail rounded-md px-2 py-0.5 text-xs'
|
||||
}
|
||||
|
||||
function stsLabel(order: Order) {
|
||||
@@ -262,7 +275,8 @@ export function useDashboardPage() {
|
||||
const gifts = finance.value?.GiftsPrise ?? 0
|
||||
|
||||
return {
|
||||
chart: { type: 'donut', fontFamily: 'inherit', offsetY: 4 },
|
||||
...chartSurfaceOptions(),
|
||||
chart: { type: 'donut', fontFamily: 'inherit', offsetY: 4, foreColor: chartSurfaceOptions().chart.foreColor },
|
||||
labels: ['سود معامله', 'کارمزد طلایی', 'هدایای طلا'],
|
||||
colors: ['#10b981', '#f59e0b', '#8b5cf6'],
|
||||
legend: {
|
||||
@@ -297,6 +311,7 @@ export function useDashboardPage() {
|
||||
|
||||
const flowChartOptions = computed(() => {
|
||||
const mobile = isMobile.value
|
||||
const surface = chartSurfaceOptions()
|
||||
const points = [...flowData.value].sort((a, b) =>
|
||||
String(a.date ?? '').localeCompare(String(b.date ?? '')),
|
||||
)
|
||||
@@ -306,12 +321,14 @@ export function useDashboardPage() {
|
||||
})
|
||||
|
||||
return {
|
||||
...surface,
|
||||
chart: {
|
||||
type: 'bar',
|
||||
stacked: true,
|
||||
toolbar: { show: false },
|
||||
fontFamily: 'inherit',
|
||||
redrawOnParentResize: true,
|
||||
foreColor: surface.chart.foreColor,
|
||||
},
|
||||
plotOptions: { bar: { borderRadius: 4, columnWidth: mobile ? '48%' : '55%' } },
|
||||
colors: ['#10b981', '#f43f5e'],
|
||||
@@ -352,7 +369,14 @@ export function useDashboardPage() {
|
||||
priceRange.value === 'DAILY' ? 'yyyy/MM/dd HH:mm' : 'yyyy/MM/dd'
|
||||
|
||||
return {
|
||||
chart: { type: 'area', toolbar: { show: false }, fontFamily: 'inherit', zoom: { enabled: false } },
|
||||
...chartSurfaceOptions(),
|
||||
chart: {
|
||||
type: 'area',
|
||||
toolbar: { show: false },
|
||||
fontFamily: 'inherit',
|
||||
zoom: { enabled: false },
|
||||
foreColor: chartSurfaceOptions().chart.foreColor,
|
||||
},
|
||||
stroke: { curve: 'smooth', width: 2 },
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
@@ -408,12 +432,14 @@ export function useDashboardPage() {
|
||||
const categories = slots.map((slot) => formatPeakHourLabel(slot.hour))
|
||||
|
||||
return {
|
||||
...chartSurfaceOptions(),
|
||||
chart: {
|
||||
type: 'bar',
|
||||
stacked: true,
|
||||
toolbar: { show: false },
|
||||
fontFamily: 'inherit',
|
||||
redrawOnParentResize: true,
|
||||
foreColor: chartSurfaceOptions().chart.foreColor,
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
@@ -481,11 +507,13 @@ export function useDashboardPage() {
|
||||
mobile ? truncateChartLabel(String(val), 11) : String(val)
|
||||
|
||||
return {
|
||||
...chartSurfaceOptions(),
|
||||
chart: {
|
||||
type: 'bar',
|
||||
toolbar: { show: false },
|
||||
fontFamily: 'inherit',
|
||||
redrawOnParentResize: true,
|
||||
foreColor: chartSurfaceOptions().chart.foreColor,
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
|
||||
+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