#685 view more events in month view on mobile

This commit is contained in:
lethemanh
2026-04-09 09:17:42 +07:00
parent 91f0a5526f
commit 2f7351f4fe
2 changed files with 95 additions and 12 deletions
+35 -12
View File
@@ -11,7 +11,7 @@ import { extractEventBaseUuid } from '@/utils/extractEventBaseUuid'
import { setSelectedCalendars as setSelectedCalendarsToStorage } from '@/utils/storage/setSelectedCalendars' import { setSelectedCalendars as setSelectedCalendarsToStorage } from '@/utils/storage/setSelectedCalendars'
import { useSelectedCalendars } from '@/utils/storage/useSelectedCalendars' import { useSelectedCalendars } from '@/utils/storage/useSelectedCalendars'
import { browserDefaultTimeZone } from '@/utils/timezone' import { browserDefaultTimeZone } from '@/utils/timezone'
import type { EventApi, LocaleInput } from '@fullcalendar/core' import type { EventApi, LocaleInput, MoreLinkArg } from '@fullcalendar/core'
import { CalendarApi, DateSelectArg } from '@fullcalendar/core' import { CalendarApi, DateSelectArg } from '@fullcalendar/core'
import frLocale from '@fullcalendar/core/locales/fr' import frLocale from '@fullcalendar/core/locales/fr'
import ruLocale from '@fullcalendar/core/locales/ru' import ruLocale from '@fullcalendar/core/locales/ru'
@@ -46,6 +46,7 @@ import { CALENDAR_VIEWS } from './utils/constants'
import Sidebar from './Sidebar/SideBar' import Sidebar from './Sidebar/SideBar'
import TempSearchDialog from './TempSearchDialog' import TempSearchDialog from './TempSearchDialog'
import { setIsMobileSearchOpen } from '@/features/Calendars/CalendarSlice' import { setIsMobileSearchOpen } from '@/features/Calendars/CalendarSlice'
import ViewMoreEvents from './ViewMoreEvents'
const localeMap: Record<string, LocaleInput | undefined> = { const localeMap: Record<string, LocaleInput | undefined> = {
fr: frLocale, fr: frLocale,
@@ -315,6 +316,18 @@ const CalendarApp: React.FC<CalendarAppProps> = ({
const [tempUsers, setTempUsers] = useState<User[]>([]) const [tempUsers, setTempUsers] = useState<User[]>([])
const [tempEvent, setTempEvent] = useState<CalendarEvent>({} as CalendarEvent) const [tempEvent, setTempEvent] = useState<CalendarEvent>({} as CalendarEvent)
const [isMoreEventsDrawerOpen, setIsMoreEventsDrawerOpen] = useState(false)
const [moreEvents, setMoreEvents] = useState<EventApi[]>([])
const handleMoreLinkClick = (arg: MoreLinkArg): string | void => {
if (!isMobile) return
setMoreEvents(arg.hiddenSegs.map(seg => seg.event))
setIsMoreEventsDrawerOpen(true)
return 'none'
}
useEffect(() => { useEffect(() => {
if (view !== 'calendar') return if (view !== 'calendar') return
const targetView = const targetView =
@@ -447,6 +460,7 @@ const CalendarApp: React.FC<CalendarAppProps> = ({
timeGridWeek: { titleFormat: { month: 'long', year: 'numeric' } } timeGridWeek: { titleFormat: { month: 'long', year: 'numeric' } }
}} }}
dayMaxEvents={true} dayMaxEvents={true}
moreLinkClick={handleMoreLinkClick}
events={eventToFullCalendarFormat( events={eventToFullCalendarFormat(
filteredEvents, filteredEvents,
filteredTempEvents, filteredTempEvents,
@@ -614,17 +628,26 @@ const CalendarApp: React.FC<CalendarAppProps> = ({
</div> </div>
{isMobile && ( {isMobile && (
<TempSearchDialog <>
tempUsers={tempUsers} <TempSearchDialog
setTempUsers={setTempUsers} tempUsers={tempUsers}
onClose={() => { setTempUsers={setTempUsers}
dispatch(setIsMobileSearchOpen(false)) onClose={() => {
onCloseSidebar() dispatch(setIsMobileSearchOpen(false))
}} onCloseSidebar()
handleToggleEventPreview={() => }}
eventHandlers.handleDateSelect(null as unknown as DateSelectArg) handleToggleEventPreview={() =>
} eventHandlers.handleDateSelect(null as unknown as DateSelectArg)
/> }
/>
<ViewMoreEvents
isOpen={isMoreEventsDrawerOpen}
onOpen={() => setIsMoreEventsDrawerOpen(true)}
onClose={() => setIsMoreEventsDrawerOpen(false)}
moreEvents={moreEvents}
handleEventClick={eventHandlers.handleEventClick}
/>
</>
)} )}
</main> </main>
) )
@@ -0,0 +1,60 @@
import type { EventApi, EventClickArg } from '@fullcalendar/core'
import {
List,
ListItem,
SwipeableDrawer,
ListItemButton,
ListItemText,
ListItemIcon
} from '@linagora/twake-mui'
import RepeatIcon from '@mui/icons-material/Repeat'
interface ViewMoreEventsProps {
isOpen: boolean
onOpen: () => void
onClose: () => void
moreEvents: EventApi[]
handleEventClick: (arg: EventClickArg) => void
}
const ViewMoreEvents: React.FC<ViewMoreEventsProps> = ({
isOpen,
onOpen,
onClose,
moreEvents,
handleEventClick
}: ViewMoreEventsProps) => {
return (
<SwipeableDrawer
anchor="bottom"
open={isOpen}
onClose={onClose}
onOpen={onOpen}
>
<List sx={{ p: 2, overflowY: 'auto' }}>
{moreEvents.map((event, index) => (
<ListItem key={index} disablePadding>
<ListItemButton
onClick={() => {
onClose()
handleEventClick({
event,
jsEvent: { preventDefault: () => {} }
} as EventClickArg)
}}
>
<ListItemText primary={event.title} />
{event.extendedProps.recurrenceId && (
<ListItemIcon>
<RepeatIcon />
</ListItemIcon>
)}
</ListItemButton>
</ListItem>
))}
</List>
</SwipeableDrawer>
)
}
export default ViewMoreEvents