[#668] Tablet view (#716)

* draft for tablet view
* adapt sidebar to tablet view
* split menubar to handle tablet and desktop separatly
* split sidebar to handle tablet and desktop separatly
* prettier day navigationin tablet view
* added missing translations
* coderabbit comments
* fix UI of view switcher on tablet, remove hard text
* fix style of selected view option
* fix wrong I18n key
* extracted menubar recurring components to own files
* adjust test case of calendar component
* refactor function change calendar view

Co-authored-by: Camille Moussu <cmoussu@linagora.com>
Co-authored-by: lethemanh <lethemanh@lethemanhs-MacBook-Pro.local>
This commit is contained in:
Camille Moussu
2026-04-03 08:49:37 +02:00
committed by GitHub
parent c1d3cf5f3d
commit 4e57f6b342
36 changed files with 1549 additions and 576 deletions
+44 -3
View File
@@ -1,5 +1,6 @@
import { useAppDispatch, useAppSelector } from '@/app/hooks'
import SettingsPage from '@/features/Settings/SettingsPage'
import { useScreenSizeDetection } from '@/useScreenSizeDetection'
import { getViewRange } from '@/utils/dateUtils'
import type { CalendarApi } from '@fullcalendar/core'
import CozyBridge from 'cozy-external-bridge'
@@ -8,6 +9,8 @@ import { ErrorSnackbar } from '../Error/ErrorSnackbar'
import { refreshCalendars } from '../Event/utils/eventUtils'
import { Menubar, MenubarProps } from '../Menubar/Menubar'
import CalendarApp from './Calendar'
import { CALENDAR_VIEWS } from './utils/constants'
import { setView } from '@/features/Settings/SettingsSlice'
export default function CalendarLayout() {
const calendarRef = useRef<CalendarApi | null>(null)
@@ -16,8 +19,31 @@ export default function CalendarLayout() {
const selectedCalendars = useAppSelector(state => state.calendars.list)
const tempcalendars = useAppSelector(state => state.calendars.templist)
const view = useAppSelector(state => state.settings.view)
const { isTablet } = useScreenSizeDetection()
const [openSidebar, setOpenSideBar] = useState(false)
const [currentDate, setCurrentDate] = useState<Date>(new Date())
const [currentView, setCurrentView] = useState<string>('timeGridWeek')
const [currentView, setCurrentView] = useState<string>(
isTablet ? CALENDAR_VIEWS.timeGridDay : CALENDAR_VIEWS.timeGridWeek
)
useEffect(() => {
const setView = () =>
setCurrentView(prev => {
if (
prev !== CALENDAR_VIEWS.timeGridDay &&
prev !== CALENDAR_VIEWS.timeGridWeek
) {
return prev
}
return isTablet
? CALENDAR_VIEWS.timeGridDay
: CALENDAR_VIEWS.timeGridWeek
})
setView()
}, [isTablet])
const isInIframe = useMemo(() => new CozyBridge().isInIframe(), [])
const handleRefresh = async () => {
@@ -47,8 +73,18 @@ export default function CalendarLayout() {
setCurrentDate(date)
}
const handleViewChange = (view: string) => {
const handleViewChange = (view: string): void => {
if (!calendarRef.current) return
dispatch(setView('calendar'))
calendarRef.current.changeView(view)
// Notify parent about view change
setCurrentView(view)
// Notify parent about date change after view change
const newDate = calendarRef.current.getDate()
handleDateChange(newDate)
}
// Hide topbar navigation elements when in settings view (same as fullscreen dialog mode)
@@ -72,7 +108,8 @@ export default function CalendarLayout() {
onDateChange: handleDateChange,
currentView,
onViewChange: handleViewChange,
isIframe: isInIframe
isIframe: isInIframe,
onToggleSidebar: () => setOpenSideBar(true)
}
return (
@@ -84,6 +121,10 @@ export default function CalendarLayout() {
onDateChange={handleDateChange}
onViewChange={handleViewChange}
menubarProps={menubarProps}
openSidebar={openSidebar}
onCloseSidebar={() => setOpenSideBar(false)}
setCurrentView={setCurrentView}
currentView={currentView}
/>
)}
{view === 'settings' && <SettingsPage isInIframe={isInIframe} />}