Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 97 additions & 62 deletions src/views/ExpenseHistory.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,35 @@
</v-container>
</v-card>
</div>
<div>
<div v-show="oldImage || newImage">
<v-card>
<v-card-title class="beta_header_style">Expense at {{ date }}</v-card-title>
<!-- <v-data-table :headers="headers" :items="displayAudits" :loading="loading.audits" multi-sort>
<template #loading>
<v-skeleton-loader type="table-row" />
</template>
</v-data-table> -->
<v-card-title class="beta_header_style">Expense {{ status }} at {{ date }}</v-card-title>
<v-card-text class="mt-2"
><v-row
><v-row v-if="!oldImage"
><v-col
><b>Expense Status</b>
<div>{{ status }}</div></v-col
><b>Original Expense Details</b>
<div v-for="data in after" :key="data.purchaseDate">{{ data }}</div></v-col
></v-row
>
<v-row v-else-if="!newImage"
><v-col
><b>Before</b>
><b>Final Expense Details</b>
<div v-for="data in before" :key="data.purchaseDate">{{ data }}</div></v-col
></v-row
>
<v-row v-else
><v-col
><b>After</b>
<div v-for="data in after" :key="data.purchaseDate">{{ data }}</div></v-col
><b>Old Expense Details</b>
<div v-for="data in before" :key="data.purchaseDate">{{ data }}</div></v-col
><v-col
><b>Expense Detail Changes</b>
<div
:style="change.includes(data) ? 'background-color: yellow' : ''"
v-for="data in after"
:key="data.purchaseDate"
>
{{ data }}
</div></v-col
></v-row
></v-card-text
>
Expand All @@ -55,7 +65,7 @@
<script setup>
import { AxiosError } from 'axios';
import dayjs from 'dayjs';
import { onBeforeMount, onMounted, reactive, ref, watch } from 'vue';
import { onBeforeMount, reactive, ref, watch } from 'vue';
import { useStore } from 'vuex';
import api from '../shared/api';
import { updateStoreEmployees } from '../utils/storeUtils';
Expand All @@ -66,13 +76,11 @@ const store = useStore();
const date = ref(null);
const status = ref(null);
const before = ref(null);
const change = ref([]);
const after = ref(null);
const expenseId = ref(null);

/**
* A row in the data table that represents a notification audit
* @typedef {Notification & { name: string, date: string }} NotificationRow
*/
const oldImage = ref(null);
const newImage = ref(null);

// *✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫*
// ❃ ❃
Expand All @@ -84,16 +92,11 @@ const expenseId = ref(null);
// To load more data, the user must click the search button, which queries the database based on these filters.
const filters = reactive({
search: '',
auditType: 'Notification',
auditType: 'crud',
startDate: null,
endDate: null,
notifType: 'None'
endDate: null
});

/**
* Currently loaded audits
* @type {import('vue').Ref<NotificationRow[]>}
*/
const loadedAudits = ref([]);

// *✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫*
Expand All @@ -102,10 +105,6 @@ const loadedAudits = ref([]);
// ❉ ❉
// *✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫*

/**
* Sublist of loaded audits, filtered by the table search filter
* @type {NotificationRow[]}
* */
const displayAudits = ref(loadedAudits.value);

// display skeletons for components when loading
Expand All @@ -121,37 +120,84 @@ const loading = reactive({
// *✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫*

/**
* Finds the changes from audit to audit and store them
*/
function findChanges(beforeAudit, afterAudit) {
change.value = [];
beforeAudit.forEach((detail, index) => {
if (!(detail === afterAudit[index])) {
change.value.push(afterAudit[index]);
}
});
}

/**
* Handles the audit details view based on what kind of audit it is
*
*
* @param data the data at that specific point in the expense
* @param audit the audit at that specific point in the expense
*/
function handleClick(audit) {
date.value = audit.date;
status.value = determineStatus(audit);
let oldImage = audit.oldImage;
let newImage = audit.newImage;
before.value = [
oldImage?.cost || '',
oldImage?.description || '',
oldImage?.purchaseDate || '',
oldImage?.showOnFeed || ''
];
after.value = [
newImage?.cost || '',
newImage?.description || '',
newImage?.purchaseDate || '',
newImage?.showOnFeed || ''
];
status.value = determineStatus(audit).toLowerCase();
oldImage.value = audit.oldImage;
newImage.value = audit.newImage;
if (!oldImage.value) {
//for created expense audits
let employee = getEmployeeByID(newImage.value.employeeId, store.getters.employees);
after.value = [
'Expense Owner: ' + employee.firstName + ' ' + employee.lastName,
'Expense Creator: ' + audit.name,
'Category: ' + newImage.value.category,
'Cost: $' + newImage.value.cost,
'Purchase Date: ' + dayjs(newImage.value.purchaseDate).format('MM/DD/YYYY'),
'Description: ' + newImage.value.description,
'Show On Feed: ' + newImage.value.showOnFeed
];
} else if (!newImage.value) {
//for deleted expense audits
let employee = getEmployeeByID(oldImage.value.employeeId, store.getters.employees);
before.value = [
'Expense Owner: ' + employee.firstName + ' ' + employee.lastName,
'Expense Deleter: ' + audit.name,
'Category: ' + oldImage.value.category,
'Cost: $' + oldImage.value.cost,
'Purchase Date: ' + dayjs(oldImage.value.purchaseDate).format('MM/DD/YYYY'),
'Description: ' + oldImage.value.description,
'Show On Feed: ' + oldImage.value.showOnFeed
];
} else {
//for updated expense audits
let employee = getEmployeeByID(oldImage.value.employeeId, store.getters.employees);
before.value = [
'Expense Owner: ' + employee.firstName + ' ' + employee.lastName,
'Expense Updater: ' + audit.name,
'Category: ' + oldImage.value.category,
'Cost: $' + oldImage.value.cost,
'Purchase Date: ' + dayjs(oldImage.value.purchaseDate).format('MM/DD/YYYY'),
'Description: ' + oldImage.value.description,
'Show On Feed: ' + oldImage.value.showOnFeed
];
after.value = [
'Expense Owner: ' + employee.firstName + ' ' + employee.lastName,
'Expense Updater: ' + audit.name,
'Category: ' + newImage.value.category,
'Cost: $' + newImage.value.cost,
'Purchase Date: ' + dayjs(newImage.value.purchaseDate).format('MM/DD/YYYY'),
'Description: ' + newImage.value.description,
'Show On Feed: ' + newImage.value.showOnFeed
];
findChanges(before.value, after.value);
}
}

/**
* Queries the database based on the current filters
* (TEMP) currently only grabs the most recent expense audit and any audits relating to that expense
*/
async function query() {
loading.audits = true;

// convert string audit type to database compatible type
//let realType = AuditType.CRUD;

const res = await api.getCrudAudits({
startDate: filters.startDate,
Expand All @@ -178,7 +224,7 @@ async function query() {
return {
...audit,
name: `${emp.firstName} ${emp.lastName}`,
date: dayjs(audit.createdAt).format('MM/DD/YYYY HH:mm')
date: dayjs(audit.createdAt).format('MM/DD/YYYY')
};
});

Expand All @@ -197,7 +243,7 @@ function filterDisplayAudits() {
displayAudits.value = loadedAudits.value.filter((audit) => {
let valid = true;

if (audit.tableItemId !== expenseId.value) {
if (audit?.tableItemId !== expenseId.value) {
valid = false;
}

Expand Down Expand Up @@ -228,17 +274,10 @@ function determineStatus(audit) {
// *✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫*

onBeforeMount(async () => {
query(); // load table data
await query(); // load table data
loading.graph = false; // TODO: load graph
});

onMounted(() => {
date.value = loadedAudits.value[0];
status.value = loadedAudits.value[0];
before.value = ['Before'];
after.value = ['After'];
});

// *✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫✮❆✦✯✿✧✩❄✬✭❀✫*
// ❃ ❃
// ❇ WATCHERS ❇
Expand All @@ -258,8 +297,6 @@ watch(filters, filterDisplayAudits, { deep: true });
gap: 16px;
}

#control-panel,
#graphs,
#table {
width: 100%;
padding: 0px;
Expand All @@ -271,8 +308,6 @@ watch(filters, filterDisplayAudits, { deep: true });
gap: 8px;
}

#control-panel > *.v-card-title,
#graphs > *.v-card-title,
#table > *.v-card-title {
width: 100%;
display: flex;
Expand Down