feat: Update Event Preview Modal UI with custom MUI theme (#240)

- Add custom MUI theme
- Update ResponsiveDialog with actionsBorderTop prop for modal footer border
- Redesign EventDisplayPreview modal with improved typography and spacing
- Replace ButtonGroup with individual RSVP buttons (Accept/Maybe/Decline)
- Add pill-shaped buttons for RSVP actions
- Ensure backward compatibility with existing modals
This commit is contained in:
lenhanphung
2025-10-27 12:23:42 +07:00
committed by GitHub
parent 51c9d68be2
commit 4774e78543
12 changed files with 358 additions and 118 deletions
+4 -2
View File
@@ -66,17 +66,19 @@ export function TimezoneSelector({ value, onChange }: TimezoneSelectProps) {
}}
slotProps={{
paper: {
sx: { width: 280, maxHeight: 400, overflow: "auto", p: 1 },
sx: { width: 280, maxHeight: 400, overflow: "hidden", p: 0 },
},
}}
>
<TimezoneAutocomplete
size="medium"
value={effectiveTimezone}
onChange={onChange}
zones={timezoneList.zones}
getTimezoneOffset={getTimezoneOffset}
autoFocus={true}
inputFontSize="10px"
showIcon={true}
inputFontSize="14px"
inputPadding="2px 4px"
onClose={handleClose}
disableClearable={true}
+24 -1
View File
@@ -78,6 +78,14 @@ interface ResponsiveDialogProps
dividers?: boolean;
/** Whether to show header action icons (expand/close) in normal mode (default: true) */
showHeaderActions?: boolean;
/** Whether to add border-top to DialogActions */
actionsBorderTop?: boolean;
/** Justify content alignment for DialogActions */
actionsJustifyContent?:
| "flex-start"
| "center"
| "flex-end"
| "space-between";
}
function ResponsiveDialog({
@@ -99,6 +107,8 @@ function ResponsiveDialog({
dialogTitleProps,
dividers = false,
showHeaderActions = true,
actionsBorderTop = false,
actionsJustifyContent = "flex-end",
sx,
...otherDialogProps
}: ResponsiveDialogProps) {
@@ -199,7 +209,20 @@ function ResponsiveDialog({
<Stack spacing={currentSpacing}>{children}</Stack>
)}
</DialogContent>
{actions && <DialogActions>{actions}</DialogActions>}
{actions && (
<DialogActions
sx={{
borderTop: actionsBorderTop
? (theme) => `1px solid ${theme.palette.divider}`
: undefined,
justifyContent: actionsJustifyContent,
paddingTop: "18px",
paddingBottom: "18px",
}}
>
{actions}
</DialogActions>
)}
</Dialog>
);
}
+10 -39
View File
@@ -1,51 +1,22 @@
import { IconButton, MenuItem } from "@mui/material";
import { MenuItem } from "@mui/material";
import { CalendarEvent } from "../../features/Events/EventsTypes";
import AddToPhotosIcon from "@mui/icons-material/AddToPhotos";
import { useRef, useState } from "react";
import EventPopover from "../../features/Events/EventModal";
import { CalendarApi, DateSelectArg } from "@fullcalendar/core";
export default function EventDuplication({
onClose,
event,
onOpenDuplicate,
}: {
onClose: Function;
event: CalendarEvent;
onOpenDuplicate?: () => void;
}) {
const [openModal, setOpenModal] = useState(false);
const [selectedRange, setSelectedRange] = useState<DateSelectArg | null>({
start: new Date(event.start),
startStr: event.start,
end: new Date(event.end ?? ""),
endStr: event.end ?? "",
allDay: event.allday ?? false,
} as DateSelectArg);
const calendarRef = useRef<CalendarApi | null>(null);
const handleClosePopover = () => {
calendarRef.current?.unselect();
setSelectedRange(null);
setOpenModal(!openModal);
onClose({}, "backdropClick");
};
return (
<>
<MenuItem
onClick={() => {
setOpenModal(true);
}}
>
Duplicate event
</MenuItem>
<EventPopover
anchorEl={null}
open={openModal}
selectedRange={selectedRange}
setSelectedRange={setSelectedRange}
calendarRef={calendarRef}
onClose={handleClosePopover}
event={event}
/>
</>
<MenuItem
onClick={() => {
onOpenDuplicate?.();
}}
>
Duplicate event
</MenuItem>
);
}
+3 -1
View File
@@ -77,12 +77,14 @@ export function InfoRow({
<Typography
variant="body2"
color={error ? "error" : "textPrimary"}
style={{
sx={{
wordBreak: "break-word",
whiteSpace: "pre-line",
maxHeight: "33vh",
overflowY: "auto",
width: "100%",
fontSize: "16px",
fontFamily: "'Inter', sans-serif",
}}
>
{data ? (
+2 -6
View File
@@ -44,6 +44,7 @@ export function renderAttendeeBadge(
>
<Badge
overlap="circular"
sx={{ marginRight: 2 }}
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
badgeContent={
classIcon && (
@@ -65,7 +66,6 @@ export function renderAttendeeBadge(
</Badge>
<Box style={{ display: "flex", flexDirection: "column", minWidth: 0 }}>
<Typography
variant="body2"
noWrap
style={{
maxWidth: "180px",
@@ -76,11 +76,7 @@ export function renderAttendeeBadge(
{a.cn || a.cal_address}
</Typography>
{isOrganizer && (
<Typography
variant="caption"
color="text.secondary"
style={{ fontStyle: "italic" }}
>
<Typography variant="caption" color="text.secondary">
Organizer
</Typography>
)}