Skip to content

Commit 62da406

Browse files
committed
세션 시간표 반영
1 parent 353ebe2 commit 62da406

File tree

5 files changed

+150
-19
lines changed

5 files changed

+150
-19
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import styled from 'styled-components'
2+
3+
const DifficultyBadge = styled.span<{ level: string }>`
4+
display: inline-block;
5+
vertical-align: top;
6+
padding: 0.3em 0.5em;
7+
font-size: 0.7rem;
8+
border-radius: 4px;
9+
line-height: 1;
10+
${({ level }) => {
11+
if (level === '초급') {
12+
return `background-color: #139d2b;`
13+
} else if (level === '중급') {
14+
return `background-color: #ff7f00;`
15+
} else if (level === '고급') {
16+
return `background-color: #cf3535;`
17+
}
18+
return `display: none;`
19+
}}
20+
`
21+
22+
export default DifficultyBadge

frontend/components/service/Program/TalkTable.tsx

Lines changed: 96 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,119 @@
11
import React from 'react'
2-
import { ITalkItem, ITalkTableData } from '../../../interfaces/IProgram'
2+
import { ITalkItem, ITalkTableList } from '../../../interfaces/IProgram'
33
import styled from 'styled-components'
4+
import { format } from 'date-fns'
5+
import Link from 'next/link'
6+
import DifficultyBadge from './DifficultyBadge'
7+
import Resources from '../../../data/constants/resources'
48

59
const Table = styled.table`
610
width: 100%;
11+
border-collapse: collapse;
12+
table-layout: fixed;
13+
`
14+
const LeftColumn = styled.div`
15+
width: 90px;
716
`
817

18+
const TableHeader = styled.thead`
19+
border-top: 2px solid ${(props) => props.theme.colors.white};
20+
border-bottom: 2px solid ${(props) => props.theme.colors.white};
21+
`
22+
const TableRow = styled.tr`
23+
& + & {
24+
border-top: 1px solid ${(props) => props.theme.colors.white};
25+
}
26+
`
27+
const TableCell = styled.div`
28+
padding: 1rem;
29+
text-align: ${(props) => props.align ?? 'center'};
30+
`
31+
const BadgeWrap = styled.div`
32+
margin-top: 0.5rem;
33+
`
34+
const Title = styled.div`
35+
margin: 0.4rem 0;
36+
`
37+
const Speaker = styled.div`
38+
color: ${(props) => props.theme.colors.violet0};
39+
`
40+
const BoldText = styled.div`
41+
font-weight: bold;
42+
`
43+
44+
const TalkTableItem = (props: { item: ITalkItem }) => {
45+
const { item } = props
46+
const isKeynote = item.category === Resources.KEYNOTE_NAME
47+
48+
return (
49+
<Link href={`/program/talks/${item.id}`}>
50+
<a>
51+
{isKeynote && <BoldText>[키노트]</BoldText>}
52+
<Title>{item.title}</Title>
53+
<Speaker>{item.user_name}</Speaker>
54+
</a>
55+
</Link>
56+
)
57+
}
58+
959
const TalkTable = (props: {
1060
day: string
1161
headers: string[]
12-
list: ITalkItem[]
62+
list: ITalkTableList[]
1363
}) => {
14-
const headers = ['트랙1(101)', '트랙2(102)']
64+
const { list } = props
65+
console.log(list)
66+
67+
const getTime = (timeString: string): string => {
68+
return format(new Date(timeString), 'HH:mm')
69+
}
1570

1671
return (
1772
<div>
18-
<table>
19-
<thead>
73+
<Table>
74+
<TableHeader>
2075
<tr>
2176
<th>
22-
시간
23-
<br />
24-
(KST)
77+
<LeftColumn>
78+
시간
79+
<br />
80+
(KST)
81+
</LeftColumn>
2582
</th>
26-
{headers.map((header) => (
83+
{props.headers.map((header) => (
2784
<th key={header}>{header}</th>
2885
))}
2986
</tr>
30-
</thead>
31-
<tbody></tbody>
32-
</table>
87+
</TableHeader>
88+
<tbody>
89+
{list.map((item, index) => (
90+
<TableRow key={`time-${index}`}>
91+
<td>
92+
<TableCell align={'left'}>
93+
{getTime(item.video_open_at)}
94+
</TableCell>
95+
</td>
96+
{item.talkList.length > 1 ? (
97+
item.talkList.map((talkItem) => (
98+
<td key={`talk-${talkItem.id}`}>
99+
<TableCell>
100+
<TalkTableItem item={talkItem} />
101+
</TableCell>
102+
</td>
103+
))
104+
) : (
105+
<td colSpan={2}>
106+
<TableCell>
107+
<TalkTableItem
108+
item={item.talkList[0]}
109+
/>
110+
</TableCell>
111+
</td>
112+
)}
113+
</TableRow>
114+
))}
115+
</tbody>
116+
</Table>
33117
</div>
34118
)
35119
}

frontend/components/service/Program/TalkTableToggleButton.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ const ButtonGroup = styled.div`
66
width: 100%;
77
align-items: center;
88
justify-content: center;
9+
border-bottom: 1px solid ${(props) => props.theme.colors.white};
910
`
1011
const Button = styled.button<{ selected: boolean }>`
1112
border-radius: 4px;
1213
font-size: 1rem;
13-
padding: 0 2rem;
14+
padding: 1rem 2rem;
1415
background: inherit;
1516
cursor: pointer;
1617
border: 0;

frontend/interfaces/IProgram.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { IApiTalkItem } from './api/IApiPrograms'
22

3+
export interface ITalkTableList {
4+
[key: string]: any
5+
talkList: ITalkItem[]
6+
}
7+
38
export interface ITalkItem extends IApiTalkItem {}
49

510
export interface ICategoryListItem {

frontend/pages/program/talk-schedule.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import PageTitle from '../../components/core/PageTitle'
66
import { PageProps } from '../../interfaces/PageProps'
77
import { getTalkList } from '../api/program'
88
import { GetServerSidePropsContext } from 'next'
9-
import { ITalkItem, ITalkList } from '../../interfaces/IProgram'
9+
import { ITalkItem, ITalkList, ITalkTableList } from '../../interfaces/IProgram'
1010
import { compareAsc, isSameDay } from 'date-fns'
1111
import TalkTableToggleButton from '../../components/service/Program/TalkTableToggleButton'
1212
import TalkTable from '../../components/service/Program/TalkTable'
@@ -24,6 +24,25 @@ const TalkSchedule: NextPage = (props: TalkTableProps) => {
2424
setSelectedDay(day)
2525
}
2626

27+
const groupByProperty = (
28+
array: ITalkItem[],
29+
property: string
30+
): ITalkTableList[] => {
31+
const groupByValue: { [key: string]: ITalkItem[] } = array.reduce(
32+
(obj, item) => {
33+
obj[item[property]] = obj[item[property]] || []
34+
obj[item[property]].push(item)
35+
return obj
36+
},
37+
{}
38+
)
39+
40+
return Object.keys(groupByValue).map((key: string) => ({
41+
[property]: key,
42+
talkList: groupByValue[key]
43+
}))
44+
}
45+
2746
const tableData: ITalkItem[] = data.list.sort((a, b) =>
2847
compareAsc(new Date(a.video_open_at), new Date(b.video_open_at))
2948
)
@@ -32,7 +51,7 @@ const TalkSchedule: NextPage = (props: TalkTableProps) => {
3251
isSameDay(new Date(item.video_open_at), new Date(2022, 9, 1))
3352
)
3453
const day2tableList: ITalkItem[] = tableData.filter((item) =>
35-
isSameDay(new Date(item.video_open_at), new Date(2022, 10, 1))
54+
isSameDay(new Date(item.video_open_at), new Date(2022, 9, 2))
3655
)
3756

3857
return (
@@ -42,14 +61,14 @@ const TalkSchedule: NextPage = (props: TalkTableProps) => {
4261
{selectedDay === 'day1' ? (
4362
<TalkTable
4463
day="day1"
45-
headers={['트랙1(101)', '트랙2(102)']}
46-
list={day1tableList}
64+
headers={['트랙1', '트랙2']}
65+
list={groupByProperty(day1tableList, 'video_open_at')}
4766
/>
4867
) : (
4968
<TalkTable
5069
day="day2"
51-
headers={['트랙1(103)', '트랙2(104)']}
52-
list={day2tableList}
70+
headers={['트랙1', '트랙2']}
71+
list={groupByProperty(day2tableList, 'video_open_at')}
5372
/>
5473
)}
5574
</div>

0 commit comments

Comments
 (0)