initial commit
This commit is contained in:
562
resources/js/pages/dashboards/analytics.vue
Normal file
562
resources/js/pages/dashboards/analytics.vue
Normal file
@@ -0,0 +1,562 @@
|
||||
<script setup>
|
||||
import LineChart from '@core/libs/chartjs/components/LineChart';
|
||||
import { endOfMonth, format, startOfMonth, subDays, subMonths } from 'date-fns';
|
||||
import { computed, onBeforeMount, ref, watch } from 'vue';
|
||||
import { useTheme } from 'vuetify';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
const vuetifyTheme = useTheme();
|
||||
const store = useStore();
|
||||
const selectedPeriod = ref('this_month');
|
||||
const date = ref('');
|
||||
const userData = useCookie('userData');
|
||||
const showDateRange = computed(() => selectedPeriod.value === 'custom');
|
||||
|
||||
const periodOptions = ref([
|
||||
{ abbreviation: 'today', name: 'Today' },
|
||||
{ abbreviation: 'last7_days', name: 'Last 7 Days' },
|
||||
{ abbreviation: 'last30_days', name: 'Last 30 Days' },
|
||||
{ abbreviation: 'this_month', name: 'This Month' },
|
||||
{ abbreviation: 'last_month', name: 'Last Month' },
|
||||
{ abbreviation: 'this_quarter', name: 'Current Quarter' },
|
||||
{ abbreviation: 'last_quarter', name: 'Last Quarter' },
|
||||
{ abbreviation: 'this_year', name: 'This Year' },
|
||||
{ abbreviation: 'last_year', name: 'Last Year' },
|
||||
{ abbreviation: 'last365_days', name: 'Last 365 Days' },
|
||||
{ abbreviation: 'custom', name: 'Custom' },
|
||||
]);
|
||||
|
||||
const setPeriod = (period) => {
|
||||
selectedPeriod.value = period;
|
||||
setDateRange();
|
||||
};
|
||||
|
||||
const setDateRange = () => {
|
||||
const today = new Date();
|
||||
let start, end;
|
||||
|
||||
switch (selectedPeriod.value) {
|
||||
case 'today':
|
||||
start = end = today;
|
||||
break;
|
||||
case 'last7_days':
|
||||
start = subDays(today, 7);
|
||||
end = today;
|
||||
break;
|
||||
case 'last30_days':
|
||||
start = subDays(today, 30);
|
||||
end = today;
|
||||
break;
|
||||
case 'this_month':
|
||||
start = startOfMonth(today);
|
||||
end = endOfMonth(today);
|
||||
break;
|
||||
case 'last_month':
|
||||
start = startOfMonth(subMonths(today, 1));
|
||||
end = endOfMonth(subMonths(today, 1));
|
||||
break;
|
||||
case 'this_quarter':
|
||||
end = startOfMonth(subMonths(today, today.getMonth() % 3));
|
||||
start = endOfMonth(subMonths(today, today.getMonth() % 3 + 2));
|
||||
break;
|
||||
case 'last_quarter':
|
||||
end = startOfMonth(subMonths(today, today.getMonth() % 3 + 3));
|
||||
start = endOfMonth(subMonths(today, today.getMonth() % 3 + 5));
|
||||
break;
|
||||
case 'this_year':
|
||||
start = new Date(today.getFullYear(), 0, 1);
|
||||
end = new Date(today.getFullYear(), 11, 31);
|
||||
break;
|
||||
case 'last_year':
|
||||
start = new Date(today.getFullYear() - 1, 0, 1);
|
||||
end = new Date(today.getFullYear() - 1, 11, 31);
|
||||
break;
|
||||
case 'last365_days':
|
||||
start = subDays(today, 365);
|
||||
end = today;
|
||||
break;
|
||||
case 'custom':
|
||||
return;
|
||||
default:
|
||||
start = end = today;
|
||||
}
|
||||
|
||||
date.value = [format(start, 'yyyy-MM-dd'), format(end, 'yyyy-MM-dd')];
|
||||
};
|
||||
|
||||
onBeforeMount(async () => {
|
||||
setDateRange();
|
||||
const [startDate, endDate] = date.value;
|
||||
|
||||
await store.dispatch('getAdminDashboardData', {
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
});
|
||||
});
|
||||
|
||||
watch(selectedPeriod, async () => {
|
||||
setDateRange();
|
||||
if (selectedPeriod.value !== 'custom') {
|
||||
const [startDate, endDate] = date.value;
|
||||
await store.dispatch('getAdminDashboardData', {
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const getButtonColor = (buttonPeriod) => {
|
||||
return selectedPeriod.value === buttonPeriod ? 'primary' : 'secondary';
|
||||
};
|
||||
|
||||
const changeDateRange = async () => {
|
||||
console.log('changed date', date.value, 'type:', typeof date.value);
|
||||
|
||||
try {
|
||||
const dateString = typeof date.value === 'string' ? date.value : '';
|
||||
const [startDate, endDate] = dateString.split(" to ");
|
||||
|
||||
if (startDate && endDate) {
|
||||
await store.dispatch('getAdminDashboardData', {
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
});
|
||||
} else {
|
||||
console.warn('Invalid date range');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error processing date range:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const assignmentData = computed(() => [
|
||||
{ title: 'Patients', amount: store.getters.getDashboardData.totals.total_patints, color: 'primary' },
|
||||
{ title: 'Orders', amount: store.getters.getDashboardData.totals.total_orders, color: 'success' },
|
||||
{ title: 'Amount', amount: store.getters.getDashboardData.totals.total_amount ? formatAmount(store.getters.getDashboardData.totals.total_amount) : '$0.00', color: 'secondary' },
|
||||
{ title: 'Products Sold', amount: store.getters.getDashboardData.totals.total_products_sold, color: 'error' },
|
||||
]);
|
||||
|
||||
const recentActivity = [
|
||||
{ title: 'Patient created by Provider', subtitle: '31/Jul/2024 00:33 39.50.134.183' },
|
||||
{ type: 'divider', inset: true },
|
||||
{ title: 'Order Created By Patient William', subtitle: '31/Jul/2024 00:19 39.50.134.183' },
|
||||
{ type: 'divider', inset: true },
|
||||
];
|
||||
|
||||
const OrdersData = ref([]);
|
||||
const ordersHeaders = [
|
||||
{ title: 'Date', key: 'date' },
|
||||
{ title: '#Order', key: 'order_id' },
|
||||
{ title: 'Patient', key: 'patient_name' },
|
||||
{ title: 'Amount', key: 'amount' },
|
||||
];
|
||||
const completedMeetingsHeaders = [
|
||||
{ title: 'Date', key: 'appointment_date' },
|
||||
{ title: 'Time', key: 'appointment_time' },
|
||||
{ title: '#Order', key: 'order_id' },
|
||||
{ title: 'Patient', key: 'patient_name' },
|
||||
{ title: 'Provider', key: 'provider_name' },
|
||||
{ title: 'Start Time', key: 'start_time' },
|
||||
{ title: 'End Time', key: 'end_time' },
|
||||
{ title: 'Duration', key: 'duration' },
|
||||
];
|
||||
const productsHeaders = [
|
||||
{ title: 'ID', key: 'product_id' },
|
||||
{ title: 'Name', key: 'product_name' },
|
||||
{ title: 'Amount', key: 'total_amount' },
|
||||
{ title: 'Orders', key: 'total_orders' },
|
||||
];
|
||||
|
||||
function changeFormat(dateFormat) {
|
||||
const dateParts = dateFormat.split('-');
|
||||
const year = parseInt(dateParts[0]);
|
||||
const month = parseInt(dateParts[1]);
|
||||
const day = parseInt(dateParts[2]);
|
||||
const date = new Date(year, month - 1, day);
|
||||
return `${month}-${day}-${date.getFullYear()}`;
|
||||
};
|
||||
|
||||
const formatDateTime = (dateStr) => {
|
||||
const [date, time] = dateStr.split(' ');
|
||||
const [year, month, day] = date.split('-');
|
||||
const [hours, minutes] = time.split(':');
|
||||
return `${month}-${day}-${year} ${hours}:${minutes}`;
|
||||
};
|
||||
|
||||
const formattedDuration = (startTime, endTime) => {
|
||||
const start = new Date(startTime);
|
||||
const end = new Date(endTime);
|
||||
const diffInSeconds = Math.floor((end - start) / 1000); // Difference in seconds
|
||||
|
||||
const hours = Math.floor(diffInSeconds / 3600);
|
||||
const minutes = Math.floor((diffInSeconds % 3600) / 60);
|
||||
const seconds = diffInSeconds % 60;
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}h ${minutes}m ${seconds}s`;
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}m ${seconds}s`;
|
||||
} else {
|
||||
return `${seconds}s`;
|
||||
}
|
||||
};
|
||||
const formatAmount = (amount) => {
|
||||
return new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD'
|
||||
}).format(amount);
|
||||
};
|
||||
const data = ref({
|
||||
labels: [],
|
||||
datasets: [
|
||||
{
|
||||
fill: false,
|
||||
tension: 0,
|
||||
pointRadius: 4,
|
||||
label: 'Meetings',
|
||||
pointHoverRadius: 6,
|
||||
pointStyle: 'circle',
|
||||
borderColor: 'green',
|
||||
backgroundColor: 'green',
|
||||
pointHoverBorderWidth: 5,
|
||||
pointHoverBorderColor: 'white',
|
||||
pointBorderColor: 'transparent',
|
||||
pointHoverBackgroundColor: 'primary',
|
||||
data: [],
|
||||
yAxisID: 'y-axis-meetings',
|
||||
},
|
||||
{
|
||||
fill: false,
|
||||
tension: 0,
|
||||
label: 'Sales',
|
||||
pointRadius: 4,
|
||||
pointHoverRadius: 6,
|
||||
pointStyle: 'circle',
|
||||
borderColor: 'orange',
|
||||
backgroundColor: 'orange',
|
||||
pointHoverBorderWidth: 5,
|
||||
pointHoverBorderColor: 'white',
|
||||
pointBorderColor: 'transparent',
|
||||
pointHoverBackgroundColor: 'warning',
|
||||
data: [],
|
||||
yAxisID: 'y-axis-sales',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const updateChartData = (newData) => {
|
||||
const isSingleDate = newData.graph_data.dates.length === 1;
|
||||
let labels = newData.graph_data.dates;
|
||||
let meetingsData = newData.graph_data.data.total_meetings;
|
||||
let salesData = newData.graph_data.data.total_sales;
|
||||
|
||||
if (isSingleDate) {
|
||||
labels = [labels[0], labels[0]];
|
||||
meetingsData = [meetingsData[0], meetingsData[0]];
|
||||
salesData = [salesData[0], salesData[0]];
|
||||
}
|
||||
|
||||
data.value = {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
...data.value.datasets[0],
|
||||
data: meetingsData,
|
||||
},
|
||||
{
|
||||
...data.value.datasets[1],
|
||||
data: salesData,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
const formatOrderId = (id) => {
|
||||
if (id >= 1 && id <= 9) {
|
||||
return id.toString().padStart(4, '0');
|
||||
} else if (id >= 10 && id <= 99) {
|
||||
return id.toString().padStart(4, '0');
|
||||
} else if (id >= 100 && id <= 999) {
|
||||
return id.toString().padStart(4, '0');
|
||||
} else {
|
||||
return id; // or handle cases for IDs outside these ranges
|
||||
}
|
||||
}
|
||||
watch(() => store.getters.getDashboardData, updateChartData, { immediate: true });
|
||||
|
||||
const chartConfig = computed(() => {
|
||||
const maxMeetings = Math.max(...data.value.datasets[0].data, 1);
|
||||
const maxSales = Math.max(...data.value.datasets[1].data, 1);
|
||||
const isSingleDate = store.getters.getDashboardData.graph_data.dates.length === 1;
|
||||
|
||||
return {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
'y-axis-meetings': {
|
||||
type: 'linear',
|
||||
position: 'left',
|
||||
beginAtZero: true,
|
||||
min: 0,
|
||||
max: maxMeetings * 2,
|
||||
ticks: {
|
||||
stepSize: Math.max(1, Math.floor(maxMeetings / 4)),
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Meetings',
|
||||
},
|
||||
},
|
||||
'y-axis-sales': {
|
||||
type: 'linear',
|
||||
position: 'right',
|
||||
beginAtZero: true,
|
||||
min: 0,
|
||||
max: maxSales * 1.5,
|
||||
ticks: {
|
||||
callback: (value) => `$${value.toLocaleString()}`,
|
||||
stepSize: Math.max(1, Math.floor(maxSales / 4)),
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Sales',
|
||||
},
|
||||
},
|
||||
x: {
|
||||
ticks: {
|
||||
autoSkip: true,
|
||||
maxTicksLimit: isSingleDate ? 2 : 10,
|
||||
maxRotation: 0,
|
||||
minRotation: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: (context) => {
|
||||
let label = context.dataset.label || '';
|
||||
if (label) {
|
||||
label += ': ';
|
||||
}
|
||||
if (context.parsed.y !== null) {
|
||||
label += context.dataset.yAxisID === 'y-axis-sales'
|
||||
? `$${context.parsed.y.toLocaleString()}`
|
||||
: context.parsed.y;
|
||||
}
|
||||
return label;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow class="match-height d-flex" v-if="$can('read', 'Dashboard Filters')">
|
||||
<VCol cols="12" :md="selectedPeriod === 'custom' ? '9' : '12'"
|
||||
class="d-flex align-center justify-end flex-wrap pull-right">
|
||||
<VBtn class="mx-2" :color="getButtonColor('today')" @click="setPeriod('today')">Day</VBtn>
|
||||
<VBtn class="mx-2" :color="getButtonColor('last7_days')" @click="setPeriod('last7_days')">Week</VBtn>
|
||||
<VBtn class="mx-2" :color="getButtonColor('this_month')" @click="setPeriod('this_month')">Month</VBtn>
|
||||
<VSelect v-model="selectedPeriod" label="Filter By" density="comfortable" item-title="name"
|
||||
item-value="abbreviation" :items="periodOptions" class="medium-width" />
|
||||
</VCol>
|
||||
<VCol cols="12" :md="selectedPeriod === 'custom' ? '3' : ''" v-if="selectedPeriod === 'custom'">
|
||||
<AppDateTimePicker v-model="date" label="Date Range" :config="{ mode: 'range' }" @change="changeDateRange()"
|
||||
class="ml-4 date-range-picker" />
|
||||
</VCol>
|
||||
</VRow>
|
||||
<VRow>
|
||||
<VCol cols="12" md="4">
|
||||
<VCard title="Welcome! Glad to see you." class="main-cards">
|
||||
<VCardText>
|
||||
<h1 class="mb-2 mt-10">{{ userData.fullName || userData.username }}</h1>
|
||||
<p>Here are your company's most recent statistics:</p>
|
||||
</VCardText>
|
||||
<VCardItem>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VList class="card-list mb-0">
|
||||
<VListItem v-for="assignment in assignmentData" :key="assignment.title" class="pb-2">
|
||||
<template #title>
|
||||
<div class="text-h6 me-4 mb-0 text-truncate">
|
||||
{{ assignment.title }}
|
||||
</div>
|
||||
</template>
|
||||
<template #append>
|
||||
<VBtn :color="assignment.color" class="rounded" size="small" width="100">
|
||||
{{ assignment.amount }}
|
||||
</VBtn>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
<VCol cols="12" md="8">
|
||||
<VCard title="Overview" class="main-cards">
|
||||
<VCardText>
|
||||
<!-- <ApexChart /> -->
|
||||
<LineChart :chart-options="chartConfig" :height="400" :chart-data="data" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
</VRow>
|
||||
<VRow>
|
||||
<VCol cols="12" md="6">
|
||||
<VCard title="Recent Activity" class="activity-card">
|
||||
<VCardText>
|
||||
<template v-if="store.getters.getDashboardData.patient_reg_activity.length">
|
||||
<v-list v-for="recentAct in store.getters.getDashboardData.patient_reg_activity" :key="recentAct.id"
|
||||
lines="two" style="border-bottom: 1px solid silver;padding-bottom: 0px;">
|
||||
<v-list-item :title="recentAct.activity" :subtitle="changeFormat(recentAct.created_at)"
|
||||
style="padding-bottom: 0px;"></v-list-item>
|
||||
</v-list>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="display: flex; justify-content: center; align-items: center; height: 200px;">
|
||||
No Record
|
||||
</div>
|
||||
</template>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
|
||||
<VCol cols="12" md="6">
|
||||
<VCard title="Recent Orders" class="recent-cards ">
|
||||
<VCardText>
|
||||
<VDataTable :headers="ordersHeaders" :items="store.getters.getDashboardData.orders_data" :items-per-page="5"
|
||||
class="text-no-wrap">
|
||||
<template #item.order_id="{ item }">
|
||||
<RouterLink :to="{ name: 'admin-order-detail', params: { id: item.order_id } }">
|
||||
<span class="text-h6 text-primary">{{ formatOrderId(item.order_id) }}</span>
|
||||
</RouterLink>
|
||||
</template>
|
||||
<template #item.date="{ item }">
|
||||
<span class="text-h6">{{ changeFormat(item.date) }}</span>
|
||||
</template>
|
||||
<template #item.amount="{ item }">
|
||||
<span class="text-h6">{{ formatAmount(item.amount) }}</span>
|
||||
</template>
|
||||
</VDataTable>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
</VRow>
|
||||
<VRow>
|
||||
<VCol cols="12" md="6">
|
||||
<VCard title="Completed Appointments" class="recent-cards ">
|
||||
<VCardText>
|
||||
<VDataTable :headers="completedMeetingsHeaders" :items="store.getters.getDashboardData.completed_meetings"
|
||||
:items-per-page="5" class="text-no-wrap">
|
||||
<template #item.appointment_date="{ item }">
|
||||
<span class="text-h6">{{ changeFormat(item.appointment_date) }}</span>
|
||||
</template>
|
||||
<template #item.order_id="{ item }">
|
||||
<span class="text-h6">{{ item.order_id }}</span>
|
||||
</template>
|
||||
<template #item.start_time="{ item }">
|
||||
<span class="text-h6">{{ formatDateTime(item.start_time) }}</span>
|
||||
</template>
|
||||
<template #item.end_time="{ item }">
|
||||
<span class="text-h6">{{ formatDateTime(item.end_time) }}</span>
|
||||
</template>
|
||||
<template #item.duration="{ item }">
|
||||
<span class="text-h6">{{ formattedDuration(item.start_time, item.end_time) }}</span>
|
||||
</template>
|
||||
</VDataTable>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VCard title="Products" class="recent-cards">
|
||||
<VCardText>
|
||||
<VDataTable :headers="productsHeaders" :items="store.getters.getDashboardData.products" :items-per-page="5"
|
||||
class="text-no-wrap">
|
||||
<template #item.product_id="{ item }">
|
||||
<span class="text-h6">{{ item.product_id }}</span>
|
||||
</template>
|
||||
<template #item.total_amount="{ item }">
|
||||
<span class="text-h6">{{ formatAmount(item.total_amount) }}</span>
|
||||
</template>
|
||||
</VDataTable>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@use "@core-scss/template/libs/apex-chart.scss";
|
||||
|
||||
.activity-card {
|
||||
min-height: 480px;
|
||||
max-height: 480px;
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
|
||||
.main-cards {
|
||||
min-height: 508px;
|
||||
}
|
||||
|
||||
.recent-cards {
|
||||
min-height: 480px;
|
||||
}
|
||||
|
||||
.medium-width {
|
||||
min-width: 200px;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
.date-range-picker {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.ml-4 {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.d-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.mx-2 {
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.v-btn {
|
||||
min-width: 80px;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.v-autocomplete {
|
||||
min-width: 200px;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
.v-autocomplete__content {
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.v-autocomplete {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.v-btn {
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.date-range-picker {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
102
resources/js/pages/dashboards/crm.vue
Normal file
102
resources/js/pages/dashboards/crm.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<script setup>
|
||||
import CrmActivityTimeline from '@/views/dashboards/crm/CrmActivityTimeline.vue'
|
||||
import CrmDeveloperMeetup from '@/views/dashboards/crm/CrmDeveloperMeetup.vue'
|
||||
import CrmMeetingSchedule from '@/views/dashboards/crm/CrmMeetingSchedule.vue'
|
||||
import CrmRevenueReport from '@/views/dashboards/crm/CrmRevenueReport.vue'
|
||||
import CrmSalesOverview from '@/views/dashboards/crm/CrmSalesOverview.vue'
|
||||
import CrmTotalGrowthCharts from '@/views/dashboards/crm/CrmTotalGrowthCharts.vue'
|
||||
import CrmTotalSales from '@/views/dashboards/crm/CrmTotalSales.vue'
|
||||
import CrmTransactions from '@/views/dashboards/crm/CrmTransactions.vue'
|
||||
import CrmUpgradeYourPlan from '@/views/dashboards/crm/CrmUpgradeYourPlan.vue'
|
||||
import CrmWeeklySales from '@/views/dashboards/crm/CrmWeeklySales.vue'
|
||||
import illustration1 from '@images/cards/illustration-1.png'
|
||||
import illustration2 from '@images/cards/illustration-2.png'
|
||||
import { useStore } from 'vuex'
|
||||
const store = useStore()
|
||||
const cardStatisticsWithImages = [
|
||||
{
|
||||
title: 'Total Meetings',
|
||||
subtitle: 'Year of 2021',
|
||||
stats: '13k',
|
||||
change: 15.6,
|
||||
// image: illustration1,
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
title: 'Orders',
|
||||
subtitle: 'Year of 2021',
|
||||
stats: '13k',
|
||||
change: 15.6,
|
||||
// image: illustration1,
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
title: 'New Patients',
|
||||
subtitle: 'Year of 2021',
|
||||
stats: '13k',
|
||||
change: 15.6,
|
||||
// image: illustration1,
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
title: 'New Providers',
|
||||
subtitle: 'Last Week',
|
||||
stats: '24.5k',
|
||||
change: -20,
|
||||
// image: illustration2,
|
||||
color: 'secondary',
|
||||
},
|
||||
]
|
||||
|
||||
// const statistic = {
|
||||
// title: 'New Project',
|
||||
// color: 'primary',
|
||||
// icon: 'ri-file-word-2-line',
|
||||
// stats: '862',
|
||||
// change: -18,
|
||||
// subtitle: 'Yearly Project'
|
||||
// }
|
||||
// onMounted(() => {
|
||||
// store.dispatch('updateIsLoading', false)
|
||||
// })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<VRow class="match-height">
|
||||
<VCol
|
||||
v-for="statistics in cardStatisticsWithImages"
|
||||
:key="statistics.title"
|
||||
class="pt-8 pt-sm-3"
|
||||
cols="12"
|
||||
md="3"
|
||||
sm="6"
|
||||
|
||||
>
|
||||
<CardStatisticsWithImages v-bind="statistics" />
|
||||
</VCol>
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="8"
|
||||
md="12"
|
||||
>
|
||||
<CrmWeeklySales />
|
||||
</VCol>
|
||||
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
style="display: none;"
|
||||
>
|
||||
<CrmActivityTimeline />
|
||||
</VCol>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<CrmMeetingSchedule />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</section>
|
||||
</template>
|
147
resources/js/pages/dashboards/ecommerce.vue
Normal file
147
resources/js/pages/dashboards/ecommerce.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<script setup>
|
||||
import ECommerceCongratulations from '@/views/dashboards/ecommerce/ECommerceCongratulations.vue'
|
||||
import ECommerceInvoiceTable from '@/views/dashboards/ecommerce/ECommerceInvoiceTable.vue'
|
||||
import ECommerceMeetingSchedule from '@/views/dashboards/ecommerce/ECommerceMeetingSchedule.vue'
|
||||
import ECommerceNewVisitors from '@/views/dashboards/ecommerce/ECommerceNewVisitors.vue'
|
||||
import ECommerceTotalProfit from '@/views/dashboards/ecommerce/ECommerceTotalProfit.vue'
|
||||
import ECommerceTotalRevenue from '@/views/dashboards/ecommerce/ECommerceTotalRevenue.vue'
|
||||
import ECommerceTotalSalesChart from '@/views/dashboards/ecommerce/ECommerceTotalSalesChart.vue'
|
||||
import ECommerceTotalSalesRadial from '@/views/dashboards/ecommerce/ECommerceTotalSalesRadial.vue'
|
||||
import ECommerceTransactions from '@/views/dashboards/ecommerce/ECommerceTransactions.vue'
|
||||
import ECommerceWebsiteTransactions from '@/views/dashboards/ecommerce/ECommerceWebsiteTransactions.vue'
|
||||
|
||||
const statisticsVertical = [
|
||||
{
|
||||
title: 'Revenue',
|
||||
color: 'success',
|
||||
icon: 'ri-money-dollar-circle-line',
|
||||
stats: '95.2k',
|
||||
change: 12,
|
||||
subtitle: 'Revenue Increase',
|
||||
},
|
||||
{
|
||||
title: 'Transactions',
|
||||
color: 'info',
|
||||
icon: 'ri-bank-card-line',
|
||||
stats: '$1.2k',
|
||||
change: 38,
|
||||
subtitle: 'Daily Transactions',
|
||||
},
|
||||
]
|
||||
|
||||
const statisticsVerticalTwo = [
|
||||
{
|
||||
title: 'Logistics',
|
||||
color: 'error',
|
||||
icon: 'ri-car-line',
|
||||
stats: '44.10k',
|
||||
change: 12,
|
||||
subtitle: 'Revenue Increase',
|
||||
},
|
||||
{
|
||||
title: 'Reports',
|
||||
color: 'warning',
|
||||
icon: 'ri-file-chart-line',
|
||||
stats: '268',
|
||||
change: -28,
|
||||
subtitle: 'System Bugs',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow class="match-height">
|
||||
<VCol
|
||||
cols="12"
|
||||
md="8"
|
||||
class="d-flex flex-column align-self-end"
|
||||
>
|
||||
<ECommerceCongratulations />
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
v-for="statistic in statisticsVertical"
|
||||
:key="statistic.title"
|
||||
cols="12"
|
||||
sm="6"
|
||||
md="2"
|
||||
>
|
||||
<CardStatisticsVertical v-bind="statistic" />
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="8"
|
||||
>
|
||||
<ECommerceTotalProfit />
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="4"
|
||||
>
|
||||
<VRow class="match-height">
|
||||
<VCol cols="12">
|
||||
<ECommerceTotalSalesChart />
|
||||
</VCol>
|
||||
<VCol cols="6">
|
||||
<ECommerceTotalRevenue />
|
||||
</VCol>
|
||||
<VCol cols="6">
|
||||
<ECommerceTotalSalesRadial />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="4"
|
||||
>
|
||||
<ECommerceTransactions />
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="4"
|
||||
>
|
||||
<VRow>
|
||||
<VCol
|
||||
v-for="statistics in statisticsVerticalTwo"
|
||||
:key="statistics.title"
|
||||
cols="6"
|
||||
>
|
||||
<CardStatisticsVertical v-bind="statistics" />
|
||||
</VCol>
|
||||
|
||||
<VCol cols="12">
|
||||
<ECommerceNewVisitors />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="4"
|
||||
>
|
||||
<ECommerceWebsiteTransactions />
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="8"
|
||||
>
|
||||
<ECommerceInvoiceTable />
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="4"
|
||||
>
|
||||
<ECommerceMeetingSchedule />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@use "@core-scss/template/libs/apex-chart.scss";
|
||||
</style>
|
Reference in New Issue
Block a user