commit a2b61cf2ab5c44abd1963eece22e5d09dad7b0c4
parent 893aafc6ad5f6dbb809881972bdfd168c407350b
Author: Berchtold Samuel <samuel.berchtold@gmail.com>
Date: Wed, 9 Oct 2024 00:06:13 +0200
change low width table design to description tables
Diffstat:
5 files changed, 198 insertions(+), 141 deletions(-)
diff --git a/index.html b/index.html
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="viewport" content="width=device-width" />
<link rel="apple-touch-icon" href="/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
@@ -13,7 +13,7 @@
<title>My Heats</title>
</head>
<body>
- <noscript>You need to enable JavaScript to run this app.</noscript>
+ <noscript>Why You scared of JavaScript so much, failure.</noscript>
<div id="root"></div>
<script type="module" src="/src/frontend/main.jsx"></script>
</body>
diff --git a/src/frontend/App.jsx b/src/frontend/App.jsx
@@ -65,7 +65,7 @@ function Layout() {
}, [])
return (
- <Fragment>
+ <>
<nav className={theme}>
<ul>
<li>
@@ -123,7 +123,7 @@ function Layout() {
}
</span>
</footer>
- </Fragment>
+ </>
)
}
diff --git a/src/frontend/Leaderboard.jsx b/src/frontend/Leaderboard.jsx
@@ -204,46 +204,51 @@ function NewHeatForm(leaderboard, rankingComp, selectHeatRef, selectRankRef, ses
<p>
Create new heat with top N athletes from the sorted leaderboard (<i>* required</i>).
</p>
- <form method='post' onSubmit={e => newHeatFromLeaderboard(
- e,
- leaderboard,
- rankingComp,
- selectHeatRef,
- selectRankRef,
- session,
- )}>
- <table>
- <thead>
- <tr>
- <th>New heat name *</th>
- <th>Location</th>
- <th>Planned start</th>
- <th>Include top N</th>
- <td></td>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td data-title='New heat name *'>
- <input type='text' name='name' />
- </td>
- <td data-title='Location'>
- <input type='text' name='location' />
- </td>
- <td data-title='Planned start'>
- <input
- type='time'
- name='planned_start' />
- </td>
- <td data-title='Include top N'>
- <input type='number' name='size' />
- </td>
- <td>
- <button type='submit'>+ new</button>
- </td>
- </tr>
- </tbody>
- </table>
+ <form
+ method="post"
+ onSubmit={(e) =>
+ newHeatFromLeaderboard(
+ e,
+ leaderboard,
+ rankingComp,
+ selectHeatRef,
+ selectRankRef,
+ session
+ )
+ }
+ >
+ <div className="table-container">
+ <table>
+ <thead>
+ <tr>
+ <th>New heat name *</th>
+ <th>Location</th>
+ <th>Planned start</th>
+ <th>Include top N</th>
+ <td></td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td data-title="New heat name *">
+ <input type="text" name="name" />
+ </td>
+ <td data-title="Location">
+ <input type="text" name="location" />
+ </td>
+ <td data-title="Planned start">
+ <input type="time" name="planned_start" />
+ </td>
+ <td data-title="Include top N">
+ <input type="number" name="size" />
+ </td>
+ <td>
+ <button type="submit">+ new</button>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
</form>
</div>
)
@@ -351,85 +356,130 @@ function Leaderboard({session}) {
}, [heatSelection]);
return (
- <div>
- <div className='Leaderboard'>
+ <>
+ <div className="Leaderboard">
<header>
- <button disabled={!loading} className='loading' >↺ loading</button>
- <button className={`show-details ${details ? 'toggled' : ''}`} onClick={() => showDetails(!details)}>
- <div className='thumb'></div>
- <span>{details ? 'less' : 'more'}</span>
+ <button disabled={!loading} className="loading">
+ ↺ loading
</button>
- <label htmlFor='heat'>Heats to display</label>
+ <button
+ className={`show-details ${details ? "toggled" : ""}`}
+ onClick={() => showDetails(!details)}
+ >
+ <div className="thumb"></div>
+ <span>{details ? "less" : "more"}</span>
+ </button>
+ <label htmlFor="heat">Heats to display</label>
<Select
closeMenuOnSelect={false}
isMulti
options={heatOpts}
- onChange={h => setHeatSelection(h)}
+ onChange={(h) => setHeatSelection(h)}
ref={selectHeatRef}
- id='heat' />
- <label htmlFor='rank' className={details ? '' : 'hidden'}>Rank by</label>
- <Select
+ id="heat"
+ />
+ <label htmlFor="rank" className={details ? "" : "hidden"}>
+ Rank by
+ </label>
+ <Select
closeMenuOnSelect={false}
isMulti
options={rankOpts}
defaultValue={rankOpts[0].options[3]}
- onChange={h => setRankingComp(h)}
+ onChange={(h) => setRankingComp(h)}
ref={selectRankRef}
- className={details ? '' : 'hidden'}
- id='rank' />
+ className={details ? "" : "hidden"}
+ id="rank"
+ />
</header>
- <table className={details ? 'leaderboard' : 'hide-rank'}>
- <thead>
- <tr>
- <th className={details ? 'right' : 'hidden'}>Rank</th>
- <th className='right'>Start Nr.</th>
- <th>Name</th>
- <th className={details ? '' : 'hidden'}>Birthday</th>
- <th className={details ? '' : 'hidden'}>School</th>
- {heatSelection.map(h => (
- <th className={details ? 'right' : 'hidden'} key={h.value}>{h.label}</th>
+ <div className="table-container">
+ <table className={details ? "leaderboard" : "hide-rank"}>
+ <thead>
+ <tr>
+ <th className={details ? "right" : "hidden"}>Rank</th>
+ <th className="right">Start Nr.</th>
+ <th>Name</th>
+ <th className={details ? "" : "hidden"}>Birthday</th>
+ <th className={details ? "" : "hidden"}>School</th>
+ {heatSelection.map((h) => (
+ <th className={details ? "right" : "hidden"} key={h.value}>
+ {h.label}
+ </th>
+ ))}
+ <th className={details ? "right" : "hidden"}>Best</th>
+ <th className={details ? "right" : "hidden"}>Worst</th>
+ <th className="right">Total</th>
+ </tr>
+ </thead>
+ <tbody>
+ {leaderboard.sort(rankByHeat(rankingComp)).map((i) => (
+ <tr key={i.id}>
+ <td className={details ? "right" : "hidden"}></td>
+ <td data-title="Start Nr." className="right">
+ {i.nr}
+ </td>
+ <td data-title="Name">
+ {i.firstname} {i.lastname}
+ </td>
+ <td data-title="Birthday" className={details ? "" : "hidden"}>
+ {i.birthday
+ ? new Date(i.birthday).toLocaleDateString(
+ locale,
+ dateOptions
+ )
+ : ""}
+ </td>
+ <td data-title="School" className={details ? "" : "hidden"}>
+ {i.school}
+ </td>
+ {heatSelection.map((h) => (
+ // list all scores from the judges seperated with '+' signs, show sum on right side
+ <td
+ key={h.value}
+ className={details ? "right" : "hidden"}
+ data-title={h.label}
+ >
+ {formatScores(i, h)}
+ </td>
+ ))}
+ <td
+ className={details ? "right" : "hidden"}
+ data-title="Best"
+ >
+ {i.bestHeat}
+ </td>
+ <td
+ className={details ? "right" : "hidden"}
+ data-title="Worst"
+ >
+ {i.worstHeat}
+ </td>
+ <td className="right total" data-title="Total">
+ {i.sum}
+ </td>
+ </tr>
))}
- <th className={details ? 'right' : 'hidden'}>Best</th>
- <th className={details ? 'right' : 'hidden'}>Worst</th>
- <th className='right'>Total</th>
- </tr>
- </thead>
- <tbody>
- {leaderboard.sort(rankByHeat(rankingComp)).map(i => (
- <tr key={i.id}>
- <td className={details ? 'right' : 'hidden'}></td>
- <td data-title='Start Nr.' className='right'>{i.nr}</td>
- <td data-title='Name'>{i.firstname} {i.lastname}</td>
- <td data-title='Birthday' className={details ? '' : 'hidden'}>
- {i.birthday ? new Date(i.birthday).toLocaleDateString(locale, dateOptions) : ''}
- </td>
- <td data-title='School' className={details ? '' : 'hidden'}>{i.school}</td>
- {heatSelection.map(h => (
- <Fragment key={h.value}>
- {/* list all scores from the judges seperated with '+' signs, show sum on right side */}
- <td className={details ? 'right' : 'hidden'} data-title={h.label}>{formatScores(i, h)}</td>
- </Fragment>
- ))}
- <td className={details ? 'right' : 'hidden'} data-title='Best'>{i.bestHeat}</td>
- <td className={details ? 'right' : 'hidden'} data-title='Worst'>{i.worstHeat}</td>
- <td className='right total' data-title='Total'>{i.sum}</td>
- </tr>
- ))}
- </tbody>
- </table>
+ </tbody>
+ </table>
+ </div>
</div>
<ExportForm
leaderboard={leaderboard}
heatSelection={heatSelection}
- rankingComp={rankingComp} />
- {session.auth ? <NewHeatForm
- leaderboard={leaderboard}
rankingComp={rankingComp}
- selectHeatRef={selectHeatRef}
- selectRankRef={selectRankRef}
- session={session}
- /> : ''}
- </div>
+ />
+ {session.auth ? (
+ <NewHeatForm
+ leaderboard={leaderboard}
+ rankingComp={rankingComp}
+ selectHeatRef={selectHeatRef}
+ selectRankRef={selectRankRef}
+ session={session}
+ />
+ ) : (
+ ""
+ )}
+ </>
)
}
diff --git a/src/frontend/css/App.css b/src/frontend/css/App.css
@@ -99,10 +99,11 @@ footer span button {
}
.loginForm, .exportForm {
- margin: 30px;
+ margin: auto;
+ padding: 3rem;
}
.loginForm button, .loginForm input, .exportForm button {
- width: 250px;
+ width: 100%;
display: block;
}
@@ -125,6 +126,11 @@ footer span button {
padding: 0 20px;
}
+.table-container {
+ padding-top: 1rem;
+ overflow-x: auto;
+}
+
.Scoring ul {
display: flex;
flex-direction: row;
@@ -214,55 +220,50 @@ td.total {
}
/* https://css-tricks.com/making-tables-responsive-with-minimal-css */
-@media(max-width: 1100px) {
+/* Mobile / Small screen styles */
+@media (max-width: 768px) {
+ table.leaderboard {
+ display: block;
+ }
+
table.leaderboard thead {
- left: -9999px;
- position: absolute;
- visibility: hidden;
+ display: none;
}
- table.leaderboard tr {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- padding: 20px 0;
+ table.leaderboard tbody,
+ table.leaderboard tr,
+ table.leaderboard td {
+ display: block;
}
- table.leaderboard tr:not(:last-child) {
- border-bottom: 1px solid #e1e1e7;
+ table.leaderboard tr {
+ padding: 2rem;
}
table.leaderboard td {
- margin: 0 -1px -1px 0;
- padding-top: 35px;
- margin-bottom: 25px;
+ display: flex;
+ padding: 10px;
+ border-bottom: 1px solid #ddd;
position: relative;
- width: 35%;
- text-align: left !important;
}
- table.leaderboard td:before {
- content: attr(data-title);
- position: absolute;
- top: 3px;
- left: 20px;
+ table.leaderboard:not(.hide-rank) tr td:first-child::before {
+ content: counter(rowNumber) ". Rank";
+ }
+
+ table.leaderboard td[data-title]:before {
+ content: attr(data-title) ": ";
+ display: inline-block;
+ width: 50%;
+ padding-right: 1rem;
+ text-align: right;
+ align-content: center;
font-size: 0.8em;
text-transform: uppercase;
color: #b0b0b6;
}
- table.leaderboard td:nth-child(-n+6) {
- /* background: rgb(236, 236, 236); */
- }
-
- table td button {
- position: absolute;
- bottom: 0;
- height: 50px;
- width: 100%;
- }
-
- table td:empty {
- display: none;
+ table.leaderboard tr {
+ border-bottom: 1px solid #ddd;
}
}
diff --git a/src/frontend/css/index.css b/src/frontend/css/index.css
@@ -1,8 +1,13 @@
* {
padding: 0;
margin: 0;
+ box-sizing: border-box;
font-family: monospace;
- font-size: 18px;
+ font-size: 1.125rem;
+}
+
+html, body {
+ height: 100%;
}
a {
@@ -21,6 +26,7 @@ button, input {
background: white;
border: 1px solid #f3f2f7;
color: black;
+ white-space: nowrap;
}
button {