Tweaked type definitions in signup form

This commit is contained in:
Jono Mingard 2023-05-24 15:53:04 +12:00
parent af907b70cb
commit 03fb1b188c
6 changed files with 32 additions and 33 deletions

View File

@ -1,15 +1,15 @@
import React, {ComponentProps} from 'react';
import pages, {Page, PageName} from './pages';
import {AppContext, SignupFormOptions} from './AppContext';
import {AppContextProvider, SignupFormOptions} from './AppContext';
import {ContentBox} from './components/ContentBox';
import {Frame} from './components/Frame';
import {setupGhostApi} from './utils/api';
type Props = {
type AppProps = {
options: SignupFormOptions;
};
const App: React.FC<Props> = ({options}) => {
const App: React.FC<AppProps> = ({options}) => {
const [page, setPage] = React.useState<Page>({
name: 'FormPage',
data: {}
@ -38,13 +38,13 @@ const App: React.FC<Props> = ({options}) => {
return (
<div>
<AppContext.Provider value={context}>
<AppContextProvider value={context}>
<Frame>
<ContentBox>
<PageComponent {...data} />
</ContentBox>
</Frame>
</AppContext.Provider>
</AppContextProvider>
</div>
);
};

View File

@ -1,5 +1,5 @@
// Ref: https://reactjs.org/docs/context.html
import React, {ComponentProps} from 'react';
import React, {ComponentProps, useContext} from 'react';
import pages, {Page, PageName} from './pages';
import {GhostApi} from './utils/api';
@ -19,4 +19,8 @@ export type AppContextType = {
api: GhostApi,
}
export const AppContext = React.createContext<AppContextType>({} as any);
const AppContext = React.createContext<AppContextType>({} as any);
export const AppContextProvider = AppContext.Provider;
export const useAppContext = () => useContext(AppContext);

View File

@ -1,12 +1,12 @@
import React from 'react';
import {AppContext} from '../AppContext';
import {useAppContext} from '../AppContext';
type Props = {
type ContentBoxProps = {
children: React.ReactNode
};
export const ContentBox: React.FC<Props> = ({children}) => {
const {color} = React.useContext(AppContext).options;
export const ContentBox: React.FC<ContentBoxProps> = ({children}) => {
const {color} = useAppContext().options;
const style = {
'--gh-accent-color': color

View File

@ -1,12 +1,10 @@
import React, {FormEventHandler} from 'react';
import {AppContext} from '../../AppContext';
import {isMinimal} from '../../utils/helpers';
import {isValidEmail} from '../../utils/validator';
import {useAppContext} from '../../AppContext';
type Props = {};
export const FormPage: React.FC<Props> = () => {
const {options} = React.useContext(AppContext);
export const FormPage: React.FC = () => {
const {options} = useAppContext();
if (isMinimal(options)) {
return (
@ -27,11 +25,11 @@ export const FormPage: React.FC<Props> = () => {
</div>;
};
const Form: React.FC<Props> = () => {
const Form: React.FC = () => {
const [email, setEmail] = React.useState('');
const [error, setError] = React.useState('');
const [loading, setLoading] = React.useState(false);
const {api, setPage, options} = React.useContext(AppContext);
const {api, setPage, options} = useAppContext();
const labels = options.labels;
const submit: FormEventHandler<HTMLFormElement> = async (e) => {

View File

@ -1,13 +1,13 @@
import React from 'react';
import {AppContext} from '../../AppContext';
import {isMinimal} from '../../utils/helpers';
import {useAppContext} from '../../AppContext';
type Props = {
type SuccessPageProps = {
email: string;
};
export const SuccessPage: React.FC<Props> = ({email}) => {
const {options} = React.useContext(AppContext);
export const SuccessPage: React.FC<SuccessPageProps> = ({email}) => {
const {options} = useAppContext();
if (isMinimal(options)) {
return <div>

View File

@ -2,23 +2,20 @@ import React from 'react';
import {FormPage} from './components/pages/FormPage';
import {SuccessPage} from './components/pages/SuccessPage';
// When adding a new page, also add it at the bottom to the Page type (*)
const Pages = {
FormPage,
SuccessPage
};
// (*) Note we have repeated names here, and don't use PageName
// to make type checking work for the Page type, so we have type checks in place
// that we pass the right data to the right page (otherwise it will only check if
// the name is correct, and the data is correct for any page, not the specific page)
export type Page = PageType<'FormPage'> | PageType<'SuccessPage'>;
export type PageName = keyof typeof Pages;
export type PageType<Name extends PageName> = {
name: Name;
// get props of component
data: React.ComponentProps<typeof Pages[Name]>;
type PageTypes = {
[name in PageName]: {
name: name,
data: React.ComponentProps<typeof Pages[name]>
}
}
export type Page = PageTypes[keyof PageTypes]
export default Pages;