feat: redesign event modal with responsive dialog and improved layout
Implemented a new ResponsiveDialog component and redesigned EventModal with better UX for both normal and extended modes. New Features: - Created reusable ResponsiveDialog component (src/components/Dialog/) * Normal mode: 685px centered popup * Extended mode: fullscreen with 90px header preservation * Auto spacing via MUI Stack (16px normal, 24px extended) * Back arrow navigation in extended mode * No backdrop/shadow in extended mode for seamless integration * Configurable props for all dimensions and behaviors EventModal Improvements: - Replaced native checkbox with MUI Checkbox component - Migrated from Popover to ResponsiveDialog - Reorganized field layout => Comprehensive documentation in Dialog/README.md Note: RepeatEvent integration tests need additional refactoring (tracked separately)
This commit is contained in:
+302
-221
@@ -2,14 +2,11 @@ import { CalendarApi, DateSelectArg } from "@fullcalendar/core";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
CardActions,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
Checkbox,
|
||||
FormControl,
|
||||
FormControlLabel,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Popover,
|
||||
Select,
|
||||
SelectChangeEvent,
|
||||
TextField,
|
||||
@@ -18,7 +15,7 @@ import {
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||
import AttendeeSelector from "../../components/Attendees/AttendeeSearch";
|
||||
import { TIMEZONES } from "../../utils/timezone-data";
|
||||
import { ResponsiveDialog } from "../../components/Dialog";
|
||||
import { putEventAsync } from "../Calendars/CalendarSlice";
|
||||
import { Calendars } from "../Calendars/CalendarTypes";
|
||||
import { userAttendee } from "../User/userDataTypes";
|
||||
@@ -26,6 +23,58 @@ import { CalendarEvent, RepetitionObject } from "./EventsTypes";
|
||||
import { createSelector } from "@reduxjs/toolkit";
|
||||
import RepeatEvent from "../../components/Event/EventRepeat";
|
||||
|
||||
// Helper component for field with label
|
||||
const FieldWithLabel = React.memo(
|
||||
({
|
||||
label,
|
||||
isExpanded,
|
||||
children,
|
||||
}: {
|
||||
label: string;
|
||||
isExpanded: boolean;
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
if (!isExpanded) {
|
||||
// Normal mode: label on top
|
||||
return (
|
||||
<Box>
|
||||
<Typography
|
||||
component="label"
|
||||
sx={{
|
||||
display: "block",
|
||||
marginBottom: "4px",
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Typography>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
// Extended mode: label on left
|
||||
return (
|
||||
<Box display="flex" alignItems="center">
|
||||
<Typography
|
||||
component="label"
|
||||
sx={{
|
||||
minWidth: "115px",
|
||||
marginRight: "12px",
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Typography>
|
||||
<Box flexGrow={1}>{children}</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
FieldWithLabel.displayName = "FieldWithLabel";
|
||||
|
||||
function EventPopover({
|
||||
anchorEl,
|
||||
open,
|
||||
@@ -63,7 +112,6 @@ function EventPopover({
|
||||
const userPersonnalCalendars: Calendars[] = useAppSelector(
|
||||
selectPersonnalCalendars
|
||||
);
|
||||
const timezones = TIMEZONES.aliases;
|
||||
const [showMore, setShowMore] = useState(false);
|
||||
|
||||
const [title, setTitle] = useState(event?.title ?? "");
|
||||
@@ -90,9 +138,7 @@ function EventPopover({
|
||||
const [eventClass, setEventClass] = useState(event?.class ?? "PUBLIC");
|
||||
const [busy, setBusy] = useState(event?.transp ?? "OPAQUE");
|
||||
|
||||
const [timezone, setTimezone] = useState(
|
||||
Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
);
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedRange) {
|
||||
@@ -111,7 +157,9 @@ function EventPopover({
|
||||
}, [event, organizer?.cal_address]);
|
||||
|
||||
const handleClose = () => {
|
||||
onClose({}, "backdropClick"); // Reset
|
||||
onClose({}, "backdropClick");
|
||||
// Reset state
|
||||
setShowMore(false);
|
||||
setTitle("");
|
||||
setDescription("");
|
||||
setAttendees([]);
|
||||
@@ -126,7 +174,7 @@ function EventPopover({
|
||||
calId: userPersonnalCalendars[calendarid].id,
|
||||
title,
|
||||
URL: `/calendars/${userPersonnalCalendars[calendarid].id}/${newEventUID}.ics`,
|
||||
start: new Date(start),
|
||||
start: new Date(start).toISOString(),
|
||||
allday,
|
||||
uid: newEventUID,
|
||||
description,
|
||||
@@ -150,244 +198,277 @@ function EventPopover({
|
||||
alarm: { trigger: alarm, action: "EMAIL" },
|
||||
};
|
||||
if (end) {
|
||||
newEvent.end = new Date(end);
|
||||
newEvent.end = new Date(end).toISOString();
|
||||
}
|
||||
|
||||
if (attendees.length > 0) {
|
||||
newEvent.attendee = newEvent.attendee.concat(attendees);
|
||||
}
|
||||
|
||||
await dispatch(
|
||||
putEventAsync({
|
||||
cal: userPersonnalCalendars[calendarid],
|
||||
newEvent,
|
||||
})
|
||||
);
|
||||
// Close popup immediately
|
||||
onClose({}, "backdropClick");
|
||||
|
||||
// Reset
|
||||
// Reset state
|
||||
setShowMore(false);
|
||||
setTitle("");
|
||||
setDescription("");
|
||||
setAttendees([]);
|
||||
setLocation("");
|
||||
setCalendarid(0);
|
||||
|
||||
// Save to API in background
|
||||
dispatch(
|
||||
putEventAsync({
|
||||
cal: userPersonnalCalendars[calendarid],
|
||||
newEvent,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const dialogActions = (
|
||||
<Box display="flex" justifyContent="space-between" width="100%" px={2}>
|
||||
{!showMore && (
|
||||
<Button onClick={() => setShowMore(!showMore)}>Show More</Button>
|
||||
)}
|
||||
<Box display="flex" gap={1} ml={showMore ? "auto" : 0}>
|
||||
<Button variant="outlined" onClick={handleClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="contained" onClick={handleSave} disabled={!title}>
|
||||
Save
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
<ResponsiveDialog
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: "center",
|
||||
horizontal: "center",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "center",
|
||||
horizontal: "center",
|
||||
}}
|
||||
title={event?.uid ? "Duplicate Event" : "Create Event"}
|
||||
isExpanded={showMore}
|
||||
onExpandToggle={() => setShowMore(!showMore)}
|
||||
actions={dialogActions}
|
||||
>
|
||||
<Card>
|
||||
<CardHeader title={event?.uid ? "Duplicate Event" : "Create Event"} />
|
||||
<CardContent
|
||||
style={{ maxHeight: "85vh", maxWidth: "40vw", overflow: "auto" }}
|
||||
>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Title"
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
/>
|
||||
<FormControl fullWidth margin="dense" size="small">
|
||||
<FieldWithLabel label="Title" isExpanded={showMore}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "Title" : ""}
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
/>
|
||||
</FieldWithLabel>
|
||||
<FieldWithLabel label="Description" isExpanded={showMore}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "Description" : ""}
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
multiline
|
||||
rows={2}
|
||||
/>
|
||||
</FieldWithLabel>
|
||||
<FieldWithLabel label="Calendar" isExpanded={showMore}>
|
||||
<FormControl fullWidth margin="dense" size="small">
|
||||
{!showMore && (
|
||||
<InputLabel id="calendar-select-label">Calendar</InputLabel>
|
||||
<Select
|
||||
labelId="calendar-select-label"
|
||||
value={calendarid.toString()}
|
||||
label="Calendar"
|
||||
onChange={(e: SelectChangeEvent) =>
|
||||
setCalendarid(Number(e.target.value))
|
||||
}
|
||||
>
|
||||
{Object.keys(userPersonnalCalendars).map((calendar, index) => (
|
||||
<MenuItem key={index} value={index}>
|
||||
{userPersonnalCalendars[index].name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Start"
|
||||
type={allday ? "date" : "datetime-local"}
|
||||
value={allday ? start.split("T")[0] : start}
|
||||
onChange={(e) => {
|
||||
const newStart = e.target.value;
|
||||
setStart(newStart);
|
||||
const newRange = {
|
||||
...selectedRange,
|
||||
start: new Date(newStart),
|
||||
startStr: newStart,
|
||||
allDay: allday,
|
||||
};
|
||||
setSelectedRange(newRange);
|
||||
calendarRef.current?.select(newRange);
|
||||
}}
|
||||
size="small"
|
||||
margin="dense"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="End"
|
||||
type={allday ? "date" : "datetime-local"}
|
||||
value={allday ? end.split("T")[0] : end}
|
||||
onChange={(e) => {
|
||||
const newEnd = e.target.value;
|
||||
setEnd(newEnd);
|
||||
const newRange = {
|
||||
...selectedRange,
|
||||
end: new Date(newEnd),
|
||||
endStr: newEnd,
|
||||
allDay: allday,
|
||||
};
|
||||
setSelectedRange(newRange);
|
||||
calendarRef.current?.select(newRange);
|
||||
}}
|
||||
size="small"
|
||||
margin="dense"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={allday}
|
||||
onChange={() => {
|
||||
const endDate = new Date(end);
|
||||
const startDate = new Date(start);
|
||||
setAllDay(!allday);
|
||||
if (endDate.getDate() === startDate.getDate()) {
|
||||
endDate.setDate(startDate.getDate() + 1);
|
||||
setEnd(formatLocalDateTime(endDate));
|
||||
}
|
||||
)}
|
||||
<Select
|
||||
labelId="calendar-select-label"
|
||||
value={calendarid.toString()}
|
||||
label={!showMore ? "Calendar" : ""}
|
||||
onChange={(e: SelectChangeEvent) =>
|
||||
setCalendarid(Number(e.target.value))
|
||||
}
|
||||
>
|
||||
{Object.keys(userPersonnalCalendars).map((calendar, index) => (
|
||||
<MenuItem key={index} value={index}>
|
||||
{userPersonnalCalendars[index].name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</FieldWithLabel>
|
||||
|
||||
<FieldWithLabel label="Date & Time" isExpanded={showMore}>
|
||||
<Box display="flex" gap={2}>
|
||||
<Box flexGrow={1}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
Start
|
||||
</Typography>
|
||||
)}
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "Start" : ""}
|
||||
type={allday ? "date" : "datetime-local"}
|
||||
value={allday ? start.split("T")[0] : start}
|
||||
onChange={(e) => {
|
||||
const newStart = e.target.value;
|
||||
setStart(newStart);
|
||||
const newRange = {
|
||||
...selectedRange,
|
||||
startStr: allday ? start.split("T")[0] : start,
|
||||
endStr: allday
|
||||
? endDate.toISOString().split("T")[0]
|
||||
: endDate.toISOString(),
|
||||
start: new Date(allday ? start.split("T")[0] : start),
|
||||
end: new Date(
|
||||
allday
|
||||
? endDate.toISOString().split("T")[0]
|
||||
: endDate.toISOString()
|
||||
),
|
||||
start: new Date(newStart),
|
||||
startStr: newStart,
|
||||
allDay: allday,
|
||||
};
|
||||
setSelectedRange(newRange);
|
||||
calendarRef.current?.select(newRange);
|
||||
}}
|
||||
size="small"
|
||||
margin="dense"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
All day
|
||||
</label>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Description"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
multiline
|
||||
rows={2}
|
||||
/>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Location"
|
||||
value={location}
|
||||
onChange={(e) => setLocation(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
/>
|
||||
<AttendeeSelector attendees={attendees} setAttendees={setAttendees} />
|
||||
{/* Extended options */}
|
||||
{showMore && (
|
||||
<>
|
||||
<RepeatEvent
|
||||
repetition={repetition}
|
||||
eventStart={selectedRange?.start ?? new Date()}
|
||||
setRepetition={setRepetition}
|
||||
/>
|
||||
<FormControl fullWidth margin="dense" size="small">
|
||||
<InputLabel id="alarm">Alarm</InputLabel>
|
||||
<Select
|
||||
labelId="alarm"
|
||||
value={alarm}
|
||||
onChange={(e: SelectChangeEvent) => setAlarm(e.target.value)}
|
||||
>
|
||||
<MenuItem value={""}>No Alarm</MenuItem>
|
||||
<MenuItem value={"-PT1M"}>1 minute</MenuItem>
|
||||
<MenuItem value={"-PT5M"}>2 minutes</MenuItem>
|
||||
<MenuItem value={"-PT10M"}>10 minutes</MenuItem>
|
||||
<MenuItem value={"-PT15M"}>15 minutes</MenuItem>
|
||||
<MenuItem value={"-PT30M"}>30 minutes</MenuItem>
|
||||
<MenuItem value={"-PT1H"}>1 hours</MenuItem>
|
||||
<MenuItem value={"-PT2H"}>2 hours</MenuItem>
|
||||
<MenuItem value={"-PT5H"}>5 hours</MenuItem>
|
||||
<MenuItem value={"-PT12H"}>12 hours</MenuItem>
|
||||
<MenuItem value={"-PT1D"}>1 day</MenuItem>
|
||||
<MenuItem value={"-PT2D"}>2 days</MenuItem>
|
||||
<MenuItem value={"-PT1W"}>1 week</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormControl fullWidth margin="dense" size="small">
|
||||
<InputLabel id="Visibility">Visibility</InputLabel>
|
||||
<Select
|
||||
labelId="Visibility"
|
||||
label="Visibility"
|
||||
value={eventClass}
|
||||
onChange={(e: SelectChangeEvent) =>
|
||||
setEventClass(e.target.value)
|
||||
}
|
||||
>
|
||||
<MenuItem value={"PUBLIC"}>Public</MenuItem>
|
||||
<MenuItem value={"CONFIDENTIAL"}>Show time only</MenuItem>
|
||||
<MenuItem value={"PRIVATE"}>Private</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormControl fullWidth margin="dense" size="small">
|
||||
<InputLabel id="busy">is Busy</InputLabel>
|
||||
<Select
|
||||
labelId="busy"
|
||||
value={busy}
|
||||
label="is busy"
|
||||
onChange={(e: SelectChangeEvent) => setBusy(e.target.value)}
|
||||
>
|
||||
<MenuItem value={"TRANSPARENT"}>Free</MenuItem>
|
||||
<MenuItem value={"OPAQUE"}>Busy </MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
|
||||
<CardActions>
|
||||
<Box mt={2} display="flex" justifyContent="flex-end" gap={1}>
|
||||
<Button variant="outlined" onClick={handleClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button size="small" onClick={() => setShowMore(!showMore)}>
|
||||
{showMore ? "Show Less" : "Show More"}
|
||||
</Button>
|
||||
<Button variant="contained" onClick={handleSave} disabled={!title}>
|
||||
Save
|
||||
</Button>
|
||||
</Box>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Popover>
|
||||
<Box flexGrow={1}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
End
|
||||
</Typography>
|
||||
)}
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "End" : ""}
|
||||
type={allday ? "date" : "datetime-local"}
|
||||
value={allday ? end.split("T")[0] : end}
|
||||
onChange={(e) => {
|
||||
const newEnd = e.target.value;
|
||||
setEnd(newEnd);
|
||||
const newRange = {
|
||||
...selectedRange,
|
||||
end: new Date(newEnd),
|
||||
endStr: newEnd,
|
||||
allDay: allday,
|
||||
};
|
||||
setSelectedRange(newRange);
|
||||
calendarRef.current?.select(newRange);
|
||||
}}
|
||||
size="small"
|
||||
margin="dense"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</FieldWithLabel>
|
||||
<FieldWithLabel label=" " isExpanded={showMore}>
|
||||
<Box>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={allday}
|
||||
onChange={() => {
|
||||
const endDate = new Date(end);
|
||||
const startDate = new Date(start);
|
||||
setAllDay(!allday);
|
||||
if (endDate.getDate() === startDate.getDate()) {
|
||||
endDate.setDate(startDate.getDate() + 1);
|
||||
setEnd(formatLocalDateTime(endDate));
|
||||
}
|
||||
|
||||
const newRange = {
|
||||
...selectedRange,
|
||||
startStr: allday ? start.split("T")[0] : start,
|
||||
endStr: allday
|
||||
? endDate.toISOString().split("T")[0]
|
||||
: endDate.toISOString(),
|
||||
start: new Date(allday ? start.split("T")[0] : start),
|
||||
end: new Date(
|
||||
allday
|
||||
? endDate.toISOString().split("T")[0]
|
||||
: endDate.toISOString()
|
||||
),
|
||||
allDay: allday,
|
||||
};
|
||||
setSelectedRange(newRange);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label="All day"
|
||||
sx={{ padding: "0 8px 0 0" }}
|
||||
/>
|
||||
</Box>
|
||||
</FieldWithLabel>
|
||||
<FieldWithLabel label="Attendees" isExpanded={showMore}>
|
||||
<AttendeeSelector attendees={attendees} setAttendees={setAttendees} />
|
||||
</FieldWithLabel>
|
||||
<FieldWithLabel label="Location" isExpanded={showMore}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "Location" : ""}
|
||||
value={location}
|
||||
onChange={(e) => setLocation(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
/>
|
||||
</FieldWithLabel>
|
||||
{/* Extended options */}
|
||||
{showMore && (
|
||||
<>
|
||||
<FieldWithLabel label="Repeat" isExpanded={showMore}>
|
||||
<RepeatEvent
|
||||
repetition={repetition}
|
||||
eventStart={selectedRange?.start ?? new Date()}
|
||||
setRepetition={setRepetition}
|
||||
/>
|
||||
</FieldWithLabel>
|
||||
<FieldWithLabel label="Alarm" isExpanded={showMore}>
|
||||
<FormControl fullWidth margin="dense" size="small">
|
||||
<Select
|
||||
labelId="alarm"
|
||||
value={alarm}
|
||||
onChange={(e: SelectChangeEvent) => setAlarm(e.target.value)}
|
||||
>
|
||||
<MenuItem value={""}>No Alarm</MenuItem>
|
||||
<MenuItem value={"-PT1M"}>1 minute</MenuItem>
|
||||
<MenuItem value={"-PT5M"}>2 minutes</MenuItem>
|
||||
<MenuItem value={"-PT10M"}>10 minutes</MenuItem>
|
||||
<MenuItem value={"-PT15M"}>15 minutes</MenuItem>
|
||||
<MenuItem value={"-PT30M"}>30 minutes</MenuItem>
|
||||
<MenuItem value={"-PT1H"}>1 hours</MenuItem>
|
||||
<MenuItem value={"-PT2H"}>2 hours</MenuItem>
|
||||
<MenuItem value={"-PT5H"}>5 hours</MenuItem>
|
||||
<MenuItem value={"-PT12H"}>12 hours</MenuItem>
|
||||
<MenuItem value={"-PT1D"}>1 day</MenuItem>
|
||||
<MenuItem value={"-PT2D"}>2 days</MenuItem>
|
||||
<MenuItem value={"-PT1W"}>1 week</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</FieldWithLabel>
|
||||
|
||||
<FieldWithLabel label="Visibility" isExpanded={showMore}>
|
||||
<FormControl fullWidth margin="dense" size="small">
|
||||
<Select
|
||||
labelId="Visibility"
|
||||
value={eventClass}
|
||||
onChange={(e: SelectChangeEvent) =>
|
||||
setEventClass(e.target.value)
|
||||
}
|
||||
>
|
||||
<MenuItem value={"PUBLIC"}>Public</MenuItem>
|
||||
<MenuItem value={"CONFIDENTIAL"}>Show time only</MenuItem>
|
||||
<MenuItem value={"PRIVATE"}>Private</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</FieldWithLabel>
|
||||
<FieldWithLabel label="Show as" isExpanded={showMore}>
|
||||
<FormControl fullWidth margin="dense" size="small">
|
||||
<Select
|
||||
labelId="busy"
|
||||
value={busy}
|
||||
onChange={(e: SelectChangeEvent) => setBusy(e.target.value)}
|
||||
>
|
||||
<MenuItem value={"TRANSPARENT"}>Free</MenuItem>
|
||||
<MenuItem value={"OPAQUE"}>Busy </MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</FieldWithLabel>
|
||||
</>
|
||||
)}
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user