From 335ff4df6059a1b357801e8cd22bb9cd982ccb0c Mon Sep 17 00:00:00 2001 From: Thijn Date: Wed, 4 Dec 2024 14:27:08 +0100 Subject: [PATCH 01/68] PC108-73: person widget is by default empty --- src/views/widgets/PersonenWidget.vue | 57 +++++++++++----------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/src/views/widgets/PersonenWidget.vue b/src/views/widgets/PersonenWidget.vue index 61ff41d..a7159b8 100644 --- a/src/views/widgets/PersonenWidget.vue +++ b/src/views/widgets/PersonenWidget.vue @@ -5,16 +5,22 @@ import { klantStore, navigationStore } from '../../store/store.js' @@ -50,7 +51,7 @@ import { NcDashboardWidget, NcEmptyContent, NcButton, NcTextField } from '@nextc import { getTheme } from '../../services/getTheme.js' import Search from 'vue-material-design-icons/Magnify.vue' import OfficeBuildingOutline from 'vue-material-design-icons/OfficeBuildingOutline.vue' -import ViewKlantRegister from '../../modals/klantRegister/ViewKlantRegister.vue' +import ViewKlant from '../../modals/klanten/ViewKlant.vue' export default { name: 'OrganisatiesWidget', @@ -62,7 +63,7 @@ export default { Search, NcTextField, OfficeBuildingOutline, - ViewKlantRegister, + ViewKlant, }, data() { @@ -136,7 +137,7 @@ export default { onShow(item) { klantStore.setWidgetKlantId(item.id) this.isModalOpen = true - navigationStore.setModal('viewKlantRegister') + navigationStore.setModal('viewKlant') }, diff --git a/src/views/widgets/PersonenWidget.vue b/src/views/widgets/PersonenWidget.vue index 61ff41d..f8abb96 100644 --- a/src/views/widgets/PersonenWidget.vue +++ b/src/views/widgets/PersonenWidget.vue @@ -36,10 +36,11 @@ import { klantStore, navigationStore } from '../../store/store.js' Zoeken - + @save-success="fetchPersonenItems" + @close-modal="() => (isModalOpen = false)" /> @@ -50,7 +51,7 @@ import { NcDashboardWidget, NcEmptyContent, NcButton, NcTextField } from '@nextc import { getTheme } from '../../services/getTheme.js' import Search from 'vue-material-design-icons/Magnify.vue' import AccountOutline from 'vue-material-design-icons/AccountOutline.vue' -import ViewKlantRegister from '../../modals/klantRegister/ViewKlantRegister.vue' +import ViewKlant from '../../modals/klanten/ViewKlant.vue' export default { name: 'PersonenWidget', @@ -62,7 +63,7 @@ export default { Search, NcTextField, AccountOutline, - ViewKlantRegister, + ViewKlant, }, data() { @@ -134,9 +135,8 @@ export default { }, onShow(item) { klantStore.setWidgetKlantId(item.id) - this.isModalOpen = true - navigationStore.setModal('viewKlantRegister') + navigationStore.setModal('viewKlant') }, }, From 53c68f984c38d8a550ceac153ce258b0f4a7b736 Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 17 Dec 2024 14:40:00 +0100 Subject: [PATCH 04/68] finished frontend resultaten --- src/entities/index.js | 1 + src/entities/resultaat/index.js | 3 + src/entities/resultaat/resultaat.mock.ts | 14 ++ src/entities/resultaat/resultaat.spec.ts | 12 ++ src/entities/resultaat/resultaat.ts | 32 ++++ src/entities/resultaat/resultaat.types.ts | 7 + src/modals/Modals.vue | 7 + src/modals/resultaten/DeleteResultaat.vue | 109 ++++++++++++ src/modals/resultaten/ResultaatForm.vue | 194 ++++++++++++++++++++++ src/store/modules/resultaten.spec.ts | 36 ++++ src/store/modules/resultaten.ts | 174 +++++++++++++++++++ src/store/store.js | 4 + src/views/resultaten/ZaakResultaten.vue | 136 +++++++++++++++ src/views/zaken/ZaakDetails.vue | 14 +- 14 files changed, 742 insertions(+), 1 deletion(-) create mode 100644 src/entities/resultaat/index.js create mode 100644 src/entities/resultaat/resultaat.mock.ts create mode 100644 src/entities/resultaat/resultaat.spec.ts create mode 100644 src/entities/resultaat/resultaat.ts create mode 100644 src/entities/resultaat/resultaat.types.ts create mode 100644 src/modals/resultaten/DeleteResultaat.vue create mode 100644 src/modals/resultaten/ResultaatForm.vue create mode 100644 src/store/modules/resultaten.spec.ts create mode 100644 src/store/modules/resultaten.ts create mode 100644 src/views/resultaten/ZaakResultaten.vue diff --git a/src/entities/index.js b/src/entities/index.js index 0b8f0bc..188ecbe 100644 --- a/src/entities/index.js +++ b/src/entities/index.js @@ -7,3 +7,4 @@ export * from './bericht/index.js' export * from './rol/index.js' export * from './medewerkers/index.js' export * from './contactmoment/index.js' +export * from './resultaat/index.js' diff --git a/src/entities/resultaat/index.js b/src/entities/resultaat/index.js new file mode 100644 index 0000000..018cfaa --- /dev/null +++ b/src/entities/resultaat/index.js @@ -0,0 +1,3 @@ +export * from './resultaat.ts' +export * from './resultaat.types.ts' +export * from './resultaat.mock.ts' diff --git a/src/entities/resultaat/resultaat.mock.ts b/src/entities/resultaat/resultaat.mock.ts new file mode 100644 index 0000000..a0e50ba --- /dev/null +++ b/src/entities/resultaat/resultaat.mock.ts @@ -0,0 +1,14 @@ +import { Resultaat } from './resultaat' +import { TResultaat } from './resultaat.types' + +export const mockResultaatData = (): TResultaat[] => [ + { + id: '15551d6f-44e3-43f3-a9d2-59e583c91eb0', + url: 'https://api.example.com/resultaten/15551d6f-44e3-43f3-a9d2-59e583c91eb0', + zaak: '15551d6f-44e3-43f3-a9d2-59e583c91eb0', + resultaattype: 'Audit', + toelichting: 'Deze taak omvat het uitvoeren van een gedetailleerde interne audit van de bedrijfsprocessen om te controleren of alle afdelingen voldoen aan de vastgestelde kwaliteitsnormen. De bevindingen worden gedocumenteerd en er worden aanbevelingen gedaan voor verbeteringen.', + }, +] + +export const mockResultaat = (data: TResultaat[] = mockResultaatData()): TResultaat[] => data.map(item => new Resultaat(item)) diff --git a/src/entities/resultaat/resultaat.spec.ts b/src/entities/resultaat/resultaat.spec.ts new file mode 100644 index 0000000..5d402d4 --- /dev/null +++ b/src/entities/resultaat/resultaat.spec.ts @@ -0,0 +1,12 @@ +import { Resultaat } from './resultaat' +import { mockResultaatData } from './resultaat.mock' + +describe('Resultaat Entity', () => { + it('should create a Resultaat entity with full data', () => { + const resultaat = new Resultaat(mockResultaatData()[0]) + + expect(resultaat).toBeInstanceOf(Resultaat) + expect(resultaat).toEqual(mockResultaatData()[0]) + expect(resultaat.validate().success).toBe(true) + }) +}) diff --git a/src/entities/resultaat/resultaat.ts b/src/entities/resultaat/resultaat.ts new file mode 100644 index 0000000..2a050bc --- /dev/null +++ b/src/entities/resultaat/resultaat.ts @@ -0,0 +1,32 @@ +import { SafeParseReturnType, z } from 'zod' +import { TResultaat } from './resultaat.types' + +export class Resultaat implements TResultaat { + + public id: string + public url: string + public zaak: string + public resultaattype: string + public toelichting: string + + constructor(source: TResultaat) { + this.id = source.id || '' + this.url = source.url || '' + this.zaak = source.zaak || '' + this.resultaattype = source.resultaattype || '' + this.toelichting = source.toelichting || '' + } + + public validate(): SafeParseReturnType { + const schema = z.object({ + id: z.string(), + url: z.string(), + zaak: z.string(), + resultaattype: z.string(), + toelichting: z.string(), + }) + + return schema.safeParse(this) + } + +} diff --git a/src/entities/resultaat/resultaat.types.ts b/src/entities/resultaat/resultaat.types.ts new file mode 100644 index 0000000..87ab98f --- /dev/null +++ b/src/entities/resultaat/resultaat.types.ts @@ -0,0 +1,7 @@ +export type TResultaat = { + id: string; + url: string; + zaak: string; + resultaattype: string; + toelichting: string; +} diff --git a/src/modals/Modals.vue b/src/modals/Modals.vue index 75895c0..ab355e9 100644 --- a/src/modals/Modals.vue +++ b/src/modals/Modals.vue @@ -32,6 +32,9 @@ import { navigationStore } from '../store/store.js' + + + @@ -55,6 +58,8 @@ import AddBerichtToZaak from './zaken/AddBerichtToZaak.vue' import AddTaakToZaak from './zaken/AddTaakToZaak.vue' import ContactMomentenForm from './contactMomenten/ContactMomentenForm.vue' import AddRolToZaak from './zaken/AddRolToZaak.vue' +import ResultaatForm from './resultaten/ResultaatForm.vue' +import DeleteResultaat from './resultaten/DeleteResultaat.vue' export default { name: 'Modals', @@ -78,6 +83,8 @@ export default { AddTaakToZaak, ContactMomentenForm, AddRolToZaak, + ResultaatForm, + DeleteResultaat, }, } diff --git a/src/modals/resultaten/DeleteResultaat.vue b/src/modals/resultaten/DeleteResultaat.vue new file mode 100644 index 0000000..3056cd5 --- /dev/null +++ b/src/modals/resultaten/DeleteResultaat.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/src/modals/resultaten/ResultaatForm.vue b/src/modals/resultaten/ResultaatForm.vue new file mode 100644 index 0000000..9b46315 --- /dev/null +++ b/src/modals/resultaten/ResultaatForm.vue @@ -0,0 +1,194 @@ + + + + + + + diff --git a/src/store/modules/resultaten.spec.ts b/src/store/modules/resultaten.spec.ts new file mode 100644 index 0000000..c797683 --- /dev/null +++ b/src/store/modules/resultaten.spec.ts @@ -0,0 +1,36 @@ +/* eslint-disable no-console */ +import { setActivePinia, createPinia } from 'pinia' + +import { useZaakStore } from './zaken.js' +import { Zaak, mockZaak } from '../../entities/index.js' + +describe('Zaak Store', () => { + beforeEach(() => { + setActivePinia(createPinia()) + }) + + it('sets zaak item correctly', () => { + const store = useZaakStore() + + store.setZaakItem(mockZaak()[0]) + + expect(store.zaakItem).toBeInstanceOf(Zaak) + expect(store.zaakItem).toEqual(mockZaak()[0]) + + expect(store.zaakItem.validate().success).toBe(true) + }) + + it('sets zaken list correctly', () => { + const store = useZaakStore() + + store.setZakenList(mockZaak()) + + expect(store.zakenList).toHaveLength(mockZaak().length) + + store.zakenList.forEach((item, index) => { + expect(item).toBeInstanceOf(Zaak) + expect(item).toEqual(mockZaak()[index]) + expect(item.validate().success).toBe(true) + }) + }) +}) diff --git a/src/store/modules/resultaten.ts b/src/store/modules/resultaten.ts new file mode 100644 index 0000000..1262119 --- /dev/null +++ b/src/store/modules/resultaten.ts @@ -0,0 +1,174 @@ +import { defineStore } from 'pinia' +import { TResultaat, Resultaat } from '../../entities/index.js' + +const apiEndpoint = '/index.php/apps/zaakafhandelapp/api/zrc/resultaten' + +type TOptions = { + /** + * Save the resultaat item to the store in 'resultaatItem' + */ + setItem?: boolean +} + +export const useResultaatStore = defineStore('resultaten', { + state: () => ({ + resultaatItem: null, + resultatenList: [], + /** + * Set the zaakId, used when creating a new resultaat on a zaak. + */ + zaakId: null, + }), + actions: { + setResultaatItem(resultaatItem: Resultaat | TResultaat) { + this.resultaatItem = resultaatItem && new Resultaat(resultaatItem) + console.info('Active resultaat item set to ' + resultaatItem) + }, + setResultatenList(resultatenList: Resultaat[] | TResultaat[]) { + this.resultatenList = resultatenList.map( + (resultaatItem) => new Resultaat(resultaatItem), + ) + console.info('Resultaten list set to ' + resultatenList.length + ' items') + }, + /** + * Refresh the list of resultaten items. + * + * @param search - Optional search query to filter the resultaten list. (default: `null`) + * @throws If the HTTP request fails. + * @return { Promise<{ response: Response, data: TResultaat[], entities: Resultaat[] }> } The response, raw data, and entities. + */ + async refreshResultatenList(search: string = null): Promise<{ response: Response, data: TResultaat[], entities: Resultaat[] }> { + let endpoint = apiEndpoint + + if (search !== null && search !== '') { + endpoint = endpoint + '?_search=' + search + } + + console.info('Refreshing resultaten list with search: ' + search) + + const response = await fetch(endpoint, { + method: 'GET', + }) + + if (!response.ok) { + console.error(response) + throw new Error(`HTTP error! status: ${response.status}`) + } + + const data = (await response.json()).results as TResultaat[] + const entities = data.map((resultaatItem: TResultaat) => new Resultaat(resultaatItem)) + + this.setResultatenList(data) + + return { response, data, entities } + }, + /** + * Fetch a single resultaat item by its ID. + * + * @param id - The ID of the resultaat item to fetch. + * @param options - Options for fetching the resultaat item. (default: `{}`) + * @throws If the HTTP request fails. + * @return { Promise<{ response: Response, data: TResultaat, entity: Resultaat }> } The response, raw data, and entity. + */ + async getResultaat( + id: string, + options: TOptions = {}, + ): Promise<{ response: Response, data: TResultaat, entity: Resultaat }> { + const endpoint = `${apiEndpoint}/${id}` + + console.info('Fetching resultaat item with id: ' + id) + + const response = await fetch(endpoint, { + method: 'GET', + }) + + if (!response.ok) { + console.error(response) + throw new Error(`HTTP error! status: ${response.status}`) + } + + const data = await response.json() + const entity = new Resultaat(data) + + options.setItem && this.setResultaatItem(data) + + return { response, data, entity } + }, + /** + * Delete a resultaat item from the store. + * + * @param resultaatItem - The resultaat item to delete. + * @throws If the HTTP request fails. + * @return {Promise<{ response: Response }>} The response from the delete request. + */ + async deleteResultaat(resultaatItem: Resultaat | TResultaat): Promise<{ response: Response }> { + if (!resultaatItem) { + throw new Error('No resultaat item to delete') + } + if (!resultaatItem.id) { + throw new Error('No id for resultaat item to delete') + } + + const endpoint = `${apiEndpoint}/${resultaatItem.id}` + + console.info('Deleting resultaat item with id: ' + resultaatItem.id) + + const response = await fetch(endpoint, { + method: 'DELETE', + }) + + this.refreshResultatenList() + + return { response } + }, + /** + * Save a resultaat item to the store. If the resultaat item does not have a uuid, it will be created. + * Otherwise, it will be updated. + * + * @param resultaatItem - The resultaat item to save. + * @param options - Options for saving the resultaat item. (default: `{ setItem: true }`) + * @throws If there is no resultaat item to save or if the HTTP request fails. + * @return {Promise<{ response: Response, data: TResultaat, entity: Resultaat }>} The response, raw data, and entity. + */ + async saveResultaat( + resultaatItem: Resultaat | TResultaat, + options: TOptions = { setItem: true }, + ): Promise<{ response: Response, data: TResultaat, entity: Resultaat }> { + if (!resultaatItem) { + throw new Error('No resultaat item to save') + } + + const isNewResultaat = !resultaatItem?.id + const endpoint = isNewResultaat + ? `${apiEndpoint}` + : `${apiEndpoint}/${resultaatItem?.id}` + const method = isNewResultaat ? 'POST' : 'PUT' + + console.info('Saving resultaat item with id: ' + resultaatItem?.id) + + const response = await fetch( + endpoint, + { + method, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(resultaatItem), + }, + ) + + if (!response.ok) { + console.error(response) + throw new Error(response.statusText || 'Failed to save resultaat') + } + + const data = await response.json() as TResultaat + const entity = new Resultaat(data) + + options.setItem && this.setResultaatItem(data) + this.refreshResultatenList() + + return { response, data, entity } + }, + }, +}) diff --git a/src/store/store.js b/src/store/store.js index 8734fa1..c73b63d 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -10,6 +10,7 @@ import { useTaakStore } from './modules/taak.js' import { useSearchStore } from './modules/search.ts' import { useContactMomentStore } from './modules/contactmoment.ts' import { useMedewerkerStore } from './modules/medewerkers.js' +import { useResultaatStore } from './modules/resultaten.ts' const berichtStore = useBerichtStore(pinia) const klantStore = useKlantStore(pinia) @@ -21,6 +22,8 @@ const zaakTypeStore = useZaakTypeStore(pinia) const searchStore = useSearchStore(pinia) const contactMomentStore = useContactMomentStore(pinia) const medewerkerStore = useMedewerkerStore(pinia) +const resultaatStore = useResultaatStore(pinia) + export { berichtStore, klantStore, @@ -32,4 +35,5 @@ export { searchStore, contactMomentStore, medewerkerStore, + resultaatStore, } diff --git a/src/views/resultaten/ZaakResultaten.vue b/src/views/resultaten/ZaakResultaten.vue new file mode 100644 index 0000000..ed39e4b --- /dev/null +++ b/src/views/resultaten/ZaakResultaten.vue @@ -0,0 +1,136 @@ + + + + + + diff --git a/src/views/zaken/ZaakDetails.vue b/src/views/zaken/ZaakDetails.vue index 48703ca..8826c06 100644 --- a/src/views/zaken/ZaakDetails.vue +++ b/src/views/zaken/ZaakDetails.vue @@ -1,5 +1,5 @@ Status wijzigen + + + Resultaat toevoegen + @@ -116,6 +122,9 @@ import { navigationStore, zaakStore } from '../../store/store.js' + + + @@ -188,6 +197,7 @@ import FileDocumentPlusOutline from 'vue-material-design-icons/FileDocumentPlusO import VectorPolylineEdit from 'vue-material-design-icons/VectorPolylineEdit.vue' import Eye from 'vue-material-design-icons/Eye.vue' import TimelineQuestionOutline from 'vue-material-design-icons/TimelineQuestionOutline.vue' +import FileChartCheckOutline from 'vue-material-design-icons/FileChartCheckOutline.vue' // Views import ZaakEigenschappen from '../eigenschappen/ZaakEigenschappen.vue' @@ -197,6 +207,7 @@ import ZaakTaken from '../taken/ZaakTaken.vue' import ZaakBesluiten from '../besluiten/ZaakBesluiten.vue' import ZaakDocumenten from '../documenten/ZaakDocumenten.vue' import ZakenZaken from '../zaken/ZakenZaken.vue' +import ZaakResultaten from '../resultaten/ZaakResultaten.vue' export default { name: 'ZaakDetails', @@ -214,6 +225,7 @@ export default { ZaakBesluiten, ZaakDocumenten, ZakenZaken, + ZaakResultaten, // Icons DotsHorizontal, Pencil, From 43fda4d87b967d3bcc70c7b3b24c991f6454f5a7 Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 17 Dec 2024 19:51:01 +0100 Subject: [PATCH 05/68] WIP - working on besluit for zaken --- src/entities/besluit/besluit.mock.ts | 12 ++ src/entities/besluit/besluit.spec.ts | 12 ++ src/entities/besluit/besluit.ts | 26 +++ src/entities/besluit/besluit.types.ts | 5 + src/entities/besluit/index.js | 3 + src/entities/index.js | 1 + src/modals/Modals.vue | 7 + src/modals/besluiten/BesluitForm.vue | 214 +++++++++++++++++++++++++ src/modals/besluiten/DeleteBesluit.vue | 107 +++++++++++++ src/store/modules/besluiten.spec.ts | 22 +++ src/store/modules/besluiten.ts | 176 ++++++++++++++++++++ src/store/store.js | 3 + src/views/besluiten/ZaakBesluiten.vue | 92 ++++++----- src/views/zaken/ZaakDetails.vue | 10 +- 14 files changed, 647 insertions(+), 43 deletions(-) create mode 100644 src/entities/besluit/besluit.mock.ts create mode 100644 src/entities/besluit/besluit.spec.ts create mode 100644 src/entities/besluit/besluit.ts create mode 100644 src/entities/besluit/besluit.types.ts create mode 100644 src/entities/besluit/index.js create mode 100644 src/modals/besluiten/BesluitForm.vue create mode 100644 src/modals/besluiten/DeleteBesluit.vue create mode 100644 src/store/modules/besluiten.spec.ts create mode 100644 src/store/modules/besluiten.ts diff --git a/src/entities/besluit/besluit.mock.ts b/src/entities/besluit/besluit.mock.ts new file mode 100644 index 0000000..4e04e92 --- /dev/null +++ b/src/entities/besluit/besluit.mock.ts @@ -0,0 +1,12 @@ +import { Besluit } from './besluit' +import { TBesluit } from './besluit.types' + +export const mockBesluitData = (): TBesluit[] => [ + { + id: '15551d6f-44e3-43f3-a9d2-59e583c91eb0', + url: 'https://api.example.com/besluiten/15551d6f-44e3-43f3-a9d2-59e583c91eb0', + besluit: 'dsadsadasdasdadfas', + }, +] + +export const mockBesluit = (data: TBesluit[] = mockBesluitData()): TBesluit[] => data.map(item => new Besluit(item)) diff --git a/src/entities/besluit/besluit.spec.ts b/src/entities/besluit/besluit.spec.ts new file mode 100644 index 0000000..6d21b16 --- /dev/null +++ b/src/entities/besluit/besluit.spec.ts @@ -0,0 +1,12 @@ +import { Besluit } from './besluit' +import { mockBesluitData } from './besluit.mock' + +describe('Besluit Entity', () => { + it('should create a Besluit entity with full data', () => { + const besluit = new Besluit(mockBesluitData()[0]) + + expect(besluit).toBeInstanceOf(Besluit) + expect(besluit).toEqual(mockBesluitData()[0]) + expect(besluit.validate().success).toBe(true) + }) +}) diff --git a/src/entities/besluit/besluit.ts b/src/entities/besluit/besluit.ts new file mode 100644 index 0000000..08d5fb7 --- /dev/null +++ b/src/entities/besluit/besluit.ts @@ -0,0 +1,26 @@ +import { SafeParseReturnType, z } from 'zod' +import { TBesluit } from './besluit.types' + +export class Besluit implements TBesluit { + + public id: string + public url: string + public besluit: string + + constructor(source: TBesluit) { + this.id = source.id || '' + this.url = source.url || '' + this.besluit = source.besluit || '' + } + + public validate(): SafeParseReturnType { + const schema = z.object({ + id: z.string(), + url: z.string(), + besluit: z.string(), + }) + + return schema.safeParse(this) + } + +} diff --git a/src/entities/besluit/besluit.types.ts b/src/entities/besluit/besluit.types.ts new file mode 100644 index 0000000..2be07f8 --- /dev/null +++ b/src/entities/besluit/besluit.types.ts @@ -0,0 +1,5 @@ +export type TBesluit = { + id: string; + url: string; + besluit: string; +} diff --git a/src/entities/besluit/index.js b/src/entities/besluit/index.js new file mode 100644 index 0000000..27a05c3 --- /dev/null +++ b/src/entities/besluit/index.js @@ -0,0 +1,3 @@ +export * from './besluit.ts' +export * from './besluit.types.ts' +export * from './besluit.mock.ts' diff --git a/src/entities/index.js b/src/entities/index.js index 188ecbe..4ba60de 100644 --- a/src/entities/index.js +++ b/src/entities/index.js @@ -8,3 +8,4 @@ export * from './rol/index.js' export * from './medewerkers/index.js' export * from './contactmoment/index.js' export * from './resultaat/index.js' +export * from './besluit/index.js' diff --git a/src/modals/Modals.vue b/src/modals/Modals.vue index ab355e9..9703b6d 100644 --- a/src/modals/Modals.vue +++ b/src/modals/Modals.vue @@ -35,6 +35,9 @@ import { navigationStore } from '../store/store.js' + + + @@ -60,6 +63,8 @@ import ContactMomentenForm from './contactMomenten/ContactMomentenForm.vue' import AddRolToZaak from './zaken/AddRolToZaak.vue' import ResultaatForm from './resultaten/ResultaatForm.vue' import DeleteResultaat from './resultaten/DeleteResultaat.vue' +import BesluitForm from './besluiten/BesluitForm.vue' +import DeleteBesluit from './besluiten/DeleteBesluit.vue' export default { name: 'Modals', @@ -85,6 +90,8 @@ export default { AddRolToZaak, ResultaatForm, DeleteResultaat, + BesluitForm, + DeleteBesluit, }, } diff --git a/src/modals/besluiten/BesluitForm.vue b/src/modals/besluiten/BesluitForm.vue new file mode 100644 index 0000000..07d1ca4 --- /dev/null +++ b/src/modals/besluiten/BesluitForm.vue @@ -0,0 +1,214 @@ + + + + + + + diff --git a/src/modals/besluiten/DeleteBesluit.vue b/src/modals/besluiten/DeleteBesluit.vue new file mode 100644 index 0000000..ec0aa11 --- /dev/null +++ b/src/modals/besluiten/DeleteBesluit.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/src/store/modules/besluiten.spec.ts b/src/store/modules/besluiten.spec.ts new file mode 100644 index 0000000..551872f --- /dev/null +++ b/src/store/modules/besluiten.spec.ts @@ -0,0 +1,22 @@ +/* eslint-disable no-console */ +import { setActivePinia, createPinia } from 'pinia' + +import { useBesluitStore } from './besluiten.js' +import { Besluit, mockBesluit } from '../../entities/index.js' + +describe('Besluit Store', () => { + beforeEach(() => { + setActivePinia(createPinia()) + }) + + it('sets besluit item correctly', () => { + const store = useBesluitStore() + + store.setBesluitItem(mockBesluit()[0]) + + expect(store.besluitItem).toBeInstanceOf(Besluit) + expect(store.besluitItem).toEqual(mockBesluit()[0]) + + expect(store.besluitItem.validate().success).toBe(true) + }) +}) diff --git a/src/store/modules/besluiten.ts b/src/store/modules/besluiten.ts new file mode 100644 index 0000000..99c7cc1 --- /dev/null +++ b/src/store/modules/besluiten.ts @@ -0,0 +1,176 @@ +import { defineStore } from 'pinia' +import { TBesluit, Besluit } from '../../entities/index.js' + +const getApiEndpoint = (zaakId: string) => `/index.php/apps/zaakafhandelapp/api/zrc/zaken/${zaakId}/besluiten` + +type TOptions = { + /** + * Save the besluit item to the store in 'besluitItem' + */ + setItem?: boolean +} + +export const useBesluitStore = defineStore('besluiten', { + state: () => ({ + besluitItem: null, + zaakId: null, + }), + actions: { + setBesluitItem(besluitItem: Besluit | TBesluit) { + this.besluitItem = besluitItem && new Besluit(besluitItem) + console.info('Active besluit item set to ' + besluitItem) + }, + /** + * Fetch a single besluit item by its ID. + * + * @param zaakId - The ID of the zaak the besluit belongs to + * @param id - The ID of the besluit item to fetch. + * @param options - Options for fetching the besluit item. (default: `{}`) + * @throws If the HTTP request fails. + * @return { Promise<{ response: Response, data: TBesluit, entity: Besluit }> } The response, raw data, and entity. + */ + async getBesluit( + zaakId: string, + id: string, + options: TOptions = {}, + ): Promise<{ response: Response, data: TBesluit, entity: Besluit }> { + const endpoint = `${getApiEndpoint(zaakId)}/${id}` + + console.info('Fetching besluit item with id: ' + id + ' from zaak: ' + zaakId) + + const response = await fetch(endpoint, { + method: 'GET', + }) + + if (!response.ok) { + console.error(response) + throw new Error(`HTTP error! status: ${response.status}`) + } + + const data = await response.json() + const entity = new Besluit(data) + + options.setItem && this.setBesluitItem(data) + + return { response, data, entity } + }, + /** + * Fetch all besluiten for a zaak. + * + * @param zaakId - The ID of the zaak to fetch besluiten for + * @throws If the HTTP request fails. + * @return { Promise<{ response: Response, data: TBesluit[], entities: Besluit[] }> } The response, raw data array, and entity array. + */ + async getBesluiten( + zaakId: string, + ): Promise<{ response: Response, data: TBesluit[], entities: Besluit[] }> { + const endpoint = getApiEndpoint(zaakId) + + console.info('Fetching besluiten for zaak: ' + zaakId) + + const response = await fetch(endpoint, { + method: 'GET', + }) + + if (!response.ok) { + console.error(response) + throw new Error(`HTTP error! status: ${response.status}`) + } + + const _data = (await response.json()).results as { [key: string]: TBesluit } + + /* + As of now (17/12/2024) the data gets send back in this format + { + "results": { + "5137a1e5-b54d-43ad-abd1-4b5bff5fcd3f": { + "id": "5137a1e5-b54d-43ad-abd1-4b5bff5fcd3f", + "name": "Zaakt type 1", + "summary": "summary for one" + }, + } + } + Instead of the expected array of objects. + So some processing is needed to get the data in the expected format. + */ + + const data = Object.values(_data) + const entities = data.map((item: TBesluit) => new Besluit(item)) + + return { response, data, entities } + }, + /** + * Delete a besluit item from the store. + * + * @param zaakId - The ID of the zaak the besluit belongs to + * @param besluitId - The ID of the besluit item to delete. + * @throws If the HTTP request fails. + * @return {Promise<{ response: Response }>} The response from the delete request. + */ + async deleteBesluit(zaakId: string, besluitId: string): Promise<{ response: Response }> { + if (!besluitId) { + throw new Error('No besluit item to delete') + } + + const endpoint = `${getApiEndpoint(zaakId)}/${besluitId}` + + console.info('Deleting besluit item with id: ' + besluitId + ' from zaak: ' + zaakId) + + const response = await fetch(endpoint, { + method: 'DELETE', + }) + + return { response } + }, + /** + * Save a besluit item to the store. If the besluit item does not have a uuid, it will be created. + * Otherwise, it will be updated. + * + * @param zaakId - The ID of the zaak the besluit belongs to + * @param besluitItem - The besluit item to save. + * @param options - Options for saving the besluit item. (default: `{ setItem: true }`) + * @throws If there is no besluit item to save or if the HTTP request fails. + * @return {Promise<{ response: Response, data: TBesluit, entity: Besluit }>} The response, raw data, and entity. + */ + async saveBesluit( + zaakId: string, + besluitItem: Besluit | TBesluit, + options: TOptions = { setItem: true }, + ): Promise<{ response: Response, data: TBesluit, entity: Besluit }> { + if (!besluitItem) { + throw new Error('No besluit item to save') + } + + const isNewBesluit = !besluitItem?.id + const endpoint = isNewBesluit + ? getApiEndpoint(zaakId) + : `${getApiEndpoint(zaakId)}/${besluitItem?.id}` + const method = isNewBesluit ? 'POST' : 'PUT' + + console.info('Saving besluit item with id: ' + besluitItem?.id + ' to zaak: ' + zaakId) + + const response = await fetch( + endpoint, + { + method, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(besluitItem), + }, + ) + + if (!response.ok) { + console.error(response) + throw new Error(response.statusText || 'Failed to save besluit') + } + + const data = await response.json() as TBesluit + const entity = new Besluit(data) + + options.setItem && this.setBesluitItem(data) + + return { response, data, entity } + }, + }, +}) diff --git a/src/store/store.js b/src/store/store.js index c73b63d..d2c2fce 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -11,6 +11,7 @@ import { useSearchStore } from './modules/search.ts' import { useContactMomentStore } from './modules/contactmoment.ts' import { useMedewerkerStore } from './modules/medewerkers.js' import { useResultaatStore } from './modules/resultaten.ts' +import { useBesluitStore } from './modules/besluiten.ts' const berichtStore = useBerichtStore(pinia) const klantStore = useKlantStore(pinia) @@ -23,6 +24,7 @@ const searchStore = useSearchStore(pinia) const contactMomentStore = useContactMomentStore(pinia) const medewerkerStore = useMedewerkerStore(pinia) const resultaatStore = useResultaatStore(pinia) +const besluitStore = useBesluitStore(pinia) export { berichtStore, @@ -36,4 +38,5 @@ export { contactMomentStore, medewerkerStore, resultaatStore, + besluitStore, } diff --git a/src/views/besluiten/ZaakBesluiten.vue b/src/views/besluiten/ZaakBesluiten.vue index e4db490..6ed93b5 100644 --- a/src/views/besluiten/ZaakBesluiten.vue +++ b/src/views/besluiten/ZaakBesluiten.vue @@ -1,41 +1,46 @@ + - - + + + + + + + + + diff --git a/src/modals/klantRegister/ViewKlantRegister.vue b/src/modals/klantRegister/ViewKlantRegister.vue index 074da71..5d75e4d 100644 --- a/src/modals/klantRegister/ViewKlantRegister.vue +++ b/src/modals/klantRegister/ViewKlantRegister.vue @@ -1,437 +1,437 @@ - - - - - - + + + + + + diff --git a/src/modals/klanten/SearchKlantModal.vue b/src/modals/klanten/SearchKlantModal.vue index e18b0c7..6b2d802 100644 --- a/src/modals/klanten/SearchKlantModal.vue +++ b/src/modals/klanten/SearchKlantModal.vue @@ -1,402 +1,402 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/modals/medewerkers/EditMedewerker.vue b/src/modals/medewerkers/EditMedewerker.vue index 563f726..0d0f98b 100644 --- a/src/modals/medewerkers/EditMedewerker.vue +++ b/src/modals/medewerkers/EditMedewerker.vue @@ -1,166 +1,166 @@ - - - - - - - + + + + + + + diff --git a/src/modals/zaakTypen/DeleteZaaktype.vue b/src/modals/zaakTypen/DeleteZaaktype.vue index 514ddbb..fe1edff 100644 --- a/src/modals/zaakTypen/DeleteZaaktype.vue +++ b/src/modals/zaakTypen/DeleteZaaktype.vue @@ -1,98 +1,98 @@ - - - - - + + + + + diff --git a/src/modals/zaakTypen/ZaaktypeForm.vue b/src/modals/zaakTypen/ZaaktypeForm.vue index 38cd3dc..088181d 100644 --- a/src/modals/zaakTypen/ZaaktypeForm.vue +++ b/src/modals/zaakTypen/ZaaktypeForm.vue @@ -1,290 +1,290 @@ - - - - - + + + + + diff --git a/src/modals/zaken/AddBerichtToZaak.vue b/src/modals/zaken/AddBerichtToZaak.vue index fffed4a..4a7849e 100644 --- a/src/modals/zaken/AddBerichtToZaak.vue +++ b/src/modals/zaken/AddBerichtToZaak.vue @@ -1,146 +1,146 @@ - - - - - - - + + + + + + + diff --git a/src/modals/zaken/AddRolToZaak.vue b/src/modals/zaken/AddRolToZaak.vue index b62c9e7..433a6e4 100644 --- a/src/modals/zaken/AddRolToZaak.vue +++ b/src/modals/zaken/AddRolToZaak.vue @@ -1,149 +1,149 @@ - - - - - - - + + + + + + + diff --git a/src/modals/zaken/AddTaakToZaak.vue b/src/modals/zaken/AddTaakToZaak.vue index b9799e1..ec919b5 100644 --- a/src/modals/zaken/AddTaakToZaak.vue +++ b/src/modals/zaken/AddTaakToZaak.vue @@ -1,150 +1,150 @@ - - - - - - - + + + + + + + diff --git a/src/services/icons/icon/icon-calendar-check-outline.js b/src/services/icons/icon/icon-calendar-check-outline.js index 1124ab5..7b1a74c 100644 --- a/src/services/icons/icon/icon-calendar-check-outline.js +++ b/src/services/icons/icon/icon-calendar-check-outline.js @@ -1,13 +1,13 @@ -import { getTheme } from '../../getTheme.js' - -/** - * Returns the correct 'calendar-check-outline' icon based on the theme as a class name. - * - * this class name can be put into a component that accepts an 'icon' prop - * @return {string} - */ -export function iconCalendarCheckOutline() { - const theme = getTheme() - - return theme === 'light' ? 'icon-calendar-check-outline-dark' : 'icon-calendar-check-outline-light' -} +import { getTheme } from '../../getTheme.js' + +/** + * Returns the correct 'calendar-check-outline' icon based on the theme as a class name. + * + * this class name can be put into a component that accepts an 'icon' prop + * @return {string} + */ +export function iconCalendarCheckOutline() { + const theme = getTheme() + + return theme === 'light' ? 'icon-calendar-check-outline-dark' : 'icon-calendar-check-outline-light' +} diff --git a/src/services/icons/icons.css b/src/services/icons/icons.css index 5b381ca..98d9e3f 100644 --- a/src/services/icons/icons.css +++ b/src/services/icons/icons.css @@ -1,23 +1,23 @@ -/* progress close */ -.icon-progress-close-dark { - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHBhdGgNCiAgICAgICAgZD0iTTEzIDIuMDNWNC4wNUMxNy4zOSA0LjU5IDIwLjUgOC41OCAxOS45NiAxMi45N0MxOS41IDE2LjYxIDE2LjY0IDE5LjUgMTMgMTkuOTNWMjEuOTNDMTguNSAyMS4zOCAyMi41IDE2LjUgMjEuOTUgMTFDMjEuNSA2LjI1IDE3LjczIDIuNSAxMyAyLjAzTTExIDIuMDZDOS4wNSAyLjI1IDcuMTkgMyA1LjY3IDQuMjZMNy4xIDUuNzRDOC4yMiA0Ljg0IDkuNTcgNC4yNiAxMSA0LjA2VjIuMDZNNC4yNiA1LjY3QzMgNy4xOSAyLjI1IDkuMDQgMi4wNSAxMUg0LjA1QzQuMjQgOS41OCA0LjggOC4yMyA1LjY5IDcuMUw0LjI2IDUuNjdNMi4wNiAxM0MyLjI2IDE0Ljk2IDMuMDMgMTYuODEgNC4yNyAxOC4zM0w1LjY5IDE2LjlDNC44MSAxNS43NyA0LjI0IDE0LjQyIDQuMDYgMTNIMi4wNk03LjEgMTguMzdMNS42NyAxOS43NEM3LjE4IDIxIDkuMDQgMjEuNzkgMTEgMjJWMjBDOS41OCAxOS44MiA4LjIzIDE5LjI1IDcuMSAxOC4zN00xNC41OSA4TDEyIDEwLjU5TDkuNDEgOEw4IDkuNDFMMTAuNTkgMTJMOCAxNC41OUw5LjQxIDE2TDEyIDEzLjQxTDE0LjU5IDE2TDE2IDE0LjU5TDEzLjQxIDEyTDE2IDkuNDFMMTQuNTkgOFoiDQogICAgICAgIHN0eWxlPSJmaWxsLW9wYWNpdHk6LjU7ZmlsbC1ydWxlOm5vbnplcm8iIGZpbGw9IiMwMDAwMDAiIC8+DQo8L3N2Zz4=); -} -.icon-progress-close-light { - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHBhdGgNCiAgICAgICAgZD0iTTEzIDIuMDNWNC4wNUMxNy4zOSA0LjU5IDIwLjUgOC41OCAxOS45NiAxMi45N0MxOS41IDE2LjYxIDE2LjY0IDE5LjUgMTMgMTkuOTNWMjEuOTNDMTguNSAyMS4zOCAyMi41IDE2LjUgMjEuOTUgMTFDMjEuNSA2LjI1IDE3LjczIDIuNSAxMyAyLjAzTTExIDIuMDZDOS4wNSAyLjI1IDcuMTkgMyA1LjY3IDQuMjZMNy4xIDUuNzRDOC4yMiA0Ljg0IDkuNTcgNC4yNiAxMSA0LjA2VjIuMDZNNC4yNiA1LjY3QzMgNy4xOSAyLjI1IDkuMDQgMi4wNSAxMUg0LjA1QzQuMjQgOS41OCA0LjggOC4yMyA1LjY5IDcuMUw0LjI2IDUuNjdNMi4wNiAxM0MyLjI2IDE0Ljk2IDMuMDMgMTYuODEgNC4yNyAxOC4zM0w1LjY5IDE2LjlDNC44MSAxNS43NyA0LjI0IDE0LjQyIDQuMDYgMTNIMi4wNk03LjEgMTguMzdMNS42NyAxOS43NEM3LjE4IDIxIDkuMDQgMjEuNzkgMTEgMjJWMjBDOS41OCAxOS44MiA4LjIzIDE5LjI1IDcuMSAxOC4zN00xNC41OSA4TDEyIDEwLjU5TDkuNDEgOEw4IDkuNDFMMTAuNTkgMTJMOCAxNC41OUw5LjQxIDE2TDEyIDEzLjQxTDE0LjU5IDE2TDE2IDE0LjU5TDEzLjQxIDEyTDE2IDkuNDFMMTQuNTkgOFoiDQogICAgICAgIHN0eWxlPSJmaWxsLXJ1bGU6bm9uemVybyIgZmlsbD0iI2ZmZmZmZiIgLz4NCjwvc3ZnPg==); -} - -/* pencil */ -.icon-pencil-dark { - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTIwLjcxLDcuMDRDMjEuMSw2LjY1IDIxLjEsNiAyMC43MSw1LjYzTDE4LjM3LDMuMjlDMTgsMi45IDE3LjM1LDIuOSAxNi45NiwzLjI5TDE1LjEyLDUuMTJMMTguODcsOC44N00zLDE3LjI1VjIxSDYuNzVMMTcuODEsOS45M0wxNC4wNiw2LjE4TDMsMTcuMjVaIiAvPjwvc3ZnPg==); -} -.icon-pencil-light { - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTIwLjcxLDcuMDRDMjEuMSw2LjY1IDIxLjEsNiAyMC43MSw1LjYzTDE4LjM3LDMuMjlDMTgsMi45IDE3LjM1LDIuOSAxNi45NiwzLjI5TDE1LjEyLDUuMTJMMTguODcsOC44N00zLDE3LjI1VjIxSDYuNzVMMTcuODEsOS45M0wxNC4wNiw2LjE4TDMsMTcuMjVaIiBmaWxsPSIjZmZmZmZmIiAvPjwvc3ZnPg==); -} - -/* CalendarCheckOutline */ -.icon-calendar-check-outline-dark { - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTE5IDNIMThWMUgxNlYzSDhWMUg2VjNINUMzLjkgMyAzIDMuOSAzIDVWMTlDMyAyMC4xMSAzLjkgMjEgNSAyMUgxOUMyMC4xMSAyMSAyMSAyMC4xMSAyMSAxOVY1QzIxIDMuOSAyMC4xMSAzIDE5IDNNMTkgMTlINVY5SDE5VjE5TTUgN1Y1SDE5VjdINU0xMC41NiAxNy40NkwxNi41IDExLjUzTDE1LjQzIDEwLjQ3TDEwLjU2IDE1LjM0TDguNDUgMTMuMjNMNy4zOSAxNC4yOUwxMC41NiAxNy40NloiIC8+PC9zdmc+); -} -.icon-calendar-check-outline-light { - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTE5IDNIMThWMUgxNlYzSDhWMUg2VjNINUMzLjkgMyAzIDMuOSAzIDVWMTlDMyAyMC4xMSAzLjkgMjEgNSAyMUgxOUMyMC4xMSAyMSAyMSAyMC4xMSAyMSAxOVY1QzIxIDMuOSAyMC4xMSAzIDE5IDNNMTkgMTlINVY5SDE5VjE5TTUgN1Y1SDE5VjdINU0xMC41NiAxNy40NkwxNi41IDExLjUzTDE1LjQzIDEwLjQ3TDEwLjU2IDE1LjM0TDguNDUgMTMuMjNMNy4zOSAxNC4yOUwxMC41NiAxNy40NloiIGZpbGw9IiNmZmZmZmYiIC8+PC9zdmc+); +/* progress close */ +.icon-progress-close-dark { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHBhdGgNCiAgICAgICAgZD0iTTEzIDIuMDNWNC4wNUMxNy4zOSA0LjU5IDIwLjUgOC41OCAxOS45NiAxMi45N0MxOS41IDE2LjYxIDE2LjY0IDE5LjUgMTMgMTkuOTNWMjEuOTNDMTguNSAyMS4zOCAyMi41IDE2LjUgMjEuOTUgMTFDMjEuNSA2LjI1IDE3LjczIDIuNSAxMyAyLjAzTTExIDIuMDZDOS4wNSAyLjI1IDcuMTkgMyA1LjY3IDQuMjZMNy4xIDUuNzRDOC4yMiA0Ljg0IDkuNTcgNC4yNiAxMSA0LjA2VjIuMDZNNC4yNiA1LjY3QzMgNy4xOSAyLjI1IDkuMDQgMi4wNSAxMUg0LjA1QzQuMjQgOS41OCA0LjggOC4yMyA1LjY5IDcuMUw0LjI2IDUuNjdNMi4wNiAxM0MyLjI2IDE0Ljk2IDMuMDMgMTYuODEgNC4yNyAxOC4zM0w1LjY5IDE2LjlDNC44MSAxNS43NyA0LjI0IDE0LjQyIDQuMDYgMTNIMi4wNk03LjEgMTguMzdMNS42NyAxOS43NEM3LjE4IDIxIDkuMDQgMjEuNzkgMTEgMjJWMjBDOS41OCAxOS44MiA4LjIzIDE5LjI1IDcuMSAxOC4zN00xNC41OSA4TDEyIDEwLjU5TDkuNDEgOEw4IDkuNDFMMTAuNTkgMTJMOCAxNC41OUw5LjQxIDE2TDEyIDEzLjQxTDE0LjU5IDE2TDE2IDE0LjU5TDEzLjQxIDEyTDE2IDkuNDFMMTQuNTkgOFoiDQogICAgICAgIHN0eWxlPSJmaWxsLW9wYWNpdHk6LjU7ZmlsbC1ydWxlOm5vbnplcm8iIGZpbGw9IiMwMDAwMDAiIC8+DQo8L3N2Zz4=); +} +.icon-progress-close-light { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHBhdGgNCiAgICAgICAgZD0iTTEzIDIuMDNWNC4wNUMxNy4zOSA0LjU5IDIwLjUgOC41OCAxOS45NiAxMi45N0MxOS41IDE2LjYxIDE2LjY0IDE5LjUgMTMgMTkuOTNWMjEuOTNDMTguNSAyMS4zOCAyMi41IDE2LjUgMjEuOTUgMTFDMjEuNSA2LjI1IDE3LjczIDIuNSAxMyAyLjAzTTExIDIuMDZDOS4wNSAyLjI1IDcuMTkgMyA1LjY3IDQuMjZMNy4xIDUuNzRDOC4yMiA0Ljg0IDkuNTcgNC4yNiAxMSA0LjA2VjIuMDZNNC4yNiA1LjY3QzMgNy4xOSAyLjI1IDkuMDQgMi4wNSAxMUg0LjA1QzQuMjQgOS41OCA0LjggOC4yMyA1LjY5IDcuMUw0LjI2IDUuNjdNMi4wNiAxM0MyLjI2IDE0Ljk2IDMuMDMgMTYuODEgNC4yNyAxOC4zM0w1LjY5IDE2LjlDNC44MSAxNS43NyA0LjI0IDE0LjQyIDQuMDYgMTNIMi4wNk03LjEgMTguMzdMNS42NyAxOS43NEM3LjE4IDIxIDkuMDQgMjEuNzkgMTEgMjJWMjBDOS41OCAxOS44MiA4LjIzIDE5LjI1IDcuMSAxOC4zN00xNC41OSA4TDEyIDEwLjU5TDkuNDEgOEw4IDkuNDFMMTAuNTkgMTJMOCAxNC41OUw5LjQxIDE2TDEyIDEzLjQxTDE0LjU5IDE2TDE2IDE0LjU5TDEzLjQxIDEyTDE2IDkuNDFMMTQuNTkgOFoiDQogICAgICAgIHN0eWxlPSJmaWxsLXJ1bGU6bm9uemVybyIgZmlsbD0iI2ZmZmZmZiIgLz4NCjwvc3ZnPg==); +} + +/* pencil */ +.icon-pencil-dark { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTIwLjcxLDcuMDRDMjEuMSw2LjY1IDIxLjEsNiAyMC43MSw1LjYzTDE4LjM3LDMuMjlDMTgsMi45IDE3LjM1LDIuOSAxNi45NiwzLjI5TDE1LjEyLDUuMTJMMTguODcsOC44N00zLDE3LjI1VjIxSDYuNzVMMTcuODEsOS45M0wxNC4wNiw2LjE4TDMsMTcuMjVaIiAvPjwvc3ZnPg==); +} +.icon-pencil-light { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTIwLjcxLDcuMDRDMjEuMSw2LjY1IDIxLjEsNiAyMC43MSw1LjYzTDE4LjM3LDMuMjlDMTgsMi45IDE3LjM1LDIuOSAxNi45NiwzLjI5TDE1LjEyLDUuMTJMMTguODcsOC44N00zLDE3LjI1VjIxSDYuNzVMMTcuODEsOS45M0wxNC4wNiw2LjE4TDMsMTcuMjVaIiBmaWxsPSIjZmZmZmZmIiAvPjwvc3ZnPg==); +} + +/* CalendarCheckOutline */ +.icon-calendar-check-outline-dark { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTE5IDNIMThWMUgxNlYzSDhWMUg2VjNINUMzLjkgMyAzIDMuOSAzIDVWMTlDMyAyMC4xMSAzLjkgMjEgNSAyMUgxOUMyMC4xMSAyMSAyMSAyMC4xMSAyMSAxOVY1QzIxIDMuOSAyMC4xMSAzIDE5IDNNMTkgMTlINVY5SDE5VjE5TTUgN1Y1SDE5VjdINU0xMC41NiAxNy40NkwxNi41IDExLjUzTDE1LjQzIDEwLjQ3TDEwLjU2IDE1LjM0TDguNDUgMTMuMjNMNy4zOSAxNC4yOUwxMC41NiAxNy40NloiIC8+PC9zdmc+); +} +.icon-calendar-check-outline-light { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTE5IDNIMThWMUgxNlYzSDhWMUg2VjNINUMzLjkgMyAzIDMuOSAzIDVWMTlDMyAyMC4xMSAzLjkgMjEgNSAyMUgxOUMyMC4xMSAyMSAyMSAyMC4xMSAyMSAxOVY1QzIxIDMuOSAyMC4xMSAzIDE5IDNNMTkgMTlINVY5SDE5VjE5TTUgN1Y1SDE5VjdINU0xMC41NiAxNy40NkwxNi41IDExLjUzTDE1LjQzIDEwLjQ3TDEwLjU2IDE1LjM0TDguNDUgMTMuMjNMNy4zOSAxNC4yOUwxMC41NiAxNy40NloiIGZpbGw9IiNmZmZmZmYiIC8+PC9zdmc+); } \ No newline at end of file diff --git a/src/services/icons/index.js b/src/services/icons/index.js index f2e0c7d..38f5d85 100644 --- a/src/services/icons/index.js +++ b/src/services/icons/index.js @@ -1,7 +1,7 @@ -import { iconProgressClose as _iconProgressClose } from './icon/icon-progress-close.js' -import { iconPencil as _iconPencil } from './icon/icon-pencil.js' -import { iconCalendarCheckOutline as _iconCalendarCheckOutline } from './icon/icon-calendar-check-outline.js' - -export const iconProgressClose = _iconProgressClose() -export const iconPencil = _iconPencil() -export const iconCalendarCheckOutline = _iconCalendarCheckOutline() +import { iconProgressClose as _iconProgressClose } from './icon/icon-progress-close.js' +import { iconPencil as _iconPencil } from './icon/icon-pencil.js' +import { iconCalendarCheckOutline as _iconCalendarCheckOutline } from './icon/icon-calendar-check-outline.js' + +export const iconProgressClose = _iconProgressClose() +export const iconPencil = _iconPencil() +export const iconCalendarCheckOutline = _iconCalendarCheckOutline() diff --git a/src/views/contactMomenten/ContactMomentDetails.vue b/src/views/contactMomenten/ContactMomentDetails.vue index 79e5d53..d29f2ce 100644 --- a/src/views/contactMomenten/ContactMomentDetails.vue +++ b/src/views/contactMomenten/ContactMomentDetails.vue @@ -1,224 +1,224 @@ - - - - - - - + + + + + + + diff --git a/src/views/contactMomenten/ContactMomentenIndex.vue b/src/views/contactMomenten/ContactMomentenIndex.vue index f985d80..9955d9a 100644 --- a/src/views/contactMomenten/ContactMomentenIndex.vue +++ b/src/views/contactMomenten/ContactMomentenIndex.vue @@ -1,46 +1,46 @@ - - - - - + + + + + diff --git a/src/views/contactMomenten/ContactMomentenList.vue b/src/views/contactMomenten/ContactMomentenList.vue index 2be1a1f..3f067b7 100644 --- a/src/views/contactMomenten/ContactMomentenList.vue +++ b/src/views/contactMomenten/ContactMomentenList.vue @@ -1,190 +1,190 @@ - - - - - + + + + + diff --git a/src/views/medewerkers/MedewerkerDetails.vue b/src/views/medewerkers/MedewerkerDetails.vue index 4252e52..c73873e 100644 --- a/src/views/medewerkers/MedewerkerDetails.vue +++ b/src/views/medewerkers/MedewerkerDetails.vue @@ -1,164 +1,164 @@ - - - - - - - + + + + + + + diff --git a/src/views/medewerkers/MedewerkerList.vue b/src/views/medewerkers/MedewerkerList.vue index b43f6f4..f556bf8 100644 --- a/src/views/medewerkers/MedewerkerList.vue +++ b/src/views/medewerkers/MedewerkerList.vue @@ -1,189 +1,189 @@ - - - - - + + + + + diff --git a/src/views/widgets/ContactMomentenWidget.vue b/src/views/widgets/ContactMomentenWidget.vue index 761e906..6db5d9b 100644 --- a/src/views/widgets/ContactMomentenWidget.vue +++ b/src/views/widgets/ContactMomentenWidget.vue @@ -1,211 +1,211 @@ - - - - - - + + + + + + diff --git a/src/views/widgets/TakenWidget.vue b/src/views/widgets/TakenWidget.vue index ca60f47..e5e1a16 100644 --- a/src/views/widgets/TakenWidget.vue +++ b/src/views/widgets/TakenWidget.vue @@ -1,225 +1,225 @@ - - - - - - + + + + + + From 788ced37a157c6b53ce98117354c8329bcdb74fb Mon Sep 17 00:00:00 2001 From: Remko Date: Wed, 18 Dec 2024 09:32:37 +0100 Subject: [PATCH 08/68] added view contactmoment --- src/modals/Modals.vue | 3 + .../contactMomenten/ContactMomentenForm.vue | 51 +- .../contactMomenten/ViewContactMoment.vue | 1035 +++++++++++++++++ src/modals/zaken/ZaakForm.vue | 2 +- src/store/modules/navigation.ts | 7 + 5 files changed, 1092 insertions(+), 6 deletions(-) create mode 100644 src/modals/contactMomenten/ViewContactMoment.vue diff --git a/src/modals/Modals.vue b/src/modals/Modals.vue index 75895c0..da20130 100644 --- a/src/modals/Modals.vue +++ b/src/modals/Modals.vue @@ -14,6 +14,7 @@ import { navigationStore } from '../store/store.js' + @@ -55,6 +56,7 @@ import AddBerichtToZaak from './zaken/AddBerichtToZaak.vue' import AddTaakToZaak from './zaken/AddTaakToZaak.vue' import ContactMomentenForm from './contactMomenten/ContactMomentenForm.vue' import AddRolToZaak from './zaken/AddRolToZaak.vue' +import ViewContactMoment from './contactMomenten/ViewContactMoment.vue' export default { name: 'Modals', @@ -78,6 +80,7 @@ export default { AddTaakToZaak, ContactMomentenForm, AddRolToZaak, + ViewContactMoment, }, } diff --git a/src/modals/contactMomenten/ContactMomentenForm.vue b/src/modals/contactMomenten/ContactMomentenForm.vue index d296226..f1bc2aa 100644 --- a/src/modals/contactMomenten/ContactMomentenForm.vue +++ b/src/modals/contactMomenten/ContactMomentenForm.vue @@ -89,7 +89,7 @@ import { contactMomentStore, navigationStore, taakStore, zaakStore } from '../.. :disabled="loading" :loading="fetchLoading" type="primary" - @click="contactMomenten[i].klant = null"> + @click="removeKlant(i)"> @@ -131,6 +131,14 @@ import { contactMomentStore, navigationStore, taakStore, zaakStore } from '../.. + @@ -476,7 +484,7 @@ import { contactMomentStore, navigationStore, taakStore, zaakStore } from '../.. Klant taak aanmaken - + @@ -503,16 +511,22 @@ import { contactMomentStore, navigationStore, taakStore, zaakStore } from '../.. + + @@ -529,6 +543,7 @@ import getValidISOstring from '../../services/getValidISOstring.js' import SearchKlantModal from '../../modals/klanten/SearchKlantModal.vue' import EditTaak from '../../modals/taken/EditTaak.vue' import ZaakForm from '../../modals/zaken/ZaakForm.vue' +import ViewContactMoment from '../../modals/contactMomenten/ViewContactMoment.vue' // Entities import { ContactMoment } from '../../entities/index.js' @@ -542,6 +557,7 @@ import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue' import Cancel from 'vue-material-design-icons/Cancel.vue' import Minus from 'vue-material-design-icons/Minus.vue' import ProgressClose from 'vue-material-design-icons/ProgressClose.vue' +import Eye from 'vue-material-design-icons/Eye.vue' export default { name: 'ContactMomentenForm', @@ -641,6 +657,9 @@ export default { taakFormOpen: false, taakClientType: 'both', zaakFormOpen: false, + viewContactMomentIsView: false, + viewContactMomentId: null, + isContactMomentFormOpen: false, tabs: [1], tabCounter: 1, @@ -821,6 +840,28 @@ export default { closeTaakForm() { this.taakFormOpen = false + this.fetchKlantData(this.contactMomenten[this.selectedContactMoment].klant.id) + }, + + viewContactMoment(id) { + this.isContactMomentFormOpen = true + this.viewContactMomentIsView = true + this.viewContactMomentId = id + navigationStore.setViewModal('viewContactMoment') + }, + + closeViewContactMomentModal() { + this.isContactMomentFormOpen = false + navigationStore.setViewModal(null) + }, + + removeKlant(i) { + this.contactMomenten[i].klant = null + this.contactMomenten[i].taken = null + this.contactMomenten[i].zaken = null + this.contactMomenten[i].berichten = null + this.contactMomenten[i].klantContactmomenten = null + this.contactMomenten[i].auditTrails = null }, // zaak functions @@ -831,7 +872,7 @@ export default { zaakFormSaveSuccess() { this.zaakFormOpen = false - this.fetchKlantData(this.klant.id) + this.fetchKlantData(this.contactMomenten[this.selectedContactMoment].klant.id) }, async closeContactMoment(id) { diff --git a/src/modals/contactMomenten/ViewContactMoment.vue b/src/modals/contactMomenten/ViewContactMoment.vue new file mode 100644 index 0000000..45fa866 --- /dev/null +++ b/src/modals/contactMomenten/ViewContactMoment.vue @@ -0,0 +1,1035 @@ + + + + + + + + + diff --git a/src/modals/zaken/ZaakForm.vue b/src/modals/zaken/ZaakForm.vue index 0d66c89..88ea9d3 100644 --- a/src/modals/zaken/ZaakForm.vue +++ b/src/modals/zaken/ZaakForm.vue @@ -191,7 +191,7 @@ export default { methods: { closeModal() { navigationStore.setModal(null) - this?.dashboardWidget && this.$emit('close') + this?.dashboardWidget && this.$emit('close-modal') }, fetchZaakType() { this.zaakTypeLoading = true diff --git a/src/store/modules/navigation.ts b/src/store/modules/navigation.ts index 3afe94d..57de284 100644 --- a/src/store/modules/navigation.ts +++ b/src/store/modules/navigation.ts @@ -4,6 +4,7 @@ import { defineStore } from 'pinia' interface NavigationStoreState { selected: 'dashboard' | 'berichten' | 'klanten' | 'rollen' | 'taken' | 'zaken' | 'zaakTypen' | 'search' | 'auditTrail' | 'contactMomenten' | 'medewerkers'; modal: string; + viewModal: string; dialog: string; transferData: string; } @@ -14,6 +15,8 @@ export const useNavigationStore = defineStore('ui', { selected: 'dashboard', // The currently active modal, managed trough the state to ensure that only one modal can be active at the same time modal: null, + // The currently active view modal, managed trough the state to ensure that only one view modal can be active at the same time + viewModal: null, // The currently active dialog dialog: null, // Any data needed in various models, dialogs, views which cannot be transferred through normal means or without writing bad/excessive code @@ -28,6 +31,10 @@ export const useNavigationStore = defineStore('ui', { this.modal = modal console.log('Active modal set to ' + modal) }, + setViewModal(modal: NavigationStoreState['modal']) { + this.viewModal = modal + console.log('Active modal set to ' + modal) + }, setDialog(dialog: NavigationStoreState['dialog']) { this.dialog = dialog console.log('Active dialog set to ' + dialog) From 9a7baedc7292e8081b9e6d186964ce539762a730 Mon Sep 17 00:00:00 2001 From: Robert Zondervan Date: Wed, 18 Dec 2024 10:18:55 +0100 Subject: [PATCH 09/68] Operationalise objects controller --- appinfo/routes.php | 6 ++++++ lib/Controller/ObjectsController.php | 10 +++++++--- lib/Service/ObjectService.php | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index cf4db34..cae6f6d 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -58,5 +58,11 @@ ['name' => 'settings#create', 'url' => '/settings', 'verb' => 'POST'], // User ['name' => 'users#me', 'url' => '/me', 'verb' => 'GET'], + ['name' => 'objects#index', 'url' => '/api/objects/{_objectType}', 'verb' => 'GET', 'requirements' => ['_objectType' => '[^/]+']], + ['name' => 'objects#show', 'url' => '/api/objects/{_objectType}/{id}', 'verb' => 'GET', 'requirements' => ['_objectType' => '[^/]+', 'id' => '[^/]+']], + ['name' => 'objects#getAuditTrail', 'url' => '/api/objects/{_objectType}/{id}/audit_trail', 'verb' => 'GET', 'requirements' => ['_objectType' => '[^/]+', 'id' => '[^/]+']], + ['name' => 'objects#create', 'url' => '/api/objects/{_objectType}', 'verb' => 'POST', 'requirements' => ['_objectType' => '[^/]+', 'id' => '[^/]+']], + ['name' => 'objects#update', 'url' => '/api/objects/{_objectType}/{id}', 'verb' => 'PUT', 'requirements' => ['_objectType' => '[^/]+', 'id' => '[^/]+']], + ['name' => 'objects#destroy', 'url' => '/api/objects/{_objectType}/{id}', 'verb' => 'DELETE', 'requirements' => ['_objectType' => '[^/]+', 'id' => '[^/]+']] ] ]; diff --git a/lib/Controller/ObjectsController.php b/lib/Controller/ObjectsController.php index f39ee49..900fc1e 100644 --- a/lib/Controller/ObjectsController.php +++ b/lib/Controller/ObjectsController.php @@ -36,7 +36,7 @@ private function validateObjectType(array $requestParams): string { } $objectType = $requestParams['_objectType']; - + try { // This will throw an exception if object type is not properly configured $this->objectService->getMapper($objectType); @@ -64,6 +64,8 @@ public function index(): JSONResponse // Validate object type configuration $objectType = $this->validateObjectType($requestParams); + unset($requestParams['_objectType']); + // Fetch objects based on filters and order using provided objectType $data = $this->objectService->getResultArrayForRequest( objectType: $objectType, @@ -132,10 +134,11 @@ public function create(): JSONResponse // Remove the 'id' field if it exists, as we're creating a new object unset($data['id']); unset($data['_objectType']); + unset($data['_route']); // Save the new object $object = $this->objectService->saveObject($objectType, $data); - + // Return the created object as a JSON response return new JSONResponse($object); } catch (Exception $e) { @@ -164,10 +167,11 @@ public function update(string $id): JSONResponse // Ensure ID in data matches URL parameter $data['id'] = $id; unset($data['_objectType']); + unset($data['_route']); // Save the updated object $object = $this->objectService->saveObject($objectType, $data); - + // Return the updated object as a JSON response return new JSONResponse($object); } catch (Exception $e) { diff --git a/lib/Service/ObjectService.php b/lib/Service/ObjectService.php index ab77564..4d89ef8 100644 --- a/lib/Service/ObjectService.php +++ b/lib/Service/ObjectService.php @@ -49,7 +49,7 @@ public function __construct( * @throws NotFoundExceptionInterface|ContainerExceptionInterface If OpenRegister service is not available or if register/schema is not configured. * @throws Exception */ - private function getMapper(string $objectType): mixed + public function getMapper(string $objectType): mixed { $objectTypeLower = strtolower($objectType); From bc42bd03c3061a56575608054467778b39442e10 Mon Sep 17 00:00:00 2001 From: Robert Zondervan Date: Wed, 18 Dec 2024 10:21:33 +0100 Subject: [PATCH 10/68] Add producten to settings --- lib/Controller/SettingsController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 31f7270..5c92b85 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -105,7 +105,10 @@ public function index(): JSONResponse 'contactmomenten_register' => '', 'medewerkers_source' => 'internal', 'medewerkers_schema' => '', - 'medewerkers_register' => '' + 'medewerkers_register' => '', + 'producten_source' => 'internal', + 'producten_schema' => '', + 'producten_register' => '', ]; // Get the current values for the object types from the configuration From 261d6b1454ee0422ec7cdbda5315f0ed3ef1a5fd Mon Sep 17 00:00:00 2001 From: Thijn Date: Wed, 18 Dec 2024 11:45:48 +0100 Subject: [PATCH 11/68] fixed a bug while loading data in parralel if the result is 500 --- .../contactMomenten/ContactMomentenForm.vue | 70 ++++++++++++++----- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/src/modals/contactMomenten/ContactMomentenForm.vue b/src/modals/contactMomenten/ContactMomentenForm.vue index f1bc2aa..b980d6a 100644 --- a/src/modals/contactMomenten/ContactMomentenForm.vue +++ b/src/modals/contactMomenten/ContactMomentenForm.vue @@ -906,8 +906,33 @@ export default { this.contactMomenten[this.selectedContactMoment].klant = await klantResponse.json() } - // fetch all data in parallel - const [zakenRes, takenRes, berichtenRes, auditTrailRes, contactMomentenRes] = await Promise.all([ + /** + * This code block handles parallel fetching and parsing of multiple API endpoints in a fault-tolerant way. + * Here's what happens step by step: + * + * 1. First, we initiate 5 parallel fetch requests using Promise.allSettled(): + * - This allows all requests to run simultaneously rather than sequentially + * - Unlike Promise.all(), allSettled() won't fail if some requests fail + * - Each request fetches different data for the same klant ID (cases, tasks, messages etc) + * + * 2. Once all fetches complete (successfully or not), we process the responses: + * - results contains an array of 5 promise results + * - Each result is either {status: 'fulfilled', value: Response} or {status: 'rejected', reason: Error} + * + * 3. We then parse the JSON from successful responses using another Promise.allSettled(): + * - For each fulfilled fetch with ok status, we parse the JSON asynchronously + * - For failed fetches or non-ok responses, we return null + * - This creates another layer of fault tolerance during JSON parsing + * + * 4. Finally, we destructure the parsed results into separate variables: + * - Each variable gets either the parsed JSON data or null if any step failed + * - This gives us clean variables to work with, regardless of failures + * + * The end result is we get all our data in parallel, with proper error handling, + * and clean null values for any failed requests rather than thrown exceptions. + */ + // #1 + const results = await Promise.allSettled([ fetch(`/index.php/apps/zaakafhandelapp/api/klanten/${id}/zaken`), fetch(`/index.php/apps/zaakafhandelapp/api/klanten/${id}/taken`), fetch(`/index.php/apps/zaakafhandelapp/api/klanten/${id}/berichten`), @@ -915,45 +940,55 @@ export default { fetch(`/index.php/apps/zaakafhandelapp/api/klanten/${id}/contactmomenten`), ]) - // parse all data - const [zakenData, takenData, berichtenData, auditTrailData, contactMomentenData] = await Promise.all([ - zakenRes.json(), - takenRes.json(), - berichtenRes.json(), - auditTrailRes.json(), - contactMomentenRes.json(), - ]) + // #2 & #3 + const parsedResults = await Promise.allSettled( + results.map(async (result) => { + if (result.status === 'fulfilled' && result.value.ok) { + return await result.value.json() + } + return null + }), + ) + + // #4 + const [zakenData, takenData, berichtenData, auditTrailData, contactMomentenData] = parsedResults.map(result => + result.status === 'fulfilled' ? result.value : null, + ) - // set data - if (Array.isArray(zakenData.results)) { + // set data, checking for null values + if (zakenData?.results && Array.isArray(zakenData.results)) { if (this.isView) { this.zaken = zakenData.results } else { this.contactMomenten[this.selectedContactMoment].zaken = zakenData.results } } - if (Array.isArray(takenData.results)) { + + if (takenData?.results && Array.isArray(takenData.results)) { if (this.isView) { this.taken = takenData.results } else { this.contactMomenten[this.selectedContactMoment].taken = takenData.results } } - if (Array.isArray(berichtenData.results)) { + + if (berichtenData?.results && Array.isArray(berichtenData.results)) { if (this.isView) { this.berichten = berichtenData.results } else { this.contactMomenten[this.selectedContactMoment].berichten = berichtenData.results } } - if (Array.isArray(auditTrailData)) { + + if (auditTrailData && Array.isArray(auditTrailData)) { if (this.isView) { this.auditTrails = auditTrailData } else { this.contactMomenten[this.selectedContactMoment].auditTrails = auditTrailData } } - if (Array.isArray(contactMomentenData.results)) { + + if (contactMomentenData?.results && Array.isArray(contactMomentenData.results)) { if (this.isView) { this.klantContactmomenten = contactMomentenData.results } else { @@ -963,7 +998,8 @@ export default { } catch (error) { console.error('Error in fetchKlantData:', error) - throw error + // Don't throw the error, as we want the component to continue working + // even if some data failed to load } }, From 7a33d1538aa1fd2937a810a63bf98d85934cdc74 Mon Sep 17 00:00:00 2001 From: Remko Date: Wed, 18 Dec 2024 12:02:54 +0100 Subject: [PATCH 12/68] lint-fix --- src/entities/medewerkers/medewerkers.mock.ts | 3 +- src/entities/medewerkers/medewerkers.types.ts | 14 +- .../contactMomenten/ContactMomentenForm.vue | 113 ++++++++-------- .../klantRegister/ViewKlantRegister.vue | 71 +++++----- src/modals/klanten/SearchKlantModal.vue | 23 ++-- src/modals/medewerkers/EditMedewerker.vue | 7 +- src/modals/zaakTypen/DeleteZaaktype.vue | 7 +- src/modals/zaakTypen/ZaaktypeForm.vue | 121 +++++------------- src/modals/zaken/AddBerichtToZaak.vue | 8 +- src/modals/zaken/AddRolToZaak.vue | 8 +- src/modals/zaken/AddTaakToZaak.vue | 8 +- src/services/icons/icons.css | 17 ++- .../contactMomenten/ContactMomentDetails.vue | 48 +++---- .../contactMomenten/ContactMomentenIndex.vue | 10 +- .../contactMomenten/ContactMomentenList.vue | 33 ++--- src/views/medewerkers/MedewerkerDetails.vue | 42 +++--- src/views/medewerkers/MedewerkerList.vue | 29 +++-- src/views/widgets/ContactMomentenWidget.vue | 15 ++- src/views/widgets/TakenWidget.vue | 19 +-- 19 files changed, 274 insertions(+), 322 deletions(-) diff --git a/src/entities/medewerkers/medewerkers.mock.ts b/src/entities/medewerkers/medewerkers.mock.ts index c1f4d55..324455f 100644 --- a/src/entities/medewerkers/medewerkers.mock.ts +++ b/src/entities/medewerkers/medewerkers.mock.ts @@ -12,4 +12,5 @@ export const mockMedewerkerData = (): TMedewerker[] => [ }, ] -export const mockMedewerker = (data: TMedewerker[] = mockMedewerkerData()): TMedewerker[] => data.map(item => new Medewerker(item)) +export const mockMedewerker = (data: TMedewerker[] = mockMedewerkerData()): TMedewerker[] => + data.map((item) => new Medewerker(item)) diff --git a/src/entities/medewerkers/medewerkers.types.ts b/src/entities/medewerkers/medewerkers.types.ts index df6ec55..c3045e7 100644 --- a/src/entities/medewerkers/medewerkers.types.ts +++ b/src/entities/medewerkers/medewerkers.types.ts @@ -1,8 +1,8 @@ export type TMedewerker = { - id: string; - voornaam: string; - tussenvoegsel: string; - achternaam: string; - email: string; - telefoonnummer: string; -} + id: string; + voornaam: string; + tussenvoegsel: string; + achternaam: string; + email: string; + telefoonnummer: string; +}; diff --git a/src/modals/contactMomenten/ContactMomentenForm.vue b/src/modals/contactMomenten/ContactMomentenForm.vue index 422209a..a9ce29b 100644 --- a/src/modals/contactMomenten/ContactMomentenForm.vue +++ b/src/modals/contactMomenten/ContactMomentenForm.vue @@ -29,21 +29,28 @@ import { contactMomentStore, navigationStore, taakStore, zaakStore } from '../..