-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(debtor): split into two components
- Loading branch information
Showing
4 changed files
with
382 additions
and
203 deletions.
There are no files selected for viewing
93 changes: 93 additions & 0 deletions
93
apps/dashboard/src/modules/financial/components/debtor/DebtorHandouts.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
<template> | ||
<CardComponent | ||
:header="t('modules.financial.fine.handoutEvents.header')" | ||
class="w-full"> | ||
<DataTable | ||
paginator | ||
v-model:rows="take" | ||
v-model:first="skip" | ||
:rowsPerPageOptions="[5, 10, 25, 50, 100]" | ||
:value="debtorStore.fineHandoutEvents" | ||
> | ||
<Column field="id" id="id" :header="t('common.id')"> | ||
<template #body v-if="debtorStore.isFineHandoutEventsLoading"> | ||
<Skeleton class="w-4 my-1 h-1rem surface-300"/> | ||
</template> | ||
</Column> | ||
<Column field="createdAt" id="date" :header="t('common.date')"> | ||
<template #body v-if="debtorStore.isFineHandoutEventsLoading"> | ||
<Skeleton class="w-7 my-1 h-1rem surface-300"/> | ||
</template> | ||
<template #body="slotProps" v-else>{{ formatDateTime(new Date(slotProps.data.createdAt)) }}</template> | ||
</Column> | ||
<Column | ||
field="referenceDate" | ||
id="referenceDate" | ||
:header="t('modules.financial.fine.handoutEvents.referenceDate')"> | ||
<template #body v-if="debtorStore.isFineHandoutEventsLoading"> | ||
<Skeleton class="w-4 my-1 h-1rem surface-300"/> | ||
</template> | ||
<template #body="slotProps" v-else>{{ formatDateTime(new Date(slotProps.data.referenceDate)) }}</template> | ||
</Column> | ||
<Column id="info" :header="t('common.info')" > | ||
<template #body v-if="debtorStore.isFineHandoutEventsLoading"> | ||
<Skeleton class="w-2 my-1 h-1rem surface-300"/> | ||
</template> | ||
<template #body v-else> | ||
<i class="pi pi-info-circle"/> | ||
</template> | ||
</Column> | ||
</DataTable> | ||
</CardComponent> | ||
<!-- <Dialog--> | ||
<!-- v-model:visible="showModal"--> | ||
<!-- class="w-auto flex w-9 md:w-4"--> | ||
<!-- :header="t('modules.financial.fine.handoutEvents.details')">--> | ||
<!-- <div class="flex flex-column">--> | ||
<!-- <div class="flex flex-row justify-content-between">--> | ||
<!-- <p>{{ t("modules.financial.fine.handoutEvents.number") }}</p>--> | ||
<!-- <p>{{ selectedHandoutEvent?.fines.length }}</p>--> | ||
<!-- </div>--> | ||
<!-- <div class="flex flex-row justify-content-between">--> | ||
<!-- <p>{{ t("modules.financial.fine.handoutEvents.total") }}</p>--> | ||
<!-- <p>{{ formatPrice(modalTotalFines) }}--> | ||
<!-- </p>--> | ||
<!-- </div>--> | ||
<!-- <div class="flex flex-row justify-content-between">--> | ||
<!-- <p>{{ t("common.createdAt") }}</p>--> | ||
<!-- <p>{{ formatDateTime(new Date(selectedHandoutEvent?.createdAt || '')) }}</p>--> | ||
<!-- </div>--> | ||
<!-- <div class="flex flex-row justify-content-between">--> | ||
<!-- <p>{{ t("modules.financial.fine.handoutEvents.referenceDate") }}</p>--> | ||
<!-- <p>{{ formatDateTime(new Date(selectedHandoutEvent?.referenceDate || '')) }}</p>--> | ||
<!-- </div>--> | ||
<!-- </div>--> | ||
<!-- </Dialog>--> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { useI18n } from "vue-i18n"; | ||
import { formatDateTime } from "@/utils/formatterUtils"; | ||
import Column from "primevue/column"; | ||
import CardComponent from "@/components/CardComponent.vue"; | ||
import Skeleton from "primevue/skeleton"; | ||
import DataTable from "primevue/datatable"; | ||
import { ref, watch } from "vue"; | ||
import { useDebtorStore } from "@/stores/debtor.store"; | ||
const { t } = useI18n(); | ||
const debtorStore = useDebtorStore(); | ||
const take = ref(10); | ||
const skip = ref(0); | ||
watch(take, () => debtorStore.fetchFineHandoutEvents(take.value, skip.value)); | ||
watch(skip, () => debtorStore.fetchFineHandoutEvents(take.value, skip.value)); | ||
</script> | ||
|
||
|
||
<style scoped lang="scss"> | ||
</style> |
210 changes: 210 additions & 0 deletions
210
apps/dashboard/src/modules/financial/components/debtor/DebtorTable.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
<template> | ||
<CardComponent :header="t('modules.financial.debtor.debtorUsers.header')" class="w-full"> | ||
<DataTable :value="debtorRows" tableStyle="min-width: 50rem" | ||
removableSort | ||
filterDisplay="row" | ||
@sort="onSortClick" | ||
striped-rows | ||
v-model:selection="selectedUsers"> | ||
|
||
<Column selectionMode="multiple" style="width: 2%" > | ||
</Column> | ||
|
||
<Column field="id" header="Id" style="width: 5%"> | ||
<template #body v-if="debtorStore.isDebtorsLoading"> | ||
<Skeleton class="w-6 mr-8 my-1 h-2rem surface-300"/> | ||
</template> | ||
</Column> | ||
|
||
<Column field="name" header="Name" :sortable="true" style="width: 15%"> | ||
<template #body v-if="debtorStore.isDebtorsLoading"> | ||
<Skeleton class="w-6 mr-8 my-1 h-2rem surface-300"/> | ||
</template> | ||
<template #body="{ data }" v-else> | ||
{{ data.name }} | ||
</template> | ||
<template #filter> | ||
<InputText v-model="nameFilter" type="text" class="p-column-filter" placeholder="Search" /> | ||
</template> | ||
</Column> | ||
|
||
<Column field="secondaryBalance" filter-match-mode="notEquals" | ||
:header="secondaryBalanceHeader" :sortable="true" :showFilterMenu="false" style="width: 20%"> | ||
<template #body v-if="debtorStore.isDebtorsLoading"> | ||
<Skeleton class="w-6 mr-8 my-1 h-2rem surface-300"/> | ||
</template> | ||
<template #body="{ data }" v-else> | ||
{{ data.secondaryBalance }} | ||
</template> | ||
<template #filter> | ||
<Calendar | ||
v-model="secondaryBalanceDate" | ||
id="firstDate" | ||
showTime | ||
hourFormat="24" | ||
placeholder="Click to change date" | ||
/> | ||
</template> | ||
</Column> | ||
|
||
<Column field="primaryBalance" filter-match-mode="notEquals" | ||
:header="primaryBalanceHeader" :sortable="true" :showFilterMenu="false" style="width: 20%"> | ||
<template #body v-if="debtorStore.isDebtorsLoading"> | ||
<Skeleton class="w-6 mr-8 my-1 h-2rem surface-300"/> | ||
</template> | ||
<template #body="{ data }" v-else> | ||
{{ data.primaryBalance }} | ||
</template> | ||
<template #filter> | ||
<Calendar | ||
v-model="primaryBalanceDate" | ||
id="firstDate" | ||
showTime | ||
hourFormat="24" | ||
placeholder="Click to change date" | ||
/> | ||
</template> | ||
</Column> | ||
|
||
<Column field="fine" header="Fine" :sortable="true" style="width: 10%"> | ||
<template #body v-if="debtorStore.isDebtorsLoading"> | ||
<Skeleton class="w-6 mr-8 my-1 h-2rem surface-300"/> | ||
</template> | ||
</Column> | ||
|
||
<Column field="fineSince" header="Fine since" :sortable="true" style="width: 10%"> | ||
<template #body v-if="debtorStore.isDebtorsLoading"> | ||
<Skeleton class="w-6 mr-8 my-1 h-2rem surface-300"/> | ||
</template> | ||
<template #body="slotProps" v-else> | ||
<span v-if="slotProps.data.fineSince" class="text-red-500 font-bold"> | ||
{{ formatTimeSince(new Date(slotProps.data.fineSince), new Date()) }} | ||
</span> | ||
</template> | ||
</Column> | ||
|
||
</DataTable> | ||
</CardComponent> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { useI18n } from "vue-i18n"; | ||
import CardComponent from "@/components/CardComponent.vue"; | ||
import { useDebtorStore, SortField } from "@/stores/debtor.store"; | ||
import { computed, type ComputedRef, onMounted, ref, watch } from "vue"; | ||
import Calendar from "primevue/calendar"; | ||
import Column from "primevue/column"; | ||
import { formatPrice, formatTimeSince } from "@/utils/formatterUtils"; | ||
import DataTable, { type DataTableSortEvent } from "primevue/datatable"; | ||
import Skeleton from "primevue/skeleton"; | ||
import { debounce } from "lodash"; | ||
const { t } = useI18n(); | ||
const debtorStore = useDebtorStore(); | ||
// All the users that have been selected for actions | ||
const selectedUsers = ref(); | ||
// Primary balance | ||
const primaryBalanceDate = ref<Date>(); | ||
const primaryBalanceHeader = computed(() => { | ||
if(primaryBalanceDate.value == undefined) { | ||
return "Primary balance now "; | ||
} else { | ||
return "Primary balance on " + primaryBalanceDate.value.toLocaleString('nl', { | ||
year: 'numeric', | ||
month: 'short', | ||
day: 'numeric' | ||
}); | ||
} | ||
}); | ||
// Secondary balance | ||
const secondaryBalanceDate = ref<Date>(); | ||
const secondaryBalanceHeader = computed(() => { | ||
if(secondaryBalanceDate.value == undefined) { | ||
return "Secondary balance --/--/--"; | ||
} else { | ||
return "Secondary balance on " + secondaryBalanceDate.value.toLocaleString('nl', { | ||
year: 'numeric', | ||
month: 'short', | ||
day: 'numeric' | ||
}); | ||
} | ||
}); | ||
// Fetch new calculated fines based on the dates | ||
watch(primaryBalanceDate, updateCalculatedFines); | ||
watch(secondaryBalanceDate, updateCalculatedFines); | ||
async function updateCalculatedFines() { | ||
selectedUsers.value = []; | ||
await debtorStore.fetchCalculatedFines(primaryBalanceDate.value || new Date(), secondaryBalanceDate.value); | ||
} | ||
const nameFilter = ref<string>(""); | ||
watch(nameFilter, debounce(() => { | ||
console.log(2); | ||
debtorStore.filter = { | ||
name: nameFilter.value | ||
}; | ||
}, 50)); | ||
const onSortClick = (sort: DataTableSortEvent) => { | ||
if (sort.sortField == SortField.SECONDARY_BALANCE | ||
&& secondaryBalanceDate.value == undefined) { | ||
return; | ||
} | ||
debtorStore.sort = { | ||
field: sort.sortField as SortField || null, | ||
direction: sort.sortOrder || null | ||
}; | ||
}; | ||
// Row in the datatable | ||
interface DebtorRow { | ||
id: number | undefined; | ||
name: string; | ||
primaryBalance: string; | ||
secondaryBalance: string; | ||
fine?: string; | ||
} | ||
// Convert data from the store to something that can be displayed by the datatable | ||
const debtorRows: ComputedRef<DebtorRow[]> = computed(() => { | ||
if (debtorStore.isDebtorsLoading) { | ||
return new Array(10); | ||
} | ||
const debtorRowsArr = []; | ||
for (const debtorId in debtorStore.debtors) { | ||
const debtor = debtorStore.debtors[debtorId]; | ||
debtorRowsArr.push({ | ||
id: debtor.user.gewisId, | ||
name: debtor.user.firstName + " " + debtor.user.lastName, | ||
primaryBalance: formatPrice(debtor.fine.balances[0].amount), | ||
secondaryBalance: debtor.fine.balances[1] && formatPrice(debtor.fine.balances[1].amount), | ||
fine: debtor.fine.balances[0].fine && formatPrice( | ||
debtor.fine.balances[0].fine | ||
), | ||
fineSince: debtor.fine.balances[0].fineSince | ||
}); | ||
} | ||
return debtorRowsArr; | ||
}); | ||
onMounted(() => { | ||
updateCalculatedFines(); | ||
}); | ||
</script> | ||
|
||
|
||
<style scoped lang="scss"> | ||
</style> |
Oops, something went wrong.