design changes, refactor

This commit is contained in:
Radek Davidek 2025-12-28 19:16:00 +01:00
parent 356cd757f4
commit 4a00eeb3a4
7 changed files with 107 additions and 46 deletions

View File

@ -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>

View File

@ -1,4 +1,4 @@
package com.darts.stats;
package cz.kamma.darts;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

View File

@ -1,4 +1,4 @@
package com.darts.stats;
package cz.kamma.darts;
import lombok.Data;
import lombok.NoArgsConstructor;

View File

@ -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;

View File

@ -1,4 +1,4 @@
package com.darts.stats;
package cz.kamma.darts;
import lombok.Builder;
import lombok.Data;

View File

@ -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

File diff suppressed because one or more lines are too long