Skip to content

Commit d8b19e6

Browse files
ConwayDeckerNabbeunNabi
authored andcommitted
feat: add create functionality for healthcare professional
The values necessary within the store were added along with the api call to be used later. The ModEditHealthcareProfessionalSection was refactored to be a generic component for creating or editing.
1 parent a150412 commit d8b19e6

9 files changed

+760
-26
lines changed

components/ModCreateHealthcareProfessionalSection.vue

+569
Large diffs are not rendered by default.

components/ModDashboardHealthProfessionalCard.vue

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div
33
:class="[
4-
'border-2 border-primary rounded-lg px-2 w-fit',
4+
'mod-dashboard-healthcare-professional-card border-2 border-primary rounded-lg px-2 w-fit',
55
(isEditable && chosenLocaleIndex === 0) ? 'border-t-0 mt-0 rounded-t-none' : 'my-3',
66
]"
77
>
@@ -115,7 +115,8 @@
115115
/>
116116
</div>
117117
<div
118-
v-if="moderationScreenStore.editHealthcareProfessionalScreenIsActive()"
118+
v-if="moderationScreenStore.editHealthcareProfessionalScreenIsActive()
119+
|| moderationScreenStore.createHealthcareProfessionalScreenIsActive()"
119120
class="flex w-8 items-center justify-center
120121
cursor-pointer font-bold text-secondary text-sm self-start p-1"
121122
>

components/ModDashboardTopbar.vue

+11-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,21 @@
55
>
66
{{ updateTextForModerationDashboard(moderationSubmissionsStore.selectedModerationListViewChosen) }}
77
</h1>
8-
<div class="dashboard-search flex flex-col mt-4">
8+
<div class="dashboard-search flex items-center mt-4">
9+
<NuxtLink
10+
v-if="moderationSubmissionsStore.selectedModerationListViewChosen
11+
=== SelectedModerationListView.HealthcareProfessionals"
12+
:to="`/moderation/create-healthcare-professional`"
13+
class="flex justify-center items-center rounded-full bg-secondary-bg border-primary p-1 border-2 w-40
14+
font-semibold text-sm mr-2 overflow-hidden text-center hover:bg-currentColor"
15+
>
16+
{{ $t('modDashboardTopbar.addHealthcareProfessional') }}
17+
</NuxtLink>
918
<div class="justify-start items-start flex">
1019
<input
1120
type="text"
1221
:placeholder="$t('modDashboardTopbar.placeholderText')"
13-
class="mb-5 px-3 py-3.5 w-96 h-12 bg-secondary-bg rounded-lg border border-primary-text-muted
22+
class=" px-3 py-3.5 w-96 h-12 bg-secondary-bg rounded-lg border border-primary-text-muted
1423
text-primary-text text-sm font-normal font-sans placeholder-primary-text-muted"
1524
>
1625
<SVGLookingGlass

components/ModEditHealthcareProfessionalSection.vue

+91-18
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@
107107
</div>
108108
</Transition>
109109
<div
110-
v-if="healthcareProfessionalsStore.healthcareProfessionalSectionFields.names"
110+
v-if="moderationScreenStore.editHealthcareProfessionalScreenIsActive()
111+
&& healthcareProfessionalsStore.healthcareProfessionalSectionFields.names"
111112
class="flex flex-col"
112113
>
113114
<div
@@ -124,6 +125,25 @@
124125
/>
125126
</div>
126127
</div>
128+
<div
129+
v-if="moderationScreenStore.createHealthcareProfessionalScreenIsActive()
130+
&& healthcareProfessionalsStore.createHealthcareProfessionalInput.names"
131+
class="flex flex-col"
132+
>
133+
<div
134+
v-for="(nameLocale, index) in healthcareProfessionalsStore.createHealthcareProfessionalInput.names"
135+
:key="`${nameLocale.firstName}-${nameLocale.lastName}-${index}`"
136+
@click="() => setChosenLocaleNameInput(index)"
137+
>
138+
<ModDashboardHealthProfessionalCard
139+
:healthcare-professional="{} as HealthcareProfessional"
140+
:healthcare-professional-name-by-locale="nameLocale"
141+
:chosen-locale-index="index"
142+
:is-editable="editingLocaleName"
143+
:set-is-editable-function="setEditingLocaleName"
144+
/>
145+
</div>
146+
</div>
127147
<button
128148
type="button"
129149
data-testid="mod-healthcare-add-name-button"
@@ -265,7 +285,14 @@ import ModSearchbar from './ModSearchBar.vue'
265285
import { useHealthcareProfessionalsStore } from '~/stores/healthcareProfessionalsStore'
266286
import { useFacilitiesStore } from '~/stores/facilitiesStore'
267287
import { useLocaleStore } from '~/stores/localeStore'
268-
import { Insurance, Locale, Degree, Specialty, type LocalizedNameInput, type Facility } from '~/typedefs/gqlTypes'
288+
import { useModerationScreenStore } from '~/stores/moderationScreenStore'
289+
import { Insurance,
290+
Locale,
291+
Degree,
292+
Specialty,
293+
type LocalizedNameInput,
294+
type Facility,
295+
type HealthcareProfessional } from '~/typedefs/gqlTypes'
269296
import { useI18n } from '#imports'
270297
271298
let toast: ToastInterface
@@ -277,6 +304,7 @@ const { t } = useI18n()
277304
const loadingStore = useLoadingStore()
278305
loadingStore.setIsLoading(true)
279306
307+
const moderationScreenStore = useModerationScreenStore()
280308
const localesStore = useLocaleStore()
281309
const healthcareProfessionalsStore = useHealthcareProfessionalsStore()
282310
const facilitiesStore = useFacilitiesStore()
@@ -361,19 +389,35 @@ const setChosenLocaleNameInput = (index: number) => {
361389
362390
//This will keep track of the healthcare professional to not lose it but we can swap it later with the chosen one
363391
const tempToHoldZeroIndexedHealthcareProfessionalToSwap
364-
= healthcareProfessionalsStore.healthcareProfessionalSectionFields.names[0]
392+
= moderationScreenStore.editHealthcareProfessionalScreenIsActive()
393+
? healthcareProfessionalsStore.healthcareProfessionalSectionFields.names[0]
394+
: healthcareProfessionalsStore.createHealthcareProfessionalInput.names[0]
365395
366396
//This finds the chosen healthcare professional to edit
367397
chosenHealthcareProfessionalToEdit.value
368-
= healthcareProfessionalsStore.healthcareProfessionalSectionFields.names.find((_, index) => index === chosenLocaleIndex.value)
398+
= moderationScreenStore.editHealthcareProfessionalScreenIsActive()
399+
? healthcareProfessionalsStore.healthcareProfessionalSectionFields
400+
.names.find((_, index) => index === chosenLocaleIndex.value)
401+
: healthcareProfessionalsStore.createHealthcareProfessionalInput
402+
.names.find((_, index) => index === chosenLocaleIndex.value)
369403
370404
if (chosenHealthcareProfessionalToEdit.value) {
371405
//Set the chosen healthcare professional name to move it closer to the input
372-
healthcareProfessionalsStore.healthcareProfessionalSectionFields.names[0]
406+
if (moderationScreenStore.editHealthcareProfessionalScreenIsActive()) {
407+
healthcareProfessionalsStore.healthcareProfessionalSectionFields.names[0]
373408
= chosenHealthcareProfessionalToEdit.value
374-
// Put the temp one in the index where the old locale name was
375-
healthcareProfessionalsStore.healthcareProfessionalSectionFields.names[chosenLocaleIndex.value]
376-
= tempToHoldZeroIndexedHealthcareProfessionalToSwap
409+
// Put the temp one in the index where the old locale name was
410+
healthcareProfessionalsStore.healthcareProfessionalSectionFields.names[chosenLocaleIndex.value]
411+
= tempToHoldZeroIndexedHealthcareProfessionalToSwap
412+
}
413+
414+
if (moderationScreenStore.createHealthcareProfessionalScreenIsActive()) {
415+
healthcareProfessionalsStore.createHealthcareProfessionalInput.names[0]
416+
= chosenHealthcareProfessionalToEdit.value
417+
// Put the temp one in the index where the old locale name was
418+
healthcareProfessionalsStore.createHealthcareProfessionalInput.names[chosenLocaleIndex.value]
419+
= tempToHoldZeroIndexedHealthcareProfessionalToSwap
420+
}
377421
//Autofill with the chosen healthcare professional locale name]
378422
autofillNameLocaleInputWithChosenHealthcareProfessional(chosenHealthcareProfessionalToEdit.value)
379423
// Set the chosenLocaleIndex to 0 so the correct pencil is showing
@@ -426,13 +470,21 @@ const handleUpdateExistingName = () => {
426470
}
427471
428472
const handleDeleteExistingName = () => {
429-
if (healthcareProfessionalsStore.healthcareProfessionalSectionFields.names.length <= 1) {
473+
if (healthcareProfessionalsStore.healthcareProfessionalSectionFields.names.length <= 1
474+
&& moderationScreenStore.editHealthcareProfessionalScreenIsActive()
475+
) {
430476
toast.error(t('modHealthcareProfessionalSection.oneNameNecessary'))
431477
return
432478
}
433-
// Remove the first element safely since we reordered the one for deletion at 0
434-
healthcareProfessionalsStore.healthcareProfessionalSectionFields.names.shift()
435479
480+
// Remove the first element safely since we reordered the one for deletion at 0
481+
if (moderationScreenStore.editHealthcareProfessionalScreenIsActive()) {
482+
healthcareProfessionalsStore.healthcareProfessionalSectionFields.names.shift()
483+
}
484+
// Remove the first element safely since we reordered the one for deletion at 0
485+
if (moderationScreenStore.createHealthcareProfessionalScreenIsActive()) {
486+
healthcareProfessionalsStore.createHealthcareProfessionalInput.names.shift()
487+
}
436488
setEditingLocaleName(false)
437489
438490
// Allows for the inputs to completely transition before resetting the fields
@@ -451,8 +503,7 @@ const handleAddLocalizedName = () => {
451503
middleName: nameLocaleInputs.middleName
452504
}
453505
// Checks to keep user from adding a name with same locale instead of editing
454-
const existingNameForLocale = healthcareProfessionalsStore.healthcareProfessionalSectionFields.names
455-
.find(name => name.locale === nameLocaleInputs.locale)
506+
const existingNameForLocale = checkIfHealthcareProfessionalHasAnExistingNameForLocale()
456507
457508
// Displays message if user is trying to add a locale for name that exists and they aren't editing a healthcare professional
458509
if (existingNameForLocale) {
@@ -478,18 +529,40 @@ const handleAddLocalizedName = () => {
478529
return
479530
}
480531
481-
if (nameLocaleInputs.firstName
482-
&& nameLocaleInputs.lastName
483-
&& nameLocaleInputs.firstName.length
484-
&& nameLocaleInputs.lastName.length
485-
&& healthcareProfessionalsStore.healthcareProfessionalSectionFields.names) {
532+
const checkValidityOfNameInputs
533+
= nameLocaleInputs.firstName
534+
&& nameLocaleInputs.lastName
535+
&& nameLocaleInputs.firstName.length
536+
&& nameLocaleInputs.lastName.length
537+
538+
if (checkValidityOfNameInputs
539+
&& healthcareProfessionalsStore.healthcareProfessionalSectionFields.names
540+
&& moderationScreenStore.editHealthcareProfessionalScreenIsActive()) {
486541
healthcareProfessionalsStore.healthcareProfessionalSectionFields.names.push(localizedNameToAdd)
487542
}
488543
544+
if (checkValidityOfNameInputs
545+
&& healthcareProfessionalsStore.createHealthcareProfessionalInput.names
546+
&& moderationScreenStore.createHealthcareProfessionalScreenIsActive()) {
547+
healthcareProfessionalsStore.createHealthcareProfessionalInput.names.push(localizedNameToAdd)
548+
}
549+
489550
// Sets the chosen healthcare professional to undefined to reset
490551
handleCloseAddingNewLocalizedName()
491552
}
492553
554+
function checkIfHealthcareProfessionalHasAnExistingNameForLocale() {
555+
if (moderationScreenStore.editHealthcareProfessionalScreenIsActive()) {
556+
return healthcareProfessionalsStore.healthcareProfessionalSectionFields.names
557+
.find(name => name.locale === nameLocaleInputs.locale)
558+
}
559+
560+
if (moderationScreenStore.createHealthcareProfessionalScreenIsActive()) {
561+
return healthcareProfessionalsStore.createHealthcareProfessionalInput.names
562+
.find(name => name.locale === nameLocaleInputs.locale)
563+
}
564+
}
565+
493566
const handleFacilitySearchInputChange = (filteredItems: Ref<Facility[]>, inputValue: string) => {
494567
filteredItems.value = currentFacilities.filter(({ nameEn, nameJa, id }) => {
495568
const isMatch

components/ModMainContent.vue

+16
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@
2727
<ModEditHealthcareProfessionalSection />
2828
</form>
2929
</div>
30+
<div
31+
v-if="moderationScreenStore.createHealthcareProfessionalScreenIsActive()"
32+
class="h-full overflow-hidden"
33+
>
34+
<form
35+
class="p-4 h-full overflow-y-auto"
36+
>
37+
<ModCreateHealthcareProfessionalSection />
38+
</form>
39+
</div>
3040
</div>
3141
</template>
3242

@@ -66,6 +76,11 @@ const setActiveScreenBasedOnRoute = async () => {
6676
healthcareProfessionalStore.selectedHealthcareProfessionalId = selectedIdFromModSubmissionList.value
6777
return
6878
}
79+
if (
80+
routePathForModerationScreen.value.includes('create-healthcare-professional')) {
81+
moderationScreenStore.setActiveScreen(ModerationScreen.CreateHealthcareProfessional)
82+
return
83+
}
6984
7085
// This will default the screen based on the route to the dashboard if all the other stuff fails
7186
moderationScreenStore.setActiveScreen(ModerationScreen.Dashboard)
@@ -75,6 +90,7 @@ const setActiveScreenBasedOnRoute = async () => {
7590
}
7691
7792
watch(selectedIdFromModSubmissionList, setActiveScreenBasedOnRoute)
93+
watch(routePathForModerationScreen, setActiveScreenBasedOnRoute)
7894
7995
onMounted(() => {
8096
setActiveScreenBasedOnRoute()

i18n/locales/en.json

+1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
"healthcareProfessionalMedicalInfo": "Healthcare Professional Medical Info"
145145
},
146146
"modDashboardTopbar": {
147+
"addHealthcareProfessional": "Add Healthcare Professional",
147148
"placeholderText": "Enter name or ID to search",
148149
"approved": "Approved",
149150
"rejected": "Rejected",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<NuxtPage />
3+
</template>

stores/healthcareProfessionalsStore.ts

+60-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ import type { Maybe } from 'graphql/jsutils/Maybe'
22
import { defineStore } from 'pinia'
33
import { reactive, ref, type Ref } from 'vue'
44
import { gql } from 'graphql-request'
5-
import { type Facility, type DeleteResult, type HealthcareProfessional,
5+
import { type Insurance,
6+
type Degree,
7+
type Specialty,
8+
type Locale, type Facility, type DeleteResult, type HealthcareProfessional,
69
type LocalizedNameInput,
710
type Mutation,
811
type MutationDeleteHealthcareProfessionalArgs,
912
type MutationUpdateHealthcareProfessionalArgs,
1013
type Relationship,
11-
RelationshipAction } from '~/typedefs/gqlTypes'
14+
RelationshipAction,
15+
type CreateHealthcareProfessionalInput } from '~/typedefs/gqlTypes'
1216
import { gqlClient, graphQLClientRequestWithRetry } from '~/utils/graphql'
1317
import { useLocaleStore } from '~/stores/localeStore'
1418
import type { ServerError, ServerResponse } from '~/typedefs/serverResponse'
@@ -33,6 +37,16 @@ export const useHealthcareProfessionalsStore = defineStore(
3337
spokenLanguages: [],
3438
updatedDate: ''
3539
})
40+
41+
const createHealthcareProfessionalInput: CreateHealthcareProfessionalInput = reactive({
42+
acceptedInsurance: [] as Insurance[],
43+
degrees: [] as Degree[],
44+
facilityIds: [] as string[],
45+
names: [] as LocalizedNameInput[],
46+
specialties: [] as Specialty[],
47+
spokenLanguages: [] as Locale[]
48+
})
49+
3650
const selectedFacilities: Ref<Facility[]> = ref([])
3751
// This is the array to be sent to the backend if there is a change in the relations
3852
const facilitiesRelationsToSelectedHealthcareProfessional: Ref<Relationship[]> = ref([])
@@ -150,6 +164,23 @@ export const useHealthcareProfessionalsStore = defineStore(
150164
return
151165
}
152166

167+
async function createHealthcareProfessional():
168+
Promise<ServerResponse<Maybe<HealthcareProfessional>>> {
169+
const serverResponse = { data: {} as Maybe<HealthcareProfessional>, errors: [] as ServerError[], hasErrors: false }
170+
171+
const response = await graphQLClientRequestWithRetry<Mutation>(
172+
gqlClient.request.bind(gqlClient),
173+
createHealthcareProfessionalGqMutation,
174+
createHealthcareProfessionalInput
175+
)
176+
177+
serverResponse.data = response.data?.createHealthcareProfessional
178+
serverResponse.errors = response.errors ? response.errors : []
179+
serverResponse.hasErrors = response.hasErrors
180+
181+
return serverResponse
182+
}
183+
153184
async function deleteHealthcareProfessional(healthcareProfessionalId: MutationDeleteHealthcareProfessionalArgs):
154185
Promise<ServerResponse<Maybe<DeleteResult>>> {
155186
const serverResponse = { data: {} as Maybe<DeleteResult>, errors: [] as ServerError[], hasErrors: false }
@@ -167,7 +198,9 @@ export const useHealthcareProfessionalsStore = defineStore(
167198
return serverResponse
168199
}
169200

170-
const displayChosenLocaleForHealthcareProfessional = (healthcareProfessional: HealthcareProfessional) => {
201+
const displayChosenLocaleForHealthcareProfessional = (
202+
healthcareProfessional: HealthcareProfessional | CreateHealthcareProfessionalInput
203+
) => {
171204
// find the name of the healthcare professional from the chosen display locale
172205
const nameFromChosenLocaleDisplay = healthcareProfessional.names.find(name => name.locale === localeStore.locale.code)
173206
// return the name of the healthcare professional of chosen locale or default to the 0 indexed recorded name
@@ -185,7 +218,9 @@ export const useHealthcareProfessionalsStore = defineStore(
185218
setSelectedHealthcareProfessional,
186219
removedHealthcareProfessionalNames,
187220
facilitiesRelationsToSelectedHealthcareProfessional,
188-
selectedFacilities
221+
selectedFacilities,
222+
createHealthcareProfessional,
223+
createHealthcareProfessionalInput
189224
}
190225
}
191226
)
@@ -287,3 +322,24 @@ mutation Mutation($id: ID!) {
287322
}
288323
}
289324
`
325+
326+
const createHealthcareProfessionalGqMutation = gql`
327+
mutation Mutation($input: CreateHealthcareProfessionalInput!) {
328+
createHealthcareProfessional(input: $input) {
329+
id
330+
names {
331+
firstName
332+
middleName
333+
lastName
334+
locale
335+
}
336+
spokenLanguages
337+
degrees
338+
specialties
339+
acceptedInsurance
340+
facilityIds
341+
createdDate
342+
updatedDate
343+
}
344+
}
345+
`

0 commit comments

Comments
 (0)