File size: 4,685 Bytes
dd7ec11
f05d33c
 
35140b4
f05d33c
 
 
35140b4
eb29a95
08d7ef5
97ec6f2
 
35140b4
 
0fd75db
08d7ef5
0fd75db
 
35140b4
dd7ec11
f05d33c
644d65a
f05d33c
 
 
 
 
 
 
 
 
 
 
35140b4
 
0fd75db
35140b4
0fd75db
 
 
 
 
35140b4
0fd75db
08d7ef5
 
 
 
 
 
 
 
 
 
 
f05d33c
 
 
 
0fd75db
 
b0c2459
0fd75db
 
 
 
 
 
 
96eeadd
0fd75db
 
96eeadd
 
 
 
 
 
 
 
 
 
 
0fd75db
a764df6
0fd75db
 
 
08d7ef5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<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 { error, 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;
  export let displayPublish: 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;
	}

  const handlePublish = async (id: string) => {
    if (loading) return;
    loading = true
    const request = await fetch(`/api/community/${id}/publish`, {
      method: "POST"
    });
    const { success } = await request.json();
    if (success) card.isPublic = true;
    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 displayPublish || displayDelete}
      <div class="absolute bottom-0 left-0 w-full p-4 flex items-center justify-end gap-3">
        {#if displayPublish && !card.isPublic}
          <button
            class="px-4 py-2.5 text-white rounded-full bg-blue-500 backdrop-blur-sm text-sm font-medium transition-all duration-200 hover:bg-blue-700"
            on:click={(e) => {
              e.stopPropagation();
              e.preventDefault();
              handlePublish(card.id);
              success("Published successfully");
            }}
          >
            Publish
          </button>
        {/if}
        {#if displayDelete}
          <button
            class="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);
              error("Deleted successfully");
            }}
          >
            <Icon icon="ic:round-delete" class="text-white w-5 h-5" />
          </button>
        {/if}
      </div>
    {/if}
    {#if loading}
      <Loading />
    {/if}
  </div>
{/if}