From 74754022cae757811bb5e4104ee1dc8e1049d78c Mon Sep 17 00:00:00 2001 From: patrickpeinanw <144158754+patrickpeinanw@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:58:59 -0700 Subject: [PATCH] Side accordions for addresses, directors, partners and proprietors (#6) * set up basic dashboard template and UI for address accordion * update AddressAccordion * update i18n text * set up current directors accordion * Side accordions for directors, partners, and proprietors * fix AddressDisplay unit test * cypress tests --------- Co-authored-by: Patrick Wang --- cypress/e2e/accessibility/business-dash.cy.ts | 2 + cypress/e2e/components/addresses.cy.ts | 38 ++++ cypress/e2e/components/parties.cy.ts | 23 +++ cypress/fixtures/address.json | 50 +++++ cypress/fixtures/addressSFandGF.json | 26 +++ cypress/fixtures/directorParties.json | 184 ++++++++++++++++++ cypress/fixtures/partnerParties.json | 112 +++++++++++ cypress/fixtures/proprietorParties.json | 40 ++++ cypress/support/commands.ts | 45 +++++ package.json | 3 + pnpm-lock.yaml | 23 +++ src/app.config.ts | 5 +- src/components/bcros/Accordion.vue | 46 +++++ src/components/bcros/AccordionItem.vue | 27 +++ src/components/bcros/Address.vue | 40 ++++ src/components/bcros/AddressDisplay.vue | 7 +- src/components/bcros/DetailsInfoBox.vue | 25 +++ src/components/bcros/Footer.vue | 6 +- src/components/bcros/OfficeAddress.vue | 62 ++++++ src/components/bcros/PartyInfo.vue | 65 +++++++ src/enums/address-type-e.ts | 4 + src/enums/party-type-e.ts | 5 + src/enums/role-type-e.ts | 12 +- src/interfaces/accordion-item-i.ts | 9 + src/interfaces/address-i.ts | 22 ++- src/interfaces/officer.i.ts | 13 ++ src/interfaces/parties-i.ts | 10 + src/interfaces/role-i.ts | 5 + src/lang/en.json | 21 +- src/pages/dashboard.vue | 125 +++++++++++- src/stores/business.ts | 57 +++++- src/utils/is-same.ts | 13 ++ .../bcros/BcrosAddressDisplay.spec.ts | 29 +-- 33 files changed, 1117 insertions(+), 37 deletions(-) create mode 100644 cypress/e2e/components/addresses.cy.ts create mode 100644 cypress/e2e/components/parties.cy.ts create mode 100644 cypress/fixtures/address.json create mode 100644 cypress/fixtures/addressSFandGF.json create mode 100644 cypress/fixtures/directorParties.json create mode 100644 cypress/fixtures/partnerParties.json create mode 100644 cypress/fixtures/proprietorParties.json create mode 100644 src/components/bcros/Accordion.vue create mode 100644 src/components/bcros/AccordionItem.vue create mode 100644 src/components/bcros/Address.vue create mode 100644 src/components/bcros/DetailsInfoBox.vue create mode 100644 src/components/bcros/OfficeAddress.vue create mode 100644 src/components/bcros/PartyInfo.vue create mode 100644 src/enums/address-type-e.ts create mode 100644 src/enums/party-type-e.ts create mode 100644 src/interfaces/accordion-item-i.ts create mode 100644 src/interfaces/officer.i.ts create mode 100644 src/interfaces/parties-i.ts create mode 100644 src/interfaces/role-i.ts create mode 100644 src/utils/is-same.ts diff --git a/cypress/e2e/accessibility/business-dash.cy.ts b/cypress/e2e/accessibility/business-dash.cy.ts index 3584d01a..d6575bf1 100644 --- a/cypress/e2e/accessibility/business-dash.cy.ts +++ b/cypress/e2e/accessibility/business-dash.cy.ts @@ -4,6 +4,8 @@ context('Accessibility -> Business Dashboard', () => { }) it('check page passes accessibility after initial page load', () => { + cy.getOfficeAddresses() + cy.getDirectorParties() cy.get('[data-cy="business-dashboard"]').should('exist') cy.checkA11y('[data-cy="business-dashboard"]') }) diff --git a/cypress/e2e/components/addresses.cy.ts b/cypress/e2e/components/addresses.cy.ts new file mode 100644 index 00000000..64f2cbc6 --- /dev/null +++ b/cypress/e2e/components/addresses.cy.ts @@ -0,0 +1,38 @@ +context('Business dashboard -> Address side component', () => { + beforeEach(() => { + cy.visitBusinessDash() + }) + + it('Address accordion is rendered for Registered Office and Record Office', () => { + cy.getOfficeAddresses() + + // the accordion exists + cy.get('[data-cy="accordion_officeAddresses"]').should('exist') + + // accordion headers exist + cy.get('[data-cy="accordion_item_button_officeAddresses0"]').contains('Registered Office').should('be.visible') + cy.get('[data-cy="accordion_item_button_officeAddresses1"]').contains('Records Office').should('be.visible') + + // the first accordion item is expanded by default and it contain address information + cy.get('[data-cy="officeAddresses_0"]').contains('Delivery Address').should('be.visible') + cy.get('[data-cy="officeAddresses_0"]').contains('Mailing Address').should('be.visible') + cy.get('[data-cy="officeAddresses_1"]').contains('Delivery Address').should('not.be.visible') + cy.get('[data-cy="officeAddresses_1"]').contains('Mailing Address').should('not.be.visible') + + // expand the second item + cy.get('[data-cy="accordion_item_button_officeAddresses1"]').click() + + // Note: the current config allow only one item to be expanded + // This is different from the behavior of the old dashboard. + cy.get('[data-cy="officeAddresses_0"]').contains('Delivery Address').should('not.be.visible') + cy.get('[data-cy="officeAddresses_0"]').contains('Mailing Address').should('not.be.visible') + cy.get('[data-cy="officeAddresses_1"]').contains('Delivery Address').should('be.visible') + cy.get('[data-cy="officeAddresses_1"]').contains('Mailing Address').should('be.visible') + }) + + it('Business Addresses section is rendered for SP and GP', () => { + cy.getBusinessAddresses() + cy.get('[data-cy="accordion_officeAddresses"]').should('not.exist') + cy.get('[data-cy="businessAddresses"]').should('exist') + }) +}) diff --git a/cypress/e2e/components/parties.cy.ts b/cypress/e2e/components/parties.cy.ts new file mode 100644 index 00000000..8629972a --- /dev/null +++ b/cypress/e2e/components/parties.cy.ts @@ -0,0 +1,23 @@ +context('Business dashboard -> Parties side components', () => { + beforeEach(() => { + cy.visitBusinessDash() + }) + + it('Directors accordion is rendered', () => { + cy.getDirectorParties() + cy.get('[data-cy="accordion_directors"]').should('exist') + cy.get('[data-cy="accordion_directors"]').children().eq(0).children().should('have.length', 5) + }) + + it('Partners accordion is rendered', () => { + cy.getPartnerParties() + cy.get('[data-cy="accordion_partners"]').should('exist') + cy.get('[data-cy="accordion_partners"]').children().eq(0).children().should('have.length', 3) + }) + + it('Proprietors accordion is rendered', () => { + cy.getProprietorParties() + cy.get('[data-cy="accordion_proprietors"]').should('exist') + cy.get('[data-cy="accordion_proprietors"]').children().eq(0).children().should('have.length', 1) + }) +}) diff --git a/cypress/fixtures/address.json b/cypress/fixtures/address.json new file mode 100644 index 00000000..7777d877 --- /dev/null +++ b/cypress/fixtures/address.json @@ -0,0 +1,50 @@ +{ + "recordsOffice": { + "deliveryAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "addressType": "delivery", + "deliveryInstructions": "", + "id": 2716699, + "postalCode": "V6J 5L2", + "streetAddress": "201-1768 8th Ave W", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "addressType": "mailing", + "deliveryInstructions": "", + "id": 2716698, + "postalCode": "V6J 5L2", + "streetAddress": "201-1768 8th Ave W", + "streetAddressAdditional": "" + } + }, + "registeredOffice": { + "deliveryAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "addressType": "delivery", + "deliveryInstructions": "", + "id": 2716701, + "postalCode": "V6J 5L2", + "streetAddress": "201-1768 8th Ave W", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "addressType": "mailing", + "deliveryInstructions": "", + "id": 2716700, + "postalCode": "V6J 5L2", + "streetAddress": "201-1768 8th Ave W", + "streetAddressAdditional": "" + } + } +} \ No newline at end of file diff --git a/cypress/fixtures/addressSFandGF.json b/cypress/fixtures/addressSFandGF.json new file mode 100644 index 00000000..67b0da22 --- /dev/null +++ b/cypress/fixtures/addressSFandGF.json @@ -0,0 +1,26 @@ +{ + "businessOffice": { + "deliveryAddress": { + "addressCity": "Prince Rupert", + "addressCountry": "CA", + "addressRegion": "BC", + "addressType": "delivery", + "deliveryInstructions": null, + "id": 2776826, + "postalCode": "V8J 4C5", + "streetAddress": "153 Alpine Dr", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Prince Rupert", + "addressCountry": "CA", + "addressRegion": "BC", + "addressType": "mailing", + "deliveryInstructions": null, + "id": 2776825, + "postalCode": "V8J 4C5", + "streetAddress": "153 Alpine Dr", + "streetAddressAdditional": "" + } + } +} \ No newline at end of file diff --git a/cypress/fixtures/directorParties.json b/cypress/fixtures/directorParties.json new file mode 100644 index 00000000..3e933255 --- /dev/null +++ b/cypress/fixtures/directorParties.json @@ -0,0 +1,184 @@ +{ + "parties": [ + { + "deliveryAddress": { + "addressCity": "Oakville", + "addressCountry": "CA", + "addressRegion": "ON", + "deliveryInstructions": "", + "id": 2841040, + "postalCode": "L6M 4M6", + "streetAddress": "23-1489 Heritage Way", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Oakville", + "addressCountry": "CA", + "addressRegion": "ON", + "deliveryInstructions": "", + "id": 2841041, + "postalCode": "L6M 4M6", + "streetAddress": "23-1489 Heritage Way", + "streetAddressAdditional": "" + }, + "officer": { + "email": null, + "firstName": "SD", + "id": 578627, + "lastName": "S", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2024-04-02", + "cessationDate": null, + "roleType": "Director" + } + ] + }, + { + "deliveryAddress": { + "addressCity": "Oakville", + "addressCountry": "CA", + "addressRegion": "ON", + "deliveryInstructions": null, + "id": 2841026, + "postalCode": "L6M 4M6", + "streetAddress": "34-1489 Heritage Way", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Oakville", + "addressCountry": "CA", + "addressRegion": "ON", + "deliveryInstructions": null, + "id": 2841027, + "postalCode": "L6M 4M6", + "streetAddress": "34-1489 Heritage Way", + "streetAddressAdditional": "" + }, + "officer": { + "email": null, + "firstName": "SDF", + "id": 581750, + "lastName": "ASDF", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2024-04-02", + "cessationDate": null, + "roleType": "Director" + } + ] + }, + { + "deliveryAddress": { + "addressCity": "Oakville", + "addressCountry": "CA", + "addressRegion": "ON", + "deliveryInstructions": "", + "id": 2841036, + "postalCode": "L6M 4M6", + "streetAddress": "34-1489 Heritage Way", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Oakville", + "addressCountry": "CA", + "addressRegion": "ON", + "deliveryInstructions": "", + "id": 2841037, + "postalCode": "L6M 4M6", + "streetAddress": "34-1489 Heritage Way", + "streetAddressAdditional": "" + }, + "officer": { + "email": null, + "firstName": "KIAL", + "id": 581751, + "lastName": "TEST", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2024-04-02", + "cessationDate": null, + "roleType": "Director" + } + ] + }, + { + "deliveryAddress": { + "addressCity": "Edmonton", + "addressCountry": "CA", + "addressRegion": "AB", + "deliveryInstructions": null, + "id": 2841030, + "postalCode": "T6L 7G9", + "streetAddress": "324-5211 25 Ave NW", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Edmonton", + "addressCountry": "CA", + "addressRegion": "AB", + "deliveryInstructions": null, + "id": 2841031, + "postalCode": "T6L 7G9", + "streetAddress": "324-5211 25 Ave NW", + "streetAddressAdditional": "" + }, + "officer": { + "email": null, + "firstName": "SD", + "id": 581752, + "lastName": "S", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2024-04-02", + "cessationDate": null, + "roleType": "Director" + } + ] + }, + { + "deliveryAddress": { + "addressCity": "Pitt Meadows", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2841034, + "postalCode": "V3Y 1T2", + "streetAddress": "34-19032 Advent Rd", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Pitt Meadows", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2841035, + "postalCode": "V3Y 1T2", + "streetAddress": "34-19032 Advent Rd", + "streetAddressAdditional": "" + }, + "officer": { + "email": null, + "firstName": "DF", + "id": 581753, + "lastName": "ADF", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2024-04-02", + "cessationDate": null, + "roleType": "Director" + } + ] + } + ] +} \ No newline at end of file diff --git a/cypress/fixtures/partnerParties.json b/cypress/fixtures/partnerParties.json new file mode 100644 index 00000000..8ae0952c --- /dev/null +++ b/cypress/fixtures/partnerParties.json @@ -0,0 +1,112 @@ +{ + "parties": [ + { + "deliveryAddress": { + "addressCity": "Penticton", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2794490, + "postalCode": "V2A 5C6", + "streetAddress": "2-529 Main St", + "streetAddressAdditional": null + }, + "mailingAddress": { + "addressCity": "Penticton", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2794491, + "postalCode": "V2A 5C6", + "streetAddress": "2-529 Main St", + "streetAddressAdditional": null + }, + "officer": { + "email": "kial@daxiom.com", + "firstName": "KIAL", + "id": 579371, + "lastName": "JINNAH", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2024-01-12", + "cessationDate": null, + "roleType": "Partner" + } + ] + }, + { + "deliveryAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2776804, + "postalCode": "V6E 1V4", + "streetAddress": "203-1265 Beach Ave", + "streetAddressAdditional": null + }, + "mailingAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2776805, + "postalCode": "V6E 1V4", + "streetAddress": "203-1265 Beach Ave", + "streetAddressAdditional": null + }, + "officer": { + "email": "hrvoje.fekete+gov.bc.test1@gmail.com", + "firstName": "HRVOJE", + "id": 578175, + "lastName": "FEKETE", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2023-11-28", + "cessationDate": null, + "roleType": "Partner" + } + ] + }, + { + "deliveryAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2776806, + "postalCode": "V6E 1V4", + "streetAddress": "503-1265 Beach Ave", + "streetAddressAdditional": null + }, + "mailingAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2776807, + "postalCode": "V6E 1V4", + "streetAddress": "503-1265 Beach Ave", + "streetAddressAdditional": null + }, + "officer": { + "email": "hrvoje.fekete+gov.bc.test2@gmail.com", + "firstName": "HRVOJE2", + "id": 578176, + "lastName": "FEKETE2", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2023-11-28", + "cessationDate": null, + "roleType": "Partner" + } + ] + } + ] +} \ No newline at end of file diff --git a/cypress/fixtures/proprietorParties.json b/cypress/fixtures/proprietorParties.json new file mode 100644 index 00000000..313950fe --- /dev/null +++ b/cypress/fixtures/proprietorParties.json @@ -0,0 +1,40 @@ +{ + "parties": [ + { + "deliveryAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2776827, + "postalCode": "V6E 1V4", + "streetAddress": "203-1265 Beach Ave", + "streetAddressAdditional": "" + }, + "mailingAddress": { + "addressCity": "Vancouver", + "addressCountry": "CA", + "addressRegion": "BC", + "deliveryInstructions": null, + "id": 2776828, + "postalCode": "V6E 1V4", + "streetAddress": "203-1265 Beach Ave", + "streetAddressAdditional": "" + }, + "officer": { + "email": "hrvoje.fekete+gov.bc.test1@gmail.com", + "firstName": "HRVOJE", + "id": 578179, + "lastName": "FEKETE", + "partyType": "person" + }, + "roles": [ + { + "appointmentDate": "2023-11-28", + "cessationDate": null, + "roleType": "Proprietor" + } + ] + } + ] +} \ No newline at end of file diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index b03c0fdc..6309be86 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -34,6 +34,51 @@ Cypress.Commands.add('visitBusinessDash', () => { cy.injectAxe() }) +Cypress.Commands.add('getBusinessAddresses', () => { + sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true') + + cy.intercept('GET', '**/api/v2/businesses/**/addresses*', { fixture: 'addressSFandGF.json' }).as('getAddresses') + cy.visit('') + cy.wait(['@getAddresses']) + cy.injectAxe() +}) + +Cypress.Commands.add('getOfficeAddresses', () => { + sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true') + + cy.intercept('GET', '**/api/v2/businesses/**/addresses*', { fixture: 'address.json' }).as('getAddresses') + cy.visit('') + cy.wait(['@getAddresses']) + cy.injectAxe() +}) + +Cypress.Commands.add('getDirectorParties', () => { + sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true') + + cy.intercept('GET', '**/api/v2/businesses/**/parties*', { fixture: 'directorParties.json' }).as('getParties') + cy.visit('') + cy.wait(['@getParties']) + cy.injectAxe() +}) + +Cypress.Commands.add('getPartnerParties', () => { + sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true') + + cy.intercept('GET', '**/api/v2/businesses/**/parties*', { fixture: 'partnerParties.json' }).as('getParties') + cy.visit('') + cy.wait(['@getParties']) + cy.injectAxe() +}) + +Cypress.Commands.add('getProprietorParties', () => { + sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true') + + cy.intercept('GET', '**/api/v2/businesses/**/parties*', { fixture: 'proprietorParties.json' }).as('getParties') + cy.visit('') + cy.wait(['@getParties']) + cy.injectAxe() +}) + Cypress.Commands.add('visitBusinessDashAuthError', () => { sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true') cy.intercept('GET', '**/api/v1/users/**/settings', { statusCode: 500, body: {} }).as('getSettingsError') diff --git a/package.json b/package.json index 1274db1b..9c0469e4 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,12 @@ "@pinia/nuxt": "^0.5.1", "@vuepic/vue-datepicker": "^8.7.0", "@vueuse/core": "^10.10.0", + "country-list": "^2.3.0", "http-status-codes": "^2.3.0", "keycloak-js": "^24.0.4", "launchdarkly-vue-client-sdk": "^2.2.0", + "lodash.isequal": "^4.5.0", + "lodash.omit": "^4.5.0", "moment": "^2.30.1", "nuxt": "^3.11.2", "sass": "^1.77.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a32b511e..9ad23e05 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: '@vueuse/core': specifier: ^10.10.0 version: 10.10.0(vue@3.4.27) + country-list: + specifier: ^2.3.0 + version: 2.3.0 http-status-codes: specifier: ^2.3.0 version: 2.3.0 @@ -38,6 +41,12 @@ dependencies: launchdarkly-vue-client-sdk: specifier: ^2.2.0 version: 2.2.0(vue@3.4.27) + lodash.isequal: + specifier: ^4.5.0 + version: 4.5.0 + lodash.omit: + specifier: ^4.5.0 + version: 4.5.0 moment: specifier: ^2.30.1 version: 2.30.1 @@ -797,6 +806,7 @@ packages: /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead dependencies: '@humanwhocodes/object-schema': 2.0.3 debug: 4.3.4(supports-color@8.1.1) @@ -810,6 +820,7 @@ packages: /@humanwhocodes/object-schema@2.0.3: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead /@iconify-json/heroicons@1.1.21: resolution: {integrity: sha512-A+3L4KN+TjH3V8fQ2N2dkOOnLLxMgMBzO8RDT0P9YL+YzvLMIbe/lkDLSB8NB8x0DKWmkvTimoo1l4DKMwi7Zg==} @@ -4094,6 +4105,10 @@ packages: /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + /country-list@2.3.0: + resolution: {integrity: sha512-qZk66RlmQm7fQjMYWku1AyjlKPogjPEorAZJG88owPExoPV8EsyCcuFLvO2afTXHEhi9liVOoyd+5A6ZS5QwaA==} + dev: false + /crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -6748,6 +6763,10 @@ packages: /lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: false + /lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} dev: false @@ -6759,6 +6778,10 @@ packages: /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + /lodash.omit@4.5.0: + resolution: {integrity: sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==} + dev: false + /lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} dev: true diff --git a/src/app.config.ts b/src/app.config.ts index c367a9dd..78ba002c 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -6,8 +6,11 @@ export default defineAppConfig({ accordion: { wrapper: 'divide-y', container: 'border-gray-400', + item: { + color: 'text-gray-700' + }, default: { - class: 'm-0 p-3 text-gray-900 font-bold bg-gray-100 hover:bg-gray-200 rounded-none' + class: 'm-0 p-3 text-gray-900 font-bold bg-white hover:bg-gray-200 rounded-none' } }, alert: { diff --git a/src/components/bcros/Accordion.vue b/src/components/bcros/Accordion.vue new file mode 100644 index 00000000..9d03e862 --- /dev/null +++ b/src/components/bcros/Accordion.vue @@ -0,0 +1,46 @@ + + + diff --git a/src/components/bcros/AccordionItem.vue b/src/components/bcros/AccordionItem.vue new file mode 100644 index 00000000..6ba79880 --- /dev/null +++ b/src/components/bcros/AccordionItem.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/components/bcros/Address.vue b/src/components/bcros/Address.vue new file mode 100644 index 00000000..ad6d346a --- /dev/null +++ b/src/components/bcros/Address.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/components/bcros/AddressDisplay.vue b/src/components/bcros/AddressDisplay.vue index 04da1ef3..a3fb1467 100644 --- a/src/components/bcros/AddressDisplay.vue +++ b/src/components/bcros/AddressDisplay.vue @@ -7,7 +7,7 @@ > {{ addressLine }} - diff --git a/src/components/bcros/DetailsInfoBox.vue b/src/components/bcros/DetailsInfoBox.vue new file mode 100644 index 00000000..089dcb8d --- /dev/null +++ b/src/components/bcros/DetailsInfoBox.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/src/components/bcros/Footer.vue b/src/components/bcros/Footer.vue index 98ad3edf..2763e5e8 100644 --- a/src/components/bcros/Footer.vue +++ b/src/components/bcros/Footer.vue @@ -16,8 +16,8 @@ -
- {{ $t('label.footer.version') }} +
+ {{ $t('label.footer.version') }} - +
- TBD + - + + - TBD + + + + + + + + + + +
diff --git a/src/stores/business.ts b/src/stores/business.ts index 560b0bd3..f54877ec 100644 --- a/src/stores/business.ts +++ b/src/stores/business.ts @@ -4,7 +4,8 @@ import { StatusCodes } from 'http-status-codes' export const useBcrosBusiness = defineStore('bcros/business', () => { const currentBusiness: Ref = ref({} as BusinessI) const currentFolioNumber: Ref = ref('') - + const currentBusinessAddresses: Ref = ref({} as EntityAddressCollectionI) + const currentParties: Ref = ref({} as PartiesI) const currentBusinessIdentifier = computed((): string => currentBusiness.value.identifier) const currentBusinessName = computed((): string => { if (currentBusiness.value.alternateNames && currentBusiness.value.legalType === BusinessTypeE.SOLE_PROP) { @@ -63,6 +64,38 @@ export const useBcrosBusiness = defineStore('bcros/business', () => { }) } + async function getBusinessAddress (identifier: string, params?: object) { + return await useBcrosFetch(`${apiURL}/businesses/${identifier}/addresses`, { params }) + .then(({ data, error }) => { + if (error.value || !data.value) { + console.warn('Error fetching business addresses for', identifier) + errors.value.push({ + statusCode: error.value?.status || StatusCodes.INTERNAL_SERVER_ERROR, + message: error.value?.data?.message, + category: ErrorCategoryE.ENTITY_BASIC + }) + } + + return data.value + }) + } + + async function getParties (identifier: string, params?: object) { + return await useBcrosFetch(`${apiURL}/businesses/${identifier}/parties`, { params }) + .then(({ data, error }) => { + if (error.value || !data.value) { + console.warn('Error fetching parties for', identifier) + errors.value.push({ + statusCode: error.value?.status || StatusCodes.INTERNAL_SERVER_ERROR, + message: error.value?.data?.message, + category: ErrorCategoryE.ENTITY_BASIC + }) + } + + return data.value + }) + } + async function loadBusiness (identifier: string, force = false) { const businessCached = currentBusiness.value && identifier === currentBusinessIdentifier.value if (!businessCached || force) { @@ -72,20 +105,40 @@ export const useBcrosBusiness = defineStore('bcros/business', () => { async function loadBusinessContact (identifier: string, force = false) { const contactCached = currentBusinessContact.value && identifier === currentBusinessContact.value.businessIdentifier + await getBusinessAddress(identifier) if (!contactCached || force) { currentBusinessContact.value = await getBusinessContact(identifier) || {} as ContactBusinessI } } + async function loadBusinessAddresses (identifier: string, force = false) { + const addressesCached = currentBusinessAddresses && identifier === currentBusinessIdentifier.value + if (!addressesCached || force) { + currentBusinessAddresses.value = await getBusinessAddress(identifier) || {} as EntityAddressCollectionI + } + } + + async function loadParties (identifier: string, force = false) { + const partiesCached = currentParties && identifier === currentBusinessIdentifier.value + if (!partiesCached || force) { + currentParties.value = await getParties(identifier) || {} as PartiesI + } + } + return { currentBusiness, currentBusinessIdentifier, currentBusinessName, currentBusinessContact, currentFolioNumber, + currentBusinessAddresses, + currentParties, + getBusinessAddress, getBusinessContact, getBusinessDetails, loadBusiness, - loadBusinessContact + loadBusinessContact, + loadBusinessAddresses, + loadParties } }) diff --git a/src/utils/is-same.ts b/src/utils/is-same.ts new file mode 100644 index 00000000..fd537371 --- /dev/null +++ b/src/utils/is-same.ts @@ -0,0 +1,13 @@ +import isEqual from 'lodash.isequal' +import omit from 'lodash.omit' + +/** + * Compares two objects while omitting specified properties from the comparison. + * @param objA the first object to compare + * @param objB the second object to compare + * @param props an optional array of properties to omit during the comparison + * @returns a boolean indicating a match of objects + */ +export const isSame = (objA: object, objB: object, props: string[] = []): boolean => { + return isEqual({ ...omit(objA, props) }, { ...omit(objB, props) }) +} diff --git a/tests/components/bcros/BcrosAddressDisplay.spec.ts b/tests/components/bcros/BcrosAddressDisplay.spec.ts index 283f76ad..66afd6ca 100644 --- a/tests/components/bcros/BcrosAddressDisplay.spec.ts +++ b/tests/components/bcros/BcrosAddressDisplay.spec.ts @@ -1,12 +1,13 @@ import { describe, expect, it } from 'vitest' import { mount } from '@vue/test-utils' +import { getName } from 'country-list' import { BcrosAddressDisplay } from '#components' describe('AddressDisplay tests', () => { const addressFilled: AddressI = { addressCity: 'Vancouver', - addressCountry: 'Canada', + addressCountry: 'CA', addressRegion: 'BC', locationDescription: 'Cool house', postalCode: 'V1L 4T7', @@ -16,14 +17,14 @@ describe('AddressDisplay tests', () => { const addressPartial: Partial = { addressCity: 'Victoria', - addressCountry: 'Canada', + addressCountry: 'CA', addressRegion: 'BC', postalCode: 'V1K 5T8', streetAddress: '452 Waffles Street' } const addressMissingParts: Partial = { - addressCountry: 'Canada', + addressCountry: 'CA', addressRegion: '', locationDescription: 'Find me if you can', postalCode: null, @@ -39,11 +40,11 @@ describe('AddressDisplay tests', () => { expect(addressLines.at(0).text()).toBe(addressFilled.streetAddress) expect(addressLines.at(1).text()).toBe(addressFilled.streetAdditional) expect(addressLines.at(2).text()).toBe('Vancouver BC V1L 4T7') - expect(addressLines.at(3).text()).toBe(addressFilled.addressCountry) - // const locDesc = wrapper.find('[data-cy=location-description]') - // expect(locDesc.exists()).toBe(true) - // expect(locDesc.find('.title').text()).toBe('Location Description') - // expect(locDesc.find('[data-cy=content]').text()).toBe(addressFilled.locationDescription) + expect(addressLines.at(3).text()).toBe(getName(addressFilled.addressCountry)) + const locDesc = wrapper.find('[data-cy=location-description]') + expect(locDesc.exists()).toBe(true) + expect(locDesc.find('.title').text()).toBe('Location Description') + expect(locDesc.find('[data-cy=content]').text()).toBe(addressFilled.locationDescription) wrapper.unmount() }) @@ -57,7 +58,7 @@ describe('AddressDisplay tests', () => { expect(addressLines.length).toBe(3) expect(addressLines.at(0).text()).toBe(addressPartial.streetAddress) expect(addressLines.at(1).text()).toBe('Victoria BC V1K 5T8') - expect(addressLines.at(2).text()).toBe(addressPartial.addressCountry) + expect(addressLines.at(2).text()).toBe(getName(addressFilled.addressCountry)) expect(wrapper.find('[data-cy=location-description]').exists()).toBe(false) wrapper.unmount() @@ -70,11 +71,11 @@ describe('AddressDisplay tests', () => { expect(wrapper.find('[data-cy=address-display]').exists()).toBe(true) const addressLines = wrapper.findAll('[data-cy=address-line]') expect(addressLines.length).toBe(1) - expect(addressLines.at(0).text()).toBe(addressMissingParts.addressCountry) - // const locDesc = wrapper.find('[data-cy=location-description]') - // expect(locDesc.exists()).toBe(true) - // expect(locDesc.find('.title').text()).toBe('Location Description') - // expect(locDesc.find('[data-cy=content]').text()).toBe(addressMissingParts.locationDescription) + expect(addressLines.at(0).text()).toBe(getName(addressFilled.addressCountry)) + const locDesc = wrapper.find('[data-cy=location-description]') + expect(locDesc.exists()).toBe(true) + expect(locDesc.find('.title').text()).toBe('Location Description') + expect(locDesc.find('[data-cy=content]').text()).toBe(addressMissingParts.locationDescription) wrapper.unmount() })