11import { wrap } from '@suspensive/react'
22import React from "react"
3+ import * as R from 'remeda'
34import styled from 'styled-components'
45
56import Page from "components/common/Page"
@@ -8,6 +9,12 @@ import { useNavigate } from 'react-router'
89import { useListSessionsQuery } from 'utils/hooks/useAPI'
910import useTranslation from "utils/hooks/useTranslation"
1011
12+ const ENABLE_DETAILS = false
13+
14+ const TD_HEIGHT = 2.5
15+ const TD_WIDTH = 12.5
16+ const TD_WIDTH_MOBILE = 20
17+
1118type TimeTableData = {
1219 [ date : string ] : {
1320 [ time : string ] : {
@@ -83,10 +90,11 @@ const getTimeTableData: (data: APIPretalxSessions) => TimeTableData = (data) =>
8390 return timeTableData
8491}
8592
86- const SessionColumn : React . FC < { rowSpan : number , session : APIPretalxSessions [ 0 ] } > = ( { rowSpan, session } ) => {
93+ const SessionColumn : React . FC < { rowSpan : number , colSpan ?: number , session : APIPretalxSessions [ 0 ] } > = ( { rowSpan, colSpan , session } ) => {
8794 const navigate = useNavigate ( )
88- return < td rowSpan = { rowSpan } >
89- < SessionBox onClick = { ( ) => navigate ( `/session/${ session . code } ` ) } >
95+ const clickable = ENABLE_DETAILS && R . isArray ( session . speakers ) && ! R . isEmpty ( session . speakers )
96+ return < td rowSpan = { rowSpan } colSpan = { colSpan } >
97+ < SessionBox onClick = { ( ) => clickable && navigate ( `/session/${ session . code } ` ) } className = { clickable ? 'clickable' : '' } >
9098 < h6 > { session . title } </ h6 >
9199 < SessionSpeakerContainer >
92100 { session . speakers . map ( ( speaker ) => < kbd key = { speaker . code } > { speaker . name } </ kbd > ) }
@@ -95,15 +103,6 @@ const SessionColumn: React.FC<{ rowSpan: number, session: APIPretalxSessions[0]
95103 </ td >
96104}
97105
98- const BreakColumn : React . FC < { colSpan : number , hideText ?: boolean } > = ( { colSpan, hideText } ) => {
99- const t = useTranslation ( )
100- return < td colSpan = { colSpan } >
101- < small style = { { color : 'rgba(255, 255, 255, 0.5)' } } > { ! hideText && t ( '휴식' ) } </ small >
102- </ td >
103- }
104-
105- const BlankColumn : React . FC = ( ) => < td > </ td >
106-
107106export const SessionTimeTablePage : React . FC = ( ) => {
108107 const t = useTranslation ( )
109108
@@ -123,11 +122,13 @@ export const SessionTimeTablePage: React.FC = () => {
123122 const timeTableData = getTimeTableData ( data )
124123 const dates = Object . keys ( timeTableData ) . sort ( ( a , b ) => new Date ( a ) . getTime ( ) - new Date ( b ) . getTime ( ) )
125124 const rooms : { [ room : string ] : number } = getRooms ( data ) . reduce ( ( acc , room ) => ( { ...acc , [ room ] : 0 } ) , { } )
126- const sortedRoomList = Object . keys ( rooms ) . sort ( )
127125 const roomCount = Object . keys ( rooms ) . length
126+ const sortedRoomList = Object . keys ( rooms ) . sort ( )
128127
129128 const selectedDate = confDate || dates [ 0 ]
130129 const selectedTableData = timeTableData [ selectedDate ]
130+
131+ let breakCount = 0
131132 return < >
132133 < hr />
133134 < SessionDateTabContainer >
@@ -151,24 +152,59 @@ export const SessionTimeTablePage: React.FC = () => {
151152 < tr > < td colSpan = { roomCount + 1 } > </ td > </ tr >
152153 {
153154 Object . entries ( selectedTableData ) . map ( ( [ time , roomData ] , i , a ) => {
155+ const hasSession = Object . values ( rooms ) . some ( ( c ) => c >= 1 ) || Object . values ( roomData ) . some ( ( room ) => room !== undefined )
156+
157+ if ( ! hasSession ) {
158+ if ( breakCount > 1 ) {
159+ breakCount --
160+ return < tr > </ tr >
161+ } else {
162+ // 지금부터 다음 세션이 존재하기 전까지의 휴식 시간을 계산합니다.
163+ breakCount = 1
164+ for ( let bi = i + 1 ; bi < a . length ; bi ++ ) {
165+ if ( Object . values ( a [ bi ] [ 1 ] ) . some ( ( room ) => room !== undefined ) ) break
166+ breakCount += 1
167+ }
168+
169+ // I really hate this, but I can't think of a better way to do this.
170+ const height = TD_HEIGHT * breakCount / ( breakCount <= 2 ? 1 : 3 )
171+ return < tr >
172+ < td style = { { height : `${ height } rem` , transform : `translateY(-${ height / 2 } rem)` } } > { time } </ td >
173+ < td colSpan = { roomCount + 1 } rowSpan = { breakCount } style = { { height : `${ height } rem` } } >
174+ < div style = { { display : 'flex' , flexDirection : 'column' , justifyContent : 'center' , alignItems : 'center' } } >
175+ { i !== a . length - 1 && < small style = { { color : 'rgba(255, 255, 255, 0.5)' } } > { t ( '휴식' ) } </ small > }
176+ </ div >
177+ </ td >
178+ </ tr >
179+ }
180+ }
181+
182+ // 만약 세션 타입이 아닌 발표가 존재하는 경우, 해당 줄에서는 colSpan이 roomCount인 column을 생성합니다.
183+ const nonSessionTypeData = Object . values ( roomData ) . find ( ( room ) => room !== undefined && room . session . submission_type . en !== 'Session' )
184+ if ( nonSessionTypeData ) {
185+ Object . keys ( rooms ) . forEach ( ( room ) => rooms [ room ] = nonSessionTypeData . rowSpan - 1 )
186+ return < tr >
187+ < td > { time } </ td >
188+ < SessionColumn rowSpan = { nonSessionTypeData . rowSpan } colSpan = { roomCount } session = { nonSessionTypeData . session } />
189+ </ tr >
190+ }
191+
154192 return < tr >
155193 < td > { time } </ td >
156194 {
157- Object . values ( rooms ) . some ( ( c ) => c >= 1 ) || Object . values ( roomData ) . some ( ( room ) => room !== undefined )
158- ? sortedRoomList . map ( ( room ) => {
159- const roomDatum = roomData [ room ]
160- if ( roomDatum === undefined ) {
161- // 진행 중인 세션이 없는 경우, 해당 줄에서는 해당 room의 빈 column을 생성합니다.
162- if ( rooms [ room ] <= 0 ) return < BlankColumn />
163- // 진행 중인 세션이 있는 경우, 이번 줄에서는 해당 세션들만큼 column을 생성하지 않습니다.
164- rooms [ room ] -= 1
165- return null
166- }
167- // 세션이 여러 줄에 걸쳐있는 경우, n-1 줄만큼 해당 room에 column을 생성하지 않도록 합니다.
168- if ( roomDatum . rowSpan > 1 ) rooms [ room ] = roomDatum . rowSpan - 1
169- return < SessionColumn key = { room } rowSpan = { roomDatum . rowSpan } session = { roomDatum . session } />
170- } )
171- : < BreakColumn colSpan = { roomCount } hideText = { i === a . length - 1 } />
195+ sortedRoomList . map ( ( room ) => {
196+ const roomDatum = roomData [ room ]
197+ if ( roomDatum === undefined ) {
198+ // 진행 중인 세션이 없는 경우, 해당 줄에서는 해당 room의 빈 column을 생성합니다.
199+ if ( rooms [ room ] <= 0 ) return < td > </ td >
200+ // 진행 중인 세션이 있는 경우, 이번 줄에서는 해당 세션들만큼 column을 생성하지 않습니다.
201+ rooms [ room ] -= 1
202+ return null
203+ }
204+ // 세션이 여러 줄에 걸쳐있는 경우, n-1 줄만큼 해당 room에 column을 생성하지 않도록 합니다.
205+ if ( roomDatum . rowSpan > 1 ) rooms [ room ] = roomDatum . rowSpan - 1
206+ return < SessionColumn key = { room } rowSpan = { roomDatum . rowSpan } session = { roomDatum . session } />
207+ } )
172208 }
173209 </ tr >
174210 } )
@@ -189,9 +225,6 @@ export const SessionTimeTablePage: React.FC = () => {
189225 )
190226}
191227
192- const TD_HEIGHT = 2.5
193- const TD_WIDTH = 12.5
194-
195228const SessionDateTabContainer = styled . div `
196229 display: flex;
197230 gap: 2rem;
@@ -262,6 +295,17 @@ const SessionTable = styled.table`
262295 max-width: ${ TD_WIDTH } vw;
263296 border-top: 1px solid rgba(255, 255, 255, 0.1);
264297 }
298+
299+ small {
300+ font-size: 0.8rem;
301+ }
302+
303+ @media only screen and (max-width: 810px) {
304+ td:not(:first-child) {
305+ width: ${ TD_WIDTH_MOBILE } vw;
306+ max-width: ${ TD_WIDTH_MOBILE } vw;
307+ }
308+ }
265309`
266310
267311const SessionBox = styled . div `
@@ -272,19 +316,21 @@ const SessionBox = styled.div`
272316 flex-direction: column;
273317 justify-content: center;
274318 align-items: center;
275- border: 1px solid rgba(176, 168, 254, 0.75 );
319+ border: 1px solid rgba(176, 168, 254, 0.3 );
276320 border-radius: 0.5rem;
277321
278322 background-color: rgba(176, 168, 254, 0.1);
279323 font-size: 1rem;
280324 transition: all 0.25s ease;
281325
282- cursor: pointer;
326+ &.clickable {
327+ cursor: pointer;
328+ }
283329
284330 h6 {
285331 margin: 0;
286332 color: rgba(255, 255, 255, 0.6);
287- font-size: 0.9rem ;
333+ font-size: 0.8rem ;
288334 transition: all 0.25s ease;
289335 }
290336
@@ -300,6 +346,7 @@ const SessionBox = styled.div`
300346 }
301347
302348 &:hover {
349+ border: 1px solid rgba(176, 168, 254, 0.75);
303350 background-color: rgba(176, 168, 254, 0.25);
304351 transition: all 0.25s ease;
305352
0 commit comments