feat: extended player profile

This commit is contained in:
Dawid Wysokiński 2023-01-18 16:40:54 +01:00
parent 29ae462b1f
commit 84c5c3fc9a
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
2 changed files with 144 additions and 80 deletions

113
src/common/DialogTable.ts Normal file
View File

@ -0,0 +1,113 @@
import { ListResult } from '../lib/client';
const translations: Record<string, Record<string, string>> = {
pl_PL: {
Loading: 'Wczytywanie',
'Previous page': 'Poprzednia strona',
'Next page': 'Następna strona',
},
};
const t = (s: string) => {
return translations[window.game_data.locale]?.[s] ?? s;
};
export type DialogTableColumn<T> = {
header: string;
accessor: (row: T) => string;
};
export class DialogTable<T> {
constructor(
private readonly id: string,
private readonly columns: DialogTableColumn<T>[],
private readonly limit: number,
private readonly loadData: (
page: number,
limit: number
) => Promise<ListResult<T>>
) {}
public async render() {
await this.renderPage(1);
}
private async renderPage(page: number) {
window.Dialog.show(`${this.id}_loading`, `<p>${t('Loading')}...</p>`);
const { data, total } = await this.loadData(page, this.limit);
const maxPage = Math.ceil(total / this.limit);
const pageOpts = [];
for (let i = 1; i <= (page > maxPage ? page : maxPage); i++) {
pageOpts.push(
`<option${
i === page ? ' disabled selected' : ''
} value="${i}">${i}</option>`
);
}
const prevPageId = `${this.id}_page_prev`;
const selectId = `${this.id}_page_select`;
const nextPageId = `${this.id}_page_next`;
window.Dialog.show(
this.id,
`
<div style="display: flex; flex-direction: row; align-items: center; justify-content: center; margin-bottom: 10px">
<button title="${t(
'Previous page'
)}" style="margin-right: 5px" class="btn" id="${prevPageId}"${
page <= 1 ? ' disabled' : ''
}>&lt;</button>
<select style="margin-right: 5px" id="${selectId}">
${pageOpts.join('')}
</select>
<button title="${t('Next page')}" class="btn" id="${nextPageId}"${
page >= maxPage ? ' disabled' : ''
}>&gt;</button>
</div>
<table class="vis">
<tbody>
<tr>
${this.columns.map((col) => `<th>${col.header}</th>`).join('')}
</tr>
${data
.map(
(r) => `
<tr>
${this.columns
.map((col) => `<td>${col.accessor(r)}</td>`)
.join('')}
</tr>
`
)
.join('')}
</tbody>
</table>
`
);
document
.querySelector('#' + prevPageId)
?.addEventListener('click', (e: Event) => {
this.renderPage(page - 1);
});
document
.querySelector('#' + selectId)
?.addEventListener('change', (e: Event) => {
if (!(e.currentTarget instanceof HTMLSelectElement)) {
return;
}
this.renderPage(parseInt(e.currentTarget.value));
});
document
.querySelector('#' + nextPageId)
?.addEventListener('click', (e: Event) => {
this.renderPage(page + 1);
});
}
}

View File

@ -1,6 +1,7 @@
// Extended player profile
import { ListResult, Player, TribeChange, TWHelpClient } from './lib/client';
import { DialogTable } from './common/DialogTable';
const SCREEN = 'info_player';
const MODE = null;
@ -15,7 +16,6 @@ const translations: Record<string, Record<string, string>> = {
'Show tribe changes': 'Pokaż zmiany plemion',
'Show history': 'Pokaż historię',
'Show ennoblements': 'Pokaż przejęcia',
'Fetching data': 'Pobieranie danych',
'Old tribe': 'Stare plemię',
'New tribe': 'Nowe plemię',
'Date/time': 'Data/czas',
@ -47,13 +47,12 @@ class TWHelpConnector {
}
}
interface UIConnector {
tribeChanges(page: number, limit: number): Promise<ListResult<TribeChange>>;
enum DialogId {
TRIBE_CHANGES = 'kichiyaki_tribe_changes',
}
enum DialogId {
TRIBE_CHANGES_LOADING = 'kichiyaki_tribe_changes_loading',
TRIBE_CHANGES = 'kichiyaki_tribe_changes',
interface UIConnector {
tribeChanges(page: number, limit: number): Promise<ListResult<TribeChange>>;
}
class UI {
@ -143,81 +142,33 @@ class UI {
private async showTribeChanges(e: Event) {
e.preventDefault();
await this._showTribeChanges(1);
}
private async _showTribeChanges(page: number) {
window.Dialog.show(
DialogId.TRIBE_CHANGES_LOADING,
`<p>${t('Fetching data')}...</p>`
);
const tcs = await this.connector.tribeChanges(page, UI.TRIBE_CHANGES_LIMIT);
const maxPage = Math.ceil(tcs.total / UI.TRIBE_CHANGES_LIMIT);
const pageOpts = [];
for (let i = 1; i <= (page > maxPage ? page : maxPage); i++) {
pageOpts.push(
`<option${
i === page ? ' disabled selected' : ''
} value="${i}">${i}</option>`
);
}
const selectId = `${DialogId.TRIBE_CHANGES}_page`;
window.Dialog.show(
await new DialogTable(
DialogId.TRIBE_CHANGES,
`
<div>
<label>
Page:
<select id="${selectId}">
${pageOpts.join('')}
</select>
</label>
</div>
<table class="vis">
<tbody>
<tr>
<th>${t('Old tribe')}</th>
<th>${t('New tribe')}</th>
<th>${t('Date/time')}</th>
</tr>
${tcs.data
.map(
(tc) => `
<tr>
<td>${
tc.player.tribe
? `<a href="${tc.player.tribe.profileUrl}">${tc.player.tribe.tag}</a>`
: '-'
}</td>
<td>${
tc.newTribe
? `<a href="${tc.newTribe.profileUrl}">${tc.newTribe.tag}</a>`
: '-'
}</td>
<td>${new Date(tc.createdAt).toLocaleString()}</td>
</tr>
`
)
.join('')}
</tbody>
</table>
`
);
document
.querySelector('#' + selectId)
?.addEventListener('change', (e: Event) => {
console.log(e.currentTarget);
if (!(e.currentTarget instanceof HTMLSelectElement)) {
return;
}
this._showTribeChanges(parseInt(e.currentTarget.value));
});
[
{
header: t('Old tribe'),
accessor: (tc) =>
tc.player.tribe
? `<a href="${tc.player.tribe.profileUrl}">${tc.player.tribe.tag}</a>`
: '-',
},
{
header: t('New tribe'),
accessor: (tc) =>
tc.newTribe
? `<a href="${tc.newTribe.profileUrl}">${tc.newTribe.tag}</a>`
: '-',
},
{
header: t('Date/time'),
accessor: (tc) => new Date(tc.createdAt).toLocaleString(),
},
],
2,
(page: number, limit: number) => {
return this.connector.tribeChanges(page, limit);
}
).render();
}
private showHistory(e: Event) {