Añadido el update para las imagenes

This commit is contained in:
2025-12-08 18:03:17 -03:00
parent 4c47da4567
commit 5c388cfb12
3 changed files with 112 additions and 27 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ export async function updatePost(post: Post, callbackfn: Function, message: stri
try { try {
const formData = new FormData(); const formData = new FormData();
formData.append("content", post.content); 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}`, { const req = await fetch(get(apiBase) + `/api/posts/${post.id}`, {
method: 'PUT', method: 'PUT',
+110 -26
View File
@@ -4,6 +4,8 @@
import InputGroupButton from '@/components/ui/input-group/input-group-button.svelte'; import InputGroupButton from '@/components/ui/input-group/input-group-button.svelte';
import InputGroupTextarea from '@/components/ui/input-group/input-group-textarea.svelte'; import InputGroupTextarea from '@/components/ui/input-group/input-group-textarea.svelte';
import Kbd from '@/components/ui/kbd/kbd.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 type { Post } from '../../types';
import ArrowUpIcon from '@lucide/svelte/icons/arrow-up'; import ArrowUpIcon from '@lucide/svelte/icons/arrow-up';
import { Dialog } from '@/components/ui/dialog'; import { Dialog } from '@/components/ui/dialog';
@@ -15,6 +17,7 @@
import TooltipTrigger from '@/components/ui/tooltip/tooltip-trigger.svelte'; import TooltipTrigger from '@/components/ui/tooltip/tooltip-trigger.svelte';
import TooltipContent from '@/components/ui/tooltip/tooltip-content.svelte'; import TooltipContent from '@/components/ui/tooltip/tooltip-content.svelte';
import Spinner from '@/components/ui/spinner/spinner.svelte'; import Spinner from '@/components/ui/spinner/spinner.svelte';
import { filtrarImagen } from '@/utils';
interface Props { interface Props {
post: Post | null; post: Post | null;
@@ -24,6 +27,21 @@
let cargando = $state(false); 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) { async function handleKeydown(e: KeyboardEvent) {
if (e.ctrlKey && e.key === 'Enter') { if (e.ctrlKey && e.key === 'Enter') {
cargando = true; cargando = true;
@@ -37,6 +55,24 @@
await callbackfn(e); await callbackfn(e);
cargando = false; 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);
}
</script> </script>
<Dialog open={true} onOpenChange={() => (post = null)}> <Dialog open={true} onOpenChange={() => (post = null)}>
@@ -50,6 +86,10 @@
<InputGroupTextarea <InputGroupTextarea
bind:value={post!.content} bind:value={post!.content}
maxlength={280} maxlength={280}
ondragover={(e) => {
e.preventDefault();
}}
ondrop={handleDrop}
placeholder="Alguna novedad?" placeholder="Alguna novedad?"
onkeydown={handleKeydown} onkeydown={handleKeydown}
class="text-white" class="text-white"
@@ -63,32 +103,76 @@
</p> </p>
/ 280 / 280
</Kbd> </Kbd>
<TooltipProvider> <div class="flex items-center gap-2">
<Tooltip> {#if post.image}
<TooltipTrigger> <button
<InputGroupButton class="h-6 w-6 overflow-hidden rounded-full"
variant="default" onclick={() => (post.image = null)}
disabled={cargando} >
type="submit" <div class="relative h-full w-full">
class="transform rounded-full transition-transform ease-in hover:scale-120" <div
size="xs" class="relative h-full w-full"
> role="presentation"
<p class="flex items-center gap-1"> onmouseenter={() => (hoverimg = true)}
{#if cargando} onmouseleave={() => (hoverimg = false)}
<Spinner /> >
Cargando... <div class={{ 'brightness-50': hoverimg }}>
{:else} <img
Modificar src={URL.createObjectURL(post.image)}
<ArrowUpIcon class="mt-0.5 h-3.5! w-3.5!" /> alt="imagen seleccionada"
{/if} class="h-full w-full object-cover"
</p> onload={(e) => {
</InputGroupButton> const target = e.currentTarget as HTMLImageElement;
</TooltipTrigger> URL.revokeObjectURL(target.src);
<TooltipContent> }}
<Kbd>Ctrl</Kbd>+<Kbd>Enter</Kbd> />
</TooltipContent> </div>
</Tooltip> <div
</TooltipProvider> class="absolute inset-0 flex items-center justify-center"
class:opacity-100={hoverimg}
class:opacity-0={!hoverimg}
>
<Trash class="h-4 w-4 text-white" />
</div>
</div>
</div>
</button>
{/if}
<InputGroupButton
size="icon-sm"
variant="outline"
onclick={seleccionarImagen}
class={`${post?.image ? 'bg-blue-500/30!' : ''} rounded-full`}
>
<Paperclip />
</InputGroupButton>
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<InputGroupButton
variant="default"
disabled={cargando}
type="submit"
class="transform rounded-full transition-transform ease-in hover:scale-120"
size="xs"
>
<p class="flex items-center gap-1">
{#if cargando}
<Spinner />
Cargando...
{:else}
Modificar
<ArrowUpIcon class="mt-0.5 h-3.5! w-3.5!" />
{/if}
</p>
</InputGroupButton>
</TooltipTrigger>
<TooltipContent>
<Kbd>Ctrl</Kbd>+<Kbd>Enter</Kbd>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</div> </div>
</InputGroupAddon> </InputGroupAddon>
</InputGroup> </InputGroup>
+1
View File
@@ -7,6 +7,7 @@ export interface Post {
authorName: string; authorName: string;
content: string; content: string;
imageUrl?: string; imageUrl?: string;
image?: File | null;
parentPostId?: string; parentPostId?: string;
likesCount: number; likesCount: number;
repliesCount: number; repliesCount: number;