Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1430: Add query params to card self service form #1749

Merged
merged 10 commits into from
Nov 25, 2024
Prev Previous commit
Next Next commit
1430: Init card from query params in useCardGeneratorSelfService
seluianova committed Nov 11, 2024
commit 34cb958ab7abe71dc247a1fb0d6bfd1934f0d4ea
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Checkbox, FormGroup, InputGroup, Intent } from '@blueprintjs/core'
import InfoOutlined from '@mui/icons-material/InfoOutlined'
import { Alert, styled } from '@mui/material'
import React, { ReactElement, useContext, useEffect, useRef, useState } from 'react'
import React, { ReactElement, useContext, useState } from 'react'

import { Card, isFullNameValid, isValid } from '../../cards/Card'
import ClearInputButton from '../../cards/extensions/components/ClearInputButton'
import useWindowDimensions from '../../hooks/useWindowDimensions'
import BasicDialog from '../../mui-modules/application/BasicDialog'
import { ProjectConfigContext } from '../../project-configs/ProjectConfigContext'
import PlainDate from '../../util/PlainDate'
import ExtensionForms from '../cards/ExtensionForms'
import { ActionButton } from './components/ActionButton'
import { IconTextButton } from './components/IconTextButton'
@@ -31,7 +30,6 @@ const Container = styled('div')`

type CardSelfServiceFormProps = {
card: Card
cardQueryParams: URLSearchParams
updateCard: (card: Partial<Card>) => void
dataPrivacyAccepted: boolean
setDataPrivacyAccepted: (value: boolean) => void
@@ -50,43 +48,8 @@ const getTooltipMessage = (cardsValid: boolean, dataPrivacyAccepted: boolean): s
return tooltipMessages.join('\n')
}

const useInitializeCard = (cardQueryParams: URLSearchParams, updateCard: (card: Partial<Card>) => void) => {
const hasInitialized = useRef(false)

useEffect(() => {
if (!hasInitialized.current) {
hasInitialized.current = true

const fullName = cardQueryParams.get('name')
const birthday = cardQueryParams.get('geburtsdatum')

const parsedBirthday: PlainDate | null = (() => {
if (!birthday) {
return null
}
try {
return PlainDate.from(birthday)
} catch {
return null
}
})()

const referenceNumber = cardQueryParams.get('ref')

updateCard({
...(fullName !== null && { fullName }),
extensions: {
...(referenceNumber !== null && { koblenzReferenceNumber: referenceNumber }),
...(parsedBirthday !== null && { birthday: parsedBirthday }),
},
})
}
}, [cardQueryParams, updateCard])
}

const CardSelfServiceForm = ({
card,
cardQueryParams,
updateCard,
dataPrivacyAccepted,
setDataPrivacyAccepted,
@@ -99,8 +62,6 @@ const CardSelfServiceForm = ({
const cardValid = isValid(card, { expirationDateNullable: true })
const cardCreationDisabled = !cardValid || !dataPrivacyAccepted

useInitializeCard(cardQueryParams, updateCard)

return (
<>
<Container key={card.id}>
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Spinner } from '@blueprintjs/core'
import React, { ReactElement, useContext, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import styled from 'styled-components'

import KoblenzLogo from '../../assets/koblenz_logo.svg'
@@ -74,7 +73,6 @@ const HeaderLogo = styled.img`
// TODO 1646 Add tests for CardSelfService
const CardSelfServiceView = (): ReactElement => {
const projectConfig = useContext(ProjectConfigContext)
const [queryParams] = useSearchParams()
const [dataPrivacyAccepted, setDataPrivacyAccepted] = useState<boolean>(false)
const {
selfServiceState,
@@ -115,7 +113,6 @@ const CardSelfServiceView = (): ReactElement => {
{selfServiceState === CardSelfServiceStep.form && (
<CardSelfServiceForm
card={selfServiceCard}
cardQueryParams={queryParams}
dataPrivacyAccepted={dataPrivacyAccepted}
setDataPrivacyAccepted={setDataPrivacyAccepted}
updateCard={updatedCard => setSelfServiceCard(updateCard(selfServiceCard, updatedCard))}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ApolloError } from '@apollo/client'
import { useCallback, useContext, useState } from 'react'
import { useCallback, useContext, useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'

import { Card, generateCardInfo, initializeCard } from '../../../cards/Card'
import { generatePdf } from '../../../cards/PdfFactory'
@@ -8,6 +9,7 @@ import getMessageFromApolloError from '../../../errors/getMessageFromApolloError
import { DynamicActivationCode, StaticVerificationCode } from '../../../generated/card_pb'
import { useCreateCardsFromSelfServiceMutation } from '../../../generated/graphql'
import { ProjectConfigContext } from '../../../project-configs/ProjectConfigContext'
import PlainDate from '../../../util/PlainDate'
import { base64ToUint8Array, uint8ArrayToBase64 } from '../../../util/base64'
import downloadDataUri from '../../../util/downloadDataUri'
import getCustomDeepLinkFromQrCode from '../../../util/getCustomDeepLinkFromQrCode'
@@ -31,12 +33,46 @@ type UseCardGeneratorSelfServiceReturn = {
downloadPdf: (code: CreateCardsResult, fileName: string) => Promise<void>
}

const parseDate = (dateString: string): PlainDate | undefined => {
try {
return PlainDate.from(dateString)
} catch {
return undefined
f1sh1918 marked this conversation as resolved.
Show resolved Hide resolved
}
}

const handleQueryParams = (
cardQueryParams: URLSearchParams
): {
fullName?: string
birthday?: PlainDate
koblenzReferenceNumber?: string
} => {
const fullName = cardQueryParams.get('name') ?? undefined
const birthday = cardQueryParams.get('geburtsdatum') ?? undefined
const referenceNumber = cardQueryParams.get('ref') ?? undefined
return {
fullName,
birthday: birthday ? parseDate(birthday) : undefined,
koblenzReferenceNumber: referenceNumber,
}
}

const useCardGeneratorSelfService = (): UseCardGeneratorSelfServiceReturn => {
const projectConfig = useContext(ProjectConfigContext)
const appToaster = useAppToaster()
const [cardQueryParams, setSearchParams] = useSearchParams()
const { fullName, birthday, koblenzReferenceNumber } = handleQueryParams(cardQueryParams)
const [selfServiceCard, setSelfServiceCard] = useState(
initializeCard(projectConfig.card, undefined, { expirationDate: null })
initializeCard(projectConfig.card, undefined, {
fullName,
expirationDate: null,
extensions: { birthday, koblenzReferenceNumber },
})
)
useEffect(() => {
setSearchParams(undefined, { replace: true })
}, [setSearchParams])
seluianova marked this conversation as resolved.
Show resolved Hide resolved
const [isLoading, setIsLoading] = useState<boolean>(false)
const [selfServiceState, setSelfServiceState] = useState<CardSelfServiceStep>(CardSelfServiceStep.form)
const [deepLink, setDeepLink] = useState<string>('')
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ const BirthdayExtension: Extension<BirthdayExtensionState> = {
},
}),
isValid: ({ birthday }: BirthdayExtensionState) => {
if (birthday === null) {
if (birthday == null) {
seluianova marked this conversation as resolved.
Show resolved Hide resolved
return false
}
const today = PlainDate.fromLocalDate(new Date())