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/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, +}; 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/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}
diff --git a/src/lib/hooks/login.ts b/src/lib/hooks/login.ts new file mode 100644 index 0000000..9794a88 --- /dev/null +++ b/src/lib/hooks/login.ts @@ -0,0 +1,38 @@ +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" + }, + credentials: 'include', + body: JSON.stringify(dto) + }); + if (req.ok) { + const token = await req.json(); + sesionStore.set(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..681959e --- /dev/null +++ b/src/lib/hooks/register.ts @@ -0,0 +1,36 @@ +import { apiBase } from "@/stores/url"; +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?msg="+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 new file mode 100644 index 0000000..649b18b --- /dev/null +++ b/src/lib/stores/usuario.ts @@ -0,0 +1,11 @@ +import { writable } from 'svelte/store'; +import type { Sesion } from '../../types'; + +export const currentSesion = writable(null); + +export const sesionStore = { + subscribe: currentSesion.subscribe, + set: currentSesion.set, + update: currentSesion.update, + reset: () => currentSesion.set(null) +}; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 7f8d6d2..03797f5 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(()=>{ + 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: [] }; -} 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 e99aed3..a402bd9 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -1,9 +1,60 @@ - + +
- + {#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}
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}
diff --git a/src/types.d.ts b/src/types.d.ts index f157535..bc001ff 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -12,3 +12,35 @@ 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[]; +} + +export interface Sesion { + accessToken:string?; + message:string; + url:string; + displayname:string; +} + +export interface LoginDto { + username: string?; + password: string?; +} + +export interface RegisterDto { + username: string?; + email: string?; + password: string?; + displayName: string?; +}