Spaces:
Running
Running
File size: 3,626 Bytes
dd7ec11 f05d33c 35140b4 f05d33c 35140b4 eb29a95 96eeadd 97ec6f2 35140b4 0fd75db 35140b4 dd7ec11 f05d33c 644d65a f05d33c 35140b4 0fd75db 35140b4 0fd75db 35140b4 0fd75db f05d33c 0fd75db b0c2459 0fd75db 96eeadd 0fd75db 96eeadd 0fd75db a764df6 0fd75db dd7ec11 0fd75db |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
<script lang="ts">
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import Icon from "@iconify/svelte";
import type { CommunityCard } from "$lib/type";
import { galleryStore } from "$lib/stores/use-gallery";
import Loading from "$lib/components/Loading.svelte";
import Reactions from "./reactions/Reactions.svelte";
import { success } from "$lib/utils/toaster";
export let card: CommunityCard;
export let form: Record<string, string> | undefined = undefined;
export let displayReactions: boolean = true;
export let displayDelete: boolean = false;
let is_visible = true;
let loading = false;
const handleClick = async () => {
const request = await fetch(`/api/community/${card?.id}?${new URLSearchParams(form)}`);
const { gallery, next, previous } = await request.json();
galleryStore.set({
gallery,
open: true,
next,
previous
});
$page.url.searchParams.set('gallery', card?.id);
goto(`?${$page.url.searchParams.toString()}`);
};
const handleDelete = async (id: string) => {
if (loading) return;
loading = true
const request = await fetch(`/api/community/${id}`, {
method: "DELETE"
});
const { success } = await request.json();
if (success) is_visible = false;
loading = false;
}
</script>
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
{#if is_visible}
<div
class="cursor-pointer group bg-neutral-700 rounded-xl h-[400px] max-w-[400px] md:h-[350px] md:max-w-[350px] w-full relative flex items-start justify-between flex-col p-5 transition-all duration-200 brightness-90 hover:brightness-100 z-[1] overflow-hidden"
on:click={handleClick}
>
<div class="w-full h-full absolute top-0 left-0 -z-[1] rounded-xl overflow-hidden" class:!brightness-50={loading}>
<img class="w-full h-full bg-center bg-cover transition-all duration-200 group-hover:scale-110 object-cover" src="/api/images/{card.image}" alt="{card.prompt}" />
<div class="bg-gradient-to-b from-transparent via-black/50 to-black/70 absolute h-[100px] bottom-0 left-0 w-full"></div>
</div>
<div class="group-hover:opacity-100 opacity-0 translate-y-full group-hover:translate-y-0 transition-all duration-200 flex flex-col gap-4 w-full">
<div class="bg-black/40 backdrop-blur-sm border border-white/30 rounded-lg px-6 py-3 text-white transition-all duration-200 w-full relative">
<p class="text-white font-semibold text-lg">{card.prompt}</p>
<p class="text-white/75 font-regular text-base">{card.model.id}</p>
<button
class="absolute bottom-3 right-3"
on:click={(e) => {
e.stopPropagation();
e.preventDefault();
navigator.clipboard.writeText(card.prompt);
success("Prompt copied to clipboard");
}}
>
<Icon icon="solar:copy-bold-duotone" class="w-5 h-5 text-white/75 hover:text-white" />
</button>
</div>
</div>
{#if displayReactions}
<Reactions reactions={card.reactions} gallery_id={card.id} />
{/if}
{#if displayDelete}
<button
class="absolute bottom-3 right-3 p-2.5 rounded-full bg-red-500 backdrop-blur-sm transition-all duration-200 hover:bg-red-700"
on:click={(e) => {
e.stopPropagation();
e.preventDefault();
handleDelete(card.id);
}}
>
<Icon icon="ic:round-delete" class="text-white w-5 h-5" />
</button>
{/if}
{#if loading}
<Loading />
{/if}
</div>
{/if} |