|
1 | | -import { cn } from '@bcsdlab/utils'; |
2 | | -import { useSuspenseQuery } from '@tanstack/react-query'; |
3 | | -import { coopshopQueries } from 'api/coopshop/queries'; |
4 | | -import Book from 'components/CampusInfo/svg/book.svg'; |
5 | | -import Cafe from 'components/CampusInfo/svg/cafe.svg'; |
6 | | -import Cut from 'components/CampusInfo/svg/cut.svg'; |
7 | | -import Flatware from 'components/CampusInfo/svg/flatware.svg'; |
8 | | -import Glasses from 'components/CampusInfo/svg/glasses.svg'; |
9 | | -import Laundry from 'components/CampusInfo/svg/laundry.svg'; |
10 | | -import PostOffice from 'components/CampusInfo/svg/post-office.svg'; |
11 | | -import Print from 'components/CampusInfo/svg/print.svg'; |
12 | | -import styles from './CampusInfo.module.scss'; |
13 | | - |
14 | | -const CAFETERIA_HEAD_TABLE = { |
15 | | - row: ['평일', '주말'], |
16 | | - col: ['아침', '점심', '저녁'], |
17 | | -}; |
18 | | - |
19 | | -const SHOP_ICON = { |
20 | | - 서점: <Book />, |
21 | | - 대즐: <Cafe />, |
22 | | - 미용실: <Cut />, |
23 | | - 세탁소: <Laundry />, |
24 | | - 우체국: <PostOffice />, |
25 | | - '복지관 참빛관 편의점': <Cafe />, |
26 | | - 복사실: <Print />, |
27 | | - 학생식당: <Flatware />, |
28 | | - 복지관식당: <Flatware />, |
29 | | - 오락실: <Cafe />, |
30 | | - 안경원: <Glasses />, |
31 | | - 우편취급국: <PostOffice />, |
32 | | -}; |
33 | | - |
34 | | -const formatDateRange = (fromDate: string, toDate: string) => { |
35 | | - const from = new Date(fromDate); |
36 | | - const to = new Date(toDate); |
37 | | - |
38 | | - const options: Intl.DateTimeFormatOptions = { |
39 | | - year: 'numeric', |
40 | | - month: 'long', |
41 | | - day: 'numeric', |
42 | | - }; |
43 | | - |
44 | | - const fromFormatted = from.toLocaleDateString('ko-KR', options); |
45 | | - let toFormatted = to.toLocaleDateString('ko-KR', options); |
46 | | - |
47 | | - if (from.getFullYear() === to.getFullYear()) { |
48 | | - const toOptions: Intl.DateTimeFormatOptions = { |
49 | | - month: 'long', |
50 | | - day: 'numeric', |
51 | | - }; |
52 | | - |
53 | | - toFormatted = to.toLocaleDateString('ko-KR', toOptions); |
54 | | - } |
55 | | - |
56 | | - return `기간 : ${fromFormatted} - ${toFormatted}`; |
57 | | -}; |
58 | | - |
59 | | -function CampusInfo() { |
60 | | - const { data: campusInfo } = useSuspenseQuery(coopshopQueries.allShopInfo()); |
61 | | - |
62 | | - const cafeteriaInfo = campusInfo?.coop_shops.find((shop) => shop.name === '학생식당'); |
63 | | - const filteredCampusInfo = campusInfo?.coop_shops.filter((shop) => shop.name !== '학생식당'); |
64 | | - |
65 | | - const getFormattedShopTime = (open: string, close: string) => { |
66 | | - if (open === close) { |
67 | | - return open; |
68 | | - } |
69 | | - |
70 | | - return `${open} - ${close}`; |
71 | | - }; |
72 | | - |
73 | | - const getTimeToTypeAndDay = (type: string, day: string) => { |
74 | | - const target = cafeteriaInfo?.opens?.find((open) => open.day_of_week === day && open.type === type); |
75 | | - |
76 | | - return target ? getFormattedShopTime(target.open_time, target.close_time) : '미운영'; |
77 | | - }; |
78 | | - |
79 | | - return ( |
80 | | - <div className={styles.container}> |
81 | | - <div className={styles['title-container']}> |
82 | | - <h2 className={styles.title}>{`${campusInfo.semester} 시설물 운영 시간`}</h2> |
83 | | - <div className={styles.subtitle}>{formatDateRange(campusInfo.from_date, campusInfo.to_date)}</div> |
84 | | - </div> |
85 | | - <section className={styles['info-container']}> |
86 | | - <div className={styles['info-column']}> |
87 | | - <div className={styles['info-block']}> |
88 | | - <div className={styles['info-cafeteria']}> |
89 | | - <div className={styles['info-title-container']}> |
90 | | - <div className={styles['icon-wrapper']}> |
91 | | - <Flatware /> |
92 | | - </div> |
93 | | - <div className={styles['info-title']}>학생식당</div> |
94 | | - </div> |
95 | | - <table className={styles.table}> |
96 | | - <thead> |
97 | | - <tr className={styles['table-head__tr']}> |
98 | | - <th>시간</th> |
99 | | - {CAFETERIA_HEAD_TABLE.row.map((type) => ( |
100 | | - <th className={styles['table-head__th']} key={type}> |
101 | | - {type} |
102 | | - </th> |
103 | | - ))} |
104 | | - </tr> |
105 | | - </thead> |
106 | | - <tbody> |
107 | | - {CAFETERIA_HEAD_TABLE.col.map((type) => ( |
108 | | - <tr className={styles['table-body__tr']} key={type}> |
109 | | - <td className={styles['table-body__td']}>{type}</td> |
110 | | - {CAFETERIA_HEAD_TABLE.row.map((day) => ( |
111 | | - <td |
112 | | - className={cn({ |
113 | | - [styles['table-body__td']]: true, |
114 | | - [styles.closed]: getTimeToTypeAndDay(type, day) === '미운영', |
115 | | - })} |
116 | | - key={`${type}-${day}`} |
117 | | - > |
118 | | - {getTimeToTypeAndDay(type, day)} |
119 | | - </td> |
120 | | - ))} |
121 | | - </tr> |
122 | | - ))} |
123 | | - </tbody> |
124 | | - </table> |
125 | | - </div> |
126 | | - </div> |
127 | | - |
128 | | - {filteredCampusInfo.slice(0, 2).map(({ id, name, opens }) => ( |
129 | | - <div className={styles['info-block']} key={id}> |
130 | | - <div className={styles['icon-wrapper']}>{SHOP_ICON[name as keyof typeof SHOP_ICON]}</div> |
131 | | - <div className={styles['info-description-container']}> |
132 | | - <div className={styles['info-title']}>{name}</div> |
133 | | - {opens.map(({ day_of_week, open_time, close_time }) => ( |
134 | | - <div |
135 | | - className={styles['info-description']} |
136 | | - key={`${id}-${day_of_week}`} |
137 | | - >{`${day_of_week}: ${getFormattedShopTime(open_time, close_time)}`}</div> |
138 | | - ))} |
139 | | - </div> |
140 | | - </div> |
141 | | - ))} |
142 | | - </div> |
143 | | - <div className={styles['info-column']}> |
144 | | - {filteredCampusInfo.slice(2, 6).map(({ id, name, opens }) => ( |
145 | | - <div className={styles['info-block']} key={id}> |
146 | | - <div className={styles['icon-wrapper']}>{SHOP_ICON[name as keyof typeof SHOP_ICON]}</div> |
147 | | - <div className={styles['info-description-container']}> |
148 | | - <div className={styles['info-title']}>{name}</div> |
149 | | - {opens.map(({ day_of_week, open_time, close_time }) => ( |
150 | | - <div |
151 | | - className={styles['info-description']} |
152 | | - key={`${id}-${day_of_week}`} |
153 | | - >{`${day_of_week}: ${getFormattedShopTime(open_time, close_time)}`}</div> |
154 | | - ))} |
155 | | - </div> |
156 | | - </div> |
157 | | - ))} |
158 | | - </div> |
159 | | - <div className={styles['info-column']}> |
160 | | - {filteredCampusInfo.slice(6).map(({ id, name, opens }) => ( |
161 | | - <div className={styles['info-block']} key={id}> |
162 | | - <div className={styles['icon-wrapper']}>{SHOP_ICON[name as keyof typeof SHOP_ICON]}</div> |
163 | | - <div className={styles['info-description-container']}> |
164 | | - <div className={styles['info-title']}>{name}</div> |
165 | | - {opens.map(({ day_of_week, open_time, close_time }) => ( |
166 | | - <div |
167 | | - className={styles['info-description']} |
168 | | - key={`${id}-${day_of_week}`} |
169 | | - >{`${day_of_week}: ${getFormattedShopTime(open_time, close_time)}`}</div> |
170 | | - ))} |
171 | | - </div> |
172 | | - </div> |
173 | | - ))} |
174 | | - </div> |
175 | | - </section> |
176 | | - </div> |
177 | | - ); |
178 | | -} |
179 | | - |
180 | | -export default CampusInfo; |
| 1 | +export { default } from 'components/CampusInfo'; |
0 commit comments