diff --git a/src/utils/ApiRequests.js b/src/utils/ApiRequests.ts similarity index 80% rename from src/utils/ApiRequests.js rename to src/utils/ApiRequests.ts index 77e8d68..f70c701 100644 --- a/src/utils/ApiRequests.js +++ b/src/utils/ApiRequests.ts @@ -1,12 +1,21 @@ import axios from "axios"; import { StatusCodes as STATUS } from "http-status-codes"; -import { AUTHCODE_REGEX, SHARECODE_REGEX } from "/src/constants"; +import { AUTHCODE_REGEX, SHARECODE_REGEX } from "@/constants"; +import type { Store } from "vuex"; +import type { Match, MatchChat, MatchWeapons, Player, PlayerMeta } from "@/api"; +import type { RootState } from "@/stores/matchDetails"; const API_URL = import.meta.env.VITE_API_URL; // /player/ GET returns player details (last 10 matches) -export const GetUser = async (store, id) => { - let response = null; +export const GetUser = async ( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/ban-types + store: Store<"playerDetails", RootState, {}, {}>, + id: string +): Promise => { + let response: Player | null = null; await axios .get(`${API_URL}/player/${id}`) @@ -43,8 +52,12 @@ export const GetUser = async (store, id) => { }; // /player//meta/ GET returns player meta-stats with -export const GetPlayerMeta = async (store, player_id, limit = 4) => { - let response = null; +export const GetPlayerMeta = async ( + store: Store, + player_id: string, + limit = 4 +): Promise => { + let response: PlayerMeta | null = null; await axios .get(`${API_URL}/player/${player_id}/meta/${limit}`) @@ -81,8 +94,12 @@ export const GetPlayerMeta = async (store, player_id, limit = 4) => { }; // /player//next/ GET returns 20 matches after for player -export const LoadMoreMatches = async (store, player_id, date) => { - let response = null; +export const LoadMoreMatches = async ( + store: Store, + player_id: string, + date: number +): Promise => { + let response: Player | null = null; await axios .get(`${API_URL}/player/${player_id}/next/${date}`) @@ -119,8 +136,13 @@ export const LoadMoreMatches = async (store, player_id, date) => { }; // /player//track POST Track player FORM_DATA: authcode, [sharecode] -export const TrackMe = async (store, id64, authcode, sharecode = "") => { - let status = null; +export const TrackMe = async ( + store: Store, + id64: string, + authcode: string, + sharecode = "" +): Promise => { + let status: number | null = null; let message = ""; if (sharecode !== "" && !SHARECODE_REGEX.test(sharecode)) { @@ -184,8 +206,11 @@ export const TrackMe = async (store, id64, authcode, sharecode = "") => { }; // /match/ GET returns details for match -export const GetMatchDetails = async (store, match_id) => { - let response = null; +export const GetMatchDetails = async ( + store: Store, + match_id: string +): Promise => { + let response: Match | null = null; await axios .get(`${API_URL}/match/${match_id}`) @@ -221,9 +246,19 @@ export const GetMatchDetails = async (store, match_id) => { return response; }; +type MatchRounds = { + rounds: { + [round: string]: { + [player: string]: Array<{ equip: number; spent: number; bank: number }>; + }; + }; +}; // /match//rounds GET returns round-stats for match -export const GetPlayerValue = async (store, match_id) => { - let response = null; +export const GetPlayerValue = async ( + store: Store, + match_id: string +): Promise => { + let response: MatchRounds | null = null; await axios .get(`${API_URL}/match/${match_id}/rounds`) @@ -260,8 +295,11 @@ export const GetPlayerValue = async (store, match_id) => { }; // /match//weapons GET returns weapon-stats for match -export const GetWeaponDmg = async (store, match_id) => { - let response = null; +export const GetWeaponDmg = async ( + store: Store, + match_id: string +): Promise => { + let response: MatchWeapons | null = null; await axios .get(`${API_URL}/match/${match_id}/weapons`) @@ -298,8 +336,11 @@ export const GetWeaponDmg = async (store, match_id) => { }; // /match//chat GET returns chat history for match -export const GetChatHistory = async (store, match_id) => { - let response = null; +export const GetChatHistory = async ( + store: Store, + match_id: string +): Promise => { + let response: MatchChat | null = null; await axios .get(`${API_URL}/match/${match_id}/chat`) @@ -336,8 +377,11 @@ export const GetChatHistory = async (store, match_id) => { }; // /matches//chat/ GET returns chat history for match with translated sections -export const GetChatHistoryTranslated = async (store, match_id) => { - let response = null; +export const GetChatHistoryTranslated = async ( + store: Store, + match_id: string +): Promise => { + let response: MatchChat | null = null; await axios .get(`${API_URL}/match/${match_id}/chat?translate=1`) @@ -374,8 +418,13 @@ export const GetChatHistoryTranslated = async (store, match_id) => { }; // /matches GET returns last 20 matches in DB -export const GetMatches = async (store) => { - let response = null; +export const GetMatches = async ( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/ban-types + store: Store<"matchDetails", RootState, {}, {}> +): Promise => { + let response: Match[] | null = null; await axios .get(`${API_URL}/matches`) @@ -409,8 +458,14 @@ export const GetMatches = async (store) => { }; // /matches/next/ GET returns 20 matches after time -export const LoadMoreMatchesExplore = async (store, date) => { - let response = null; +export const LoadMoreMatchesExplore = async ( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/ban-types + store: Store<"matchDetails", RootState, {}, {}>, + date: number +): Promise => { + let response: Match[] | null = null; await axios .get(`${API_URL}/matches/next/${date}`) diff --git a/src/utils/DateTime.js b/src/utils/DateTime.ts similarity index 62% rename from src/utils/DateTime.js rename to src/utils/DateTime.ts index a60431f..37c9b4e 100644 --- a/src/utils/DateTime.js +++ b/src/utils/DateTime.ts @@ -1,6 +1,9 @@ -import { DateTime, Duration } from "luxon/build/es6/luxon"; +import { DateTime, Duration } from "luxon"; -export const ConvertTickToTime = (tick, rate = 64) => { +export const ConvertTickToTime = ( + tick: number, + rate = 64 +): string | undefined => { const time = Duration.fromObject({ hours: 0, minutes: 0, @@ -11,16 +14,22 @@ export const ConvertTickToTime = (tick, rate = 64) => { else if (time.hours < 1) return time.toFormat("mm:ss"); }; -export const FormatDuration = (d) => { - const duration = Duration.fromObject({ hours: 0, minutes: 0, seconds: d }) - .normalize() - .toObject(); +export const FormatDuration = (d: number): string | undefined => { + const duration = Duration.fromObject({ + hours: 0, + minutes: 0, + seconds: d, + }).normalize(); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore if (duration.hours > 1) return `${duration.hours} h ${duration.minutes} min`; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore else if (duration.hours < 1) return `${duration.minutes} min`; }; -export const FormatFullDuration = (d) => { +export const FormatFullDuration = (d: number): string | undefined => { const duration = Duration.fromObject({ hours: 0, minutes: 0, @@ -31,7 +40,7 @@ export const FormatFullDuration = (d) => { else if (duration.hours < 1) return duration.toFormat("mm:ss"); }; -export const FormatDate = (date) => { +export const FormatDate = (date: number): string => { const matchDate = DateTime.fromSeconds(date || 0); const diff = DateTime.now().diff(matchDate); @@ -42,10 +51,10 @@ export const FormatDate = (date) => { month: "2-digit", year: "numeric", }); - else return matchDate.toRelative(); + else return matchDate.toRelative() || ""; }; -export const FormatFullDate = (date) => { +export const FormatFullDate = (date: number): string => { const matchDate = DateTime.fromSeconds(date || 0); return matchDate.toLocaleString({ @@ -59,18 +68,18 @@ export const FormatFullDate = (date) => { }); }; -export const FormatVacDate = (date, match) => { +export const FormatVacDate = (date: number, match: number): string => { const vacDate = DateTime.fromSeconds(date || 0); const matchDate = DateTime.fromSeconds(match || 0); if (vacDate.diff(matchDate).as("days") >= -30) { - return vacDate.toRelative(); + return vacDate.toRelative() || ""; } else { return ""; } }; -export const MatchNotParsedTime = (match) => { +export const MatchNotParsedTime = (match: number): boolean => { const matchDate = DateTime.fromSeconds(match || 0); return matchDate.diffNow().as("hours") >= -2; diff --git a/src/utils/Display.js b/src/utils/Display.ts similarity index 82% rename from src/utils/Display.js rename to src/utils/Display.ts index a002c1c..2894de6 100644 --- a/src/utils/Display.js +++ b/src/utils/Display.ts @@ -1,4 +1,4 @@ -export const DisplayRank = (rankNr = 0) => { +export const DisplayRank = (rankNr = 0): Array => { const rankMap = new Map([ [0, "Unranked"], [1, "Silver I"], @@ -23,7 +23,7 @@ export const DisplayRank = (rankNr = 0) => { return [`/images/rank_icons/skillgroup${rankNr}.svg`, rankMap.get(rankNr)]; }; -export const DisplayWeapon = (weaponId) => { +export const DisplayWeapon = (weaponId: number): string => { const wepaonMap = new Map([ [1, "p2000"], [2, "glock"], @@ -63,16 +63,12 @@ export const DisplayWeapon = (weaponId) => { [310, "scar20"], [311, "g3sg1"], ]); - if (wepaonMap.get(weaponId)) { - return `/images/weapons/${wepaonMap.get(weaponId)}.svg`; - } else { - weaponId; - } + return `/images/weapons/${wepaonMap.get(weaponId) || ""}.svg`; }; -export const LoadImage = (mapName) => { - let img = new Image(); - let background = document.querySelector(".bg-img"); +export const LoadImage = (mapName: string): void => { + const img = new Image(); + const background = document.querySelector(".bg-img") as HTMLImageElement; img.onload = function () { if (background) { diff --git a/src/utils/GoTo.js b/src/utils/GoTo.ts similarity index 52% rename from src/utils/GoTo.js rename to src/utils/GoTo.ts index a5af574..7275614 100644 --- a/src/utils/GoTo.js +++ b/src/utils/GoTo.ts @@ -1,17 +1,17 @@ import router from "../router"; -export const GoToMatch = (id) => { +export const GoToMatch = (id: string): void => { router.push({ name: "Match", params: { match_id: id } }); }; -export const GoToPlayer = (id) => { +export const GoToPlayer = (id: string): void => { router.push({ name: "Player", params: { id: id } }); }; -export const GoToError = (code) => { +export const GoToError = (code: string): void => { router.push({ name: code }); }; -export const GoToLink = (link) => { +export const GoToLink = (link: string): void => { router.replace(link); }; diff --git a/src/utils/HLTV.js b/src/utils/HLTV.ts similarity index 95% rename from src/utils/HLTV.js rename to src/utils/HLTV.ts index 41b2861..30eb5ce 100644 --- a/src/utils/HLTV.js +++ b/src/utils/HLTV.ts @@ -1,12 +1,12 @@ export const GetHLTV_1 = ( kills = 0, - rounds, + rounds: number, deaths = 0, k2 = 0, k3 = 0, k4 = 0, k5 = 0 -) => { +): string => { const k1 = kills - k2 - k3 - k4 - k5; const Weight_KPR = 0.679; // weight kills per round const Weight_SPR = 0.317; // weight survived rounds per round diff --git a/src/utils/LocalStorage.js b/src/utils/LocalStorage.js deleted file mode 100644 index e009af4..0000000 --- a/src/utils/LocalStorage.js +++ /dev/null @@ -1,31 +0,0 @@ -export const SaveLastVisitedToLocalStorage = (data) => { - let a = JSON.parse(localStorage.getItem("recent-visited")) || []; - - if (a.length === 0) { - a.unshift(data); - } else if (a.length === 9) { - if (a.find((p) => p.steamid64 === data.steamid64)) { - a.shift(); - a.splice( - a.findIndex((i) => i.steamid64 === data.steamid64), - 1 - ); - a.unshift(data); - } else if (!a.find((p) => p.steamid64 === data.steamid64)) { - a.shift(); - a.unshift(data); - } - } else if (a.length > 0 && a.length < 9) { - if (a.find((p) => p.steamid64 === data.steamid64)) { - a.splice( - a.findIndex((i) => i.steamid64 === data.steamid64), - 1 - ); - a.unshift(data); - } else if (!a.find((p) => p.steamid64 === data.steamid64)) { - a.unshift(data); - } - } - - localStorage.setItem("recent-visited", JSON.stringify(a)); -}; diff --git a/src/utils/LocalStorage.ts b/src/utils/LocalStorage.ts new file mode 100644 index 0000000..e9b5cee --- /dev/null +++ b/src/utils/LocalStorage.ts @@ -0,0 +1,33 @@ +import type { Player } from "@/api"; + +export const SaveLastVisitedToLocalStorage = (data: Player): void => { + const a = JSON.parse(localStorage.getItem("recent-visited") || "") || []; + + if (a.length === 0) { + a.unshift(data); + } else if (a.length === 9) { + if (a.find((p: Player) => p.steamid64 === data.steamid64)) { + a.shift(); + a.splice( + a.findIndex((p: Player) => p.steamid64 === data.steamid64), + 1 + ); + a.unshift(data); + } else if (!a.find((p: Player) => p.steamid64 === data.steamid64)) { + a.shift(); + a.unshift(data); + } + } else if (a.length > 0 && a.length < 9) { + if (a.find((p: Player) => p.steamid64 === data.steamid64)) { + a.splice( + a.findIndex((p: Player) => p.steamid64 === data.steamid64), + 1 + ); + a.unshift(data); + } else if (!a.find((p: Player) => p.steamid64 === data.steamid64)) { + a.unshift(data); + } + } + + localStorage.setItem("recent-visited", JSON.stringify(a)); +}; diff --git a/src/utils/Utils.js b/src/utils/Utils.js deleted file mode 100644 index 51fea98..0000000 --- a/src/utils/Utils.js +++ /dev/null @@ -1,125 +0,0 @@ -import { GoToError } from "/src/utils/GoTo"; - -export const errorHandling = (code) => { - if (code === 404) { - GoToError("404"); - } else if (code === 500) { - GoToError("500"); - } else if (code === 502) { - GoToError("502"); - } else { - GoToError("404"); - } -}; - -export const setTitle = (title) => { - document.title = `${title} | csgoWTF`; -}; - -export const closeNav = (navSelector) => { - const nav = document.getElementById(navSelector); - if (nav) if (nav.classList.contains("show")) nav.classList.remove("show"); -}; - -export const GetWinLoss = (matchResult, teamId) => { - if (matchResult === teamId) { - return "win"; - } else if (matchResult === 0) { - return "draw"; - } else { - return "loss"; - } -}; - -export const truncate = (str, len, ending) => { - if (len == null) len = 100; - - if (ending == null) ending = ".."; - - if (str.length > len) return str.substring(0, len - ending.length) + ending; - else return str; -}; - -export const checkStatEmpty = (stat) => { - if (stat) return stat; - return 0; -}; - -export const FixMapName = (map) => { - return map.split("_")[1].replace(/^\w/, (c) => c.toUpperCase()); -}; - -export const getPlayerArr = (stats, team, color) => { - let arr = []; - for (let i = (team - 1) * 5; i < team * 5; i++) { - arr.push({ - value: truncate(stats[i].player.name, 12), - textStyle: { - color: color - ? getComputedStyle(document.documentElement).getPropertyValue( - `--csgo-${stats[i].color}` - ) - : "white", - }, - }); - } - arr.reverse(); - return arr; -}; - -export const constructAvatarUrl = (hash, size) => { - const base = - "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars"; - const imgSize = size ? `_${size}` : ""; - - if (hash) { - const hashDir = hash.substring(0, 2); - - return `${base}/${hashDir}/${hash}${imgSize}.jpg`; - } -}; - -export const sortObjectValue = (obj, direction = "asc") => { - const sortable = []; - for (let key in obj) { - sortable.push([key, obj[key]]); - } - - if (direction === "asc") { - sortable.sort((a, b) => { - return a[1] - b[1]; - }); - } - if (direction === "desc") { - sortable.sort((a, b) => { - return b[1] - a[1]; - }); - } - - return sortable; -}; - -export const CreatePlayersArray = (stats) => { - let arr = []; - for (let i in stats) { - arr.push({ team_id: stats[i].team_id, player: stats[i].player }); - } - return arr; -}; - -export const scrollToPos = (pos = 0) => { - window.scrollTo({ - top: pos, - left: 0, - behavior: "smooth", - }); -}; - -export const StripControlCodes = (str = "") => { - const regexpControl = /\p{C}/gu; - return str.replace(regexpControl, ""); -}; - -export const ProcessName = (str = "") => { - return StripControlCodes(str).trim(); -}; diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts new file mode 100644 index 0000000..fb6ea18 --- /dev/null +++ b/src/utils/Utils.ts @@ -0,0 +1,160 @@ +import { GoToError } from "@/utils/GoTo"; +import type { Player, Stats } from "@/api"; + +enum ErrorPage { + INTERNAL_SERVER_ERROR = 500, + BAD_GATEWAY = 502, +} +export const errorHandling = (code: number): void => { + if (code === ErrorPage.INTERNAL_SERVER_ERROR) { + GoToError("500"); + } else if (code === ErrorPage.BAD_GATEWAY) { + GoToError("502"); + } else { + GoToError("404"); + } +}; + +export const setTitle = (title: string): void => { + document.title = `${title} | csgoWTF`; +}; + +export const closeNav = (navSelector: string): void => { + const nav = document.getElementById(navSelector); + if (nav) if (nav.classList.contains("show")) nav.classList.remove("show"); +}; + +export const closeNavEventListener = (navSelector: string): void => { + document.addEventListener("click", (e: MouseEvent) => { + const divElem = e.target as HTMLDivElement; + const mainNav = divElem.querySelector( + `#${navSelector}` + ) as HTMLDivElement | null; + if (mainNav === null) { + closeNav(navSelector); + } + }); +}; + +enum WLD { + WIN = "win", + LOSS = "loss", + DRAW = "draw", +} +export const GetWinLoss = (matchResult: number, teamId: number): WLD => { + if (matchResult === teamId) { + return WLD.WIN; + } else if (matchResult === 0) { + return WLD.DRAW; + } else { + return WLD.LOSS; + } +}; + +export const truncate = (str: string, len: number, ending = ".."): string => { + if (len == null) len = 100; + + if (str.length > len) return str.substring(0, len - ending.length) + ending; + else return str; +}; + +export const checkStatEmpty = (stat: never): never | number => { + if (stat) return stat; + return 0; +}; + +export const FixMapName = (map: string): string => { + return map.split("_")[1].replace(/^\w/, (c) => c.toUpperCase()); +}; + +type PlayerArrayType = { + value: string; + textStyle: PlayerArrayTextStyle; +}; +type PlayerArrayTextStyle = { + color: string; +}; +export const getPlayerArr = ( + stats: Stats[], + team: number, + color = false +): PlayerArrayType[] => { + const arr: PlayerArrayType[] = []; + for (let i = (team - 1) * 5; i < team * 5; i++) { + arr.push({ + value: truncate(stats[i].player?.name || "", 12), + textStyle: { + color: color + ? getComputedStyle(document.documentElement).getPropertyValue( + `--csgo-${stats[i].color}` + ) + : "white", + }, + }); + } + arr.reverse(); + return arr; +}; + +export const constructAvatarUrl = (hash: string, size: number): string => { + let output = ""; + const base = + "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars"; + const imgSize = size ? `_${size}` : ""; + + if (hash) { + const hashDir = hash.substring(0, 2); + output = `${base}/${hashDir}/${hash}${imgSize}.jpg`; + } + return output; +}; + +export const sortObjectValue = ( + obj: Record, + direction = "asc" +): Array<[string, number]> => { + const sortable: Array<[string, number]> = []; + for (const key in obj) { + sortable.push([key, obj[key]]); + } + + if (direction === "asc") { + sortable.sort((a, b) => { + return a[1] - b[1]; + }); + } + if (direction === "desc") { + sortable.sort((a, b) => { + return b[1] - a[1]; + }); + } + + return sortable; +}; + +export const CreatePlayersArray = ( + stats: Stats[] +): Array> => { + const arr: Array> = []; + for (let i = 0; i < stats.length; i++) { + arr.push({ team_id: stats[i].teamId, player: stats[i].player }); + } + return arr; +}; + +export const scrollToPos = (pos = 0): void => { + window.scrollTo({ + top: pos, + left: 0, + behavior: "smooth", + }); +}; + +export const StripControlCodes = (str = ""): string => { + const regexpControl = /\p{C}/gu; + return str.replace(regexpControl, ""); +}; + +export const ProcessName = (str = ""): string => { + return StripControlCodes(str).trim(); +}; diff --git a/src/utils/index.js b/src/utils/index.js deleted file mode 100644 index f905603..0000000 --- a/src/utils/index.js +++ /dev/null @@ -1,85 +0,0 @@ -import { - ConvertTickToTime, - FormatDate, - FormatDuration, - FormatFullDate, - FormatFullDuration, - FormatVacDate, - MatchNotParsedTime, -} from "./DateTime"; -import { GoToLink, GoToMatch, GoToPlayer } from "./GoTo"; -import { SaveLastVisitedToLocalStorage } from "./LocalStorage"; -import { GetHLTV_1 } from "./HLTV"; -import { DisplayRank, DisplayWeapon, LoadImage } from "./Display"; -import { - GetChatHistory, - GetChatHistoryTranslated, - GetMatchDetails, - GetMatches, - GetPlayerMeta, - GetPlayerValue, - GetUser, - GetWeaponDmg, - LoadMoreMatches, - LoadMoreMatchesExplore, - TrackMe, -} from "./ApiRequests"; -import { - checkStatEmpty, - closeNav, - constructAvatarUrl, - CreatePlayersArray, - errorHandling, - FixMapName, - getPlayerArr, - GetWinLoss, - ProcessName, - scrollToPos, - setTitle, - sortObjectValue, - StripControlCodes, - truncate, -} from "./Utils"; - -export { - MatchNotParsedTime, - GetChatHistoryTranslated, - GetChatHistory, - ConvertTickToTime, - FormatDate, - FormatFullDuration, - FormatFullDate, - FormatDuration, - FormatVacDate, - GoToMatch, - GoToPlayer, - GoToLink, - SaveLastVisitedToLocalStorage, - GetHLTV_1, - DisplayRank, - LoadImage, - GetUser, - TrackMe, - GetPlayerValue, - DisplayWeapon, - LoadMoreMatches, - GetPlayerMeta, - GetMatchDetails, - setTitle, - GetWinLoss, - truncate, - checkStatEmpty, - getPlayerArr, - constructAvatarUrl, - FixMapName, - closeNav, - sortObjectValue, - GetWeaponDmg, - CreatePlayersArray, - GetMatches, - LoadMoreMatchesExplore, - scrollToPos, - StripControlCodes, - ProcessName, - errorHandling, -}; diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..0956284 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,7 @@ +export * from "./ApiRequests"; +export * from "./DateTime"; +export * from "./Display"; +export * from "./GoTo"; +export * from "./HLTV"; +export * from "./LocalStorage"; +export * from "./Utils";