all repos — caroster @ 1c9c57fd6ca54fe787c0a5418c9e7e1132362d0b

[Octree] Group carpool to your event https://caroster.io

disable waiting list edit button if empty, scrollable event details, address google map link, fix columns minimum height
Karian Før karian@subtext.studio
Mon, 20 Jul 2020 15:53:46 +0000
commit

1c9c57fd6ca54fe787c0a5418c9e7e1132362d0b

parent

d580513542f88cc9579b8af512dd00c3a630b173

M app/.eslintrcapp/.eslintrc

@@ -38,7 +38,7 @@ "complexity": ["warn", 16],

"max-len": ["warn", 110], "arrow-parens": "off", "prefer-destructuring": "error", - "indent": ["error", 2], + "indent": ["error", 2, {"ignoredNodes": ["ConditionalExpression"]}], "operator-linebreak": "off", "curly": "off", "no-extra-boolean-cast": "off",
D app/src/components/TextField/index.js

@@ -1,35 +0,0 @@

-import React from 'react'; -import TextFieldMUI from '@material-ui/core/TextField'; -import {makeStyles} from '@material-ui/core/styles'; - -const TextField = ({className, light, ...props}) => { - const classes = useStyles(); - return ( - <TextFieldMUI - className={`${classes.input} ${className} ${light ? 'light' : ''}`} - fullWidth - margin="dense" - {...props} - /> - ); -}; - -const useStyles = makeStyles(theme => ({ - input: { - '&.light .MuiFormLabel-root': { - color: 'white', - }, - '&.light .MuiInputBase-input': {color: 'white'}, - '&.light .MuiInput-underline::before': { - borderColor: 'white', - }, - '&.light .MuiInput-underline:hover:not(.Mui-disabled)::before': { - borderColor: 'white', - }, - '&.light .MuiInput-underline::after': { - transform: 'scaleX(0)', - }, - }, -})); - -export default TextField;
M app/src/containers/Car/HeaderEditing.jsapp/src/containers/Car/HeaderEditing.js

@@ -100,7 +100,7 @@ <IconButton

size="small" color="primary" type="submit" - className={classes.editBtn} + className={classes.edit} > <Icon>done</Icon> </IconButton>

@@ -108,7 +108,7 @@ <DateTimePicker

label={t('car.creation.date')} value={date} onChange={setDate} - className={classes.textField} + className={classes.picker} fullWidth format="LLLL" disablePast

@@ -118,7 +118,6 @@ name="date"

cancelLabel={t('generic.cancel')} /> <TextField - className={classes.textField} label={t('car.creation.name')} fullWidth autoFocus

@@ -129,7 +128,6 @@ id="EditCarName"

name="name" /> <TextField - className={classes.textField} label={t('car.creation.phone')} fullWidth autoFocus

@@ -140,7 +138,6 @@ id="EditCarPhone"

name="phone" /> <TextField - className={classes.textField} label={t('car.creation.meeting')} fullWidth margin="dense"

@@ -152,7 +149,6 @@ id="EditCarMeeting"

name="meeting" /> <TextField - className={classes.textField} label={t('car.creation.notes')} fullWidth margin="dense"

@@ -211,8 +207,10 @@ );

}; const useStyles = makeStyles(theme => ({ - header: {padding: theme.spacing(2)}, - editBtn: { + header: { + padding: theme.spacing(2), + }, + edit: { position: 'absolute', top: 0, right: 0,

@@ -233,6 +231,9 @@ margin: theme.spacing(2, 0),

'& > *:first-child': { marginBottom: theme.spacing(2), }, + }, + picker: { + marginBottom: theme.spacing(2), }, }));
M app/src/containers/CarColumns/index.jsapp/src/containers/CarColumns/index.js

@@ -95,12 +95,12 @@ overflow: 'visible',

}, }, slide: { - height: `calc(100vh - ${theme.mixins.toolbar.minHeight}px - ${theme.spacing( - 2 - )})`, + minHeight: `calc(100vh - ${ + theme.mixins.toolbar.minHeight + theme.spacing(14) + }px)`, outline: 'none', padding: theme.spacing(1), - marginBottom: theme.spacing(10), + marginBottom: theme.spacing(12), }, }));
M app/src/containers/CreateEvent/Step1.jsapp/src/containers/CreateEvent/Step1.js

@@ -47,7 +47,6 @@

return ( <form onSubmit={onNext}> <TextField - className={classes.textField} label={t('event.creation.event_name')} fullWidth autoFocus

@@ -59,7 +58,6 @@ name="name"

/> {!connected && ( <TextField - className={classes.textField} label={t('event.creation.creator_email')} fullWidth margin="dense"

@@ -99,7 +97,6 @@ );

}; const useStyles = makeStyles(theme => ({ - textField: {}, button: { marginTop: theme.spacing(2), },
M app/src/containers/CreateEvent/Step2.jsapp/src/containers/CreateEvent/Step2.js

@@ -34,7 +34,6 @@ <DatePicker

label={t('event.creation.date')} value={date} onChange={setDate} - className={classes.textField} fullWidth format="DD.MM.YYYY" disablePast

@@ -43,7 +42,6 @@ name="date"

cancelLabel={t('generic.cancel')} /> <TextField - className={classes.textField} label={t('event.creation.address')} fullWidth margin="dense"

@@ -69,7 +67,6 @@ );

}; const useStyles = makeStyles(theme => ({ - textField: {}, button: { marginTop: theme.spacing(2), },
M app/src/containers/EventDetails/index.jsapp/src/containers/EventDetails/index.js

@@ -1,13 +1,23 @@

import React from 'react'; import Typography from '@material-ui/core/Typography'; -import TextField from '../../components/TextField'; -import moment from 'moment'; -import {useEvent} from '../../contexts/Event'; -import {useTranslation} from 'react-i18next'; -import {makeStyles} from '@material-ui/core'; import Button from '@material-ui/core/Button'; +import Link from '@material-ui/core/Link'; import {DatePicker} from '@material-ui/pickers'; +import TextField from '@material-ui/core/TextField'; +import {makeStyles, createMuiTheme, ThemeProvider} from '@material-ui/core'; +import {useTranslation} from 'react-i18next'; +import moment from 'moment'; +import {useEvent} from '../../contexts/Event'; import Map from '../../components/Map'; +import {caroster} from '../../theme'; + +const theme = createMuiTheme({ + ...caroster, + palette: { + ...caroster.palette, + type: 'dark', + }, +}); const EventDetails = ({toggleDetails}) => { const {t} = useTranslation();

@@ -16,95 +26,103 @@ const {event, isEditing, setEditingEvent, editingEvent} = useEvent();

if (!event) return null; const idPrefix = isEditing ? 'EditEvent' : 'Event'; + return ( - <div> - <div className={classes.section}> - {isEditing && ( - <div className={classes.section}> - <Typography variant="h6">{t('event.fields.name')}</Typography> + <ThemeProvider theme={theme}> + <div className={classes.container}> + <div className={classes.section}> + {isEditing && ( + <div className={classes.section}> + <Typography variant="h6">{t('event.fields.name')}</Typography> + <TextField + defaultValue={event.name} + value={editingEvent.name} + onChange={e => + setEditingEvent({...editingEvent, name: e.target.value}) + } + fullWidth + id="EditEventName" + name="name" + /> + </div> + )} + <Typography variant="h6">{t('event.fields.starts_on')}</Typography> + {isEditing ? ( + <DatePicker + value={ + editingEvent.date + ? moment(editingEvent.date) + : event.date + ? moment(event.date) + : null + } + onChange={date => + setEditingEvent({...editingEvent, date: date?.toISOString()}) + } + fullWidth + format="DD.MM.YYYY" + disablePast + id={`${idPrefix}Date`} + name="date" + TextFieldComponent={p => <TextField {...p} />} + cancelLabel={t('generic.cancel')} + /> + ) : ( + <Typography variant="body1" id={`${idPrefix}Date`}> + {moment(event.date).format('DD.MM.YYYY') || + t('event.fields.empty')} + </Typography> + )} + </div> + <div className={classes.section}> + <Typography variant="h6">{t('event.fields.address')}</Typography> + {isEditing ? ( <TextField - light - value={editingEvent.name} + defaultValue={event.address} + value={editingEvent.address} onChange={e => - setEditingEvent({...editingEvent, name: e.target.value}) + setEditingEvent({...editingEvent, address: e.target.value}) } - id="EditEventName" - name="name" + fullWidth + multiline + rows={4} + id={`${idPrefix}Address`} + name="address" /> - </div> - )} - <Typography variant="h6">{t('event.fields.starts_on')}</Typography> - {isEditing ? ( - <DatePicker - value={editingEvent.date ? moment(editingEvent.date) : null} - onChange={date => - setEditingEvent({...editingEvent, date: date?.toISOString()}) - } - className={classes.textField} - fullWidth - format="DD.MM.YYYY" - disablePast - id={`${idPrefix}Date`} - name="date" - TextFieldComponent={p => <TextField light {...p} />} - cancelLabel={t('generic.cancel')} - /> - ) : ( - <Typography variant="body1" id={`${idPrefix}Date`}> - {event.date || t('event.fields.empty')} - </Typography> - )} - </div> - <div className={classes.section}> - <Typography variant="h6"> - {t('event.fields.address')} - {!isEditing && event.address && ( - <Button - href={`https://www.google.ch/maps/place/${encodeURI( - 'event.address' - )}`} - size="small" - color="primary" - className={classes.seeOnGMapButton} - id="SeeOnGoogleMap" - > - {t('event.actions.see_on_gmap')} - </Button> + ) : ( + <Typography variant="body1" id={`${idPrefix}Address`}> + {event.address ? ( + <Link + href={`https://maps.google.com/?q=${event.address}`} + onClick={e => e.preventDefault} + > + {event.address} + </Link> + ) : ( + t('event.fields.empty') + )} + </Typography> )} - </Typography> - {isEditing ? ( - <TextField - light - multiline - rows={4} - value={editingEvent.address} - onChange={e => - setEditingEvent({...editingEvent, address: e.target.value}) - } - id={`${idPrefix}Address`} - name="address" - /> - ) : ( - <Typography variant="body1" id={`${idPrefix}Address`}> - {event.address || t('event.fields.empty')} - </Typography> + </div> + <div className={classes.actions}> + <Button onClick={toggleDetails} variant="contained" id={`CarFindBtn`}> + {t('event.actions.find_car')} + </Button> + </div> + {event.position && ( + <div className={classes.map} id={`${idPrefix}AddressMap`}> + <Map position={event.position} /> + </div> )} </div> - <div className={classes.actions}> - <Button onClick={toggleDetails} variant="contained" id={`CarFindBtn`}> - {t('event.actions.find_car')} - </Button> - </div> - {event.position && ( - <div className={classes.map} id={`${idPrefix}AddressMap`}> - <Map position={event.position} /> - </div> - )} - </div> + </ThemeProvider> ); }; const useStyles = makeStyles(theme => ({ + container: { + marginBottom: theme.spacing(12), + }, section: { marginBottom: theme.spacing(2), },
M app/src/containers/NewCarDialog/index.jsapp/src/containers/NewCarDialog/index.js

@@ -88,13 +88,11 @@ <DialogTitle>{t('car.creation.title')}</DialogTitle>

<DialogContent> <DialogContentText> <TextField - className={classes.textField} label={t('car.creation.name')} - fullWidth - autoFocus - margin="dense" value={name} onChange={e => setName(e.target.value)} + fullWidth + autoFocus id="NewCarName" name="name" />

@@ -104,8 +102,8 @@ value={date}

onChange={setDate} className={classes.picker} fullWidth - format="LLLL" disablePast + format="LLLL" id="NewCarDateTime" name="date" />

@@ -120,36 +118,33 @@ marks={marks}

valueLabelDisplay="auto" /> <TextField - className={classes.textField} label={t('car.creation.meeting')} - fullWidth - margin="dense" value={meeting} onChange={e => setMeeting(e.target.value)} + fullWidth + margin="dense" id="NewCarMeeting" name="meeting" /> <TextField - className={classes.textField} label={t('car.creation.phone')} + value={phone} + onChange={e => setPhone(e.target.value)} fullWidth margin="dense" - value={phone} - onChange={e => setPhone(e.target.value)} id="NewCarPhone" name="phone" /> <TextField - className={classes.textField} label={t('car.creation.notes')} + value={details} + onChange={e => setDetails(e.target.value)} fullWidth margin="dense" inputProps={{maxLength: 250}} helperText={`${details.length}/250`} multiline rows={4} - value={details} - onChange={e => setDetails(e.target.value)} id="NewCarDetails" name="details" />

@@ -181,10 +176,8 @@ );

}; const useStyles = makeStyles(theme => ({ - textField: { - marginBottom: theme.spacing(2), - }, picker: { + marginTop: theme.spacing(3), marginBottom: theme.spacing(3), }, }));
M app/src/containers/PassengersList/Passenger.jsapp/src/containers/PassengersList/Passenger.js

@@ -3,10 +3,13 @@ import ListItemAvatar from '@material-ui/core/ListItemAvatar';

import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import Icon from '@material-ui/core/Icon'; +import {makeStyles} from '@material-ui/core/styles'; import {useTranslation} from 'react-i18next'; const Passenger = ({passenger, button}) => { const {t} = useTranslation(); + const classes = useStyles(); + return !!passenger ? ( <> <ListItemText primary={passenger} />

@@ -19,9 +22,20 @@ <ListItemIcon color="disabled">

<Icon>person</Icon> </ListItemIcon> </ListItemAvatar> - <ListItemText primary={t('car.passengers.empty')} /> + <ListItemText + classes={{ + root: classes.empty, + }} + primary={t('car.passengers.empty')} + /> </> ); }; + +const useStyles = makeStyles(theme => ({ + empty: { + color: theme.palette.text.secondary, + }, +})); export default Passenger;
M app/src/containers/WaitingList/index.jsapp/src/containers/WaitingList/index.js

@@ -116,6 +116,7 @@ <IconButton

size="small" color="primary" className={classes.editBtn} + disabled={!event.waiting_list || !event.waiting_list.length} onClick={toggleEditing} > {isEditing ? <Icon>check</Icon> : <Icon>edit</Icon>}
M app/src/index.jsapp/src/index.js

@@ -3,8 +3,8 @@ import ReactDOM from 'react-dom';

import 'fontsource-roboto'; import './i18n'; import 'moment/locale/fr-ch'; -import App from './App'; import * as serviceWorker from './serviceWorker'; +import App from './App'; ReactDOM.render( <React.StrictMode>
M app/src/pages/Event.jsapp/src/pages/Event.js

@@ -202,9 +202,11 @@ },

].filter(Boolean)} /> </Toolbar> - <Container className={classes.container} maxWidth="sm"> - <EventDetails toggleDetails={toggleDetails} /> - </Container> + {detailsOpen && ( + <Container className={classes.container} maxWidth="sm"> + <EventDetails toggleDetails={toggleDetails} /> + </Container> + )} </AppBar> <CarColumns toggleNewCar={toggleNewCar} /> <EventFab toggleNewCar={toggleNewCar} open={openNewCar} />

@@ -225,6 +227,7 @@ },

appbar: ({detailsOpen}) => ({ overflow: 'hidden', height: detailsOpen ? '100vh' : theme.mixins.toolbar.minHeight, + overflowY: detailsOpen ? 'scroll' : 'hidden', transition: 'height 0.3s ease', zIndex: theme.zIndex.appBar, position: 'fixed',
M app/src/theme.jsapp/src/theme.js

@@ -1,6 +1,6 @@

import {createMuiTheme} from '@material-ui/core/styles'; -export default createMuiTheme({ +export const caroster = { palette: { primary: { main: '#009688',

@@ -24,5 +24,14 @@ backgroundColor: '#242424',

color: 'white', }, }, + MuiInput: { + underline: { + '&&&&:hover:before': { + borderBottomColor: '#009688', + }, + }, + }, }, -}); +}; + +export default createMuiTheme(caroster);