Skip to content

Commit

Permalink
add /multi-channel/pid-verification route (#332)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fbasham authored Mar 5, 2025
1 parent 394da40 commit dab6d2d
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 0 deletions.
8 changes: 8 additions & 0 deletions frontend/app/.server/locales/protected-en.json
Original file line number Diff line number Diff line change
Expand Up @@ -363,5 +363,13 @@
"other-last-names": "Other last names",
"search": "Search",
"matches": "Matches"
},
"pid-verification": {
"page-title": "Validation result",
"status-passed": "Passed",
"validation-passed": "Validation passed",
"all-input-successful": "All inputs have been successfully validated and match the primary identity document.",
"next": "Next",
"previous": "Previous"
}
}
8 changes: 8 additions & 0 deletions frontend/app/.server/locales/protected-fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -364,5 +364,13 @@
"other-last-names": "Other last names",
"search": "Search",
"matches": "Matches"
},
"pid-verification": {
"page-title": "Validation result",
"status-passed": "Passed",
"validation-passed": "Validation passed",
"all-input-successful": "All inputs have been successfully validated and match the primary identity document.",
"next": "Next",
"previous": "Previous"
}
}
8 changes: 8 additions & 0 deletions frontend/app/i18n-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ export const i18nRoutes = [
},
{
id: 'MCF-0001',
file: 'routes/protected/multi-channel/pid-verification.tsx',
paths: {
en: '/en/protected/multi-channel/pid-verification',
fr: '/fr/protege/multi-chaine/pid-verification',
},
},
{
id: 'MCF-0002',
file: 'routes/protected/multi-channel/search-sin.tsx',
paths: {
en: '/en/protected/multi-channel/search-sin',
Expand Down
100 changes: 100 additions & 0 deletions frontend/app/routes/protected/multi-channel/pid-verification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { useId } from 'react';

import type { RouteHandle } from 'react-router';
import { useFetcher } from 'react-router';

import { faCheck } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useTranslation } from 'react-i18next';

import type { Info, Route } from './+types/pid-verification';

import { requireAuth } from '~/.server/utils/auth-utils';
import { i18nRedirect } from '~/.server/utils/route-utils';
import { Button } from '~/components/button';
import { FetcherErrorSummary } from '~/components/error-summary';
import { PageTitle } from '~/components/page-title';
import { AppError } from '~/errors/app-error';
import { ErrorCodes } from '~/errors/error-codes';
import { getTranslation } from '~/i18n-config.server';
import { handle as parentHandle } from '~/routes/protected/layout';

export const handle = {
i18nNamespace: [...parentHandle.i18nNamespace, 'protected'],
} as const satisfies RouteHandle;

export async function loader({ context, request }: Route.LoaderArgs) {
requireAuth(context.session, new URL(request.url), ['user']);

const { t } = await getTranslation(request, handle.i18nNamespace);

// TODO: fetch the verifiction status and send in order to display correct status message
return {
documentTitle: t('protected:pid-verification.page-title'),
};
}

export function meta({ data }: Route.MetaArgs) {
return [{ title: data.documentTitle }];
}

export async function action({ context, request }: Route.ActionArgs) {
requireAuth(context.session, new URL(request.url), ['user']);

const formData = await request.formData();
const action = formData.get('action');

switch (action) {
case 'back': {
// TODO: update with proper route
throw i18nRedirect('routes/protected/multi-channel/pid-verification.tsx', request);
}

case 'next': {
throw i18nRedirect('routes/protected/multi-channel/search-sin.tsx', request);
}

default: {
throw new AppError(`Unrecognized action: ${action}`, ErrorCodes.UNRECOGNIZED_ACTION);
}
}
}

export default function PidVerification({ loaderData, actionData, params }: Route.ComponentProps) {
const { t } = useTranslation(handle.i18nNamespace);
const fetcherKey = useId();
const fetcher = useFetcher<Info['actionData']>({ key: fetcherKey });
const isSubmitting = fetcher.state !== 'idle';

return (
<>
<PageTitle subTitle={t('protected:in-person.title')}>{t('protected:pid-verification.page-title')}</PageTitle>
<FetcherErrorSummary fetcherKey={fetcherKey}>
<fetcher.Form method="post" noValidate>
{/* TODO: refactor status message as reuseable component(s) and display*/}
<div
id="status-id"
role="status"
aria-live="polite"
className="flex max-w-fit items-center gap-1 rounded-full bg-green-600 px-2 py-1 text-xs text-white"
>
<FontAwesomeIcon aria-hidden="true" focusable="false" icon={faCheck} />
<span>{t('protected:pid-verification.status-passed')}</span>
</div>
<h2 className="font-lato mt-2 mb-6 text-2xl font-semibold" aria-describedby="status-id">
{t('protected:pid-verification.validation-passed')}
</h2>
<p>{t('protected:pid-verification.all-input-successful')}</p>
<div className="mt-8 flex flex-row-reverse flex-wrap items-center justify-end gap-3">
<Button name="action" value="next" variant="primary" id="continue-button" disabled={isSubmitting}>
{t('protected:pid-verification.next')}
</Button>
<Button name="action" value="back" id="back-button" disabled={isSubmitting}>
{t('protected:pid-verification.previous')}
</Button>
</div>
</fetcher.Form>
</FetcherErrorSummary>
</>
);
}

0 comments on commit dab6d2d

Please sign in to comment.