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',
+84
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,6 +103,49 @@
</p> </p>
/ 280 / 280
</Kbd> </Kbd>
<div class="flex items-center gap-2">
{#if post.image}
<button
class="h-6 w-6 overflow-hidden rounded-full"
onclick={() => (post.image = null)}
>
<div class="relative h-full w-full">
<div
class="relative h-full w-full"
role="presentation"
onmouseenter={() => (hoverimg = true)}
onmouseleave={() => (hoverimg = false)}
>
<div class={{ 'brightness-50': hoverimg }}>
<img
src={URL.createObjectURL(post.image)}
alt="imagen seleccionada"
class="h-full w-full object-cover"
onload={(e) => {
const target = e.currentTarget as HTMLImageElement;
URL.revokeObjectURL(target.src);
}}
/>
</div>
<div
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> <TooltipProvider>
<Tooltip> <Tooltip>
<TooltipTrigger> <TooltipTrigger>
@@ -90,6 +173,7 @@
</Tooltip> </Tooltip>
</TooltipProvider> </TooltipProvider>
</div> </div>
</div>
</InputGroupAddon> </InputGroupAddon>
</InputGroup> </InputGroup>
</form> </form>
+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;