-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
IS-2795: Add endpoint and modal for search
- Loading branch information
1 parent
24899aa
commit 8427dc4
Showing
14 changed files
with
489 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export interface SokDTO { | ||
initials: string; | ||
birthdate: Date; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
import React, { useState } from 'react'; | ||
import { | ||
Alert, | ||
BodyShort, | ||
Box, | ||
Button, | ||
Heading, | ||
HStack, | ||
Modal, | ||
TextField, | ||
VStack, | ||
} from '@navikt/ds-react'; | ||
import { useSokPerson } from '@/data/personoversiktHooks'; | ||
import { SokDTO } from '@/api/types/sokDTO'; | ||
import SokPersonResultat from '@/components/sokperson/SokPersonResultat'; | ||
import { MagnifyingGlassIcon } from '@navikt/aksel-icons'; | ||
import { isNumeric, removePunctuation } from '@/utils/stringUtil'; | ||
import { parseDateString } from '@/utils/dateUtils'; | ||
|
||
const texts = { | ||
buttonText: 'Søk etter sykmeldt', | ||
header: 'Søk etter sykmeldt', | ||
info: | ||
'Her kan du søke opp sykmeldte personer basert på initialer og fødselsdato.', | ||
validation: { | ||
initials: 'Vennligst angi gyldige initialer', | ||
birthdate: 'Vennligst angi en gyldig fødselsdato', | ||
}, | ||
error: 'Noe gikk galt under søket. Vennligst prøv igjen.', | ||
}; | ||
|
||
export default function SokPerson() { | ||
const [isModalOpen, setIsModalOpen] = useState<boolean>(false); | ||
const [nameInitials, setNameInitials] = useState<string>(''); | ||
const [birthdate, setBirthdate] = useState<string>(''); | ||
const { | ||
mutate, | ||
data: searchResults, | ||
isLoading, | ||
isError, | ||
isSuccess, | ||
} = useSokPerson(); | ||
const [isFormError, setIsFormError] = useState<boolean>(false); | ||
|
||
const parseBirthdate = (birthdate: string): Date | null => { | ||
const cleanedDateStr = removePunctuation(birthdate); | ||
|
||
if (cleanedDateStr.length < 6 || !isNumeric(cleanedDateStr)) { | ||
return null; | ||
} else { | ||
return parseDateString(cleanedDateStr); | ||
} | ||
}; | ||
|
||
const validInitials = (initials: string): boolean => { | ||
return initials.length <= 3 && initials.length > 1; | ||
}; | ||
|
||
const handleSubmit = () => { | ||
const parsedBirthdate = parseBirthdate(birthdate); | ||
if (validInitials(nameInitials) && !!parsedBirthdate) { | ||
const requestDTO: SokDTO = { | ||
initials: nameInitials.toLowerCase(), | ||
birthdate: parsedBirthdate, | ||
}; | ||
mutate(requestDTO); | ||
} else { | ||
setIsFormError(true); | ||
} | ||
}; | ||
|
||
return ( | ||
<Box> | ||
<Button onClick={() => setIsModalOpen(true)} size="small"> | ||
{texts.buttonText} | ||
</Button> | ||
<Modal | ||
closeOnBackdropClick | ||
className="w-[90%] max-w-[90%]" | ||
open={isModalOpen} | ||
aria-label={texts.buttonText} | ||
onClose={() => setIsModalOpen(false)} | ||
> | ||
<Modal.Header> | ||
<Heading level="2" size="medium"> | ||
{texts.header} | ||
</Heading> | ||
</Modal.Header> | ||
<Modal.Body> | ||
<VStack gap="4"> | ||
<BodyShort>{texts.info}</BodyShort> | ||
<HStack gap="8" align="end"> | ||
<TextField | ||
label="Initialer" | ||
description="AB" | ||
htmlSize={10} | ||
type="text" | ||
onChange={(e) => setNameInitials(e.target.value)} | ||
error={ | ||
isFormError && !validInitials(nameInitials) | ||
? texts.validation.initials | ||
: undefined | ||
} | ||
/> | ||
<TextField | ||
label="Fødselsdato" | ||
description="ddmmåå" | ||
htmlSize={14} | ||
type="text" | ||
onChange={(e) => setBirthdate(e.target.value)} | ||
error={ | ||
isFormError && parseBirthdate(birthdate) === null | ||
? texts.validation.birthdate | ||
: undefined | ||
} | ||
/> | ||
<Button | ||
onClick={handleSubmit} | ||
loading={isLoading} | ||
icon={<MagnifyingGlassIcon />} | ||
type="submit" | ||
> | ||
Søk | ||
</Button> | ||
</HStack> | ||
{searchResults && isSuccess && ( | ||
<SokPersonResultat sokeresultater={searchResults} /> | ||
)} | ||
{isError && ( | ||
<Alert variant="error" size="small"> | ||
{texts.error} | ||
</Alert> | ||
)} | ||
</VStack> | ||
</Modal.Body> | ||
</Modal> | ||
</Box> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import React, { ReactElement } from 'react'; | ||
import { useSorting } from '@/hooks/useSorting'; | ||
import { PersonOversiktStatusDTO } from '@/api/types/personoversiktTypes'; | ||
import { BodyShort, Box, Table } from '@navikt/ds-react'; | ||
import { LinkSyfomodiaperson } from '@/components/LinkSyfomodiaperson'; | ||
import { toLastnameFirstnameFormat } from '@/utils/stringUtil'; | ||
import { toPersonData } from '@/utils/toPersondata'; | ||
|
||
const texts = { | ||
noResults: { | ||
first: 'Fant ingen sykmeldte personer for søkeparameterne.', | ||
second: | ||
'Det kan hende personen ikke er sykmeldt eller at du ikke har tilgang å se personen.', | ||
}, | ||
}; | ||
|
||
interface Props { | ||
sokeresultater: PersonOversiktStatusDTO[]; | ||
} | ||
|
||
export default function SokPersonResultat({ | ||
sokeresultater, | ||
}: Props): ReactElement { | ||
const { columns: allColumns } = useSorting(); | ||
const columns = allColumns.filter( | ||
(column) => column.sortKey === 'NAME' || column.sortKey === 'FNR' | ||
); | ||
|
||
const personer = Object.entries(toPersonData(sokeresultater, [])); | ||
|
||
return personer.length === 0 ? ( | ||
<Box> | ||
<BodyShort>{texts.noResults.first}</BodyShort> | ||
<BodyShort>{texts.noResults.second}</BodyShort> | ||
</Box> | ||
) : ( | ||
<Table size="small" zebraStripes className="bg-white mt-2"> | ||
<Table.Header> | ||
<Table.Row> | ||
{columns.map((col, index) => ( | ||
<Table.ColumnHeader key={index} sortKey={col.sortKey}> | ||
{col.sortingText} | ||
</Table.ColumnHeader> | ||
))} | ||
<Table.DataCell /> | ||
</Table.Row> | ||
</Table.Header> | ||
<Table.Body> | ||
{personer.map(([fnr, persondata], index) => ( | ||
<Table.Row key={index}> | ||
<Table.HeaderCell scope="row" textSize="small"> | ||
{persondata.navn.length > 0 && ( | ||
<LinkSyfomodiaperson | ||
personData={persondata} | ||
personident={fnr} | ||
linkText={toLastnameFirstnameFormat(persondata.navn)} | ||
/> | ||
)} | ||
</Table.HeaderCell> | ||
<Table.DataCell textSize="small"> | ||
{persondata.navn.length > 0 ? ( | ||
fnr | ||
) : ( | ||
<LinkSyfomodiaperson | ||
personData={persondata} | ||
personident={fnr} | ||
linkText={fnr} | ||
/> | ||
)} | ||
</Table.DataCell> | ||
</Table.Row> | ||
))} | ||
</Table.Body> | ||
</Table> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.