|
6 | 6 | import {sort} from "fast-sort";
|
7 | 7 | import Scrolling from "$lib/Scrolling.svelte";
|
8 | 8 | import Other from "$lib/Other.svelte";
|
| 9 | + import {locale, str} from "$lib"; |
9 | 10 |
|
10 | 11 | export let list = [], favorites = [], deptMap = {}, hover, selected, mobile, year, term, timeSegments, selTime,
|
11 | 12 | detail, hideTerm, compete;
|
12 | 13 |
|
13 |
| - const types = [ |
| 14 | + $: types = $locale === 'ko' ? [ |
14 | 15 | "기초필수",
|
15 | 16 | "기초선택",
|
16 | 17 | "전공필수",
|
|
19 | 20 | "인문사회선택",
|
20 | 21 | "공통필수",
|
21 | 22 | "자유선택",
|
22 |
| - ]; |
| 23 | + ] : [ |
| 24 | + "Basic Required", |
| 25 | + "Basic Elective", |
| 26 | + "Major Required", |
| 27 | + "Major Elective", |
| 28 | + "Mandatory General Courses", |
| 29 | + "Humanities & Social Elective", |
| 30 | + "General Required", |
| 31 | + "Other Elective", |
| 32 | + ] |
23 | 33 | let page = 1, search = '', dept, deptList = [], type = null;
|
24 | 34 |
|
25 | 35 | $: _list = sort(list.map(i => ({
|
|
64 | 74 |
|
65 | 75 | let way = 0
|
66 | 76 | $: if (way >= 4) way = 0
|
| 77 | +
|
| 78 | +
|
| 79 | + $: l = str[$locale] |
67 | 80 | </script>
|
68 | 81 |
|
69 | 82 | <div style="position: sticky;top: 0px;background:var(--surface);z-index: 10;padding-top: 12px">
|
70 | 83 | <header>
|
71 | 84 | {#if year && !hideTerm}
|
72 | 85 | <div class="item">
|
73 |
| - <Select bind:selected={year} placeholder="년도" {mobile}> |
| 86 | + <Select bind:selected={year} placeholder={l['YEAR']} {mobile}> |
74 | 87 | {#each Array.from({length: 12}, (_, i) => 2024 - i) as y}
|
75 | 88 | <Option title={y} data={y}/>
|
76 | 89 | {/each}
|
77 | 90 | </Select>
|
78 | 91 | </div>
|
79 | 92 | <div class="item">
|
80 |
| - <Select bind:selected={term} placeholder="학기" {mobile}> |
81 |
| - <Option title="봄" data={1}/> |
82 |
| - <Option title="여름" data={2}/> |
83 |
| - <Option title="가을" data={3}/> |
84 |
| - <Option title="겨울" data={4}/> |
| 93 | + <Select bind:selected={term} placeholder={l['TERM']} {mobile}> |
| 94 | + <Option title={l['SPRING']} data={1}/> |
| 95 | + <Option title={l['SUMMER']} data={2}/> |
| 96 | + <Option title={l['FALL']} data={3}/> |
| 97 | + <Option title={l['WINTER']} data={4}/> |
85 | 98 | </Select>
|
86 | 99 | </div>
|
87 | 100 | {/if}
|
88 | 101 | <div style="flex: 1;min-width: 160px">
|
89 |
| - <Input bind:value={search} placeholder="검색" fullWidth/> |
| 102 | + <Input bind:value={search} placeholder={l['SEARCH']} fullWidth/> |
90 | 103 | </div>
|
91 | 104 | <div class="item" style="flex: 1">
|
92 |
| - <Select bind:selected={dept} placeholder="학과" {mobile} fullWidth> |
| 105 | + <Select bind:selected={dept} placeholder={l['DEPT']} {mobile} fullWidth> |
93 | 106 | <main on:wheel|stopPropagation|passive on:touchmove|stopPropagation|passive
|
94 | 107 | on:touchdown|stopPropagation|passive style="max-height: 80vh">
|
95 |
| - <Option title="전체" data={null}/> |
| 108 | + <Option title={l['ALL']} data={null}/> |
96 | 109 | {#each deptList as dept}
|
97 | 110 | <Option title={deptMap[dept]} data={dept}/>
|
98 | 111 | {/each}
|
99 | 112 | </main>
|
100 | 113 | </Select>
|
101 | 114 | </div>
|
102 | 115 | <div class="item" style="flex: 0.6">
|
103 |
| - <Select bind:selected={type} placeholder="유형" {mobile} style="max-height: 80vh;min-width: 100px" fullWidth> |
| 116 | + <Select bind:selected={type} placeholder={l['TYPE']} {mobile} style="max-height: 80vh;min-width: 100px" fullWidth> |
104 | 117 | <main on:wheel|stopPropagation|passive>
|
105 |
| - <Option title="전체" data={null}/> |
| 118 | + <Option title={l['ALL']} data={null}/> |
106 | 119 | {#each types as type}
|
107 | 120 | <Option title={type} data={type}/>
|
108 | 121 | {/each}
|
|
121 | 134 | <div style="margin: -8px 0 6px 0;display: flex;align-items: center">
|
122 | 135 | <Paper left xstack bottom>
|
123 | 136 | <Button small outlined icon="timer" slot="target"
|
124 |
| - round>{!selTime ? '전체' : ['월', '화', '수', '목', '금'][+selTime[0]] + tForm}</Button> |
| 137 | + round>{!selTime ? l['ALL'] : [l['MON'], l['TUE'], l['WED'], l['THU'], l['FRI'], l['SAT'], l['SUN']][+selTime[0]] + tForm}</Button> |
125 | 138 | <List>
|
126 | 139 | {#each [0, 1, 2, 3, 4] as date}
|
127 | 140 | {#each timeSegments as [s, e]}
|
|
130 | 143 | {@const eh = Math.floor(e / 60)}
|
131 | 144 | {@const em = (e % 60).toString().padStart(2, '0')}
|
132 | 145 | {@const key = `${date}-${s}`}
|
133 |
| - <OneLine title="{['월', '화', '수', '목', '금'][date]} {sh}:{sm} - {eh}:{em}" |
| 146 | + <OneLine title="{[l['MON'], l['TUE'], l['WED'], l['THU'], l['FRI'], l['SAT'], l['SUN']][date]} {sh}:{sm} - {eh}:{em}" |
134 | 147 | on:click={() => selTime = (selTime === key ? null : key)}
|
135 | 148 | active={selTime === key}/>
|
136 | 149 | {/each}
|
137 | 150 | {/each}
|
138 | 151 | </List>
|
139 | 152 | </Paper>
|
140 | 153 | <Button outlined round icon={way %2 ? "arrow_downward" : "arrow_upward"} small style="margin-left: 4px"
|
141 |
| - on:click={() => way++}>{['과목코드', '과목코드', '경쟁률', '경쟁률'][way]}</Button> |
| 154 | + on:click={() => way++}>{[l['CODE'], l['CODE'], l['COMPETITIVE'], l['COMPETITIVE']][way]}</Button> |
142 | 155 | </div>
|
143 | 156 | </Paginator>
|
144 | 157 | </div>
|
|
148 | 161 | {:else}
|
149 | 162 | <Table minWidth="900">
|
150 | 163 | <tr>
|
151 |
| - <Th width="3.2">학과</Th> |
152 |
| - <Th width="1.8">학점</Th> |
153 |
| - <Th width="3.6">코드</Th> |
154 |
| - <Th width="2.4">교수</Th> |
155 |
| - <Th width="6">과목 이름</Th> |
156 |
| - <Th width="4.4">수업 시간</Th> |
| 164 | + <Th width="3.2">{l['DEPT']}</Th> |
| 165 | + <Th width="1.8">{l['CREDIT']}</Th> |
| 166 | + <Th width="3.6">{l['CODE']}</Th> |
| 167 | + <Th width="2.4">{l['PROF']}</Th> |
| 168 | + <Th width="6">{l['NAME']}</Th> |
| 169 | + <Th width="4.4">{l['TIME']}</Th> |
157 | 170 | {#if compete}
|
158 |
| - <Th width="4.2">경쟁률</Th> |
| 171 | + <Th width="4.2">{l['COMPETITIVE']}</Th> |
159 | 172 | {/if}
|
160 |
| - <Th width="2.7">유형</Th> |
161 |
| - <Th width="3.8">실라버스/OTL</Th> |
| 173 | + <Th width="2.7">{l['TYPE']}</Th> |
| 174 | + <Th width="3.8">{l['SYLLABUS']}/OTL</Th> |
162 | 175 | </tr>
|
163 | 176 | {#each [...favorites, ...selected, ..._list.slice((page - 1) * itemPerPage, page * itemPerPage).filter(i => !selected.includes(i))] as lect, i}
|
164 | 177 | {@const background = i < favorites.length ? 'var(--primary-light6)' : (selected.includes(lect) ? 'var(--secondary-light6)' : '')}
|
|
201 | 214 | <TableTd data={lect} bind:hover on:choose {background}>
|
202 | 215 | {#each lect.time as time}
|
203 | 216 | <p>
|
204 |
| - {['월', '화', '수', '목', '금', '토', '일'][time.date]} |
| 217 | + {[l['MON'], l['TUE'], l['WED'], l['THU'], l['FRI'], l['SAT'], l['SUN']][time.date]} |
205 | 218 | {`${time.sh}:${time.sm.toString().padStart(2, '0')} - ${time.eh}:${time.em.toString().padStart(2, '0')}`}
|
206 | 219 | </p>
|
207 | 220 | {/each}
|
|
224 | 237 | {#if lect.kcode}
|
225 | 238 | <a href="https://cais.kaist.ac.kr/syllabusInfo?year={year}&term={term}&subject_no={lect.kcode}&dept_id={lect.dept}&lecture_class={lect.group}"
|
226 | 239 | target="_blank" on:click|stopPropagation>
|
227 |
| - <IconButton description size="18" tooltip="실라버스" right xstack bottom/> |
| 240 | + <IconButton description size="18" tooltip={l['SYLLABUS']} right xstack bottom/> |
228 | 241 | </a>
|
229 | 242 | {/if}
|
230 | 243 | {#if otlMap(lect.code)}
|
|
0 commit comments