diff --git a/app/pages/(protected)/favoritos/index.vue b/app/pages/(protected)/favoritos/index.vue new file mode 100644 index 0000000..14d01e4 --- /dev/null +++ b/app/pages/(protected)/favoritos/index.vue @@ -0,0 +1,208 @@ + + + diff --git a/app/pages/(protected)/home/index.vue b/app/pages/(protected)/home/index.vue index 9c884f1..e1a4354 100644 --- a/app/pages/(protected)/home/index.vue +++ b/app/pages/(protected)/home/index.vue @@ -16,7 +16,8 @@ class="my-4 max-w-[680px] break-words font-serif text-[34px] font-light leading-[1.08] tracking-[-0.96px] text-[#0c0a09] sm:my-5 sm:text-[40px] md:text-[48px]"> Olá, você está autenticado! -

+

Estes são os dados retornados pelo perfil da sua sessão atual.

@@ -26,6 +27,10 @@ class="inline-flex h-10 w-fit items-center justify-center rounded-full border border-[#d6d3d1] bg-transparent px-5 text-[15px] font-medium leading-none text-[#0c0a09] transition hover:border-[#0c0a09]"> Ver rankings + + Meus favoritos + +
+ +
+

+ Microsserviço consumido: https://api-ranking-jogos-production.up.railway.app/api/v1 +  ·  Feito por Gabriel e Kaiky +

+ + + Sistema de validação de token funcional + +
@@ -116,6 +138,7 @@ definePageMeta({ }) const RANKINGS_API_BASE_URL = 'https://api-ranking-jogos-production.up.railway.app/api/v1' +const WISHLIST_API_BASE_URL = 'https://gameverse-wishlist-production.up.railway.app' const rankingOptions = [ { @@ -195,6 +218,8 @@ const selectedRanking = ref('weekly') const rankings = ref([]) const isLoading = ref(false) const errorMessage = ref('') +const favoriteIds = ref(new Set()) +const togglingId = ref(null) const selectedRankingMeta = computed(() => { return rankingOptions.find((option) => option.value === selectedRanking.value) ?? rankingOptions[0] @@ -266,8 +291,81 @@ async function fetchRankings() { } } +async function fetchFavorites() { + if (!token.value) return + + try { + const data = await $fetch(`${WISHLIST_API_BASE_URL}/api/wishlist`, { + headers: { + Authorization: `Bearer ${token.value}` + } + }) + + const ids = new Set( + (data?.data ?? []) + .filter((item) => item.is_favorite === 1 || item.is_favorite === true) + .map((item) => item.game_id) + ) + favoriteIds.value = ids + } catch { + // falha silenciosa — favoritos são secundários ao ranking + } +} + +async function toggleFavorite(game) { + if (!token.value) { + await navigateTo('/login') + return + } + + const gameId = game.name + togglingId.value = gameId + + try { + if (favoriteIds.value.has(gameId)) { + await $fetch(`${WISHLIST_API_BASE_URL}/api/wishlist/${encodeURIComponent(gameId)}`, { + method: 'DELETE', + headers: { + Authorization: `Bearer ${token.value}` + } + }) + favoriteIds.value = new Set([...favoriteIds.value].filter((id) => id !== gameId)) + $toast.success(`${gameId} removido dos favoritos.`, { duration: 4000 }) + } else { + await $fetch(`${WISHLIST_API_BASE_URL}/api/wishlist`, { + method: 'POST', + headers: { + Authorization: `Bearer ${token.value}` + }, + body: { + game_id: gameId, + is_wishlist: false, + is_favorite: true, + price_alert: false + } + }) + favoriteIds.value = new Set([...favoriteIds.value, gameId]) + $toast.success(`${gameId} adicionado aos favoritos!`, { duration: 4000 }) + } + } catch (error) { + const statusCode = error?.statusCode ?? error?.response?.status ?? error?.data?.statusCode + + if (statusCode === 401) { + clearToken() + $toast.error('Sua sessão expirou. Faça login novamente.', { duration: 8000 }) + await navigateTo('/login') + return + } + + $toast.error('Erro ao atualizar favoritos. Tente novamente.', { duration: 6000 }) + } finally { + togglingId.value = null + } +} + onMounted(() => { fetchRankings() + fetchFavorites() }) watch(selectedRanking, () => {