enzostvs HF staff commited on
Commit
644d65a
β€’
1 Parent(s): f05d33c

some changes

Browse files
src/lib/components/community/Card.svelte CHANGED
@@ -8,9 +8,10 @@
8
  import Reactions from "./reactions/Reactions.svelte";
9
 
10
  export let card: CommunityCard;
 
11
 
12
  const handleClick = async () => {
13
- const request = await fetch(`/api/community/${card?.id}`);
14
  const { gallery, next, previous } = await request.json();
15
  galleryStore.set({
16
  gallery,
@@ -27,7 +28,7 @@
27
  <!-- svelte-ignore a11y-no-static-element-interactions -->
28
  <!-- svelte-ignore a11y-click-events-have-key-events -->
29
  <div
30
- class="cursor-pointer group bg-neutral-700 rounded-xl h-[400px] relative flex items-start justify-between flex-col p-5 transition-all duration-200 brightness-75 hover:brightness-100 z-[1] overflow-hidden"
31
  on:click={handleClick}
32
  >
33
  <div class="w-full h-full absolute top-0 left-0 -z-[1] rounded-xl overflow-hidden">
 
8
  import Reactions from "./reactions/Reactions.svelte";
9
 
10
  export let card: CommunityCard;
11
+ export let form: Record<string, string>;
12
 
13
  const handleClick = async () => {
14
+ const request = await fetch(`/api/community/${card?.id}?${new URLSearchParams(form)}`);
15
  const { gallery, next, previous } = await request.json();
16
  galleryStore.set({
17
  gallery,
 
28
  <!-- svelte-ignore a11y-no-static-element-interactions -->
29
  <!-- svelte-ignore a11y-click-events-have-key-events -->
30
  <div
31
+ class="cursor-pointer group bg-neutral-700 rounded-xl h-[400px] relative flex items-start justify-between flex-col p-5 transition-all duration-200 brightness-90 hover:brightness-100 z-[1] overflow-hidden"
32
  on:click={handleClick}
33
  >
34
  <div class="w-full h-full absolute top-0 left-0 -z-[1] rounded-xl overflow-hidden">
src/lib/components/community/viewer/Viewer.svelte CHANGED
@@ -7,10 +7,10 @@
7
  import Icon from "@iconify/svelte";
8
 
9
  import { galleryStore } from "$lib/stores/use-gallery";
10
- import UserIsLogged from '$lib/components/UserIsLogged.svelte';
11
  import Reactions from '../reactions/Reactions.svelte';
12
  import Button from '$lib/components/Button.svelte';
13
 
 
14
  let { open, gallery, previous, next } = get(galleryStore);
15
  let loading = false;
16
 
@@ -36,7 +36,7 @@
36
  const handlePagination = async (id?: string) => {
37
  if (!id) return;
38
  loading = true;
39
- const request = await fetch(`/api/community/${id}`);
40
  const { gallery, next, previous } = await request.json();
41
  galleryStore.set({
42
  gallery,
@@ -48,6 +48,14 @@
48
  $page.url.searchParams.set('gallery', id);
49
  goto(`?${$page.url.searchParams.toString()}`);
50
  };
 
 
 
 
 
 
 
 
51
  </script>
52
 
53
  <div
@@ -55,77 +63,84 @@
55
  class:opacity-0={!open}
56
  class:pointer-events-none={!open}
57
  >
58
- <div
59
- class="mx-auto lg:h-2/3 w-full max-w-6xl bg-neutral-900 transition-all duration-200 grid grid-cols-1 lg:grid-cols-2 rounded-xl overflow-hidden"
60
- class:translate-x-full={!open}
61
- use:clickoutside on:clickoutside={handleClose}
62
- >
63
- {#if gallery?.id}
64
- <img src={env.PUBLIC_FILE_UPLOAD_DIR}/{gallery?.image} alt={gallery?.prompt} class="w-full h-full object-cover" />
65
- <div class="flex flex-col justify-between w-full">
66
- <div class="w-full p-8">
67
- <header class="w-full flex items-start justify-between">
68
- <div class="flex items-center justify-start gap-4">
69
- <img src={gallery?.user?.picture} class="w-12 h-12 rounded-full object-cover" alt={gallery?.user?.name} />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  <div>
71
- <p class="text-neutral-100 font-bold text-lg">
72
- {gallery?.user?.name}
73
  </p>
74
- <p class="text-neutral-400 text-sm">
75
- @{gallery?.user?.preferred_username}
 
 
 
76
  </p>
 
77
  </div>
78
  </div>
79
- <button on:click={handleClose}>
80
- <Icon icon="carbon:close" class="w-6 h-6 text-white" />
81
- </button>
82
- </header>
83
- <div class="mt-8 grid grid-cols-1 gap-5">
84
- <Reactions reactions={gallery?.reactions} gallery_id={gallery.id} />
85
- <div>
86
- <a
87
- href="/generate?model={gallery?.model?.id}"
88
- class="flex items-center justify-start gap-4 rounded-lg cursor-pointer w-full text-left transition-all duration-200 hover:bg-neutral-950/50 p-3 -mx-3 group relative"
89
- >
90
- <img src={gallery?.model?.image} alt={gallery?.model?.title} class="w-14 h-14 rounded-lg object-cover" />
91
- <div>
92
- <p class="text-neutral-200 text-base font-medium">{gallery?.model?.title}</p>
93
- <p class="text-neutral-400 text-sm">{gallery?.model?.id}</p>
94
- </div>
95
- <div class="rounded-full absolute top-1/2 -translate-y-1/2 text-neutral-100 w-8 h-8 right-4 bg-pink-500 flex items-center justify-center transition-all duration-200 group-hover:opacity-100 opacity-0">
96
- <Icon icon="tabler:arrow-up" class="w-5 h-5 transform rotate-45 font-bold" />
97
- </div>
98
- </a>
99
- </div>
100
- <div>
101
- <p class="text-neutral-400 font-semibold text-xs uppercase">
102
- Prompt
103
- </p>
104
- <p class="text-neutral-200 text-base font-medium mt-2">"{gallery?.prompt}"</p>
105
- </div>
106
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  </div>
108
- <footer class="border-t border-neutral-800 px-8 py-6 flex items-center justify-between">
109
- <Button
110
- size="lg"
111
- theme="dark"
112
- disabled={!previous}
113
- loading={loading}
114
- onClick={() => handlePagination(previous)}
115
- >
116
- Previous
117
- </Button>
118
- <Button
119
- size="lg"
120
- theme="light"
121
- loading={loading}
122
- disabled={!next}
123
- onClick={() => handlePagination(next)}
124
- >
125
- Next
126
- </Button>
127
- </footer>
128
- </div>
129
- {/if}
130
- </div>
131
  </div>
 
7
  import Icon from "@iconify/svelte";
8
 
9
  import { galleryStore } from "$lib/stores/use-gallery";
 
10
  import Reactions from '../reactions/Reactions.svelte';
11
  import Button from '$lib/components/Button.svelte';
12
 
13
+ export let form: Record<string, string>;
14
  let { open, gallery, previous, next } = get(galleryStore);
15
  let loading = false;
16
 
 
36
  const handlePagination = async (id?: string) => {
37
  if (!id) return;
38
  loading = true;
39
+ const request = await fetch(`/api/community/${id}?${new URLSearchParams(form)}`);
40
  const { gallery, next, previous } = await request.json();
41
  galleryStore.set({
42
  gallery,
 
48
  $page.url.searchParams.set('gallery', id);
49
  goto(`?${$page.url.searchParams.toString()}`);
50
  };
51
+
52
+ // to url search params
53
+ const handleClickModel = (id?: string) => {
54
+ if (!id) return;
55
+ $page.url.searchParams.set('model', id);
56
+ $page.url.searchParams.delete('gallery');
57
+ goto(`/?${$page.url.searchParams.toString()}`);
58
+ };
59
  </script>
60
 
61
  <div
 
63
  class:opacity-0={!open}
64
  class:pointer-events-none={!open}
65
  >
66
+ {#if open}
67
+ <div
68
+ class="mx-auto w-full max-w-6xl bg-neutral-900 transition-all duration-200 lg:grid lg:grid-cols-2 rounded-xl overflow-hidden"
69
+ use:clickoutside on:clickoutside={handleClose}
70
+ >
71
+ {#if gallery?.id}
72
+ <img src={env.PUBLIC_FILE_UPLOAD_DIR}/{gallery?.image} alt={gallery?.prompt} class="w-full object-cover h-[200px] lg:h-auto" />
73
+ <div class="flex flex-col justify-between w-full overflow-auto flex-1">
74
+ <div class="w-full p-8">
75
+ <header class="w-full flex items-start justify-between">
76
+ <div class="flex items-center justify-start gap-4">
77
+ <img src={gallery?.user?.picture} class="w-12 h-12 rounded-full object-cover" alt={gallery?.user?.name} />
78
+ <div>
79
+ <p class="text-neutral-100 font-bold text-lg">
80
+ {gallery?.user?.name}
81
+ </p>
82
+ <p class="text-neutral-400 text-sm">
83
+ @{gallery?.user?.preferred_username}
84
+ </p>
85
+ </div>
86
+ </div>
87
+ <button on:click={handleClose}>
88
+ <Icon icon="carbon:close" class="w-6 h-6 text-white" />
89
+ </button>
90
+ </header>
91
+ <div class="mt-8 grid grid-cols-1 gap-5 overflow-auto">
92
+ <Reactions reactions={gallery?.reactions} gallery_id={gallery.id} />
93
+ <div>
94
+ <button
95
+ class="flex items-center justify-start gap-4 cursor-pointer w-full text-left transition-all duration-200 hover:bg-neutral-950/50 py-3 pr-3 pl-6 -mx-3 group relative"
96
+ on:click={() => handleClickModel(gallery?.model?.id)}
97
+ >
98
+ <img src={gallery?.model?.image} alt={gallery?.model?.title} class="w-14 h-14 rounded-lg object-cover" />
99
+ <div>
100
+ <p class="text-neutral-200 text-base font-medium">{gallery?.model?.title}</p>
101
+ <p class="text-neutral-400 text-sm">{gallery?.model?.id}</p>
102
+ </div>
103
+ <div class="rounded-full absolute top-1/2 -translate-y-1/2 text-neutral-100 w-8 h-8 right-4 bg-pink-500 flex items-center justify-center transition-all duration-200 group-hover:opacity-100 opacity-0">
104
+ <Icon icon="tabler:arrow-up" class="w-5 h-5 transform rotate-45 font-bold" />
105
+ </div>
106
+ </button>
107
+ </div>
108
  <div>
109
+ <p class="text-neutral-400 font-semibold text-xs uppercase">
110
+ Prompt
111
  </p>
112
+ <p class="text-neutral-200 text-base font-medium mt-2">"{gallery?.prompt}"</p>
113
+ </div>
114
+ <div>
115
+ <p class="text-neutral-400 font-semibold text-xs uppercase">
116
+ Dimension
117
  </p>
118
+ <p class="text-neutral-200 text-base font-medium mt-2">1024x1024</p>
119
  </div>
120
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  </div>
122
+ <footer class="border-t border-neutral-800 px-8 py-6 flex items-center justify-between">
123
+ <Button
124
+ size="lg"
125
+ theme="dark"
126
+ disabled={!previous}
127
+ loading={loading}
128
+ onClick={() => handlePagination(previous)}
129
+ >
130
+ Previous
131
+ </Button>
132
+ <Button
133
+ size="lg"
134
+ theme="light"
135
+ loading={loading}
136
+ disabled={!next}
137
+ onClick={() => handlePagination(next)}
138
+ >
139
+ Next
140
+ </Button>
141
+ </footer>
142
  </div>
143
+ {/if}
144
+ </div>
145
+ {/if}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  </div>
src/lib/components/models/Card.svelte CHANGED
@@ -22,7 +22,7 @@
22
  <!-- svelte-ignore a11y-no-static-element-interactions -->
23
  <!-- svelte-ignore a11y-click-events-have-key-events -->
24
  <div
25
- class="w-full cursor-pointer group bg-neutral-900 rounded-xl relative flex items-start justify-between flex-col p-3 border border-neutral-800 transition-all duration-200 brightness-75 hover:brightness-100 z-[1]"
26
  on:click={handleClick}
27
  >
28
  <div class="w-full h-[350px] relative z-[1] mb-3 overflow-hidden">
 
22
  <!-- svelte-ignore a11y-no-static-element-interactions -->
23
  <!-- svelte-ignore a11y-click-events-have-key-events -->
24
  <div
25
+ class="w-full cursor-pointer group bg-neutral-900 rounded-xl relative flex items-start justify-between flex-col p-3 border border-neutral-800 transition-all duration-200 brightness-90 hover:brightness-100 z-[1]"
26
  on:click={handleClick}
27
  >
28
  <div class="w-full h-[350px] relative z-[1] mb-3 overflow-hidden">
src/lib/components/models/drawer/Drawer.svelte CHANGED
@@ -9,6 +9,7 @@
9
  import UserIsLogged from '$lib/components/UserIsLogged.svelte';
10
  import Comments from '$lib/components/models/drawer/comments/Comments.svelte';
11
  import { env } from '$env/dynamic/public';
 
12
 
13
  let { open, model } = get(modelStore);
14
 
@@ -31,63 +32,86 @@
31
  </script>
32
 
33
  <div
34
- class="w-full fixed top-0 left-0 h-full bg-black bg-opacity-50 z-40 backdrop-blur transition-all duration-100"
35
  class:opacity-0={!open}
36
  class:pointer-events-none={!open}
 
37
  >
38
- <div
39
- class="ml-auto w-full max-w-3xl bg-neutral-950 h-full border-l border-neutral-800 transition-all duration-200 flex flex-col justify-between"
40
- class:translate-x-full={!open}
41
- use:clickoutside on:clickoutside={handleClose}
42
- >
43
- <div class="p-8 overflow-auto">
44
- <header class="flex w-full justify-between items-start mb-6">
45
- <div class="flex items-center justify-start gap-3 lg:gap-6">
46
- <img src={model?.image} class="lg:w-16 lg:h-16 w-12 h-12 rounded-xl bg-neutral-800 object-cover" alt={model?.id} />
47
- <div>
48
- <p class="text-white font-semibold text-lg lg:text-2xl mb-1 truncate">
49
- {model?.title ?? model?.id}
50
- </p>
51
- <div class="justify-start items-center gap-2 flex">
52
- <div class="bg-red-500 bg-opacity-20 border border-red-500 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 font-bold text-xs">
53
- <Icon icon="solar:heart-bold" class="lg:w-4 lg:h-4 w-3 h-3 text-red-500" />
54
- {model?.likes ?? 0}
55
- </div>
56
- <div class="bg-blue-500 bg-opacity-20 border border-blue-500 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 font-bold text-xs">
57
- <Icon icon="solar:download-square-bold" class="lg:w-4 lg:h-4 w-3 h-3 text-blue-500" />
58
- {model?.downloads ?? 0}
59
- </div>
60
  </div>
61
  </div>
62
- </div>
63
- <button on:click={handleClose}>
64
- <Icon icon="carbon:close" class="w-6 h-6 text-white cursor-pointer" />
65
- </button>
66
- </header>
67
- <main>
68
- {#if model?.gallery && model?.gallery?.length > 0}
69
- <div>
70
- <p class="text-neutral-400 uppercase text-xs font-bold">Examples</p>
71
- <div class="grid grid-cols-3 md:grid-cols-5 lg:grid-cols-6 gap-5 mt-2">
72
- {#each model?.gallery as example}
73
- <div class="w-full h-[120px] relative z-[1] mb-3 overflow-hidden">
74
- <img src="{env.PUBLIC_FILE_UPLOAD_DIR}/{example.image}" class="w-full h-full bg-center bg-cover rounded-lg object-cover object-center bg-neutral-800" alt={example.prompt} />
75
- </div>
76
- {/each}
77
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  {/if}
80
- </main>
81
  </div>
82
- <footer class="p-8 border-t border-neutral-900 bg-neutral-900/30">
83
- <p class="font-semibold text-neutral-100 text-base lg:text-lg mb-6">
84
- Commentaires ({model?.comments?.length ?? 0})
85
- </p>
86
- {#if model?.id}
87
- <UserIsLogged>
88
- <Comments comments={model?.comments} model={model} />
89
- </UserIsLogged>
90
- {/if}
91
- </footer>
92
- </div>
93
  </div>
 
9
  import UserIsLogged from '$lib/components/UserIsLogged.svelte';
10
  import Comments from '$lib/components/models/drawer/comments/Comments.svelte';
11
  import { env } from '$env/dynamic/public';
12
+ import Button from '$lib/components/Button.svelte';
13
 
14
  let { open, model } = get(modelStore);
15
 
 
32
  </script>
33
 
34
  <div
35
+ class="w-full fixed top-0 left-0 h-full bg-black bg-opacity-50 z-0 backdrop-blur transition-all duration-100"
36
  class:opacity-0={!open}
37
  class:pointer-events-none={!open}
38
+ class:!z-40={open}
39
  >
40
+ {#if open}
41
+ <div
42
+ class="ml-auto w-full max-w-3xl bg-neutral-950 h-full border-l border-neutral-800 transition-all duration-200 flex flex-col justify-between"
43
+ use:clickoutside on:clickoutside={handleClose}
44
+ >
45
+ <div class="p-8 overflow-auto">
46
+ <header class="flex w-full justify-between items-start mb-6 pr-6">
47
+ <div class="flex items-center justify-start gap-3 lg:gap-6">
48
+ <img src={model?.image} class="lg:w-16 lg:h-16 w-12 h-12 rounded-xl bg-neutral-800 object-cover" alt={model?.id} />
49
+ <div>
50
+ <p class="text-white font-semibold text-lg lg:text-2xl mb-1 truncate">
51
+ {model?.title ?? model?.id}
52
+ </p>
53
+ <a href="https://huggingface.co/{model?.id}" class="text-neutral-400 underline hover:text-blue-00 flex items-center justify-start gap-1">
54
+ <Icon icon="iconamoon:link-external-fill" class="w-4 h-4" />
55
+ View on HuggingFace
56
+ </a>
 
 
 
 
 
57
  </div>
58
  </div>
59
+ <button on:click={handleClose}>
60
+ <Icon icon="carbon:close" class="w-6 h-6 text-white cursor-pointer" />
61
+ </button>
62
+ </header>
63
+ <main>
64
+ <div class="justify-start items-center gap-4 flex mb-6">
65
+ <div class="bg-red-500 bg-opacity-20 border border-red-500 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 font-medium text-sm">
66
+ <Icon icon="solar:heart-bold" class="lg:w-4 lg:h-4 w-3 h-3 text-red-500" />
67
+ {model?.likes ?? 0}
 
 
 
 
 
 
68
  </div>
69
+ <a
70
+ href="/"
71
+ class="bg-blue-500 bg-opacity-20 border border-blue-500 hover:bg-opacity-60 transition-all duration-200 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 font-medium text-sm"
72
+ >
73
+ <Icon icon="solar:download-square-bold" class="lg:w-4 lg:h-4 w-3 h-3 text-blue-500" />
74
+ View files
75
+ </a>
76
+ <a
77
+ href="/generate?model={model?.id}"
78
+ class="bg-pink-500 bg-opacity-20 hover:bg-opacity-60 transition-all duration-200 border border-pink-500 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 font-medium text-sm"
79
+ >
80
+ <Icon icon="fluent:glance-horizontal-sparkles-16-filled" class="lg:w-4 lg:h-4 w-3 h-3 text-pink-500" />
81
+ Generate
82
+ </a>
83
  </div>
84
+ {#if model?.gallery && model?.gallery?.length > 0}
85
+ <div>
86
+ <p class="text-neutral-400 uppercase text-xs font-bold">Examples</p>
87
+ <div class="grid grid-cols-3 md:grid-cols-5 lg:grid-cols-6 gap-5 mt-2">
88
+ {#each model?.gallery as example}
89
+ <div class="w-full h-[120px] relative z-[1] mb-3 overflow-hidden">
90
+ <img src="{env.PUBLIC_FILE_UPLOAD_DIR}/{example.image}" class="w-full h-full bg-center bg-cover rounded-lg object-cover object-center bg-neutral-800" alt={example.prompt} />
91
+ </div>
92
+ {/each}
93
+ </div>
94
+ </div>
95
+ {:else}
96
+ <div class="bg-neutral-900 rounded-lg p-8 text-center">
97
+ <p class="text-neutral-400 font-base">No generation examples available for this model</p>
98
+ <a href="/generate?model={model?.id}" class="text-neutral-100 underline">
99
+ Generate the first one
100
+ </a>
101
+ </div>
102
+ {/if}
103
+ </main>
104
+ </div>
105
+ <footer class="p-8 border-t border-neutral-900 bg-neutral-900/30">
106
+ <p class="font-semibold text-neutral-100 text-base lg:text-lg mb-6">
107
+ Commentaires ({model?.comments?.length ?? 0})
108
+ </p>
109
+ {#if model?.id}
110
+ <UserIsLogged>
111
+ <Comments comments={model?.comments} model={model} />
112
+ </UserIsLogged>
113
  {/if}
114
+ </footer>
115
  </div>
116
+ {/if}
 
 
 
 
 
 
 
 
 
 
117
  </div>
src/lib/components/sidebar/Sidebar.svelte CHANGED
@@ -2,11 +2,13 @@
2
  import cookies from 'js-cookie';
3
  import Icon from "@iconify/svelte"
4
  import { get } from 'svelte/store';
 
5
 
6
  import { userStore, openWindowLogin } from "$lib/stores/use-user";
7
  import { SIDEBAR_MENUS } from "$lib/utils";
8
 
9
  import Menu from "./Menu.svelte";
 
10
 
11
  let isOpen = false;
12
  let user = get(userStore);
@@ -23,6 +25,13 @@
23
  cookies.remove("hf_access_token");
24
  window.location.href = "/";
25
  }
 
 
 
 
 
 
 
26
  </script>
27
 
28
  <button class="bg-transparent absolute top-10 right-8 cursor-pointer xl:hidden" on:click="{handleClick}">
 
2
  import cookies from 'js-cookie';
3
  import Icon from "@iconify/svelte"
4
  import { get } from 'svelte/store';
5
+ import { page } from '$app/stores';
6
 
7
  import { userStore, openWindowLogin } from "$lib/stores/use-user";
8
  import { SIDEBAR_MENUS } from "$lib/utils";
9
 
10
  import Menu from "./Menu.svelte";
11
+ import { browser } from '$app/environment';
12
 
13
  let isOpen = false;
14
  let user = get(userStore);
 
25
  cookies.remove("hf_access_token");
26
  window.location.href = "/";
27
  }
28
+
29
+ // sveltekit close sidebar on route change
30
+ if (browser) {
31
+ page.subscribe((value) => {
32
+ if (isOpen) handleClick();
33
+ });
34
+ }
35
  </script>
36
 
37
  <button class="bg-transparent absolute top-10 right-8 cursor-pointer xl:hidden" on:click="{handleClick}">
src/routes/+page.svelte CHANGED
@@ -26,7 +26,10 @@
26
  $: elementScroll = browser ? document?.getElementById('app') : undefined;
27
 
28
  if (data?.model?.id) {
29
- modelStore.set(data.model);
 
 
 
30
  }
31
 
32
  const handleFetchMore = async () => {
@@ -48,7 +51,10 @@
48
  const request = await fetch(`/api/models?${new URLSearchParams(form)}`);
49
  const response = await request.json();
50
  if (add) data = {...data, models: [...data.models, ...response.cards ]};
51
- else data = response;
 
 
 
52
  }
53
  </script>
54
 
@@ -61,6 +67,7 @@
61
  <Dialog open={submitModelDialog} onClose={() => submitModelDialog = false}>
62
  <SubmitModel onClose={() => submitModelDialog = false} />
63
  </Dialog>
 
64
  <h1 class="text-white font-semibold text-2xl">
65
  Explore Models ({data?.total_items ?? 0})
66
  </h1>
@@ -110,5 +117,4 @@
110
  />
111
  <GoTop />
112
  </div>
113
- <Drawer />
114
  </main>
 
26
  $: elementScroll = browser ? document?.getElementById('app') : undefined;
27
 
28
  if (data?.model?.id) {
29
+ modelStore.set({
30
+ model: data.model,
31
+ open: true
32
+ });
33
  }
34
 
35
  const handleFetchMore = async () => {
 
51
  const request = await fetch(`/api/models?${new URLSearchParams(form)}`);
52
  const response = await request.json();
53
  if (add) data = {...data, models: [...data.models, ...response.cards ]};
54
+ else {
55
+ data.models = response.cards;
56
+ data.total_items = response.total_items;
57
+ }
58
  }
59
  </script>
60
 
 
67
  <Dialog open={submitModelDialog} onClose={() => submitModelDialog = false}>
68
  <SubmitModel onClose={() => submitModelDialog = false} />
69
  </Dialog>
70
+ <Drawer />
71
  <h1 class="text-white font-semibold text-2xl">
72
  Explore Models ({data?.total_items ?? 0})
73
  </h1>
 
117
  />
118
  <GoTop />
119
  </div>
 
120
  </main>
src/routes/api/community/[id]/+server.ts CHANGED
@@ -3,8 +3,10 @@ import prisma from '$lib/prisma';
3
 
4
  /** @type {import('./$types').RequestHandler} */
5
 
6
- export async function GET({ params } : RequestEvent) {
7
  const id = params.id;
 
 
8
 
9
  const gallery = await prisma.gallery.findFirst({
10
  where: {
@@ -63,7 +65,20 @@ export async function GET({ params } : RequestEvent) {
63
  isPublic: true,
64
  createdAt: {
65
  lt: gallery.createdAt
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
 
67
  },
68
  select: {
69
  id: true,
@@ -75,7 +90,20 @@ export async function GET({ params } : RequestEvent) {
75
  isPublic: true,
76
  createdAt: {
77
  gt: gallery.createdAt
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
 
79
  },
80
  select: {
81
  id: true,
 
3
 
4
  /** @type {import('./$types').RequestHandler} */
5
 
6
+ export async function GET({ params, url } : RequestEvent) {
7
  const id = params.id;
8
+ const filter = url.searchParams.get('filter') || 'new'
9
+ const search = url.searchParams.get('search') || ''
10
 
11
  const gallery = await prisma.gallery.findFirst({
12
  where: {
 
65
  isPublic: true,
66
  createdAt: {
67
  lt: gallery.createdAt
68
+ },
69
+ OR: [
70
+ { prompt: { contains: search } },
71
+ ],
72
+ },
73
+ orderBy: {
74
+ ...(filter === 'new' ? {
75
+ createdAt: 'desc'
76
+ } : {
77
+ reactions: {
78
+ _count: 'desc'
79
+ }
80
  }
81
+ )
82
  },
83
  select: {
84
  id: true,
 
90
  isPublic: true,
91
  createdAt: {
92
  gt: gallery.createdAt
93
+ },
94
+ OR: [
95
+ { prompt: { contains: search } },
96
+ ],
97
+ },
98
+ orderBy: {
99
+ ...(filter === 'new' ? {
100
+ createdAt: 'desc'
101
+ } : {
102
+ reactions: {
103
+ _count: 'desc'
104
+ }
105
  }
106
+ )
107
  },
108
  select: {
109
  id: true,
src/routes/gallery/+page.svelte CHANGED
@@ -53,7 +53,7 @@
53
  <h1 class="text-white font-semibold text-2xl">
54
  Community Gallery ({data.total_items})
55
  </h1>
56
- <div class="flex items-center justify-between mt-5">
57
  <Radio options={COMMUNITY_FILTER_OPTIONS} value="{form.filter}" onChange={handleChangeFilter} />
58
  <div class="items-center justify-end gap-5 hidden lg:flex">
59
  <!-- <UserIsLogged> -->
@@ -74,7 +74,7 @@
74
  <!-- mx-auto grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-5 gap-5 mt-8 lg:mt-10 -->
75
  <div class="mx-auto grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 2xl:grid-cols-4 gap-5 mt-8 lg:mt-10">
76
  {#each data.cards as card}
77
- <Card card={card} />
78
  {/each}
79
  <InfiniteScroll
80
  elementScroll="{elementScroll ?? undefined}"
@@ -84,5 +84,5 @@
84
  />
85
  <GoTop />
86
  </div>
87
- <GalleryViewer />
88
  </main>
 
53
  <h1 class="text-white font-semibold text-2xl">
54
  Community Gallery ({data.total_items})
55
  </h1>
56
+ <div class="flex items-start sm:items-center justify-between mt-5 flex-col sm:flex-row gap-5 sm:justify-between">
57
  <Radio options={COMMUNITY_FILTER_OPTIONS} value="{form.filter}" onChange={handleChangeFilter} />
58
  <div class="items-center justify-end gap-5 hidden lg:flex">
59
  <!-- <UserIsLogged> -->
 
74
  <!-- mx-auto grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-5 gap-5 mt-8 lg:mt-10 -->
75
  <div class="mx-auto grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 2xl:grid-cols-4 gap-5 mt-8 lg:mt-10">
76
  {#each data.cards as card}
77
+ <Card card={card} form={form} />
78
  {/each}
79
  <InfiniteScroll
80
  elementScroll="{elementScroll ?? undefined}"
 
84
  />
85
  <GoTop />
86
  </div>
87
+ <GalleryViewer form={form} />
88
  </main>