2026-01-24 17:45:54 +03:30
|
|
|
|
<template>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<div class="dashboard-v2 box-border min-h-full w-full max-w-full overflow-x-hidden p-2 md:p-3">
|
|
|
|
|
|
<a-spin :spinning="loading">
|
|
|
|
|
|
<!-- Hero -->
|
|
|
|
|
|
<section
|
2026-06-21 21:55:54 +03:30
|
|
|
|
class="dashboard-hero rounded-xl bg-gradient-to-l from-[#0f766e] via-[#1e3a5f] to-[#0f172a] px-3 py-2.5 text-white shadow-md"
|
2026-01-24 17:45:54 +03:30
|
|
|
|
>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="flex flex-col gap-2.5 md:flex-row md:items-center md:justify-between md:gap-3">
|
|
|
|
|
|
<div class="order-2 min-w-0 md:order-1">
|
|
|
|
|
|
<div class="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardLabelWithHelp
|
2026-06-21 21:55:54 +03:30
|
|
|
|
label="مظنه"
|
|
|
|
|
|
:help="copy.hero"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
size="xs"
|
|
|
|
|
|
text-class="text-[11px]"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
label-class="text-white/80"
|
2026-01-26 11:21:13 +03:30
|
|
|
|
/>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<span class="text-[11px] text-white/80">/گرم</span>
|
2026-07-01 22:28:09 +03:30
|
|
|
|
<span class="text-lg font-bold leading-none">{{ usePrice(master?.price ?? 0, true, 'ریال') }}</span>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<span class="text-white/35">·</span>
|
|
|
|
|
|
<span class="text-[11px] text-white/80">مثقال</span>
|
2026-07-01 22:28:09 +03:30
|
|
|
|
<span class="text-sm font-semibold leading-none">{{ usePrice(master?.pricem ?? 0, true, 'ریال') }}</span>
|
2026-01-26 11:21:13 +03:30
|
|
|
|
</div>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<p v-if="master?.update_date" class="mt-1 text-[10px] leading-none text-white/55">
|
|
|
|
|
|
{{ toJalali(master.update_date) }}
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="order-1 w-full shrink-0 md:order-2 md:w-auto">
|
|
|
|
|
|
<DashboardQuickActionsBar
|
|
|
|
|
|
:quick-action-loading="quickActionLoading"
|
|
|
|
|
|
:has-product-snapshot="hasProductSnapshot"
|
|
|
|
|
|
:product-snapshot-count="productSnapshotCount"
|
|
|
|
|
|
@wallet="showQuickWallet = true"
|
|
|
|
|
|
@deactivate-all="deactivateAll"
|
|
|
|
|
|
@restore-products="restoreProducts"
|
|
|
|
|
|
@close-all-buy="closeAllBuy"
|
|
|
|
|
|
@close-all-sell="closeAllSell"
|
|
|
|
|
|
@sync-prices="syncPrices"
|
|
|
|
|
|
@sync-show="syncShow"
|
|
|
|
|
|
/>
|
2026-01-26 11:21:13 +03:30
|
|
|
|
</div>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<DashboardQuickWalletModal v-model:visible="showQuickWallet" />
|
|
|
|
|
|
|
2026-07-01 22:28:09 +03:30
|
|
|
|
<DashboardTradingIncomeSummary :finance="finance" />
|
|
|
|
|
|
|
|
|
|
|
|
<!-- تراز و آمار — ۴ کارت در یک ردیف -->
|
|
|
|
|
|
<section class="dashboard-metrics-row mt-2">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardStatCard
|
|
|
|
|
|
tone="green"
|
|
|
|
|
|
icon="vuesax-linear:receipt-2"
|
|
|
|
|
|
title="تعداد سفارش"
|
2026-07-01 22:28:09 +03:30
|
|
|
|
subtitle="ثبتشده در بازه"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
:value="String(finance?.orderCount ?? 0)"
|
|
|
|
|
|
:help="copy.kpi.orderCount"
|
|
|
|
|
|
/>
|
2026-07-01 22:28:09 +03:30
|
|
|
|
<DashboardStatCard
|
|
|
|
|
|
v-if="metalBalanceItems.length === 1"
|
|
|
|
|
|
tone="blue"
|
|
|
|
|
|
icon="vuesax-linear:empty-wallet"
|
|
|
|
|
|
:title="metalBalanceTitle(metalBalanceItems[0].metal_id, metalBalanceItems[0].label)"
|
|
|
|
|
|
subtitle="تراز وزن — سفارش موفق"
|
|
|
|
|
|
:value="formatGram(metalBalanceItems[0].goldBalance, metalBalanceItems[0].metal_id)"
|
|
|
|
|
|
:help="copy.kpi.goldBalance"
|
|
|
|
|
|
/>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardStatCard
|
2026-06-23 22:31:07 +03:30
|
|
|
|
v-else
|
2026-06-21 20:27:13 +03:30
|
|
|
|
tone="blue"
|
|
|
|
|
|
icon="vuesax-linear:empty-wallet"
|
2026-06-23 22:31:07 +03:30
|
|
|
|
:title="metalLabel.goldBalance()"
|
2026-07-01 22:28:09 +03:30
|
|
|
|
subtitle="تراز وزن — سفارش موفق"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
:value="formatGram(balance?.goldBalance)"
|
|
|
|
|
|
:help="copy.kpi.goldBalance"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<DashboardStatCard
|
|
|
|
|
|
tone="rose"
|
|
|
|
|
|
icon="vuesax-linear:dollar-circle"
|
|
|
|
|
|
title="تراز ریالی"
|
2026-07-01 22:28:09 +03:30
|
|
|
|
subtitle="ورود/خروج نقد"
|
|
|
|
|
|
:value="formatDashboardAmount(balance?.cashBalance)"
|
|
|
|
|
|
:unit="DASHBOARD_RIAL_UNIT"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
:help="copy.kpi.cashBalance"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<DashboardStatCard
|
|
|
|
|
|
tone="violet"
|
|
|
|
|
|
icon="vuesax-linear:chart-2"
|
|
|
|
|
|
title="تراز مظنه"
|
2026-07-01 22:28:09 +03:30
|
|
|
|
subtitle="میانگین موزون"
|
|
|
|
|
|
:value="formatDashboardAmount(balance?.mazanehBalance)"
|
|
|
|
|
|
:unit="DASHBOARD_RIAL_UNIT"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
:help="copy.kpi.mazanehBalance"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
2026-07-01 22:28:09 +03:30
|
|
|
|
<!-- بازه گزارش -->
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<section class="dashboard-panel mt-2">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardSectionHeader title="بازه گزارش" :help="copy.dateRange" />
|
2026-07-01 22:28:09 +03:30
|
|
|
|
<div class="dashboard-metrics-row mb-2">
|
2026-01-26 11:21:13 +03:30
|
|
|
|
<div
|
2026-06-21 20:27:13 +03:30
|
|
|
|
v-for="metric in dateRangeMetrics"
|
|
|
|
|
|
:key="metric.label"
|
2026-06-21 22:15:17 +03:30
|
|
|
|
class="dashboard-inline-metric rounded-lg px-2.5 py-2"
|
2026-01-26 11:21:13 +03:30
|
|
|
|
>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardLabelWithHelp
|
|
|
|
|
|
:label="metric.label"
|
|
|
|
|
|
:help="metric.help"
|
|
|
|
|
|
size="xs"
|
|
|
|
|
|
text-class="text-[10px]"
|
2026-06-21 22:15:17 +03:30
|
|
|
|
label-class="dashboard-text-muted"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
/>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<p class="dashboard-text text-sm font-bold">{{ metric.value }}</p>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
|
|
|
|
<BaseDatePicker
|
|
|
|
|
|
v-model:value="startDate"
|
|
|
|
|
|
format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
|
class="!w-44"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
/>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<span class="dashboard-text-muted text-xs">تا</span>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<BaseDatePicker
|
|
|
|
|
|
v-model:value="endDate"
|
|
|
|
|
|
format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
|
class="!w-44"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<a-button type="primary" size="small" @click="applyDateRange">اعمال</a-button>
|
|
|
|
|
|
<a-button size="small" @click="refreshAll">بروزرسانی</a-button>
|
|
|
|
|
|
</div>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Charts row 1 -->
|
|
|
|
|
|
<section class="mt-2 grid grid-cols-1 gap-2 xl:grid-cols-2">
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="dashboard-panel">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardSectionHeader title="ترکیب درآمد" :help="copy.charts.incomeMix" />
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="dashboard-chart-wrap">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<apexchart
|
2026-07-01 22:28:09 +03:30
|
|
|
|
v-if="(finance?.fullPriceSood ?? 0) + (finance?.fullPriceKarmozd ?? 0) + (finance?.GiftsPrise ?? 0) > 0"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
type="donut"
|
|
|
|
|
|
height="220"
|
|
|
|
|
|
:options="financeChartOptions"
|
|
|
|
|
|
:series="financeChartOptions.series"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-else
|
2026-06-21 22:15:17 +03:30
|
|
|
|
class="dashboard-empty flex h-44 items-center justify-center text-xs"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
>
|
|
|
|
|
|
در این بازه داده مالی ثبت نشده
|
|
|
|
|
|
</div>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
</div>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="dashboard-panel">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<div class="flex items-start justify-between gap-2">
|
|
|
|
|
|
<DashboardSectionHeader
|
|
|
|
|
|
class="!mb-0 min-w-0 flex-1"
|
|
|
|
|
|
title="حجم خرید و فروش"
|
|
|
|
|
|
:help="copy.charts.buySellVolume"
|
|
|
|
|
|
/>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<a-radio-group
|
2026-06-21 20:27:13 +03:30
|
|
|
|
v-model:value="flowRange"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
button-style="solid"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
size="small"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
class="shrink-0"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-radio-button value="week">۷ روز</a-radio-button>
|
|
|
|
|
|
<a-radio-button value="month">۳۰ روز</a-radio-button>
|
|
|
|
|
|
</a-radio-group>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
<a-spin :spinning="flowLoading">
|
|
|
|
|
|
<apexchart
|
|
|
|
|
|
v-if="flowData.length"
|
|
|
|
|
|
type="bar"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
:height="flowChartHeight"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
:options="flowChartOptions"
|
|
|
|
|
|
:series="flowChartOptions.series"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-else
|
2026-06-21 22:15:17 +03:30
|
|
|
|
class="dashboard-empty flex h-44 items-center justify-center text-xs"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
>
|
|
|
|
|
|
دادهای برای نمودار نیست
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-spin>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Price chart -->
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<section class="dashboard-panel mt-2">
|
|
|
|
|
|
<div class="mb-3 flex flex-wrap items-start justify-between gap-2">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardSectionHeader
|
|
|
|
|
|
class="!mb-0 min-w-0 flex-1"
|
|
|
|
|
|
title="نمودار مظنه"
|
|
|
|
|
|
:help="copy.charts.priceChart"
|
|
|
|
|
|
/>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<a-radio-group
|
2026-06-21 20:27:13 +03:30
|
|
|
|
v-model:value="priceRange"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
button-style="solid"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
size="small"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
class="dashboard-price-range shrink-0"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-radio-button value="DAILY">24 ساعت اخیر</a-radio-button>
|
|
|
|
|
|
<a-radio-button value="WEEKLY">هفته گذشته</a-radio-button>
|
|
|
|
|
|
<a-radio-button value="MONTHLY">ماه گذشته</a-radio-button>
|
|
|
|
|
|
</a-radio-group>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
<apexchart
|
|
|
|
|
|
v-if="priceSeries.length"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
:key="priceRange"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
type="area"
|
|
|
|
|
|
height="200"
|
|
|
|
|
|
:options="priceChartOptions"
|
|
|
|
|
|
:series="priceChartOptions.series"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-else
|
2026-06-21 22:15:17 +03:30
|
|
|
|
class="flex h-40 items-center justify-center text-xs dashboard-empty"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
>
|
|
|
|
|
|
داده نمودار قیمت در دسترس نیست
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<!-- Orders + side charts -->
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<section class="mt-2 grid grid-cols-1 gap-2 xl:grid-cols-3">
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="flex flex-col gap-2 xl:col-span-1">
|
|
|
|
|
|
<div class="dashboard-panel">
|
|
|
|
|
|
<div class="mb-2 flex items-start justify-between gap-2">
|
|
|
|
|
|
<DashboardSectionHeader
|
|
|
|
|
|
class="!mb-0 min-w-0 flex-1"
|
|
|
|
|
|
title="ساعات شلوغ سفارش"
|
|
|
|
|
|
:help="copy.orders.peakHours"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<a-radio-group
|
|
|
|
|
|
v-model:value="peakHoursRange"
|
|
|
|
|
|
button-style="solid"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
class="shrink-0"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-radio-button :value="7">۷ روز</a-radio-button>
|
|
|
|
|
|
<a-radio-button :value="30">۳۰ روز</a-radio-button>
|
|
|
|
|
|
</a-radio-group>
|
2026-01-26 11:21:13 +03:30
|
|
|
|
</div>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="peakHoursData?.peak_hour != null && peakHoursData.peak_count > 0"
|
|
|
|
|
|
class="mb-3 flex flex-wrap items-center gap-1.5"
|
|
|
|
|
|
>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<span class="dashboard-peak-badge dashboard-peak-badge--primary inline-flex items-center rounded-full px-2.5 py-1 text-[11px] font-semibold">
|
2026-06-21 21:55:54 +03:30
|
|
|
|
شلوغترین: {{ 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"
|
2026-06-21 22:15:17 +03:30
|
|
|
|
class="dashboard-peak-badge dashboard-peak-badge--muted inline-flex items-center rounded-full px-2 py-0.5 text-[10px]"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
>
|
|
|
|
|
|
{{ formatPeakHourLabel(slot.hour) }} · {{ slot.total }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<a-spin :spinning="peakHoursLoading">
|
|
|
|
|
|
<apexchart
|
|
|
|
|
|
v-if="peakHoursData?.total_orders"
|
|
|
|
|
|
type="bar"
|
|
|
|
|
|
:height="peakHoursChartHeight"
|
|
|
|
|
|
:options="peakHoursChartOptions"
|
|
|
|
|
|
:series="peakHoursChartOptions.series"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-else
|
2026-06-21 22:15:17 +03:30
|
|
|
|
class="dashboard-empty flex h-44 items-center justify-center text-xs"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
>
|
|
|
|
|
|
در این بازه سفارشی ثبت نشده
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-spin>
|
2026-01-26 11:21:13 +03:30
|
|
|
|
</div>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
|
|
|
|
|
|
<div class="dashboard-panel">
|
|
|
|
|
|
<div class="mb-3 flex flex-wrap items-start justify-between gap-2">
|
|
|
|
|
|
<DashboardSectionHeader
|
|
|
|
|
|
class="!mb-0 min-w-0 flex-1"
|
|
|
|
|
|
title="فعالیت محصولات"
|
|
|
|
|
|
:help="copy.charts.productActivity"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<a-radio-group
|
|
|
|
|
|
v-model:value="productActivityRange"
|
|
|
|
|
|
button-style="solid"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
class="dashboard-product-range shrink-0"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-radio-button value="day">روزانه</a-radio-button>
|
|
|
|
|
|
<a-radio-button value="week">هفتگی</a-radio-button>
|
|
|
|
|
|
<a-radio-button value="month">ماهانه</a-radio-button>
|
|
|
|
|
|
<a-radio-button value="year">سالانه</a-radio-button>
|
|
|
|
|
|
</a-radio-group>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<a-spin :spinning="productActivityLoading">
|
|
|
|
|
|
<div v-if="productReportItems.length" class="dashboard-product-chart min-w-0">
|
|
|
|
|
|
<apexchart
|
|
|
|
|
|
:key="`${productActivityRange}-${productChartHeight}-${productChartLabelWidth}`"
|
|
|
|
|
|
type="bar"
|
|
|
|
|
|
:height="productChartHeight"
|
|
|
|
|
|
:options="productChartOptions"
|
|
|
|
|
|
:series="productChartOptions.series"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-else
|
2026-06-21 22:15:17 +03:30
|
|
|
|
class="dashboard-empty flex h-44 items-center justify-center text-xs"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
>
|
|
|
|
|
|
در این بازه معاملهای برای محصولات ثبت نشده
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-spin>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-01-26 11:21:13 +03:30
|
|
|
|
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="dashboard-panel xl:col-span-2">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<div class="mb-2 flex items-start justify-between gap-2">
|
|
|
|
|
|
<DashboardSectionHeader
|
|
|
|
|
|
class="!mb-0 min-w-0 flex-1"
|
|
|
|
|
|
title="آخرین سفارشات"
|
|
|
|
|
|
:help="copy.orders.recent"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<router-link :to="{ name: 'ordersMain' }">
|
|
|
|
|
|
<a-button type="link" class="!px-0">همه سفارشات</a-button>
|
|
|
|
|
|
</router-link>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="overflow-x-auto">
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<table class="dashboard-table w-full min-w-[52rem] text-sm">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<thead>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<tr class="border-b text-xs">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<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>
|
|
|
|
|
|
<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>
|
2026-07-01 22:28:09 +03:30
|
|
|
|
<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>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<th class="px-2 py-2 text-right">وضعیت</th>
|
|
|
|
|
|
<th class="px-2 py-2 text-right">تاریخ</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
<tr
|
|
|
|
|
|
v-for="order in recentOrders"
|
|
|
|
|
|
:key="order.id"
|
2026-06-21 22:15:17 +03:30
|
|
|
|
class="border-b hover:bg-[var(--admin-bg-hover)]"
|
2026-01-26 11:21:13 +03:30
|
|
|
|
>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<td class="px-2 py-2.5 font-medium">#{{ order.id }}</td>
|
|
|
|
|
|
<td class="px-2 py-2.5">
|
|
|
|
|
|
<span class="rounded-md px-2 py-0.5 text-xs" :class="directionClass(order.direction)">
|
|
|
|
|
|
{{ directionLabel(order.direction) }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<td class="max-w-[8rem] truncate px-2 py-2.5">{{ order.customer?.name ?? '—' }}</td>
|
|
|
|
|
|
<td class="px-2 py-2.5">{{ formatGram(order.amount) }}</td>
|
2026-07-01 22:28:09 +03:30
|
|
|
|
<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>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<td class="dashboard-profit px-2 py-2.5">
|
2026-07-01 22:28:09 +03:30
|
|
|
|
{{ usePrice(order.fee ?? 0, true, 'ریال') }}
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</td>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<td class="dashboard-profit px-2 py-2.5 font-semibold">
|
2026-07-01 22:28:09 +03:30
|
|
|
|
{{ usePrice(order.total_fee ?? 0, true, 'ریال') }}
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<td class="px-2 py-2.5">
|
|
|
|
|
|
{{ usePrice(order.service_charge_price ?? 0, true, 'ریال') }}
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</td>
|
|
|
|
|
|
<td class="px-2 py-2.5">
|
|
|
|
|
|
<span class="rounded-md px-2 py-0.5 text-xs" :class="stsClass(order.sts)">
|
|
|
|
|
|
{{ stsLabel(order) }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</td>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<td class="dashboard-text-muted whitespace-nowrap px-2 py-2.5 text-xs">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
{{ order.created_at ? toJalali(order.created_at) : '—' }}
|
|
|
|
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
2026-01-26 11:21:13 +03:30
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<!-- Bottom row -->
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<section class="mt-2 grid grid-cols-1 gap-2 xl:grid-cols-2">
|
|
|
|
|
|
<div class="dashboard-panel">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardSectionHeader title="مشتریان" :help="copy.customers" />
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="grid grid-cols-2 gap-2.5 md:grid-cols-4">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<div
|
|
|
|
|
|
v-for="item in customerMetricItems"
|
|
|
|
|
|
:key="item.label"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
class="dashboard-metric-cell"
|
2026-06-21 22:15:17 +03:30
|
|
|
|
:class="`dashboard-metric-cell--${item.variant}`"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
>
|
|
|
|
|
|
<DashboardLabelWithHelp
|
|
|
|
|
|
:label="item.label"
|
|
|
|
|
|
:help="item.help"
|
|
|
|
|
|
size="xs"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
text-class="text-[11px]"
|
2026-06-21 22:15:17 +03:30
|
|
|
|
label-class="dashboard-text-muted"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
root-class="dashboard-metric-label"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
/>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<p class="dashboard-metric-value">{{ item.value }}</p>
|
2026-01-26 11:21:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="dashboard-panel">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<DashboardSectionHeader title="موجودی کیف پولها" :help="copy.wallet" />
|
2026-06-21 21:55:54 +03:30
|
|
|
|
<div class="grid grid-cols-1 gap-2.5 sm:grid-cols-3">
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<div
|
|
|
|
|
|
v-for="item in walletMetricItems"
|
|
|
|
|
|
:key="item.label"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
class="dashboard-metric-cell"
|
2026-06-21 22:15:17 +03:30
|
|
|
|
:class="`dashboard-metric-cell--${item.variant}`"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
>
|
|
|
|
|
|
<DashboardLabelWithHelp
|
|
|
|
|
|
:label="item.label"
|
|
|
|
|
|
:help="item.help"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
size="xs"
|
|
|
|
|
|
text-class="text-[11px]"
|
2026-06-21 22:15:17 +03:30
|
|
|
|
label-class="dashboard-text-muted"
|
2026-06-21 21:55:54 +03:30
|
|
|
|
root-class="dashboard-metric-label"
|
2026-06-21 20:27:13 +03:30
|
|
|
|
/>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
<p class="dashboard-metric-value">{{ item.value }}</p>
|
2026-06-21 20:27:13 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
2026-01-24 17:45:54 +03:30
|
|
|
|
</a-spin>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-06-21 21:55:54 +03:30
|
|
|
|
import { computed, ref } from 'vue'
|
2026-06-21 20:27:13 +03:30
|
|
|
|
import DashboardLabelWithHelp from '@/pages/dashboard/components/DashboardLabelWithHelp.vue'
|
2026-06-21 21:55:54 +03:30
|
|
|
|
import DashboardQuickActionsBar from '@/pages/dashboard/components/DashboardQuickActionsBar.vue'
|
|
|
|
|
|
import DashboardQuickWalletModal from '@/pages/dashboard/components/DashboardQuickWalletModal.vue'
|
2026-06-21 20:27:13 +03:30
|
|
|
|
import DashboardSectionHeader from '@/pages/dashboard/components/DashboardSectionHeader.vue'
|
|
|
|
|
|
import DashboardStatCard from '@/pages/dashboard/components/DashboardStatCard.vue'
|
2026-07-01 22:28:09 +03:30
|
|
|
|
import DashboardTradingIncomeSummary from '@/pages/dashboard/components/DashboardTradingIncomeSummary.vue'
|
2026-06-21 20:27:13 +03:30
|
|
|
|
import {
|
|
|
|
|
|
dashboardCharts,
|
|
|
|
|
|
dashboardCustomerMetrics,
|
|
|
|
|
|
dashboardCustomers,
|
|
|
|
|
|
dashboardDateMetrics,
|
|
|
|
|
|
dashboardDateRange,
|
|
|
|
|
|
dashboardGateway,
|
|
|
|
|
|
dashboardHero,
|
|
|
|
|
|
dashboardKpi,
|
|
|
|
|
|
dashboardOrders,
|
|
|
|
|
|
dashboardWallet,
|
|
|
|
|
|
dashboardWalletMetrics,
|
|
|
|
|
|
} from '@/pages/dashboard/dashboardSectionCopy'
|
2026-07-01 22:28:09 +03:30
|
|
|
|
import { DASHBOARD_RIAL_UNIT, formatDashboardAmount } from '@/pages/dashboard/dashboardFormat'
|
2026-06-21 20:27:13 +03:30
|
|
|
|
import { useDashboardPage } from '@/pages/dashboard/composables/useDashboardPage'
|
2026-06-21 21:55:54 +03:30
|
|
|
|
import { useDashboardQuickActions } from '@/pages/dashboard/composables/useDashboardQuickActions'
|
2026-06-23 22:31:07 +03:30
|
|
|
|
import { metalBalanceTitle, metalLabel } from '@/utils/adminMetalLabels'
|
2026-05-31 11:51:52 +03:30
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
const copy = {
|
|
|
|
|
|
hero: dashboardHero,
|
|
|
|
|
|
gateway: dashboardGateway,
|
|
|
|
|
|
kpi: dashboardKpi,
|
|
|
|
|
|
dateRange: dashboardDateRange,
|
|
|
|
|
|
charts: dashboardCharts,
|
|
|
|
|
|
orders: dashboardOrders,
|
|
|
|
|
|
customers: dashboardCustomers,
|
|
|
|
|
|
wallet: dashboardWallet,
|
2026-01-24 17:45:54 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
const {
|
|
|
|
|
|
loading,
|
|
|
|
|
|
flowLoading,
|
|
|
|
|
|
startDate,
|
|
|
|
|
|
endDate,
|
|
|
|
|
|
master,
|
|
|
|
|
|
finance,
|
|
|
|
|
|
balance,
|
2026-06-23 22:31:07 +03:30
|
|
|
|
metalBalanceItems,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
walletSums,
|
|
|
|
|
|
recentOrders,
|
2026-06-21 21:55:54 +03:30
|
|
|
|
peakHoursRange,
|
|
|
|
|
|
peakHoursData,
|
|
|
|
|
|
peakHoursLoading,
|
|
|
|
|
|
topPeakHours,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
priceRange,
|
|
|
|
|
|
flowRange,
|
|
|
|
|
|
flowData,
|
|
|
|
|
|
priceSeries,
|
2026-06-21 21:55:54 +03:30
|
|
|
|
productActivityRange,
|
|
|
|
|
|
productActivityLoading,
|
|
|
|
|
|
productReportItems,
|
|
|
|
|
|
productChartHeight,
|
|
|
|
|
|
productChartLabelWidth,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
refreshAll,
|
|
|
|
|
|
applyDateRange,
|
|
|
|
|
|
loadFlow,
|
2026-06-21 21:55:54 +03:30
|
|
|
|
loadProductActivity,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
formatGram,
|
|
|
|
|
|
directionLabel,
|
|
|
|
|
|
directionClass,
|
|
|
|
|
|
stsClass,
|
|
|
|
|
|
stsLabel,
|
|
|
|
|
|
financeChartOptions,
|
|
|
|
|
|
flowChartOptions,
|
2026-06-21 21:55:54 +03:30
|
|
|
|
flowChartHeight,
|
|
|
|
|
|
peakHoursChartOptions,
|
|
|
|
|
|
peakHoursChartHeight,
|
|
|
|
|
|
formatPeakHourLabel,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
priceChartOptions,
|
|
|
|
|
|
productChartOptions,
|
|
|
|
|
|
usePrice,
|
|
|
|
|
|
toJalali,
|
2026-06-21 21:55:54 +03:30
|
|
|
|
customerStats,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
} = useDashboardPage()
|
2026-01-24 17:45:54 +03:30
|
|
|
|
|
2026-07-01 22:28:09 +03:30
|
|
|
|
const tradingProfitTotal = computed(() => {
|
|
|
|
|
|
const spread = Number(finance.value?.fullPriceSood ?? 0)
|
|
|
|
|
|
const commission = Number(finance.value?.fullPriceKarmozd ?? finance.value?.fullPriceKaermozd ?? 0)
|
|
|
|
|
|
return Number(finance.value?.totalTradingProfit ?? spread + commission)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-06-21 21:55:54 +03:30
|
|
|
|
const {
|
|
|
|
|
|
quickActionLoading,
|
|
|
|
|
|
hasProductSnapshot,
|
|
|
|
|
|
productSnapshotCount,
|
|
|
|
|
|
loadSnapshotStatus,
|
|
|
|
|
|
deactivateAll,
|
|
|
|
|
|
restoreProducts,
|
|
|
|
|
|
closeAllBuy,
|
|
|
|
|
|
closeAllSell,
|
|
|
|
|
|
syncShow,
|
|
|
|
|
|
syncPrices,
|
|
|
|
|
|
} = useDashboardQuickActions(refreshAll)
|
|
|
|
|
|
|
|
|
|
|
|
const showQuickWallet = ref(false)
|
|
|
|
|
|
|
|
|
|
|
|
void loadSnapshotStatus()
|
|
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
const dateRangeMetrics = computed(() => [
|
2026-01-24 17:45:54 +03:30
|
|
|
|
{
|
2026-06-21 20:27:13 +03:30
|
|
|
|
label: 'واریز بانکی',
|
2026-07-01 22:28:09 +03:30
|
|
|
|
value: `${formatDashboardAmount(balance.value?.income_money)} ${DASHBOARD_RIAL_UNIT}`,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
help: dashboardDateMetrics.bankDeposit,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-07-01 22:28:09 +03:30
|
|
|
|
label: 'جمع سود معاملات',
|
|
|
|
|
|
value: `${formatDashboardAmount(tradingProfitTotal.value)} ${DASHBOARD_RIAL_UNIT}`,
|
|
|
|
|
|
help: dashboardDateMetrics.totalTradingProfit,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: 'تراز قیمت−پرداخت (پس از هدیه)',
|
|
|
|
|
|
value: `${formatDashboardAmount(finance.value?.sumAll)} ${DASHBOARD_RIAL_UNIT}`,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
help: dashboardDateMetrics.netIncome,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-07-01 22:28:09 +03:30
|
|
|
|
label: 'هدایا (گرم)',
|
2026-06-21 20:27:13 +03:30
|
|
|
|
value: `${finance.value?.Gifts ?? '0'} گرم`,
|
|
|
|
|
|
help: dashboardDateMetrics.gifts,
|
|
|
|
|
|
},
|
|
|
|
|
|
])
|
2026-01-24 17:45:54 +03:30
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
const customerMetricItems = computed(() => [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: 'کل مشتریان',
|
|
|
|
|
|
value: customerStats.value.total,
|
|
|
|
|
|
help: dashboardCustomerMetrics.total,
|
2026-06-21 22:15:17 +03:30
|
|
|
|
variant: 'default',
|
2026-01-24 17:45:54 +03:30
|
|
|
|
},
|
2026-06-21 20:27:13 +03:30
|
|
|
|
{
|
|
|
|
|
|
label: 'جدید (۳ ماه)',
|
|
|
|
|
|
value: customerStats.value.newCount,
|
|
|
|
|
|
help: dashboardCustomerMetrics.new,
|
2026-06-21 22:15:17 +03:30
|
|
|
|
variant: 'default',
|
2026-01-24 17:45:54 +03:30
|
|
|
|
},
|
2026-06-21 20:27:13 +03:30
|
|
|
|
{
|
|
|
|
|
|
label: 'فعال',
|
|
|
|
|
|
value: customerStats.value.active,
|
|
|
|
|
|
help: dashboardCustomerMetrics.active,
|
2026-06-21 22:15:17 +03:30
|
|
|
|
variant: 'success',
|
2026-01-24 17:45:54 +03:30
|
|
|
|
},
|
2026-06-21 20:27:13 +03:30
|
|
|
|
{
|
|
|
|
|
|
label: 'بدون احراز',
|
|
|
|
|
|
value: customerStats.value.notVerified,
|
|
|
|
|
|
help: dashboardCustomerMetrics.notVerified,
|
2026-06-21 22:15:17 +03:30
|
|
|
|
variant: 'danger',
|
2026-01-24 17:45:54 +03:30
|
|
|
|
},
|
2026-06-21 20:27:13 +03:30
|
|
|
|
])
|
2026-01-24 17:45:54 +03:30
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
const walletMetricItems = computed(() => [
|
|
|
|
|
|
{
|
2026-06-23 22:31:07 +03:30
|
|
|
|
label: metalLabel.customersGold(),
|
2026-06-21 20:27:13 +03:30
|
|
|
|
value: formatGram(walletSums.value?.gold),
|
|
|
|
|
|
help: dashboardWalletMetrics.gold,
|
2026-06-21 22:15:17 +03:30
|
|
|
|
variant: 'amber',
|
2026-01-24 17:45:54 +03:30
|
|
|
|
},
|
2026-06-21 20:27:13 +03:30
|
|
|
|
{
|
|
|
|
|
|
label: 'ریال مشتریان',
|
2026-07-01 22:28:09 +03:30
|
|
|
|
value: `${formatDashboardAmount(walletSums.value?.cash)} ${DASHBOARD_RIAL_UNIT}`,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
help: dashboardWalletMetrics.cash,
|
2026-06-21 22:15:17 +03:30
|
|
|
|
variant: 'sky',
|
2026-01-24 17:45:54 +03:30
|
|
|
|
},
|
2026-06-21 20:27:13 +03:30
|
|
|
|
{
|
2026-06-23 22:31:07 +03:30
|
|
|
|
label: metalLabel.goldValueInRial(),
|
2026-07-01 22:28:09 +03:30
|
|
|
|
value: `${formatDashboardAmount(walletSums.value?.goldToCash)} ${DASHBOARD_RIAL_UNIT}`,
|
2026-06-21 20:27:13 +03:30
|
|
|
|
help: dashboardWalletMetrics.goldToCash,
|
2026-06-21 22:15:17 +03:30
|
|
|
|
variant: 'violet',
|
2026-01-24 17:45:54 +03:30
|
|
|
|
},
|
2026-06-21 20:27:13 +03:30
|
|
|
|
])
|
2026-01-24 17:45:54 +03:30
|
|
|
|
</script>
|
|
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
<style scoped>
|
2026-06-21 21:55:54 +03:30
|
|
|
|
.dashboard-panel {
|
2026-06-21 22:15:17 +03:30
|
|
|
|
border-radius: 0.75rem;
|
|
|
|
|
|
border: 1px solid var(--admin-border);
|
|
|
|
|
|
background: var(--admin-bg-elevated);
|
|
|
|
|
|
color: var(--admin-text);
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-01 22:28:09 +03:30
|
|
|
|
.dashboard-metrics-row {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 1024px) {
|
|
|
|
|
|
.dashboard-metrics-row {
|
|
|
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
|
.dashboard-metrics-row {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 22:15:17 +03:30
|
|
|
|
.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);
|
2026-07-01 22:28:09 +03:30
|
|
|
|
min-height: 3.75rem;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
justify-content: space-between;
|
2026-06-21 22:15:17 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-profit {
|
|
|
|
|
|
color: #059669;
|
2026-06-21 21:55:54 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-metric-cell {
|
2026-06-21 22:15:17 +03:30
|
|
|
|
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;
|
2026-06-21 21:55:54 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-metric-value {
|
|
|
|
|
|
@apply mt-2 text-base font-bold leading-snug break-words;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-v2 :deep(.dashboard-metric-label) {
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-v2 :deep(.dashboard-metric-label > span:first-child) {
|
|
|
|
|
|
overflow: visible;
|
|
|
|
|
|
text-overflow: unset;
|
|
|
|
|
|
white-space: normal;
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-chart-wrap {
|
|
|
|
|
|
@apply px-1 pb-1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-v2 :deep(.apexcharts-legend) {
|
|
|
|
|
|
padding-inline: 12px !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-v2 :deep(.apexcharts-legend-series) {
|
|
|
|
|
|
margin-inline: 8px !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
.dashboard-v2 :deep(.apexcharts-tooltip) {
|
|
|
|
|
|
direction: rtl;
|
2026-01-24 17:45:54 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 21:55:54 +03:30
|
|
|
|
.dashboard-v2 :deep(.dashboard-section-header) {
|
|
|
|
|
|
overflow: visible;
|
|
|
|
|
|
padding-bottom: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-v2 :deep(.dashboard-section-title) {
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-v2 :deep(.dashboard-section-title > span:first-child) {
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
overflow: visible;
|
|
|
|
|
|
padding-bottom: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 20:27:13 +03:30
|
|
|
|
.dashboard-v2 :deep(.dashboard-label-with-help .ant-tooltip-disabled-compatible-wrapper),
|
|
|
|
|
|
.dashboard-v2 :deep(.dashboard-label-with-help .dashboard-help-trigger) {
|
|
|
|
|
|
display: inline-flex !important;
|
|
|
|
|
|
align-items: center !important;
|
2026-06-21 21:55:54 +03:30
|
|
|
|
line-height: 1 !important;
|
|
|
|
|
|
vertical-align: baseline !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-product-chart {
|
|
|
|
|
|
@apply min-w-0 px-0.5 md:px-1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-product-chart :deep(.apexcharts-yaxis-texts-g text) {
|
|
|
|
|
|
text-anchor: start !important;
|
|
|
|
|
|
direction: rtl;
|
|
|
|
|
|
unicode-bidi: plaintext;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dashboard-product-chart :deep(.apexcharts-yaxis) {
|
|
|
|
|
|
transform: translateX(-2px);
|
2026-01-24 17:45:54 +03:30
|
|
|
|
}
|
|
|
|
|
|
</style>
|
2026-06-21 22:15:17 +03:30
|
|
|
|
|
|
|
|
|
|
<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>
|