Skip to content

Commit

Permalink
feat: search, versions, and mod items
Browse files Browse the repository at this point in the history
Co-authored-by: fero <[email protected]>
Co-authored-by: sargon64 <[email protected]>
  • Loading branch information
3 people committed Aug 14, 2023
1 parent 5c07943 commit e6240bb
Show file tree
Hide file tree
Showing 16 changed files with 282 additions and 67 deletions.
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"dependencies": {
"jwt-decode": "^3.1.2",
"sugar": "^2.0.6",
"svelte-tiny-virtual-list": "^2.0.5",
"tailwind-preset-base": "workspace:^",
"ui": "workspace:^"
}
Expand Down
59 changes: 59 additions & 0 deletions apps/web/src/lib/components/ModListItem.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script lang="ts">
import Sugar from 'sugar';
import { CalendarIcon, DownloadIcon, LogoIcon, NotVerifiedIcon, VerifiedIcon, CogIcon, CubeIcon, ChevronDownIcon, CategoryIcon } from 'ui/icons';
import { Button } from 'ui/button';
import { Pill } from 'ui/pill';
import { Link } from 'ui/link';
import { slide, fly } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
export let name: string;
export let slug: string;
export let author: {
username: string;
};
export let description: string;
export let category: string;
export let downloads: any;
export let updatedAt: string;
export let icon: string;
</script>

<a href={`/mod/${slug}`}>
<div
class="beatforge-discover-list-item flex flex-row gap-2 md:gap-4 w-full bg-primary-850 hover:bg-primary-900 border-b-[1px] border-primary-850 items-center p-2 md:p-4 min-w-0 transition hover:duration-[0ms] duration-[120ms] min-h-[129px]">
<div
class="beatforge-discover-list-item-image h-12 w-12 md:h-24 md:w-24 bg-primary-600 flex flex-shrink-0 overflow-hidden rounded-md mr-2"
>
<img
alt={`Listing for mod ${name}, created by ${author}`}
src={icon ? icon : '/images/unknown.svg'}
class="w-full h-full object-fill"
/>
</div>
<div class="beatforge-discover-list-item-info w-full flex flex-col gap-1 md:gap-2 min-w-0 truncate">
<div class="beatforge-discover-list-item-info-title flex items-center gap-4">
<h2 class="font-black text-md md:text-2xl">{name}</h2>
<p class="text-sm text-primary-200">by {author}</p>
</div>
<div class="beatforge-discover-list-item-description flex min-w-0">
<p class="text-sm text-primary-200 truncate min-w-0 font-medium">
{description}
</p>
</div>
<div class="beatforge-discover-list-item-pills flex flex-row gap-2 overflow-x-auto">
<Pill label={category} customClasses="capitalize">
<CategoryIcon customClasses="w-4 h-4" />
</Pill>
<Pill label={`${downloads} Downloads`}>
<DownloadIcon customClasses="w-4 h-4" />
</Pill>
<Pill label={`Updated ${Sugar.Date.relative(new Date(updatedAt))}`}>
<CalendarIcon customClasses="w-4 h-4" />
</Pill>
</div>
</div>
</div>
</a>
62 changes: 62 additions & 0 deletions apps/web/src/lib/components/ModVersionItem.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script lang="ts">
import Sugar from 'sugar';
import { CalendarIcon, DownloadIcon, LogoIcon, NotVerifiedIcon, VerifiedIcon, CogIcon, CubeIcon, ChevronDownIcon } from 'ui/icons';
import { Button } from 'ui/button';
import { Pill } from 'ui/pill';
import { Link } from 'ui/link';
import { slide, fly } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
export let versionName: string;
export let downloads: any;
export let createdAt: string;
export let approved: boolean;
export let downloadUrl: string;
let isHovered: boolean = false
</script>

<div role="presentation" class="beatforge-modversionitem-list-item flex flex-row gap-2 md:gap-4 w-full bg-primary-850 border-b-[1px] border-primary-800 items-center p-2 md:p-4 min-w-0 min-h-[129px] rounded-md group" on:mouseenter={() => isHovered = true} on:mouseleave={() => isHovered = false}>
<div class="beatforge-modversionitem-list-item-info w-full flex flex-col gap-1 md:gap-2 min-w-0 truncate">
<div class="beatforge-modversionitem-list-item-info-title flex items-center gap-4">
<h2 class="font-black text-md md:text-2xl">{versionName}</h2>
{#if approved}
<VerifiedIcon customClasses="w-4 h-4 text-green-400" />
{:else}
<NotVerifiedIcon customClasses="w-6 h-6 text-red-400" />
{/if}
</div>
<div class="beatforge-modversionitem-list-item-pills flex flex-row gap-2 overflow-x-auto">
<Pill label={`${downloads} Downloads`}>
<DownloadIcon customClasses="w-4 h-4" />
</Pill>
<Pill label={`Updated ${Sugar.Date.relative(new Date(createdAt))}`}>
<CalendarIcon customClasses="w-4 h-4" />
</Pill>
</div>
</div>
<div class="hidden md:flex flex-col items-end w-1/3">
<div class="beatforge-btn-wrapper flex flex-col rounded-lg overflow-hidden min-w-[199px] will-change-transform -mb-[4px]">
<Button variant="gradient" customClasses="!rounded-[0px] will-change-transform">
<LogoIcon customClasses="w-4 h-4" />
<div class="text-sm font-bold will-change-transform">Install</div>
</Button>
{#if isHovered}
<div class="flex flex-row gap-[2px] mt-[2px] opacity-0 group-hover:opacity-100 overflow-hidden rounded-b-lg will-change-transform" transition:slide={{ delay: 0, duration: 350, easing: quintOut, axis: 'y' }}>
<Button variant="secondary" customClasses="!rounded-[0px]" on:click={window.open(`${downloadUrl}/package`)}>
<CubeIcon customClasses="w-4 h-4" />
<div class="text-sm font-bold">Package</div>
</Button>
<Button variant="secondary" customClasses="!rounded-[0px]" on:click={window.open(`${downloadUrl}/dll`)}>
<CogIcon customClasses="w-4 h-4" />
<div class="text-sm font-bold">.DLL</div>
</Button>
</div>
{/if}
<div class="bg-primary-800 group-hover:opacity-0 transition duration-[200ms] will-change-transform">
<ChevronDownIcon customClasses="w-3 h-3 mx-auto group-hover:rotate-180 transition duration-[200ms]"></ChevronDownIcon>
</div>
</div>
</div>
</div>
2 changes: 1 addition & 1 deletion apps/web/src/lib/components/PageTransition.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</script>

{#key pathname}
<div class="beatforge-layout__animation-root w-screen h-fit flex flex-grow relative" in:fly={{ x: -16, duration: 250, delay: 500 }} out:fly={{ x: 8, duration: 250 }}>
<div class="beatforge-layout__animation-root w-screen h-fit flex flex-grow relative" in:fly={{ x: -16, duration: 250, delay: 250 }} out:fly={{ x: 8, duration: 250 }}>
<slot />
</div>
{/key}
105 changes: 89 additions & 16 deletions apps/web/src/routes/discover/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,94 @@
<!-- todo: implement discover page -->
<script>
import GradientCtaButton from "$lib/components/landing/GradientCTAButton.svelte";
import { Text } from "ui/text";
<script lang="ts">
// import Search from '$lib/components/icons/search.svelte';
import { SearchIcon, ChevronDownIcon } from 'ui/icons';
import { Button } from 'ui/button';
import VirtualList from 'svelte-tiny-virtual-list';
import ModListItem from '$lib/components/ModListItem.svelte';
import { onMount } from 'svelte';
enum Sort {
Newest,
Oldest,
MostPopular,
LeastPopular
}
let listHeight;
let data: any[] = [];
let sort = Sort.Newest;
const search = async (q: String) => {
const res = await (await fetch(`https://search.beatforge.net/indexes/staging_mods/search`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Authorization': 'Bearer ' + '1bb9363429a821bb444c459fe529505de0c9985a6abb6802c1849797b4ae316b'
},
body: JSON.stringify({
q: q,
sort: sort
})
})).json();
data = res.hits;
};
const searchOnInput = async (e: any) => {
await search(<String>(<HTMLInputElement>e.target).value)
};
onMount(async () => {
await search('');
})
</script>

<div class="w-full h-full flex flex-col items-center px-4">
<div class="flex flex-col items-center w-full max-w-7xl text-center gap-4">
<Text variant="h2">
There aren't any mods here yet!
</Text>
<div class="w-full max-w-7xl px-6 mx-auto">
<div class="beatforge-discover-header-wrapper">
<h1 class="max-w-[700px] text-5xl font-black leading-[1.25] tracking-wide mt-4">Discover</h1>
</div>

<div class="beatforge-discover-filter-wrapper flex flex-row gap-4 mt-4">
<div class="relative flex w-full flex-row items-center overflow-hidden rounded-md bg-primary-800 text-primary-50">
<SearchIcon customClasses="w-4 h-4 absolute left-4 z-10 select-none pointer-events-none" />
<input
on:input={searchOnInput}
class="flex w-full flex-row items-center gap-2 py-3 pl-12"
placeholder="Search for mods"
/>
</div>

<Text variant="body" customClasses="text-fore-muted max-w-xl">
But there will be some very soon! Join our growing community of modders and developers on Discord, and stay up-to-date with the latest news.
</Text>
<div class="relative flex w-2/5 flex-row items-center overflow-hidden rounded-md bg-primary-800">
<ChevronDownIcon customClasses="w-4 h-4 absolute right-4 z-10 select-none pointer-events-none" />
<select class="flex w-full flex-row items-center gap-2 py-3 pl-4 pr-12">
<option value="1">Newest</option>
<option value="2">Oldest</option>
<option value="3">Most popular</option>
<option value="4">Least popular</option>
</select>
</div>
</div>

<div class="mt-4">
<GradientCtaButton />
</div>
</div>
<div
class="beatforge-discover-list-items-wrapper mt-4 overflow-hidden rounded-md"
>
{#each data as mod}
<ModListItem name={mod.name} slug={mod.slug} author={mod.author.username} description={mod.description} category={mod.category.name} downloads={mod.stats.downloads} updatedAt={mod.updatedAt} icon={mod.icon} />
{/each}
<!-- <VirtualList width="100%" itemCount={data.length} itemSize={129} height="100%">
<div slot="item" let:index let:style {style}>
<p>{data[index].name}</p>
<DiscoverListItem
name={data.mods[index].name}
slug={data.mods[index].slug}
author={data.mods[index].author.username}
description={data.mods[index].description}
category={data.mods[index].category.name}
downloads={data.mods[index].stats.downloads}
updatedAt={data.mods[index].updatedAt}
icon={data.mods[index].icon}
/>
</div>
</VirtualList> -->
</div>
</div>
24 changes: 9 additions & 15 deletions apps/web/src/routes/mod/[mod]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@
import type { PageData } from './$types';
import { copiedState } from '$lib/stores/mod';
export let data: PageData;
export let modData = data.body.data;
import Sugar from 'sugar';
import { fade } from 'svelte/transition';
import { CalendarIcon, PersonIcon, DownloadIcon, CopyIcon, GithubIcon, CheckmarkIcon, VerifiedIcon, CategoryIcon, NotVerifiedIcon } from 'ui/icons';
import Button from 'ui/button/Button.svelte';
import { CalendarIcon, PersonIcon, DownloadIcon, CopyIcon, GithubIcon, CheckmarkIcon, CategoryIcon } from 'ui/icons';
import { Button } from 'ui/button';
import ModVersionItem from '$lib/components/ModVersionItem.svelte';
const handleCopy = () => {
navigator.clipboard.writeText(modData.id)
copiedState.set(true)
Expand Down Expand Up @@ -49,7 +46,7 @@
<div class="flex -mt-4 p-4 pb-8 bg-primary-850 rounded-b-md">
<div class="sm:ml-12 overflow-hidden">
<div class="flex">
<h1 class="text-white-100 text-3xl font-bold mt-3">{modData.name}</h1>
<h1 class="text-4xl mt-2 font-black leading-[1.25] tracking-wide">{modData.name}</h1>
</div>
<div class="flex mt-5 gap-4 overflow-x-auto flex-wrap">
<a href={`/profile/${modData.author.id}`} class="whitespace-nowrap">
Expand Down Expand Up @@ -105,14 +102,11 @@
</div>
</div>
<div class="sm:p-8 bg-primary-850 rounded-md sm:pl-16 px-3 py-4 w-full">
<h2 class="text-white-100 text-lg font-bold">Versions</h2>
<h2 class="text-white-100 text-lg font-bold mb-4">Versions</h2>
{#each modData.versions as version}
<ModVersionItem versionName={version.version} downloads={version.stats.downloads} createdAt={version.createdAt} approved={version.approved} downloadUrl={version.downloadUrl} />
{/each}
</div>
</div>
</div>
</div>

<style lang="postcss">
:global(html) {
background-color: theme('colors.zinc.900');
}
</style>
</div>
1 change: 1 addition & 0 deletions apps/web/src/routes/mod/[mod]/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const load = (async ({ params, fetch }) => {
modBySlug(slug: $slug) {
id
name
slug
description
icon
cover
Expand Down
26 changes: 10 additions & 16 deletions apps/web/src/routes/profile/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@
import { Pill } from 'ui/pill';
// @ts-nocheck
import type { PageData } from './$types';
import { copiedState } from '$lib/stores/mod';
export let data: PageData;
export let userData = data.body.data;
import Sugar from 'sugar';
import { CalendarIcon, PersonIcon, DownloadIcon, CopyIcon, GithubIcon, CheckmarkIcon, VerifiedIcon, CategoryIcon, NotVerifiedIcon, AtSymbolIcon } from 'ui/icons';
import Button from 'ui/button/Button.svelte';
import { CalendarIcon, AtSymbolIcon } from 'ui/icons';
import ModListItem from '$lib/components/ModListItem.svelte';
</script>

<div class="h-full w-full">
Expand All @@ -34,7 +29,7 @@
<div class="flex -mt-4 p-4 pb-8 bg-primary-850 rounded-b-md">
<div class="sm:ml-12 overflow-hidden">
<div class="flex">
<h1 class="text-white-100 text-3xl font-bold mt-3">{userData.displayName ? userData.displayName : userData.username}</h1>
<h1 class="text-4xl mt-2 font-black leading-[1.25] tracking-wide">{userData.displayName ? userData.displayName : userData.username}</h1>
</div>
<p class="text-white-100 text-sm font-semibold py-3 opacity-70 max-w-[68ch]">
{userData.bio}
Expand All @@ -51,14 +46,13 @@
</div>

<div class="sm:p-8 bg-primary-850 rounded-md sm:pl-16 px-3 py-4 w-full">
<h2 class="text-white-100 text-lg font-bold">Mods by {userData.displayName ? userData.displayName : userData.username}</h2>
<h2 class="text-white-100 text-lg font-bold mb-4">Mods by {userData.displayName ? userData.displayName : userData.username}</h2>
<div class="overflow-hidden rounded-lg">
{#each userData.mods as mod}
<ModListItem name={mod.name} slug={mod.slug} author={mod.author.username} description={mod.description} category={mod.category.name} downloads={mod.stats.downloads} updatedAt={mod.updatedAt} icon={mod.icon} />
{/each}
</div>
</div>
</div>
</div>
</div>

<style lang="postcss">
:global(html) {
background-color: theme('colors.zinc.900');
}
</style>
</div>
29 changes: 16 additions & 13 deletions apps/web/src/routes/profile/[id]/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,22 @@ export const load = (async ({ params, fetch }) => {
description
icon
cover
category {
name
}
stats {
downloads
}
updatedAt
createdAt
versions {
version
approved
supportedGameVersions
}
category {
name
}
stats {
downloads
}
updatedAt
createdAt
versions {
version
approved
supportedGameVersions
}
author {
username
}
}
}
}
Expand Down
Loading

0 comments on commit e6240bb

Please sign in to comment.