all repos — caroster @ 11ead31f4aee86f2a841b8775231bc52abb9df0e

[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    } catch (e) {
 75      console.error(e);
 76      addToast(t('options.plus.deleteAdminError'));
 77    }
 78  };
 79
 80  const canEdit = canEditEventOptions();
 81
 82  return (
 83    <Card
 84      sx={{
 85        position: 'relative',
 86        maxWidth: '100%',
 87        width: '480px',
 88        pb: 3,
 89      }}
 90    >
 91      <Box
 92        display="flex"
 93        justifyContent="space-between"
 94        width="100%"
 95        p={2}
 96        py={1}
 97      >
 98        <Typography variant="h4" pt={1}>
 99          {t('options.plus.title')}
100        </Typography>
101      </Box>
102      <Divider />
103      <Box p={2} display="flex" justifyContent="space-between" width="100%">
104        <Typography pt={1} variant="body2" color="GrayText">
105          {t('options.plus.admins')}
106        </Typography>
107        {canEdit ? (
108          <Button
109            variant="text"
110            endIcon={<AddIcon />}
111            onClick={toggleAddAdminDialog}
112          >
113            {t('generic.add')}
114          </Button>
115        ) : (
116          <Tooltip title={t('options.plus.notRightForAddAdmin')}>
117            <div>
118              <Button variant="text" disabled endIcon={<AddIcon />}>
119                {t('generic.add')}
120              </Button>
121            </div>
122          </Tooltip>
123        )}
124      </Box>
125      <List disablePadding>
126        <ListItem
127          secondaryAction={
128            <Chip label={t('options.plus.creator')} size="medium" />
129          }
130        >
131          <ListItemIcon>
132            <AccountCircleOutlinedIcon />
133          </ListItemIcon>
134          <ListItemText primary={event.email} />
135        </ListItem>
136        {event.administrators?.map(email => (
137          <ListItem
138            secondaryAction={
139              canEditEventOptions() && (
140                <IconButton size="medium" onClick={() => deleteAdmin({email})}>
141                  <DeleteOutlineIcon />
142                </IconButton>
143              )
144            }
145          >
146            <ListItemIcon>
147              <AccountCircleOutlinedIcon />
148            </ListItemIcon>
149            <ListItemText primary={email} />
150          </ListItem>
151        ))}
152      </List>
153      <FormDialog
154        title={t('options.plus.addAdmin')}
155        open={addAdminDialogOpen}
156        cancel={toggleAddAdminDialog}
157        onSubmit={addAdmin}
158        disabled={!isEmailValid}
159      >
160        <TextField
161          fullWidth
162          error={emailError}
163          label={t('options.plus.addAdmin.email')}
164          value={adminEmail}
165          onChange={e => setAdminEmail(e.target.value)}
166          helperText={emailError && t('options.plus.addAdmin.emailHelper')}
167          variant="standard"
168        />
169      </FormDialog>
170    </Card>
171  );
172};
173
174export default CarosterPlusSettings;