mirror of
https://github.com/ivabus/gui
synced 2025-06-07 15:50:27 +03:00
#36 search for package
This commit is contained in:
parent
9e43eba092
commit
363e8150bc
3 changed files with 68 additions and 14 deletions
|
@ -1,7 +1,28 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { searchStore } from '$libs/stores';
|
import { searchStore } from '$libs/stores';
|
||||||
|
import type { GUIPackage } from '$libs/types';
|
||||||
|
import Preloader from '@tea/ui/Preloader/Preloader.svelte';
|
||||||
|
import PackageCard from '@tea/ui/PackageCard/PackageCard.svelte';
|
||||||
|
import { PackageStates } from '$libs/types';
|
||||||
|
|
||||||
|
import { installPackage } from '@api';
|
||||||
let term: string;
|
let term: string;
|
||||||
searchStore.subscribe((v) => (term = v));
|
let packagesFound: GUIPackage[] = [];
|
||||||
|
searchStore.subscribe((v) => {
|
||||||
|
term = v;
|
||||||
|
});
|
||||||
|
searchStore.packagesSearch.subscribe((pkgs) => {
|
||||||
|
packagesFound = pkgs;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getCTALabel = (state: PackageStates): string => {
|
||||||
|
return {
|
||||||
|
[PackageStates.AVAILABLE]: 'INSTALL',
|
||||||
|
[PackageStates.INSTALLED]: 'INSTALLED',
|
||||||
|
[PackageStates.INSTALLING]: 'INSTALLING',
|
||||||
|
[PackageStates.UNINSTALLED]: 'RE-INSTALL'
|
||||||
|
}[state];
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class={term ? 'show' : ''}>
|
<section class={term ? 'show' : ''}>
|
||||||
|
@ -10,10 +31,41 @@
|
||||||
Showing search results for `{term}`
|
Showing search results for `{term}`
|
||||||
</header>
|
</header>
|
||||||
<menu class="flex h-8 w-full gap-4 bg-accent px-4 text-xs">
|
<menu class="flex h-8 w-full gap-4 bg-accent px-4 text-xs">
|
||||||
<button>packages (33)</button>
|
<button>packages ({packagesFound.length})</button>
|
||||||
<button>articles (33)</button>
|
<button>articles (33)</button>
|
||||||
<button>workshops (33)</button>
|
<button>workshops (33)</button>
|
||||||
</menu>
|
</menu>
|
||||||
|
<header class="p-4 text-lg text-primary">
|
||||||
|
Top Package Results ({packagesFound.length})
|
||||||
|
</header>
|
||||||
|
<ul class="grid grid-cols-3">
|
||||||
|
{#if packagesFound.length > 0}
|
||||||
|
{#each packagesFound 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(12) as _}
|
||||||
|
<section class="h-50 border border-gray p-4">
|
||||||
|
<Preloader />
|
||||||
|
</section>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -39,6 +91,7 @@
|
||||||
section > div {
|
section > div {
|
||||||
height: 0%;
|
height: 0%;
|
||||||
transition: height 0.6s ease-in-out;
|
transition: height 0.6s ease-in-out;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
section.show > div {
|
section.show > div {
|
||||||
|
|
|
@ -26,7 +26,8 @@ async function get<T>(path: string, query?: { [key: string]: string }) {
|
||||||
const uri = join(base, path);
|
const uri = join(base, path);
|
||||||
const { data } = await client.get<T>(uri.toString(), {
|
const { data } = await client.get<T>(uri.toString(), {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: 'public' // TODO: figure out why req w/o Authorization does not work
|
Authorization: 'public', // TODO: figure out why req w/o Authorization does not work
|
||||||
|
'cache-control': 'no-cache'
|
||||||
},
|
},
|
||||||
query: query || {}
|
query: query || {}
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,16 +9,8 @@ import { getPackages, getFeaturedPackages, getPackageReviews } from '@api';
|
||||||
|
|
||||||
export const backLink = writable<string>('/');
|
export const backLink = writable<string>('/');
|
||||||
|
|
||||||
export const packages = writable<GUIPackage[]>([]);
|
|
||||||
|
|
||||||
export const featuredPackages = writable<Package[]>([]);
|
export const featuredPackages = writable<Package[]>([]);
|
||||||
|
|
||||||
export const initializePackages = async () => {
|
|
||||||
console.log('initialize packages');
|
|
||||||
const newPackages = await getPackages();
|
|
||||||
packages.set(newPackages);
|
|
||||||
};
|
|
||||||
|
|
||||||
function initPackagesStore() {
|
function initPackagesStore() {
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
const { subscribe, set } = writable<GUIPackage[]>([]);
|
const { subscribe, set } = writable<GUIPackage[]>([]);
|
||||||
|
@ -46,7 +38,6 @@ function initPackagesStore() {
|
||||||
|
|
||||||
const res = packagesIndex.search(term, { limit });
|
const res = packagesIndex.search(term, { limit });
|
||||||
const matchingPackages: GUIPackage[] = res.map((v) => v.item);
|
const matchingPackages: GUIPackage[] = res.map((v) => v.item);
|
||||||
|
|
||||||
return matchingPackages;
|
return matchingPackages;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -100,21 +91,30 @@ export const packagesReviewStore = initPackagesReviewStore();
|
||||||
|
|
||||||
function initSearchStore() {
|
function initSearchStore() {
|
||||||
const { subscribe, set } = writable<string>('');
|
const { subscribe, set } = writable<string>('');
|
||||||
|
const packagesSearch = writable<GUIPackage[]>([]);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// add fuse.js index here: packages, articles/posts, etc
|
// add fuse.js index here: packages, articles/posts, etc
|
||||||
// define fuse.js shape { tags:[], desc:string, title: string, thumb_image_url: string }
|
// define fuse.js shape { tags:[], desc:string, title: string, thumb_image_url: string }
|
||||||
// should use algolia if user is somehow online
|
// should use algolia if user is somehow online
|
||||||
|
|
||||||
// use packagesStore here
|
const packagesFound: GUIPackage[] = [];
|
||||||
|
|
||||||
let term = '';
|
let term = '';
|
||||||
|
|
||||||
subscribe((v) => (term = v));
|
subscribe((v) => (term = v));
|
||||||
|
packagesSearch.subscribe((v) => packagesFound.push(...v));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
term,
|
term,
|
||||||
|
packagesSearch,
|
||||||
|
packagesFound,
|
||||||
subscribe,
|
subscribe,
|
||||||
search: (term: string) => set(term)
|
search: async (term: string) => {
|
||||||
|
const resultPkgs = await packagesStore.search(term, 5);
|
||||||
|
packagesSearch.set(resultPkgs);
|
||||||
|
set(term);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue