all repos — caroster @ a9547860ccc77ad9735f07bda93f9234d41251f1

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

frontend/containers/CarosterPlusSettings/index.tsx (view raw)

  1import {useReducer, useState} from 'react';
  2import Box from '@mui/material/Box';
  3import Button from '@mui/material/Button';
  4import Card from '@mui/material/Card';
  5import Chip from '@mui/material/Chip';
  6import Divider from '@mui/material/Divider';
  7import List from '@mui/material/List';
  8import ListItem from '@mui/material/ListItem';
  9import ListItemIcon from '@mui/material//ListItemIcon';
 10import ListItemText from '@mui/material/ListItemText';
 11import AddIcon from '@mui/icons-material/Add';
 12import Typography from '@mui/material/Typography';
 13import TextField from '@mui/material/TextField';
 14import IconButton from '@mui/material/IconButton';
 15import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined';
 16import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
 17import {useTranslation} from 'react-i18next';
 18import usePermissions from '../../hooks/usePermissions';
 19import useToastStore from '../../stores/useToastStore';
 20import FormDialog from '../FormDialog';
 21import {validateEmail} from '../../lib/validation';
 22import {
 23  Event as EventType,
 24  useAddEventAdminMutation,
 25  useDeleteEventAdminMutation,
 26} from '../../generated/graphql';
 27import Tooltip from '@mui/material/Tooltip';
 28
 29interface Props {
 30  event: EventType & {id: string};
 31}
 32
 33const CarosterPlusSettings = ({event}: Props) => {
 34  const {t} = useTranslation();
 35  const {
 36    userPermissions: {canEditEventOptions},
 37  } = usePermissions();
 38
 39  const {addToast} = useToastStore();
 40
 41  const [addAdminMutation] = useAddEventAdminMutation();
 42  const [deleteAdminMutation] = useDeleteEventAdminMutation();
 43  const [addAdminDialogOpen, toggleAddAdminDialog] = useReducer(i => !i, false);
 44  const [adminEmail, setAdminEmail] = useState('');
 45  const isEmailValid = validateEmail(adminEmail);
 46  const emailError = adminEmail !== '' && !isEmailValid;
 47
 48  const addAdmin = async () => {
 49    try {
 50      await addAdminMutation({
 51        variables: {
 52          eventId: event.id,
 53          email: adminEmail,
 54        },
 55      });
 56      addToast(t('options.plus.adminAdded'));
 57      toggleAddAdminDialog();
 58      setAdminEmail('');
 59    } catch (e) {
 60      console.error(e);
 61      addToast(t('options.plus.addAdminError'));
 62    }
 63  };
 64
 65  const deleteAdmin = async ({email}) => {
 66    try {
 67      await deleteAdminMutation({
 68        variables: {
 69          eventId: event.id,
 70          email,
 71        },
 72      });
 73      addToast(t('options.plus.adminDeleted'));
 74      toggleAddAdminDialog();
 75    } catch (e) {
 76      console.error(e);
 77      addToast(t('options.plus.deleteAdminError'));
 78    }
 79  };
 80
 81  const canEdit = canEditEventOptions();
 82
 83  return (
 84    <Card
 85      sx={{
 86        position: 'relative',
 87        maxWidth: '100%',
 88        width: '480px',
 89        pb: 3,
 90      }}
 91    >
 92      <Box
 93        display="flex"
 94        justifyContent="space-between"
 95        width="100%"
 96        p={2}
 97        py={1}
 98      >
 99        <Typography variant="h4" pt={1}>
100          {t('options.plus.title')}
101        </Typography>
102      </Box>
103      <Divider />
104      <Box p={2} display="flex" justifyContent="space-between" width="100%">
105        <Typography pt={1} variant="body2" color="GrayText">
106          {t('options.plus.admins')}
107        </Typography>
108        {canEdit ? (
109          <Button
110            variant="text"
111            endIcon={<AddIcon />}
112            onClick={toggleAddAdminDialog}
113          >
114            {t('generic.add')}
115          </Button>
116        ) : (
117          <Tooltip title={t('options.plus.notRightForAddAdmin')}>
118            <div>
119              <Button variant="text" disabled endIcon={<AddIcon />}>
120                {t('generic.add')}
121              </Button>
122            </div>
123          </Tooltip>
124        )}
125      </Box>
126      <List disablePadding>
127        <ListItem
128          secondaryAction={
129            <Chip label={t('options.plus.creator')} size="medium" />
130          }
131        >
132          <ListItemIcon>
133            <AccountCircleOutlinedIcon />
134          </ListItemIcon>
135          <ListItemText primary={event.email} />
136        </ListItem>
137        {event.administrators?.map(email => (
138          <ListItem
139            secondaryAction={
140              canEditEventOptions() && (
141                <IconButton size="medium" onClick={() => deleteAdmin({email})}>
142                  <DeleteOutlineIcon />
143                </IconButton>
144              )
145            }
146          >
147            <ListItemIcon>
148              <AccountCircleOutlinedIcon />
149            </ListItemIcon>
150            <ListItemText primary={email} />
151          </ListItem>
152        ))}
153      </List>
154      <FormDialog
155        title={t('options.plus.addAdmin')}
156        open={addAdminDialogOpen}
157        cancel={toggleAddAdminDialog}
158        onSubmit={addAdmin}
159        disabled={!isEmailValid}
160      >
161        <TextField
162          fullWidth
163          error={emailError}
164          label={t('options.plus.addAdmin.email')}
165          value={adminEmail}
166          onChange={e => setAdminEmail(e.target.value)}
167          helperText={emailError && t('options.plus.addAdmin.emailHelper')}
168          variant="standard"
169        />
170      </FormDialog>
171    </Card>
172  );
173};
174
175export default CarosterPlusSettings;