From 9cc5831cfc6a8d7ec1d6189a7f7a7eb0fcccbdae Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 13:37:23 -0300 Subject: [PATCH 01/22] separada la logica de publicar el post a la del manejo del front --- src/lib/components/crear-post.svelte | 38 +++++++--------------------- src/lib/hooks/publicarPost.ts | 27 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 29 deletions(-) create mode 100644 src/lib/hooks/publicarPost.ts diff --git a/src/lib/components/crear-post.svelte b/src/lib/components/crear-post.svelte index 62c0748..7aa3710 100644 --- a/src/lib/components/crear-post.svelte +++ b/src/lib/components/crear-post.svelte @@ -14,6 +14,7 @@ import { Tooltip } from './ui/tooltip'; import TooltipContent from './ui/tooltip/tooltip-content.svelte'; import TooltipTrigger from './ui/tooltip/tooltip-trigger.svelte'; + import { publicarPost } from '@/hooks/publicarPost'; let mensaje = $state(''); @@ -22,35 +23,14 @@ async function handlePost(e: Event) { e.preventDefault(); - try { - const formData = new FormData(); - formData.append('content', mensaje); - // formData.append('imageUrl', ''); - // formData.append('parentPostId', ''); - - const req = fetch($apiBase + '/api/posts', { - method: 'POST', - //credentials: 'include', - headers: { - Authorization: `Bearer ${$sesionStore?.accessToken}` - }, - body: formData - }); - cargando = true; - - const res = await req; - if (res.ok) { - mensaje = ''; - const post = await res.json(); - addPost(post); - return; - } - mostrarError = 'No se pudo crear el post.'; - } catch { - mostrarError = 'Fallo al alcanzar el servidor'; - } finally { - cargando = false; - } + cargando = true; + const formData = new FormData(); + formData.append('content', mensaje); + // formData.append('imageUrl', ''); + // formData.append('parentPostId', ''); + mostrarError = await publicarPost(formData); + if (mostrarError == '') mensaje = ''; + cargando = false; } function handleKeydown(e: KeyboardEvent) { diff --git a/src/lib/hooks/publicarPost.ts b/src/lib/hooks/publicarPost.ts new file mode 100644 index 0000000..8ddb6f0 --- /dev/null +++ b/src/lib/hooks/publicarPost.ts @@ -0,0 +1,27 @@ +import { addPost } from "@/stores/posts"; +import { apiBase } from "@/stores/url"; +import { sesionStore } from "@/stores/usuario"; +import { get } from "svelte/store"; + +export async function publicarPost(formData: FormData){ + try{ + const req = fetch(get(apiBase) + '/api/posts', { + method: 'POST', + //credentials: 'include', + headers: { + Authorization: `Bearer ${get(sesionStore)?.accessToken}` + }, + body: formData + }); + + const res = await req; + if (res.ok) { + const post = await res.json(); + addPost(post); + return ''; + } + return 'No se pudo crear el post.'; + } catch { + return 'Fallo al alcanzar el servidor'; + } +} From 28a22563fe961f0a5d3d0531cf0f868b24177519 Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 13:52:57 -0300 Subject: [PATCH 02/22] cambiada interfaz mobile del header --- src/lib/head/Header.svelte | 55 +------------------------------------- 1 file changed, 1 insertion(+), 54 deletions(-) diff --git a/src/lib/head/Header.svelte b/src/lib/head/Header.svelte index 1791b52..145f2fb 100644 --- a/src/lib/head/Header.svelte +++ b/src/lib/head/Header.svelte @@ -53,15 +53,10 @@ -
- {#if $sesionStore !== null} - - {/if} -
- - - - {#if menuOpen} -
-
- - - - -
-
- {/if} From 27eae9cb62f188e49bc893e1a2d68a30a3a4be0d Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 13:53:44 -0300 Subject: [PATCH 03/22] =?UTF-8?q?a=C3=B1adido=20un=20skeleton=20de=20la=20?= =?UTF-8?q?ui=20para=20el=20adjuntar=20imagenes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/components/crear-post.svelte | 52 ++++++++++++++++------------ 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/lib/components/crear-post.svelte b/src/lib/components/crear-post.svelte index 7aa3710..0078df4 100644 --- a/src/lib/components/crear-post.svelte +++ b/src/lib/components/crear-post.svelte @@ -4,6 +4,7 @@ import InputGroupTextarea from './ui/input-group/input-group-textarea.svelte'; import InputGroup from './ui/input-group/input-group.svelte'; import ArrowUpIcon from '@lucide/svelte/icons/arrow-up'; + import Paperclip from '@lucide/svelte/icons/paperclip'; import Loader2Icon from '@lucide/svelte/icons/loader-2'; import Kbd from './ui/kbd/kbd.svelte'; @@ -15,6 +16,8 @@ import TooltipContent from './ui/tooltip/tooltip-content.svelte'; import TooltipTrigger from './ui/tooltip/tooltip-trigger.svelte'; import { publicarPost } from '@/hooks/publicarPost'; + import Button from './ui/button/button.svelte'; + import InputGroupInput from './ui/input-group/input-group-input.svelte'; let mensaje = $state(''); @@ -57,28 +60,33 @@

/ 280 - - - - {#if cargando} - - Publicando... - {:else} - Publicar - - {/if} - - - - Ctrl+Enter - - +
+ + + + + + + {#if cargando} + + Publicando... + {:else} + Publicar + + {/if} + + + + Ctrl+Enter + + +
From d08d2521b61e9d98c1b26db1eadb986e4ad33d2f Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 14:29:51 -0300 Subject: [PATCH 04/22] =?UTF-8?q?a=C3=B1adido=20boton=20para=20desseleccio?= =?UTF-8?q?nar=20imagen=20+=20un=20preview=20de=20la=20imagen=20selecciona?= =?UTF-8?q?da?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/components/crear-post.svelte | 56 +++++++++++++++++++++++----- src/lib/utils.ts | 11 ++++++ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/lib/components/crear-post.svelte b/src/lib/components/crear-post.svelte index 0078df4..fd2aaed 100644 --- a/src/lib/components/crear-post.svelte +++ b/src/lib/components/crear-post.svelte @@ -5,21 +5,17 @@ import InputGroup from './ui/input-group/input-group.svelte'; import ArrowUpIcon from '@lucide/svelte/icons/arrow-up'; import Paperclip from '@lucide/svelte/icons/paperclip'; + import Trash from '@lucide/svelte/icons/trash-2'; import Loader2Icon from '@lucide/svelte/icons/loader-2'; import Kbd from './ui/kbd/kbd.svelte'; - - import { apiBase } from '@/stores/url'; - import { sesionStore } from '@/stores/usuario'; - import type { CreatePostDto } from '../../types'; - import { addPost } from '@/stores/posts'; import { Tooltip } from './ui/tooltip'; import TooltipContent from './ui/tooltip/tooltip-content.svelte'; import TooltipTrigger from './ui/tooltip/tooltip-trigger.svelte'; import { publicarPost } from '@/hooks/publicarPost'; - import Button from './ui/button/button.svelte'; - import InputGroupInput from './ui/input-group/input-group-input.svelte'; + import { filtrarImagen } from '@/utils'; let mensaje = $state(''); + let imagen: File | null = $state(null); let cargando = $state(false); let mostrarError = $state(''); @@ -29,7 +25,7 @@ cargando = true; const formData = new FormData(); formData.append('content', mensaje); - // formData.append('imageUrl', ''); + formData.append('imagen', imagen); // formData.append('parentPostId', ''); mostrarError = await publicarPost(formData); if (mostrarError == '') mensaje = ''; @@ -41,12 +37,29 @@ handlePost(e); } } + + function handleDrop(e: Event) { + const target = e.target as HTMLInputElement; + const file = target?.files?.[0]; + imagen = filtrarImagen(file); + } + function seleccionarImagen() { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.png,.jpg,.jpeg,.gif,.webp'; + input.onchange = () => { + const file = input.files?.[0]; + imagen = filtrarImagen(file); + }; + input.click(); + }
handlePost(e)}>
- + {#if imagen} + + {/if} + diff --git a/src/lib/utils.ts b/src/lib/utils.ts index f92bfcb..c9f5098 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -11,3 +11,14 @@ export type WithoutChild = T extends { child?: any } ? Omit : T; export type WithoutChildren = T extends { children?: any } ? Omit : T; export type WithoutChildrenOrChild = WithoutChildren>; export type WithElementRef = T & { ref?: U | null }; + +export function filtrarImagen(file) { + if (file) { + const allowed = ['image/png', 'image/jpg', 'image/jpeg', 'image/gif', 'image/webp']; + if (allowed.includes(file.type)) { + return file; + } else{ + return null; + } + } +} From 865496307154c624227828a43842ecd75d1042f3 Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 15:06:55 -0300 Subject: [PATCH 05/22] =?UTF-8?q?a=C3=B1adido=20tipo=20de=20dato=20a=20fil?= =?UTF-8?q?trarImagen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/utils.ts b/src/lib/utils.ts index c9f5098..06308a2 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -12,7 +12,7 @@ export type WithoutChildren = T extends { children?: any } ? Omit = WithoutChildren>; export type WithElementRef = T & { ref?: U | null }; -export function filtrarImagen(file) { +export function filtrarImagen(file: File) { if (file) { const allowed = ['image/png', 'image/jpg', 'image/jpeg', 'image/gif', 'image/webp']; if (allowed.includes(file.type)) { From 4bd67e2b5047a95086c993970910e5fb38465bcb Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 15:07:36 -0300 Subject: [PATCH 06/22] =?UTF-8?q?a=C3=B1adido=20codigo=20para=20setear=20l?= =?UTF-8?q?a=20imagen=20en=20el=20formData=20y=20reiniciar=20los=20valores?= =?UTF-8?q?=20en=20el=20mismo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/components/crear-post.svelte | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib/components/crear-post.svelte b/src/lib/components/crear-post.svelte index fd2aaed..77952f0 100644 --- a/src/lib/components/crear-post.svelte +++ b/src/lib/components/crear-post.svelte @@ -25,10 +25,15 @@ cargando = true; const formData = new FormData(); formData.append('content', mensaje); - formData.append('imagen', imagen); + if (imagen) { + formData.append('image', imagen); + } // formData.append('parentPostId', ''); mostrarError = await publicarPost(formData); - if (mostrarError == '') mensaje = ''; + if (mostrarError == '') { + mensaje = ''; + imagen = null; + } cargando = false; } From cb22223d7c57d91812310c8a352dff37fa8d516b Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 15:11:10 -0300 Subject: [PATCH 07/22] correjida logica del filtrarImagenes --- src/lib/utils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 06308a2..0bdba03 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -17,8 +17,7 @@ export function filtrarImagen(file: File) { const allowed = ['image/png', 'image/jpg', 'image/jpeg', 'image/gif', 'image/webp']; if (allowed.includes(file.type)) { return file; - } else{ - return null; } } + return null; } From 4c47da456728ca6aeafc8425a8568f047f61583e Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 15:35:11 -0300 Subject: [PATCH 08/22] arreglado drag and drop y mejorado el componente para desligar el archivo a subir --- src/lib/components/crear-post.svelte | 44 ++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/lib/components/crear-post.svelte b/src/lib/components/crear-post.svelte index 77952f0..86b6ed8 100644 --- a/src/lib/components/crear-post.svelte +++ b/src/lib/components/crear-post.svelte @@ -16,6 +16,7 @@ let mensaje = $state(''); let imagen: File | null = $state(null); + let hoverimg = $state(false); let cargando = $state(false); let mostrarError = $state(''); @@ -44,8 +45,10 @@ } function handleDrop(e: Event) { - const target = e.target as HTMLInputElement; - const file = target?.files?.[0]; + e.preventDefault(); + const dt = (e as DragEvent).dataTransfer; + const file = dt?.files?.[0]; + if (file === undefined) return; imagen = filtrarImagen(file); } function seleccionarImagen() { @@ -54,6 +57,7 @@ input.accept = '.png,.jpg,.jpeg,.gif,.webp'; input.onchange = () => { const file = input.files?.[0]; + if (file === undefined) return; imagen = filtrarImagen(file); }; input.click(); @@ -64,6 +68,9 @@ { + e.preventDefault(); + }} ondrop={handleDrop} maxlength={280} placeholder="Alguna novedad?" @@ -82,19 +89,30 @@ {#if imagen} From 5c388cfb1268772ca417d73b2993d743781d0753 Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 18:03:17 -0300 Subject: [PATCH 09/22] =?UTF-8?q?A=C3=B1adido=20el=20update=20para=20las?= =?UTF-8?q?=20imagenes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/hooks/updatePost.ts | 2 +- src/routes/[perfil]/modalEditar.svelte | 136 ++++++++++++++++++++----- src/types.d.ts | 1 + 3 files changed, 112 insertions(+), 27 deletions(-) diff --git a/src/lib/hooks/updatePost.ts b/src/lib/hooks/updatePost.ts index 523f526..7197820 100644 --- a/src/lib/hooks/updatePost.ts +++ b/src/lib/hooks/updatePost.ts @@ -7,7 +7,7 @@ export async function updatePost(post: Post, callbackfn: Function, message: stri try { const formData = new FormData(); formData.append("content", post.content); - formData.append("imageUrl", post.imageUrl||""); + formData.append("image", post.image||""); const req = await fetch(get(apiBase) + `/api/posts/${post.id}`, { method: 'PUT', diff --git a/src/routes/[perfil]/modalEditar.svelte b/src/routes/[perfil]/modalEditar.svelte index 1eb1953..7915daf 100644 --- a/src/routes/[perfil]/modalEditar.svelte +++ b/src/routes/[perfil]/modalEditar.svelte @@ -4,6 +4,8 @@ import InputGroupButton from '@/components/ui/input-group/input-group-button.svelte'; import InputGroupTextarea from '@/components/ui/input-group/input-group-textarea.svelte'; import Kbd from '@/components/ui/kbd/kbd.svelte'; + import Paperclip from '@lucide/svelte/icons/paperclip'; + import Trash from '@lucide/svelte/icons/trash-2'; import type { Post } from '../../types'; import ArrowUpIcon from '@lucide/svelte/icons/arrow-up'; import { Dialog } from '@/components/ui/dialog'; @@ -15,6 +17,7 @@ import TooltipTrigger from '@/components/ui/tooltip/tooltip-trigger.svelte'; import TooltipContent from '@/components/ui/tooltip/tooltip-content.svelte'; import Spinner from '@/components/ui/spinner/spinner.svelte'; + import { filtrarImagen } from '@/utils'; interface Props { post: Post | null; @@ -24,6 +27,21 @@ let cargando = $state(false); + async function loadPostImage() { + if (!post?.imageUrl) return; + const response = await fetch(post.imageUrl); + const blob = await response.blob(); + const urlParts = post.imageUrl.split('/'); + const filename = urlParts[urlParts.length - 1] || 'image'; + post.image = new File([blob], filename, { type: blob.type }); + } + + $effect(() => { + void loadPostImage(); + }); + + let hoverimg = $state(false); + async function handleKeydown(e: KeyboardEvent) { if (e.ctrlKey && e.key === 'Enter') { cargando = true; @@ -37,6 +55,24 @@ await callbackfn(e); cargando = false; } + function seleccionarImagen() { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.png,.jpg,.jpeg,.gif,.webp'; + input.onchange = () => { + const file = input.files?.[0]; + if (file === undefined) return; + post!.image = filtrarImagen(file); + }; + input.click(); + } + function handleDrop(e: Event) { + e.preventDefault(); + const dt = (e as DragEvent).dataTransfer; + const file = dt?.files?.[0]; + if (file === undefined) return; + post!.image = filtrarImagen(file); + } (post = null)}> @@ -50,6 +86,10 @@ { + e.preventDefault(); + }} + ondrop={handleDrop} placeholder="Alguna novedad?" onkeydown={handleKeydown} class="text-white" @@ -63,32 +103,76 @@

/ 280 - - - - -

- {#if cargando} - - Cargando... - {:else} - Modificar - - {/if} -

-
-
- - Ctrl+Enter - -
-
+
+ {#if post.image} + + {/if} + + + + + + + +

+ {#if cargando} + + Cargando... + {:else} + Modificar + + {/if} +

+
+
+ + Ctrl+Enter + +
+
+
diff --git a/src/types.d.ts b/src/types.d.ts index c7749ce..7f75bc2 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -7,6 +7,7 @@ export interface Post { authorName: string; content: string; imageUrl?: string; + image?: File | null; parentPostId?: string; likesCount: number; repliesCount: number; From 84106abd3decc9aea19ea04471fc5cd64ec770bd Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 8 Dec 2025 20:52:58 -0300 Subject: [PATCH 10/22] feat: hecho tema de imagenes en perfil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > mamita como renegue - arreglado modificar usuarios admin - añadido subir pfp --- src/lib/components/CardCargando.svelte | 15 +++ src/lib/components/CardError.svelte | 19 ++++ src/lib/components/CardPerfil.svelte | 83 +++++++++++++++++ src/lib/components/TablaUsuarios.svelte | 93 ++++++++----------- .../components/admin/ModificarUsuario.svelte | 12 ++- src/lib/components/ui/skeleton/index.ts | 7 ++ .../components/ui/skeleton/skeleton.svelte | 17 ++++ src/lib/hooks/updateImagenDePerfil.ts | 7 ++ src/lib/hooks/updateUsuario.ts | 20 ++-- src/routes/(privado)/admin/+page.ts | 1 - src/routes/[perfil]/+page.svelte | 46 ++------- src/types.d.ts | 9 ++ 12 files changed, 224 insertions(+), 105 deletions(-) create mode 100644 src/lib/components/CardCargando.svelte create mode 100644 src/lib/components/CardError.svelte create mode 100644 src/lib/components/CardPerfil.svelte create mode 100644 src/lib/components/ui/skeleton/index.ts create mode 100644 src/lib/components/ui/skeleton/skeleton.svelte create mode 100644 src/lib/hooks/updateImagenDePerfil.ts diff --git a/src/lib/components/CardCargando.svelte b/src/lib/components/CardCargando.svelte new file mode 100644 index 0000000..aabba17 --- /dev/null +++ b/src/lib/components/CardCargando.svelte @@ -0,0 +1,15 @@ + + +
+ + + +

Cargando

+
+
+
diff --git a/src/lib/components/CardError.svelte b/src/lib/components/CardError.svelte new file mode 100644 index 0000000..3c3cbe6 --- /dev/null +++ b/src/lib/components/CardError.svelte @@ -0,0 +1,19 @@ + + +
+ + + +

+ {mensajeError} +

+
+
+
diff --git a/src/lib/components/CardPerfil.svelte b/src/lib/components/CardPerfil.svelte new file mode 100644 index 0000000..2a0b78a --- /dev/null +++ b/src/lib/components/CardPerfil.svelte @@ -0,0 +1,83 @@ + + + + + + {#if cargando} +
+ + + +
+ {:else} + +

+ {data.displayName} +

+

+ {data.bio} +

+ {/if} +
+
diff --git a/src/lib/components/TablaUsuarios.svelte b/src/lib/components/TablaUsuarios.svelte index db21f4a..9f7552f 100644 --- a/src/lib/components/TablaUsuarios.svelte +++ b/src/lib/components/TablaUsuarios.svelte @@ -34,11 +34,11 @@ let usuarioModificar: UserResponseDto | null = $state(null); - let search = $state(""); + let search = $state(''); type SortKey = 'username' | 'displayName' | 'postsCount' | 'createdAt'; - let sortBy = $state(null); - let sortDirection = $state<'asc' | 'desc'>('asc'); + let sortBy = $state(null); + let sortDirection = $state<'asc' | 'desc'>('asc'); function ordenarPor(campo: SortKey) { if (sortBy === campo) { @@ -50,52 +50,40 @@ } let usuariosFiltrados = $derived( - usuarios - .filter((u) => - u.username.toLowerCase().startsWith(search.toLowerCase()) || - u.displayName.toLowerCase().startsWith(search.toLowerCase()) - ) - .toSorted((a, b) => { - if (!sortBy) return 0; + usuarios + .filter( + (u) => + u.username.toLowerCase().startsWith(search.toLowerCase()) || + u.displayName.toLowerCase().startsWith(search.toLowerCase()) + ) + .toSorted((a, b) => { + if (!sortBy) return 0; - const key: SortKey = sortBy; + const key: SortKey = sortBy; - if (key === 'createdAt') { - const ta = new Date(a.createdAt).getTime(); - const tb = new Date(b.createdAt).getTime(); - return sortDirection === 'asc' ? ta - tb : tb - ta; - } + if (key === 'createdAt') { + const ta = new Date(a.createdAt).getTime(); + const tb = new Date(b.createdAt).getTime(); + return sortDirection === 'asc' ? ta - tb : tb - ta; + } - if (key === 'postsCount') { - return sortDirection === 'asc' - ? a.postsCount - b.postsCount - : b.postsCount - a.postsCount; - } + if (key === 'postsCount') { + return sortDirection === 'asc' + ? a.postsCount - b.postsCount + : b.postsCount - a.postsCount; + } - const sa = a[key].toString().toLowerCase(); - const sb = b[key].toString().toLowerCase(); - return sortDirection === 'asc' - ? sa.localeCompare(sb) - : sb.localeCompare(sa); - }) + const sa = a[key].toString().toLowerCase(); + const sb = b[key].toString().toLowerCase(); + return sortDirection === 'asc' ? sa.localeCompare(sb) : sb.localeCompare(sa); + }) ); function getSortIcon(campo: SortKey) { - if (sortBy !== campo) return ""; // no ícono si no está ordenando por esa columna - return sortDirection === "asc" ? "↑" : "↓"; // ascendente / descendente + if (sortBy !== campo) return ''; + return sortDirection === 'asc' ? '↑' : '↓'; } - - //let usuariosFiltrados = $derived( - //usuarios.filter((u) => - // u.username.toLowerCase().startsWith(search.toLowerCase()) || - // u.displayName.toLowerCase().startsWith(search.toLowerCase()) - // ) - //); - - - - $effect(() => { if (!open) { usuarioCambioPass = null; @@ -114,27 +102,28 @@
-
- ordenarPor("username")} class="cursor-pointer select-none"> - Usuario {getSortIcon("username")} + ordenarPor('username')} class="cursor-pointer select-none"> + Usuario {getSortIcon('username')} - ordenarPor("displayName")} class="cursor-pointer select-none"> - Nombre {getSortIcon("displayName")} + ordenarPor('displayName')} class="cursor-pointer select-none"> + Nombre {getSortIcon('displayName')} - ordenarPor("postsCount")} class="cursor-pointer select-none"> - Cantidad de posts {getSortIcon("postsCount")} + ordenarPor('postsCount')} class="cursor-pointer select-none"> + Cantidad de posts {getSortIcon('postsCount')} - ordenarPor("createdAt")} class="cursor-pointer select-none"> - Fecha de Creacion {getSortIcon("createdAt")} + ordenarPor('createdAt')} class="cursor-pointer select-none"> + Fecha de Creacion {getSortIcon('createdAt')} Acciones diff --git a/src/lib/components/admin/ModificarUsuario.svelte b/src/lib/components/admin/ModificarUsuario.svelte index f2b77f7..567cb31 100644 --- a/src/lib/components/admin/ModificarUsuario.svelte +++ b/src/lib/components/admin/ModificarUsuario.svelte @@ -18,20 +18,22 @@ let { open = $bindable(), usuario = $bindable() }: Prop = $props(); let imagen = $state(!!usuario?.profileImageUrl); - let fallback = usuario?.displayName; let cargando = $state(false); let error = $state(''); + async function onsubmit(e: SubmitEvent) { e.preventDefault(); cargando = true; - let ret: { displayName: string } | string = await updateUsuario({ + const data = { id: usuario?.id || '', bio: usuario?.bio || '', displayName: usuario?.displayName || '', - oldImageUrl: usuario?.profileImageUrl || '', - profileImage: imagen - }); + profileImage: imagen, + profileImageUrl: imagen ? null : usuario?.profileImageUrl + }; + console.log(data); + let ret: { displayName: string } | string = await updateUsuario(data); if (typeof ret === 'string') { error = ret; } else { diff --git a/src/lib/components/ui/skeleton/index.ts b/src/lib/components/ui/skeleton/index.ts new file mode 100644 index 0000000..186db21 --- /dev/null +++ b/src/lib/components/ui/skeleton/index.ts @@ -0,0 +1,7 @@ +import Root from "./skeleton.svelte"; + +export { + Root, + // + Root as Skeleton, +}; diff --git a/src/lib/components/ui/skeleton/skeleton.svelte b/src/lib/components/ui/skeleton/skeleton.svelte new file mode 100644 index 0000000..c7e3d26 --- /dev/null +++ b/src/lib/components/ui/skeleton/skeleton.svelte @@ -0,0 +1,17 @@ + + +
diff --git a/src/lib/hooks/updateImagenDePerfil.ts b/src/lib/hooks/updateImagenDePerfil.ts new file mode 100644 index 0000000..6b28196 --- /dev/null +++ b/src/lib/hooks/updateImagenDePerfil.ts @@ -0,0 +1,7 @@ +export async function updateImagenDePerfil(){ + try{ + + }catch{ + + } +} diff --git a/src/lib/hooks/updateUsuario.ts b/src/lib/hooks/updateUsuario.ts index 2a2bfb3..aa6a820 100644 --- a/src/lib/hooks/updateUsuario.ts +++ b/src/lib/hooks/updateUsuario.ts @@ -4,19 +4,23 @@ import { get } from "svelte/store" export interface AdminUpdateUsuario { id:string, - displayName: string, - bio: string, + displayName: string | null, + bio: string | null, profileImage:boolean, - oldImageUrl:string + image:File, + profileImageUrl:string|null } -export async function updateUsuario(usuario: AdminUpdateUsuario) { +export async function updateUsuario(usuario: Partial) { const formData = new FormData(); - formData.append('displayName', usuario.displayName); - formData.append('bio', usuario.bio); - if (usuario.profileImage) { - formData.append('profileImageUrl', usuario.oldImageUrl); + if (usuario.displayName) formData.append('displayName', usuario.displayName); + if (usuario.bio) formData.append('bio', usuario.bio); + if (usuario.image) formData.append('profileImage', usuario.image); + if (usuario.profileImage){ + if (usuario.profileImageUrl) formData.append('profileImageUrl', 'null'); + }else{ + if (usuario.profileImageUrl) formData.append('profileImageUrl', usuario.profileImageUrl); } try { diff --git a/src/routes/(privado)/admin/+page.ts b/src/routes/(privado)/admin/+page.ts index 7d23379..84c37d1 100644 --- a/src/routes/(privado)/admin/+page.ts +++ b/src/routes/(privado)/admin/+page.ts @@ -14,7 +14,6 @@ export async function load({}) { Authorization: `Bearer ${get(sesionStore)?.accessToken}` } }); - if (response.status === 401) { throw redirect(302, '/'); } diff --git a/src/routes/[perfil]/+page.svelte b/src/routes/[perfil]/+page.svelte index 4ccc71e..3ebada1 100644 --- a/src/routes/[perfil]/+page.svelte +++ b/src/routes/[perfil]/+page.svelte @@ -25,6 +25,10 @@ import CardHeader from '@/components/ui/card/card-header.svelte'; import CardTitle from '@/components/ui/card/card-title.svelte'; import Badge from '@/components/ui/badge/badge.svelte'; + import Pen from '@lucide/svelte/icons/pen'; + import CardCargando from '@/components/CardCargando.svelte'; + import CardError from '@/components/CardError.svelte'; + import CardPerfil from '@/components/CardPerfil.svelte'; let { params } = $props(); @@ -79,27 +83,7 @@
- - -
- - - {page.data.displayName?.[0]?.toUpperCase() || ''} - -
-

- {page.data.displayName} -

-

- @{params.perfil} -

-

- {page.data.bio} -

-
-
+
- -

{post.content}

+ +

{@html post.content.replaceAll('\n', '
')}

{#if post.imageUrl} From ab06eb9f269d50627d9c222e2783569d91e8b894 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 16:06:54 -0300 Subject: [PATCH 14/22] fix: no se mostraban los likes propios en la pagina de perfil --- src/routes/[perfil]/+page.svelte | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/routes/[perfil]/+page.svelte b/src/routes/[perfil]/+page.svelte index 7cd3f91..644b9ff 100644 --- a/src/routes/[perfil]/+page.svelte +++ b/src/routes/[perfil]/+page.svelte @@ -53,7 +53,10 @@ async function obtenerPosts() { try { const req = await fetch(baseUrl + '/api/posts/user/' + params.perfil, { - method: 'GET' + method: 'GET', + headers: { + Authorization: `Bearer ${$sesionStore?.accessToken}` + } }); if (req.ok) { setPosts(await req.json()); From d7ef3ae92f99351572532dd80dd0839c18a843f5 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 16:45:32 -0300 Subject: [PATCH 15/22] remplazo de hashtags --- src/lib/components/PostCard.svelte | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib/components/PostCard.svelte b/src/lib/components/PostCard.svelte index 56147e9..5f9a87f 100644 --- a/src/lib/components/PostCard.svelte +++ b/src/lib/components/PostCard.svelte @@ -44,6 +44,16 @@ let cargandoLike = $state(false); let errorLike = $state(false); + let contenido = $derived(() => { + let t = post.content.replaceAll('\n', '
'); + t = t.replace( + /#\w*/gm, + (match) => + `${match}` + ); + return t; + }); + async function handleBorrar() { await deletePost( post, @@ -127,7 +137,7 @@
-

{@html post.content.replaceAll('\n', '
')}

+

{@html contenido()}

{#if post.imageUrl} From 1ab5a374daa0003eae26dd18b5754dedcc0cc7db Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 16:45:52 -0300 Subject: [PATCH 16/22] =?UTF-8?q?a=C3=B1adido=20username=20en=20la=20pagin?= =?UTF-8?q?a=20de=20perfil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/components/CardPerfil.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/components/CardPerfil.svelte b/src/lib/components/CardPerfil.svelte index e29df1b..2a49fcb 100644 --- a/src/lib/components/CardPerfil.svelte +++ b/src/lib/components/CardPerfil.svelte @@ -81,6 +81,7 @@

{data.displayName} +

@{data.username}

{data.bio} From 126cbf694c1b3a9c9ffefd37f53188c3e82e4887 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 16:51:12 -0300 Subject: [PATCH 17/22] skeleton de la busqueda --- src/routes/search/+page.svelte | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/routes/search/+page.svelte diff --git a/src/routes/search/+page.svelte b/src/routes/search/+page.svelte new file mode 100644 index 0000000..e69de29 From ab21ff1ce8fbdb0a6e284c9a8ae97af6af31f8ab Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 19:57:57 -0300 Subject: [PATCH 18/22] hecha la pagina de busqueda --- src/lib/components/UserCard.svelte | 41 +++++++++++++++++++++++++++ src/lib/hooks/busquedaUsuarios.ts | 18 ++++++++++++ src/routes/search/+page.svelte | 0 src/routes/search/[user]/+page.svelte | 11 +++++++ src/routes/search/[user]/+page.ts | 16 +++++++++++ 5 files changed, 86 insertions(+) create mode 100644 src/lib/components/UserCard.svelte create mode 100644 src/lib/hooks/busquedaUsuarios.ts delete mode 100644 src/routes/search/+page.svelte create mode 100644 src/routes/search/[user]/+page.svelte create mode 100644 src/routes/search/[user]/+page.ts diff --git a/src/lib/components/UserCard.svelte b/src/lib/components/UserCard.svelte new file mode 100644 index 0000000..117c679 --- /dev/null +++ b/src/lib/components/UserCard.svelte @@ -0,0 +1,41 @@ + + + + +

+ {#if usu.bio} +
{usu.bio}
+ {/if} + + diff --git a/src/lib/hooks/busquedaUsuarios.ts b/src/lib/hooks/busquedaUsuarios.ts new file mode 100644 index 0000000..7508cba --- /dev/null +++ b/src/lib/hooks/busquedaUsuarios.ts @@ -0,0 +1,18 @@ +import { apiBase } from '@/stores/url'; +import { get } from 'svelte/store'; + +export async function busquedaUsuarios(username: string) { + if (!username) return null; + try { + const req = await fetch(`${get(apiBase)}/api/users/search?q=${username}`, { + method: 'GET' + }); + if (req.ok) { + let data = await req.json(); + return data; + } + return []; + } catch { + return null; + } +} diff --git a/src/routes/search/+page.svelte b/src/routes/search/+page.svelte deleted file mode 100644 index e69de29..0000000 diff --git a/src/routes/search/[user]/+page.svelte b/src/routes/search/[user]/+page.svelte new file mode 100644 index 0000000..5e57037 --- /dev/null +++ b/src/routes/search/[user]/+page.svelte @@ -0,0 +1,11 @@ + + +
+ {#each data.usuarios as usu} + + {/each} +
diff --git a/src/routes/search/[user]/+page.ts b/src/routes/search/[user]/+page.ts new file mode 100644 index 0000000..a5e2e59 --- /dev/null +++ b/src/routes/search/[user]/+page.ts @@ -0,0 +1,16 @@ +import { busquedaUsuarios } from '@/hooks/busquedaUsuarios'; +import type { PageProps } from '../$types'; +import { error } from '@sveltejs/kit'; +import type { UserResponseDto } from '../../../types'; + +export async function load({ params }: PageProps) { + let usuarios: UserResponseDto[] = await busquedaUsuarios(params.user); + if (usuarios == null) { + return error(500, 'No se pudo alcanzar el servidor.'); + } + + if (usuarios.length == 0) { + return error(404, 'No se encontraron usuarios que coinsidan con la busqueda.'); + } + return { usuarios }; +} From 1539c00c2735382a9b4c676252412917d4d4a1a1 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 20:06:34 -0300 Subject: [PATCH 19/22] estaba en server por lo que daba un problema con el render del search cuando volves --- src/routes/[perfil]/{+page.server.ts => +page.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/routes/[perfil]/{+page.server.ts => +page.ts} (100%) diff --git a/src/routes/[perfil]/+page.server.ts b/src/routes/[perfil]/+page.ts similarity index 100% rename from src/routes/[perfil]/+page.server.ts rename to src/routes/[perfil]/+page.ts From 3c007d2a7a310aff77df78f615952afa351c827e Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 20:08:32 -0300 Subject: [PATCH 20/22] fix: no salia la imagen de perfil del usuario en el post --- src/lib/components/PostCard.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/PostCard.svelte b/src/lib/components/PostCard.svelte index 5f9a87f..1828904 100644 --- a/src/lib/components/PostCard.svelte +++ b/src/lib/components/PostCard.svelte @@ -95,7 +95,7 @@
- + {post.authorDisplayName[0].toUpperCase()} From 56a4092a1c3cd767d10a37ec5f8f07ea3aaa646a Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 20:08:54 -0300 Subject: [PATCH 21/22] fix ahora se limita el width a la imagen posteada --- src/lib/components/PostCard.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/PostCard.svelte b/src/lib/components/PostCard.svelte index 1828904..bd9ab80 100644 --- a/src/lib/components/PostCard.svelte +++ b/src/lib/components/PostCard.svelte @@ -142,7 +142,7 @@ {#if post.imageUrl}
- + Post
From e58985b1e2e6a4a89c5a195b7a16b2242e0b3956 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 19 Dec 2025 20:09:40 -0300 Subject: [PATCH 22/22] fixes de ts --- src/routes/search/[user]/+page.svelte | 2 +- src/routes/search/[user]/+page.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/routes/search/[user]/+page.svelte b/src/routes/search/[user]/+page.svelte index 5e57037..13e3e4f 100644 --- a/src/routes/search/[user]/+page.svelte +++ b/src/routes/search/[user]/+page.svelte @@ -1,4 +1,4 @@ -