diff --git a/src/lib/components/BotonSeguir.svelte b/src/lib/components/BotonSeguir.svelte new file mode 100644 index 0000000..0e31a04 --- /dev/null +++ b/src/lib/components/BotonSeguir.svelte @@ -0,0 +1,96 @@ + + +{#if mensajeError} + +{/if} + +{#if post.authorName !== $sesionStore?.username && post.authorName !== '[deleted]'} + + + + + + {#if seguido == true} + Dejar de seguir + {:else} + Seguir + {/if} + + +{/if} diff --git a/src/lib/components/PostCard.svelte b/src/lib/components/PostCard.svelte index 4ab90ca..a97fa1b 100644 --- a/src/lib/components/PostCard.svelte +++ b/src/lib/components/PostCard.svelte @@ -32,6 +32,7 @@ import { likePost } from '@/hooks/likePost'; import { goto } from '$app/navigation'; import { resolve } from '$app/paths'; + import BotonSeguir from './BotonSeguir.svelte'; interface postProp { post: Post; @@ -43,7 +44,6 @@ let cargandoBorrar = $state(false); let mensajeError = $state(''); - let cargandoEditar = $state(false); let cargandoLike = $state(false); let errorLike = $state(false); @@ -123,6 +123,7 @@ @{post.authorName} + {#if post.authorName === $sesionStore?.username} diff --git a/src/lib/hooks/esSeguido.ts b/src/lib/hooks/esSeguido.ts new file mode 100644 index 0000000..ea2b51d --- /dev/null +++ b/src/lib/hooks/esSeguido.ts @@ -0,0 +1,26 @@ +import { sesionStore } from '@/stores/usuario'; +import { get } from 'svelte/store'; +import type { Post } from '../../types'; +import { apiBase } from '@/stores/url'; + +export async function esSeguido(post: Post) { + if (!get(sesionStore)?.accessToken || post.authorName === '[deleted]') return; + + const id = post.authorId; + try { + const response = await fetch(`${get(apiBase)}/api/users/${id}/is-following`, { + headers: { + Authorization: `Bearer ${get(sesionStore)?.accessToken}` + } + }); + + if (response.ok) { + const data = await response.json(); + return data; + } else { + return false; + } + } catch { + return null; + } +} diff --git a/src/lib/hooks/seguirUsuario.ts b/src/lib/hooks/seguirUsuario.ts new file mode 100644 index 0000000..378bfd8 --- /dev/null +++ b/src/lib/hooks/seguirUsuario.ts @@ -0,0 +1,21 @@ +import { apiBase } from '@/stores/url'; +import { sesionStore } from '@/stores/usuario'; +import { get } from 'svelte/store'; + +export async function seguirUsuario(idusuario: string, toggle: Boolean = false) { + try { + const req = await fetch(`${get(apiBase)}/api/users/${idusuario}/follow`, { + method: !toggle ? 'POST' : 'DELETE', + headers: { + Authorization: `Bearer ${get(sesionStore)?.accessToken}` + } + }); + if (req.ok) { + return true; + } else { + return false; + } + } catch { + return null; + } +} diff --git a/src/lib/stores/cacheSeguidos.svelte.js b/src/lib/stores/cacheSeguidos.svelte.js new file mode 100644 index 0000000..279429a --- /dev/null +++ b/src/lib/stores/cacheSeguidos.svelte.js @@ -0,0 +1,105 @@ +import { browser } from '$app/environment'; +import { writable } from 'svelte/store'; + +class FollowCache { + constructor() { + if (browser) { + this.loadFromStorage(); + } + } + + /** @type {Map} */ + #cache = new Map(); + + /** @type {import('svelte/store').Writable>} */ + store = writable(this.#cache); + + /** + * @param {string} userId + * @returns {boolean | undefined} + */ + get(userId) { + return this.#cache.get(userId); + } + + /** + * @param {string} userId + * @param {boolean} isFollowed + */ + set(userId, isFollowed) { + this.#cache.set(userId, isFollowed); + this.store.set(this.#cache); + this.saveToStorage(); + + if (browser) { + window.dispatchEvent( + new CustomEvent('followCacheUpdated', { + detail: { userId, isFollowed } + }) + ); + } + } + + /** + * @param {string} userId + * @returns {boolean} + */ + has(userId) { + return this.#cache.has(userId); + } + + /** + * @param {string} userId + */ + delete(userId) { + this.#cache.delete(userId); + this.store.set(this.#cache); + this.saveToStorage(); + + if (browser) { + window.dispatchEvent( + new CustomEvent('followCacheUpdated', { + detail: { userId, isFollowed: false } + }) + ); + } + } + + clear() { + this.#cache.clear(); + this.store.set(this.#cache); + this.saveToStorage(); + + if (browser) { + window.dispatchEvent( + new CustomEvent('followCacheUpdated', { + detail: { clearAll: true } + }) + ); + } + } + + saveToStorage() { + if (browser) { + const data = Object.fromEntries(this.#cache); + sessionStorage.setItem('follow-cache', JSON.stringify(data)); + } + } + + loadFromStorage() { + if (browser) { + try { + const stored = sessionStorage.getItem('follow-cache'); + if (stored) { + const data = JSON.parse(stored); + this.#cache = new Map(Object.entries(data)); + this.store.set(this.#cache); + } + } catch (error) { + console.error('Error cargando desde sesion:', error); + } + } + } +} + +export const cacheSeguidos = new FollowCache(); diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 1e1533d..eec2ce0 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -38,7 +38,7 @@ - +