Add Department Daily Report module to Department Dashboard

Integrated the Department Daily Report feature, enabling users to view, create, and manage daily reports. Added new Vue components, routing, and backend interactions for handling department-specific daily report data. Updated SessionUser functionality to include daily reports support.
This commit is contained in:
Jepp9350
2025-03-04 09:32:02 +01:00
parent 2851d768db
commit b091414087
6 changed files with 290 additions and 3 deletions
+3 -1
View File
@@ -16,6 +16,7 @@ import {EconomicProducts} from "@/components/session/token/SessionUser/Objects/e
import {Roles} from "@/components/session/token/SessionUser/Objects/Roles.vue";
import {Permissions} from "@/components/session/token/SessionUser/Objects/Permissions.vue";
import {CollectedOrderInvoices} from "@/components/session/token/SessionUser/Objects/CollectedOrderInvoices.vue";
import {DepartmentDailyReports} from "@/components/session/token/SessionUser/Objects/DepartmentDailyReports.vue";
import {ObjectsGlobal} from "@/components/session/token/SessionUser/Objects/ObjectsGlobal.vue";
import {useRouter} from "vue-router";
@@ -177,6 +178,7 @@ export const SessionUser = {
roles: Roles,
permissions: Permissions,
collectedOrderInvoices: CollectedOrderInvoices,
department_daily_reports: DepartmentDailyReports,
global: ObjectsGlobal,
},
/** The user's token & authentication status */
@@ -269,7 +271,7 @@ export const SessionUser = {
getDepartmentIdFromUrl: () => {
// Check if the department id is in the route
const router = useRouter();
return router.currentRoute.value.params.departmentId;
return parseInt(router.currentRoute.value.params.departmentId);
},
/** Redirect to */
redirectTo: {
@@ -0,0 +1,143 @@
<script>
import Swal from "sweetalert2";
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
import { ObjectsGlobal } from "@/components/session/token/SessionUser/Objects/ObjectsGlobal.vue";
import { SessionUser } from "@/components/session/token/SessionUser.vue";
import {ref} from "vue";
/**
* The DepartmentDailyReports object
*/
export const DepartmentDailyReports = {
meta: {
title: "Afdelingens dagsopgørelser",
icon: "fas fa-list",
description: "Oversigt over afdelingens dagsopgørelser",
endpoint: "/departments/daily-reports",
labels: {
single: "dagsopgørelse",
multiple: "dagsopgørelser"
}
},
columns: {
id: {
label: "ID",
type: "number",
sortable: true,
creation: {
required: false
}
},
department_id: {
label: "Afdelings ID",
type: "select",
sortable: true,
creation: {
required: true
},
options: async () => {
console.log("Getting departments");
return SessionUser.objects.departments.get.all();
}
},
water_usage: {
label: "Vandforbrug (m3)",
type: "number",
sortable: true,
creation: {
required: true
},
},
filled_by: {
label: "Udfyldt af",
type: "number",
sortable: true,
creation: {
required: false
},
},
created_at: {
label: "Oprettet",
type: "date",
sortable: true,
creation: {
required: false
}
},
},
add: async (department_id, category_id) => {
return ObjectsGlobal.add.object(
DepartmentDailyReports.meta.endpoint,
{
department_id: parseInt(department_id),
category_id: parseInt(category_id)
}
);
},
set: {
department_id: async (id, department_id) => {
return ObjectsGlobal.set.column(
DepartmentDailyReports.meta.endpoint,
id,
"department_id",
parseInt(department_id)
)
},
category_id: async (id, category_id) => {
return ObjectsGlobal.set.column(
DepartmentDailyReports.meta.endpoint,
id,
"category_id",
parseInt(category_id)
)
},
},
get: {
all: async () => {
return ObjectsGlobal.get.objects(DepartmentDailyReports.meta.endpoint);
},
single: async (id) => {
return ObjectsGlobal.get.object(DepartmentDailyReports.meta.endpoint, parseInt(id));
}
},
delete: async (id) => {
return ObjectsGlobal.delete.object(DepartmentDailyReports.meta.endpoint, parseInt(id));
},
functions: {
showCreateObjectFormDepartment: async (department_id, onAfterSubmit = null) => {
console.log("Department ID", department_id, "type", typeof department_id);
return ObjectsGlobal.showCreateObjectForm(DepartmentDailyReports, onAfterSubmit, {department_id: department_id});
},
showDeleteObjectForm: (id, onAfterSubmit = null) => {
return ObjectsGlobal.showDeleteObjectForm(DepartmentDailyReports, id, onAfterSubmit);
},
},
/**
* Show the create object form
* @param onAfterSubmit
* @returns {Promise<SweetAlertResult<Awaited<any>>>}
*/
showCreateObjectForm: (onAfterSubmit = null) => {
return ObjectsGlobal.showCreateObjectForm(DepartmentDailyReports, onAfterSubmit);
},
/**
* Show the edit object field form
* @param id
* @param column
* @param value
* @param onAfterSubmit
* @returns {Promise<SweetAlertResult<Awaited<any>>>}
*/
showEditObjectFieldForm: (id, column, value, onAfterSubmit = null) => {
return ObjectsGlobal.showEditObjectFieldForm(
DepartmentDailyReports,
id,
column,
value,
onAfterSubmit
);
}
};
</script>
@@ -199,14 +199,16 @@ export const ObjectsGlobal = {
<div class="control">
<!-- Select -->
<div class="select is-fullwidth">
<select id="${column}" class="has-background-light has-text-black" ${isLocked ? 'disabled' : ''}>`;
<select id="${column}" class="has-background-light has-text-black" ${isLocked ? 'disabled' : ''} >`;
await columns[column].options().then((response) => {
// How long are the list of options
for (let i = 0; i < response.length; i++) {
var tmp = response[i];
// Check if the column exists in the locked values
var lockedValue = lockedValues[column] === tmp.id ? 'selected' : '';
html += `<option value="${tmp.id}" ${lockedValue}>${tmp.name}</option>`;
html += `<option value="${tmp.id}" ${lockedValue}>`;
html += `${tmp.name}`;
html += `</option>`;
}
});
html += `</select>
+8
View File
@@ -71,6 +71,8 @@ import DepartmentStripeSetup from "@/views/dashboards/superUserDashboard/departm
import CollectedOrderInvoices from "@/views/dashboards/superUserDashboard/CollectedOrderInvoices.vue";
import CollectedOrderInvoice
from "@/views/dashboards/superUserDashboard/collectedOrderInvoice/collectedOrderInvoice.vue";
import DepartmentDailyReport
from "@/views/dashboards/departmentDashboard/modules/daily-report/DepartmentDailyReport.vue";
// Export the router as router
export const router = createRouter({
@@ -172,6 +174,12 @@ export const router = createRouter({
component: DepartmentBookings,
meta: { middleware: adminMiddleware }
},
{
name: 'dailyreport',
path: '/admin/:departmentId/modules/daily-report',
component: DepartmentDailyReport,
meta: { middleware: adminMiddleware }
},
{
name: 'superuser',
path: '/superuser',
@@ -0,0 +1,79 @@
<script setup>
import DepartmentDashboardHero from "@/views/dashboards/departmentDashboard/DepartmentDashboardHero.vue";
import PosDepartmentMVP from "@/components/displays/department/pos/PosDepartmentMVP.vue";
import DepartmentPosNavigation from "@/views/dashboards/departmentDashboard/modules/Pos/DepartmentPosNavigation.vue";
import RestrictedPageWrapper from "@/components/page/wrappers/RestrictedPageWrapper.vue";
import { SessionUser } from "@/components/session/token/SessionUser.vue";
import BookingsPagination from "@/components/displays/pagination/models/UserDashboard/BookingsPagination.vue";
import DepartmentDashboardPageWrapper from "@/views/dashboards/departmentDashboard/DepartmentDashboardPageWrapper.vue";
import DepartmentDashboardDailyReportCount
from "@/views/dashboards/departmentDashboard/modules/daily-report/displays/DepartmentDashboardDailyReportCount.vue";
import {ref} from "vue";
import { useRouter } from "vue-router";
// Get the department ID from the route
const router = useRouter();
const department_id = ref(parseInt(router.currentRoute.value.params.departmentId));
console.log(department_id.value);
// Define the reactive variables
const daily_reports = ref(null);
const reports = ref([
{
title: 'Transaktioner',
subtitle: 'Dagens transaktioner',
count: 10,
icon: 'fas fa-money-bill-wave',
color: 'primary',
buttons: [
{
id: 1,
href: '#',
icon: 'fas fa-list',
text: 'Se alle'
}
]
}
]);
</script>
<template>
<RestrictedPageWrapper :hasPermission="SessionUser.canAccessAdmin()">
<DepartmentDashboardPageWrapper
title="Dagsopgørelse"
subtitle="Få et overblik over dagens omsætning, forbrug og bookinger"
>
<!-- Create daily report button -->
<div class="columns is-flex-wrap-wrap">
<div class="column is-12 has-text-right">
<button class="button is-primary"
@click="SessionUser.objects.department_daily_reports.functions.showCreateObjectFormDepartment(department_id)">
<span class="icon">
<i class="fas fa-plus"></i>
</span>
<span>Opret ny dagsopgørelse</span>
</button>
</div>
</div>
<!-- At the top of the page, we want to have a button that allows the user to create a new daily report -->
<div class="columns is-multiline">
<div class="column is-4" v-for="report in reports" :key="report.title">
<DepartmentDashboardDailyReportCount
:title="report.title"
:subtitle="report.subtitle"
:count="report.count"
:icon="report.icon"
:color="report.color"
:buttons="report.buttons"
/>
</div>
</div>
</DepartmentDashboardPageWrapper>
</RestrictedPageWrapper>
</template>
<style scoped>
</style>
@@ -0,0 +1,53 @@
<script setup>
import {ref, defineProps} from 'vue';
const props = defineProps({
title: String,
subtitle: String,
count: Number,
icon: String,
color: String,
buttons: Array,
});
</script>
<template>
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left is-flex p-2">
<figure class="image is-48x48">
<span class="icon has-text-primary">
<i :class="icon" class="fa-3x"></i>
</span>
</figure>
</div>
<div class="media-content">
<p class="title is-4">{{ title }}</p>
<p class="subtitle is-6">{{ subtitle }}</p>
</div>
</div>
<div class="content has-text-centered">
<p class="title is-1">{{ count }}</p>
<p class="subtitle is-6">Antal</p>
</div>
</div>
<footer class="card-footer">
<a
v-for="button in buttons"
:key="button.id"
class="card-footer-item"
:href="button.href"
>
<span class="icon">
<i :class="button.icon"></i>
</span>
<span>{{ button.text }}</span>
</a>
</footer>
</div>
</template>
<style scoped>
</style>