Logs
Patchsets
Patchset ps-2
change low width table design to description tables
Berchtold Samuel
index.html
+2
-2
src/frontend/App.jsx
+2
-2
src/frontend/Leaderboard.jsx
+150
-100
src/frontend/css/App.css
+37
-36
change low width table design to description tables
index.html
+2
-2
1diff --git a/index.html b/index.html
2index 05d71f0..3d94e61 100644
3--- a/index.html
4+++ b/index.html
5@@ -3,7 +3,7 @@
6 <head>
7 <meta charset="UTF-8" />
8 <link rel="icon" type="image/x-icon" href="/favicon.ico" />
9- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
10+ <meta name="viewport" content="width=device-width" />
11 <link rel="apple-touch-icon" href="/logo192.png" />
12 <!--
13 manifest.json provides metadata used when your web app is installed on a
14@@ -13,7 +13,7 @@
15 <title>My Heats</title>
16 </head>
17 <body>
18- <noscript>You need to enable JavaScript to run this app.</noscript>
19+ <noscript>Why You scared of JavaScript so much, failure.</noscript>
20 <div id="root"></div>
21 <script type="module" src="/src/frontend/main.jsx"></script>
22 </body>
src/frontend/App.jsx
+2
-2
1diff --git a/src/frontend/App.jsx b/src/frontend/App.jsx
2index b8f6357..1ef94c4 100644
3--- a/src/frontend/App.jsx
4+++ b/src/frontend/App.jsx
5@@ -65,7 +65,7 @@ function Layout() {
6 }, [])
7
8 return (
9- <Fragment>
10+ <>
11 <nav className={theme}>
12 <ul>
13 <li>
14@@ -123,7 +123,7 @@ function Layout() {
15 }
16 </span>
17 </footer>
18- </Fragment>
19+ </>
20 )
21 }
22
src/frontend/Leaderboard.jsx
+150
-100
1diff --git a/src/frontend/Leaderboard.jsx b/src/frontend/Leaderboard.jsx
2index 1e44ddc..b345b12 100644
3--- a/src/frontend/Leaderboard.jsx
4+++ b/src/frontend/Leaderboard.jsx
5@@ -204,46 +204,51 @@ function NewHeatForm(leaderboard, rankingComp, selectHeatRef, selectRankRef, ses
6 <p>
7 Create new heat with top N athletes from the sorted leaderboard (<i>* required</i>).
8 </p>
9- <form method='post' onSubmit={e => newHeatFromLeaderboard(
10- e,
11- leaderboard,
12- rankingComp,
13- selectHeatRef,
14- selectRankRef,
15- session,
16- )}>
17- <table>
18- <thead>
19- <tr>
20- <th>New heat name *</th>
21- <th>Location</th>
22- <th>Planned start</th>
23- <th>Include top N</th>
24- <td></td>
25- </tr>
26- </thead>
27- <tbody>
28- <tr>
29- <td data-title='New heat name *'>
30- <input type='text' name='name' />
31- </td>
32- <td data-title='Location'>
33- <input type='text' name='location' />
34- </td>
35- <td data-title='Planned start'>
36- <input
37- type='time'
38- name='planned_start' />
39- </td>
40- <td data-title='Include top N'>
41- <input type='number' name='size' />
42- </td>
43- <td>
44- <button type='submit'>+ new</button>
45- </td>
46- </tr>
47- </tbody>
48- </table>
49+ <form
50+ method="post"
51+ onSubmit={(e) =>
52+ newHeatFromLeaderboard(
53+ e,
54+ leaderboard,
55+ rankingComp,
56+ selectHeatRef,
57+ selectRankRef,
58+ session
59+ )
60+ }
61+ >
62+ <div className="table-container">
63+ <table>
64+ <thead>
65+ <tr>
66+ <th>New heat name *</th>
67+ <th>Location</th>
68+ <th>Planned start</th>
69+ <th>Include top N</th>
70+ <td></td>
71+ </tr>
72+ </thead>
73+ <tbody>
74+ <tr>
75+ <td data-title="New heat name *">
76+ <input type="text" name="name" />
77+ </td>
78+ <td data-title="Location">
79+ <input type="text" name="location" />
80+ </td>
81+ <td data-title="Planned start">
82+ <input type="time" name="planned_start" />
83+ </td>
84+ <td data-title="Include top N">
85+ <input type="number" name="size" />
86+ </td>
87+ <td>
88+ <button type="submit">+ new</button>
89+ </td>
90+ </tr>
91+ </tbody>
92+ </table>
93+ </div>
94 </form>
95 </div>
96 )
97@@ -351,85 +356,130 @@ function Leaderboard({session}) {
98 }, [heatSelection]);
99
100 return (
101- <div>
102- <div className='Leaderboard'>
103+ <>
104+ <div className="Leaderboard">
105 <header>
106- <button disabled={!loading} className='loading' >↺ loading</button>
107- <button className={`show-details ${details ? 'toggled' : ''}`} onClick={() => showDetails(!details)}>
108- <div className='thumb'></div>
109- <span>{details ? 'less' : 'more'}</span>
110+ <button disabled={!loading} className="loading">
111+ ↺ loading
112 </button>
113- <label htmlFor='heat'>Heats to display</label>
114+ <button
115+ className={`show-details ${details ? "toggled" : ""}`}
116+ onClick={() => showDetails(!details)}
117+ >
118+ <div className="thumb"></div>
119+ <span>{details ? "less" : "more"}</span>
120+ </button>
121+ <label htmlFor="heat">Heats to display</label>
122 <Select
123 closeMenuOnSelect={false}
124 isMulti
125 options={heatOpts}
126- onChange={h => setHeatSelection(h)}
127+ onChange={(h) => setHeatSelection(h)}
128 ref={selectHeatRef}
129- id='heat' />
130- <label htmlFor='rank' className={details ? '' : 'hidden'}>Rank by</label>
131- <Select
132+ id="heat"
133+ />
134+ <label htmlFor="rank" className={details ? "" : "hidden"}>
135+ Rank by
136+ </label>
137+ <Select
138 closeMenuOnSelect={false}
139 isMulti
140 options={rankOpts}
141 defaultValue={rankOpts[0].options[3]}
142- onChange={h => setRankingComp(h)}
143+ onChange={(h) => setRankingComp(h)}
144 ref={selectRankRef}
145- className={details ? '' : 'hidden'}
146- id='rank' />
147+ className={details ? "" : "hidden"}
148+ id="rank"
149+ />
150 </header>
151- <table className={details ? 'leaderboard' : 'hide-rank'}>
152- <thead>
153- <tr>
154- <th className={details ? 'right' : 'hidden'}>Rank</th>
155- <th className='right'>Start Nr.</th>
156- <th>Name</th>
157- <th className={details ? '' : 'hidden'}>Birthday</th>
158- <th className={details ? '' : 'hidden'}>School</th>
159- {heatSelection.map(h => (
160- <th className={details ? 'right' : 'hidden'} key={h.value}>{h.label}</th>
161+ <div className="table-container">
162+ <table className={details ? "leaderboard" : "hide-rank"}>
163+ <thead>
164+ <tr>
165+ <th className={details ? "right" : "hidden"}>Rank</th>
166+ <th className="right">Start Nr.</th>
167+ <th>Name</th>
168+ <th className={details ? "" : "hidden"}>Birthday</th>
169+ <th className={details ? "" : "hidden"}>School</th>
170+ {heatSelection.map((h) => (
171+ <th className={details ? "right" : "hidden"} key={h.value}>
172+ {h.label}
173+ </th>
174+ ))}
175+ <th className={details ? "right" : "hidden"}>Best</th>
176+ <th className={details ? "right" : "hidden"}>Worst</th>
177+ <th className="right">Total</th>
178+ </tr>
179+ </thead>
180+ <tbody>
181+ {leaderboard.sort(rankByHeat(rankingComp)).map((i) => (
182+ <tr key={i.id}>
183+ <td className={details ? "right" : "hidden"}></td>
184+ <td data-title="Start Nr." className="right">
185+ {i.nr}
186+ </td>
187+ <td data-title="Name">
188+ {i.firstname} {i.lastname}
189+ </td>
190+ <td data-title="Birthday" className={details ? "" : "hidden"}>
191+ {i.birthday
192+ ? new Date(i.birthday).toLocaleDateString(
193+ locale,
194+ dateOptions
195+ )
196+ : ""}
197+ </td>
198+ <td data-title="School" className={details ? "" : "hidden"}>
199+ {i.school}
200+ </td>
201+ {heatSelection.map((h) => (
202+ // list all scores from the judges seperated with '+' signs, show sum on right side
203+ <td
204+ key={h.value}
205+ className={details ? "right" : "hidden"}
206+ data-title={h.label}
207+ >
208+ {formatScores(i, h)}
209+ </td>
210+ ))}
211+ <td
212+ className={details ? "right" : "hidden"}
213+ data-title="Best"
214+ >
215+ {i.bestHeat}
216+ </td>
217+ <td
218+ className={details ? "right" : "hidden"}
219+ data-title="Worst"
220+ >
221+ {i.worstHeat}
222+ </td>
223+ <td className="right total" data-title="Total">
224+ {i.sum}
225+ </td>
226+ </tr>
227 ))}
228- <th className={details ? 'right' : 'hidden'}>Best</th>
229- <th className={details ? 'right' : 'hidden'}>Worst</th>
230- <th className='right'>Total</th>
231- </tr>
232- </thead>
233- <tbody>
234- {leaderboard.sort(rankByHeat(rankingComp)).map(i => (
235- <tr key={i.id}>
236- <td className={details ? 'right' : 'hidden'}></td>
237- <td data-title='Start Nr.' className='right'>{i.nr}</td>
238- <td data-title='Name'>{i.firstname} {i.lastname}</td>
239- <td data-title='Birthday' className={details ? '' : 'hidden'}>
240- {i.birthday ? new Date(i.birthday).toLocaleDateString(locale, dateOptions) : ''}
241- </td>
242- <td data-title='School' className={details ? '' : 'hidden'}>{i.school}</td>
243- {heatSelection.map(h => (
244- <Fragment key={h.value}>
245- {/* list all scores from the judges seperated with '+' signs, show sum on right side */}
246- <td className={details ? 'right' : 'hidden'} data-title={h.label}>{formatScores(i, h)}</td>
247- </Fragment>
248- ))}
249- <td className={details ? 'right' : 'hidden'} data-title='Best'>{i.bestHeat}</td>
250- <td className={details ? 'right' : 'hidden'} data-title='Worst'>{i.worstHeat}</td>
251- <td className='right total' data-title='Total'>{i.sum}</td>
252- </tr>
253- ))}
254- </tbody>
255- </table>
256+ </tbody>
257+ </table>
258+ </div>
259 </div>
260 <ExportForm
261 leaderboard={leaderboard}
262 heatSelection={heatSelection}
263- rankingComp={rankingComp} />
264- {session.auth ? <NewHeatForm
265- leaderboard={leaderboard}
266 rankingComp={rankingComp}
267- selectHeatRef={selectHeatRef}
268- selectRankRef={selectRankRef}
269- session={session}
270- /> : ''}
271- </div>
272+ />
273+ {session.auth ? (
274+ <NewHeatForm
275+ leaderboard={leaderboard}
276+ rankingComp={rankingComp}
277+ selectHeatRef={selectHeatRef}
278+ selectRankRef={selectRankRef}
279+ session={session}
280+ />
281+ ) : (
282+ ""
283+ )}
284+ </>
285 )
286 }
287
src/frontend/css/App.css
+37
-36
1diff --git a/src/frontend/css/App.css b/src/frontend/css/App.css
2index ba26e36..ad1fc99 100644
3--- a/src/frontend/css/App.css
4+++ b/src/frontend/css/App.css
5@@ -99,10 +99,11 @@ footer span button {
6 }
7
8 .loginForm, .exportForm {
9- margin: 30px;
10+ margin: auto;
11+ padding: 3rem;
12 }
13 .loginForm button, .loginForm input, .exportForm button {
14- width: 250px;
15+ width: 100%;
16 display: block;
17 }
18
19@@ -125,6 +126,11 @@ footer span button {
20 padding: 0 20px;
21 }
22
23+.table-container {
24+ padding-top: 1rem;
25+ overflow-x: auto;
26+}
27+
28 .Scoring ul {
29 display: flex;
30 flex-direction: row;
31@@ -214,55 +220,50 @@ td.total {
32 }
33
34 /* https://css-tricks.com/making-tables-responsive-with-minimal-css */
35-@media(max-width: 1100px) {
36+/* Mobile / Small screen styles */
37+@media (max-width: 768px) {
38+ table.leaderboard {
39+ display: block;
40+ }
41+
42 table.leaderboard thead {
43- left: -9999px;
44- position: absolute;
45- visibility: hidden;
46+ display: none;
47 }
48
49- table.leaderboard tr {
50- display: flex;
51- flex-direction: row;
52- flex-wrap: wrap;
53- padding: 20px 0;
54+ table.leaderboard tbody,
55+ table.leaderboard tr,
56+ table.leaderboard td {
57+ display: block;
58 }
59
60- table.leaderboard tr:not(:last-child) {
61- border-bottom: 1px solid #e1e1e7;
62+ table.leaderboard tr {
63+ padding: 2rem;
64 }
65
66 table.leaderboard td {
67- margin: 0 -1px -1px 0;
68- padding-top: 35px;
69- margin-bottom: 25px;
70+ display: flex;
71+ padding: 10px;
72+ border-bottom: 1px solid #ddd;
73 position: relative;
74- width: 35%;
75- text-align: left !important;
76 }
77
78- table.leaderboard td:before {
79- content: attr(data-title);
80- position: absolute;
81- top: 3px;
82- left: 20px;
83+ table.leaderboard:not(.hide-rank) tr td:first-child::before {
84+ content: counter(rowNumber) ". Rank";
85+ }
86+
87+ table.leaderboard td[data-title]:before {
88+ content: attr(data-title) ": ";
89+ display: inline-block;
90+ width: 50%;
91+ padding-right: 1rem;
92+ text-align: right;
93+ align-content: center;
94 font-size: 0.8em;
95 text-transform: uppercase;
96 color: #b0b0b6;
97 }
98
99- table.leaderboard td:nth-child(-n+6) {
100- /* background: rgb(236, 236, 236); */
101- }
102-
103- table td button {
104- position: absolute;
105- bottom: 0;
106- height: 50px;
107- width: 100%;
108- }
109-
110- table td:empty {
111- display: none;
112+ table.leaderboard tr {
113+ border-bottom: 1px solid #ddd;
114 }
115 }
1diff --git a/src/frontend/css/index.css b/src/frontend/css/index.css
2index ae40ae5..59eaa31 100644
3--- a/src/frontend/css/index.css
4+++ b/src/frontend/css/index.css
5@@ -1,8 +1,13 @@
6 * {
7 padding: 0;
8 margin: 0;
9+ box-sizing: border-box;
10 font-family: monospace;
11- font-size: 18px;
12+ font-size: 1.125rem;
13+}
14+
15+html, body {
16+ height: 100%;
17 }
18
19 a {
20@@ -21,6 +26,7 @@ button, input {
21 background: white;
22 border: 1px solid #f3f2f7;
23 color: black;
24+ white-space: nowrap;
25 }
26
27 button {