Added a TodoChart component, adding a reactive Todo/Completed items tracker.
This commit is contained in:
parent
d4545d753a
commit
d154c28ed2
2 changed files with 552 additions and 157 deletions
|
|
@ -1,203 +1,300 @@
|
|||
<template>
|
||||
<div class="dashboard">
|
||||
<h1 class="dashboard-title">Dashboard</h1>
|
||||
<h1 class="dashboard-title">Today's Tasks</h1>
|
||||
|
||||
<div class="widgets-grid">
|
||||
<!-- Calendar Widget -->
|
||||
<!-- Locates Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<Calendar class="widget-icon" />
|
||||
<h3>Service Calendar</h3>
|
||||
<ShieldSearch class="widget-icon" />
|
||||
<h3>Locates</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<div class="metric">
|
||||
<span class="metric-number">8</span>
|
||||
<span class="metric-label">Services Scheduled Today</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-number">15</span>
|
||||
<span class="metric-label">Services This Week</span>
|
||||
</div>
|
||||
<Button
|
||||
label="View Calendar"
|
||||
size="small"
|
||||
outlined
|
||||
@click="navigateTo('/calendar')"
|
||||
/>
|
||||
<TodoChart
|
||||
title="Locates"
|
||||
:todoNumber="locatesTodoNumber"
|
||||
:completedNumber="locatesCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button" @click="navigateTo('/jobs')">
|
||||
View Locates
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
|
||||
<!-- Clients Widget -->
|
||||
<!-- Permits Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<Community class="widget-icon" />
|
||||
<h3>Client Contact List</h3>
|
||||
<ClipboardCheck class="widget-icon" />
|
||||
<h3>Permits</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<div class="status-row">
|
||||
<Tag severity="success" value="5 Active Jobs" />
|
||||
<Tag severity="warning" value="3 Pending Estimates" />
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-number">{{ clientData.length }}</span>
|
||||
<span class="metric-label">Total Client Records</span>
|
||||
</div>
|
||||
<Button
|
||||
label="View Client List"
|
||||
size="small"
|
||||
outlined
|
||||
@click="navigateTo('/clients')"
|
||||
/>
|
||||
<TodoChart
|
||||
title="Permits"
|
||||
:todoNumber="permitsTodoNumber"
|
||||
:completedNumber="permitsCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button" @click="navigateTo('/jobs')">
|
||||
View Permits
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
|
||||
<!-- Jobs Widget -->
|
||||
<!-- Permits Finalization Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<Hammer class="widget-icon" />
|
||||
<h3>Job Management</h3>
|
||||
<DoubleCheck class="widget-icon" />
|
||||
<h3>Permit Finalizations</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<div class="status-row">
|
||||
<Tag severity="info" value="4 In Progress" />
|
||||
<Tag severity="success" value="2 Completed" />
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-number">{{
|
||||
jobData.filter((job) => job.overAllStatus === "in progress").length
|
||||
}}</span>
|
||||
<span class="metric-label">Jobs In Progress</span>
|
||||
</div>
|
||||
<Button
|
||||
label="View All Jobs"
|
||||
size="small"
|
||||
outlined
|
||||
@click="navigateTo('/jobs')"
|
||||
/>
|
||||
<TodoChart
|
||||
title="Permit Finalization"
|
||||
:todoNumber="permitFinalizationsTodoNumber"
|
||||
:completedNumber="permitFinalizationsCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button" @click="navigateTo('/jobs')">
|
||||
View Finalizations
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
|
||||
<!-- Routes Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<PathArrowSolid class="widget-icon" />
|
||||
<h3>Service Routes</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<div class="metric">
|
||||
<span class="metric-number">6</span>
|
||||
<span class="metric-label">Active Routes Today</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-number">45.2</span>
|
||||
<span class="metric-label">Avg. Miles per Route</span>
|
||||
</div>
|
||||
<Button
|
||||
label="View Routes"
|
||||
size="small"
|
||||
outlined
|
||||
@click="navigateTo('/routes')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
|
||||
<!-- Time Sheets Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<Clock class="widget-icon" />
|
||||
<h3>Employee Timesheets</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<div class="metric">
|
||||
<span class="metric-number">32.5</span>
|
||||
<span class="metric-label">Total Hours This Week</span>
|
||||
</div>
|
||||
<div class="status-row">
|
||||
<Tag severity="success" value="5 Approved" />
|
||||
<Tag severity="warning" value="2 Pending Approval" />
|
||||
</div>
|
||||
<Button
|
||||
label="View Timesheets"
|
||||
size="small"
|
||||
outlined
|
||||
@click="navigateTo('/timesheets')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
|
||||
<!-- Warranties Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<HistoricShield class="widget-icon" />
|
||||
<h3>Warranty Claims</h3>
|
||||
<Shield class="widget-icon" />
|
||||
<h3>Warranties</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<div class="metric">
|
||||
<span class="metric-number">10</span>
|
||||
<span class="metric-label">Open Claims</span>
|
||||
</div>
|
||||
<div class="status-row">
|
||||
<Tag severity="success" value="3 Completed" />
|
||||
<Tag severity="warning" value="4 In Progress" />
|
||||
</div>
|
||||
<Button
|
||||
label="View Claims"
|
||||
size="small"
|
||||
outlined
|
||||
@click="navigateTo('/warranties')"
|
||||
/>
|
||||
<TodoChart
|
||||
title="Warranty Claims"
|
||||
:todoNumber="warrantyTodoNumber"
|
||||
:completedNumber="warrantyCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button" @click="navigateTo('/jobs')">
|
||||
View Warranties
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<!-- Quick Stats Summary -->
|
||||
<div class="summary-section">
|
||||
<Card>
|
||||
<!-- Incomplete Bids Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<h3>Quick Stats</h3>
|
||||
<div class="widget-header">
|
||||
<Edit class="widget-icon" />
|
||||
<h3>Incomplete Bids</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">{{ totalRevenue }}</span>
|
||||
<span class="stat-label">Monthly Revenue</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">{{ completedJobs }}</span>
|
||||
<span class="stat-label">Jobs Completed</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">{{ clientSatisfaction }}%</span>
|
||||
<span class="stat-label">Client Satisfaction</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">{{ avgResponseTime }}h</span>
|
||||
<span class="stat-label">Avg Response Time</span>
|
||||
</div>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Incomplete Bids"
|
||||
:todoNumber="bidsTodoNumber"
|
||||
:completedNumber="bidsCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/calendar')">
|
||||
Incomplete Bids
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<!-- Unapproved Estimates Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<ChatBubbleQuestion class="widget-icon" />
|
||||
<h3>Unapproved Estimates</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Unapproved Estimates"
|
||||
:todoNumber="estimatesTodoNumber"
|
||||
:completedNumber="estimatesCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/estimates')">
|
||||
Unapproved Estimates
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<!-- Half Down Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<CreditCard class="widget-icon" />
|
||||
<h3>Half Down Payments</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Half Down Payments"
|
||||
:todoNumber="halfDownTodoNumber"
|
||||
:completedNumber="halfDownCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/jobs')">
|
||||
Half Down Payments
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<!-- Late Balances Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<CardNoAccess class="widget-icon" />
|
||||
<h3>Late Balances</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Late Balances"
|
||||
:todoNumber="balancesTodoNumber"
|
||||
:completedNumber="balancesCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/jobs')">
|
||||
Late Balances
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<!-- Backflow Tests Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<WateringSoil class="widget-icon" />
|
||||
<h3>Backflow Tests</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Backflow Tests"
|
||||
:todoNumber="backflowsTodoNumber"
|
||||
:completedNumber="backflowsCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/jobs')">
|
||||
Late Balances
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<!-- Curbing Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<SoilAlt class="widget-icon" />
|
||||
<h3>Curbing</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Curbing"
|
||||
:todoNumber="curbingTodoNumber"
|
||||
:completedNumber="curbingCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/jobs')">
|
||||
Curbing
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<!-- Hyrdoseeding Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<SoilAlt class="widget-icon" />
|
||||
<h3>Hydroseeding</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Hydroseeding"
|
||||
:todoNumber="hydroseedingTodoNumber"
|
||||
:completedNumber="hydroseedingCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/jobs')">
|
||||
Hydroseeding
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<!-- Machines Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<Truck class="widget-icon" />
|
||||
<h3>Machines</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Machines"
|
||||
:todoNumber="machinesTodoNumber"
|
||||
:completedNumber="machinesCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/jobs')">
|
||||
Machines
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<!-- Deliveries Widget -->
|
||||
<Card class="widget-card">
|
||||
<template #header>
|
||||
<div class="widget-header">
|
||||
<Truck class="widget-icon" />
|
||||
<h3>Deliveries</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="widget-content">
|
||||
<TodoChart
|
||||
title="Deliveries"
|
||||
:todoNumber="deliveriesTodoNumber"
|
||||
:completedNumber="delivieriesCompletedNumber"
|
||||
>
|
||||
</TodoChart>
|
||||
<button class="sidebar-button"
|
||||
@click="navigateTo('/jobs')">
|
||||
Deliveries
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
|
|
@ -209,17 +306,29 @@
|
|||
import { ref, computed, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import Card from "primevue/card";
|
||||
import Button from "primevue/button";
|
||||
import Tag from "primevue/tag";
|
||||
import { Calendar, Community, Hammer, PathArrowSolid, Clock, HistoricShield } from "@iconoir/vue";
|
||||
import { Calendar, Community, Hammer, PathArrowSolid, Clock, Shield, ShieldSearch,
|
||||
ClipboardCheck, DoubleCheck, CreditCard, CardNoAccess, ChatBubbleQuestion, Edit,
|
||||
WateringSoil, Soil, Truck, SoilAlt } from "@iconoir/vue";
|
||||
import DataUtils from "../../utils.js";
|
||||
import { useNotificationStore } from "../../stores/notifications-primevue";
|
||||
//import SimpleChart from "../common/SimpleChart.vue";
|
||||
import TodoChart from "../common/TodoChart.vue";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// Dummy data from utils
|
||||
const clientData = ref(DataUtils.dummyClientData);
|
||||
const jobData = ref(DataUtils.dummyJobData);
|
||||
const locatesTodoNumber = ref(45);
|
||||
const locatesCompletedNumber = ref(5);
|
||||
const permitsTodoNumber = ref(24);
|
||||
const permitsCompletedNumber = ref(7);
|
||||
const permitFinalizationsTodoNumber = ref(35);
|
||||
const permitFinalizationsCompletedNumber = ref(2);
|
||||
const warrantyTodoNumber = ref(0);
|
||||
const warrantyCompletedNumber = ref(10);
|
||||
|
||||
const notifications = useNotificationStore();
|
||||
|
||||
// Computed values for dashboard metrics
|
||||
|
|
@ -266,10 +375,11 @@ onMounted(() => {
|
|||
transition:
|
||||
transform 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
background-color: var(--theme-surface-alt)
|
||||
}
|
||||
|
||||
.widget-card:hover {
|
||||
transform: translateY(-2px);
|
||||
/*transform: translateY(-2px);*/
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +391,7 @@ onMounted(() => {
|
|||
}
|
||||
|
||||
.widget-icon {
|
||||
color: rgb(69, 112, 101);
|
||||
color: var(--theme-primary-strong);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
|
@ -295,7 +405,8 @@ onMounted(() => {
|
|||
.widget-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
margin: 0;
|
||||
/*gap: 15px;*/
|
||||
}
|
||||
|
||||
.metric {
|
||||
|
|
@ -353,6 +464,10 @@ onMounted(() => {
|
|||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.sidebar-button {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.widgets-grid {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue