From b8ed9ebbc26d284dfa58740857a9a2fee5948f1f Mon Sep 17 00:00:00 2001 From: Remko Date: Tue, 26 Nov 2024 13:20:49 +0100 Subject: [PATCH 1/6] Added contact moment --- .../contactmoment/contactmoment.mock.ts | 18 +++ .../contactmoment/contactmoment.spec.ts | 12 ++ src/entities/contactmoment/contactmoment.ts | 44 ++++++ .../contactmoment/contactmoment.types.ts | 11 ++ src/entities/contactmoment/index.js | 3 + src/entities/index.js | 1 + src/store/modules/contactmoment.js | 125 ++++++++++++++++++ src/store/modules/contactmoment.spec.js | 36 +++++ src/store/store.js | 5 +- 9 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 src/entities/contactmoment/contactmoment.mock.ts create mode 100644 src/entities/contactmoment/contactmoment.spec.ts create mode 100644 src/entities/contactmoment/contactmoment.ts create mode 100644 src/entities/contactmoment/contactmoment.types.ts create mode 100644 src/entities/contactmoment/index.js create mode 100644 src/store/modules/contactmoment.js create mode 100644 src/store/modules/contactmoment.spec.js diff --git a/src/entities/contactmoment/contactmoment.mock.ts b/src/entities/contactmoment/contactmoment.mock.ts new file mode 100644 index 0000000..93b2cce --- /dev/null +++ b/src/entities/contactmoment/contactmoment.mock.ts @@ -0,0 +1,18 @@ +import { ContactMoment } from './contactmoment' +import { TContactMoment } from './contactmoment.types' + +export const mockContactMomentData = (): TContactMoment[] => [ + { + id: '15551d6f-44e3-43f3-a9d2-59e583c91eb0', + uuid: '15551d6f-44e3-43f3-a9d2-59e583c91eb0', + titel: 'Zaak 3', + notitie: 'Zaak 3', + klant: 'Klant 3', + zaak: 'Zaak 3', + taak: 'Taak 3', + product: 'Product 3', + startDate: new Date().toISOString(), + }, +] + +export const mockContactMoment = (data: TContactMoment[] = mockContactMomentData()): TContactMoment[] => data.map(item => new ContactMoment(item)) diff --git a/src/entities/contactmoment/contactmoment.spec.ts b/src/entities/contactmoment/contactmoment.spec.ts new file mode 100644 index 0000000..4b7c435 --- /dev/null +++ b/src/entities/contactmoment/contactmoment.spec.ts @@ -0,0 +1,12 @@ +import { ContactMoment } from './contactmoment' +import { mockContactMomentData } from './contactmoment.mock' + +describe('ContactMoment Entity', () => { + it('should create a ContactMoment entity with full data', () => { + const contactMoment = new ContactMoment(mockContactMomentData()[0]) + + expect(contactMoment).toBeInstanceOf(ContactMoment) + expect(contactMoment).toEqual(mockContactMomentData()[0]) + expect(contactMoment.validate().success).toBe(true) + }) +}) diff --git a/src/entities/contactmoment/contactmoment.ts b/src/entities/contactmoment/contactmoment.ts new file mode 100644 index 0000000..423fb62 --- /dev/null +++ b/src/entities/contactmoment/contactmoment.ts @@ -0,0 +1,44 @@ +import { SafeParseReturnType, z } from 'zod' +import { TContactMoment } from './contactmoment.types' + +export class ContactMoment implements TContactMoment { + + public id: string + public uuid: string + public titel: string + public notitie: string + public klant: string + public zaak: string + public taak: string + public product: string + public startDate: string + + constructor(source: TContactMoment) { + this.id = source.id || '' + this.uuid = source.uuid || '' + this.titel = source.titel || '' + this.notitie = source.notitie || '' + this.klant = source.klant || '' + this.zaak = source.zaak || '' + this.taak = source.taak || '' + this.product = source.product || '' + this.startDate = source.startDate || '' + } + + public validate(): SafeParseReturnType { + const schema = z.object({ + id: z.string().optional(), + uuid: z.string().optional(), + titel: z.string().min(1), + notitie: z.string().min(1), + klant: z.string().min(1), + zaak: z.string().min(1), + taak: z.string().min(1), + product: z.string().min(1), + startDate: z.string().min(1), + }) + + return schema.safeParse(this) + } + +} diff --git a/src/entities/contactmoment/contactmoment.types.ts b/src/entities/contactmoment/contactmoment.types.ts new file mode 100644 index 0000000..e6e8107 --- /dev/null +++ b/src/entities/contactmoment/contactmoment.types.ts @@ -0,0 +1,11 @@ +export type TContactMoment = { + id: string; + uuid: string; + titel: string; + notitie: string; + klant: string; + zaak: string; + taak: string; + product: string; + startDate: string; +} diff --git a/src/entities/contactmoment/index.js b/src/entities/contactmoment/index.js new file mode 100644 index 0000000..7296b68 --- /dev/null +++ b/src/entities/contactmoment/index.js @@ -0,0 +1,3 @@ +export * from './contactmoment.ts' +export * from './contactmoment.types.ts' +export * from './contactmoment.mock.ts' diff --git a/src/entities/index.js b/src/entities/index.js index b1e1a2d..6f68388 100644 --- a/src/entities/index.js +++ b/src/entities/index.js @@ -5,3 +5,4 @@ export * from './klanten/index.js' export * from './taak/index.js' export * from './bericht/index.js' export * from './rol/index.js' +export * from './contactmoment/index.js' diff --git a/src/store/modules/contactmoment.js b/src/store/modules/contactmoment.js new file mode 100644 index 0000000..f155ef3 --- /dev/null +++ b/src/store/modules/contactmoment.js @@ -0,0 +1,125 @@ +/* eslint-disable no-console */ +import { defineStore } from 'pinia' +import { ContactMoment } from '../../entities/index.js' + +const apiEndpoint = '/index.php/apps/zaakafhandelapp/api/contactmomenten' + +export const useContactMomentStore = defineStore('contactmomenten', { + state: () => ({ + contactMomentItem: false, + contactMomentenList: [], + }), + actions: { + setContactMomentItem(contactMomentItem) { + this.contactMomentItem = contactMomentItem && new ContactMoment(contactMomentItem) + console.info('Active contactmoment item set to ' + contactMomentItem) + }, + setContactMomentenList(contactMomentenList) { + this.contactMomentenList = contactMomentenList.map( + (contactMomentItem) => new ContactMoment(contactMomentItem), + ) + console.info('Contactmomenten list set to ' + contactMomentenList.length + ' items') + }, + /* istanbul ignore next */ // ignore this for Jest until moved into a service + async refreshContactMomentenList(search = null) { + let endpoint = apiEndpoint + + if (search !== null && search !== '') { + endpoint = endpoint + '?_search=' + search + } + + const response = await fetch(endpoint, { + method: 'GET', + }) + + if (!response.ok) { + console.info(response) + throw new Error(`HTTP error! status: ${response.status}`) + } + + const data = (await response.json()).results + const entities = data.map((contactMomentItem) => new ContactMoment(contactMomentItem)) + + this.setContactMomentenList(data) + + return { response, data, entities } + }, + // New function to get a single contactmoment + async getContactMoment(id) { + const endpoint = `${apiEndpoint}/${id}` + + const response = await fetch(endpoint, { + method: 'GET', + }) + + if (!response.ok) { + console.info(response) + throw new Error(`HTTP error! status: ${response.status}`) + } + + const data = await response.json() + const entity = new ContactMoment(data) + + this.setContactMomentItem(data) + + return { response, data, entity } + }, + // Delete a contactmoment + async deleteContactMoment(contactMomentItem) { + if (!contactMomentItem.id) { + throw new Error('No contactmoment item to delete') + } + + const endpoint = `${apiEndpoint}/${contactMomentItem.id}` + + const response = await fetch(endpoint, { + method: 'DELETE', + }) + + if (!response.ok) { + console.info(response) + throw new Error(`HTTP error! status: ${response.status}`) + } + + this.refreshContactMomentenList() + + return { response } + }, + // Create or save a contactmoment from store + async saveContactMoment(contactMomentItem) { + if (!contactMomentItem) { + throw new Error('No contactmoment item to save') + } + + const isNewContactMoment = !contactMomentItem.id + const endpoint = isNewContactMoment + ? `${apiEndpoint}` + : `${apiEndpoint}/${contactMomentItem.id}` + const method = isNewContactMoment ? 'POST' : 'PUT' + + const response = await fetch( + endpoint, + { + method, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(contactMomentItem), + }, + ) + + if (!response.ok) { + console.info(response) + throw new Error(`HTTP error! status: ${response.status}`) + } + + const data = await response.json() + const entity = new ContactMoment(data) + + this.setContactMomentItem(data) + this.refreshContactMomentenList() + + return { response, data, entity } + }, + }, +}) diff --git a/src/store/modules/contactmoment.spec.js b/src/store/modules/contactmoment.spec.js new file mode 100644 index 0000000..efe8eeb --- /dev/null +++ b/src/store/modules/contactmoment.spec.js @@ -0,0 +1,36 @@ +/* eslint-disable no-console */ +import { setActivePinia, createPinia } from 'pinia' + +import { useContactMomentStore } from './contactmoment.js' +import { ContactMoment, mockContactMoment } from '../../entities/index.js' + +describe('Contact Moment Store', () => { + beforeEach(() => { + setActivePinia(createPinia()) + }) + + it('sets contact moment item correctly', () => { + const store = useContactMomentStore() + + store.setContactMomentItem(mockContactMoment()[0]) + + expect(store.contactMomentItem).toBeInstanceOf(ContactMoment) + expect(store.contactMomentItem).toEqual(mockContactMoment()[0]) + + expect(store.contactMomentItem.validate().success).toBe(true) + }) + + it('sets contact moment list correctly', () => { + const store = useContactMomentStore() + + store.setContactMomentList(mockContactMoment()) + + expect(store.contactMomentList).toHaveLength(mockContactMoment().length) + + store.contactMomentList.forEach((item, index) => { + expect(item).toBeInstanceOf(ContactMoment) + expect(item).toEqual(mockContactMoment()[index]) + expect(item.validate().success).toBe(true) + }) + }) +}) diff --git a/src/store/store.js b/src/store/store.js index db4aa4c..4009d31 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -8,7 +8,7 @@ import { useKlantStore } from './modules/klanten.js' import { useRolStore } from './modules/rol.js' import { useTaakStore } from './modules/taak.js' import { useSearchStore } from './modules/search.ts' - +import { useContactMomentStore } from './modules/contactmoment.js' const berichtStore = useBerichtStore(pinia) const klantStore = useKlantStore(pinia) const navigationStore = useNavigationStore(pinia) @@ -17,7 +17,7 @@ const taakStore = useTaakStore(pinia) const zaakStore = useZaakStore(pinia) const zaakTypeStore = useZaakTypeStore(pinia) const searchStore = useSearchStore(pinia) - +const contactMomentStore = useContactMomentStore(pinia) export { berichtStore, klantStore, @@ -27,4 +27,5 @@ export { zaakStore, zaakTypeStore, searchStore, + contactMomentStore, } From 44223b415d2eb34a04faaa3c2f60cea99bc34924 Mon Sep 17 00:00:00 2001 From: Remko Date: Tue, 26 Nov 2024 13:21:16 +0100 Subject: [PATCH 2/6] added bsn to klant --- src/entities/klanten/klanten.mock.ts | 1 + src/entities/klanten/klanten.ts | 3 +++ src/entities/klanten/klanten.types.ts | 1 + src/modals/klanten/EditKlant.vue | 8 ++++++++ src/views/klanten/KlantDetails.vue | 18 ++++++++++++++++-- 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/entities/klanten/klanten.mock.ts b/src/entities/klanten/klanten.mock.ts index b48e1eb..ef71a7b 100644 --- a/src/entities/klanten/klanten.mock.ts +++ b/src/entities/klanten/klanten.mock.ts @@ -20,6 +20,7 @@ export const mockKlantData = (): TKlant[] => [ subject: 'John Doe', subjectIdentificatie: '1234567890', subjectType: 'person', + bsn: '1234567890', }, ] diff --git a/src/entities/klanten/klanten.ts b/src/entities/klanten/klanten.ts index ef71d14..b0038e3 100644 --- a/src/entities/klanten/klanten.ts +++ b/src/entities/klanten/klanten.ts @@ -20,6 +20,7 @@ export class Klant implements TKlant { public subject: string public subjectIdentificatie: string public subjectType: string + public bsn: string constructor(source: TKlant) { this.id = source.id || '' @@ -39,6 +40,7 @@ export class Klant implements TKlant { this.subject = source.subject || '' this.subjectIdentificatie = source.subjectIdentificatie || '' this.subjectType = source.subjectType || '' + this.bsn = source.bsn || '' } public validate(): SafeParseReturnType { @@ -59,6 +61,7 @@ export class Klant implements TKlant { subject: z.string(), subjectIdentificatie: z.string(), subjectType: z.string(), + bsn: z.string(), }) return schema.safeParse(this) diff --git a/src/entities/klanten/klanten.types.ts b/src/entities/klanten/klanten.types.ts index 5f21bac..37e6a45 100644 --- a/src/entities/klanten/klanten.types.ts +++ b/src/entities/klanten/klanten.types.ts @@ -18,4 +18,5 @@ export type TKlant = { subject: string; subjectIdentificatie: string; subjectType: string; + bsn: string; } diff --git a/src/modals/klanten/EditKlant.vue b/src/modals/klanten/EditKlant.vue index 8368e47..39c0119 100644 --- a/src/modals/klanten/EditKlant.vue +++ b/src/modals/klanten/EditKlant.vue @@ -37,6 +37,11 @@ import { klantStore, navigationStore } from '../../store/store.js' maxlength="255" :value.sync="klantItem.achternaam" /> + +

- {{ klantStore.klantItem.voornaam }} {{ klantStore.klantItem.voorvoegsel }} {{ klantStore.klantItem.achternaam }} + {{ getName(klantStore.klantItem) }}

@@ -55,6 +55,10 @@ import { navigationStore, klantStore, taakStore, berichtStore, zaakStore } from Klantnummer:

{{ klantStore.klantItem.klantnummer }}

+
+ BSN: +

{{ klantStore.klantItem.bsn }}

+
Telefoonnummer: @@ -111,7 +115,7 @@ import { navigationStore, klantStore, taakStore, berichtStore, zaakStore } from
@@ -344,6 +348,16 @@ export default { console.error('Error fetching klant data:', error) }) }, + + getName(klant) { + if (klant.type === 'persoon') { + return `${klant.voornaam} ${klant.tussenvoegsel} ${klant.achternaam}` ?? 'onbekend' + } + if (klant.type === 'organisatie') { + return klant?.bedrijfsnaam ?? 'onbekend' + } + return 'onbekend' + }, }, } From 04319a5ab087b069b68b782c4a6a395fd6cc8c6f Mon Sep 17 00:00:00 2001 From: Remko Date: Tue, 26 Nov 2024 13:21:25 +0100 Subject: [PATCH 3/6] cleanup --- src/views/berichten/BerichtenList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/berichten/BerichtenList.vue b/src/views/berichten/BerichtenList.vue index 98d0da0..65707e7 100644 --- a/src/views/berichten/BerichtenList.vue +++ b/src/views/berichten/BerichtenList.vue @@ -33,7 +33,7 @@ import { navigationStore, berichtStore } from '../../store/store.js'
Date: Tue, 26 Nov 2024 13:26:34 +0100 Subject: [PATCH 4/6] Added contact moment form --- .../contactMomenten/ContactMomentenForm.vue | 431 ++++++++++++++++++ src/modals/klanten/SearchKlantModal.vue | 261 +++++++++++ src/views/widgets/ContactMomentenWidget.vue | 34 +- 3 files changed, 711 insertions(+), 15 deletions(-) create mode 100644 src/modals/contactMomenten/ContactMomentenForm.vue create mode 100644 src/modals/klanten/SearchKlantModal.vue diff --git a/src/modals/contactMomenten/ContactMomentenForm.vue b/src/modals/contactMomenten/ContactMomentenForm.vue new file mode 100644 index 0000000..dfb5dec --- /dev/null +++ b/src/modals/contactMomenten/ContactMomentenForm.vue @@ -0,0 +1,431 @@ + + + + + + + + + diff --git a/src/modals/klanten/SearchKlantModal.vue b/src/modals/klanten/SearchKlantModal.vue new file mode 100644 index 0000000..d3e2a66 --- /dev/null +++ b/src/modals/klanten/SearchKlantModal.vue @@ -0,0 +1,261 @@ + + + + + + + + + diff --git a/src/views/widgets/ContactMomentenWidget.vue b/src/views/widgets/ContactMomentenWidget.vue index 037623f..2dd4457 100644 --- a/src/views/widgets/ContactMomentenWidget.vue +++ b/src/views/widgets/ContactMomentenWidget.vue @@ -1,5 +1,5 @@ @@ -37,7 +38,7 @@ import { NcDashboardWidget, NcEmptyContent, NcButton } from '@nextcloud/vue' import { getTheme } from '../../services/getTheme.js' import Plus from 'vue-material-design-icons/Plus.vue' import ChatOutline from 'vue-material-design-icons/ChatOutline.vue' -import BerichtForm from '../../modals/berichten/EditBericht.vue' +import ContactMomentenForm from '../../modals/contactMomenten/ContactMomentenForm.vue' export default { name: 'ContactMomentenWidget', @@ -47,35 +48,37 @@ export default { NcEmptyContent, NcButton, Plus, + ContactMomentenForm, }, data() { return { loading: false, isModalOpen: false, - berichtItems: [], + searchKlantModalOpen: false, + contactMomentItems: [], } }, computed: { items() { - return this.berichtItems + return this.contactMomentItems }, }, mounted() { - this.fetchBerichtItems() + this.fetchContactMomentItems() }, methods: { - fetchBerichtItems() { + fetchContactMomentItems() { this.loading = true - berichtStore.refreshBerichtenList() + contactMomentStore.refreshContactMomentenList() .then(() => { - this.berichtItems = berichtStore.berichtenList.map(bericht => ({ - id: bericht.id, - mainText: bericht.title, - subText: bericht.aanmaakDatum, + this.contactMomentItems = contactMomentStore.contactMomentenList.map(contactMoment => ({ + id: contactMoment.id, + mainText: contactMoment.titel, + subText: new Date(contactMoment.startDate).toLocaleString(), avatarUrl: this.getItemIcon(), })) @@ -95,13 +98,14 @@ export default { }, openModal() { this.isModalOpen = true - berichtStore.setBerichtItem(null) - navigationStore.setModal('editBericht') + contactMomentStore.setContactMomentItem(null) + navigationStore.setModal('contactMomentenForm') }, closeModal() { this.isModalOpen = false navigationStore.setModal(null) }, + onShow() { window.open('/apps/opencatalogi/catalogi', '_self') }, From 167c4992d79ccbdea9c3d635e5f877c16e155e48 Mon Sep 17 00:00:00 2001 From: Remko Date: Tue, 26 Nov 2024 13:55:51 +0100 Subject: [PATCH 5/6] Added contactmoment to menu and added delete function --- src/modals/Modals.vue | 4 +- .../contactMomenten/DeleteContactMoment.vue | 99 +++++++++ src/navigation/MainMenu.vue | 10 + src/store/modules/navigation.ts | 88 ++++---- src/views/Views.vue | 4 +- .../contactMomenten/ContactMomentDetails.vue | 192 ++++++++++++++++++ .../contactMomenten/ContactMomentenIndex.vue | 46 +++++ .../contactMomenten/ContactMomentenList.vue | 175 ++++++++++++++++ 8 files changed, 572 insertions(+), 46 deletions(-) create mode 100644 src/modals/contactMomenten/DeleteContactMoment.vue create mode 100644 src/views/contactMomenten/ContactMomentDetails.vue create mode 100644 src/views/contactMomenten/ContactMomentenIndex.vue create mode 100644 src/views/contactMomenten/ContactMomentenList.vue diff --git a/src/modals/Modals.vue b/src/modals/Modals.vue index 65c4e2c..055d875 100644 --- a/src/modals/Modals.vue +++ b/src/modals/Modals.vue @@ -18,6 +18,7 @@ import { navigationStore } from '../store/store.js' +
@@ -35,7 +36,7 @@ import WidgetTaakForm from './taken/WidgetTaakForm.vue' import EditRol from './rollen/EditRol.vue' import ViewZaakAuditTrail from './zaken/ViewZaakAuditTrail.vue' import ViewKlantRegister from './klantRegister/ViewKlantRegister.vue' - +import DeleteContactMoment from './contactMomenten/DeleteContactMoment.vue' export default { name: 'Modals', components: { @@ -52,6 +53,7 @@ export default { EditRol, ViewZaakAuditTrail, ViewKlantRegister, + DeleteContactMoment, }, } diff --git a/src/modals/contactMomenten/DeleteContactMoment.vue b/src/modals/contactMomenten/DeleteContactMoment.vue new file mode 100644 index 0000000..675a8bf --- /dev/null +++ b/src/modals/contactMomenten/DeleteContactMoment.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/src/navigation/MainMenu.vue b/src/navigation/MainMenu.vue index 6ee59aa..9ad9dea 100644 --- a/src/navigation/MainMenu.vue +++ b/src/navigation/MainMenu.vue @@ -44,6 +44,14 @@ import { navigationStore } from '../store/store.js' + + + diff --git a/src/store/modules/navigation.ts b/src/store/modules/navigation.ts index 477e2c2..74ad48f 100644 --- a/src/store/modules/navigation.ts +++ b/src/store/modules/navigation.ts @@ -1,44 +1,44 @@ -/* eslint-disable no-console */ -import { defineStore } from 'pinia' - -interface NavigationStoreState { - selected: 'dashboard' | 'berichten' | 'klanten' | 'rollen' | 'taken' | 'zaken' | 'zaakTypen' | 'search' | 'auditTrail'; - modal: string; - dialog: string; - transferData: string; -} - -export const useNavigationStore = defineStore('ui', { - state: () => ({ - // The currently active menu item, defaults to '' which triggers the dashboard - 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 dialog - dialog: null, - // Any data needed in various models, dialogs, views which cannot be transferred through normal means or without writing bad/excessive code - transferData: null, - } as NavigationStoreState), - actions: { - setSelected(selected: NavigationStoreState['selected']) { - this.selected = selected - console.log('Active menu item set to ' + selected) - }, - setModal(modal: NavigationStoreState['modal']) { - this.modal = modal - console.log('Active modal set to ' + modal) - }, - setDialog(dialog: NavigationStoreState['dialog']) { - this.dialog = dialog - console.log('Active dialog set to ' + dialog) - }, - setTransferData(data: NavigationStoreState['transferData']) { - this.transferData = data - }, - getTransferData(): NavigationStoreState['transferData'] { - const tempData = this.transferData - this.transferData = null - return tempData - }, - }, -}) +/* eslint-disable no-console */ +import { defineStore } from 'pinia' + +interface NavigationStoreState { + selected: 'dashboard' | 'berichten' | 'klanten' | 'rollen' | 'taken' | 'zaken' | 'zaakTypen' | 'search' | 'auditTrail' | 'contactMomenten'; + modal: string; + dialog: string; + transferData: string; +} + +export const useNavigationStore = defineStore('ui', { + state: () => ({ + // The currently active menu item, defaults to '' which triggers the dashboard + 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 dialog + dialog: null, + // Any data needed in various models, dialogs, views which cannot be transferred through normal means or without writing bad/excessive code + transferData: null, + } as NavigationStoreState), + actions: { + setSelected(selected: NavigationStoreState['selected']) { + this.selected = selected + console.log('Active menu item set to ' + selected) + }, + setModal(modal: NavigationStoreState['modal']) { + this.modal = modal + console.log('Active modal set to ' + modal) + }, + setDialog(dialog: NavigationStoreState['dialog']) { + this.dialog = dialog + console.log('Active dialog set to ' + dialog) + }, + setTransferData(data: NavigationStoreState['transferData']) { + this.transferData = data + }, + getTransferData(): NavigationStoreState['transferData'] { + const tempData = this.transferData + this.transferData = null + return tempData + }, + }, +}) diff --git a/src/views/Views.vue b/src/views/Views.vue index 15c6df3..b370582 100644 --- a/src/views/Views.vue +++ b/src/views/Views.vue @@ -17,6 +17,7 @@ import { navigationStore } from '../store/store.js' + @@ -35,7 +36,7 @@ import StatusssenIndex from './statussen/StatussenIndex.vue' import TakenIndex from './taken/TakenIndex.vue' import ZaakTypenIndex from './zaakTypen/ZakenTypenIndex.vue' import ZakenIndex from './zaken/ZakenIndex.vue' - +import ContactMomentenIndex from './contactMomenten/ContactMomentenIndex.vue' export default { name: 'Views', components: { @@ -43,6 +44,7 @@ export default { BesluitenIndex, DashboardIndex, SearchIndex, + ContactMomentenIndex, DocumentenIndex, KlantenIndex, ResultatenIndex, diff --git a/src/views/contactMomenten/ContactMomentDetails.vue b/src/views/contactMomenten/ContactMomentDetails.vue new file mode 100644 index 0000000..05c5059 --- /dev/null +++ b/src/views/contactMomenten/ContactMomentDetails.vue @@ -0,0 +1,192 @@ + + + + + + + diff --git a/src/views/contactMomenten/ContactMomentenIndex.vue b/src/views/contactMomenten/ContactMomentenIndex.vue new file mode 100644 index 0000000..ca70bc1 --- /dev/null +++ b/src/views/contactMomenten/ContactMomentenIndex.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/views/contactMomenten/ContactMomentenList.vue b/src/views/contactMomenten/ContactMomentenList.vue new file mode 100644 index 0000000..9a9ea39 --- /dev/null +++ b/src/views/contactMomenten/ContactMomentenList.vue @@ -0,0 +1,175 @@ + + + + + From fb07c6ba29731207ad01f2bc0f73253d367034a0 Mon Sep 17 00:00:00 2001 From: Remko Date: Tue, 26 Nov 2024 15:54:41 +0100 Subject: [PATCH 6/6] Updated klant search --- src/data/countries.js | 782 ++++++++++++++++++ src/entities/klanten/klanten.mock.ts | 9 +- src/entities/klanten/klanten.ts | 31 +- src/entities/klanten/klanten.types.ts | 9 +- .../contactMomenten/ContactMomentenForm.vue | 12 +- src/modals/klanten/EditKlant.vue | 107 ++- src/modals/klanten/SearchKlantModal.vue | 179 ++-- src/store/modules/klanten.js | 24 + src/views/klanten/KlantDetails.vue | 34 +- 9 files changed, 1083 insertions(+), 104 deletions(-) create mode 100644 src/data/countries.js diff --git a/src/data/countries.js b/src/data/countries.js new file mode 100644 index 0000000..600eca8 --- /dev/null +++ b/src/data/countries.js @@ -0,0 +1,782 @@ +export const countries = [ + { + code: 'AF', + name: 'Afghanistan', + }, + { + code: 'AL', + name: 'Albanië', + }, + { + code: 'DZ', + name: 'Algerije', + }, + { + code: 'AD', + name: 'Andorra', + }, + { + code: 'AO', + name: 'Angola', + }, + { + code: 'AG', + name: 'Antigua en Barbuda', + }, + { + code: 'AR', + name: 'Argentinië', + }, + { + code: 'AM', + name: 'Armenië', + }, + { + code: 'AU', + name: 'Australië', + }, + { + code: 'AT', + name: 'Oostenrijk', + }, + { + code: 'AZ', + name: 'Azerbeidzjan', + }, + { + code: 'BS', + name: 'Bahama\'s', + }, + { + code: 'BH', + name: 'Bahrein', + }, + { + code: 'BD', + name: 'Bangladesh', + }, + { + code: 'BB', + name: 'Barbados', + }, + { + code: 'BY', + name: 'Belarus', + }, + { + code: 'BE', + name: 'België', + }, + { + code: 'BZ', + name: 'Belize', + }, + { + code: 'BJ', + name: 'Benin', + }, + { + code: 'BT', + name: 'Bhutan', + }, + { + code: 'BO', + name: 'Bolivia', + }, + { + code: 'BA', + name: 'Bosnië en Herzegovina', + }, + { + code: 'BW', + name: 'Botswana', + }, + { + code: 'BR', + name: 'Brazilië', + }, + { + code: 'BN', + name: 'Brunei', + }, + { + code: 'BG', + name: 'Bulgarije', + }, + { + code: 'BF', + name: 'Burkina Faso', + }, + { + code: 'BI', + name: 'Burundi', + }, + { + code: 'KH', + name: 'Cambodja', + }, + { + code: 'CM', + name: 'Kameroen', + }, + { + code: 'CA', + name: 'Canada', + }, + { + code: 'CV', + name: 'Kaapverdië', + }, + { + code: 'CF', + name: 'Centraal-Afrikaanse Republiek', + }, + { + code: 'TD', + name: 'Tsjaad', + }, + { + code: 'CL', + name: 'Chili', + }, + { + code: 'CN', + name: 'China', + }, + { + code: 'CO', + name: 'Colombia', + }, + { + code: 'KM', + name: 'Comoren', + }, + { + code: 'CG', + name: 'Congo-Brazzaville', + }, + { + code: 'CD', + name: 'Congo-Kinshasa', + }, + { + code: 'CR', + name: 'Costa Rica', + }, + { + code: 'HR', + name: 'Kroatië', + }, + { + code: 'CU', + name: 'Cuba', + }, + { + code: 'CY', + name: 'Cyprus', + }, + { + code: 'CZ', + name: 'Tsjechië', + }, + { + code: 'DK', + name: 'Denemarken', + }, + { + code: 'DJ', + name: 'Djibouti', + }, + { + code: 'DM', + name: 'Dominica', + }, + { + code: 'DO', + name: 'Dominicaanse Republiek', + }, + { + code: 'EC', + name: 'Ecuador', + }, + { + code: 'EG', + name: 'Egypte', + }, + { + code: 'SV', + name: 'El Salvador', + }, + { + code: 'GQ', + name: 'Equatoriaal-Guinea', + }, + { + code: 'ER', + name: 'Eritrea', + }, + { + code: 'EE', + name: 'Estland', + }, + { + code: 'SZ', + name: 'Eswatini', + }, + { + code: 'ET', + name: 'Ethiopië', + }, + { + code: 'FJ', + name: 'Fiji', + }, + { + code: 'FI', + name: 'Finland', + }, + { + code: 'FR', + name: 'Frankrijk', + }, + { + code: 'GA', + name: 'Gabon', + }, + { + code: 'GM', + name: 'Gambia', + }, + { + code: 'GE', + name: 'Georgië', + }, + { + code: 'DE', + name: 'Duitsland', + }, + { + code: 'GH', + name: 'Ghana', + }, + { + code: 'GR', + name: 'Griekenland', + }, + { + code: 'GD', + name: 'Grenada', + }, + { + code: 'GT', + name: 'Guatemala', + }, + { + code: 'GN', + name: 'Guinee', + }, + { + code: 'GW', + name: 'Guinee-Bissau', + }, + { + code: 'GY', + name: 'Guyana', + }, + { + code: 'HT', + name: 'Haïti', + }, + { + code: 'HN', + name: 'Honduras', + }, + { + code: 'HU', + name: 'Hongarije', + }, + { + code: 'IS', + name: 'IJsland', + }, + { + code: 'IN', + name: 'India', + }, + { + code: 'ID', + name: 'Indonesië', + }, + { + code: 'IR', + name: 'Iran', + }, + { + code: 'IQ', + name: 'Irak', + }, + { + code: 'IE', + name: 'Ierland', + }, + { + code: 'IL', + name: 'Israël', + }, + { + code: 'IT', + name: 'Italië', + }, + { + code: 'JM', + name: 'Jamaica', + }, + { + code: 'JP', + name: 'Japan', + }, + { + code: 'JO', + name: 'Jordanië', + }, + { + code: 'KZ', + name: 'Kazachstan', + }, + { + code: 'KE', + name: 'Kenia', + }, + { + code: 'KI', + name: 'Kiribati', + }, + { + code: 'KP', + name: 'Noord-Korea', + }, + { + code: 'KR', + name: 'Zuid-Korea', + }, + { + code: 'KW', + name: 'Koeweit', + }, + { + code: 'KG', + name: 'Kirgizië', + }, + { + code: 'LA', + name: 'Laos', + }, + { + code: 'LV', + name: 'Letland', + }, + { + code: 'LB', + name: 'Libanon', + }, + { + code: 'LS', + name: 'Lesotho', + }, + { + code: 'LR', + name: 'Liberia', + }, + { + code: 'LY', + name: 'Libië', + }, + { + code: 'LI', + name: 'Liechtenstein', + }, + { + code: 'LT', + name: 'Litouwen', + }, + { + code: 'LU', + name: 'Luxemburg', + }, + { + code: 'MG', + name: 'Madagaskar', + }, + { + code: 'MW', + name: 'Malawi', + }, + { + code: 'MY', + name: 'Maleisië', + }, + { + code: 'MV', + name: 'Maldiven', + }, + { + code: 'ML', + name: 'Mali', + }, + { + code: 'MT', + name: 'Malta', + }, + { + code: 'MH', + name: 'Marshalleilanden', + }, + { + code: 'MR', + name: 'Mauritanië', + }, + { + code: 'MU', + name: 'Mauritius', + }, + { + code: 'MX', + name: 'Mexico', + }, + { + code: 'FM', + name: 'Micronesië', + }, + { + code: 'MD', + name: 'Moldavië', + }, + { + code: 'MC', + name: 'Monaco', + }, + { + code: 'MN', + name: 'Mongolië', + }, + { + code: 'ME', + name: 'Montenegro', + }, + { + code: 'MA', + name: 'Marokko', + }, + { + code: 'MZ', + name: 'Mozambique', + }, + { + code: 'MM', + name: 'Myanmar', + }, + { + code: 'NA', + name: 'Namibië', + }, + { + code: 'NR', + name: 'Nauru', + }, + { + code: 'NP', + name: 'Nepal', + }, + { + code: 'NL', + name: 'Nederland', + }, + { + code: 'NZ', + name: 'Nieuw-Zeeland', + }, + { + code: 'NI', + name: 'Nicaragua', + }, + { + code: 'NE', + name: 'Niger', + }, + { + code: 'NG', + name: 'Nigeria', + }, + { + code: 'MK', + name: 'Noord-Macedonië', + }, + { + code: 'NO', + name: 'Noorwegen', + }, + { + code: 'OM', + name: 'Oman', + }, + { + code: 'PK', + name: 'Pakistan', + }, + { + code: 'PW', + name: 'Palau', + }, + { + code: 'PS', + name: 'Palestina', + }, + { + code: 'PA', + name: 'Panama', + }, + { + code: 'PG', + name: 'Papoea-Nieuw-Guinea', + }, + { + code: 'PY', + name: 'Paraguay', + }, + { + code: 'PE', + name: 'Peru', + }, + { + code: 'PH', + name: 'Filipijnen', + }, + { + code: 'PL', + name: 'Polen', + }, + { + code: 'PT', + name: 'Portugal', + }, + { + code: 'QA', + name: 'Qatar', + }, + { + code: 'RO', + name: 'Roemenië', + }, + { + code: 'RU', + name: 'Rusland', + }, + { + code: 'RW', + name: 'Rwanda', + }, + { + code: 'KN', + name: 'Saint Kitts en Nevis', + }, + { + code: 'LC', + name: 'Saint Lucia', + }, + { + code: 'VC', + name: 'Saint Vincent en de Grenadines', + }, + { + code: 'WS', + name: 'Samoa', + }, + { + code: 'SM', + name: 'San Marino', + }, + { + code: 'ST', + name: 'Sao Tomé en Principe', + }, + { + code: 'SA', + name: 'Saudi-Arabië', + }, + { + code: 'SN', + name: 'Senegal', + }, + { + code: 'RS', + name: 'Servië', + }, + { + code: 'SC', + name: 'Seychellen', + }, + { + code: 'SL', + name: 'Sierra Leone', + }, + { + code: 'SG', + name: 'Singapore', + }, + { + code: 'SK', + name: 'Slowakije', + }, + { + code: 'SI', + name: 'Slovenië', + }, + { + code: 'SB', + name: 'Salomonseilanden', + }, + { + code: 'SO', + name: 'Somalië', + }, + { + code: 'ZA', + name: 'Zuid-Afrika', + }, + { + code: 'SS', + name: 'Zuid-Soedan', + }, + { + code: 'ES', + name: 'Spanje', + }, + { + code: 'LK', + name: 'Sri Lanka', + }, + { + code: 'SD', + name: 'Soedan', + }, + { + code: 'SR', + name: 'Suriname', + }, + { + code: 'SE', + name: 'Zweden', + }, + { + code: 'CH', + name: 'Zwitserland', + }, + { + code: 'SY', + name: 'Syrië', + }, + { + code: 'TW', + name: 'Taiwan', + }, + { + code: 'TJ', + name: 'Tadzjikistan', + }, + { + code: 'TZ', + name: 'Tanzania', + }, + { + code: 'TH', + name: 'Thailand', + }, + { + code: 'TL', + name: 'Oost-Timor', + }, + { + code: 'TG', + name: 'Togo', + }, + { + code: 'TO', + name: 'Tonga', + }, + { + code: 'TT', + name: 'Trinidad en Tobago', + }, + { + code: 'TN', + name: 'Tunesië', + }, + { + code: 'TR', + name: 'Turkije', + }, + { + code: 'TM', + name: 'Turkmenistan', + }, + { + code: 'TV', + name: 'Tuvalu', + }, + { + code: 'UG', + name: 'Oeganda', + }, + { + code: 'UA', + name: 'Oekraïne', + }, + { + code: 'AE', + name: 'Verenigde Arabische Emiraten', + }, + { + code: 'GB', + name: 'Verenigd Koninkrijk', + }, + { + code: 'US', + name: 'Verenigde Staten', + }, + { + code: 'UY', + name: 'Uruguay', + }, + { + code: 'UZ', + name: 'Oezbekistan', + }, + { + code: 'VU', + name: 'Vanuatu', + }, + { + code: 'VA', + name: 'Vaticaanstad', + }, + { + code: 'VE', + name: 'Venezuela', + }, + { + code: 'VN', + name: 'Vietnam', + }, + { + code: 'YE', + name: 'Jemen', + }, + { + code: 'ZM', + name: 'Zambia', + }, + { + code: 'ZW', + name: 'Zimbabwe', + }, +] diff --git a/src/entities/klanten/klanten.mock.ts b/src/entities/klanten/klanten.mock.ts index ef71a7b..4642e10 100644 --- a/src/entities/klanten/klanten.mock.ts +++ b/src/entities/klanten/klanten.mock.ts @@ -8,11 +8,19 @@ export const mockKlantData = (): TKlant[] => [ voornaam: 'John', tussenvoegsel: 'de', achternaam: 'Doe', + bsn: '1234567890', + geboortedatum: '1990-01-01', + land: 'Nederland', telefoonnummer: '0612345678', emailadres: 'john.doe@example.com', + straatnaam: 'Example Street', + plaats: 'Example City', + postcode: '1234AB', + huisnummer: '123', functie: 'Software Developer', aanmaakkanaal: 'email', bronorganisatie: 'Example Corp', + kvkNummer: '1234567890', bedrijfsnaam: 'Example Corp', websiteUrl: 'http://example.com', url: 'http://example.com', @@ -20,7 +28,6 @@ export const mockKlantData = (): TKlant[] => [ subject: 'John Doe', subjectIdentificatie: '1234567890', subjectType: 'person', - bsn: '1234567890', }, ] diff --git a/src/entities/klanten/klanten.ts b/src/entities/klanten/klanten.ts index b0038e3..4675a7c 100644 --- a/src/entities/klanten/klanten.ts +++ b/src/entities/klanten/klanten.ts @@ -5,22 +5,33 @@ export class Klant implements TKlant { public id: string public type: TKlantType + public voornaam: string public tussenvoegsel: string public achternaam: string + public bsn: string + public geboortedatum: string + public land: string + public telefoonnummer: string public emailadres: string + + public straatnaam: string + public plaats: string + public postcode: string + public huisnummer: string + public functie: string public aanmaakkanaal: string public bronorganisatie: string public bedrijfsnaam: string + public kvkNummer: string public websiteUrl: string public url: string public geverifieerd: string public subject: string public subjectIdentificatie: string public subjectType: string - public bsn: string constructor(source: TKlant) { this.id = source.id || '' @@ -28,19 +39,26 @@ export class Klant implements TKlant { this.voornaam = source.voornaam || '' this.tussenvoegsel = source.tussenvoegsel || '' this.achternaam = source.achternaam || '' + this.bsn = source.bsn || '' + this.geboortedatum = source.geboortedatum || '' + this.land = source.land || '' this.telefoonnummer = source.telefoonnummer || '' this.emailadres = source.emailadres || '' + this.straatnaam = source.straatnaam || '' + this.plaats = source.plaats || '' + this.postcode = source.postcode || '' + this.huisnummer = source.huisnummer || '' this.functie = source.functie || '' this.aanmaakkanaal = source.aanmaakkanaal || '' this.bronorganisatie = source.bronorganisatie || '' this.bedrijfsnaam = source.bedrijfsnaam || '' + this.kvkNummer = source.kvkNummer || '' this.websiteUrl = source.websiteUrl || '' this.url = source.url || '' this.geverifieerd = source.geverifieerd || '' this.subject = source.subject || '' this.subjectIdentificatie = source.subjectIdentificatie || '' this.subjectType = source.subjectType || '' - this.bsn = source.bsn || '' } public validate(): SafeParseReturnType { @@ -49,19 +67,26 @@ export class Klant implements TKlant { voornaam: z.string().min(1), tussenvoegsel: z.string(), achternaam: z.string(), + bsn: z.string(), + geboortedatum: z.string(), + land: z.string(), telefoonnummer: z.string(), emailadres: z.string().email(), + straatnaam: z.string(), + plaats: z.string(), + postcode: z.string(), + huisnummer: z.string(), functie: z.string(), aanmaakkanaal: z.string(), bronorganisatie: z.string(), bedrijfsnaam: z.string(), + kvkNummer: z.string(), websiteUrl: z.string().url(), url: z.string().url(), geverifieerd: z.string(), subject: z.string(), subjectIdentificatie: z.string(), subjectType: z.string(), - bsn: z.string(), }) return schema.safeParse(this) diff --git a/src/entities/klanten/klanten.types.ts b/src/entities/klanten/klanten.types.ts index 37e6a45..2c59511 100644 --- a/src/entities/klanten/klanten.types.ts +++ b/src/entities/klanten/klanten.types.ts @@ -6,17 +6,24 @@ export type TKlant = { voornaam: string; tussenvoegsel: string; achternaam: string; + bsn: string; + geboortedatum: string; + land: string; telefoonnummer: string; emailadres: string; + straatnaam: string; + plaats: string; + postcode: string; + huisnummer: string; functie: string; aanmaakkanaal: string; bronorganisatie: string; bedrijfsnaam: string; + kvkNummer: string; websiteUrl: string; url: string; geverifieerd: string; subject: string; subjectIdentificatie: string; subjectType: string; - bsn: string; } diff --git a/src/modals/contactMomenten/ContactMomentenForm.vue b/src/modals/contactMomenten/ContactMomentenForm.vue index dfb5dec..4fa8a57 100644 --- a/src/modals/contactMomenten/ContactMomentenForm.vue +++ b/src/modals/contactMomenten/ContactMomentenForm.vue @@ -34,7 +34,7 @@ import { navigationStore } from '../../store/store.js' + @click="openSearchKlantModal('persoon')"> @@ -48,7 +48,7 @@ import { navigationStore } from '../../store/store.js' + @click="openSearchKlantModal('organisatie')"> @@ -147,6 +147,7 @@ import { navigationStore } from '../../store/store.js'
@@ -250,6 +251,7 @@ export default { selectedZaak: null, selectedTaak: null, selectedProduct: null, + startingType: 'all', } }, mounted() { @@ -304,6 +306,12 @@ export default { }) }, + // Search functions + openSearchKlantModal(type) { + this.searchKlantModalOpen = true + this.startingType = type + }, + // Klant functions closeSearchKlantModal() { this.searchKlantModalOpen = false diff --git a/src/modals/klanten/EditKlant.vue b/src/modals/klanten/EditKlant.vue index 39c0119..35db834 100644 --- a/src/modals/klanten/EditKlant.vue +++ b/src/modals/klanten/EditKlant.vue @@ -41,6 +41,18 @@ import { klantStore, navigationStore } from '../../store/store.js' label="BSN" maxlength="255" :value.sync="klantItem.bsn" /> +
+

Geboortedatum

+ +
+ + + + + + + + + + + ({ + id: country.code, + label: country.name, + })), + }, klantItem: { voornaam: '', type: 'persoon', tussenvoegsel: '', achternaam: '', bsn: '', + geboortedatum: '', + land: '', telefoonnummer: '', emailadres: '', + straatnaam: '', + plaats: '', + postcode: '', + huisnummer: '', functie: '', aanmaakkanaal: '', bronorganisatie: '', bedrijfsnaam: '', + kvkNummer: '', websiteUrl: '', url: '', geverifieerd: '', @@ -193,11 +248,18 @@ export default { }, } }, + computed: { + items() { + return this.contactMomentItems + }, + }, updated() { if (navigationStore.modal === 'editKlant' && !this.hasUpdated) { const klantType = this.typeOptions.options.find((option) => option.value === klantStore.klantItem?.type) + const country = this.countryOptions.options.find((option) => option.id === klantStore.klantItem?.land) + if (klantStore.klantItem?.id) { this.klantItem = { ...klantStore.klantItem, @@ -206,12 +268,19 @@ export default { tussenvoegsel: klantStore.klantItem.tussenvoegsel || '', achternaam: klantStore.klantItem.achternaam || '', bsn: klantStore.klantItem.bsn || '', + geboortedatum: klantStore.klantItem.geboortedatum ? new Date(klantStore.klantItem.geboortedatum) : '', + land: country || '', telefoonnummer: klantStore.klantItem.telefoonnummer || '', emailadres: klantStore.klantItem.emailadres || '', + straatnaam: klantStore.klantItem.straatnaam || '', + plaats: klantStore.klantItem.plaats || '', + postcode: klantStore.klantItem.postcode || '', + huisnummer: klantStore.klantItem.huisnummer || '', functie: klantStore.klantItem.functie || '', aanmaakkanaal: klantStore.klantItem.aanmaakkanaal || '', bronorganisatie: klantStore.klantItem.bronorganisatie || '', bedrijfsnaam: klantStore.klantItem.bedrijfsnaam || '', + kvkNummer: klantStore.klantItem.kvkNummer || '', websiteUrl: klantStore.klantItem.websiteUrl || '', url: klantStore.klantItem.url || '', geverifieerd: klantStore.klantItem.geverifieerd || '', @@ -236,12 +305,19 @@ export default { tussenvoegsel: '', achternaam: '', bsn: '', + geboortedatum: '', + land: '', telefoonnummer: '', emailadres: '', + straatnaam: '', + plaats: '', + postcode: '', + huisnummer: '', functie: '', aanmaakkanaal: '', bronorganisatie: '', bedrijfsnaam: '', + kvkNummer: '', websiteUrl: '', url: '', geverifieerd: '', @@ -252,10 +328,13 @@ export default { }, async editKlant() { this.loading = true + try { await klantStore.saveKlant({ ...this.klantItem, type: this.klantItem.type.value, + geboortedatum: this.klantItem.geboortedatum !== '' && new Date(this.klantItem.geboortedatum).toISOString(), + land: this.klantItem.land.id, }) this.success = true this.loading = false @@ -273,30 +352,8 @@ export default { } - diff --git a/src/modals/klanten/SearchKlantModal.vue b/src/modals/klanten/SearchKlantModal.vue index d3e2a66..5b09c0a 100644 --- a/src/modals/klanten/SearchKlantModal.vue +++ b/src/modals/klanten/SearchKlantModal.vue @@ -1,5 +1,5 @@