diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..8beccd3f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "npm" # Specify npm as the package manager + directories: + - "apps/point-of-sale" + - "apps/dashboard" + - "lib/common" + schedule: + interval: "weekly" # Set the update schedule to weekly + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] # Ignore major updates diff --git a/README.md b/README.md index c8f8c2bc..cb7ea4ff 100644 --- a/README.md +++ b/README.md @@ -67,4 +67,12 @@ You can quickly start development directly in your browser by using [Codespaces] - You can access the dashboard and point of sale at `localhost:5173` and `localhost:5174` respectively. ### Proxying requests to different backends -In the respective `.env` files, you can change which backend the frontend uses in development by changing the `VITE_DEV_API_BASE`. By default, this is set to the test backend (`https://sudosos.test.gewis.nl/api/v1`), but you can also change it to `https://sudosos.gewis.nl/api/v1` for the production backend. Or you can change it to `http://localhost:3000` if you are running the backend locally. \ No newline at end of file +In the respective `.env` files, you can change which backend the frontend uses in development by changing the `VITE_DEV_API_BASE`. By default, this is set to the test backend (`https://sudosos.test.gewis.nl/api/v1`), but you can also change it to `https://sudosos.gewis.nl/api/v1` for the production backend. Or you can change it to `http://localhost:3000` if you are running the backend locally. + +## Contributors + +This project exists thanks to all the people who contribute code. + +[//]: # (TODO create a CONTRIBUTING.md) +[//]: # (If you'd like to help, see [our guide to contributing code](CONTRIBUTING.md).) +Code contributors diff --git a/apps/dashboard/index.html b/apps/dashboard/index.html index 7d96b3eb..ff82af65 100644 --- a/apps/dashboard/index.html +++ b/apps/dashboard/index.html @@ -12,6 +12,11 @@ SudoSOS + + + + +
diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 53613e3a..0d340405 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -15,50 +15,14 @@ "format": "prettier --write src/" }, "dependencies": { - "@stripe/stripe-js": "^4.4.0", - "@sudosos/sudosos-client": "github:GEWIS/sudosos-client#cfcc3dad2494d8eb1911002fe0526c1e2e29cd25", + "@stripe/stripe-js": "^4.8.0", "@sudosos/sudosos-frontend-common": "workspace:^", - "@types/dinero.js": "^1.9.4", - "@vee-validate/rules": "^4.12.8", - "@vee-validate/yup": "^4.11.1", - "dinero.js": "^1.9.1", - "fuse.js": "^7.0.0", - "jwt-decode": "^4.0.0", - "marked": "^11.1.1", - "pinia": "^2.1.3", - "primeflex": "^3.3.1", - "primeicons": "^6.0.1", - "primevue": "^3.49.0", - "sass": "^1.63.6", - "uuid": "^9.0.0", - "vee-validate": "^4.11.1", - "vue": "^3.3.4", - "vue-i18n": "^9.2.2", - "vue-router": "^4.2.2", + "@vee-validate/rules": "^4.14.1", + "@vee-validate/yup": "^4.14.1", + "marked": "^11.2.0", + "vee-validate": "^4.14.1", + "vue-i18n": "^9.14.1", "vue3-pdf-app": "^1.0.3", - "yup": "^1.2.0" - }, - "devDependencies": { - "@intlify/eslint-plugin-vue-i18n": "^2.0.0", - "@rushstack/eslint-patch": "^1.2.0", - "@tsconfig/node18": "^18.2.2", - "@types/lodash": "^4.14.198", - "@types/node": "^18.19.4", - "@types/uuid": "^9.0.2", - "@vitejs/plugin-vue": "^5.0.2", - "@vue/eslint-config-prettier": "^9.0.0", - "@vue/eslint-config-typescript": "^12.0.0", - "@vue/tsconfig": "^0.5.1", - "axios": "^1.6.8", - "eslint": "^8.50.0", - "eslint-plugin-github-commit-hash": "^1.0.3", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-vue": "^9.11.0", - "lodash": "^4.17.21", - "npm-run-all": "^4.1.5", - "prettier": "^3.1.1", - "typescript": "^5.3.3", - "vite": "^5.0.12", - "vue-tsc": "^2.0.29" + "yup": "^1.4.0" } } diff --git a/apps/dashboard/public/bier_margin_red.png b/apps/dashboard/public/bier_margin_red.png new file mode 100644 index 00000000..f4d27e23 Binary files /dev/null and b/apps/dashboard/public/bier_margin_red.png differ diff --git a/apps/dashboard/src/assets/img/bier_grayscale.png b/apps/dashboard/src/assets/img/bier_grayscale.png new file mode 100644 index 00000000..fca798fb Binary files /dev/null and b/apps/dashboard/src/assets/img/bier_grayscale.png differ diff --git a/apps/dashboard/src/components/ActionButton.vue b/apps/dashboard/src/components/ActionButton.vue index 48a1b58c..5fc8f7a5 100644 --- a/apps/dashboard/src/components/ActionButton.vue +++ b/apps/dashboard/src/components/ActionButton.vue @@ -9,7 +9,7 @@ diff --git a/apps/dashboard/src/modules/admin/components/users/forms/UserFineWaiveForm.vue b/apps/dashboard/src/modules/admin/components/users/forms/UserFineWaiveForm.vue new file mode 100644 index 00000000..48b4459d --- /dev/null +++ b/apps/dashboard/src/modules/admin/components/users/forms/UserFineWaiveForm.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/dashboard/src/modules/admin/views/AdminBannersView.vue b/apps/dashboard/src/modules/admin/views/AdminBannersView.vue index 7dde9b74..0f9c28c6 100644 --- a/apps/dashboard/src/modules/admin/views/AdminBannersView.vue +++ b/apps/dashboard/src/modules/admin/views/AdminBannersView.vue @@ -8,14 +8,14 @@ import BannersList from '@/modules/admin/components/banners/BannersList.vue'; import { onMounted } from 'vue'; import { useBannersStore } from '@/stores/banner.store'; -import { storeToRefs } from 'pinia'; +import { type StoreGeneric, storeToRefs } from 'pinia'; import { useI18n } from "vue-i18n"; const { t } = useI18n(); const bannersStore = useBannersStore(); -const { banners } = storeToRefs(bannersStore); +const { banners } = storeToRefs(bannersStore as StoreGeneric); onMounted(async () => { bannersStore.fetchBanners(); diff --git a/apps/dashboard/src/modules/admin/views/AdminSingleUserView.vue b/apps/dashboard/src/modules/admin/views/AdminSingleUserView.vue index eae9ad4d..30d3e26d 100644 --- a/apps/dashboard/src/modules/admin/views/AdminSingleUserView.vue +++ b/apps/dashboard/src/modules/admin/views/AdminSingleUserView.vue @@ -6,7 +6,7 @@
- +
{ if (route.query.token !== undefined) { const token = route.query.token as string; - authStore.gewisWebLogin(uuid(), token, apiService).catch(() => { + authStore.gewisWebLogin(crypto.randomUUID(), token, apiService).catch(() => { router.replace({ path: "/error" }); }); } diff --git a/apps/dashboard/src/modules/auth/views/AuthLoginView.vue b/apps/dashboard/src/modules/auth/views/AuthLoginView.vue index 470a80f4..233ed1bd 100644 --- a/apps/dashboard/src/modules/auth/views/AuthLoginView.vue +++ b/apps/dashboard/src/modules/auth/views/AuthLoginView.vue @@ -27,7 +27,6 @@ import { onBeforeMount, ref } from "vue"; import { useAuthStore } from "@sudosos/sudosos-frontend-common"; import apiService from "@/services/ApiService"; import router from "@/router"; -import { v4 as uuid } from 'uuid'; import { useI18n } from "vue-i18n"; const { t } = useI18n(); @@ -48,7 +47,7 @@ const hasToken = () => { onBeforeMount(() => { if (route.query.token !== undefined) { const token = route.query.token as string; - authStore.gewisWebLogin(uuid(), token, apiService) + authStore.gewisWebLogin(crypto.randomUUID(), token, apiService) .then(() => { router.push('/'); }) diff --git a/apps/dashboard/src/modules/financial/components/invoice/InvoiceAddressingCard.vue b/apps/dashboard/src/modules/financial/components/invoice/InvoiceAddressingCard.vue index bfad9144..255914c3 100644 --- a/apps/dashboard/src/modules/financial/components/invoice/InvoiceAddressingCard.vue +++ b/apps/dashboard/src/modules/financial/components/invoice/InvoiceAddressingCard.vue @@ -11,7 +11,7 @@ import FormCard from "@/components/FormCard.vue"; import { computed, onBeforeMount, ref, watch } from "vue"; import type { InvoiceResponse } from "@sudosos/sudosos-client"; -import InvoiceAddressingForm from "@/modules/financial/components/invoice/forms/InvoiceAddressingForm.vue"; +import InvoiceAddressingForm from "@/modules/financial/components/invoice/forms/InvoiceUpdateAddressingForm.vue"; import { updateInvoiceAddressingObject } from "@/utils/validation-schema"; import { schemaToForm } from "@/utils/formUtils"; import { InvoiceStatusResponseStateEnum } from "@sudosos/sudosos-client/src/api"; diff --git a/apps/dashboard/src/modules/financial/components/invoice/InvoiceAmountCard.vue b/apps/dashboard/src/modules/financial/components/invoice/InvoiceAmountCard.vue new file mode 100644 index 00000000..ec219b39 --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/InvoiceAmountCard.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceEntriesTable.vue b/apps/dashboard/src/modules/financial/components/invoice/InvoiceEntriesTable.vue similarity index 76% rename from apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceEntriesTable.vue rename to apps/dashboard/src/modules/financial/components/invoice/InvoiceEntriesTable.vue index 710d6a01..980fafcd 100644 --- a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceEntriesTable.vue +++ b/apps/dashboard/src/modules/financial/components/invoice/InvoiceEntriesTable.vue @@ -35,7 +35,7 @@ {{ entry.data.vatPercentage + '%' }} - + {{ entry.data.description }} @@ -46,7 +46,7 @@ class="p-1" > @@ -58,10 +58,11 @@ import { formatPrice } from "@/utils/formatterUtils"; import Column from "primevue/column"; import DataTable from "primevue/datatable"; -import { computed, onMounted, type PropType, type Ref, ref } from "vue"; +import { onMounted, type PropType, type Ref, ref } from "vue"; import type { InvoiceEntryResponse, InvoiceResponse } from "@sudosos/sudosos-client"; import type { DineroObject } from "dinero.js"; import { useI18n } from "vue-i18n"; +import { isDirty } from "@/utils/invoiceUtil"; const { t } = useI18n(); @@ -73,13 +74,13 @@ const props = defineProps({ }); const exclVat: Ref = ref({ amount: 0, precision: 2, currency: 'EUR' }); +const totalEntries: Ref = ref({ amount: 0, precision: 2, currency: 'EUR' }); const vat: Ref> = ref({}); const inclVat: Ref = ref({ amount: 0, precision: 2, currency: 'EUR' }); -const totalRows: InvoiceEntryResponse[] = []; -const totalRowCutoff = computed(() => { - return props.invoice.invoiceEntries.length - totalRows.length; -}); -const allRows = ref(props.invoice.invoiceEntries); +const totalRows: (InvoiceEntryResponse & { class?: any })[] = []; +const allRows: Ref<(InvoiceEntryResponse & { class?: any })[]> = ref([]); +const totalRowCutoff = ref(0); + const rowTotal = (row: any): DineroObject => { return { @@ -90,12 +91,20 @@ const rowTotal = (row: any): DineroObject => { onMounted(() => { props.invoice.invoiceEntries.forEach((entry) => { + allRows.value.push({ + description: entry.description, + amount: entry.amount, + vatPercentage: entry.vatPercentage, + priceInclVat: entry.priceInclVat, + custom: false, + }); const price = entry.priceInclVat.amount * entry.amount; inclVat.value.amount += price; const excl = Math.round(price / (1 + (entry.vatPercentage / 100))); const vatAmount = price - excl; exclVat.value.amount += excl; + totalEntries.value.amount += price; if (entry.vatPercentage in vat.value) { vat.value[entry.vatPercentage].amount += vatAmount; @@ -123,16 +132,26 @@ onMounted(() => { }); } - if (props.invoice.transfer) { + totalRows.push({ + description: t('common.incl'), + amount: 1, + vatPercentage: 0, + priceInclVat: totalEntries.value, + custom: false, + }); + + if (props.invoice.transfer && isDirty(props.invoice)) { totalRows.push({ - description: t('common.incl'), + description: t('modules.financial.invoice.transfer'), amount: 1, vatPercentage: 0, + class: { 'text-red-500': true }, priceInclVat: props.invoice.transfer.amountInclVat, custom: false, }); } + totalRowCutoff.value = allRows.value.length; allRows.value.push(...totalRows); }); diff --git a/apps/dashboard/src/modules/financial/components/invoice/InvoicePdf.vue b/apps/dashboard/src/modules/financial/components/invoice/InvoicePdf.vue index e2d21f8d..0d1f1f8d 100644 --- a/apps/dashboard/src/modules/financial/components/invoice/InvoicePdf.vue +++ b/apps/dashboard/src/modules/financial/components/invoice/InvoicePdf.vue @@ -50,7 +50,7 @@ import { useToast } from "primevue/usetoast"; import type { InvoiceResponse } from "@sudosos/sudosos-client"; import CardComponent from "@/components/CardComponent.vue"; import VuePdfApp from "vue3-pdf-app"; -import InvoiceEntriesTable from "@/modules/financial/components/invoice/forms/InvoiceEntriesTable.vue"; +import InvoiceEntriesTable from "@/modules/financial/components/invoice/InvoiceEntriesTable.vue"; import { useI18n } from "vue-i18n"; const { t } = useI18n(); diff --git a/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreate.vue b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreate.vue new file mode 100644 index 00000000..aa8aac12 --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreate.vue @@ -0,0 +1,100 @@ + + + + + \ No newline at end of file diff --git a/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateAddressingCard.vue b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateAddressingCard.vue new file mode 100644 index 00000000..2c99cae8 --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateAddressingCard.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateSettingsCard.vue b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateSettingsCard.vue new file mode 100644 index 00000000..3f38f6dc --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateSettingsCard.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateUserCard.vue b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateUserCard.vue new file mode 100644 index 00000000..a8834634 --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceCreateUserCard.vue @@ -0,0 +1,144 @@ + + + + + \ No newline at end of file diff --git a/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceTransactionsCard.vue b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceTransactionsCard.vue new file mode 100644 index 00000000..22e9c5d2 --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/create/InvoiceTransactionsCard.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceAmountForm.vue b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceAmountForm.vue new file mode 100644 index 00000000..ebb03977 --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceAmountForm.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceAddressingForm.vue b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceBaseAddressingForm.vue similarity index 75% rename from apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceAddressingForm.vue rename to apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceBaseAddressingForm.vue index eaf9b2ea..670cae98 100644 --- a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceAddressingForm.vue +++ b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceBaseAddressingForm.vue @@ -46,28 +46,15 @@ + \ No newline at end of file diff --git a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceBaseSettingsForm.vue b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceBaseSettingsForm.vue new file mode 100644 index 00000000..ef44d942 --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceBaseSettingsForm.vue @@ -0,0 +1,51 @@ + + + + + \ No newline at end of file diff --git a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceSettingsForm.vue b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceSettingsForm.vue index 15c74eda..ee6a72d8 100644 --- a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceSettingsForm.vue +++ b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceSettingsForm.vue @@ -1,30 +1,8 @@ + + diff --git a/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceUpdateAddressingForm.vue b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceUpdateAddressingForm.vue new file mode 100644 index 00000000..a8ad9e42 --- /dev/null +++ b/apps/dashboard/src/modules/financial/components/invoice/forms/InvoiceUpdateAddressingForm.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/apps/dashboard/src/modules/financial/components/payout/forms/PayoutCreateForm.vue b/apps/dashboard/src/modules/financial/components/payout/forms/PayoutCreateForm.vue index 09cc98bf..86b1caf8 100644 --- a/apps/dashboard/src/modules/financial/components/payout/forms/PayoutCreateForm.vue +++ b/apps/dashboard/src/modules/financial/components/payout/forms/PayoutCreateForm.vue @@ -4,8 +4,9 @@ :value="form.model.user.value.value" @update:value="form.context.setFieldValue('user', $event)" :errors="form.context.errors.value.user" - id="name" placeholder="John Doe" type="text"/> + id="name" placeholder="John Doe"/> +
diff --git a/apps/dashboard/src/modules/financial/routes.ts b/apps/dashboard/src/modules/financial/routes.ts index a4b4e57e..85644125 100644 --- a/apps/dashboard/src/modules/financial/routes.ts +++ b/apps/dashboard/src/modules/financial/routes.ts @@ -5,6 +5,7 @@ import PayoutsView from "@/modules/financial/views/payouts/PayoutsView.vue"; import { UserRole } from "@/utils/rbacUtils"; import InvoiceOverview from "@/modules/financial/views/invoice/InvoiceOverview.vue"; import InvoiceInfoView from "@/modules/financial/views/invoice/InvoiceInfoView.vue"; +import InvoiceCreateView from "@/modules/financial/views/invoice/InvoiceCreateView.vue"; export function financialRoutes(): RouteRecordRaw[] { return [ @@ -14,42 +15,62 @@ export function financialRoutes(): RouteRecordRaw[] { meta: { requiresAuth: true }, children: [ { - path: '/fine', - component: FineView, - name: 'fine', - meta: { - requiresAuth: true, - rolesAllowed: [UserRole.BAC_PM] - } - }, - { - path: '/invoice', - component: InvoiceOverview, - name: 'invoice', - meta: { - requiresAuth: true, - rolesAllowed: [UserRole.BAC_PM] - } - }, - { - path: '/invoice/:id/info', - name: 'invoiceInfo', - component: InvoiceInfoView, - props: true, - meta: { - requiresAuth: true, - rolesAllowed: [UserRole.BAC_PM] - } - }, - { - path: '/payouts', - component: PayoutsView, - name: 'payouts', - meta: { - requiresAuth: true, - rolesAllowed: [UserRole.BAC_PM] + path: '/fine', + component: FineView, + name: 'fine', + meta: { + requiresAuth: true, + rolesAllowed: [UserRole.BAC_PM] + } + }, + { + path: '/invoice', + component: InvoiceOverview, + name: 'invoice', + meta: { + requiresAuth: true, + rolesAllowed: [UserRole.BAC_PM] + } + }, + { + path: '/invoice/create', + component: InvoiceCreateView, + name: 'invoiceCreate', + meta: { + requiresAuth: true, + rolesAllowed: [UserRole.BAC_PM] + } + }, + { + path: '/invoice/:id', + redirect: to => { + const { id } = to.params; + return `/invoice/${id}/info`; + }, + meta: { + requiresAuth: true, + rolesAllowed: [UserRole.BAC_PM] + } + }, + { + path: '/invoice/:id/info', + name: 'invoiceInfo', + component: InvoiceInfoView, + props: true, + meta: { + requiresAuth: true, + rolesAllowed: [UserRole.BAC_PM] + } + }, + { + path: '/payouts', + component: PayoutsView, + name: 'payouts', + meta: { + requiresAuth: true, + rolesAllowed: [UserRole.BAC_PM] + } } - } ] } ]; diff --git a/apps/dashboard/src/modules/financial/views/FineView.vue b/apps/dashboard/src/modules/financial/views/FineView.vue index 559636f6..578469e4 100644 --- a/apps/dashboard/src/modules/financial/views/FineView.vue +++ b/apps/dashboard/src/modules/financial/views/FineView.vue @@ -205,7 +205,7 @@ const handlePickedDates = handleSubmit(async (values) => { [values.firstDate.toISOString(), values.secondDate.toISOString()], ["MEMBER"]); const userFullNameMap: { [key: number]: string } = {}; - userStore.users.forEach((user: any) => { + Object.values(userStore.users).forEach((user: any) => { userFullNameMap[user.id] = `${user.firstName} ${user.lastName}`; }); const deletedUsers = userStore.getDeletedUsers.map((u: UserResponse) => u.id); diff --git a/apps/dashboard/src/modules/financial/views/invoice/InvoiceCreateView.vue b/apps/dashboard/src/modules/financial/views/invoice/InvoiceCreateView.vue new file mode 100644 index 00000000..80517a68 --- /dev/null +++ b/apps/dashboard/src/modules/financial/views/invoice/InvoiceCreateView.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/apps/dashboard/src/modules/financial/views/invoice/InvoiceInfoView.vue b/apps/dashboard/src/modules/financial/views/invoice/InvoiceInfoView.vue index a1726401..4959a980 100644 --- a/apps/dashboard/src/modules/financial/views/invoice/InvoiceInfoView.vue +++ b/apps/dashboard/src/modules/financial/views/invoice/InvoiceInfoView.vue @@ -3,15 +3,20 @@
- {{ isCredit ? t("modules.financial.invoice.credit") : t("modules.financial.invoice.invoice") }} + {{ t("modules.financial.invoice.invoice") }} {{ invoice.reference + ": " }} {{ invoice.description }} + + + {{ t("modules.financial.invoice.dirty") }} +
- + + @@ -39,19 +44,18 @@ import InvoiceStepsCard from "@/modules/financial/components/invoice/InvoiceStep import InvoicePdf from "@/modules/financial/components/invoice/InvoicePdf.vue"; import InvoiceInfo from "@/modules/financial/components/invoice/InvoiceInfo.vue"; import { useI18n } from "vue-i18n"; +import InvoiceAmountCard from "@/modules/financial/components/invoice/InvoiceAmountCard.vue"; +import { isDirty } from "@/utils/invoiceUtil"; const { t } = useI18n(); - const toast = useToast(); const route = useRoute(); +const invoiceStore = useInvoiceStore(); const invoice: Ref = ref(undefined); -const invoiceStore = useInvoiceStore(); -const isCredit = computed(() => { - if (!invoice.value) return false; - return invoice.value?.transfer?.to === undefined; -}); +// Invoice is considered dirty if entry total does not match transfer total +const dirty = computed(() => isDirty(invoice.value as InvoiceResponse)); onBeforeMount(async () => { const id = Number(route.params.id); diff --git a/apps/dashboard/src/modules/financial/views/invoice/InvoiceOverview.vue b/apps/dashboard/src/modules/financial/views/invoice/InvoiceOverview.vue index b2a02984..951dfeba 100644 --- a/apps/dashboard/src/modules/financial/views/invoice/InvoiceOverview.vue +++ b/apps/dashboard/src/modules/financial/views/invoice/InvoiceOverview.vue @@ -1,7 +1,17 @@