all repos — caroster @ 65bcb7d208677b65df7ba31f656ee6ee0cfb1d1d

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