Skip to content

Commit

Permalink
feat/create add-form UI (#517)
Browse files Browse the repository at this point in the history
  • Loading branch information
Indraneel Purohit authored Jul 12, 2024
1 parent 19bf5cf commit d173294
Show file tree
Hide file tree
Showing 14 changed files with 1,461 additions and 3 deletions.
1 change: 1 addition & 0 deletions web-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"react-dom": "^17.0.0 || ^18.0.0",
"react-ga4": "^2.1.0",
"react-google-recaptcha": "^3.1.0",
"react-hook-form": "^7.52.0",
"react-i18next": "^14.1.2",
"react-leaflet": "^4.2.1",
"react-loading-overlay-ts": "^2.0.2",
Expand Down
Binary file added web-app/public/assets/rocket.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 26 additions & 1 deletion web-app/src/app/Theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const palette = {
},
text: {
primary: '#474747',
secondary: '#95a4f4',
secondary: 'rgba(71, 71, 71, 0.8)',
disabled: 'rgba(0,0,0,0.3)',
},
};
Expand All @@ -50,10 +50,35 @@ export const theme = createTheme({
fontFamily: '"Muli"',
},
components: {
MuiFormLabel: {
styleOverrides: {
root: {
color: '#474747',
fontWeight: 'bold',
},
},
},
MuiTextField: {
styleOverrides: {
root: {
'&.md-small-input': {
input: { paddingTop: '7px', paddingBottom: '7px' },
},
},
},
},
MuiSelect: {
styleOverrides: {
root: {
'.MuiSelect-select': { paddingTop: '7px', paddingBottom: '7px' },
},
},
},
MuiButton: {
styleOverrides: {
root: {
textTransform: 'none',
boxShadow: 'none',
},
},
},
Expand Down
8 changes: 6 additions & 2 deletions web-app/src/app/router/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import Home from '../screens/Home';
import ForgotPassword from '../screens/ForgotPassword';
import FAQ from '../screens/FAQ';
import About from '../screens/About';
import Contribute from '../screens/Contribute';
import PostRegistration from '../screens/PostRegistration';
import TermsAndConditions from '../screens/TermsAndConditions';
import PrivacyPolicy from '../screens/PrivacyPolicy';
Expand All @@ -25,6 +24,9 @@ import {
} from '../services/channel-service';
import { useAppDispatch } from '../hooks';
import { logout } from '../store/profile-reducer';
import FeedSubmission from '../screens/FeedSubmission';
import FeedSubmissionFAQ from '../screens/FeedSubmissionFAQ';
import FeedSubmitted from '../screens/FeedSubmitted';

export const AppRouter: React.FC = () => {
const navigateTo = useNavigate();
Expand Down Expand Up @@ -82,7 +84,9 @@ export const AppRouter: React.FC = () => {
<Route path='about' element={<About />} />
<Route path='feeds' element={<Feeds />} />
<Route path='feeds/:feedId' element={<Feed />} />
<Route path='contribute' element={<Contribute />} />
<Route path='contribute' element={<FeedSubmission />} />
<Route path='contribute/submitted' element={<FeedSubmitted />} />
<Route path='contribute-faq' element={<FeedSubmissionFAQ />} />
<Route path='privacy-policy' element={<PrivacyPolicy />} />
<Route path='terms-and-conditions' element={<TermsAndConditions />} />
</Routes>
Expand Down
50 changes: 50 additions & 0 deletions web-app/src/app/screens/FeedSubmission/FeedSubmissionStepper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Stepper from '@mui/material/Stepper';
import Step from '@mui/material/Step';
import StepLabel from '@mui/material/StepLabel';
import FeedSubmissionForm from './Form';
import { useNavigate } from 'react-router-dom';

const steps = ['', '', ''];

export default function FeedSubmissionStepper(): React.ReactElement {
const [activeStep, setActiveStep] = React.useState(0);
const navigateTo = useNavigate();

const handleNext = (): void => {
const nextStep = activeStep + 1;
setActiveStep(nextStep);
if (nextStep === steps.length) {
navigateTo('/contribute/submitted');
}
};

const handleBack = (): void => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};

return (
<Box sx={{ width: '100%', px: 5 }}>
<Stepper activeStep={activeStep} sx={{ mb: 3 }}>
{steps.map((label) => {
const stepProps: { completed?: boolean } = {};
const labelProps: {
optional?: React.ReactNode;
} = {};
return (
<Step key={label} {...stepProps}>
<StepLabel {...labelProps}>{label}</StepLabel>
</Step>
);
})}
</Stepper>

<FeedSubmissionForm
activeStep={activeStep}
handleBack={handleBack}
handleNext={handleNext}
/>
</Box>
);
}
201 changes: 201 additions & 0 deletions web-app/src/app/screens/FeedSubmission/Form/FirstStep.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import {
Grid,
FormControl,
FormLabel,
RadioGroup,
FormControlLabel,
Radio,
Select,
MenuItem,
Button,
TextField,
FormHelperText,
} from '@mui/material';

import { type SubmitHandler, Controller, useForm } from 'react-hook-form';
import { type FeedSubmissionFormFormInput } from '.';

export interface FeedSubmissionFormFormInputFirstStep {
name: string;
isOfficialProducer: string;
dataType: string;
transitProviderName: string;
feedLink: string;
licensePath: string;
}

interface FormFirstStepProps {
initialValues: FeedSubmissionFormFormInput;
submitFormData: (formData: Partial<FeedSubmissionFormFormInput>) => void;
}

export default function FormFirstStep({
initialValues,
submitFormData,
}: FormFirstStepProps): React.ReactElement {
const {
control,
handleSubmit,
formState: { errors },
} = useForm<FeedSubmissionFormFormInputFirstStep>({
defaultValues: {
name: initialValues.name,
isOfficialProducer: initialValues.isOfficialProducer,
dataType: initialValues.dataType,
transitProviderName: initialValues.transitProviderName,
feedLink: initialValues.feedLink,
licensePath: initialValues.licensePath,
},
});
const onSubmit: SubmitHandler<FeedSubmissionFormFormInputFirstStep> = (
data,
): void => {
submitFormData(data);
};
return (
<>
{/* eslint-disable-next-line @typescript-eslint/no-misused-promises */}
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container direction={'column'} rowSpacing={2}>
<Grid item>
<FormControl
component='fieldset'
fullWidth
error={errors.name !== undefined}
>
<FormLabel required>
Your Name and (if applicable) Organization
</FormLabel>
<Controller
rules={{ required: 'Your name is required' }}
control={control}
name='name'
render={({ field }) => (
<TextField
{...field}
className='md-small-input'
sx={{
input: { py: 1 },
}}
error={errors.name !== undefined}
helperText={errors.name?.message ?? ''}
/>
)}
/>
</FormControl>
</Grid>
<Grid item>
<FormControl
component='fieldset'
error={errors.isOfficialProducer !== undefined}
>
<FormLabel required>
Are you the official producer or transit agency responsible for
this data ?
</FormLabel>
<Controller
rules={{ required: 'This field is required' }}
control={control}
name='isOfficialProducer'
render={({ field }) => (
<>
<RadioGroup {...field}>
<FormControlLabel
value='yes'
control={<Radio color='default' />}
label='Yes'
/>
<FormControlLabel
value='no'
control={<Radio sx={{}} />}
label='No'
/>
</RadioGroup>
<FormHelperText>
{errors.isOfficialProducer?.message ?? ''}
</FormHelperText>
</>
)}
/>
</FormControl>
</Grid>
<Grid item>
<FormControl
component='fieldset'
error={errors.dataType !== undefined}
>
<FormLabel required>Data Type</FormLabel>
<Controller
rules={{ required: true }}
control={control}
name='dataType'
render={({ field }) => (
<Select {...field}>
<MenuItem value={'GTFS Schedule'}>GTFS Schedule</MenuItem>
<MenuItem value={'GTFS Realtime'}>GTFS Realtime</MenuItem>
</Select>
)}
/>
</FormControl>
</Grid>
<Grid item>
<FormControl component='fieldset' fullWidth>
<FormLabel>Transit Provider Name</FormLabel>
<Controller
control={control}
name='transitProviderName'
render={({ field }) => (
<TextField {...field} className='md-small-input' />
)}
/>
</FormControl>
</Grid>
<Grid item>
<FormControl
component='fieldset'
fullWidth
error={errors.feedLink !== undefined}
>
<FormLabel component='legend' required>
Feed link
</FormLabel>
<Controller
rules={{ required: 'Feed link required' }}
control={control}
name='feedLink'
render={({ field }) => (
<TextField
className='md-small-input'
helperText={errors.feedLink?.message ?? ''}
error={errors.feedLink !== undefined}
{...field}
/>
)}
/>
</FormControl>
</Grid>
<Grid item>
<FormControl component='fieldset' fullWidth>
<FormLabel component='legend'>Link to feed license</FormLabel>
<Controller
control={control}
name='licensePath'
render={({ field }) => (
<TextField className='md-small-input' {...field} />
)}
/>
</FormControl>
</Grid>

<Grid container spacing={2}>
<Grid item>
<Button type='submit' variant='contained' sx={{ mt: 3, mb: 2 }}>
Next
</Button>
</Grid>
</Grid>
</Grid>
</form>
</>
);
}
Loading

0 comments on commit d173294

Please sign in to comment.