design changes, refactor
This commit is contained in:
parent
356cd757f4
commit
4a00eeb3a4
4
pom.xml
4
pom.xml
@ -3,7 +3,7 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.darts.stats</groupId>
|
||||
<groupId>cz.kamma.darts</groupId>
|
||||
<artifactId>darts-stats-web</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
</descriptorRefs>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.darts.stats.App</mainClass>
|
||||
<mainClass>cz.kamma.darts.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.darts.stats;
|
||||
package cz.kamma.darts;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.darts.stats;
|
||||
package cz.kamma.darts;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.darts.stats;
|
||||
package cz.kamma.darts;
|
||||
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
@ -16,6 +16,13 @@ public class RawGame {
|
||||
private List<RawThrow> throwsList;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class RawPlayerThrow {
|
||||
private int value;
|
||||
private boolean isBust;
|
||||
private String label;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class RawThrow {
|
||||
private int value;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.darts.stats;
|
||||
package cz.kamma.darts;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -7,12 +7,13 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>
|
||||
:root {
|
||||
--primary: #2563eb;
|
||||
--bg: #f8fafc;
|
||||
--card-bg: #ffffff;
|
||||
--text-main: #1e293b;
|
||||
--text-muted: #64748b;
|
||||
--border: #e2e8f0;
|
||||
--primary: #22c55e; /* Green */
|
||||
--primary-hover: #16a34a;
|
||||
--bg: #0f172a; /* Dark slate */
|
||||
--card-bg: #1e293b;
|
||||
--text-main: #f8fafc;
|
||||
--text-muted: #94a3b8;
|
||||
--border: #334155;
|
||||
}
|
||||
body {
|
||||
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
@ -23,13 +24,13 @@
|
||||
line-height: 1.5;
|
||||
}
|
||||
.container { max-width: 1200px; margin: auto; }
|
||||
h1 { font-size: 2rem; font-weight: 800; margin-bottom: 2rem; display: flex; align-items: center; gap: 10px; }
|
||||
h1 { font-size: 2rem; font-weight: 800; margin-bottom: 2rem; display: flex; align-items: center; gap: 10px; color: var(--primary); }
|
||||
|
||||
.card {
|
||||
background: var(--card-bg);
|
||||
padding: 24px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
box-shadow: 0 4px 6px -1px rgba(0,0,0,0.2);
|
||||
margin-bottom: 24px;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
@ -39,23 +40,24 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
background: #eff6ff;
|
||||
background: #14532d33; /* Dark green tint */
|
||||
border: 1px dashed var(--primary);
|
||||
}
|
||||
input[type="file"] {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
button {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
color: #052e16; /* Dark green text for contrast */
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
button:hover { opacity: 0.9; }
|
||||
button:hover { background: var(--primary-hover); transform: translateY(-1px); }
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
@ -70,9 +72,9 @@
|
||||
gap: 16px;
|
||||
}
|
||||
.player-header {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
border-bottom: 2px solid var(--bg);
|
||||
font-size: 1.4rem;
|
||||
font-weight: 800;
|
||||
border-bottom: 2px solid var(--border);
|
||||
padding-bottom: 8px;
|
||||
color: var(--primary);
|
||||
}
|
||||
@ -81,23 +83,26 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #33415544;
|
||||
}
|
||||
.stat-label { color: var(--text-muted); font-size: 0.9rem; font-weight: 500; }
|
||||
.stat-value { font-size: 1.1rem; font-weight: 700; color: var(--text-main); }
|
||||
|
||||
table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 0.95rem; }
|
||||
th {
|
||||
background-color: var(--bg);
|
||||
background-color: #0f172a;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
color: var(--primary);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: background 0.2s;
|
||||
border-bottom: 2px solid var(--border);
|
||||
}
|
||||
th:hover { background-color: var(--border); }
|
||||
td { padding: 12px; border-bottom: 1px solid var(--border); }
|
||||
td { padding: 12px; border-bottom: 1px solid var(--border); color: var(--text-main); }
|
||||
tr:hover td { background-color: #ffffff05; }
|
||||
tr:last-child td { border-bottom: none; }
|
||||
|
||||
.badge {
|
||||
@ -107,10 +112,40 @@
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.badge-win { background: #dcfce7; color: #166534; }
|
||||
.badge-loss { background: #fee2e2; color: #991b1b; }
|
||||
.badge-win { background: #064e3b; color: #34d399; }
|
||||
.badge-loss { background: #7f1d1d; color: #fca5a5; }
|
||||
|
||||
.chart-container { position: relative; height: 350px; width: 100%; }
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 600px) {
|
||||
body { padding: 12px; }
|
||||
h1 { font-size: 1.5rem; margin-bottom: 1.5rem; }
|
||||
.card { padding: 16px; margin-bottom: 16px; }
|
||||
|
||||
.upload-section {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
margin: 0 -16px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
table {
|
||||
min-width: 600px; /* Force scroll on small screens */
|
||||
}
|
||||
|
||||
.chart-container { height: 250px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -137,20 +172,22 @@
|
||||
|
||||
<div class="card">
|
||||
<h2>Recent Games</h2>
|
||||
<table id="games-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable(0)">Date ↕</th>
|
||||
<th onclick="sortTable(1)">Player ↕</th>
|
||||
<th onclick="sortTable(2)">Opponent ↕</th>
|
||||
<th onclick="sortTable(3)">Avg ↕</th>
|
||||
<th onclick="sortTable(4)">Darts ↕</th>
|
||||
<th onclick="sortTable(5)">Round ↕</th>
|
||||
<th onclick="sortTable(6)">Result ↕</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
<div class="table-container">
|
||||
<table id="games-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable(0)">Date ↕</th>
|
||||
<th onclick="sortTable(1)">Player ↕</th>
|
||||
<th onclick="sortTable(2)">Opponent ↕</th>
|
||||
<th onclick="sortTable(3)">Avg ↕</th>
|
||||
<th onclick="sortTable(4)">Darts ↕</th>
|
||||
<th onclick="sortTable(5)">Round ↕</th>
|
||||
<th onclick="sortTable(6)">Result ↕</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -230,19 +267,23 @@
|
||||
const players = [...new Set(games.map(g => g.player))];
|
||||
const dates = [...new Set(games.map(g => g.date))].sort((a, b) => new Date(a) - new Date(b));
|
||||
|
||||
const datasets = players.map(player => {
|
||||
const datasets = players.map((player, index) => {
|
||||
const playerGames = games.filter(g => g.player === player);
|
||||
const data = dates.map(date => {
|
||||
const game = playerGames.find(g => g.date === date);
|
||||
return game ? game.average : null;
|
||||
});
|
||||
|
||||
const colors = ['#22c55e', '#3b82f6', '#a855f7', '#f59e0b'];
|
||||
const color = colors[index % colors.length];
|
||||
|
||||
return {
|
||||
label: player,
|
||||
data: data,
|
||||
borderColor: '#' + Math.floor(Math.random()*16777215).toString(16),
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
borderColor: color,
|
||||
backgroundColor: color + '22',
|
||||
fill: true,
|
||||
tension: 0.3,
|
||||
spanGaps: true
|
||||
};
|
||||
});
|
||||
@ -256,8 +297,20 @@
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: { labels: { color: '#f8fafc', font: { weight: '600' } } }
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero: false, title: { display: true, text: '3-Dart Average' } }
|
||||
y: {
|
||||
beginAtZero: false,
|
||||
grid: { color: '#334155' },
|
||||
ticks: { color: '#94a3b8' },
|
||||
title: { display: true, text: '3-Dart Average', color: '#94a3b8' }
|
||||
},
|
||||
x: {
|
||||
grid: { color: '#334155' },
|
||||
ticks: { color: '#94a3b8' }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
1
stats.json
Normal file
1
stats.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user