-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add New Drive View #584
Merged
arturtamborski
merged 9 commits into
CodeForPoznan:react-revolution
from
vlakyi:pah-add-new-drive-form
May 2, 2021
Merged
Add New Drive View #584
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
163ae01
Add CarCountryFilter for more advanced filtering in admin panel (#556)
arturtamborski e69600b
PAH-557 add Kurdish translation (#571)
juliaanholcer 72c64f9
Merge branch 'master' of https://github.com/CodeForPoznan/pah-fm into…
vlakyi 7b24794
Fix issue related to shell script on windows (windows can't understan…
vlakyi ce4589f
Add formik and yup for forms state management and validation.
vlakyi ff513ba
Add colors for Add Drive View
vlakyi 78a2ff4
Create Add Drive View and Add new route for it.
vlakyi 4e55993
Resolve issues listed in code review(Renamed folder to AddDrive, chan…
vlakyi b82eeb0
Fix naming inconsitency and extract button's texts from JSX to variab…
vlakyi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Convert to LF line endings on checkout. | ||
*.sh text eol=lf | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import Page from '../../components/Page'; | ||
import { | ||
FormControl, | ||
Box, | ||
TextField, | ||
InputLabel, | ||
Select, | ||
MenuItem, | ||
Container, | ||
Button, | ||
Typography, | ||
} from '@material-ui/core'; | ||
|
||
import useT from '../../utils/translation'; | ||
import { useFormik } from 'formik'; | ||
import * as yup from 'yup'; | ||
|
||
// styling | ||
import { useStyles, WhiteBox, ButtonsContainer } from './styles'; | ||
|
||
const DriveView = () => { | ||
// local state | ||
const [traveled, setTraveled] = useState(0); | ||
|
||
// Translated labels | ||
const title = useT('Add new drive'); | ||
const errorTitle = useT('Please correct the following error(s):'); | ||
const traveledT = useT('traveled'); | ||
const submit = useT('Submit'); | ||
const reset = useT('Reset'); | ||
|
||
// separate object to generate fields dynamically | ||
const translatedFieldsLabels = { | ||
date: useT('Date'), | ||
startLocation: useT('Start location'), | ||
mileageStart: useT('Starting mileage'), | ||
project: useT('Project'), | ||
car: useT('Choose a car'), | ||
passenger: useT('Passenger'), | ||
description: useT('Description'), | ||
endLocation: useT('End location'), | ||
mileageEnd: useT('Ending mileage'), | ||
}; | ||
|
||
const validationSchema = yup.object().shape({ | ||
startLocation: yup.string().required(useT('Start location is required')), | ||
mileageStart: yup.number().required(useT('Starting mileage is required')), | ||
project: yup.string().required(useT('Project is required')), | ||
car: yup.string().required(useT('Car is required')), | ||
passenger: yup.string().required(useT('Start location is required')), | ||
endLocation: yup.string().required(useT('End location is required')), | ||
mileageEnd: yup.number().required(useT('Ending mileage is required')), | ||
}); | ||
|
||
const formik = useFormik({ | ||
initialValues: { | ||
date: new Date().toISOString().split('T')[0], | ||
startLocation: '', | ||
mileageStart: 0, | ||
project: '', | ||
car: '', | ||
passenger: '', | ||
description: '', | ||
endLocation: '', | ||
mileageEnd: 0, | ||
}, | ||
validateOnChange: false, | ||
validationSchema: validationSchema, | ||
onSubmit: (values) => { | ||
alert(JSON.stringify(values, null, 2)); | ||
}, | ||
}); | ||
|
||
useEffect(() => { | ||
const { mileageStart, mileageEnd } = formik.values; | ||
const mileage = mileageEnd - mileageStart; | ||
|
||
if (mileage !== traveled && mileage >= 0) { | ||
setTraveled(mileage); | ||
} | ||
}, [formik.values, traveled]); | ||
|
||
// values to generate MenuItems in select fields. Will be converted to redux slice. | ||
const selectItems = { | ||
project: ['TestProject1', 'TestProject2', 'TestProject3'], | ||
car: ['Audi', 'Opel', 'Lamborghini'], | ||
passenger: ['Passenger1', 'Passenger2', 'Passenger3'], | ||
}; | ||
|
||
const selectItemsNames = Object.keys(selectItems); | ||
|
||
// generate fieldList array dynamically | ||
const fieldList = Object.keys(formik.values).map((label) => { | ||
let type = 'text'; | ||
|
||
// set type based on label | ||
if (label.includes('mileage')) { | ||
type = 'number'; | ||
} else if (label === 'date') { | ||
type = 'date'; | ||
} | ||
|
||
const isSelect = selectItemsNames.includes(label); | ||
|
||
const result = { | ||
isTextField: !isSelect, | ||
translatedLabel: translatedFieldsLabels[label], | ||
labelName: label, | ||
type, | ||
errorText: formik.errors[label], | ||
}; | ||
|
||
if (isSelect) { | ||
result.items = selectItems[label]; | ||
} | ||
|
||
return result; | ||
}); | ||
|
||
const classes = useStyles(); | ||
|
||
return ( | ||
<Page title="Drive" className={classes.root}> | ||
<Container className={classes.container} maxWidth="md"> | ||
{Object.keys(formik.errors).length > 0 ? ( | ||
<Box className={classes.errorContainer}> | ||
<Typography | ||
variant="h4" | ||
component="h4" | ||
className={classes.errorTitle} | ||
> | ||
{errorTitle} | ||
</Typography> | ||
<ul> | ||
{Object.values(formik.errors).map((errorText) => ( | ||
<li key={errorText}>{errorText}</li> | ||
))} | ||
</ul> | ||
</Box> | ||
) : null} | ||
<form className={classes.formContainer} onSubmit={formik.handleSubmit}> | ||
<Typography variant="h2" component="h2" className={classes.title}> | ||
{title} | ||
</Typography> | ||
<Box display="flex" flexDirection="column"> | ||
{fieldList.map((field) => { | ||
if (!field.isTextField) { | ||
const { translatedLabel, labelName, items, errorText } = field; | ||
return ( | ||
<WhiteBox key={`${labelName}-select-container`}> | ||
<FormControl variant="outlined" fullWidth> | ||
<InputLabel id={`drive-${labelName}-label`}> | ||
{translatedLabel} | ||
</InputLabel> | ||
<Select | ||
id={`drive-${labelName}`} | ||
name={labelName} | ||
labelId={`drive-${labelName}-label`} | ||
label={translatedLabel} | ||
value={formik.values[labelName]} | ||
onChange={formik.handleChange} | ||
error={!!errorText} | ||
> | ||
{items.map((item) => ( | ||
<MenuItem key={item} value={item}> | ||
{item} | ||
</MenuItem> | ||
))} | ||
</Select> | ||
</FormControl> | ||
</WhiteBox> | ||
); | ||
} else { | ||
const { translatedLabel, labelName, type, errorText } = field; | ||
return ( | ||
<WhiteBox key={`${labelName}-container`}> | ||
<TextField | ||
id={`drive-${labelName}`} | ||
name={labelName} | ||
variant="outlined" | ||
fullWidth | ||
label={translatedLabel} | ||
type={type} | ||
value={formik.values[labelName]} | ||
onChange={formik.handleChange} | ||
error={!!errorText} | ||
/> | ||
</WhiteBox> | ||
); | ||
} | ||
})} | ||
</Box> | ||
<p> | ||
{traveled} km {traveledT} | ||
</p> | ||
<ButtonsContainer> | ||
<Button type="submit" variant="contained" color="primary"> | ||
{submit} | ||
</Button> | ||
<Button variant="contained" onClick={formik.resetForm}> | ||
{reset} | ||
</Button> | ||
</ButtonsContainer> | ||
</form> | ||
</Container> | ||
</Page> | ||
); | ||
}; | ||
|
||
export default DriveView; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { makeStyles, styled } from '@material-ui/styles'; | ||
import { Box } from '@material-ui/core'; | ||
|
||
export const useStyles = makeStyles(({ palette }) => ({ | ||
root: { | ||
flexGrow: 1, | ||
display: 'flex', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
minHeight: '100%', | ||
}, | ||
container: { | ||
display: 'flex', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
flexDirection: 'column', | ||
background: palette.background.grayLight, | ||
padding: '4rem 2rem', | ||
margin: '0.5rem', | ||
borderRadius: '0.3rem', | ||
}, | ||
formContainer: { | ||
minWidth: '60%', | ||
}, | ||
title: { | ||
fontSize: '2rem', | ||
fontWeight: 'normal', | ||
marginBottom: '2rem', | ||
}, | ||
errorContainer: { | ||
minWidth: '60%', | ||
padding: '.75rem 1.25rem', | ||
marginBottom: '1rem', | ||
fontSize: '1rem', | ||
color: palette.errorMessage.fg, | ||
backgroundColor: palette.errorMessage.bg, | ||
border: `1px solid ${palette.errorMessage.border}`, | ||
borderRadius: '.25rem', | ||
}, | ||
errorTitle: { | ||
fontSize: '1.125rem', | ||
fontWeight: 'bold', | ||
}, | ||
})); | ||
|
||
export const WhiteBox = styled(Box)({ | ||
backgroundColor: 'white', | ||
marginBottom: '1.5rem', | ||
'&:last-of-type': { | ||
marginBottom: 'unset', | ||
}, | ||
}); | ||
|
||
export const ButtonsContainer = styled(Box)({ | ||
display: 'flex', | ||
justifyContent: 'space-between', | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍