diff --git a/devcon-app/src/components/domain/app/dc7/sessions/index.tsx b/devcon-app/src/components/domain/app/dc7/sessions/index.tsx index 89a6647d0..7ef51a97e 100644 --- a/devcon-app/src/components/domain/app/dc7/sessions/index.tsx +++ b/devcon-app/src/components/domain/app/dc7/sessions/index.tsx @@ -397,7 +397,7 @@ export const SessionCard = ({

diff --git a/devcon-app/src/components/domain/app/dc7/sessions/timeline.tsx b/devcon-app/src/components/domain/app/dc7/sessions/timeline.tsx index d879d9661..e63f93cd5 100644 --- a/devcon-app/src/components/domain/app/dc7/sessions/timeline.tsx +++ b/devcon-app/src/components/domain/app/dc7/sessions/timeline.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react' +import React, { useMemo, useRef } from 'react' import { Session as SessionType } from 'types/Session' import { Event } from 'types/Event' import moment from 'moment' @@ -48,26 +48,36 @@ const DayGrid = ({ timeSlots: any[] day: string }) => { + const scrollSyncRef = useRef(null) return ( -

-
+ {/*
{day}
-
-
+
*/} +
+
+
+ {day} +
+
{timeSlots.map((time, index) => (
0 ? 'translateX(-50%)' : 'translateX(0)' }} @@ -79,71 +89,73 @@ const DayGrid = ({
))}
- -
-
- {rooms.map((room, roomIndex) => { - const sessions = sessionsByRoom[room] - - const sessionByTimeslotStart: Record< - string, - { session: SessionType; columns: number; columnIndent: number } - > = {} - - if (sessions) { - sessions.forEach((session: SessionType) => { - const start = moment.utc(session.slot_start).add(7, 'hours') - const end = moment.utc(session.slot_end).add(7, 'hours') - const durationInMinutes = end.diff(start, 'minutes') - // const columns = Math.ceil(durationInMinutes / 10) // Since timeslots are 10 minutes each - const columns = durationInMinutes / 10 - - const excessMinutes = start.minute() % 10 - - const nearestTen = start.clone().subtract(excessMinutes, 'minutes') - - const startFormatted = nearestTen.format('h:mm A') - - sessionByTimeslotStart[startFormatted] = { - session, - columns, - columnIndent: excessMinutes === 5 ? 0.5 : 0, + +
+
+ {rooms.map((room, roomIndex) => { + const sessions = sessionsByRoom[room] + + const sessionByTimeslotStart: Record< + string, + { session: SessionType; columns: number; columnIndent: number } + > = {} + + if (sessions) { + sessions.forEach((session: SessionType) => { + const start = moment.utc(session.slot_start).add(7, 'hours') + const end = moment.utc(session.slot_end).add(7, 'hours') + const durationInMinutes = end.diff(start, 'minutes') + // const columns = Math.ceil(durationInMinutes / 10) // Since timeslots are 10 minutes each + const columns = durationInMinutes / 10 + + const excessMinutes = start.minute() % 10 + + const nearestTen = start.clone().subtract(excessMinutes, 'minutes') + + const startFormatted = nearestTen.format('h:mm A') + + sessionByTimeslotStart[startFormatted] = { + session, + columns, + columnIndent: excessMinutes === 5 ? 0.5 : 0, + } + }) } - }) - } - - return ( - - {timeSlots.map((timeslot, slotIndex) => { - const match = sessionByTimeslotStart[timeslot.format('h:mm A')] - - if (!match) - // || room !== 'Main Stage') - return
- - return ( -
-
- -
-
- ) - })} -
- ) - })} -
-
+ + return ( + + {timeSlots.map((timeslot, slotIndex) => { + const match = sessionByTimeslotStart[timeslot.format('h:mm A')] + + if (!match) + // || room !== 'Main Stage') + return ( +
+ ) + + return ( +
+
+ +
+
+ ) + })} +
+ ) + })} +
+
@@ -192,48 +204,48 @@ const Timeline = ({ sessions, event, days }: { sessions: SessionType[]; event: E }) as string[] return ( -
- - {/* */} -
- {days.map(day => { - const sessionsForDay = sessions.filter(session => moment(session.slot_start).format('MMM DD') === day) - - if (!sessionsForDay.length) return null - - const sessionsByRoom: any = {} - - const firstTimeSlot = moment.utc(sessionsForDay[0].slot_start).add(7, 'hours') - const lastTimeSlot = moment.utc(sessionsForDay[sessionsForDay.length - 1].slot_end).add(7, 'hours') - - sessionsForDay.forEach((session: any) => { - if (sessionsByRoom[session.slot_room?.name]) { - sessionsByRoom[session.slot_room?.name].push(session) - } else { - sessionsByRoom[session.slot_room?.name] = [session] - } - }) - - const generateTimeSlots = () => { - const slots = [] - const startTime = moment.utc(firstTimeSlot) - startTime.subtract(startTime.minute() % 10, 'minutes') - - const endTime = moment.utc(lastTimeSlot).add(10, 'minutes') // Add buffer after last session + 7 for bangkok - - while (startTime <= endTime) { - slots.push(startTime.clone()) - startTime.add(10, 'minutes') - } - return slots - } - - const timeSlots = generateTimeSlots() - - return - })} -
- {/*
*/} +
+ {days.map(day => { + const sessionsForDay = sessions.filter(session => moment(session.slot_start).format('MMM DD') === day) + + if (!sessionsForDay.length) return null + + const sessionsByRoom: any = {} + + const firstTimeSlot = moment.utc(sessionsForDay[0].slot_start).add(7, 'hours') + const lastTimeSlot = moment.utc(sessionsForDay[sessionsForDay.length - 1].slot_end).add(7, 'hours') + + sessionsForDay.forEach((session: any) => { + if (sessionsByRoom[session.slot_room?.name]) { + sessionsByRoom[session.slot_room?.name].push(session) + } else { + sessionsByRoom[session.slot_room?.name] = [session] + } + }) + + const generateTimeSlots = () => { + const slots = [] + const startTime = moment.utc(firstTimeSlot) + startTime.subtract(startTime.minute() % 10, 'minutes') + + const endTime = moment.utc(lastTimeSlot).add(10, 'minutes') // Add buffer after last session + 7 for bangkok + + while (startTime <= endTime) { + slots.push(startTime.clone()) + startTime.add(10, 'minutes') + } + return slots + } + + const timeSlots = generateTimeSlots() + + return ( +
+ + +
+ ) + })}
) } diff --git a/lib/components/event-schedule/swipe-to-scroll/SwipeToScroll.tsx b/lib/components/event-schedule/swipe-to-scroll/SwipeToScroll.tsx index 3677a94f1..f199c833f 100644 --- a/lib/components/event-schedule/swipe-to-scroll/SwipeToScroll.tsx +++ b/lib/components/event-schedule/swipe-to-scroll/SwipeToScroll.tsx @@ -1,4 +1,4 @@ -import React, { forwardRef, useImperativeHandle } from "react"; +import React, { forwardRef, useEffect, useImperativeHandle } from "react"; import css from "./sts.module.scss"; import { useDrag } from "react-use-gesture"; import useDimensions from "react-cool-dimensions"; @@ -7,6 +7,7 @@ type SwipeToScrollProps = { noBounds?: boolean; noScrollReset?: boolean; focusRef?: React.RefObject; + syncElement?: React.RefObject; children: React.ReactChild | React.ReactChild[]; scrollIndicatorDirections?: { ["left"]?: boolean; @@ -87,11 +88,28 @@ const SwipeToScroll = forwardRef((props: SwipeToScrollProps, ref) => { ] ); + // useEffect(() => { + // if (props.syncElement?.current) { + // if (isNativeScroll) { + // props.syncElement.current.style.overflowX = 'auto'; + // props.syncElement.current.style.transform = 'translateX(0px) !important'; + // } else { + // props.syncElement.current.style.overflowX = ''; + // props.syncElement.current.style.transform = ''; + // } + // } + // }, [isNativeScroll]); + const reset = React.useCallback(() => { if (el.current) { const scrollContainer = el.current; lastX.current = 0; scrollContainer.style.transform = `translateX(0px)`; + + if (props.syncElement?.current) { + props.syncElement.current.style.transform = `translateX(0px)`; + } + syncScrollIndicators(scrollContainer); } }, [syncScrollIndicators]); @@ -154,9 +172,20 @@ const SwipeToScroll = forwardRef((props: SwipeToScrollProps, ref) => { left: clampedScrollLeft, // elementRect.left - 16, behavior: "smooth", }); + + if (props.syncElement?.current) { + props.syncElement.current.scrollTo({ + left: clampedScrollLeft, + behavior: "smooth", + }); + } } else { // Use translateX for devices with a cursor scrollContainer.style.transform = `translateX(-${clampedScrollLeft}px)`; + + if (props.syncElement?.current) { + props.syncElement.current.style.transform = `translateX(-${clampedScrollLeft}px)`; + } } lastX.current = clampedScrollLeft; @@ -182,6 +211,10 @@ const SwipeToScroll = forwardRef((props: SwipeToScrollProps, ref) => { lastX.current = Math.min(Math.max(0, lastX.current - delta[0]), maxScroll); scrollContainer.style.transform = `translateX(-${lastX.current}px)`; + if (props.syncElement?.current) { + props.syncElement.current.style.transform = `translateX(-${lastX.current}px)`; + } + if (down) { containerEl.current!.style.cursor = "grabbing"; } else { @@ -194,9 +227,9 @@ const SwipeToScroll = forwardRef((props: SwipeToScrollProps, ref) => { if (scrollIndicatorClass) className += ` ${scrollIndicatorClass}`; if (props.noBounds) className += ` ${css["no-bounds"]}`; - let scrollContainerClass = css["swipe-to-scroll"]; + let scrollContainerClass = "h-full select-none"; - if (isNativeScroll) scrollContainerClass += ` ${css["is-native-scroll"]}`; + if (isNativeScroll) scrollContainerClass += " overflow-x-auto !translate-x-0"; return (
{ observe(element); }} className={scrollContainerClass} + onScroll={(e) => { + if (props.syncElement?.current) { + // @ts-ignore + props.syncElement.current.scrollLeft = e.target.scrollLeft; + } + }} // This prevents selection (text, image) while dragging onMouseDown={(e) => { e.preventDefault();