Skip to content

Commit

Permalink
issue-198: added custom date picker in date select views
Browse files Browse the repository at this point in the history
  • Loading branch information
ali-ahnaf committed Feb 5, 2025
1 parent c43921e commit ce39c3f
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 79 deletions.
4 changes: 2 additions & 2 deletions client/src/components/EventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import MeetingRoomRoundedIcon from '@mui/icons-material/MeetingRoomRounded';
import StairsIcon from '@mui/icons-material/Stairs';
import AccessTimeFilledRoundedIcon from '@mui/icons-material/AccessTimeFilledRounded';
import EventSeatRoundedIcon from '@mui/icons-material/EventSeatRounded';
import { convertToLocaleTime } from '@helpers/utility';
import { convertToLocaleTime, isPastDate } from '@helpers/utility';
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
import LocationOnRoundedIcon from '@mui/icons-material/LocationOnRounded';
import EmailRoundedIcon from '@mui/icons-material/EmailRounded';
Expand Down Expand Up @@ -227,7 +227,7 @@ const EventCard = ({ sx, event, onDelete, handleEditClick, isEditable, handleEve
const menuItems: JSX.Element[] = [];
if (isEditable) {
menuItems.push(
<MenuItem key="edit" onClick={onEditClick}>
<MenuItem key="edit" onClick={onEditClick} disabled={isPastDate(event.start) ? true : false}>
Edit
</MenuItem>,
);
Expand Down
12 changes: 12 additions & 0 deletions client/src/helpers/utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Api from '@/api/api';
import { ROUTES } from '@config/routes';
import { secrets } from '@config/secrets';
import { ApiResponse } from '@quickmeet/shared';
import dayjs, { Dayjs } from 'dayjs';
import { toast } from 'react-hot-toast';
import { NavigateFunction } from 'react-router-dom';

Expand Down Expand Up @@ -192,3 +193,14 @@ export const chromeBackground = {
const params = new URLSearchParams(window.location.search);

export const isChromeExt = Boolean(params.get('chrome')) || secrets.appEnvironment === 'chrome';

export const isPastDate = (date: string | Dayjs | undefined): boolean => {
if (!date || !dayjs(date).isValid()) {
return false;
}

const selectedDate = dayjs(date).startOf('day');
const today = dayjs().startOf('day');

return selectedDate.isBefore(today);
};
78 changes: 40 additions & 38 deletions client/src/pages/Home/BookRoomView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ import HourglassBottomRoundedIcon from '@mui/icons-material/HourglassBottomRound
import MeetingRoomRoundedIcon from '@mui/icons-material/MeetingRoomRounded';
import TitleIcon from '@mui/icons-material/Title';
import LoadingButton from '@mui/lab/LoadingButton';
import { Box, Checkbox, Typography } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { Box, Checkbox, IconButton, Typography } from '@mui/material';
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
import dayjs from 'dayjs';
import 'dayjs/locale/en-gb';
import { useEffect, useRef, useState } from 'react';
import toast from 'react-hot-toast';
import { useNavigate } from 'react-router-dom';
import DatePickerPopper from '@/pages/Home/MyEventsView/DatePickerPopper';

const createRoomDropdownOptions = (rooms: IConferenceRoom[]) => {
return (rooms || []).map((room) => ({ value: room.email, text: room.name, seats: room.seats, floor: room.floor }) as RoomsDropdownOption);
Expand Down Expand Up @@ -64,6 +65,8 @@ export default function BookRoomView({ onRoomBooked }: BookRoomViewProps) {
});

const [date, setDate] = useState(dayjs());
const [datePickerOpen, setDatePickerOpen] = useState(false);
const [datePickerAnchorEl, setDatePickerAnchorEl] = useState<null | HTMLElement>(null);

// Utilities and hooks
const navigate = useNavigate();
Expand Down Expand Up @@ -199,6 +202,11 @@ export default function BookRoomView({ onRoomBooked }: BookRoomViewProps) {
});
}

const handleDatePopperClick = (event: React.MouseEvent<HTMLElement>) => {
setDatePickerAnchorEl(event.currentTarget);
setDatePickerOpen(true);
};

async function onBookClick() {
setBookClickLoading(true);
const { startTime, duration, seats, conference, attendees, title, room } = formData;
Expand Down Expand Up @@ -283,42 +291,28 @@ export default function BookRoomView({ onRoomBooked }: BookRoomViewProps) {
/>
</Box>
<Box sx={{ flex: 1, display: 'flex' }}>
<DatePicker
disablePast
defaultValue={date}
onChange={(newDate) => {
if (newDate) {
setDate(newDate);
}
}}
slotProps={{
inputAdornment: {
position: 'start',
sx: {
input: {
cursor: 'pointer',
},
},
},
}}
sx={{
'.MuiOutlinedInput-root': {
'& fieldset': {
border: 'none',
},
},
'.MuiInputBase-input': {
color: (theme) => theme.palette.common.black,
fontFamily: 'inherit',
fontSize: '1.125rem',
fontWeight: 400,
},
'.MuiSvgIcon-root': {
color: (theme) => theme.palette.grey[50],
},
'.MuiButtonBase-root': { cursor: 'pointer' },
}}
/>
<Box sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<IconButton aria-label="calender" size="small" onClick={handleDatePopperClick}>
<CalendarMonthIcon
sx={[
(theme) => ({
color: theme.palette.grey[50],
}),
]}
fontSize="medium"
/>
</IconButton>
<Typography
sx={{
cursor: 'pointer',
ml: 2,
}}
variant="subtitle1"
onClick={handleDatePopperClick}
>
{date.format('DD/MM/YYYY')}
</Typography>
</Box>
</Box>
</Box>
<Box>
Expand Down Expand Up @@ -456,6 +450,14 @@ export default function BookRoomView({ onRoomBooked }: BookRoomViewProps) {
</Typography>
</LoadingButton>
</Box>
<DatePickerPopper
disablePast={true}
currentDate={date}
setCurrentDate={setDate}
open={datePickerOpen}
setOpen={setDatePickerOpen}
anchorEl={datePickerAnchorEl}
/>
</Box>
);
}
6 changes: 4 additions & 2 deletions client/src/pages/Home/MyEventsView/DatePickerPopper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box, Chip, ClickAwayListener, Divider, Fade, GlobalStyles, List, ListItem, Popper } from '@mui/material';
import { StaticDatePicker, PickersShortcutsItem, PickersShortcutsProps, type PickerChangeHandlerContext, type DateValidationError } from '@mui/x-date-pickers';
import { StaticDatePicker, PickersShortcutsItem, PickersShortcutsProps, PickerChangeHandlerContext, DateValidationError } from '@mui/x-date-pickers';
import dayjs from 'dayjs';
import { useEffect, useRef } from 'react';

Expand Down Expand Up @@ -67,14 +67,15 @@ function DatePickerShortcuts(props: PickersShortcutsProps<dayjs.Dayjs | null>) {
}

interface DatePickerPopperProps {
disablePast?: boolean;
currentDate: dayjs.Dayjs;
setCurrentDate: React.Dispatch<React.SetStateAction<dayjs.Dayjs>>;
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
anchorEl: HTMLElement | null;
}

const DatePickerPopper = ({ open, setOpen, currentDate, setCurrentDate, anchorEl }: DatePickerPopperProps) => {
const DatePickerPopper = ({ open, setOpen, currentDate, setCurrentDate, anchorEl, disablePast }: DatePickerPopperProps) => {
const hasMounted = useRef(false);

useEffect(() => {
Expand Down Expand Up @@ -119,6 +120,7 @@ const DatePickerPopper = ({ open, setOpen, currentDate, setCurrentDate, anchorEl
/>
{/* https://mui.com/x/react-date-pickers/date-picker/#customization */}
<StaticDatePicker
disablePast={disablePast}
onChange={onDateChange}
value={currentDate}
slots={{
Expand Down
76 changes: 39 additions & 37 deletions client/src/pages/Home/MyEventsView/EditEventsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ import TitleIcon from '@mui/icons-material/Title';
import { FormData, IAvailableRoomsDropdownOption } from '@helpers/types';
import { LoadingButton } from '@mui/lab';
import { AppBar, Box, Button, Checkbox, IconButton, Skeleton, Stack, Typography } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
import dayjs from 'dayjs';
import 'dayjs/locale/en-gb';
import { useEffect, useRef, useState } from 'react';
import { EventResponse, IConferenceRoom, IAvailableRooms, IPeopleInformation } from '@quickmeet/shared';
import { useNavigate } from 'react-router-dom';
import DatePickerPopper from '@/pages/Home/MyEventsView/DatePickerPopper';

const createRoomDropdownOptions = (rooms: IConferenceRoom[]) => {
return (rooms || []).map((room) => ({ value: room.email, text: room.name, seats: room.seats, floor: room.floor }) as RoomsDropdownOption);
Expand Down Expand Up @@ -85,6 +86,8 @@ export default function EditEventsView({ open, event, handleClose, currentRoom,
const [formData, setFormData] = useState<FormData>(initFormData(event));

const [date, setDate] = useState(dayjs(event.start!));
const [datePickerOpen, setDatePickerOpen] = useState(false);
const [datePickerAnchorEl, setDatePickerAnchorEl] = useState<null | HTMLElement>(null);

// Utilities and hooks
const api = useApi();
Expand Down Expand Up @@ -186,6 +189,11 @@ export default function EditEventsView({ open, event, handleClose, currentRoom,
setAvailableRoomOptions({ others: unPreferredRoomOptions, preferred: preferredRoomOptions });
}

const handleDatePopperClick = (event: React.MouseEvent<HTMLElement>) => {
setDatePickerAnchorEl(event.currentTarget);
setDatePickerOpen(true);
};

async function setPreferences() {
const eventTime = new Date(event.start!);
const currentTime = new Date(new Date().toUTCString());
Expand Down Expand Up @@ -315,42 +323,28 @@ export default function EditEventsView({ open, event, handleClose, currentRoom,
/>
</Box>
<Box sx={{ flex: 1, display: 'flex' }}>
<DatePicker
disablePast
defaultValue={dayjs(event.start!)}
onChange={(newDate) => {
if (newDate) {
setDate(newDate);
}
}}
slotProps={{
inputAdornment: {
position: 'start',
sx: {
input: {
cursor: 'pointer',
},
},
},
}}
sx={{
'.MuiOutlinedInput-root': {
'& fieldset': {
border: 'none',
},
},
'.MuiInputBase-input': {
color: (theme) => theme.palette.common.black,
fontFamily: 'inherit',
fontSize: '1.125rem',
fontWeight: 400,
},
'.MuiSvgIcon-root': {
color: (theme) => theme.palette.grey[50],
},
'.MuiButtonBase-root': { cursor: 'pointer' },
}}
/>
<Box sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<IconButton aria-label="calender" size="small" onClick={handleDatePopperClick}>
<CalendarMonthIcon
sx={[
(theme) => ({
color: theme.palette.grey[50],
}),
]}
fontSize="medium"
/>
</IconButton>
<Typography
sx={{
cursor: 'pointer',
ml: 2,
}}
variant="subtitle1"
onClick={handleDatePopperClick}
>
{date.format('DD/MM/YYYY')}
</Typography>
</Box>
</Box>
</Box>

Expand Down Expand Up @@ -509,6 +503,14 @@ export default function EditEventsView({ open, event, handleClose, currentRoom,
</Typography>
</Button>
</Box>
<DatePickerPopper
disablePast={true}
currentDate={date}
setCurrentDate={setDate}
open={datePickerOpen}
setOpen={setDatePickerOpen}
anchorEl={datePickerAnchorEl}
/>
</Box>
);
}

0 comments on commit ce39c3f

Please sign in to comment.