diff --git a/custom_ui/api/db/tasks.py b/custom_ui/api/db/tasks.py index 8bcae60..e4f9ba0 100644 --- a/custom_ui/api/db/tasks.py +++ b/custom_ui/api/db/tasks.py @@ -42,6 +42,40 @@ def get_task_status_options(): return build_error_response(str(e), 500) +@frappe.whitelist() +def get_tasks_due(subject_filter): + """Return the number of items due today of the type of subject_filter""" + try: + filters = { + 'subject': ['like', f'%{subject_filter}%'], + 'status': ['not in', ["Template", "Completed", "Cancelled"]] + } + count = frappe.db.count("Task", filters=filters) + return build_success_response(count) + except frappe.ValidationError as ve: + return build_error_response(str(ve), 400) + except Exception as e: + return build_error_response(str(e), 500) + + +@frappe.whitelist() +def get_tasks_completed(subject_filter): + """Return the number of items due today marked complete of the type of subject_filter""" + try: + filters = { + 'subject': ['like', f'%{subject_filter}%'], + 'status': ['not in', ["Template", "Cancelled"]] + } + print("Completed Task filter", filters) + count = frappe.db.count("Task", filters=filters) + print("Matching Records:", count) + return build_success_response(count) + except frappe.ValidationError as ve: + return build_error_response(str(ve), 400) + except Exception as e: + return build_error_response(str(e), 500) + + @frappe.whitelist() def get_tasks_table_data(filters={}, sortings=[], page=1, page_size=10): """Get paginated task table data with filtering and sorting support.""" diff --git a/frontend/src/api.js b/frontend/src/api.js index a6bb5e8..936cae9 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -25,6 +25,8 @@ const FRAPPE_GET_JOB_TEMPLATES_METHOD = "custom_ui.api.db.jobs.get_job_templates const FRAPPE_GET_TASKS_METHOD = "custom_ui.api.db.tasks.get_tasks_table_data"; const FRAPPE_GET_TASKS_STATUS_OPTIONS = "custom_ui.api.db.tasks.get_task_status_options"; const FRAPPE_SET_TASK_STATUS_METHOD = "custom_ui.api.db.tasks.set_task_status"; +const FRAPPE_GET_TASKS_DUE_METHOD = "custom_ui.api.db.tasks.get_tasks_due"; +const FRAPPE_GET_TASKS_COMPLETED_METHOD = "custom_ui.api.db.tasks.get_tasks_completed"; // Invoice methods const FRAPPE_GET_INVOICES_METHOD = "custom_ui.api.db.invoices.get_invoice_table_data"; const FRAPPE_UPSERT_INVOICE_METHOD = "custom_ui.api.db.invoices.upsert_invoice"; @@ -45,7 +47,7 @@ const FRAPPE_GET_CLIENT_NAMES_METHOD = "custom_ui.api.db.clients.get_client_name class Api { // ============================================================================ - // CORE REQUEST METHOD + // CORE REQUEST METHOPD // ============================================================================ static async request(frappeMethod, args = {}) { @@ -401,6 +403,16 @@ class Api { return await this.request(FRAPPE_SET_TASK_STATUS_METHOD, { taskName, newStatus }); } + static async getTasksDue(subjectFilter) { + const result = await this.request(FRAPPE_GET_TASKS_DUE_METHOD, {subjectFilter}); + return result; + } + + static async getTasksCompleted(subjectFilter) { + const result = await this.request(FRAPPE_GET_TASKS_COMPLETED_METHOD, {subjectFilter}); + return result; + } + // ============================================================================ // INVOICE / PAYMENT METHODS // ============================================================================ diff --git a/frontend/src/components/pages/Home.vue b/frontend/src/components/pages/Home.vue index df3ad5e..d1ecda7 100644 --- a/frontend/src/components/pages/Home.vue +++ b/frontend/src/components/pages/Home.vue @@ -15,11 +15,11 @@
@@ -37,11 +37,11 @@ @@ -241,12 +241,12 @@ @@ -264,12 +264,12 @@ @@ -334,6 +334,7 @@ import Tag from "primevue/tag"; import { Calendar, Community, Hammer, PathArrowSolid, Clock, Shield, ShieldSearch, ClipboardCheck, DoubleCheck, CreditCard, CardNoAccess, ChatBubbleQuestion, Edit, WateringSoil, Soil, Truck, SoilAlt } from "@iconoir/vue"; +import Api from "../../api.js"; import DataUtils from "../../utils.js"; import { useNotificationStore } from "../../stores/notifications-primevue"; //import SimpleChart from "../common/SimpleChart.vue"; @@ -344,15 +345,22 @@ 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 locatesTodoNumber = ref(0); +const locatesCompletedNumber = ref(0); +const permitsTodoNumber = ref(0); +const permitsCompletedNumber = ref(0); const permitFinalizationsTodoNumber = ref(35); const permitFinalizationsCompletedNumber = ref(2); const warrantyTodoNumber = ref(0); const warrantyCompletedNumber = ref(10); +const chartData = ref({ + locates: {todo: 0, done: 0}, + permits: {todo: 0, done: 0}, + curbing: {todo: 0, done: 0}, + hydroseed: {todo: 0, done: 0}, +}); + const notifications = useNotificationStore(); // Computed values for dashboard metrics @@ -365,8 +373,16 @@ const avgResponseTime = computed(() => 2.3); const navigateTo = (path) => { router.push(path); }; -onMounted(() => { +onMounted(async() => { notifications.addWarning("Dashboard metrics are based on dummy data for demonstration purposes. UPDATES COMING SOON!"); + chartData.value.locates.todo = await Api.getTasksDue("Locate"); + chartData.value.locates.done = await Api.getTasksCompleted("Locate"); + chartData.value.permits.todo = await Api.getTasksDue("Permit"); + chartData.value.permits.done = await Api.getTasksCompleted("Permit"); + chartData.value.curbing.todo = await Api.getTasksDue("Curbing"); + chartData.value.curbing.done = await Api.getTasksCompleted("Curbing"); + chartData.value.hydroseed.todo = await Api.getTasksDue("Hydroseed"); + chartData.value.hydroseed.done = await Api.getTasksCompleted("Hydroseed"); });