diff --git a/src/newui/src/api/demo.ts b/src/newui/src/api/demo.ts new file mode 100644 index 0000000..3aecdd0 --- /dev/null +++ b/src/newui/src/api/demo.ts @@ -0,0 +1,20 @@ +import { ApiRequestParams } from '@/types/api'; +import { DemoApiResponse, DemoStats } from '@/types/demo'; + +import { api } from 'boot/axios'; + +export const DemoApi = { + list: async (steamId: string, params: ApiRequestParams = { limit: 50, offset: 0 }): Promise => { + const { data } = await api.get(`player/${steamId}/demos`, { + params, + }); + + return data; + }, + + details: async (demoId: number): Promise => { + const { data } = await api.get(`demo/${demoId}/stats/`); + + return data; + }, +}; diff --git a/src/newui/src/api/player.ts b/src/newui/src/api/player.ts index ef2f338..c1f83fb 100644 --- a/src/newui/src/api/player.ts +++ b/src/newui/src/api/player.ts @@ -4,7 +4,7 @@ import type { PlayerApiResponse, PlayerInfoResponse, PlayerStats, PlayerTeamMate import { api } from 'boot/axios'; export const PlayerApi = { - get: async (params: ApiRequestParams = { limit: 50, offset: 0 }): Promise => { + list: async (params: ApiRequestParams = { limit: 50, offset: 0 }): Promise => { const { data } = await api.get('players', { params, }); diff --git a/src/newui/src/components/Player/Demos.vue b/src/newui/src/components/Player/Demos.vue index 5a55d80..0854c6a 100644 --- a/src/newui/src/components/Player/Demos.vue +++ b/src/newui/src/components/Player/Demos.vue @@ -1,7 +1,105 @@ - + diff --git a/src/newui/src/components/common/DataTable.vue b/src/newui/src/components/common/DataTable.vue index 8daa1a6..47fae66 100644 --- a/src/newui/src/components/common/DataTable.vue +++ b/src/newui/src/components/common/DataTable.vue @@ -4,34 +4,34 @@ import debounce from 'lodash/debounce'; import snakeCase from 'lodash/snakeCase'; import get from 'lodash/get'; import { useQuasar } from 'quasar'; -import { onMounted, ref } from 'vue'; +import { computed, onMounted, ref } from 'vue'; import { DataTableHeader, DataTablePagination, DataTableRequestDetails } from '@/types/dataTable'; import notification from 'src/utils/notification'; +import { has } from 'lodash'; /* ====================== Data ====================== */ -const props = defineProps({ - columns: { - type: Array as () => DataTableHeader[], - required: true, - }, - apiCall: { - type: Function as () => any, - required: true, - }, - entityName: { - type: String, - required: true, - }, -}); +const props = withDefaults( + defineProps<{ + columns: DataTableHeader[]; + apiCall: (params: any) => any; + entityName: string; + rowsPerPage?: number | string; + addActionsSlot?: boolean; + }>(), + { + rowsPerPage: 20, + addActionsSlot: false, + } +); const tableRef = ref(); const items = ref([]); const pagination = ref({ page: 1, - rowsPerPage: 20, + rowsPerPage: props.rowsPerPage, sortBy: '', descending: false, } as DataTablePagination); @@ -43,6 +43,26 @@ if (props.entityName && $q.localStorage.has(entityListSortKey)) { pagination.value.sortBy = $q.localStorage.getItem(entityListSortKey) as string; } +const headers = computed(() => { + let headers: DataTableHeader[] = props.columns.map((el) => { + if (!has(el, 'align')) { + el.align = 'center'; + } + + if (!has(el, 'field')) { + el.field = el.name; + } + + return el; + }); + + if (props.addActionsSlot) { + headers = headers.concat([{ classes: 'hs-action', field: 'actions', label: '', name: 'actions', sortable: false }]); + } + + return headers; +}); + /* ====================== Methods ====================== */ const getData = debounce(async (tableProps: DataTableRequestDetails) => { @@ -106,11 +126,11 @@ onMounted(async () => { import { ref } from 'vue'; +import { DEMO_TYPE_IMAGES, DEMO_TYPES } from 'src/constants/demos'; /* ====================== Data ====================== */ @@ -13,36 +14,36 @@ const demoTypes = ref([ label: 'All', }, { - value: 'valve', + value: DEMO_TYPES.VALVE, label: 'Valve', - image: 'images/demoTypes/valve.png', + image: DEMO_TYPE_IMAGES[DEMO_TYPES.VALVE], }, { - value: 'esea', + value: DEMO_TYPES.ESEA, label: 'ESEA', - image: 'images/demoTypes/esea.png', + image: DEMO_TYPE_IMAGES[DEMO_TYPES.ESEA], }, { - value: 'faceit', + value: DEMO_TYPES.FACEIT, label: 'FACEIT', - image: 'images/demoTypes/faceit.png', + image: DEMO_TYPE_IMAGES[DEMO_TYPES.FACEIT], }, { - value: 'cevo', + value: DEMO_TYPES.CEVO, label: 'CEVO', - image: 'images/demoTypes/cevo.png', + image: DEMO_TYPE_IMAGES[DEMO_TYPES.CEVO], }, { - value: 'esportal', + value: DEMO_TYPES.ESPORTAL, label: 'Esportal', - image: 'images/demoTypes/esportal.png', + image: DEMO_TYPE_IMAGES[DEMO_TYPES.ESPORTAL], class: 'bg-blue-500 rounded', style: 'height: 20px', }, { - value: 'custom', + value: DEMO_TYPES.CUSTOM, label: 'Custom', - image: 'images/demoTypes/custom.png', + image: DEMO_TYPE_IMAGES[DEMO_TYPES.CUSTOM], style: 'height: 20px', }, ]); diff --git a/src/newui/src/constants/demos.ts b/src/newui/src/constants/demos.ts new file mode 100644 index 0000000..51e9fa9 --- /dev/null +++ b/src/newui/src/constants/demos.ts @@ -0,0 +1,17 @@ +import { Dictionary } from 'types/common'; + +export const DEMO_TYPES = { + VALVE: 'valve', + ESEA: 'esea', + FACEIT: 'faceit', + CEVO: 'cevo', + ESPORTAL: 'esportal', + CUSTOM: 'custom', +}; + +export const DEMO_TYPE_IMAGES: Dictionary = {}; +DEMO_TYPE_IMAGES[DEMO_TYPES.VALVE] = 'images/demoTypes/valve.png'; +DEMO_TYPE_IMAGES[DEMO_TYPES.ESEA] = 'images/demoTypes/esea.png'; +DEMO_TYPE_IMAGES[DEMO_TYPES.FACEIT] = 'images/demoTypes/faceit.png'; +DEMO_TYPE_IMAGES[DEMO_TYPES.ESPORTAL] = 'images/demoTypes/esportal.png'; +DEMO_TYPE_IMAGES[DEMO_TYPES.CUSTOM] = 'images/demoTypes/custom.png'; diff --git a/src/newui/src/constants/ranks.ts b/src/newui/src/constants/ranks.ts index b455f8f..dbe50a0 100644 --- a/src/newui/src/constants/ranks.ts +++ b/src/newui/src/constants/ranks.ts @@ -1,4 +1,5 @@ export const RANKS = { + 0: 'Unknown', 1: 'Silver I', 2: 'Silver II', 3: 'Silver III', diff --git a/src/newui/src/pages/Player/Details.vue b/src/newui/src/pages/Player/Details.vue index 6212a40..73dd5e2 100644 --- a/src/newui/src/pages/Player/Details.vue +++ b/src/newui/src/pages/Player/Details.vue @@ -239,7 +239,7 @@ provide('steamId', route.params.id); /> - + diff --git a/src/newui/src/pages/Player/List.vue b/src/newui/src/pages/Player/List.vue index 81d6f08..eedd9a5 100644 --- a/src/newui/src/pages/Player/List.vue +++ b/src/newui/src/pages/Player/List.vue @@ -17,17 +17,17 @@ import FolderFilter from 'src/components/filters/FolderFilter.vue'; const tableRef = ref(); const columns = [ - { label: 'Name', name: 'steamInfo', field: 'steamInfo', align: 'left', style: 'width: 35%' }, - { label: 'MM Rank', name: 'lastRank', field: 'lastRank', align: 'center', sortable: true }, - { label: 'Demos', name: 'demos', field: 'demos', align: 'center', sortable: true }, - { label: 'Last Played', name: 'lastTimestamp', field: 'lastTimestamp', align: 'center', sortable: true }, + { label: 'Name', name: 'steamInfo', align: 'left', style: 'width: 35%' }, + { label: 'MM Rank', name: 'lastRank', sortable: true }, + { label: 'Demos', name: 'demos', sortable: true }, + { label: 'Last Played', name: 'lastTimestamp', sortable: true }, ] as DataTableHeader[]; const selectedFolder = ref('All'); /* ====================== Methods ====================== */ const getPlayers = async ({ limit, offset, orderBy }: ApiRequestParams) => { - const { playerCount, players } = await PlayerApi.get({ + const { playerCount, players } = await PlayerApi.list({ ...{ limit, offset, orderBy }, ...(selectedFolder.value !== 'All' ? { folder: selectedFolder.value } : {}), }); diff --git a/src/newui/src/types/dataTable.ts b/src/newui/src/types/dataTable.ts index 352d759..8d3d39f 100644 --- a/src/newui/src/types/dataTable.ts +++ b/src/newui/src/types/dataTable.ts @@ -12,7 +12,7 @@ export type DataTableHeader = { /** * Row Object property to determine value for this column or function which maps to the required property */ - field: string | CallableFunction; + field?: string | CallableFunction; /** * If we use visible-columns, this col will always be visible diff --git a/src/newui/src/types/demo.ts b/src/newui/src/types/demo.ts new file mode 100644 index 0000000..dfa47ea --- /dev/null +++ b/src/newui/src/types/demo.ts @@ -0,0 +1,62 @@ +import { PlayerStats } from '@/types/player'; + +export type RankUpdate = { + numWins: number; + rankChange: number; + rankNew: number; + rankOld: number; +}; + +export type DemoResponse = { + assists: number; + assistsFlash: number; + bannedPlayers: number; + damage: number; + deaths: number; + demoid: number; + entryKills: number; + entryKillsAttempted: number; + folder: string; + hs: number; + hsPercent: number; + kills: number; + map: string; + mmRankUpdate: RankUpdate; + openKills: number; + openKillsAttempted: number; + outcome: string; + path: string; + rating: number; + roundsT: number; + roundsWithDamageInfo: number; + rws: number; + score: number[]; + surrendered: boolean; + timestamp: number; + type: string; + winner: number; +}; + +export type DemoApiResponse = { + demoCount: number; + demos: DemoResponse; +}; + +export type DemoStats = { + demoid: number; + detailedScore: number[][]; + map: string; + path: string; + rounds: { + tick: number; + }[]; + score: number[]; + surrendered: boolean; + teams: { + 2: PlayerStats[]; + 3: PlayerStats[]; + }; + timestamp: number; + type: string; + winner: number; +}; diff --git a/src/newui/src/types/player.ts b/src/newui/src/types/player.ts index aa419eb..2fc7a3b 100644 --- a/src/newui/src/types/player.ts +++ b/src/newui/src/types/player.ts @@ -1,4 +1,5 @@ import { RANKS } from 'src/constants/ranks'; +import { RankUpdate } from '@/types/demo'; export type SteamInfoResponse = { avatar: string; @@ -61,6 +62,9 @@ export type PlayerStats = { name: string; }[]; won: number; + mmRankUpdate?: RankUpdate; + team?: number; + steamid?: string; }; export type PlayerInfoResponse = { diff --git a/src/newui/tsconfig.json b/src/newui/tsconfig.json index 73b1455..b3077ed 100644 --- a/src/newui/tsconfig.json +++ b/src/newui/tsconfig.json @@ -30,6 +30,18 @@ "stores/*": [ "src/stores/*" ], + "api/*": [ + "src/api/*" + ], + "constants/*": [ + "src/constants/*" + ], + "types/*": [ + "src/types/*" + ], + "utils/*": [ + "src/utils/*" + ], } }, "include": [