feat: add new permissions and update role assignments in Permission and Role enums; enhance dashboard and analysis components with conditional rendering based on permissions
This commit is contained in:
parent
ad9ee3a99b
commit
c378036691
@ -9,7 +9,30 @@ enum Permission: string
|
||||
use ProvidesEnumOptions;
|
||||
|
||||
case DASHBOARD_VIEW = 'dashboard.view';
|
||||
case DASHBOARD_ATTENDANCE = 'dashboard.attendance';
|
||||
case DASHBOARD_CASH = 'dashboard.cash';
|
||||
case DASHBOARD_REVENUE = 'dashboard.revenue';
|
||||
case DASHBOARD_EXPENSE = 'dashboard.expense';
|
||||
case DASHBOARD_ORDERS_CHANNEL = 'dashboard.orders_channel';
|
||||
case DASHBOARD_ORDERS_PAYMENT = 'dashboard.orders_payment';
|
||||
case DASHBOARD_ORDERS_MARKETING = 'dashboard.orders_marketing';
|
||||
case DASHBOARD_ORDERS_STATUS = 'dashboard.orders_status';
|
||||
|
||||
case ANALYSIS_VIEW = 'analysis.view';
|
||||
case ANALYSIS_ATTENDANCE = 'analysis.attendance';
|
||||
case ANALYSIS_CASH = 'analysis.cash';
|
||||
case ANALYSIS_RAW_MATERIALS = 'analysis.raw_materials';
|
||||
case ANALYSIS_PRODUCT_STOCK = 'analysis.product_stock';
|
||||
case ANALYSIS_REVENUE = 'analysis.revenue';
|
||||
case ANALYSIS_EXPENSE = 'analysis.expense';
|
||||
case ANALYSIS_BUSY_HOURS = 'analysis.busy_hours';
|
||||
case ANALYSIS_PROFIT_ORDERS = 'analysis.profit_orders';
|
||||
case ANALYSIS_PROFIT_HPP = 'analysis.profit_hpp';
|
||||
case ANALYSIS_PROFIT_GROSS = 'analysis.profit_gross';
|
||||
case ANALYSIS_PROFIT_MARGIN = 'analysis.profit_margin';
|
||||
case ANALYSIS_TOP_SUPPLIERS = 'analysis.top_suppliers';
|
||||
case ANALYSIS_TOP_CUSTOMERS = 'analysis.top_customers';
|
||||
case ANALYSIS_TOP_PRODUCTS = 'analysis.top_products';
|
||||
|
||||
case EMPLOYEES_VIEW = 'employees.view';
|
||||
case EMPLOYEES_CREATE = 'employees.create';
|
||||
@ -118,7 +141,30 @@ public function label(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::DASHBOARD_VIEW => 'Lihat Dashboard',
|
||||
self::DASHBOARD_ATTENDANCE => 'Lihat Kartu Kehadiran',
|
||||
self::DASHBOARD_CASH => 'Lihat Kartu Kas Toko',
|
||||
self::DASHBOARD_REVENUE => 'Lihat Kartu Pendapatan',
|
||||
self::DASHBOARD_EXPENSE => 'Lihat Kartu Pengeluaran',
|
||||
self::DASHBOARD_ORDERS_CHANNEL => 'Lihat Kartu Pesanan per Channel',
|
||||
self::DASHBOARD_ORDERS_PAYMENT => 'Lihat Kartu Pesanan per Pembayaran',
|
||||
self::DASHBOARD_ORDERS_MARKETING => 'Lihat Kartu Pesanan per Marketing',
|
||||
self::DASHBOARD_ORDERS_STATUS => 'Lihat Kartu Pesanan per Status',
|
||||
|
||||
self::ANALYSIS_VIEW => 'Lihat Analisa',
|
||||
self::ANALYSIS_ATTENDANCE => 'Lihat Analisa Kehadiran',
|
||||
self::ANALYSIS_CASH => 'Lihat Analisa Kas Toko',
|
||||
self::ANALYSIS_RAW_MATERIALS => 'Lihat Analisa Bahan Baku',
|
||||
self::ANALYSIS_PRODUCT_STOCK => 'Lihat Analisa Stok Produk',
|
||||
self::ANALYSIS_REVENUE => 'Lihat Analisa Pendapatan',
|
||||
self::ANALYSIS_EXPENSE => 'Lihat Analisa Pengeluaran',
|
||||
self::ANALYSIS_BUSY_HOURS => 'Lihat Analisa Jam Sibuk',
|
||||
self::ANALYSIS_PROFIT_ORDERS => 'Lihat Analisa Total Order',
|
||||
self::ANALYSIS_PROFIT_HPP => 'Lihat Analisa HPP',
|
||||
self::ANALYSIS_PROFIT_GROSS => 'Lihat Analisa Laba Kotor',
|
||||
self::ANALYSIS_PROFIT_MARGIN => 'Lihat Analisa Profit Margin',
|
||||
self::ANALYSIS_TOP_SUPPLIERS => 'Lihat Top 5 Supplier',
|
||||
self::ANALYSIS_TOP_CUSTOMERS => 'Lihat Top 5 Pelanggan',
|
||||
self::ANALYSIS_TOP_PRODUCTS => 'Lihat Top 5 Produk',
|
||||
|
||||
self::EMPLOYEES_VIEW => 'Lihat Pegawai',
|
||||
self::EMPLOYEES_CREATE => 'Tambah Pegawai',
|
||||
@ -228,8 +274,14 @@ public function label(): string
|
||||
public function group(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::DASHBOARD_VIEW => 'Umum',
|
||||
self::ANALYSIS_VIEW => 'Umum',
|
||||
self::DASHBOARD_VIEW, self::DASHBOARD_ATTENDANCE, self::DASHBOARD_CASH,
|
||||
self::DASHBOARD_REVENUE, self::DASHBOARD_EXPENSE, self::DASHBOARD_ORDERS_CHANNEL,
|
||||
self::DASHBOARD_ORDERS_PAYMENT, self::DASHBOARD_ORDERS_MARKETING, self::DASHBOARD_ORDERS_STATUS => 'Umum',
|
||||
self::ANALYSIS_VIEW, self::ANALYSIS_ATTENDANCE, self::ANALYSIS_CASH,
|
||||
self::ANALYSIS_RAW_MATERIALS, self::ANALYSIS_PRODUCT_STOCK, self::ANALYSIS_REVENUE,
|
||||
self::ANALYSIS_EXPENSE, self::ANALYSIS_BUSY_HOURS, self::ANALYSIS_PROFIT_ORDERS,
|
||||
self::ANALYSIS_PROFIT_HPP, self::ANALYSIS_PROFIT_GROSS, self::ANALYSIS_PROFIT_MARGIN,
|
||||
self::ANALYSIS_TOP_SUPPLIERS, self::ANALYSIS_TOP_CUSTOMERS, self::ANALYSIS_TOP_PRODUCTS => 'Umum',
|
||||
self::EMPLOYEES_VIEW, self::EMPLOYEES_CREATE, self::EMPLOYEES_UPDATE,
|
||||
self::EMPLOYEES_DELETE, self::EMPLOYEES_RESET_PASSWORD, self::EMPLOYEES_TOGGLE_STATUS => 'Pegawai',
|
||||
self::ATTENDANCES_VIEW, self::ATTENDANCES_CREATE, self::ATTENDANCES_DELETE,
|
||||
|
||||
@ -51,8 +51,31 @@ public function permissions(): array
|
||||
|
||||
self::DIREKTUR => [
|
||||
Permission::DASHBOARD_VIEW,
|
||||
Permission::DASHBOARD_ATTENDANCE,
|
||||
Permission::DASHBOARD_CASH,
|
||||
Permission::DASHBOARD_REVENUE,
|
||||
Permission::DASHBOARD_EXPENSE,
|
||||
Permission::DASHBOARD_ORDERS_CHANNEL,
|
||||
Permission::DASHBOARD_ORDERS_PAYMENT,
|
||||
Permission::DASHBOARD_ORDERS_MARKETING,
|
||||
Permission::DASHBOARD_ORDERS_STATUS,
|
||||
Permission::ANALYSIS_VIEW,
|
||||
|
||||
Permission::ANALYSIS_ATTENDANCE,
|
||||
Permission::ANALYSIS_CASH,
|
||||
Permission::ANALYSIS_RAW_MATERIALS,
|
||||
Permission::ANALYSIS_PRODUCT_STOCK,
|
||||
Permission::ANALYSIS_REVENUE,
|
||||
Permission::ANALYSIS_EXPENSE,
|
||||
Permission::ANALYSIS_BUSY_HOURS,
|
||||
Permission::ANALYSIS_PROFIT_ORDERS,
|
||||
Permission::ANALYSIS_PROFIT_HPP,
|
||||
Permission::ANALYSIS_PROFIT_GROSS,
|
||||
Permission::ANALYSIS_PROFIT_MARGIN,
|
||||
Permission::ANALYSIS_TOP_SUPPLIERS,
|
||||
Permission::ANALYSIS_TOP_CUSTOMERS,
|
||||
Permission::ANALYSIS_TOP_PRODUCTS,
|
||||
|
||||
Permission::EMPLOYEES_VIEW,
|
||||
|
||||
Permission::STOCKS_VIEW,
|
||||
@ -98,8 +121,31 @@ public function permissions(): array
|
||||
|
||||
self::ADMIN_TOKO => [
|
||||
Permission::DASHBOARD_VIEW,
|
||||
Permission::DASHBOARD_ATTENDANCE,
|
||||
Permission::DASHBOARD_CASH,
|
||||
Permission::DASHBOARD_REVENUE,
|
||||
Permission::DASHBOARD_EXPENSE,
|
||||
Permission::DASHBOARD_ORDERS_CHANNEL,
|
||||
Permission::DASHBOARD_ORDERS_PAYMENT,
|
||||
Permission::DASHBOARD_ORDERS_MARKETING,
|
||||
Permission::DASHBOARD_ORDERS_STATUS,
|
||||
Permission::ANALYSIS_VIEW,
|
||||
|
||||
Permission::ANALYSIS_ATTENDANCE,
|
||||
Permission::ANALYSIS_CASH,
|
||||
Permission::ANALYSIS_RAW_MATERIALS,
|
||||
Permission::ANALYSIS_PRODUCT_STOCK,
|
||||
Permission::ANALYSIS_REVENUE,
|
||||
Permission::ANALYSIS_EXPENSE,
|
||||
Permission::ANALYSIS_BUSY_HOURS,
|
||||
Permission::ANALYSIS_PROFIT_ORDERS,
|
||||
Permission::ANALYSIS_PROFIT_HPP,
|
||||
Permission::ANALYSIS_PROFIT_GROSS,
|
||||
Permission::ANALYSIS_PROFIT_MARGIN,
|
||||
Permission::ANALYSIS_TOP_SUPPLIERS,
|
||||
Permission::ANALYSIS_TOP_CUSTOMERS,
|
||||
Permission::ANALYSIS_TOP_PRODUCTS,
|
||||
|
||||
Permission::STOCKS_VIEW,
|
||||
|
||||
Permission::CUTTINGS_VERIFY,
|
||||
@ -160,6 +206,24 @@ public function permissions(): array
|
||||
|
||||
self::CASHIER => [
|
||||
Permission::DASHBOARD_VIEW,
|
||||
Permission::DASHBOARD_ATTENDANCE,
|
||||
Permission::DASHBOARD_CASH,
|
||||
Permission::DASHBOARD_REVENUE,
|
||||
Permission::DASHBOARD_ORDERS_CHANNEL,
|
||||
Permission::DASHBOARD_ORDERS_PAYMENT,
|
||||
Permission::DASHBOARD_ORDERS_STATUS,
|
||||
|
||||
Permission::ANALYSIS_VIEW,
|
||||
Permission::ANALYSIS_ATTENDANCE,
|
||||
Permission::ANALYSIS_CASH,
|
||||
Permission::ANALYSIS_REVENUE,
|
||||
Permission::ANALYSIS_EXPENSE,
|
||||
Permission::ANALYSIS_PROFIT_ORDERS,
|
||||
Permission::ANALYSIS_PROFIT_HPP,
|
||||
Permission::ANALYSIS_PROFIT_GROSS,
|
||||
Permission::ANALYSIS_PROFIT_MARGIN,
|
||||
Permission::ANALYSIS_TOP_CUSTOMERS,
|
||||
Permission::ANALYSIS_TOP_PRODUCTS,
|
||||
|
||||
Permission::ATTENDANCES_VIEW,
|
||||
Permission::ATTENDANCES_CREATE,
|
||||
@ -197,6 +261,12 @@ public function permissions(): array
|
||||
|
||||
self::ADMIN_BAHAN_BAKU => [
|
||||
Permission::DASHBOARD_VIEW,
|
||||
Permission::DASHBOARD_ATTENDANCE,
|
||||
|
||||
Permission::ANALYSIS_VIEW,
|
||||
Permission::ANALYSIS_ATTENDANCE,
|
||||
Permission::ANALYSIS_RAW_MATERIALS,
|
||||
Permission::ANALYSIS_TOP_SUPPLIERS,
|
||||
|
||||
Permission::ATTENDANCES_VIEW,
|
||||
Permission::ATTENDANCES_CREATE,
|
||||
@ -242,6 +312,22 @@ public function permissions(): array
|
||||
|
||||
self::MARKETING => [
|
||||
Permission::DASHBOARD_VIEW,
|
||||
Permission::DASHBOARD_ATTENDANCE,
|
||||
Permission::DASHBOARD_REVENUE,
|
||||
Permission::DASHBOARD_ORDERS_CHANNEL,
|
||||
Permission::DASHBOARD_ORDERS_PAYMENT,
|
||||
Permission::DASHBOARD_ORDERS_MARKETING,
|
||||
Permission::DASHBOARD_ORDERS_STATUS,
|
||||
|
||||
Permission::ANALYSIS_VIEW,
|
||||
Permission::ANALYSIS_ATTENDANCE,
|
||||
Permission::ANALYSIS_REVENUE,
|
||||
Permission::ANALYSIS_PROFIT_ORDERS,
|
||||
Permission::ANALYSIS_PROFIT_HPP,
|
||||
Permission::ANALYSIS_PROFIT_GROSS,
|
||||
Permission::ANALYSIS_PROFIT_MARGIN,
|
||||
Permission::ANALYSIS_TOP_CUSTOMERS,
|
||||
Permission::ANALYSIS_TOP_PRODUCTS,
|
||||
|
||||
Permission::ATTENDANCES_VIEW,
|
||||
Permission::ATTENDANCES_CREATE,
|
||||
@ -268,8 +354,10 @@ public function permissions(): array
|
||||
|
||||
self::NON_OPERATOR => [
|
||||
Permission::DASHBOARD_VIEW,
|
||||
Permission::DASHBOARD_ATTENDANCE,
|
||||
|
||||
Permission::DASHBOARD_VIEW,
|
||||
Permission::ANALYSIS_VIEW,
|
||||
Permission::ANALYSIS_ATTENDANCE,
|
||||
|
||||
Permission::ATTENDANCES_VIEW,
|
||||
Permission::ATTENDANCES_CREATE,
|
||||
|
||||
@ -16,10 +16,13 @@ import type { ChartConfig } from '@/components/ui/chart';
|
||||
import { ChartContainer } from '@/components/ui/chart';
|
||||
import { DatePicker } from '@/components/ui/date-picker';
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { useCan } from '@/composables/useCan';
|
||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||
import { formatRupiah } from '@/lib/rupiah';
|
||||
import admin from '@/routes/admin';
|
||||
|
||||
const { can } = useCan();
|
||||
|
||||
const props = defineProps<{
|
||||
filters: {
|
||||
start_date?: string;
|
||||
@ -351,7 +354,7 @@ watch([startDate, endDate], () => {
|
||||
|
||||
<!-- Kehadiran & Kas Toko -->
|
||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<StatCard title="Kehadiran" :icon="UserCheck" main-label="Total Karyawan"
|
||||
<StatCard v-if="can('analysis.attendance')" title="Kehadiran" :icon="UserCheck" main-label="Total Karyawan"
|
||||
:main-value="attendance.total_employees" :sub-label="attendance.percentage + '% hadir'" :items="[
|
||||
{
|
||||
label: 'Hadir',
|
||||
@ -367,7 +370,7 @@ watch([startDate, endDate], () => {
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard title="Kas Toko" :icon="Banknote" main-label="Total Saldo"
|
||||
<StatCard v-if="can('analysis.cash')" title="Kas Toko" :icon="Banknote" main-label="Total Saldo"
|
||||
:main-value="'Rp' + formatRupiah(cashOverview.total_balance)" :sub-label="cashOverview.total_transactions + ' transaksi'
|
||||
" :items="[
|
||||
{
|
||||
@ -380,7 +383,7 @@ watch([startDate, endDate], () => {
|
||||
},
|
||||
]" :cols="2" />
|
||||
|
||||
<StatCard title="Bahan Baku" :icon="Package" main-label="Total Stok"
|
||||
<StatCard v-if="can('analysis.raw_materials')" title="Bahan Baku" :icon="Package" main-label="Total Stok"
|
||||
:main-value="rawMaterialStock.total_stock.toLocaleString('id-ID')"
|
||||
:sub-label="'Rp' + formatRupiah(rawMaterialStock.total_value)" :items="[
|
||||
{
|
||||
@ -397,7 +400,7 @@ watch([startDate, endDate], () => {
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard title="Stok Produk" :icon="ShoppingCart" main-label="Total Stok"
|
||||
<StatCard v-if="can('analysis.product_stock')" title="Stok Produk" :icon="ShoppingCart" main-label="Total Stok"
|
||||
:main-value="productStock.total_stock.toLocaleString('id-ID')"
|
||||
:sub-label="'Rp' + formatRupiah(productStock.total_value) + (productStock.total_reject > 0 ? ' (' + productStock.total_reject + ' reject)' : '')"
|
||||
:items="[
|
||||
@ -417,7 +420,7 @@ watch([startDate, endDate], () => {
|
||||
</div>
|
||||
|
||||
<!-- Revenue Chart -->
|
||||
<Card class="py-4 sm:py-0">
|
||||
<Card v-if="can('analysis.revenue')" class="py-4 sm:py-0">
|
||||
<CardHeader class="flex flex-col items-stretch border-b p-0! sm:flex-row">
|
||||
<div class="flex flex-1 flex-col justify-center gap-1 px-6 py-5 sm:py-6">
|
||||
<CardTitle>Pendapatan</CardTitle>
|
||||
@ -459,7 +462,7 @@ watch([startDate, endDate], () => {
|
||||
</Card>
|
||||
|
||||
<!-- Expense Chart -->
|
||||
<Card class="py-4 sm:py-0">
|
||||
<Card v-if="can('analysis.expense')" class="py-4 sm:py-0">
|
||||
<CardHeader class="flex flex-col items-stretch border-b p-0! sm:flex-row">
|
||||
<div class="flex flex-1 flex-col justify-center gap-1 px-6 py-5 sm:py-6">
|
||||
<CardTitle>Pengeluaran</CardTitle>
|
||||
@ -501,7 +504,7 @@ watch([startDate, endDate], () => {
|
||||
</Card>
|
||||
|
||||
<!-- Busy Hours Chart -->
|
||||
<Card>
|
||||
<Card v-if="can('analysis.busy_hours')">
|
||||
<CardHeader>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
@ -537,7 +540,7 @@ watch([startDate, endDate], () => {
|
||||
|
||||
<!-- Profit Metrics Cards -->
|
||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<StatCard title="Total Order" :icon="ShoppingCart" main-label="Pesanan Selesai"
|
||||
<StatCard v-if="can('analysis.profit_orders')" title="Total Order" :icon="ShoppingCart" main-label="Pesanan Selesai"
|
||||
:main-value="profitMetrics.total_orders.toLocaleString('id-ID')"
|
||||
:sub-label="'AOV: Rp' + formatRupiah(profitMetrics.aov)" :items="[
|
||||
{
|
||||
@ -550,7 +553,7 @@ watch([startDate, endDate], () => {
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard title="HPP" :icon="TrendingDown" main-label="Harga Pokok"
|
||||
<StatCard v-if="can('analysis.profit_hpp')" title="HPP" :icon="TrendingDown" main-label="Harga Pokok"
|
||||
:main-value="'Rp' + formatRupiah(profitMetrics.hpp)" sub-label="Total biaya produksi" :items="[
|
||||
{
|
||||
label: 'Laba Kotor',
|
||||
@ -562,7 +565,7 @@ watch([startDate, endDate], () => {
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard title="Laba Kotor" :icon="TrendingUp" main-label="Gross Profit"
|
||||
<StatCard v-if="can('analysis.profit_gross')" title="Laba Kotor" :icon="TrendingUp" main-label="Gross Profit"
|
||||
:main-value="'Rp' + formatRupiah(profitMetrics.laba_kotor)"
|
||||
:sub-label="profitMetrics.laba_kotor >= 0 ? 'Positif' : 'Negatif'" :items="[
|
||||
{
|
||||
@ -575,7 +578,7 @@ watch([startDate, endDate], () => {
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard title="Profit Margin" :icon="Percent" main-label="Margin"
|
||||
<StatCard v-if="can('analysis.profit_margin')" title="Profit Margin" :icon="Percent" main-label="Margin"
|
||||
:main-value="profitMetrics.profit_margin + '%'"
|
||||
:sub-label="'Laba Bersih: Rp' + formatRupiah(profitMetrics.laba_bersih)" :items="[
|
||||
{
|
||||
@ -591,7 +594,7 @@ watch([startDate, endDate], () => {
|
||||
|
||||
<!-- Top 5 Charts -->
|
||||
<div class="grid gap-4 md:grid-cols-3">
|
||||
<Card>
|
||||
<Card v-if="can('analysis.top_suppliers')">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">Top 5 Supplier</CardTitle>
|
||||
<CardDescription>Berdasarkan total harga pembelian</CardDescription>
|
||||
@ -617,7 +620,7 @@ watch([startDate, endDate], () => {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Card v-if="can('analysis.top_customers')">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">Top 5 Pelanggan</CardTitle>
|
||||
<CardDescription>Berdasarkan total nilai pesanan</CardDescription>
|
||||
@ -643,7 +646,7 @@ watch([startDate, endDate], () => {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Card v-if="can('analysis.top_products')">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">Top 5 Produk</CardTitle>
|
||||
<CardDescription>Berdasarkan jumlah terjual</CardDescription>
|
||||
|
||||
@ -10,8 +10,7 @@ import {
|
||||
TrendingUp,
|
||||
UserCheck,
|
||||
} from '@lucide/vue';
|
||||
import { Donut } from '@unovis/ts';
|
||||
import { VisAxis, VisDonut, VisGroupedBar, VisSingleContainer, VisXYContainer } from '@unovis/vue';
|
||||
import { VisDonut, VisSingleContainer } from '@unovis/vue';
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||
import StatCard from '@/components/card/StatCard.vue';
|
||||
import {
|
||||
@ -22,6 +21,7 @@ import {
|
||||
} from '@/components/ui/card';
|
||||
import type { ChartConfig } from '@/components/ui/chart';
|
||||
import { ChartContainer } from '@/components/ui/chart';
|
||||
import { useCan } from '@/composables/useCan';
|
||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||
import { formatRupiah } from '@/lib/rupiah';
|
||||
|
||||
@ -83,6 +83,8 @@ interface DashboardProps {
|
||||
|
||||
const props = defineProps<DashboardProps>();
|
||||
|
||||
const { can } = useCan();
|
||||
|
||||
const currentTime = ref(new Date());
|
||||
let timer: ReturnType<typeof setInterval>;
|
||||
|
||||
@ -142,6 +144,7 @@ const channelChartConfig = computed(() => {
|
||||
color: channelColors[index % channelColors.length],
|
||||
};
|
||||
});
|
||||
|
||||
return config;
|
||||
});
|
||||
|
||||
@ -154,6 +157,7 @@ const paymentChartConfig = computed(() => {
|
||||
color: paymentColors[index % paymentColors.length],
|
||||
};
|
||||
});
|
||||
|
||||
return config;
|
||||
});
|
||||
|
||||
@ -166,6 +170,7 @@ const statusChartConfig = computed(() => {
|
||||
color: statusColors[index % statusColors.length],
|
||||
};
|
||||
});
|
||||
|
||||
return config;
|
||||
});
|
||||
|
||||
@ -178,6 +183,7 @@ const marketingChartConfig = computed(() => {
|
||||
color: marketingColors[index % marketingColors.length],
|
||||
};
|
||||
});
|
||||
|
||||
return config;
|
||||
});
|
||||
</script>
|
||||
@ -220,8 +226,9 @@ const marketingChartConfig = computed(() => {
|
||||
</Card>
|
||||
|
||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<StatCard title="Kehadiran" :icon="UserCheck" main-label="Total Karyawan"
|
||||
:main-value="attendance.total_employees" :sub-label="attendance.percentage + '% hadir'" :items="[
|
||||
<StatCard v-if="can('dashboard.attendance')" title="Kehadiran" :icon="UserCheck"
|
||||
main-label="Total Karyawan" :main-value="attendance.total_employees"
|
||||
:sub-label="attendance.percentage + '% hadir'" :items="[
|
||||
{
|
||||
label: 'Hadir',
|
||||
value: attendance.present,
|
||||
@ -236,7 +243,7 @@ const marketingChartConfig = computed(() => {
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard title="Kas Toko" :icon="Banknote" main-label="Total Saldo"
|
||||
<StatCard v-if="can('dashboard.cash')" title="Kas Toko" :icon="Banknote" main-label="Total Saldo"
|
||||
:main-value="'Rp' + formatRupiah(cashOverview.total_balance)" :sub-label="cashOverview.total_transactions + ' transaksi'
|
||||
" :items="[
|
||||
{
|
||||
@ -249,7 +256,7 @@ const marketingChartConfig = computed(() => {
|
||||
},
|
||||
]" :cols="2" />
|
||||
|
||||
<StatCard title="Pendapatan" :icon="TrendingUp" main-label="Total"
|
||||
<StatCard v-if="can('dashboard.revenue')" title="Pendapatan" :icon="TrendingUp" main-label="Total"
|
||||
:main-value="'Rp' + formatRupiah(revenueSummary.total_revenue)" :sub-label="revenueSummary.total_orders + ' transaksi selesai'
|
||||
" :items="[
|
||||
{
|
||||
@ -269,7 +276,7 @@ const marketingChartConfig = computed(() => {
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard title="Pengeluaran" :icon="TrendingDown" main-label="Total"
|
||||
<StatCard v-if="can('dashboard.expense')" title="Pengeluaran" :icon="TrendingDown" main-label="Total"
|
||||
:main-value="'Rp' + formatRupiah(expenseSummary.total)" :items="[
|
||||
{
|
||||
label: 'Belanja',
|
||||
@ -287,7 +294,7 @@ const marketingChartConfig = computed(() => {
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<Card>
|
||||
<Card v-if="can('dashboard.orders_channel')">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">Pesanan per Channel</CardTitle>
|
||||
</CardHeader>
|
||||
@ -316,7 +323,7 @@ const marketingChartConfig = computed(() => {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Card v-if="can('dashboard.orders_payment')">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">Pesanan per Pembayaran</CardTitle>
|
||||
</CardHeader>
|
||||
@ -346,15 +353,14 @@ const marketingChartConfig = computed(() => {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Card v-if="can('dashboard.orders_marketing')">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">Pesanan per Marketing</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div v-if="orderStats.by_marketing.length > 0">
|
||||
<ChartContainer :config="marketingChartConfig" class="mx-auto aspect-square max-h-[200px]">
|
||||
<VisSingleContainer :data="orderStats.by_marketing"
|
||||
:margin="{ top: 10, bottom: 10 }">
|
||||
<VisSingleContainer :data="orderStats.by_marketing" :margin="{ top: 10, bottom: 10 }">
|
||||
<VisDonut :value="(d: (typeof orderStats.by_marketing)[number]) => d.count"
|
||||
:color="(_d: (typeof orderStats.by_marketing)[number], i: number) => marketingColors[i % marketingColors.length]"
|
||||
:arc-width="30" />
|
||||
@ -376,7 +382,7 @@ const marketingChartConfig = computed(() => {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Card v-if="can('dashboard.orders_status')">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">Pesanan per Status</CardTitle>
|
||||
</CardHeader>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user