enzostvs HF staff commited on
Commit
c479a59
β€’
1 Parent(s): 97ec6f2

prepare infinite scroll

Browse files
package-lock.json CHANGED
@@ -9,7 +9,8 @@
9
  "version": "0.0.1",
10
  "dependencies": {
11
  "@iconify/svelte": "^3.1.4",
12
- "@sveltejs/adapter-node": "^1.3.1"
 
13
  },
14
  "devDependencies": {
15
  "@fontsource/fira-mono": "^4.5.10",
@@ -3420,6 +3421,11 @@
3420
  "svelte": "^3.19.0 || ^4.0.0"
3421
  }
3422
  },
 
 
 
 
 
3423
  "node_modules/svelte-preprocess": {
3424
  "version": "5.1.1",
3425
  "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.1.tgz",
 
9
  "version": "0.0.1",
10
  "dependencies": {
11
  "@iconify/svelte": "^3.1.4",
12
+ "@sveltejs/adapter-node": "^1.3.1",
13
+ "svelte-infinite-scroll": "^2.0.1"
14
  },
15
  "devDependencies": {
16
  "@fontsource/fira-mono": "^4.5.10",
 
3421
  "svelte": "^3.19.0 || ^4.0.0"
3422
  }
3423
  },
3424
+ "node_modules/svelte-infinite-scroll": {
3425
+ "version": "2.0.1",
3426
+ "resolved": "https://registry.npmjs.org/svelte-infinite-scroll/-/svelte-infinite-scroll-2.0.1.tgz",
3427
+ "integrity": "sha512-goTHCfOHRDCs8C5MeSuIc6LlAQ8zVQ+M4Y3LyvrDjx5rqSSxSrdCuQwIyWYNcO6j6/mnqRro3QB64ClBzfn+Wg=="
3428
+ },
3429
  "node_modules/svelte-preprocess": {
3430
  "version": "5.1.1",
3431
  "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.1.tgz",
package.json CHANGED
@@ -36,6 +36,7 @@
36
  "type": "module",
37
  "dependencies": {
38
  "@iconify/svelte": "^3.1.4",
39
- "@sveltejs/adapter-node": "^1.3.1"
 
40
  }
41
  }
 
36
  "type": "module",
37
  "dependencies": {
38
  "@iconify/svelte": "^3.1.4",
39
+ "@sveltejs/adapter-node": "^1.3.1",
40
+ "svelte-infinite-scroll": "^2.0.1"
41
  }
42
  }
src/lib/cards.json ADDED
The diff for this file is too large to render. See raw diff
 
src/lib/components/GoTop.svelte ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { browser } from "$app/environment";
3
+ import Icon from "@iconify/svelte";
4
+
5
+ const goTop = () => {
6
+ const element = document.getElementById('app');
7
+ element?.scrollTo({ top: 0, behavior: 'smooth' });
8
+ }
9
+
10
+ // WIP display only if scroll > 0 dynamically
11
+ $: visible = browser ? (document?.getElementById('app') as HTMLElement)?.scrollTop > 0 : false;
12
+ </script>
13
+
14
+ <button
15
+ class="rounded-full h-12 w-12 bg-white shadow-lg brightness-90 transition-all duration-200 hover:brightness-110 fixed bottom-8 right-8 flex items-center justify-center text-indigo-500 z-10"
16
+ class:opacity-0={!visible}
17
+ class:pointer-events-none={!visible}
18
+ on:click={goTop}
19
+ >
20
+ <Icon icon="foundation:arrow-up" class="w-8 h-8" />
21
+ </button>
src/lib/utils/index.ts CHANGED
@@ -1 +1,16 @@
1
- export const REACTION_EMOJIS = ["❀️", "🀩", "πŸŽ‰", "πŸ”₯"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export const REACTION_EMOJIS = ["❀️", "🀩", "πŸŽ‰", "πŸ”₯"]
2
+
3
+ export const COMMUNITY_FILTER_OPTIONS = [
4
+ {
5
+ label: "Most Liked",
6
+ value: "likes",
7
+ icon: "lucide:heart",
8
+ iconColor: "text-red-500"
9
+ },
10
+ {
11
+ label: "New",
12
+ value: "new",
13
+ icon: "lucide:zap",
14
+ iconColor: "text-yellow-500"
15
+ },
16
+ ];
src/routes/+page.svelte CHANGED
@@ -1,30 +1,29 @@
1
  <script lang="ts">
 
 
 
2
  import Button from "$lib/components/Button.svelte";
3
  import Card from "$lib/components/community/Card.svelte";
4
  import Input from "$lib/components/fields/Input.svelte";
5
  import Radio from "$lib/components/fields/Radio.svelte";
 
 
6
 
7
  export let data;
8
 
9
  let form = {
10
- filter: "likes"
 
11
  }
12
 
13
- const filter_options = [
14
- {
15
- label: "Most Liked",
16
- value: "likes",
17
- icon: "lucide:heart",
18
- iconColor: "text-red-500"
19
- },
20
- {
21
- label: "New",
22
- value: "new",
23
- icon: "lucide:zap",
24
- iconColor: "text-yellow-500"
25
- },
26
- ];
27
 
 
 
 
 
 
 
28
  </script>
29
 
30
  <svelte:head>
@@ -36,7 +35,7 @@
36
  Community Gallery
37
  </h1>
38
  <div class="flex items-center justify-between mt-5">
39
- <Radio options={filter_options} value="{form.filter}" onChange={(filter) => form = {...form, filter }} />
40
  <div class="flex items-center justify-end gap-5">
41
  <Button icon="ic:round-plus" theme="dark" size="lg">Upload own Image</Button>
42
  <Button icon="fluent:glance-horizontal-sparkles-16-filled" href="/generate" theme="pink" size="lg">Generate</Button>
@@ -49,4 +48,10 @@
49
  {#each data.cards as card}
50
  <Card card={card} />
51
  {/each}
 
 
 
 
 
 
52
  </div>
 
1
  <script lang="ts">
2
+ import { browser } from "$app/environment";
3
+ import InfiniteScroll from "svelte-infinite-scroll";
4
+
5
  import Button from "$lib/components/Button.svelte";
6
  import Card from "$lib/components/community/Card.svelte";
7
  import Input from "$lib/components/fields/Input.svelte";
8
  import Radio from "$lib/components/fields/Radio.svelte";
9
+ import { COMMUNITY_FILTER_OPTIONS } from "$lib/utils/index.js";
10
+ import GoTop from "$lib/components/GoTop.svelte";
11
 
12
  export let data;
13
 
14
  let form = {
15
+ filter: "likes",
16
+ page: "0",
17
  }
18
 
19
+ $: elementScroll = browser ? document?.getElementById('app') : undefined;
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
+ const fetchMore = async () => {
22
+ form = {...form, page: (Number(form.page) + 1).toString()};
23
+ const response = await fetch(`/api/community?${new URLSearchParams(form)}`);
24
+ const new_cards = await response.json();
25
+ data = {...data, cards: [...data.cards, ...new_cards]};
26
+ }
27
  </script>
28
 
29
  <svelte:head>
 
35
  Community Gallery
36
  </h1>
37
  <div class="flex items-center justify-between mt-5">
38
+ <Radio options={COMMUNITY_FILTER_OPTIONS} value="{form.filter}" onChange={(filter) => form = {...form, filter }} />
39
  <div class="flex items-center justify-end gap-5">
40
  <Button icon="ic:round-plus" theme="dark" size="lg">Upload own Image</Button>
41
  <Button icon="fluent:glance-horizontal-sparkles-16-filled" href="/generate" theme="pink" size="lg">Generate</Button>
 
48
  {#each data.cards as card}
49
  <Card card={card} />
50
  {/each}
51
+ <InfiniteScroll
52
+ elementScroll="{elementScroll ?? undefined}"
53
+ threshold={100}
54
+ on:loadMore={fetchMore}
55
+ />
56
+ <GoTop />
57
  </div>
src/routes/+page.ts CHANGED
@@ -1,5 +1,10 @@
1
  export async function load({ fetch }) {
2
- const data = await fetch("/api/community")
 
 
 
 
 
3
  const cards = await data.json()
4
  return { cards }
5
  }
 
1
  export async function load({ fetch }) {
2
+ const data = await fetch("/api/community?page=1", {
3
+ method: "GET",
4
+ headers: {
5
+ "Content-Type": "application/json"
6
+ }
7
+ })
8
  const cards = await data.json()
9
  return { cards }
10
  }
src/routes/api/community/+server.ts CHANGED
@@ -1,30 +1,19 @@
1
- import { error, json } from '@sveltejs/kit';
2
  // import { env } from '$env/dynamic/private'
3
 
4
- import type { CommunityCard } from '$lib/type';
5
- import { REACTION_EMOJIS } from "$lib/utils";
6
 
7
  /** @type {import('./$types').RequestHandler} */
8
 
9
- export async function GET() {
10
  const hasError = false
11
-
12
- const cards: CommunityCard[] = Array.from({ length: 50 }, (_, i) => ({
13
- reactions: REACTION_EMOJIS.sort(() => Math.random() - Math.random()).slice(0,
14
- Math.floor(Math.random() * REACTION_EMOJIS.length)
15
- ).map((emoji) => ({
16
- emoji,
17
- users: Array.from({ length: Math.floor(Math.random() * 10) }, (_, i) => i.toString()),
18
- })),
19
- id: i.toString(),
20
- model_name: "CommunityCard",
21
- prompt: "What is your favorite color?",
22
- image: "https://picsum.photos/seed/" + i + "/500/500",
23
- }))
24
-
25
  if (hasError) {
26
  return error(500, 'Internal Server Error')
27
  }
28
-
 
 
29
  return json(cards)
30
  }
 
1
+ import { error, json, type RequestEvent } from '@sveltejs/kit';
2
  // import { env } from '$env/dynamic/private'
3
 
4
+ import jsonData from "$lib/cards.json";
 
5
 
6
  /** @type {import('./$types').RequestHandler} */
7
 
8
+ export async function GET(request : RequestEvent) {
9
  const hasError = false
10
+
11
+ const page = parseInt(request.url.searchParams.get('page') || '0')
 
 
 
 
 
 
 
 
 
 
 
 
12
  if (hasError) {
13
  return error(500, 'Internal Server Error')
14
  }
15
+
16
+ const cards = jsonData.slice(page * 25, page * 25 + 25)
17
+
18
  return json(cards)
19
  }