diff --git a/app/components/Sidebar.vue b/app/components/Sidebar.vue index 300c44c..87d5049 100644 --- a/app/components/Sidebar.vue +++ b/app/components/Sidebar.vue @@ -59,10 +59,15 @@ const navigationItems = [ icon: 'mdi:account-circle-outline' }, { - label: 'Rankings', + label: 'Rankings por Período', to: '/ranking-jogos', icon: 'mdi:trophy-outline' }, + { + label: 'Ranking por Plataforma', + to: '/ranking-plataforma', + icon: 'mdi:layers-outline' + }, { label: 'Perfil gamer', to: '/perfil-gamer', diff --git a/app/pages/(protected)/home/index.vue b/app/pages/(protected)/home/index.vue index ce06e55..73282df 100644 --- a/app/pages/(protected)/home/index.vue +++ b/app/pages/(protected)/home/index.vue @@ -221,7 +221,7 @@ -
+
@@ -286,6 +286,7 @@ useHead({ }) const RANKINGS_API_BASE_URL = 'https://api-ranking-jogos-production.up.railway.app/api/v1' +const COMPARE_API_BASE_URL = 'https://ranking-plataforma.onrender.com' const WISHLIST_API_BASE_URL = 'https://gameverse-wishlist-production.up.railway.app' const CATALOG_API_BASE_URL = 'https://catalogo-jogos-sd-production.up.railway.app' const GIFT_CARD_API_BASE_URL = 'https://giftcardapipedro-production.up.railway.app/api' @@ -353,6 +354,12 @@ const gamerProfile = reactive({ data: null }) +const rankingPlataforma = reactive({ + isLoading: true, + error: '', + items: [] +}) + const isRedirecting = ref(false) const userName = computed( @@ -382,6 +389,9 @@ const totalGiftBalance = computed(() => giftCards.items.reduce((sum, card) => sum + Number(card.balance ?? 0), 0) ) const favoriteNames = computed(() => favorites.items.map((item) => item.game_id).filter(Boolean)) +const rankingPlataformaItems = computed(() => + rankingPlataforma.items.slice(0, 3).map((g) => `${g.name} · ${g.platform} · ${g.score}`) +) const catalogNames = computed(() => catalog.items.map((item) => item.title).filter(Boolean)) const giftCardCodes = computed(() => giftCards.items.map((item) => `${item.code} · ${formatCurrency(item.balance)}`).filter(Boolean) @@ -448,6 +458,11 @@ const shortcuts = [ to: '/ranking-jogos', icon: 'mdi:trophy-outline' }, + { + label: 'Ranking por plataforma', + to: '/ranking-plataforma', + icon: 'mdi:layers-outline' + }, { label: 'Novo jogo no catálogo', to: '/catalogo/criar', @@ -496,6 +511,18 @@ const servicePreviews = computed(() => [ empty: 'Nenhum gift card emitido.', to: '/gift-card', action: 'Gerenciar gift cards' + }, + { + badge: 'Plataformas', + badgeClass: 'bg-[rgba(196,184,232,0.56)]', + title: 'Ranking por plataforma', + icon: 'mdi:layers-outline', + loading: rankingPlataforma.isLoading, + error: rankingPlataforma.error, + items: rankingPlataformaItems.value, + empty: 'Nenhum dado disponível.', + to: '/ranking-plataforma', + action: 'Ver ranking completo' } ]) @@ -619,6 +646,24 @@ async function fetchGiftCards() { } } +async function fetchRankingPlataforma() { + rankingPlataforma.isLoading = true + rankingPlataforma.error = '' + + try { + const data = await $fetch(`${COMPARE_API_BASE_URL}/compare`, { + headers: authHeaders() + }) + rankingPlataforma.items = Array.isArray(data?.data) ? data.data : [] + } catch (error) { + if (await tratarErroAuth(error)) return + rankingPlataforma.items = [] + rankingPlataforma.error = error?.data?.message ?? 'Erro ao carregar ranking por plataforma.' + } finally { + rankingPlataforma.isLoading = false + } +} + async function fetchGamerProfile() { gamerProfile.isLoading = true gamerProfile.error = '' @@ -648,7 +693,8 @@ onMounted(() => { fetchFavorites(), fetchCatalog(), fetchGiftCards(), - fetchGamerProfile() + fetchGamerProfile(), + fetchRankingPlataforma() ]) }) diff --git a/app/pages/(protected)/ranking-jogos/index.vue b/app/pages/(protected)/ranking-jogos/index.vue index 67db2e8..5743cfb 100644 --- a/app/pages/(protected)/ranking-jogos/index.vue +++ b/app/pages/(protected)/ranking-jogos/index.vue @@ -17,7 +17,7 @@ Ranking de jogos

- Acompanhe os jogos por período, plataforma e volume de jogadores ativos. + Acompanhe os jogos por período e volume de jogadores ativos.

@@ -181,41 +181,6 @@ const rankingOptions = [ badge: 'Ano', title: 'Ranking anual' }, - { - label: 'Steam', - value: 'steam', - endpoint: '/rankings/platforms/Steam', - badge: 'Steam', - title: 'Ranking da Steam' - }, - { - label: 'Epic Games', - value: 'epic-games', - endpoint: '/rankings/platforms/Epic Games', - badge: 'Epic Games', - title: 'Ranking da Epic Games' - }, - { - label: 'Riot Launcher', - value: 'riot-launcher', - endpoint: '/rankings/platforms/Riot Launcher', - badge: 'Riot Launcher', - title: 'Ranking da Riot Launcher' - }, - { - label: 'Multiplataforma', - value: 'multi-platform', - endpoint: '/rankings/platforms/Multiplataforma', - badge: 'Multiplataforma', - title: 'Ranking multiplataforma' - }, - { - label: 'Battle.net', - value: 'battle-net', - endpoint: '/rankings/platforms/Battle.net', - badge: 'Battle.net', - title: 'Ranking da Battle.net' - }, { label: 'Mais jogados', value: 'most-played', diff --git a/app/pages/(protected)/ranking-plataforma/index.vue b/app/pages/(protected)/ranking-plataforma/index.vue new file mode 100644 index 0000000..a58cc58 --- /dev/null +++ b/app/pages/(protected)/ranking-plataforma/index.vue @@ -0,0 +1,318 @@ + + + diff --git a/package-lock.json b/package-lock.json index af6a271..0f04803 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "zod": "^3.25.76" }, "devDependencies": { + "@iconify-json/mdi": "^1.2.3", "@types/node": "^25.6.0", "prettier": "^3.8.3", "prettier-plugin-tailwindcss": "^0.8.0" @@ -82,6 +83,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -579,36 +581,12 @@ "integrity": "sha512-/B8YJGPzaYq1NbsQmwgP8EZqg40NpTw4ZB3suuI0TplbxKHeK94jeaawLmVhCv+YwUnOpiWEz9U6SeThku/8JQ==", "license": "MIT" }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -1029,6 +1007,16 @@ "node": ">=18" } }, + "node_modules/@iconify-json/mdi": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@iconify-json/mdi/-/mdi-1.2.3.tgz", + "integrity": "sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@iconify/types": "*" + } + }, "node_modules/@iconify/collections": { "version": "1.0.677", "resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.677.tgz", @@ -1488,6 +1476,7 @@ "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.4.2.tgz", "integrity": "sha512-5+IPRNX2CjkBhuWUwz0hBuLqiaJPRoKzQ+SvcdrQDbAyE+VDeFt74VpSFr5/R0ujrK4b+XnSHUJWdS72w6hsog==", "license": "MIT", + "peer": true, "dependencies": { "c12": "^3.3.3", "consola": "^3.4.2", @@ -1572,6 +1561,7 @@ "resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-4.4.2.tgz", "integrity": "sha512-/q6C7Qhiricgi+PKR7ovBnJlKTL0memCbA1CzRT+itCW/oeYzUfeMdQ35mGntlBoyRPNrMXbzuSUhfDbSCU57w==", "license": "MIT", + "peer": true, "dependencies": { "@vue/shared": "^3.5.30", "defu": "^6.1.4", @@ -3190,19 +3180,6 @@ "giget": "dist/cli.mjs" } }, - "node_modules/@prisma/config/node_modules/magicast": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", - "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/parser": "^7.25.4", - "@babel/types": "^7.25.4", - "source-map-js": "^1.2.0" - } - }, "node_modules/@prisma/config/node_modules/perfect-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", @@ -4008,6 +3985,7 @@ "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.19.0" } @@ -4500,6 +4478,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4833,6 +4812,7 @@ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "license": "Apache-2.0", + "peer": true, "peerDependencies": { "bare-abort-controller": "*" }, @@ -5030,6 +5010,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -5131,6 +5112,7 @@ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -5310,7 +5292,8 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz", "integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/cliui": { "version": "9.0.1", @@ -8297,6 +8280,7 @@ "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.4.2.tgz", "integrity": "sha512-iWVFpr/YEqVU/CenqIHMnIkvb2HE/9f+q8oxZ+pj2et+60NljGRClCgnmbvGPdmNFE0F1bEhoBCYfqbDOCim3Q==", "license": "MIT", + "peer": true, "dependencies": { "@dxup/nuxt": "^0.4.0", "@nuxt/cli": "^3.34.0", @@ -8549,6 +8533,7 @@ "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.117.0.tgz", "integrity": "sha512-l3cbgK5wUvWDVNWM/JFU77qDdGZK1wudnLsFcrRyNo/bL1CyU8pC25vDhMHikVY29lbK2InTWsX42RxVSutUdQ==", "license": "MIT", + "peer": true, "dependencies": { "@oxc-project/types": "^0.117.0" }, @@ -8747,6 +8732,7 @@ "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", "license": "MIT", + "peer": true, "dependencies": { "@vue/devtools-api": "^7.7.7" }, @@ -8869,6 +8855,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -9412,6 +9399,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9475,6 +9463,7 @@ "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -9582,6 +9571,7 @@ "integrity": "sha512-aRvldGE5UUJTtVmFiH3WfNFNiqFlAtePUxcI0UEGlnXCX7DqhiMT5TRYwncHFeA/Reca5W6ToXXyCMTeFPdSXA==", "hasInstallScript": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@prisma/config": "6.16.2", "@prisma/engines": "6.16.2" @@ -10095,6 +10085,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -10893,6 +10884,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", "license": "MIT", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -11780,6 +11772,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -12144,6 +12137,7 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.32", "@vue/compiler-sfc": "3.5.32", @@ -12433,6 +12427,7 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "license": "ISC", + "peer": true, "bin": { "yaml": "bin.mjs" }, @@ -12526,6 +12521,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 4922699..5e81e11 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "zod": "^3.25.76" }, "devDependencies": { + "@iconify-json/mdi": "^1.2.3", "@types/node": "^25.6.0", "prettier": "^3.8.3", "prettier-plugin-tailwindcss": "^0.8.0"