feat(tour): added tournament history page :D
This commit is contained in:
parent
75f3c2a769
commit
aca2dbd070
13 changed files with 245 additions and 4 deletions
|
|
@ -34,6 +34,12 @@ import {
|
||||||
* @interface TournamentData200ResponsePayloadData
|
* @interface TournamentData200ResponsePayloadData
|
||||||
*/
|
*/
|
||||||
export interface TournamentData200ResponsePayloadData {
|
export interface TournamentData200ResponsePayloadData {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof TournamentData200ResponsePayloadData
|
||||||
|
*/
|
||||||
|
playerCount: number;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
|
@ -64,6 +70,7 @@ export interface TournamentData200ResponsePayloadData {
|
||||||
* Check if a given object implements the TournamentData200ResponsePayloadData interface.
|
* Check if a given object implements the TournamentData200ResponsePayloadData interface.
|
||||||
*/
|
*/
|
||||||
export function instanceOfTournamentData200ResponsePayloadData(value: object): value is TournamentData200ResponsePayloadData {
|
export function instanceOfTournamentData200ResponsePayloadData(value: object): value is TournamentData200ResponsePayloadData {
|
||||||
|
if (!('playerCount' in value) || value['playerCount'] === undefined) return false;
|
||||||
if (!('owner' in value) || value['owner'] === undefined) return false;
|
if (!('owner' in value) || value['owner'] === undefined) return false;
|
||||||
if (!('users' in value) || value['users'] === undefined) return false;
|
if (!('users' in value) || value['users'] === undefined) return false;
|
||||||
if (!('games' in value) || value['games'] === undefined) return false;
|
if (!('games' in value) || value['games'] === undefined) return false;
|
||||||
|
|
@ -81,6 +88,7 @@ export function TournamentData200ResponsePayloadDataFromJSONTyped(json: any, ign
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
||||||
|
'playerCount': json['playerCount'],
|
||||||
'owner': json['owner'],
|
'owner': json['owner'],
|
||||||
'users': ((json['users'] as Array<any>).map(TournamentData200ResponsePayloadDataUsersInnerFromJSON)),
|
'users': ((json['users'] as Array<any>).map(TournamentData200ResponsePayloadDataUsersInnerFromJSON)),
|
||||||
'games': ((json['games'] as Array<any>).map(PongHistory200ResponsePayloadDataInnerFromJSON)),
|
'games': ((json['games'] as Array<any>).map(PongHistory200ResponsePayloadDataInnerFromJSON)),
|
||||||
|
|
@ -99,6 +107,7 @@ export function TournamentData200ResponsePayloadDataToJSONTyped(value?: Tourname
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
|
'playerCount': value['playerCount'],
|
||||||
'owner': value['owner'],
|
'owner': value['owner'],
|
||||||
'users': ((value['users'] as Array<any>).map(TournamentData200ResponsePayloadDataUsersInnerToJSON)),
|
'users': ((value['users'] as Array<any>).map(TournamentData200ResponsePayloadDataUsersInnerToJSON)),
|
||||||
'games': ((value['games'] as Array<any>).map(PongHistory200ResponsePayloadDataInnerToJSON)),
|
'games': ((value['games'] as Array<any>).map(PongHistory200ResponsePayloadDataInnerToJSON)),
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,12 @@ import { mapValues } from '../runtime';
|
||||||
* @interface TournamentList200ResponsePayloadDataInner
|
* @interface TournamentList200ResponsePayloadDataInner
|
||||||
*/
|
*/
|
||||||
export interface TournamentList200ResponsePayloadDataInner {
|
export interface TournamentList200ResponsePayloadDataInner {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof TournamentList200ResponsePayloadDataInner
|
||||||
|
*/
|
||||||
|
playerCount: number;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
|
@ -43,6 +49,7 @@ export interface TournamentList200ResponsePayloadDataInner {
|
||||||
* Check if a given object implements the TournamentList200ResponsePayloadDataInner interface.
|
* Check if a given object implements the TournamentList200ResponsePayloadDataInner interface.
|
||||||
*/
|
*/
|
||||||
export function instanceOfTournamentList200ResponsePayloadDataInner(value: object): value is TournamentList200ResponsePayloadDataInner {
|
export function instanceOfTournamentList200ResponsePayloadDataInner(value: object): value is TournamentList200ResponsePayloadDataInner {
|
||||||
|
if (!('playerCount' in value) || value['playerCount'] === undefined) return false;
|
||||||
if (!('id' in value) || value['id'] === undefined) return false;
|
if (!('id' in value) || value['id'] === undefined) return false;
|
||||||
if (!('owner' in value) || value['owner'] === undefined) return false;
|
if (!('owner' in value) || value['owner'] === undefined) return false;
|
||||||
if (!('time' in value) || value['time'] === undefined) return false;
|
if (!('time' in value) || value['time'] === undefined) return false;
|
||||||
|
|
@ -59,6 +66,7 @@ export function TournamentList200ResponsePayloadDataInnerFromJSONTyped(json: any
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
||||||
|
'playerCount': json['playerCount'],
|
||||||
'id': json['id'],
|
'id': json['id'],
|
||||||
'owner': json['owner'],
|
'owner': json['owner'],
|
||||||
'time': json['time'],
|
'time': json['time'],
|
||||||
|
|
@ -76,6 +84,7 @@ export function TournamentList200ResponsePayloadDataInnerToJSONTyped(value?: Tou
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
|
'playerCount': value['playerCount'],
|
||||||
'id': value['id'],
|
'id': value['id'],
|
||||||
'owner': value['owner'],
|
'owner': value['owner'],
|
||||||
'time': value['time'],
|
'time': value['time'],
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import './profile/profile.ts'
|
||||||
import './logout/logout.ts'
|
import './logout/logout.ts'
|
||||||
import './pongHistory/pongHistory.ts'
|
import './pongHistory/pongHistory.ts'
|
||||||
import './tttHistory/tttHistory.ts'
|
import './tttHistory/tttHistory.ts'
|
||||||
|
import './tourHistory/tourHistory.ts'
|
||||||
|
|
||||||
// ---- Initial load ----
|
// ---- Initial load ----
|
||||||
setTitle("");
|
setTitle("");
|
||||||
|
|
|
||||||
156
frontend/src/pages/tourHistory/tourHistory.ts
Normal file
156
frontend/src/pages/tourHistory/tourHistory.ts
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
import { addRoute, navigateTo, type RouteHandlerParams, type RouteHandlerReturn } from "@app/routing";
|
||||||
|
import pageAll from './tourHistoryAll.html?raw';
|
||||||
|
import pageSingle from './tourHistorySingle.html?raw';
|
||||||
|
import { isNullish } from "@app/utils";
|
||||||
|
import client from "@app/api";
|
||||||
|
import { showError, showInfo } from "@app/toast";
|
||||||
|
import { getUser } from "@app/auth";
|
||||||
|
|
||||||
|
|
||||||
|
function getHHMM(d: Date): string {
|
||||||
|
let h = d.getHours();
|
||||||
|
let m = d.getMinutes();
|
||||||
|
return `${h < 9 ? '0' : ''}${h}:${m < 9 ? '0' : ''}${m}`
|
||||||
|
}
|
||||||
|
|
||||||
|
async function tourHistoryAll(_url: string, args: RouteHandlerParams): Promise<RouteHandlerReturn> {
|
||||||
|
|
||||||
|
let data = await client.tournamentList();
|
||||||
|
if (data.kind !== 'success') {
|
||||||
|
showError(`Failed to fetch data: ${data.msg}`);
|
||||||
|
return {
|
||||||
|
html: "", postInsert: async () => navigateTo('/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
html: pageAll, postInsert: async (app) => {
|
||||||
|
const tourDiv = app?.querySelector('#tourList');
|
||||||
|
if (!tourDiv || !app)
|
||||||
|
return showError('Fatal Error');
|
||||||
|
let childrens = await Promise.all(data.payload.data.map(async (tour) => {
|
||||||
|
const ownerUser = await client.getUser({ user: tour.owner });
|
||||||
|
const ownerUserName = ownerUser.kind === 'success' ? ownerUser.payload.name : "User Not Found";
|
||||||
|
return {
|
||||||
|
...tour,
|
||||||
|
ownerName: ownerUserName,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
childrens.sort((l, r) => ((new Date(r.time).getTime()) - (new Date(l.time)).getTime()));
|
||||||
|
|
||||||
|
childrens.map(tour => {
|
||||||
|
let time = new Date(tour.time);
|
||||||
|
let owner = { id: tour.owner, name: tour.ownerName };
|
||||||
|
let id = tour.id;
|
||||||
|
let playerCount = tour.playerCount;
|
||||||
|
|
||||||
|
const eventItem = document.createElement('div');
|
||||||
|
eventItem.classList.add(
|
||||||
|
'bg-white',
|
||||||
|
'p-4',
|
||||||
|
'rounded-lg',
|
||||||
|
'shadow-md',
|
||||||
|
'mb-4',
|
||||||
|
'flex',
|
||||||
|
'justify-between',
|
||||||
|
'items-center',
|
||||||
|
);
|
||||||
|
|
||||||
|
eventItem.innerHTML = `
|
||||||
|
<div class="text-left">
|
||||||
|
<p class="text-lg font-semibold text-gray-700"><strong>Time:</strong> ${time.toDateString()} ${getHHMM(time)}</p>
|
||||||
|
<p class="text-sm text-gray-500"><strong>Created By:</strong> ${owner.name} </p>
|
||||||
|
<p class="text-sm text-gray-500"><strong>Player Count:</strong> ${playerCount}</p>
|
||||||
|
</div>
|
||||||
|
<button class="bg-blue-500 text-white px-3 py-2 rounded-lg hover:bg-blue-600" onclick="navigateTo('/tour/${id}')">View</button>`;
|
||||||
|
return eventItem;
|
||||||
|
}).forEach(v => tourDiv.appendChild(v));
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function tourHistorySingle(_url: string, args: RouteHandlerParams): Promise<RouteHandlerReturn> {
|
||||||
|
if (isNullish(args.tourid)) {
|
||||||
|
showError(`No Tournament Specified`);
|
||||||
|
return {
|
||||||
|
html: "", postInsert: async () => navigateTo('/tour')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = await client.tournamentData({ id: args.tourid });
|
||||||
|
if (data.kind !== 'success') {
|
||||||
|
showError(`Failed to fetch data: ${data.msg}`);
|
||||||
|
return {
|
||||||
|
html: "", postInsert: async () => navigateTo('/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let d = data.payload.data;
|
||||||
|
let user = getUser();
|
||||||
|
if (user === null) {
|
||||||
|
showError(`You must be logged in`);
|
||||||
|
return {
|
||||||
|
html: "", postInsert: async () => navigateTo('/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
html: pageSingle, postInsert: async (app) => {
|
||||||
|
const tourOwner = app?.querySelector<HTMLSpanElement>('#tourOwner');
|
||||||
|
const tourTime = app?.querySelector<HTMLSpanElement>('#tourTime');
|
||||||
|
const tourCount = app?.querySelector<HTMLSpanElement>('#tourCount');
|
||||||
|
const tourPlayerList = app?.querySelector<HTMLTableElement>('#tourPlayerList');
|
||||||
|
const tourGames = app?.querySelector<HTMLDivElement>('#tourGames');
|
||||||
|
if (!tourOwner || !tourTime || !tourCount || !tourPlayerList || !tourGames || !app)
|
||||||
|
return showError('Fatal Error');
|
||||||
|
|
||||||
|
|
||||||
|
d.users.sort((l, r) => r.score - l.score);
|
||||||
|
let time = new Date(d.time);
|
||||||
|
|
||||||
|
const medals = ["🥇", "🥈", "🥉"];
|
||||||
|
tourPlayerList.innerHTML = d.users.map((player, idx) =>
|
||||||
|
`<tr class="${player.id === user.id ? "bg-amber-400 hover:bg-amber-500" : "hover:bg-gray-50"}" key="${player.id}">
|
||||||
|
<td class="px-4 py-2 text-sm text-gray-800 text-center border-b font-semibold min-w-100px">${idx < medals.length ? `<span class="font-lg">${medals[idx]}</span>` : ''}${player.nickname}</td>
|
||||||
|
<td class="px-4 py-2 text-sm text-gray-800 text-center border-b font-bold min-w-100px">${player.score}</td></tr>`)
|
||||||
|
.join("");
|
||||||
|
|
||||||
|
tourOwner.innerText = await (async () => {
|
||||||
|
let req = await client.getUser({ user: d.owner });
|
||||||
|
if (req.kind === 'success')
|
||||||
|
return req.payload.name;
|
||||||
|
return 'Unknown User';
|
||||||
|
})();
|
||||||
|
tourCount.innerText = d.playerCount.toString();
|
||||||
|
tourTime.innerText = `${time.toDateString()} ${getHHMM(time)}`;
|
||||||
|
|
||||||
|
let gameElement = d.games.map(g => {
|
||||||
|
let rdate = Date.parse(g.date);
|
||||||
|
if (Number.isNaN(rdate)) return undefined;
|
||||||
|
let date = new Date(rdate);
|
||||||
|
const e = document.createElement('div');
|
||||||
|
let color = 'bg-slate-300';
|
||||||
|
e.className =
|
||||||
|
'grid grid-cols-[1fr_auto_1fr] items-center rounded-lg px-4 py-3 ' + color;
|
||||||
|
|
||||||
|
e.innerHTML = `
|
||||||
|
<div class="text-right">
|
||||||
|
<div class="font-semibold ${g.outcome === 'winL' ? 'text-green-600' : 'text-red-600'}">${g.left.name}</div>
|
||||||
|
<div class="text-lg ${g.outcome === 'winL' ? 'text-green-600' : 'text-red-600'}">${g.left.score}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center text-sm text-gray-800 px-4 whitespace-nowrap">${date.toDateString()}<br />${getHHMM(date)}</div>
|
||||||
|
|
||||||
|
<div class="text-left">
|
||||||
|
<div class="font-semibold ${g.outcome === 'winR' ? 'text-green-600' : 'text-red-600'}">${g.right.name}</div>
|
||||||
|
<div class="text-lg ${g.outcome === 'winR' ? 'text-green-600' : 'text-red-600'}">${g.right.score}</div>
|
||||||
|
</div>`;
|
||||||
|
return e;
|
||||||
|
}).filter(v => !isNullish(v));
|
||||||
|
gameElement.forEach(e => tourGames.appendChild(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addRoute('/tour', tourHistoryAll);
|
||||||
|
addRoute('/tour/:tourid', tourHistorySingle);
|
||||||
9
frontend/src/pages/tourHistory/tourHistoryAll.html
Normal file
9
frontend/src/pages/tourHistory/tourHistoryAll.html
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<div class="fixed inset-0 flex items-center justify-center bg-[#43536b]">
|
||||||
|
<div
|
||||||
|
class="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-gray-200 w-212.5 p-6 rounded-xl shadow-2xl text-center z-50">
|
||||||
|
<h2 class="text-2xl font-bold text-center mb-4 text-gray-700">
|
||||||
|
List of All Tournaments
|
||||||
|
</h2>
|
||||||
|
<div id="tourList" class="max-w-3xl mx-auto space-y-2 max-h-[50dvh] overflow-scroll"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
37
frontend/src/pages/tourHistory/tourHistorySingle.html
Normal file
37
frontend/src/pages/tourHistory/tourHistorySingle.html
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<div class="fixed inset-0 flex items-center justify-center bg-[#43536b]">
|
||||||
|
<div
|
||||||
|
class="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-gray-200 w-212.5 p-6 rounded-xl shadow-2xl text-center z-50">
|
||||||
|
<h2 class="text-2xl font-bold text-center mb-4 text-gray-700">
|
||||||
|
Tournament <span id="tour-date"> </span>
|
||||||
|
</h2>
|
||||||
|
<div id="tourInfo" class="bg-white p-4 rounded-lg shadow-md mb-4">
|
||||||
|
<p class="text-lg"> <strong class="text-gray-700">Created By:<strong> <span class="text-amber-500"
|
||||||
|
id="tourOwner"></span></p>
|
||||||
|
<p class="text-lg"> <strong class="text-gray-700">Finished At:<strong> <span class="text-amber-500"
|
||||||
|
id="tourTime"></span></p>
|
||||||
|
<p class="text-lg"> <strong class="text-gray-700">Players:<strong> <span class="text-amber-500"
|
||||||
|
id="tourCount"></span></p>
|
||||||
|
</div>
|
||||||
|
<div class="max-h-[320px] overflow-y-auto overflow-x-auto border rounded-lg mb-4">
|
||||||
|
<table class="min-w-full border-collapse table-fixed">
|
||||||
|
<thead class="sticky top-0 z-10 bg-gray-100">
|
||||||
|
<tr>
|
||||||
|
<th class="px-4 py-2 text-center text-lg font-semibold text-gray-700 border-b">
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th class="px-4 py-2 text-center text-lg font-semibold text-gray-700 border-b">
|
||||||
|
Score
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody id="tourPlayerList">
|
||||||
|
<!-- rows -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div id="tourGames" class="max-w-3xl mx-auto space-y-2 max-h-[25dvh] overflow-scroll">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -5,8 +5,6 @@
|
||||||
src: url("/fonts/DejaVuSansMono.woff2") format("woff2");
|
src: url("/fonts/DejaVuSansMono.woff2") format("woff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.displaybox {
|
.displaybox {
|
||||||
@apply
|
@apply
|
||||||
fixed
|
fixed
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ CREATE TABLE IF NOT EXISTS tournament (
|
||||||
id TEXT PRIMARY KEY NOT NULL,
|
id TEXT PRIMARY KEY NOT NULL,
|
||||||
time TEXT NOT NULL default (datetime ('now')),
|
time TEXT NOT NULL default (datetime ('now')),
|
||||||
owner TEXT NOT NULL,
|
owner TEXT NOT NULL,
|
||||||
|
playerCount INTEGER NOT NULL,
|
||||||
FOREIGN KEY (owner) REFERENCES user (id)
|
FOREIGN KEY (owner) REFERENCES user (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export const TournamentImpl: Omit<ITournamentDb, keyof Database> = {
|
||||||
): TournamentData | null {
|
): TournamentData | null {
|
||||||
// Fetch tournament
|
// Fetch tournament
|
||||||
const tournament = this
|
const tournament = this
|
||||||
.prepare('SELECT id, time, owner FROM tournament WHERE id = @id')
|
.prepare('SELECT * FROM tournament WHERE id = @id')
|
||||||
.get({ id }) as TournamentTable;
|
.get({ id }) as TournamentTable;
|
||||||
|
|
||||||
if (!tournament) {
|
if (!tournament) {
|
||||||
|
|
@ -90,7 +90,7 @@ export const TournamentImpl: Omit<ITournamentDb, keyof Database> = {
|
||||||
): void {
|
): void {
|
||||||
const tournamentId = newUUID() as TournamentId;
|
const tournamentId = newUUID() as TournamentId;
|
||||||
|
|
||||||
this.prepare('INSERT INTO tournament (id, owner) VALUES (@id, @owner)').run({ id: tournamentId, owner });
|
this.prepare('INSERT INTO tournament (id, owner, playerCount) VALUES (@id, @owner, @count)').run({ id: tournamentId, owner, count: users.length });
|
||||||
for (const u of users) {
|
for (const u of users) {
|
||||||
this.prepare('INSERT INTO tour_user (user, nickname, score, tournament) VALUES (@id, @name, @score, @tournament)').run({ id: u.id, name: u.name, score: u.score, tournament: tournamentId });
|
this.prepare('INSERT INTO tour_user (user, nickname, score, tournament) VALUES (@id, @name, @score, @tournament)').run({ id: u.id, name: u.name, score: u.score, tournament: tournamentId });
|
||||||
}
|
}
|
||||||
|
|
@ -115,6 +115,7 @@ export interface TournamentTable {
|
||||||
id: TournamentId;
|
id: TournamentId;
|
||||||
time: string;
|
time: string;
|
||||||
owner: UserId;
|
owner: UserId;
|
||||||
|
playerCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TournamentUser {
|
export interface TournamentUser {
|
||||||
|
|
|
||||||
|
|
@ -2497,12 +2497,16 @@
|
||||||
"data": {
|
"data": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
"playerCount",
|
||||||
"owner",
|
"owner",
|
||||||
"users",
|
"users",
|
||||||
"games",
|
"games",
|
||||||
"time"
|
"time"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"playerCount": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
"owner": {
|
"owner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "ownerId"
|
"description": "ownerId"
|
||||||
|
|
@ -2736,11 +2740,15 @@
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
"playerCount",
|
||||||
"id",
|
"id",
|
||||||
"owner",
|
"owner",
|
||||||
"time"
|
"time"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"playerCount": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "tournamentId"
|
"description": "tournamentId"
|
||||||
|
|
|
||||||
|
|
@ -355,12 +355,16 @@
|
||||||
"data": {
|
"data": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
"playerCount",
|
||||||
"owner",
|
"owner",
|
||||||
"users",
|
"users",
|
||||||
"games",
|
"games",
|
||||||
"time"
|
"time"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"playerCount": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
"owner": {
|
"owner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "ownerId"
|
"description": "ownerId"
|
||||||
|
|
@ -591,11 +595,15 @@
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
"playerCount",
|
||||||
"id",
|
"id",
|
||||||
"owner",
|
"owner",
|
||||||
"time"
|
"time"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"playerCount": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "tournamentId"
|
"description": "tournamentId"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ type TournamentDataParams = Static<typeof TournamentDataParams>;
|
||||||
const TournamentDataResponse = {
|
const TournamentDataResponse = {
|
||||||
'200': typeResponse('success', 'tournamentData.success', {
|
'200': typeResponse('success', 'tournamentData.success', {
|
||||||
data: Type.Object({
|
data: Type.Object({
|
||||||
|
playerCount: Type.Number(),
|
||||||
owner: Type.String({ description: 'ownerId' }),
|
owner: Type.String({ description: 'ownerId' }),
|
||||||
users: Type.Array(
|
users: Type.Array(
|
||||||
Type.Object({
|
Type.Object({
|
||||||
|
|
@ -65,8 +66,10 @@ const route: FastifyPluginAsync = async (fastify): Promise<void> => {
|
||||||
'tournamentData.failure.notFound',
|
'tournamentData.failure.notFound',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
console.log(data);
|
||||||
const typed_res: TournamentDataResponse['200']['payload']['data'] =
|
const typed_res: TournamentDataResponse['200']['payload']['data'] =
|
||||||
{
|
{
|
||||||
|
playerCount: data.playerCount,
|
||||||
owner: data.owner,
|
owner: data.owner,
|
||||||
time: data.time,
|
time: data.time,
|
||||||
users: data.users.map((v) => ({
|
users: data.users.map((v) => ({
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ const TournamentListResponse = {
|
||||||
'200': typeResponse('success', 'tournamentList.success', {
|
'200': typeResponse('success', 'tournamentList.success', {
|
||||||
data: Type.Array(
|
data: Type.Array(
|
||||||
Type.Object({
|
Type.Object({
|
||||||
|
playerCount: Type.Number(),
|
||||||
id: Type.String({ description: 'tournamentId' }),
|
id: Type.String({ description: 'tournamentId' }),
|
||||||
owner: Type.String({ description: 'ownerId' }),
|
owner: Type.String({ description: 'ownerId' }),
|
||||||
time: Type.String(),
|
time: Type.String(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue