Skip to content

Commit

Permalink
Merge pull request #52 from delta10/feat/add-retry-button
Browse files Browse the repository at this point in the history
Voeg melding toe voor wanneer het submitten faalt #10
  • Loading branch information
iehkaatee authored Nov 7, 2024
2 parents a8b8ea4 + 7eb36dd commit 9988172
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 20 deletions.
12 changes: 11 additions & 1 deletion src/app/[locale]/incident/components/IncidentFormFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import { useTranslations } from 'next-intl'
import { Button } from '@/components/ui/Button'
import { useStepperStore } from '@/store/stepper_store'
import { steps, usePathname as usePath, useRouter } from '@/routing/navigation'
import { ImSpinner8 } from 'react-icons/im'

type IncidentFormFooterProps = {
handleSignalSubmit?: () => void
loading?: boolean
ariaDescribedById?: string
} & React.HTMLAttributes<HTMLDivElement>

const IncidentFormFooter = ({
className,
handleSignalSubmit,
loading,
ariaDescribedById,
}: IncidentFormFooterProps) => {
const t = useTranslations('general.describe_form')
const { step, addOneStep, removeOneStep } = useStepperStore()
Expand Down Expand Up @@ -56,12 +61,17 @@ const IncidentFormFooter = ({
</Button>
)}
{step === 4 && (
// Note: current button has no visual indicator when disabled.
<Button
variant="primary"
type="submit"
className="justify-self-end"
disabled={loading}
tabIndex={loading ? 0 : undefined}
aria-describedby={ariaDescribedById}
className="flex items-center gap-2 justify-self-end"
onClick={() => (handleSignalSubmit ? handleSignalSubmit() : null)}
>
{loading && <ImSpinner8 className="animate-spin" />}
{t('submit_button')}
</Button>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@ import { useTranslations } from 'next-intl'
import { Divider } from '@/components/ui/Divider'
import { LinkWrapper } from '@/components/ui/LinkWrapper'
import { useStepperStore } from '@/store/stepper_store'
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import { LocationMap } from '@/components/ui/LocationMap'
import { signalsClient } from '@/services/client/api-client'
import { useRouter } from '@/routing/navigation'
import { postAttachments } from '@/services/attachment/attachments'
import { useFormStore } from '@/store/form_store'
import { _NestedLocationModel } from '@/services/client'
import { Paragraph, Heading } from '@/components/index'
import { MAX_NUMBER_FILES } from '@/components/ui/upload/FileUpload'
import PreviewFile from '@/components/ui/upload/PreviewFile'
import { SubmitAlert } from '@/app/[locale]/incident/summary/components/SubmitAlert'

const IncidentSummaryForm = () => {
const t = useTranslations('describe-summary')
const { formState } = useFormStore()
const { goToStep } = useStepperStore()
const router = useRouter()
const [error, setError] = useState<boolean>(false)
const [loading, setLoading] = useState<boolean>(false)

useEffect(() => {
router.prefetch('/incident/thankyou')
Expand All @@ -36,8 +38,11 @@ const IncidentSummaryForm = () => {
* generated types with the real API requirements.
*/
const handleSignalSubmit = async () => {
await signalsClient.v1
.v1PublicSignalsCreate({
setError(false)
setLoading(true)

try {
const res = await signalsClient.v1.v1PublicSignalsCreate({
text: formState.description,
// @ts-ignore
location: {
Expand All @@ -62,21 +67,33 @@ const IncidentSummaryForm = () => {
incident_date_start: new Date().toISOString(),
extra_properties: formState.extra_properties,
})
.then((res) => {
if (formState.attachments.length > 0) {
const signalId = res.signal_id
if (signalId) {
formState.attachments.forEach((attachment) => {
const formData = new FormData()
formData.append('signal_id', signalId)
formData.append('file', attachment)
postAttachments(signalId, formData)
})

if (formState.attachments.length > 0) {
const signalId = res.signal_id
if (signalId) {
try {
await Promise.all(
formState.attachments.map(async (attachment) => {
const formData = new FormData()
formData.append('signal_id', signalId)
formData.append('file', attachment)
return postAttachments(signalId, formData)
})
)
} catch (e) {
// Note: the report does not have fail when one or more of the attachments is not uploaded successfully.
console.error('One of the attachments failed while uploading', e)
}
}
})
.then((res) => router.push('/incident/thankyou'))
.catch((err) => console.error(err))
}

router.push('/incident/thankyou')
} catch (err) {
console.error(err)
setError(true)
} finally {
setLoading(false)
}
}

return (
Expand Down Expand Up @@ -163,7 +180,14 @@ const IncidentSummaryForm = () => {
</>
)}
</div>
<IncidentFormFooter handleSignalSubmit={handleSignalSubmit} />

<SubmitAlert error={error} loading={loading} />

<IncidentFormFooter
handleSignalSubmit={handleSignalSubmit}
ariaDescribedById="submit-described-by"
loading={loading}
/>
</div>
)
}
Expand Down
50 changes: 50 additions & 0 deletions src/app/[locale]/incident/summary/components/SubmitAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useTranslations } from 'next-intl'
import React, { useEffect, useRef } from 'react'
import {
Alert,
Paragraph,
} from '@utrecht/component-library-react/dist/css-module'
import { Heading, MultilineData } from '@utrecht/component-library-react'

export const SubmitAlert = ({
error,
loading,
}: {
error: boolean
loading: boolean
}) => {
const t = useTranslations('describe-summary')
const alertRef = useRef<HTMLDivElement | null>(null)
const multilineRef = useRef<HTMLPreElement>(null)

// Scroll to error message when an error occurs
useEffect(() => {
if ((error || loading) && alertRef.current) {
alertRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' })
}
}, [error, loading])

if (loading) {
return (
<Alert ref={alertRef} id="submit-described-by">
<Heading level={3}>{t('submit_alert.loading.heading')}</Heading>
<MultilineData ref={multilineRef} className="pt-2">
{t('submit_alert.loading.description')}
</MultilineData>
</Alert>
)
}

if (error) {
return (
<Alert ref={alertRef} type="error" id="submit-described-by">
<Heading level={3}>{t('submit_alert.error.heading')}</Heading>
<Paragraph className="pt-2">
{t('submit_alert.error.description')}
</Paragraph>
</Alert>
)
}

return null
}
2 changes: 1 addition & 1 deletion src/services/attachment/attachments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export const postAttachments = async (

return response.data
} catch (error) {
throw new Error('Could not fetch suggested addresses. Please try again.')
throw new Error('Something went wrong uploading the attachment')
}
}
10 changes: 10 additions & 0 deletions translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@
"input_sharing_heading": "Report sharing",
"input_sharing_allowed": "Yes, I authorize the Municipality of Amsterdam to forward my report to other organizations if it is not intended for the municipality."
}
},
"submit_alert": {
"error": {
"heading": "Submit failed",
"description": "Due to a technical error, the report could not be sent. We did not receive your information. Please try again in a few minutes."
},
"loading": {
"heading": "Processing",
"description": "Your report is being processed. You will automatically go to the next page once the report is received.\n\nPlease wait a moment...."
}
}
},
"describe-thankyou": {
Expand Down
11 changes: 11 additions & 0 deletions translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@
"input_sharing_heading": "Melding delen",
"input_sharing_allowed": "Ja, ik geef de gemeente Amsterdam toestemming om mijn melding door te sturen naar andere organisaties als de melding niet voor de gemeente is bestemd."
}
},
"submit_alert": {
"error": {
"heading": "Versturen mislukt",
"description": "Wegens een technische fout kon de melding niet worden verzonden. We hebben uw gegevens niet ontvangen. Probeer het over een paar minuten opnieuw."

},
"loading": {
"heading": "Bezig met afhandelen",
"description": "Uw melding wordt afgehandeld. U gaat automatisch naar de volgende pagina zodra de melding is ontvangen.\n\nEen ogenblik geduld alstublieft..."
}
}
},
"describe-thankyou": {
Expand Down

0 comments on commit 9988172

Please sign in to comment.