Fixed focus lost on username input field
This commit is contained in:
56
AGENTS.md
56
AGENTS.md
@@ -1,12 +1,8 @@
|
|||||||
# Codex Agent Guide — CoopGameChooser
|
# Agent Guide — Pick'n'Play
|
||||||
|
|
||||||
This repo is a tiny, purpose-built web app for a closed Discord group to:
|
Also see the other related files: API.md, IIS.md, SPEC.md
|
||||||
1) submit game suggestions blindly
|
|
||||||
2) reveal all suggestions with authors
|
|
||||||
3) vote 0–10 blindly
|
|
||||||
4) reveal totals sorted by score
|
|
||||||
|
|
||||||
Tech constraints:
|
## Tech constraints:
|
||||||
- .NET 10
|
- .NET 10
|
||||||
- ASP.NET Core Minimal API
|
- ASP.NET Core Minimal API
|
||||||
- Static HTML/CSS/JS (no Razor Pages, no Blazor, no HTMX)
|
- Static HTML/CSS/JS (no Razor Pages, no Blazor, no HTMX)
|
||||||
@@ -15,53 +11,11 @@ Tech constraints:
|
|||||||
- Single active “session” (one room) unless extended later
|
- Single active “session” (one room) unless extended later
|
||||||
- Runs on IIS (Windows Server)
|
- Runs on IIS (Windows Server)
|
||||||
|
|
||||||
This file tells Codex how to work in this repo.
|
## Working Style
|
||||||
Also see the other related files: API.md, IIS.md, SPEC.md
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Operating Principles
|
|
||||||
|
|
||||||
### Non-negotiables
|
|
||||||
- **Server-side enforcement of phase rules** (clients must not be trusted).
|
|
||||||
- **Blindness**:
|
|
||||||
- Suggest phase: player can only read/write their own suggestions.
|
|
||||||
- Vote phase: player can only read/write their own votes.
|
|
||||||
- Results phase: only aggregated totals are shown.
|
|
||||||
- **Minimal moving parts**: prefer `Program.cs` + a few small files over frameworks.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Repo Layout Target
|
|
||||||
|
|
||||||
- `Program.cs` — Minimal host wiring (services, middleware, endpoint maps)
|
|
||||||
- `Endpoints/` — Minimal API route files split by area (state, suggest, vote, results, admin) + helpers
|
|
||||||
- `Contracts/` — DTOs and request records
|
|
||||||
- `Data/` — EF Core DbContext and migrations
|
|
||||||
- `Domain/` — Plain models: Player, Suggestion, Vote, AppState, Phase enum
|
|
||||||
- `wwwroot/`
|
|
||||||
- `index.html` — app shell; loads phase-specific views
|
|
||||||
- `app.js` — main client script (ES module)
|
|
||||||
- `js/` — shared frontend modules (e.g., API client)
|
|
||||||
- `styles.css` — minimal styling
|
|
||||||
|
|
||||||
Do not introduce MVC controllers, Razor Pages, Blazor, or SPA frameworks.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security Notes
|
|
||||||
|
|
||||||
- Cookie must be HttpOnly and SameSite=Strict
|
|
||||||
- Use HTTPS in production
|
|
||||||
- No client-side trust for blindness
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Codex Working Style
|
|
||||||
|
|
||||||
|
- After every iteration, do a git commit with a brief summary of the changes as a commit message.
|
||||||
- Implement API first, UI second
|
- Implement API first, UI second
|
||||||
- Keep changes small and testable
|
- Keep changes small and testable
|
||||||
- Prefer clarity over abstraction
|
- Prefer clarity over abstraction
|
||||||
- Avoid introducing new dependencies unless they remove complexity.
|
- Avoid introducing new dependencies unless they remove complexity.
|
||||||
- After every iteration, do a git commit with a brief summary of the changes as a commit message.
|
|
||||||
- Keep endpoint logic in `Endpoints/` and shared helpers/DTOs in their folders to avoid Program.cs bloat.
|
- Keep endpoint logic in `Endpoints/` and shared helpers/DTOs in their folders to avoid Program.cs bloat.
|
||||||
|
|||||||
3
SPEC.md
3
SPEC.md
@@ -1,4 +1,4 @@
|
|||||||
# CoopGameChooser — Product Spec (MVP)
|
# Pick'n'Play — Product Spec (MVP)
|
||||||
|
|
||||||
## Goal
|
## Goal
|
||||||
A micro web app for a closed Discord group (4–8 players) to decide what co-op game to play using a phased process:
|
A micro web app for a closed Discord group (4–8 players) to decide what co-op game to play using a phased process:
|
||||||
@@ -33,5 +33,4 @@ A micro web app for a closed Discord group (4–8 players) to decide what co-op
|
|||||||
|
|
||||||
## Non-functional
|
## Non-functional
|
||||||
- Desktop + mobile usable
|
- Desktop + mobile usable
|
||||||
- Simple polling acceptable
|
|
||||||
- IIS-hosted
|
- IIS-hosted
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ function setAuthUI(isAuthed) {
|
|||||||
if (adminCard) adminCard.classList.add("hidden");
|
if (adminCard) adminCard.classList.add("hidden");
|
||||||
const loginUser = $("login-username");
|
const loginUser = $("login-username");
|
||||||
const cachedUser = getSavedUsername();
|
const cachedUser = getSavedUsername();
|
||||||
if (loginUser && cachedUser) loginUser.value = cachedUser;
|
if (loginUser && cachedUser && !loginUser.dataset.userEditing && !loginUser.value) {
|
||||||
|
loginUser.value = cachedUser;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,6 +313,13 @@ function setupHandlers() {
|
|||||||
}
|
}
|
||||||
setAuthMode(state.authMode);
|
setAuthMode(state.authMode);
|
||||||
|
|
||||||
|
const loginUser = $("login-username");
|
||||||
|
if (loginUser) {
|
||||||
|
const markEditing = () => { loginUser.dataset.userEditing = "1"; };
|
||||||
|
["focus", "input", "keydown"].forEach(evt => loginUser.addEventListener(evt, markEditing));
|
||||||
|
loginUser.addEventListener("blur", () => { delete loginUser.dataset.userEditing; });
|
||||||
|
}
|
||||||
|
|
||||||
const langSelects = Array.from(document.querySelectorAll(".lang-select"));
|
const langSelects = Array.from(document.querySelectorAll(".lang-select"));
|
||||||
const syncLanguageSelects = () => langSelects.forEach(sel => sel.value = getLanguage());
|
const syncLanguageSelects = () => langSelects.forEach(sel => sel.value = getLanguage());
|
||||||
syncLanguageSelects();
|
syncLanguageSelects();
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<body class="page">
|
<body class="page">
|
||||||
<section class="card hidden" id="auth-card">
|
<section class="card hidden" id="auth-card">
|
||||||
<div class="auth-logo">
|
<div class="auth-logo">
|
||||||
<img src="logo.png" alt="CoopGameChooser logo" />
|
<img src="logo.png" alt="Pick'n'Play logo" />
|
||||||
</div>
|
</div>
|
||||||
<div class="stack">
|
<div class="stack">
|
||||||
<h2 id="auth-title" data-i18n="auth.loginHeading">Log in</h2>
|
<h2 id="auth-title" data-i18n="auth.loginHeading">Log in</h2>
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
|
|
||||||
<section>
|
<section>
|
||||||
<div class="status-bar">
|
<div class="status-bar">
|
||||||
<img src="logo.png" alt="CoopGameChooser logo" class="logo-mark">
|
<img src="logo.png" alt="Pick'n'Play logo" class="logo-mark">
|
||||||
<div class="status-left">
|
<div class="status-left">
|
||||||
<span id="welcome-text" data-i18n="auth.welcome">Welcome!</span>
|
<span id="welcome-text" data-i18n="auth.welcome">Welcome!</span>
|
||||||
<a id="logout" href="#" class="link inline-link" data-i18n="auth.logout">Logout</a>
|
<a id="logout" href="#" class="link inline-link" data-i18n="auth.logout">Logout</a>
|
||||||
|
|||||||
@@ -132,11 +132,11 @@ button.ghost { background: transparent; border-color: #d5c7b5; color: #2c1c0d; }
|
|||||||
|
|
||||||
.card-grid {
|
.card-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 900px;
|
max-width: 1280px;
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
.results-grid { max-width: none; }
|
.results-grid { max-width: none; }
|
||||||
|
|||||||
Reference in New Issue
Block a user