Save finished games and add history views
This commit is contained in:
+243
-1
@@ -506,7 +506,7 @@ h3 {
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: var(--surface-soft);
|
||||
max-height: 280px;
|
||||
max-height: calc(100vh - 500px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@@ -541,6 +541,211 @@ h3 {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.games-page {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.games-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.games-header p {
|
||||
margin: 6px 0 0;
|
||||
}
|
||||
|
||||
.games-header-actions {
|
||||
margin-top: 0;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.games-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.game-card {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 14px;
|
||||
background: var(--surface-soft);
|
||||
}
|
||||
|
||||
.game-card:hover {
|
||||
border-color: #b7c0cb;
|
||||
background: #eef2f6;
|
||||
}
|
||||
|
||||
.game-card-main {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.game-card-label {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.game-card-title {
|
||||
margin: 4px 0 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.game-card-meta {
|
||||
display: flex;
|
||||
gap: 0;
|
||||
flex-wrap: wrap;
|
||||
color: var(--muted);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.game-card-meta span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.game-card-meta span + span::before {
|
||||
content: "|";
|
||||
margin: 0 10px;
|
||||
color: #9aa3af;
|
||||
}
|
||||
|
||||
.result-badge {
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 6px;
|
||||
padding: 6px 10px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.result-win {
|
||||
background: #ecfdf3;
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.result-loss {
|
||||
background: #fef2f2;
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.result-draw {
|
||||
background: #eef2f6;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 24px 14px;
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
margin: 8px 0 0;
|
||||
}
|
||||
|
||||
.game-detail-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(280px, 420px) minmax(0, 1fr);
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.game-summary {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.game-summary-copy {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.game-summary-label {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.85rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.game-summary-title {
|
||||
margin: 4px 0 0;
|
||||
font-size: 2rem;
|
||||
line-height: 1;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.game-summary-meta {
|
||||
margin-top: 14px;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.game-meta-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.game-meta-key {
|
||||
color: var(--muted);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.game-meta-value {
|
||||
text-align: right;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.history-board {
|
||||
margin-top: 14px;
|
||||
width: min(100%, 420px);
|
||||
aspect-ratio: 1 / 1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, 1fr);
|
||||
grid-template-rows: repeat(8, minmax(0, 1fr));
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: #d2b48c;
|
||||
}
|
||||
|
||||
.history-square {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
|
||||
.history-square-light {
|
||||
background: #f6e7cf;
|
||||
}
|
||||
|
||||
.history-square-dark {
|
||||
background: #b18155;
|
||||
}
|
||||
|
||||
.history-square img {
|
||||
width: 82%;
|
||||
height: 82%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
#chess-canvas {
|
||||
width: min(100%, 640px);
|
||||
aspect-ratio: 1 / 1;
|
||||
@@ -555,4 +760,41 @@ h3 {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.games-header {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.games-header-actions {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.game-card-main {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.game-summary {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.game-summary-title {
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
|
||||
.game-meta-row {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.game-meta-value {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.game-detail-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,11 +464,18 @@ export class PlayApp {
|
||||
|
||||
onGameOver(data) {
|
||||
this.setStatus(`Game over: ${data.result} (${data.reason})`);
|
||||
this.showModal(
|
||||
"Game over",
|
||||
`${data.result.toUpperCase()} - ${data.reason}`,
|
||||
[{ label: "OK" }],
|
||||
);
|
||||
const actions = [{ label: "OK" }];
|
||||
if (data.game_id) {
|
||||
actions.unshift({
|
||||
label: "View saved game",
|
||||
className: "btn-primary",
|
||||
onClick: () => {
|
||||
window.location.href = `/games/${data.game_id}`;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
this.showModal("Game over", `${data.result.toUpperCase()} - ${data.reason}`, actions);
|
||||
}
|
||||
|
||||
onDrawOffered(data) {
|
||||
|
||||
Reference in New Issue
Block a user