[SPA][P4] #169 Lobby join + start round wired via vertical slice in shell #182
@@ -2,6 +2,9 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
import { createApiClient } from '../../../../../src/api/client';
|
||||||
|
import { createVerticalSliceController } from '../../../../../src/spa/vertical-slice';
|
||||||
|
|
||||||
interface SessionDetail {
|
interface SessionDetail {
|
||||||
session: { code: string; status: string; current_round: number };
|
session: { code: string; status: string; current_round: number };
|
||||||
round_question: { id: number; prompt: string; answers: Array<{ text: string }> } | null;
|
round_question: { id: number; prompt: string; answers: Array<{ text: string }> } | null;
|
||||||
@@ -51,6 +54,8 @@ export class HostShellComponent {
|
|||||||
scoreboardPayload = '';
|
scoreboardPayload = '';
|
||||||
session: SessionDetail | null = null;
|
session: SessionDetail | null = null;
|
||||||
|
|
||||||
|
private readonly controller = createVerticalSliceController(createApiClient());
|
||||||
|
|
||||||
private normalizeCode(value: string): string {
|
private normalizeCode(value: string): string {
|
||||||
return value.trim().toUpperCase();
|
return value.trim().toUpperCase();
|
||||||
}
|
}
|
||||||
@@ -79,8 +84,11 @@ export class HostShellComponent {
|
|||||||
this.error = '';
|
this.error = '';
|
||||||
this.scoreboardError = '';
|
this.scoreboardError = '';
|
||||||
try {
|
try {
|
||||||
const code = this.normalizeCode(this.sessionCode);
|
const state = await this.controller.hydrateLobby(this.sessionCode);
|
||||||
this.session = await this.request<SessionDetail>(`/lobby/sessions/${encodeURIComponent(code)}`, 'GET');
|
if (!state.session || state.errorMessage) {
|
||||||
|
throw new Error(state.errorMessage ?? 'Unknown error');
|
||||||
|
}
|
||||||
|
this.session = state.session as SessionDetail;
|
||||||
this.sessionCode = this.session.session.code;
|
this.sessionCode = this.session.session.code;
|
||||||
this.roundQuestionId = this.session.round_question?.id ? String(this.session.round_question.id) : '';
|
this.roundQuestionId = this.session.round_question?.id ? String(this.session.round_question.id) : '';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -92,11 +100,13 @@ export class HostShellComponent {
|
|||||||
|
|
||||||
async startRound(): Promise<void> {
|
async startRound(): Promise<void> {
|
||||||
await this.runAction(async () => {
|
await this.runAction(async () => {
|
||||||
const code = this.normalizeCode(this.sessionCode);
|
const state = await this.controller.startRound(this.sessionCode, this.categorySlug.trim());
|
||||||
await this.request(`/lobby/sessions/${encodeURIComponent(code)}/rounds/start`, 'POST', {
|
if (!state.session || state.errorMessage) {
|
||||||
category_slug: this.categorySlug.trim(),
|
throw new Error(state.errorMessage ?? 'Unknown error');
|
||||||
});
|
}
|
||||||
await this.refreshSession();
|
this.session = state.session as SessionDetail;
|
||||||
|
this.sessionCode = this.session.session.code;
|
||||||
|
this.roundQuestionId = this.session.round_question?.id ? String(this.session.round_question.id) : '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
import { createApiClient } from '../../../../../src/api/client';
|
||||||
|
import { createSessionContextStore } from '../../../../../src/spa/session-context-store';
|
||||||
|
import { createVerticalSliceController } from '../../../../../src/spa/vertical-slice';
|
||||||
|
|
||||||
interface SessionDetail {
|
interface SessionDetail {
|
||||||
session: { code: string; status: string; current_round: number };
|
session: { code: string; status: string; current_round: number };
|
||||||
round_question: { id: number; prompt: string; answers: Array<{ text: string }> } | null;
|
round_question: { id: number; prompt: string; answers: Array<{ text: string }> } | null;
|
||||||
@@ -61,6 +65,9 @@ export class PlayerShellComponent {
|
|||||||
submitError: { kind: 'lie' | 'guess'; message: string } | null = null;
|
submitError: { kind: 'lie' | 'guess'; message: string } | null = null;
|
||||||
session: SessionDetail | null = null;
|
session: SessionDetail | null = null;
|
||||||
|
|
||||||
|
private readonly sessionContextStore = createSessionContextStore();
|
||||||
|
private readonly controller = createVerticalSliceController(createApiClient(), this.sessionContextStore);
|
||||||
|
|
||||||
private normalizeCode(value: string): string {
|
private normalizeCode(value: string): string {
|
||||||
return value.trim().toUpperCase();
|
return value.trim().toUpperCase();
|
||||||
}
|
}
|
||||||
@@ -88,8 +95,11 @@ export class PlayerShellComponent {
|
|||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.error = '';
|
this.error = '';
|
||||||
try {
|
try {
|
||||||
const code = this.normalizeCode(this.sessionCode);
|
const state = await this.controller.hydrateLobby(this.sessionCode);
|
||||||
this.session = await this.request<SessionDetail>(`/lobby/sessions/${encodeURIComponent(code)}`, 'GET');
|
if (!state.session || state.errorMessage) {
|
||||||
|
throw new Error(state.errorMessage ?? 'Unknown error');
|
||||||
|
}
|
||||||
|
this.session = state.session as SessionDetail;
|
||||||
this.sessionCode = this.session.session.code;
|
this.sessionCode = this.session.session.code;
|
||||||
if (this.session.session.status !== 'guess') {
|
if (this.session.session.status !== 'guess') {
|
||||||
this.selectedGuess = '';
|
this.selectedGuess = '';
|
||||||
@@ -105,17 +115,19 @@ export class PlayerShellComponent {
|
|||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.error = '';
|
this.error = '';
|
||||||
try {
|
try {
|
||||||
const payload = await this.request<{
|
const state = await this.controller.joinLobby(this.sessionCode, this.nickname);
|
||||||
player: { id: number; session_token: string };
|
if (!state.session || state.errorMessage) {
|
||||||
session: { code: string };
|
throw new Error(state.errorMessage ?? 'Unknown error');
|
||||||
}>('/lobby/sessions/join', 'POST', {
|
}
|
||||||
code: this.normalizeCode(this.sessionCode),
|
this.session = state.session as SessionDetail;
|
||||||
nickname: this.nickname.trim(),
|
this.sessionCode = this.session.session.code;
|
||||||
});
|
|
||||||
this.playerId = payload.player.id;
|
const sessionContext = this.sessionContextStore.get();
|
||||||
this.sessionToken = payload.player.session_token;
|
this.playerId = sessionContext?.playerId ?? 0;
|
||||||
this.sessionCode = payload.session.code;
|
this.sessionToken = sessionContext?.token ?? '';
|
||||||
await this.refreshSession();
|
if (this.session.session.status !== 'guess') {
|
||||||
|
this.selectedGuess = '';
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.error = `Join failed: ${(error as Error).message}`;
|
this.error = `Join failed: ${(error as Error).message}`;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user