diff --git a/src/lib/components/crear-post.svelte b/src/lib/components/crear-post.svelte
new file mode 100644
index 0000000..eb674e6
--- /dev/null
+++ b/src/lib/components/crear-post.svelte
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+ 229}>
+ {mensaje.length}
+
+ / 255
+
+
+ Publicar
+
+
+
+
+
diff --git a/src/lib/components/ui/avatar/avatar-fallback.svelte b/src/lib/components/ui/avatar/avatar-fallback.svelte
new file mode 100644
index 0000000..249d4a4
--- /dev/null
+++ b/src/lib/components/ui/avatar/avatar-fallback.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/lib/components/ui/avatar/avatar-image.svelte b/src/lib/components/ui/avatar/avatar-image.svelte
new file mode 100644
index 0000000..2bb9db4
--- /dev/null
+++ b/src/lib/components/ui/avatar/avatar-image.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/lib/components/ui/avatar/avatar.svelte b/src/lib/components/ui/avatar/avatar.svelte
new file mode 100644
index 0000000..e37214d
--- /dev/null
+++ b/src/lib/components/ui/avatar/avatar.svelte
@@ -0,0 +1,19 @@
+
+
+
diff --git a/src/lib/components/ui/avatar/index.ts b/src/lib/components/ui/avatar/index.ts
new file mode 100644
index 0000000..d06457b
--- /dev/null
+++ b/src/lib/components/ui/avatar/index.ts
@@ -0,0 +1,13 @@
+import Root from "./avatar.svelte";
+import Image from "./avatar-image.svelte";
+import Fallback from "./avatar-fallback.svelte";
+
+export {
+ Root,
+ Image,
+ Fallback,
+ //
+ Root as Avatar,
+ Image as AvatarImage,
+ Fallback as AvatarFallback,
+};
diff --git a/src/lib/components/ui/input-group/index.ts b/src/lib/components/ui/input-group/index.ts
new file mode 100644
index 0000000..fe1f55d
--- /dev/null
+++ b/src/lib/components/ui/input-group/index.ts
@@ -0,0 +1,22 @@
+import Root from "./input-group.svelte";
+import Addon from "./input-group-addon.svelte";
+import Button from "./input-group-button.svelte";
+import Input from "./input-group-input.svelte";
+import Text from "./input-group-text.svelte";
+import Textarea from "./input-group-textarea.svelte";
+
+export {
+ Root,
+ Addon,
+ Button,
+ Input,
+ Text,
+ Textarea,
+ //
+ Root as InputGroup,
+ Addon as InputGroupAddon,
+ Button as InputGroupButton,
+ Input as InputGroupInput,
+ Text as InputGroupText,
+ Textarea as InputGroupTextarea,
+};
diff --git a/src/lib/components/ui/input-group/input-group-addon.svelte b/src/lib/components/ui/input-group/input-group-addon.svelte
new file mode 100644
index 0000000..09f2b64
--- /dev/null
+++ b/src/lib/components/ui/input-group/input-group-addon.svelte
@@ -0,0 +1,55 @@
+
+
+
+
+
{
+ if ((e.target as HTMLElement).closest("button")) {
+ return;
+ }
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
+ }}
+ {...restProps}
+>
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/input-group/input-group-button.svelte b/src/lib/components/ui/input-group/input-group-button.svelte
new file mode 100644
index 0000000..d38a71e
--- /dev/null
+++ b/src/lib/components/ui/input-group/input-group-button.svelte
@@ -0,0 +1,49 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/input-group/input-group-input.svelte b/src/lib/components/ui/input-group/input-group-input.svelte
new file mode 100644
index 0000000..ded2655
--- /dev/null
+++ b/src/lib/components/ui/input-group/input-group-input.svelte
@@ -0,0 +1,23 @@
+
+
+
diff --git a/src/lib/components/ui/input-group/input-group-text.svelte b/src/lib/components/ui/input-group/input-group-text.svelte
new file mode 100644
index 0000000..332f63d
--- /dev/null
+++ b/src/lib/components/ui/input-group/input-group-text.svelte
@@ -0,0 +1,22 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/input-group/input-group-textarea.svelte b/src/lib/components/ui/input-group/input-group-textarea.svelte
new file mode 100644
index 0000000..91850ff
--- /dev/null
+++ b/src/lib/components/ui/input-group/input-group-textarea.svelte
@@ -0,0 +1,23 @@
+
+
+
diff --git a/src/lib/components/ui/input-group/input-group.svelte b/src/lib/components/ui/input-group/input-group.svelte
new file mode 100644
index 0000000..a216aeb
--- /dev/null
+++ b/src/lib/components/ui/input-group/input-group.svelte
@@ -0,0 +1,38 @@
+
+
+textarea]:h-auto",
+
+ // Variants based on alignment.
+ "has-[>[data-align=inline-start]]:[&>input]:ps-2",
+ "has-[>[data-align=inline-end]]:[&>input]:pe-2",
+ "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
+ "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
+
+ // Focus state.
+ "has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]",
+
+ // Error state.
+ "has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
+
+ className
+ )}
+ {...props}
+>
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/kbd/index.ts b/src/lib/components/ui/kbd/index.ts
new file mode 100644
index 0000000..6aa7f07
--- /dev/null
+++ b/src/lib/components/ui/kbd/index.ts
@@ -0,0 +1,10 @@
+import Root from "./kbd.svelte";
+import Group from "./kbd-group.svelte";
+
+export {
+ Root,
+ Group,
+ //
+ Root as Kbd,
+ Group as KbdGroup,
+};
diff --git a/src/lib/components/ui/kbd/kbd-group.svelte b/src/lib/components/ui/kbd/kbd-group.svelte
new file mode 100644
index 0000000..61447a5
--- /dev/null
+++ b/src/lib/components/ui/kbd/kbd-group.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/kbd/kbd.svelte b/src/lib/components/ui/kbd/kbd.svelte
new file mode 100644
index 0000000..cdf6a08
--- /dev/null
+++ b/src/lib/components/ui/kbd/kbd.svelte
@@ -0,0 +1,25 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/textarea/index.ts b/src/lib/components/ui/textarea/index.ts
new file mode 100644
index 0000000..ace797a
--- /dev/null
+++ b/src/lib/components/ui/textarea/index.ts
@@ -0,0 +1,7 @@
+import Root from "./textarea.svelte";
+
+export {
+ Root,
+ //
+ Root as Textarea,
+};
diff --git a/src/lib/components/ui/textarea/textarea.svelte b/src/lib/components/ui/textarea/textarea.svelte
new file mode 100644
index 0000000..7fcef1a
--- /dev/null
+++ b/src/lib/components/ui/textarea/textarea.svelte
@@ -0,0 +1,23 @@
+
+
+
diff --git a/src/lib/head/AvatarButton.svelte b/src/lib/head/AvatarButton.svelte
new file mode 100644
index 0000000..2d28b2c
--- /dev/null
+++ b/src/lib/head/AvatarButton.svelte
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+ {$sesionStore?.displayName[0]}
+
+
+
+
+
+ Mi Perfil
+
+
+ await logout(menuOpen)}>Cerrar Sesion
+
+
+
diff --git a/src/lib/head/Header.svelte b/src/lib/head/Header.svelte
index 7f75a0d..1791b52 100644
--- a/src/lib/head/Header.svelte
+++ b/src/lib/head/Header.svelte
@@ -8,43 +8,40 @@
import { onMount } from 'svelte';
import { apiBase } from '@/stores/url';
import { goto } from '$app/navigation';
+ import AvatarButton from './AvatarButton.svelte';
let menuOpen = $state(false);
const toggleMenu = () => (menuOpen = !menuOpen);
- let showCerrarSesion = $state(false);
+ let showCerrarSesion = $state(false);
- onMount(()=>{
- sesionStore.subscribe((value)=>{
- showCerrarSesion = !!value?.accessToken;
- })
+ 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();
- goto("/");
- }
-
- }
+ 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();
+ goto('/');
+ }
+ }
@@ -53,31 +50,38 @@
Mini-X
-
diff --git a/src/lib/hooks/logout.ts b/src/lib/hooks/logout.ts
new file mode 100644
index 0000000..9fe4b4e
--- /dev/null
+++ b/src/lib/hooks/logout.ts
@@ -0,0 +1,25 @@
+import { goto } from '$app/navigation';
+import { apiBase } from '@/stores/url';
+import { sesionStore } from '@/stores/usuario';
+
+export async function logout(menuOpen: boolean) {
+ 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();
+ goto('/');
+ }
+}
diff --git a/src/lib/stores/usuario.ts b/src/lib/stores/usuario.ts
index 649b18b..d109b99 100644
--- a/src/lib/stores/usuario.ts
+++ b/src/lib/stores/usuario.ts
@@ -1,7 +1,16 @@
import { writable } from 'svelte/store';
+import { browser } from '$app/environment';
import type { Sesion } from '../../types';
-export const currentSesion = writable(null);
+const initialValue = browser ? JSON.parse(localStorage.getItem('sesion') || 'null') : null;
+
+export const currentSesion = writable(initialValue);
+
+if (browser) {
+ currentSesion.subscribe((value) => {
+ localStorage.setItem('sesion', JSON.stringify(value));
+ });
+}
export const sesionStore = {
subscribe: currentSesion.subscribe,
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 03797f5..f7f8c0e 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -2,65 +2,72 @@
import Card from '@/components/ui/card/card.svelte';
import type { Post } from '../types';
import { Content } from '@/components/ui/card';
- import { apiBase } from '@/stores/url';
+ import { apiBase } from '@/stores/url';
+ import { sesionStore } from '@/stores/usuario';
+ import CrearPost from '@/components/crear-post.svelte';
- $effect(()=>{
- getPosts();
- });
+ $effect(() => {
+ getPosts();
+ });
- let posts: Post[] = $state([]);
+ let posts: Post[] = $state([]);
- async function getPosts() {
- const { subscribe } = apiBase;
- let baseUrl: string = '';
+ 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();
- }
-
- }
+ subscribe((value) => {
+ baseUrl = value;
+ })();
+ const req = await fetch(`${baseUrl}/api/posts/timeline?pageSize=3`);
+ if (req.ok) {
+ posts = await req.json();
+ }
+ }
-
- {#if posts.length <= 0}
-
-
- No hay Posts que mostrar
-
-
- {:else}
- {#each posts as post}
+
+
+ {#if $sesionStore !== null}
+
+ {/if}
+
+
+ {#if posts.length <= 0}
-
-
- {post.authorId}
- {post.createdAt.toLocaleDateString()}
-
-
{post.content}
- {#if post.imageUrl}
-

- {/if}
-
- {post.likesCount} likes
- {post.repliesCount} replies
- {#if post.isEdited}
- Editado
- {/if}
-
-
+ No hay Posts que mostrar
- {/each}
- {/if}
+ {:else}
+ {#each posts as post}
+
+
+
+
+ {post.authorId}
+ {post.createdAt.toLocaleDateString()}
+
+
{post.content}
+ {#if post.imageUrl}
+

+ {/if}
+
+ {post.likesCount} likes
+ {post.repliesCount} replies
+ {#if post.isEdited}
+ Editado
+ {/if}
+
+
+
+
+ {/each}
+ {/if}
+
diff --git a/src/routes/[perfil]/+page.svelte b/src/routes/[perfil]/+page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/types.d.ts b/src/types.d.ts
index bc001ff..8f6cff6 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -27,10 +27,10 @@ export interface User {
}
export interface Sesion {
- accessToken:string?;
- message:string;
- url:string;
- displayname:string;
+ accessToken: string?;
+ message: string;
+ url: string;
+ displayName: string;
}
export interface LoginDto {