Skip to content
Snippets Groups Projects
Verified Commit ebd1a2b3 authored by Andreas Ellewsen's avatar Andreas Ellewsen
Browse files

Enforce double quotes for jsx

parent 94a3b8b3
No related branches found
No related tags found
No related merge requests found
Pipeline #96960 passed
This commit is part of merge request !110. Comments created here will be created in the context of that merge request.
......@@ -25,6 +25,7 @@
"react/jsx-props-no-spreading": "off",
"@typescript-eslint/semi": ["error", "never"],
"react/jsx-uses-react": "off",
"jsx-quotes": "error",
"react/react-in-jsx-scope": "off"
}
}
......@@ -2,13 +2,12 @@ import React from 'react'
import { render, waitFor, screen } from '@testing-library/react'
import Link from './index'
describe('Tests for Link component', () => {
test('External link prefixes route link with //', async () => {
render(<Link external to='example.org' />)
render(<Link external to="example.org" />)
await waitFor(() => screen.getByRole('link'))
expect(screen.getByRole('link')).toHaveAttribute('href', '//example.org')
})
})
\ No newline at end of file
})
......@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'
import { useHistory } from 'react-router-dom'
interface SponsorGuestButtonsProps {
yourGuestsActive?: boolean,
yourGuestsActive?: boolean
registerNewGuestActive?: boolean
}
......@@ -24,41 +24,70 @@ export default function SponsorGuestButtons(props: SponsorGuestButtonsProps) {
}
return (
<Box sx={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-evenly', marginBottom: '2rem' }}>
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-evenly',
marginBottom: '2rem',
}}
>
<Box
sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}
>
<IconButton onClick={goToOverview}>
<PersonIcon
fontSize='large'
fontSize="large"
sx={{
borderRadius: '2rem',
borderStyle: 'solid',
borderColor: (theme: Theme) => yourGuestsActive ? theme.palette.primary.main : theme.greg.deactivatedColor,
borderColor: (theme: Theme) =>
yourGuestsActive
? theme.palette.primary.main
: theme.greg.deactivatedColor,
fill: 'white',
backgroundColor: (theme: Theme) => yourGuestsActive ? theme.palette.primary.main : theme.greg.deactivatedColor,
}} />
backgroundColor: (theme: Theme) =>
yourGuestsActive
? theme.palette.primary.main
: theme.greg.deactivatedColor,
}}
/>
</IconButton>
<Box sx={{
typography: 'caption',
}}>
<Box
sx={{
typography: 'caption',
}}
>
{t('yourGuests')}
</Box>
</Box>
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<Box
sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}
>
<IconButton onClick={goToRegister}>
<PersonAddIcon
fontSize='large'
fontSize="large"
sx={{
borderRadius: '2rem',
borderStyle: 'solid',
borderColor: (theme: Theme) => registerNewGuestActive ? theme.palette.primary.main : theme.greg.deactivatedColor,
borderColor: (theme: Theme) =>
registerNewGuestActive
? theme.palette.primary.main
: theme.greg.deactivatedColor,
fill: 'white',
backgroundColor: (theme: Theme) => registerNewGuestActive ? theme.palette.primary.main : theme.greg.deactivatedColor,
}} />
backgroundColor: (theme: Theme) =>
registerNewGuestActive
? theme.palette.primary.main
: theme.greg.deactivatedColor,
}}
/>
</IconButton>
<Box sx={{
typography: 'caption',
}}>
<Box
sx={{
typography: 'caption',
}}
>
{t('registerNewGuest')}
</Box>
</Box>
......
......@@ -12,7 +12,7 @@ function InviteLink() {
useEffect(() => {
fetch(`/api/ui/v1/invited/${id}`)
}, [])
return <Redirect to='/invite' />
return <Redirect to="/invite" />
}
export default InviteLink
......@@ -13,7 +13,6 @@ import { SummaryFormMethods } from './summaryFormMethods'
import SubmitState from './submitState'
import SponsorGuestButtons from '../components/sponsorGuestButtons'
export default function StepRegistration() {
const { t } = useTranslation(['common'])
const [formData, setFormData] = useState<RegisterFormData>({
......@@ -56,7 +55,7 @@ export default function StepRegistration() {
}
const handleForwardFromRegister = (
updateFormData: RegisterFormData,
updateFormData: RegisterFormData
): void => {
setFormData(updateFormData)
setActiveStep((prevActiveStep) => prevActiveStep + 1)
......@@ -96,11 +95,21 @@ export default function StepRegistration() {
)}
</Box>
<Box sx={{ display: 'flex', flexDirection: 'row', pt: 2, color: 'primary.main', paddingBottom: '1rem' }}>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
pt: 2,
color: 'primary.main',
paddingBottom: '1rem',
}}
>
{activeStep === REGISTER_STEP && (
<Button data-testid='button-next'
sx={{ color: 'theme.palette.secondary', mr: 1 }}
onClick={handleNext}>
<Button
data-testid="button-next"
sx={{ color: 'theme.palette.secondary', mr: 1 }}
onClick={handleNext}
>
{t('button.next')}
</Button>
)}
......
......@@ -11,7 +11,13 @@ import {
} from '@mui/material'
import { Controller, SubmitHandler, useForm } from 'react-hook-form'
import { DatePicker } from '@mui/lab'
import React, { forwardRef, Ref, useEffect, useImperativeHandle, useState } from 'react'
import React, {
forwardRef,
Ref,
useEffect,
useImperativeHandle,
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { RegisterFormData } from './formData'
import { PersonFormMethods } from './personFormMethods'
......@@ -19,214 +25,231 @@ import useOus, { OuData } from '../../hooks/useOus'
import useRoleTypes, { RoleTypeData } from '../../hooks/useRoleTypes'
import { isValidEmail } from '../../utils'
interface StepPersonFormProperties {
nextHandler(formState: RegisterFormData): void
formData: RegisterFormData
}
const StepPersonForm = forwardRef((props: StepPersonFormProperties, ref: Ref<PersonFormMethods>) => {
const { i18n, t } = useTranslation(['common'])
const { nextHandler, formData } = props
const ous = useOus()
const [ouChoice, setOuChoice] = useState(formData.ou_id ? formData.ou_id : '')
const [selectedRoleType, setSelectedRoleType] = useState(formData.role_type ? formData.role_type : '')
const roleTypes = useRoleTypes()
const roleTypeSort = () => (a: RoleTypeData, b: RoleTypeData) => {
if (i18n.language === 'en') {
return a.name_nb.localeCompare(b.name_nb)
const StepPersonForm = forwardRef(
(props: StepPersonFormProperties, ref: Ref<PersonFormMethods>) => {
const { i18n, t } = useTranslation(['common'])
const { nextHandler, formData } = props
const ous = useOus()
const [ouChoice, setOuChoice] = useState(
formData.ou_id ? formData.ou_id : ''
)
const [selectedRoleType, setSelectedRoleType] = useState(
formData.role_type ? formData.role_type : ''
)
const roleTypes = useRoleTypes()
const roleTypeSort = () => (a: RoleTypeData, b: RoleTypeData) => {
if (i18n.language === 'en') {
return a.name_nb.localeCompare(b.name_nb)
}
return a.name_en.localeCompare(b.name_en)
}
return a.name_en.localeCompare(b.name_en)
}
const enSort = (a: OuData, b: OuData) => {
if (a.en > b.en) {
return 1
const enSort = (a: OuData, b: OuData) => {
if (a.en > b.en) {
return 1
}
if (b.en > a.en) {
return -1
}
return 0
}
if (b.en > a.en) {
return -1
}
return 0
}
const nbSort = (a: OuData, b: OuData) => {
if (a.nb > b.nb) {
return 1
const nbSort = (a: OuData, b: OuData) => {
if (a.nb > b.nb) {
return 1
}
if (b.nb > a.nb) {
return -1
}
return 0
}
if (b.nb > a.nb) {
return -1
}
return 0
}
const submit: SubmitHandler<RegisterFormData> = (data) => {
nextHandler(data)
}
const submit: SubmitHandler<RegisterFormData> = (data) => {
nextHandler(data)
}
const {
register,
control,
handleSubmit,
formState: { errors },
reset,
setValue,
} = useForm<RegisterFormData>()
const onSubmit = handleSubmit(submit)
useEffect(() => {
reset(formData)
}, [])
const handleOuChange = (event: SelectChangeEvent) => {
if (event.target.value) {
setOuChoice(event.target.value)
setValue('ou_id', parseInt(event.target.value, 10))
} else {
setValue('ou_id', undefined)
const {
register,
control,
handleSubmit,
formState: { errors },
reset,
setValue,
} = useForm<RegisterFormData>()
const onSubmit = handleSubmit(submit)
useEffect(() => {
reset(formData)
}, [])
const handleOuChange = (event: SelectChangeEvent) => {
if (event.target.value) {
setOuChoice(event.target.value)
setValue('ou_id', parseInt(event.target.value, 10))
} else {
setValue('ou_id', undefined)
}
}
}
register('role_type', {
required: t<string>('validation.roleTypeRequired'),
})
register('role_type', {
required: t<string>('validation.roleTypeRequired'),
})
const handleRoleTypeChange = (event: any) => {
setValue('role_type', event.target.value)
setSelectedRoleType(event.target.value)
}
const handleRoleTypeChange = (event: any) => {
setValue('role_type', event.target.value)
setSelectedRoleType(event.target.value)
}
function doSubmit() {
return onSubmit()
}
function doSubmit() {
return onSubmit()
}
useImperativeHandle(ref, () => ({ doSubmit }))
return (
<>
<Typography variant='h5' sx={{
paddingTop: '1rem',
paddingBottom: '1rem',
}}>{t('registerWizardText.registerContactInfo')}</Typography>
<Typography sx={{ paddingBottom: '2rem' }}>{t('registerWizardText.registerPage')}</Typography>
<Box sx={{ maxWidth: '30rem' }}>
<form onSubmit={onSubmit}>
<Stack spacing={2}>
<TextField
id='firstName'
label={t('input.firstName')}
error={!!errors.first_name}
helperText={errors.first_name && errors.first_name.message}
{...register(`first_name`, {
required: t<string>('validation.firstNameRequired'),
})}
/>
<TextField
id='lastName'
label={t('input.lastName')}
error={!!errors.last_name}
helperText={errors.last_name && errors.last_name.message}
{...register(`last_name`, {
required: t<string>('validation.lastNameRequired'),
})}
/>
<TextField
id='email'
label={t('input.email')}
error={!!errors.email}
helperText={errors.email && errors.email.message}
{...register(`email`, {
validate: isValidEmail,
})}
/>
<Typography variant='h5' sx={{ paddingTop: '1rem' }}>{t('registerWizardText.registerPeriod')}</Typography>
<Typography sx={{ paddingBottom: '1rem' }}>{t('registerWizardText.registerPeriodText')}</Typography>
<FormControl fullWidth>
<InputLabel id='ou-select-label'>{t('common:ou')}</InputLabel>
<Select
labelId='ou-select-label'
id='ou-select-label'
value={ouChoice?.toString()}
label={t('common:ou')}
onChange={handleOuChange}
useImperativeHandle(ref, () => ({ doSubmit }))
return (
<>
<Typography
variant="h5"
sx={{
paddingTop: '1rem',
paddingBottom: '1rem',
}}
>
{t('registerWizardText.registerContactInfo')}
</Typography>
<Typography sx={{ paddingBottom: '2rem' }}>
{t('registerWizardText.registerPage')}
</Typography>
<Box sx={{ maxWidth: '30rem' }}>
<form onSubmit={onSubmit}>
<Stack spacing={2}>
<TextField
id="firstName"
label={t('input.firstName')}
error={!!errors.first_name}
helperText={errors.first_name && errors.first_name.message}
{...register(`first_name`, {
required: t<string>('validation.firstNameRequired'),
})}
/>
<TextField
id="lastName"
label={t('input.lastName')}
error={!!errors.last_name}
helperText={errors.last_name && errors.last_name.message}
{...register(`last_name`, {
required: t<string>('validation.lastNameRequired'),
})}
/>
<TextField
id="email"
label={t('input.email')}
error={!!errors.email}
helperText={errors.email && errors.email.message}
{...register(`email`, {
validate: isValidEmail,
})}
/>
<Typography variant="h5" sx={{ paddingTop: '1rem' }}>
{t('registerWizardText.registerPeriod')}
</Typography>
<Typography sx={{ paddingBottom: '1rem' }}>
{t('registerWizardText.registerPeriodText')}
</Typography>
<FormControl fullWidth>
<InputLabel id="ou-select-label">{t('common:ou')}</InputLabel>
<Select
labelId="ou-select-label"
id="ou-select-label"
value={ouChoice?.toString()}
label={t('common:ou')}
onChange={handleOuChange}
>
{ous.length > 0
? ous
.sort(i18n.language === 'en' ? enSort : nbSort)
.map((ou) => (
<MenuItem key={ou.id.toString()} value={ou.id}>
{i18n.language === 'en' ? ou.en : ou.nb} ({ou.id})
</MenuItem>
))
: ''}
</Select>
</FormControl>
<TextField
id="roletype-select"
select
value={selectedRoleType}
error={!!errors.role_type}
label={t('input.roleType')}
onChange={handleRoleTypeChange}
>
{ous.length > 0 ? (
ous
.sort(i18n.language === 'en' ? enSort : nbSort)
.map((ou) => (
<MenuItem key={ou.id.toString()} value={ou.id}>
{i18n.language === 'en' ? ou.en : ou.nb} ({ou.id})
</MenuItem>
))
) : ('')}
</Select>
</FormControl>
<TextField
id='roletype-select'
select
value={selectedRoleType}
error={!!errors.role_type}
label={t('input.roleType')}
onChange={handleRoleTypeChange}
>
{
roleTypes.sort(roleTypeSort())
.map((roleType) => (
<MenuItem
key={roleType.id.toString()}
value={roleType.id}>{i18n.language === 'en' ? roleType.name_en : roleType.name_nb}</MenuItem>
))
}
</TextField>
<Controller name='role_start'
control={control}
render={({ field }) => (
<DatePicker
mask='____-__-__'
label={t('input.roleStartDate')}
value={field.value}
inputFormat='yyyy-MM-dd'
onChange={(value) => {
field.onChange(value)
}}
renderInput={(params) => <TextField {...params} />}
/>)}
/>
<Controller name='role_end'
control={control}
defaultValue={undefined}
render={({ field }) => (
<DatePicker
mask='____-__-__'
label={t('input.roleEndDate')}
value={field.value}
inputFormat='yyyy-MM-dd'
onChange={(value) => {
field.onChange(value)
}}
renderInput={(params) => <TextField {...params} />}
/>)}
/>
<TextField
id='comment'
label={t('input.comment')}
multiline
rows={5}
{...register(`comment`)}
/>
</Stack>
</form>
</Box>
</>
)
})
{roleTypes.sort(roleTypeSort()).map((roleType) => (
<MenuItem key={roleType.id.toString()} value={roleType.id}>
{i18n.language === 'en'
? roleType.name_en
: roleType.name_nb}
</MenuItem>
))}
</TextField>
<Controller
name="role_start"
control={control}
render={({ field }) => (
<DatePicker
mask="____-__-__"
label={t('input.roleStartDate')}
value={field.value}
inputFormat="yyyy-MM-dd"
onChange={(value) => {
field.onChange(value)
}}
renderInput={(params) => <TextField {...params} />}
/>
)}
/>
<Controller
name="role_end"
control={control}
defaultValue={undefined}
render={({ field }) => (
<DatePicker
mask="____-__-__"
label={t('input.roleEndDate')}
value={field.value}
inputFormat="yyyy-MM-dd"
onChange={(value) => {
field.onChange(value)
}}
renderInput={(params) => <TextField {...params} />}
/>
)}
/>
<TextField
id="comment"
label={t('input.comment')}
multiline
rows={5}
{...register(`comment`)}
/>
</Stack>
</form>
</Box>
</>
)
}
)
export default StepPersonForm
......@@ -33,17 +33,17 @@ const PersonLine = ({ person }: PersonLineProps) => {
key={person.name}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell component='th' scope='row'>
<TableCell component="th" scope="row">
{person.name}
</TableCell>
<TableCell align='left'>
<TableCell align="left">
{i18n.language === 'en' ? person.role_en : person.role_nb}
</TableCell>
<TableCell align='left'>{person.period}</TableCell>
<TableCell align='left'>
<TableCell align="left">{person.period}</TableCell>
<TableCell align="left">
{i18n.language === 'en' ? person.ou_en : person.ou_nb}
</TableCell>
<TableCell align='left'>
<TableCell align="left">
<Link to={`/sponsor/guest/${person.pid}`}>{t('common:details')}</Link>
</TableCell>
</TableRow>
......@@ -72,14 +72,14 @@ const ActiveGuests = ({ persons }: GuestProps) => {
<AccordionDetails>
<p>{t('common:activeGuestsDescription')}</p>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label='simple table'>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead sx={{ backgroundColor: 'primary.light' }}>
<TableRow>
<TableCell>{t('common:name')}</TableCell>
<TableCell align='left'>{t('common:role')}</TableCell>
<TableCell align='left'>{t('common:period')}</TableCell>
<TableCell align='left'>{t('common:ou')}</TableCell>
<TableCell align='left'>{t('common:choice')}</TableCell>
<TableCell align="left">{t('common:role')}</TableCell>
<TableCell align="left">{t('common:period')}</TableCell>
<TableCell align="left">{t('common:ou')}</TableCell>
<TableCell align="left">{t('common:choice')}</TableCell>
</TableRow>
</TableHead>
<TableBody>
......@@ -125,14 +125,14 @@ const WaitingGuests = ({ persons }: GuestProps) => {
<p>{t('common:waitingGuestsDescription')}</p>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label='simple table'>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead sx={{ backgroundColor: 'primary.light' }}>
<TableRow>
<TableCell>{t('common:name')}</TableCell>
<TableCell align='left'>{t('common:role')}</TableCell>
<TableCell align='left'>{t('common:period')}</TableCell>
<TableCell align='left'>{t('common:ou')}</TableCell>
<TableCell align='left'>{t('common:choice')}</TableCell>
<TableCell align="left">{t('common:role')}</TableCell>
<TableCell align="left">{t('common:period')}</TableCell>
<TableCell align="left">{t('common:ou')}</TableCell>
<TableCell align="left">{t('common:choice')}</TableCell>
</TableRow>
</TableHead>
<TableBody>
......@@ -160,10 +160,10 @@ function FrontPage({ guests }: FrontPageProps) {
const [t] = useTranslation(['common'])
return (
<Page header='Sponsor front page'>
<Link to='/register'>{t('common:registerText')}</Link>
<Page header="Sponsor front page">
<Link to="/register">{t('common:registerText')}</Link>
<WaitingGuests persons={guests} />
<hr className='rounded' />
<hr className="rounded" />
<ActiveGuests persons={guests} />
</Page>
)
......
......@@ -33,13 +33,13 @@ const RoleLine = ({ guest }: RoleLineProps) => {
key={guest.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell align='left'>
<TableCell align="left">
{i18n.language === 'en' ? guest.role_en : guest.role_nb}
</TableCell>
<TableCell component='th' scope='row'>
<TableCell component="th" scope="row">
{guest.period}
</TableCell>
<TableCell align='left'>
<TableCell align="left">
{i18n.language === 'en' ? guest.ou_en : guest.ou_nb}
</TableCell>
</TableRow>
......@@ -68,7 +68,7 @@ export default function GuestInfo({ guests }: GuestInfoProps) {
}}
>
<Box>
<IconButton component={Link} to='/sponsor'>
<IconButton component={Link} to="/sponsor">
<ArrowBackIcon />
</IconButton>
</Box>
......@@ -80,7 +80,7 @@ export default function GuestInfo({ guests }: GuestInfoProps) {
}}
>
<PersonOutlineRoundedIcon
fontSize='large'
fontSize="large"
sx={{
borderRadius: '2rem',
borderStyle: 'solid',
......@@ -100,41 +100,41 @@ export default function GuestInfo({ guests }: GuestInfoProps) {
</Box>
<h4>{t('sponsor.contactInfo')}</h4>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label='simple table'>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead sx={{ backgroundColor: 'primary.light' }}>
<TableRow>
<TableCell align='left'>{t('sponsor.contactInfo')}</TableCell>
<TableCell align="left">{t('sponsor.contactInfo')}</TableCell>
<TableCell />
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell align='left'>{t('input.fullName')}</TableCell>
<TableCell align='left'>{guestInfo.name}</TableCell>
<TableCell align="left">{t('input.fullName')}</TableCell>
<TableCell align="left">{guestInfo.name}</TableCell>
</TableRow>
<TableRow>
<TableCell align='left'>{t('input.email')}</TableCell>
<TableCell align='left'>{guestInfo.email}</TableCell>
<TableCell align="left">{t('input.email')}</TableCell>
<TableCell align="left">{guestInfo.email}</TableCell>
</TableRow>
<TableRow>
<TableCell align='left'>{t('input.nationalIdNumber')}</TableCell>
<TableCell align='left'>{guestInfo.fnr}</TableCell>
<TableCell align="left">{t('input.nationalIdNumber')}</TableCell>
<TableCell align="left">{guestInfo.fnr}</TableCell>
</TableRow>
<TableRow>
<TableCell align='left'>{t('input.mobilePhone')}</TableCell>
<TableCell align='left'>{guestInfo.mobile}</TableCell>
<TableCell align="left">{t('input.mobilePhone')}</TableCell>
<TableCell align="left">{guestInfo.mobile}</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
<h4>{t('sponsor.roleInfo')}</h4>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label='simple table'>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead sx={{ backgroundColor: 'primary.light' }}>
<TableRow>
<TableCell align='left'>{t('common:role')}</TableCell>
<TableCell align='left'>{t('common:period')}</TableCell>
<TableCell align='left'>{t('common:ou')}</TableCell>
<TableCell align="left">{t('common:role')}</TableCell>
<TableCell align="left">{t('common:period')}</TableCell>
<TableCell align="left">{t('common:ou')}</TableCell>
</TableRow>
</TableHead>
<TableBody>
......
......@@ -44,10 +44,10 @@ function Sponsor() {
return (
<>
<Route path='/sponsor/guest/:pid'>
<Route path="/sponsor/guest/:pid">
<GuestInfo guests={guests} />
</Route>
<Route exact path='/sponsor'>
<Route exact path="/sponsor">
<FrontPage guests={guests} />
</Route>
</>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment