Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/app/components/book-checkbox/book-checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ import React from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck';
import {treatSpaceOrEnterAsClick} from '~/helpers/events';
import type { SalesforceBook } from '~/helpers/books';
import type {SalesforceBook} from '~/helpers/books';
import cn from 'classnames';
import './book-checkbox.scss';

export default function BookCheckbox({book, name, checked, toggle, disabled}: {
export default function BookCheckbox({
book,
name,
checked,
toggle,
disabled
}: {
book: SalesforceBook;
name: string;
name?: string;
checked: boolean;
toggle: (b: SalesforceBook) => void;
disabled?: boolean;
Expand Down Expand Up @@ -36,6 +42,7 @@ export default function BookCheckbox({book, name, checked, toggle, disabled}: {
className="indicator"
tabIndex={disabled ? -1 : 0}
role="checkbox"
aria-label={label}
aria-checked={checked}
aria-disabled={disabled}
onKeyDown={treatSpaceOrEnterAsClick}
Expand Down
6 changes: 3 additions & 3 deletions src/app/components/book-selector/book-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function Subject({
}: {
subject: string;
books: SalesforceBook[];
name: string;
name?: string;
selectedBooks: SalesforceBook[];
toggleBook: (b: SalesforceBook) => void;
limitReached: boolean;
Expand Down Expand Up @@ -64,12 +64,12 @@ const defaultIncludeFilter = () => true;

type PropsFromOutside = {
prompt: string;
name: string;
name?: string;
selectedBooks: SalesforceBook[];
toggleBook: (b: SalesforceBook) => void;
limit?: number;
additionalInstructions?: string;
includeFilter?: () => boolean;
includeFilter?: (b: SalesforceBook) => boolean;
};

type Books = Parameters<typeof salesforceTitles>[0]
Expand Down
8 changes: 6 additions & 2 deletions src/app/components/form-input/form-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export default function FormInput({
inputProps,
suggestions
}: {
label: string;
label?: string;
longLabel?: string;
inputProps: InputProps;
suggestions?: string[];
Expand Down Expand Up @@ -211,7 +211,11 @@ export default function FormInput({
return (
<label className="form-input">
<div className="control-group">
{label && <label className="field-label" htmlFor={id}>{label}</label>}
{label && (
<label className="field-label" htmlFor={id}>
{label}
</label>
)}
{longLabel && (
<label className="field-long-label">{longLabel}</label>
)}
Expand Down
66 changes: 37 additions & 29 deletions src/app/components/multi-page-form/multi-page-form.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import usePaginatorContext, {PaginatorContextProvider} from '~/components/paginator/paginator-context';
import usePaginatorContext, {
PaginatorContextProvider
} from '~/components/paginator/paginator-context';
import usePagesContext, {PagesContextProvider} from './pages-context';
import {FormattedMessage} from 'react-intl';
import ButtonRow from './buttons';
Expand All @@ -13,24 +15,22 @@ function MarkupChildren({children}: {children: React.ReactNode[]}) {
const {isVisible} = usePaginatorContext();
const {validatedPages, activeRef} = usePagesContext();

return (
children.map((child, i) => {
const isActive = isVisible(i);
const pageNumber = i + 1;
const isValidated = pageNumber in validatedPages;
return children.map((child, i) => {
const isActive = isVisible(i);
const pageNumber = i + 1;
const isValidated = pageNumber in validatedPages;

return (
<div
className={isValidated ? 'validated' : undefined}
hidden={!isActive}
ref={isActive ? activeRef : null}
key={i}
>
{child}
</div>
);
})
);
return (
<div
className={isValidated ? 'validated' : undefined}
hidden={!isActive}
ref={isActive ? activeRef : null}
key={i}
>
{child}
</div>
);
});
}

function PageCount() {
Expand All @@ -39,32 +39,41 @@ function PageCount() {

return (
<div className="page-count">
<FormattedMessage id="form.step-of" values={{current: currentPage, total: pages}} />
<FormattedMessage
id="form.step-of"
values={{current: currentPage, total: pages}}
/>
</div>
);
}

type MultiPageFormProps = {
children: React.ReactNode[];
validatePage?: (p: unknown) => boolean;
onPageChange?: (p: unknown) => boolean;
validatePage?: (p: number) => boolean;
onPageChange?: (p: number) => void;
onSubmit: (form: HTMLFormElement) => void;
submitting: boolean;
// onSubmit is redefined above to be simpler
} & Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'>;

function MultiPageFormInContext({
children,
validatePage=pass, onPageChange=pass, onSubmit,
submitting, ...formParams
validatePage = pass,
onPageChange = pass,
onSubmit,
submitting,
...formParams
}: MultiPageFormProps) {
const formRef = React.useRef<HTMLFormElement>(null);

return (
<div className="multi-page-form">
<form
acceptCharset="UTF-8" className="form"
method="post" ref={formRef} {...formParams}
acceptCharset="UTF-8"
className="form"
method="post"
ref={formRef}
{...formParams}
aria-label="form"
>
<PagesContextProvider
Expand All @@ -76,10 +85,9 @@ function MultiPageFormInContext({
>
<MarkupChildren children={children} />
<PageCount />
{
submitting &&
<div className="big-message">Submitting...</div>
}
{submitting && (
<div className="big-message">Submitting...</div>
)}
<ButtonRow disabled={submitting} {...{formRef, onSubmit}} />
</PagesContextProvider>
</form>
Expand Down
28 changes: 13 additions & 15 deletions src/app/components/multi-page-form/pages-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@ import {useState, useRef, useEffect, useCallback} from 'react';
import usePaginatorContext from '~/components/paginator/paginator-context';
import buildContext from '~/components/jsx-helpers/build-context';

function useContextValue({pages, validatePage, onPageChange}: {
function useContextValue({
pages,
validatePage,
onPageChange
}: {
pages: number;
validatePage: (p: unknown) => boolean;
onPageChange: (p: unknown) => void;
validatePage: (p: number) => boolean;
onPageChange: (p: number) => void;
}) {
const [validatedPages, setValidatedPages] = useState({});
const activeRef = useRef<HTMLDivElement>(null);
const {currentPage} = usePaginatorContext();
const validateCurrentPage = useCallback(
() => {
const invalid = activeRef.current?.querySelector(':invalid');
const validateCurrentPage = useCallback(() => {
const invalid = activeRef.current?.querySelector(':invalid');

setValidatedPages({[currentPage]: true, ...validatedPages});
return invalid === null && validatePage(currentPage);
},
[currentPage, validatedPages, validatePage]
);
setValidatedPages({[currentPage]: true, ...validatedPages});
return invalid === null && validatePage(currentPage);
}, [currentPage, validatedPages, validatePage]);

useEffect(() => {
onPageChange(currentPage);
Expand All @@ -29,7 +30,4 @@ function useContextValue({pages, validatePage, onPageChange}: {

const {useContext, ContextProvider} = buildContext({useContextValue});

export {
useContext as default,
ContextProvider as PagesContextProvider
};
export {useContext as default, ContextProvider as PagesContextProvider};
4 changes: 2 additions & 2 deletions src/app/helpers/use-document-head.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,11 @@ export default function useDocumentHead({
noindex = false
}: {
title?: string;
description?: string;
description?: string | null;
noindex?: boolean;
}) {
useEffect(() => {
setPageTitleAndDescription(title, description);
setPageTitleAndDescription(title, description ?? undefined);
}, [title, description]);

useEffect(() => {
Expand Down
Loading