#64 TopPackages component

- fixes grid bg layout
This commit is contained in:
neil 2022-12-06 20:10:22 +08:00
parent 44d59a3cc5
commit 4ac357a4db
8 changed files with 126 additions and 5 deletions

View file

@ -0,0 +1,60 @@
<script lang="ts">
import '$appcss';
import type { GUIPackage } from '$libs/types';
import { PackageStates } from '$libs/types';
import Preloader from '@tea/ui/Preloader/Preloader.svelte';
import PackageCard from '@tea/ui/PackageCard/PackageCard.svelte';
import { onMount } from 'svelte';
import { getTopPackages } from '$libs/api/mock';
import { installPackage } from '@api';
let packages: GUIPackage[] = [];
const getCTALabel = (state: PackageStates): string => {
return {
[PackageStates.AVAILABLE]: 'INSTALL',
[PackageStates.INSTALLED]: 'INSTALLED',
[PackageStates.INSTALLING]: 'INSTALLING',
[PackageStates.UNINSTALLED]: 'RE-INSTALL'
}[state];
};
onMount(async () => {
if (!packages.length) {
packages = await getTopPackages();
}
});
</script>
<header class="flex items-center justify-between border border-gray bg-black p-4 text-primary">
<span>TOP PACKAGES</span>
<a href="/packages" class="font-sono text-sm underline">View all packages</a>
</header>
<ul class="grid grid-cols-3 bg-black">
{#if packages.length > 0}
{#each packages as pkg}
<div class={pkg.state === PackageStates.INSTALLING ? 'animate-pulse' : ''}>
<PackageCard
{pkg}
link={`/packages/${pkg.slug}`}
ctaLabel={getCTALabel(pkg.state)}
onClickCTA={async () => {
try {
pkg.state = PackageStates.INSTALLING;
await installPackage(pkg.full_name);
pkg.state = PackageStates.INSTALLED;
} catch (error) {
console.error(error);
}
}}
/>
</div>
{/each}
{:else}
{#each Array(9) as _}
<section class="h-50 border border-gray p-4">
<Preloader />
</section>
{/each}
{/if}
</ul>

View file

@ -241,3 +241,13 @@ export async function getFeaturedCourses(): Promise<Course[]> {
return mockCourses; return mockCourses;
} }
export async function getTopPackages(): Promise<GUIPackage[]> {
await delay(500);
return packages.slice(0, 9).map((pkg) => {
return {
...pkg,
state: PackageStates.AVAILABLE
};
});
}

View file

@ -142,3 +142,8 @@ export async function getFeaturedCourses(): Promise<Course[]> {
const courses = await mock.getFeaturedCourses(); const courses = await mock.getFeaturedCourses();
return courses; return courses;
} }
export async function getTopPackages(): Promise<GUIPackage[]> {
const packages = await mock.getTopPackages();
return packages;
}

View file

@ -15,7 +15,7 @@
<nav class="border border-t-0 border-l-0 border-b-0 border-gray"> <nav class="border border-t-0 border-l-0 border-b-0 border-gray">
<NavBar /> <NavBar />
</nav> </nav>
<section class="px-16 pt-24"> <section class="px-16 pt-24 pb-24">
{#if backLink} {#if backLink}
<header class="px-16 py-2 text-3xl text-gray hover:text-primary"> <header class="px-16 py-2 text-3xl text-gray hover:text-primary">
<a href={backLink}>&#8592</a> <a href={backLink}>&#8592</a>
@ -46,10 +46,10 @@
overflow-y: scroll; overflow-y: scroll;
} }
figure { figure {
position: absolute; position: fixed;
z-index: 0; z-index: 0;
top: 220px; top: 220px;
left: 0px; left: 240px;
right: 0px; right: 0px;
bottom: 0px; bottom: 0px;
background-image: url('/images/footer-grid-element.svg'); background-image: url('/images/footer-grid-element.svg');

View file

@ -5,6 +5,7 @@
import PageHeader from '$components/PageHeader/PageHeader.svelte'; import PageHeader from '$components/PageHeader/PageHeader.svelte';
import FeaturedPackages from '$components/FeaturedPackages/FeaturedPackages.svelte'; import FeaturedPackages from '$components/FeaturedPackages/FeaturedPackages.svelte';
import GettingStarted from '$components/GettingStarted/GettingStarted.svelte'; import GettingStarted from '$components/GettingStarted/GettingStarted.svelte';
import TopPackages from '$components/TopPackages/TopPackages.svelte';
backLink.set(''); backLink.set('');
</script> </script>
@ -16,6 +17,9 @@
<section class="mt-8"> <section class="mt-8">
<GettingStarted /> <GettingStarted />
</section> </section>
<section class="mt-8">
<TopPackages />
</section>
</div> </div>
<style> <style>

View file

@ -0,0 +1,42 @@
import Gallery from './Gallery.svelte';
// More on how to set up stories at: https://storybook.js.org/docs/7.0/svelte/writing-stories/introduction
export default {
title: 'Example/Gallery',
component: Gallery,
tags: ['docsPage'],
render: (args) => ({
Component: Gallery,
props: args
}),
argTypes: {
onClick: () => console.log('does nothing')
}
};
// More on writing stories with args: https://storybook.js.org/docs/7.0/svelte/writing-stories/args
export const Example = {
args: {
items: [
{
imageUrl:
'https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/%22_Shot_From_The_Sky%22_Army_Show_1945_Oak_Ridge_%2824971013612%29.jpg/2732px-%22_Shot_From_The_Sky%22_Army_Show_1945_Oak_Ridge_%2824971013612%29.jpg',
title: 'Item 1',
subTitle: 'sub-title',
link: '#'
},
{
imageUrl: 'https://tea.xyz/Images/packages/sqlite_org.jpg',
title: 'Item 2',
subTitle: 'sub-title 2',
link: '#'
},
{
imageUrl: 'https://tea.xyz/Images/packages/gnu_org_libtool.jpg',
title: 'Item 3',
subTitle: 'sub-title 3',
link: '#'
}
]
}
};

View file

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '../app.css';
import { onDestroy, onMount } from 'svelte'; import { onDestroy, onMount } from 'svelte';
import { watchResize } from 'svelte-watch-resize'; import { watchResize } from 'svelte-watch-resize';
import Preloader from '../Preloader/Preloader.svelte'; import Preloader from '../Preloader/Preloader.svelte';

View file

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '../app.css';
import ImgLoader from '../ImgLoader/ImgLoader.svelte'; import ImgLoader from '../ImgLoader/ImgLoader.svelte';
export let width = 0; export let width = 0;