feat(leaderboard): opt-out support — server endpoint, client method, UI button

- Server: DELETE /api/leaderboard/opt-in sets leaderboard_opt_in=0,
  hiding the player without deleting their row (scores preserved for re-opt-in)
- SyncProvider trait: opt_out_leaderboard() default no-op method + blanket impl
- SolitaireServerClient: implements opt_out_leaderboard via DELETE request with JWT refresh
- Leaderboard UI: "Opt Out" button (dark red) alongside existing "Opt In" button
- Server integration test: opt-out hides, opt-in restores (round-trip verified)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-04-27 02:01:20 +00:00
parent 15b9b5477b
commit 648c5c18d9
6 changed files with 205 additions and 21 deletions
+1
View File
@@ -44,6 +44,7 @@ fn build_router_inner(pool: SqlitePool, rate_limit: bool) -> Router {
.route("/api/sync/push", post(sync::push))
.route("/api/leaderboard", get(leaderboard::get_leaderboard))
.route("/api/leaderboard/opt-in", post(leaderboard::opt_in))
.route("/api/leaderboard/opt-in", delete(leaderboard::opt_out))
.route("/api/account", delete(auth::delete_account))
.layer(axum_middleware::from_fn(middleware::require_auth));