adds feed
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import { page } from "$app/state";
|
||||
import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg";
|
||||
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
|
||||
import Search, {
|
||||
type SearchItem,
|
||||
} from "$lib/components/base/search.svelte";
|
||||
import CategoryCard from "$lib/components/category_card.svelte";
|
||||
import EmptyStateFeed from "$lib/components/empty_states/empty_state_feed.svelte";
|
||||
import FeedCard from "$lib/components/profile/feed_card.svelte";
|
||||
import Scene from "$lib/components/scene.svelte";
|
||||
import TrailCard from "$lib/components/trail/trail_card.svelte";
|
||||
import {
|
||||
@@ -13,6 +16,7 @@
|
||||
type TrailSearchResult,
|
||||
} from "$lib/models/trail.js";
|
||||
import { categories } from "$lib/stores/category_store";
|
||||
import { feed_index } from "$lib/stores/feed_store.js";
|
||||
import {
|
||||
searchActors,
|
||||
searchMulti,
|
||||
@@ -20,7 +24,6 @@
|
||||
type LocationSearchResult,
|
||||
} from "$lib/stores/search_store.js";
|
||||
import { theme } from "$lib/stores/theme_store";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
import { getIconForLocation } from "$lib/util/icon_util.js";
|
||||
import { Canvas } from "@threlte/core";
|
||||
import { _ } from "svelte-i18n";
|
||||
@@ -29,6 +32,15 @@
|
||||
|
||||
let searchDropdownItems: SearchItem[] = $state([]);
|
||||
|
||||
let feed = $state(data.feed);
|
||||
|
||||
let pagination = $derived({
|
||||
page: feed.page,
|
||||
totalPages: feed.totalItems,
|
||||
});
|
||||
|
||||
let loading: boolean = false;
|
||||
|
||||
async function search(q: string) {
|
||||
if (q.startsWith("@")) {
|
||||
const actors = await searchActors(q);
|
||||
@@ -97,18 +109,41 @@
|
||||
goto(`/map/?lat=${item.value.lat}&lon=${item.value.lon}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function onScroll(e: Event) {
|
||||
if (!page.data.user) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
window.innerHeight + window.scrollY >=
|
||||
0.8 * document.body.offsetHeight &&
|
||||
pagination.page !== pagination.totalPages &&
|
||||
!loading
|
||||
) {
|
||||
loading = true;
|
||||
await loadNextPage();
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadNextPage() {
|
||||
pagination.page += 1;
|
||||
feed = await feed_index(pagination.page);
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Home | wanderer</title>
|
||||
</svelte:head>
|
||||
|
||||
<svelte:window onscroll={onScroll} />
|
||||
|
||||
<section
|
||||
class="hero grid grid-cols-1 lg:grid-cols-2 md:px-8 md:gap-8"
|
||||
style="height: calc(100vh - 112px)"
|
||||
style="min-height: calc(100vh - 112px)"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col justify-center gap-8 max-w-md mx-8 sm:mx-auto mt-0 lg:-mt-24 md:mt-24"
|
||||
class="flex flex-col justify-center gap-8 max-w-md mx-8 sm:mx-auto mt-0 lg:-mt-24 md:mt-24 max-h-screen md:sticky top-0"
|
||||
>
|
||||
<h2 class="text-5xl sm:text-6xl md:text-7xl font-bold">
|
||||
{$_("welcome_to")} <span class="-tracking-[0.075em]">wanderer</span>
|
||||
@@ -125,89 +160,111 @@
|
||||
items={searchDropdownItems}
|
||||
></Search>
|
||||
</div>
|
||||
<div class="hidden md:block">
|
||||
<Canvas toneMapping={0}>
|
||||
<Scene></Scene>
|
||||
</Canvas>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
class="max-w-7xl mx-auto mt-8 px-8 xl:px-0 grid grid-cols-1 md:grid-cols-2 items-center gap-x-12"
|
||||
>
|
||||
<div
|
||||
id="trails"
|
||||
class="flex flex-wrap justify-items-center gap-8 py-8 order-1 md:order-none"
|
||||
>
|
||||
{#if data.trails.length == 0}
|
||||
<img
|
||||
style="width: min(450px, 100%)"
|
||||
class="rounded-md"
|
||||
src={$theme === "light"
|
||||
? emptyStateTrailLight
|
||||
: emptyStateTrailDark}
|
||||
alt="Empty state"
|
||||
/>
|
||||
{:else}
|
||||
{#each data.trails as trail}
|
||||
{#if !page.data.user}
|
||||
<div class="hidden md:block">
|
||||
<Canvas toneMapping={0}>
|
||||
<Scene></Scene>
|
||||
</Canvas>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="space-y-2">
|
||||
{#if feed.items.length === 0}
|
||||
<EmptyStateFeed></EmptyStateFeed>
|
||||
{/if}
|
||||
{#each feed.items as f}
|
||||
<a
|
||||
class="w-full md:max-w-72"
|
||||
href="/trail/view/@{trail.author}{trail.domain
|
||||
? '@' + trail.domain
|
||||
: ''}/{trail.id}"
|
||||
>
|
||||
<TrailCard {trail} fullWidth selected={false} hovered={false}></TrailCard></a
|
||||
class="block"
|
||||
href={(f.type === "trail" ? "/trail/view/" : "/lists/") +
|
||||
`@${f.expand.author?.preferred_username}@${f.expand.author?.domain}/${f.item}`}
|
||||
>
|
||||
<FeedCard feedItem={f}></FeedCard>
|
||||
</a>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="max-w-md md:mx-auto space-y-8">
|
||||
{#if data.trails.length == 0}
|
||||
<h2 class="text-4xl md:text-5xl font-bold">
|
||||
{$_("hero_section_1_heading")}
|
||||
</h2>
|
||||
<h5>{$_("hero_section_1_text_alternative")}</h5>
|
||||
<a
|
||||
class="inline-block btn-primary btn-large"
|
||||
href="/trail/edit/new"
|
||||
role="button">{$_("new-trail")}</a
|
||||
>
|
||||
{:else}
|
||||
<h2 class="text-4xl md:text-5xl font-bold">
|
||||
{$currentUser
|
||||
? $_("trails-for-you")
|
||||
: $_("explore-some-trails")}
|
||||
</h2>
|
||||
<h5>
|
||||
{$_("hero_section_1_text")}
|
||||
</h5>
|
||||
<a
|
||||
class="inline-block btn-primary btn-large"
|
||||
href="/trails"
|
||||
role="button">{$_("explore")}</a
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
<section
|
||||
class="max-w-7xl mx-auto mt-8 px-8 xl:px-0 grid grid-cols-1 md:grid-cols-2 items-center"
|
||||
>
|
||||
<div class="max-w-md md:mx-auto space-y-8">
|
||||
<h2 class="text-4xl md:text-5xl font-bold">{$_("categories")}</h2>
|
||||
<h5>
|
||||
{$_("hero_section_2_text")}
|
||||
</h5>
|
||||
</div>
|
||||
<div
|
||||
id="categories"
|
||||
class="grid grid-cols-1 lg:grid-cols-2 justify-items-center gap-8 py-8"
|
||||
{#if !page.data.user}
|
||||
<section
|
||||
class="max-w-7xl mx-auto mt-8 px-8 xl:px-0 grid grid-cols-1 md:grid-cols-2 items-center gap-x-12"
|
||||
>
|
||||
{#each $categories as category}
|
||||
<a href="/trails?category={category.name}">
|
||||
<CategoryCard {category}></CategoryCard>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
||||
<div
|
||||
id="trails"
|
||||
class="flex flex-wrap justify-items-center gap-8 py-8 order-1 md:order-none"
|
||||
>
|
||||
{#if data.trails.length == 0}
|
||||
<img
|
||||
style="width: min(450px, 100%)"
|
||||
class="rounded-md"
|
||||
src={$theme === "light"
|
||||
? emptyStateTrailLight
|
||||
: emptyStateTrailDark}
|
||||
alt="Empty state"
|
||||
/>
|
||||
{:else}
|
||||
{#each data.trails as trail}
|
||||
<a
|
||||
class="w-full md:max-w-72"
|
||||
href="/trail/view/@{trail.author}{trail.domain
|
||||
? '@' + trail.domain
|
||||
: ''}/{trail.id}"
|
||||
>
|
||||
<TrailCard
|
||||
{trail}
|
||||
fullWidth
|
||||
selected={false}
|
||||
hovered={false}
|
||||
></TrailCard></a
|
||||
>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="max-w-md md:mx-auto space-y-8">
|
||||
{#if data.trails.length == 0}
|
||||
<h2 class="text-4xl md:text-5xl font-bold">
|
||||
{$_("hero_section_1_heading")}
|
||||
</h2>
|
||||
<h5>{$_("hero_section_1_text_alternative")}</h5>
|
||||
<a
|
||||
class="inline-block btn-primary btn-large"
|
||||
href="/trail/edit/new"
|
||||
role="button">{$_("new-trail")}</a
|
||||
>
|
||||
{:else}
|
||||
<h2 class="text-4xl md:text-5xl font-bold">
|
||||
{$_("explore-some-trails")}
|
||||
</h2>
|
||||
<h5>
|
||||
{$_("hero_section_1_text")}
|
||||
</h5>
|
||||
<a
|
||||
class="inline-block btn-primary btn-large"
|
||||
href="/trails"
|
||||
role="button">{$_("explore")}</a
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
class="max-w-7xl mx-auto mt-8 px-8 xl:px-0 grid grid-cols-1 md:grid-cols-2 items-center"
|
||||
>
|
||||
<div class="max-w-md md:mx-auto space-y-8">
|
||||
<h2 class="text-4xl md:text-5xl font-bold">{$_("categories")}</h2>
|
||||
<h5>
|
||||
{$_("hero_section_2_text")}
|
||||
</h5>
|
||||
</div>
|
||||
<div
|
||||
id="categories"
|
||||
class="grid grid-cols-1 lg:grid-cols-2 justify-items-center gap-8 py-8"
|
||||
>
|
||||
{#each $categories as category}
|
||||
<a href="/trails?category={category.name}">
|
||||
<CategoryCard {category}></CategoryCard>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Trail } from "$lib/models/trail";
|
||||
import { categories_index } from "$lib/stores/category_store";
|
||||
import { feed_index } from "$lib/stores/feed_store";
|
||||
import { trails_recommend } from "$lib/stores/trail_store";
|
||||
import type { ServerLoad } from "@sveltejs/kit";
|
||||
|
||||
@@ -7,11 +8,13 @@ export const load: ServerLoad = async ({ params, locals, fetch }) => {
|
||||
try {
|
||||
await categories_index(fetch)
|
||||
|
||||
const feed = await feed_index(1, 10, fetch);
|
||||
|
||||
const trails: Trail[] = await trails_recommend(4, fetch)
|
||||
return { trails: trails ?? [] }
|
||||
return { trails: trails ?? [], feed }
|
||||
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
return { trails: [] }
|
||||
return { trails: [], feed: {items: [], page: 1, perPage: 1, totalItems: 0, totalPages: 0} }
|
||||
};
|
||||
13
web/src/routes/api/v1/feed/+server.ts
Normal file
13
web/src/routes/api/v1/feed/+server.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { FeedItem } from "$lib/models/feed";
|
||||
import { Collection, handleError, list } from "$lib/util/api_util";
|
||||
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||
|
||||
export async function GET(event: RequestEvent) {
|
||||
try {
|
||||
const r = await list<FeedItem>(event, Collection.feed);
|
||||
return json(r)
|
||||
} catch (e) {
|
||||
return handleError(e)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -404,7 +404,6 @@
|
||||
><i class="fa fa-table mr-3"></i>{$_("all-activities")}</span
|
||||
>
|
||||
<div class=" overflow-x-auto">
|
||||
{data.logs.length}
|
||||
<SummitLogTable
|
||||
{summitLogs}
|
||||
handle={page.params.handle}
|
||||
|
||||
Reference in New Issue
Block a user