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;