Skip to content

Commit

Permalink
fix: 2044 register page (#26)
Browse files Browse the repository at this point in the history
* add TeacherForm

* indep 1st block

* add indepLearner form

* password

* EmailVerificationSent page

* EmailVerificationFailed page

* clean up

* show messages if password do not match

* clean up

* rewrite teacher form with formik & yup

* password strength check

* rewrite indep form with formik

* add MyErrorMessage

* add required for T&C option in indep form

* extract CflErrorMessage

* use helperText for form fields

* fix linting

* merge from main

* rename files

* simplify spacing

* quick save

* add cfl field components

* quick save

* create reusable cfl form fields

* enforce type safety

* create cfl checkbox field

* house keeping

* MuiTypographyFormVariantStyle

* reuse theme variable

* create date picker component

* quick save

* code cleanup and fix date picker

* reuse components

* add base html tag

* use new CFL package

* email verification page

Co-Authored-By: SKairinos <stefan.kairinos@ocado.com>
  • Loading branch information
cewei8483 and SKairinos authored May 10, 2023
1 parent 5e0d8d5 commit 78477e2
Show file tree
Hide file tree
Showing 21 changed files with 1,284 additions and 39 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ yarn-error.log*
/backend/static
*.sqlite3
/frontend/build
node_modules
8 changes: 5 additions & 3 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@
"@mui/icons-material": "^5.11.11",
"@mui/material": "^5.11.12",
"@reduxjs/toolkit": "^1.9.3",
"codeforlife": "github:ocadotechnology/codeforlife-package-javascript#v1.5.5",
"codeforlife": "github:ocadotechnology/codeforlife-package-javascript#v1.7.1",
"formik": "^2.2.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.8.2",
"react-scripts": "^5.0.1",
"sass": "^1.58.3",
"web-vitals": "^2.1.4"
"web-vitals": "^2.1.4",
"yup": "^1.1.1"
},
"devDependencies": {
"@cypress/code-coverage": "^3.10.0",
Expand All @@ -60,4 +62,4 @@
"nyc": {
"exclude": []
}
}
}
1 change: 1 addition & 0 deletions frontend/public/handlebars_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

<head>
<title>Code for Life</title>
<base href="/">
<link rel="icon" type="image/x-icon" href="{% static '{{ faviconUrl }}' %}">
<style>
html,
Expand Down
1 change: 1 addition & 0 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Code for Life</title>
<base href="/">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<style>
html,
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/app/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ import Newsletter from '../pages/newsletter/Newsletter';
import Forbidden from '../pages/forbidden/Forbidden';
import PageNotFound from '../pages/pageNotFound/PageNotFound';
import InternalServerError from '../pages/internalServerError/InternalServerError';
import EmailVerification from 'pages/emailVerification/EmailVerification';

export const paths = {
home: '/',
teachers: '/teachers',
students: '/students',
register: '/register',
emailVerification: '/register/email-verification',
aboutUs: '/about-us',
codingClubs: '/coding-clubs',
getInvolved: '/get-involved',
Expand Down Expand Up @@ -90,6 +92,10 @@ const router = createBrowserRouter([
{
path: paths.internalServerError,
element: <InternalServerError />
},
{
path: paths.emailVerification,
element: <EmailVerification />
}
]);

Expand Down
52 changes: 40 additions & 12 deletions frontend/src/app/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,59 @@ import { createTheme, ThemeOptions } from '@mui/material/styles';

import { theme as cflTheme } from 'codeforlife';

// Styles shared by all form components.
export const formStyleOverrides = {
fontFamily: '"Inter"',
fontSize: '14px',
fontWeight: 500,
marginBottom: '12px'
};

const options: ThemeOptions = {
typography: {
h1: {
fontFamily: '"SpaceGrotesk"',
fontWeight: 500,
marginBottom: 24
marginBottom: '24px'
},
h2: {
fontFamily: '"SpaceGrotesk"',
fontWeight: 500,
marginBottom: 22
marginBottom: '22px'
},
h3: {
fontFamily: '"SpaceGrotesk"',
fontWeight: 500,
marginBottom: 20
marginBottom: '20px'
},
h4: {
fontFamily: '"SpaceGrotesk"',
fontWeight: 500,
marginBottom: 18
marginBottom: '18px'
},
h5: {
fontFamily: '"SpaceGrotesk"',
fontWeight: 500,
marginBottom: 16
marginBottom: '16px'
},
h6: {
fontFamily: '"SpaceGrotesk"',
fontWeight: 500,
marginBottom: 14
marginBottom: '14px'
},
body1: {
fontFamily: '"Inter"',
fontSize: 18,
marginBottom: 16
fontSize: '18px',
marginBottom: '16px'
},
body2: {
fontFamily: '"Inter"',
fontSize: 16,
marginBottom: 14
fontSize: '16px',
marginBottom: '14px'
},
button: {
fontFamily: '"Inter"',
fontSize: 14,
fontSize: '14px',
fontWeight: 550
}
},
Expand Down Expand Up @@ -80,13 +88,17 @@ const options: ThemeOptions = {
MuiFormControlLabel: {
defaultProps: {
sx: {
'.MuiTypography-root': { m: 0 }
'.MuiTypography-root': {
...formStyleOverrides,
m: 0
}
}
}
},
MuiInputBase: {
styleOverrides: {
root: {
background: 'white',
margin: 0
}
}
Expand Down Expand Up @@ -114,6 +126,22 @@ const options: ThemeOptions = {
padding: 0
})
}
},
MuiFormHelperText: {
styleOverrides: {
root: {
...formStyleOverrides,
marginTop: 4,
marginLeft: 4
}
}
},
MuiCheckbox: {
styleOverrides: {
root: {
color: 'white'
}
}
}
// MuiToolbar: {
// styleOverrides: {
Expand Down
163 changes: 163 additions & 0 deletions frontend/src/components/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import React from 'react';
import {
Unstable_Grid2 as Grid,
Select,
SelectProps,
MenuItem,
FormHelperText,
FormHelperTextProps
} from '@mui/material';

import { formStyleOverrides } from '../app/theme';

const monthOptions = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];

export interface DatePickerProps {
defaultsToToday?: boolean,
previousYears?: number,
helperText?: string,
formHelperTextProps?: FormHelperTextProps,
onChange: (date: Date | undefined) => void
}

const DatePicker: React.FC<DatePickerProps> = ({
defaultsToToday = false,
previousYears = 150,
helperText,
formHelperTextProps,
onChange
}) => {
const now = new Date();

const [date, setDate] = React.useState((defaultsToToday)
? { day: now.getDay(), month: now.getMonth(), year: now.getFullYear() }
: { day: 0, month: 0, year: 0 }
);

const dayIsDisabled = date.month === 0 || date.year === 0;

if ([date.day, date.month, date.year].every(n => n !== 0)) {
onChange(new Date(date.year, date.month, date.day));
}

function getLastDay(month: number, year: number): number {
return new Date(year, month, 0).getDate();
}

function _onChange(
key: 'day' | 'month' | 'year',
value: number | string
): void {
const newDate = { ...date };
newDate[key] = Number(value);

if (key !== 'day' &&
!dayIsDisabled &&
newDate.day > getLastDay(newDate.month, newDate.year)
) {
newDate.day = 0;
onChange(undefined);
}

setDate(newDate);
}

function getDayOptions(): number[] {
return Array
.from(Array(getLastDay(date.month, date.year)).keys())
.map(day => day + 1);
}

const yearOptions = Array
.from(Array(previousYears).keys())
.map(year => year + 1 - previousYears + now.getFullYear())
.reverse();

const commonSelectProps: SelectProps<number> = {
style: { backgroundColor: 'white', width: '100%' },
size: 'small'
};

return (
<Grid
container
columnSpacing={2}
marginBottom={formStyleOverrides.marginBottom}
>
{helperText !== undefined && helperText !== '' &&
<Grid xs={12}>
<FormHelperText {...formHelperTextProps}>
{helperText}
</FormHelperText>
</Grid>
}
<Grid xs={4}>
<Select
id='select-day'
value={date.day}
onChange={(event) => { _onChange('day', event.target.value); }}
disabled={dayIsDisabled}
{...commonSelectProps}
>
<MenuItem className='header' value={0}>
Day
</MenuItem>
{!dayIsDisabled && getDayOptions().map((day) =>
<MenuItem key={`day-${day}`} value={day} dense>
{day}
</MenuItem>
)}
</Select>
</Grid>
<Grid xs={4}>
<Select
id='select-month'
value={date.month}
onChange={(event) => { _onChange('month', event.target.value); }}
{...commonSelectProps}
>
<MenuItem className='header' value={0}>
Month
</MenuItem>
{monthOptions.map((month, index) =>
<MenuItem key={`month-${month}`} value={index + 1} dense>
{month}
</MenuItem>
)}
</Select>
</Grid>
<Grid xs={4}>
<Select
id='select-year'
value={date.year}
onChange={(event) => { _onChange('year', event.target.value); }}
{...commonSelectProps}
>
<MenuItem className='header' value={0}>
Year
</MenuItem>
{yearOptions.map((year) =>
<MenuItem key={`year-${year}`} value={year} dense>
{year}
</MenuItem>
)}
</Select>
</Grid>
</Grid>
);
};

export default DatePicker;
11 changes: 9 additions & 2 deletions frontend/src/components/PageSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@ export interface PageSectionProps extends Pick<Grid2Props, (
py?: boolean
background?: string
className?: string
maxWidth?: Breakpoint
}

const PageSection: React.FC<PageSectionProps> = ({
bgcolor, children, px = true, py = true, background, className
bgcolor,
children,
px = true,
py = true,
background,
className,
maxWidth = process.env.REACT_APP_CONTAINER_MAX_WIDTH as Breakpoint
}) => {
return <>
<Grid
Expand All @@ -27,7 +34,7 @@ const PageSection: React.FC<PageSectionProps> = ({
sx={{ background, bgcolor }}
>
<Container
maxWidth={process.env.REACT_APP_CONTAINER_MAX_WIDTH as Breakpoint}
maxWidth={maxWidth}
className={className}
>
{children}
Expand Down
Loading

0 comments on commit 78477e2

Please sign in to comment.