From 50187910b4b6fef70ca1f41bd097894f266bab78 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 15:37:37 -0300 Subject: [PATCH 01/11] creada store de usuario --- src/lib/stores/usuario.ts | 11 +++++++++++ src/types.d.ts | 13 +++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/lib/stores/usuario.ts diff --git a/src/lib/stores/usuario.ts b/src/lib/stores/usuario.ts new file mode 100644 index 0000000..a337b11 --- /dev/null +++ b/src/lib/stores/usuario.ts @@ -0,0 +1,11 @@ +import { writable } from 'svelte/store'; +import type { User } from '../../types'; + +export const currentUser = writable(null); + +export const userStore = { + subscribe: currentUser.subscribe, + set: currentUser.set, + update: currentUser.update, + reset: () => currentUser.set(null) +}; diff --git a/src/types.d.ts b/src/types.d.ts index f157535..4cb424b 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -12,3 +12,16 @@ export interface Post { visibility: string; hashtags?: string[]; } +export interface User { + _id: string; + displayName: string; + username: string; + email: string; + passwordHash: string; + bio?: string; + profileImageUrl?: string; + createdAt: Date; + followersCount: number; + followingCount: number; + refreshTokens: RefreshToken[]; +} From 543f253db54c5986fa74471554f43757853cfd8a Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 16:35:14 -0300 Subject: [PATCH 02/11] movi la logica de traer los posts al componente --- src/routes/+page.svelte | 25 +++++++++++++++++++++---- src/routes/+page.ts | 15 --------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 7f8d6d2..487f1cc 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -2,12 +2,29 @@ import Card from '@/components/ui/card/card.svelte'; import type { Post } from '../types'; import { Content } from '@/components/ui/card'; + import { apiBase } from '@/stores/url'; - interface Props { - posts: Post[]; - } + $effect(async()=>{ + await getPosts(); + }); + + let posts: Post[] = $state([]); + + async function getPosts() { + const { subscribe } = apiBase; + let baseUrl: string = ''; + + subscribe((value) => { + baseUrl = value; + })(); + + const req = await fetch(`${baseUrl}/api/posts/timeline?pageSize=3`); + if (req.ok){ + posts = await req.json(); + } + + } - let { posts = [] }: Props = $props();
diff --git a/src/routes/+page.ts b/src/routes/+page.ts index ff3a798..77ab0a0 100644 --- a/src/routes/+page.ts +++ b/src/routes/+page.ts @@ -1,16 +1 @@ -import { apiBase } from '@/stores/url'; - export const ssr = true; - -export async function load({}) { - const { subscribe } = apiBase; - let baseUrl: string = ''; - - subscribe((value) => { - baseUrl = value; - })(); - - const req = await fetch(`${baseUrl}/Posts`); - if (req.ok) return { posts: req }; - else return { posts: [] }; -} From 4545252bd25a1b1c91d14c7d30f6e53d580c9f86 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 18:25:04 -0300 Subject: [PATCH 03/11] =?UTF-8?q?a=C3=B1adido=20codigo=20para=20el=20alert?= =?UTF-8?q?=20de=20shadcn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/alert/alert-description.svelte | 23 ++++++++++ .../components/ui/alert/alert-title.svelte | 20 +++++++++ src/lib/components/ui/alert/alert.svelte | 44 +++++++++++++++++++ src/lib/components/ui/alert/index.ts | 14 ++++++ 4 files changed, 101 insertions(+) create mode 100644 src/lib/components/ui/alert/alert-description.svelte create mode 100644 src/lib/components/ui/alert/alert-title.svelte create mode 100644 src/lib/components/ui/alert/alert.svelte create mode 100644 src/lib/components/ui/alert/index.ts diff --git a/src/lib/components/ui/alert/alert-description.svelte b/src/lib/components/ui/alert/alert-description.svelte new file mode 100644 index 0000000..8b56aed --- /dev/null +++ b/src/lib/components/ui/alert/alert-description.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/alert/alert-title.svelte b/src/lib/components/ui/alert/alert-title.svelte new file mode 100644 index 0000000..77e45ad --- /dev/null +++ b/src/lib/components/ui/alert/alert-title.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/alert/alert.svelte b/src/lib/components/ui/alert/alert.svelte new file mode 100644 index 0000000..2b2eff9 --- /dev/null +++ b/src/lib/components/ui/alert/alert.svelte @@ -0,0 +1,44 @@ + + + + + diff --git a/src/lib/components/ui/alert/index.ts b/src/lib/components/ui/alert/index.ts new file mode 100644 index 0000000..97e21b4 --- /dev/null +++ b/src/lib/components/ui/alert/index.ts @@ -0,0 +1,14 @@ +import Root from "./alert.svelte"; +import Description from "./alert-description.svelte"; +import Title from "./alert-title.svelte"; +export { alertVariants, type AlertVariant } from "./alert.svelte"; + +export { + Root, + Description, + Title, + // + Root as Alert, + Description as AlertDescription, + Title as AlertTitle, +}; From ccebc7934c613f04ad87c2ef5435742203dd7b43 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 18:25:57 -0300 Subject: [PATCH 04/11] codigo de login front --- src/lib/components/signup-form.svelte | 32 ++++++++++----- .../ui/login-form/login-form.svelte | 14 +++++-- src/lib/hooks/login.ts | 37 ++++++++++++++++++ src/lib/hooks/register.ts | 39 +++++++++++++++++++ src/lib/stores/usuario.ts | 14 +++---- src/routes/login/+page.svelte | 36 +++++++++++++++-- src/types.d.ts | 16 ++++++++ 7 files changed, 163 insertions(+), 25 deletions(-) create mode 100644 src/lib/hooks/login.ts create mode 100644 src/lib/hooks/register.ts diff --git a/src/lib/components/signup-form.svelte b/src/lib/components/signup-form.svelte index 84b91c9..4db6eaf 100644 --- a/src/lib/components/signup-form.svelte +++ b/src/lib/components/signup-form.svelte @@ -1,32 +1,44 @@ - + Registrarse
-
+ register(e, dto, setAlert)}> - Nombre Completo - + Nombre de Usuario + + + + Nombre Visible + + + Email - + Contraseña - + Debe de tener por lo menos 8 caracteres. diff --git a/src/lib/components/ui/login-form/login-form.svelte b/src/lib/components/ui/login-form/login-form.svelte index 0213693..b866e05 100644 --- a/src/lib/components/ui/login-form/login-form.svelte +++ b/src/lib/components/ui/login-form/login-form.svelte @@ -3,7 +3,13 @@ import * as Card from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { FieldGroup, Field, FieldLabel, FieldDescription } from '@/components/ui/field'; - const id = $props.id(); + import type { LoginDto } from '../../../../types'; + import { login } from '@/hooks/login'; + let {id, showAlert = $bindable() } = $props(); + + let dto: LoginDto = $state({password: "", username: ""}); + + const setAlert = () => showAlert = true; @@ -12,11 +18,11 @@ ingrese su usuario para logearse en la cuenta - + Usuario - +
@@ -25,7 +31,7 @@ Te Olvidaste la contraseña?
- +
diff --git a/src/lib/hooks/login.ts b/src/lib/hooks/login.ts new file mode 100644 index 0000000..6493096 --- /dev/null +++ b/src/lib/hooks/login.ts @@ -0,0 +1,37 @@ +import { apiBase } from "@/stores/url"; +import type { LoginDto } from "../../types"; +import { sesionStore } from "@/stores/usuario"; +import { goto } from "$app/navigation"; + +export async function login(e:FormDataEvent,dto: LoginDto, callbackfn:()=>void){ + e.preventDefault(); + if (dto.password == "" || dto.username == "") return; + try { + + const { subscribe } = apiBase; + let baseUrl: string = ''; + + subscribe((value) => { + baseUrl = value; + })(); + const req = await fetch(baseUrl + "/api/auth/login", { + method: "POST", + headers:{ + "Content-Type": "application/json" + }, + body: JSON.stringify(dto) + }); + if (req.ok) { + const token = await req.json(); + sesionStore.set({ accessToken: token }) + goto("/") + } else { + callbackfn(); + } + + } catch { + callbackfn(); + console.error("fallo al intentar alcanzar el servidor") + + } +} diff --git a/src/lib/hooks/register.ts b/src/lib/hooks/register.ts new file mode 100644 index 0000000..6c44ff1 --- /dev/null +++ b/src/lib/hooks/register.ts @@ -0,0 +1,39 @@ +import { apiBase } from "@/stores/url"; +import { sesionStore } from "@/stores/usuario"; +import { goto } from "$app/navigation"; +import type { RegisterDto } from "../../types"; + +export async function register(e:FormDataEvent,dto: RegisterDto, callbackfn:()=>void){ + e.preventDefault(); + if (dto.password == "" || dto.username == "" || + !dto.email?.includes("@") || dto.displayName=="") return; + try { + + const { subscribe } = apiBase; + let baseUrl: string = ''; + + subscribe((value) => { + baseUrl = value; + })(); + const req = await fetch(baseUrl + "/api/auth/register", { + method: "POST", + headers:{ + "Content-Type": "application/json" + }, + body: JSON.stringify(dto) + }); + if (req.ok) { + const data= await req.json(); + goto("/login", { state: { + message: data.message, + }}); + } else { + callbackfn(); + } + + } catch { + callbackfn(); + console.error("fallo al intentar alcanzar el servidor") + + } +} diff --git a/src/lib/stores/usuario.ts b/src/lib/stores/usuario.ts index a337b11..649b18b 100644 --- a/src/lib/stores/usuario.ts +++ b/src/lib/stores/usuario.ts @@ -1,11 +1,11 @@ import { writable } from 'svelte/store'; -import type { User } from '../../types'; +import type { Sesion } from '../../types'; -export const currentUser = writable(null); +export const currentSesion = writable(null); -export const userStore = { - subscribe: currentUser.subscribe, - set: currentUser.set, - update: currentUser.update, - reset: () => currentUser.set(null) +export const sesionStore = { + subscribe: currentSesion.subscribe, + set: currentSesion.set, + update: currentSesion.update, + reset: () => currentSesion.set(null) }; diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte index e99aed3..e968672 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -1,9 +1,37 @@ - + +
- + + {#if showAlert} +
+ + + No se pudo iniciar sesion + + Revise su usuario o contraseña + + +
+ {/if}
diff --git a/src/types.d.ts b/src/types.d.ts index 4cb424b..d617b8e 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -25,3 +25,19 @@ export interface User { followingCount: number; refreshTokens: RefreshToken[]; } + +export interface Sesion { + accessToken:string?; +} + +export interface LoginDto { + username: string?; + password: string?; +} + +export interface RegisterDto { + username: string?; + email: string?; + password: string?; + displayName: string?; +} From e08cb337d09bc677ad542623113a8b9b0306506c Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 18:26:14 -0300 Subject: [PATCH 05/11] fix: async innecesario --- src/routes/+page.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 487f1cc..03797f5 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,8 +4,8 @@ import { Content } from '@/components/ui/card'; import { apiBase } from '@/stores/url'; - $effect(async()=>{ - await getPosts(); + $effect(()=>{ + getPosts(); }); let posts: Post[] = $state([]); From 7366972a0c10ac8f1407e4fcf1357fa2cb11d005 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 19:30:39 -0300 Subject: [PATCH 06/11] update: mantengo el dto para poder guardar los nuevos datos del back login --- src/types.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types.d.ts b/src/types.d.ts index d617b8e..bc001ff 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -28,6 +28,9 @@ export interface User { export interface Sesion { accessToken:string?; + message:string; + url:string; + displayname:string; } export interface LoginDto { From 9778c55cc3dc7fbeabdc4023a9b18947a75d824e Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 19:30:39 -0300 Subject: [PATCH 07/11] update: mantengo el dto para poder guardar los nuevos datos del back login --- src/lib/hooks/login.ts | 2 +- src/types.d.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/hooks/login.ts b/src/lib/hooks/login.ts index 6493096..5bce4a4 100644 --- a/src/lib/hooks/login.ts +++ b/src/lib/hooks/login.ts @@ -23,7 +23,7 @@ export async function login(e:FormDataEvent,dto: LoginDto, callbackfn:()=>void){ }); if (req.ok) { const token = await req.json(); - sesionStore.set({ accessToken: token }) + sesionStore.set(token); goto("/") } else { callbackfn(); diff --git a/src/types.d.ts b/src/types.d.ts index d617b8e..bc001ff 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -28,6 +28,9 @@ export interface User { export interface Sesion { accessToken:string?; + message:string; + url:string; + displayname:string; } export interface LoginDto { From a380adb940e4d8d5127ffdca57560a54c4e42162 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 22:12:59 -0300 Subject: [PATCH 08/11] =?UTF-8?q?Feat:=20A=C3=B1adido=20alert=20en=20caso?= =?UTF-8?q?=20de=20fallo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/register/+page.svelte | 35 +++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/routes/register/+page.svelte b/src/routes/register/+page.svelte index fbbb126..471d138 100644 --- a/src/routes/register/+page.svelte +++ b/src/routes/register/+page.svelte @@ -1,9 +1,38 @@ -
-
- +
+ + {#if showAlert} +
+ + + No se pudo crear la cuenta + + Intente nuevamente. + + +
+ {/if}
From 23ee793c74d3726170192885b4c5a80e4ada5b23 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 22:16:15 -0300 Subject: [PATCH 09/11] Feat: Logout Front --- src/lib/head/Header.svelte | 100 +++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 27 deletions(-) diff --git a/src/lib/head/Header.svelte b/src/lib/head/Header.svelte index 971aff4..774035e 100644 --- a/src/lib/head/Header.svelte +++ b/src/lib/head/Header.svelte @@ -4,9 +4,45 @@ import ButtonGroup from '@/components/ui/button-group/button-group.svelte'; import { page } from '$app/state'; import { slide } from 'svelte/transition'; + import { sesionStore } from '@/stores/usuario'; + import { onMount } from 'svelte'; + import { apiBase } from '@/stores/url'; let menuOpen = $state(false); const toggleMenu = () => (menuOpen = !menuOpen); + + let showCerrarSesion = $state(false); + + onMount(()=>{ + sesionStore.subscribe((value)=>{ + showCerrarSesion = !!value?.accessToken; + }) + + }); + + async function cerrarSesion(){ + try{ + const req = await fetch($apiBase+"/api/auth/logout", { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${$sesionStore?.accessToken}` + + }, + credentials: "include" + }); + if(req.ok){ + + sesionStore.reset(); + menuOpen = false; + } + }catch{ + console.log("fallo el lougout") + } finally{ + sesionStore.reset(); + } + + }
@@ -22,19 +58,24 @@ @@ -64,20 +105,25 @@ {#if menuOpen}
-
- - -
+
+ {#if showCerrarSesion} + + {:else} + + + {/if} +
{/if}
From e5f9a6f1ec1d88fedccf7a9f6a6af9bb1429b823 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 22:17:07 -0300 Subject: [PATCH 10/11] Fix: no se seteaban las credenciales --- src/lib/hooks/login.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/hooks/login.ts b/src/lib/hooks/login.ts index 5bce4a4..9794a88 100644 --- a/src/lib/hooks/login.ts +++ b/src/lib/hooks/login.ts @@ -19,6 +19,7 @@ export async function login(e:FormDataEvent,dto: LoginDto, callbackfn:()=>void){ headers:{ "Content-Type": "application/json" }, + credentials: 'include', body: JSON.stringify(dto) }); if (req.ok) { From 5c6415c41e23ef65e48a9d006dbc9f18ea77dee4 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 14 Nov 2025 22:18:20 -0300 Subject: [PATCH 11/11] Fix: InfoAlert correjido que no llegaba el estado del alert a la pagina de login --- src/lib/hooks/register.ts | 5 +--- src/routes/login/+page.js | 5 ++++ src/routes/login/+page.svelte | 49 +++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 src/routes/login/+page.js diff --git a/src/lib/hooks/register.ts b/src/lib/hooks/register.ts index 6c44ff1..681959e 100644 --- a/src/lib/hooks/register.ts +++ b/src/lib/hooks/register.ts @@ -1,5 +1,4 @@ import { apiBase } from "@/stores/url"; -import { sesionStore } from "@/stores/usuario"; import { goto } from "$app/navigation"; import type { RegisterDto } from "../../types"; @@ -24,9 +23,7 @@ export async function register(e:FormDataEvent,dto: RegisterDto, callbackfn:()=> }); if (req.ok) { const data= await req.json(); - goto("/login", { state: { - message: data.message, - }}); + goto("/login?msg="+data.message); } else { callbackfn(); } diff --git a/src/routes/login/+page.js b/src/routes/login/+page.js new file mode 100644 index 0000000..044e0b7 --- /dev/null +++ b/src/routes/login/+page.js @@ -0,0 +1,5 @@ +export function load({ url }) { + return { + message: url.searchParams.get('msg') + }; +} diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte index e968672..a402bd9 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -2,11 +2,23 @@ import * as Alert from '@/components/ui/alert'; import LoginForm from '@/components/ui/login-form/login-form.svelte'; import AlertCircleIcon from "@lucide/svelte/icons/alert-circle"; - import { fade } from 'svelte/transition'; - let showAlert: boolean = $state(false); + import { fade, fly } from 'svelte/transition'; + import Info from '@lucide/svelte/icons/info'; + + let {data} = $props(); + + let showAlert: boolean = $state(false); + + let message = $state(data.message); $effect(()=>{ resetAlert(); + if (data.message) { + history.replaceState(history.state, "", "/login"); + setTimeout(() => { + message = ""; + }, 7000); + } }); async function resetAlert (){ @@ -15,22 +27,33 @@ showAlert=false; } } -
- - {#if showAlert} -
- - - No se pudo iniciar sesion - - Revise su usuario o contraseña - - + {#if message} +
+ + + Info + + Ingrese las credenciales de la cuenta recien creada + + +
+ + {/if} + + {#if showAlert} +
+ + + No se pudo iniciar sesion + + Revise su usuario o contraseña + +
{/if}