all repos — caroster @ f5c854ad35aa58a77481d22c3554680f8828f45f

[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 'next-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, index) => (
137          <ListItem
138            key={index}
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;