generateur_v3/frontend/src/components/exos/Feed.svelte

232 lines
5.5 KiB
Svelte

<script lang="ts">
import { getContext } from 'svelte/internal';
import Card from './Card.svelte';
import Head from './Head.svelte';
import ModalCard from './ModalCard.svelte';
import { getExo, getExos, getTags } from '../../requests/exo.request';
import { page } from '$app/stores';
import { onMount } from 'svelte';
import Pagination from './Pagination.svelte';
import { goto } from '$app/navigation';
import {type Writable, writable} from 'svelte/store';
import { setContext } from 'svelte';
import type { Page, Tag } from '../../types/exo.type';
import type { Store } from '../../types/api.type';
import { page as p } from '$app/stores';
const { show } = getContext<{ show: Function }>('modal');
const { navigate, insertUrl } = getContext<{ navigate: Function; insertUrl: Function }>(
'navigation'
);
const { isAuth } = getContext<{ isAuth: Writable<boolean> }>('auth');
let filter = $isAuth ? 'user' : 'public';
const exerciceStore = writable<Store<Page | undefined>>({
isLoading: false,
isFetching: false,
isSuccess: false,
data: undefined
});
const tagStore = writable<Store<Tag[] | undefined>>({
isLoading: false,
isFetching: false,
isSuccess: false,
data: []
});
setContext('exos', exerciceStore);
setContext('tags', tagStore);
onMount(() => {
let page = $page.url.searchParams.get('page')
if(page == null){
page = '1'
}
if ($page.params.slug != undefined && !['user', 'public'].includes($page.params.slug)) {
getExo($page.params.slug).then((r) => {
insertUrl('exercices/' + filter);
show(ModalCard, { exo: r, exos: exerciceStore, tags: tagStore }, () => navigate(-1));
});
} else if ($page.params.slug == undefined || $page.params.slug == "user") {
filter = $isAuth ? 'user' : 'public';
goto(`/exercices/${filter}?${new URLSearchParams({page}).toString()}`)
} else if($page.params.slug == "public"){
filter = 'public';
goto(`/exercices/${filter}?${new URLSearchParams({page}).toString()}`)
}
});
$: filter = ['user', 'public'].includes($page.params.slug) ? $page.params.slug : filter;
/*$: if(['user', 'public'].includes($page.params.slug) && !$isAuth){
filter = "public"
//goto('/exercices/' + filter)
}*/
const size = 15;
$: activePage = parseInt($page.url.searchParams.get('page')!) || 1;
let search = '';
let selected: Tag[] = [];
$: {
if(!$isAuth){
filter = 'public'
}
exerciceStore.update((s) => {
return { ...s, isFetching: true };
});
getExos(filter as 'public' | 'user', {
page: activePage == 0 ? 1: activePage,
search,
size,
tags: [...selected.map((t) => t.id_code)]
})
.then((r) => {
console.log('R', r);
if (activePage > r.totalPage && r.total != 0 && r.totalPage != 0) {
activePage = r.totalPage;
//$p.url.searchParams.set('page', String(activePage));
goto(`?${new URLSearchParams({page: activePage}).toString()}`);
return;
}
exerciceStore.update((e) => {
return { ...e, isSuccess: true, isFetching: false, data: r };
});
})
.catch(console.log);
}
$: {
if($isAuth) {
tagStore.update((s) => {
return {...s, isFetching: true};
});
getTags().then((r) => {
tagStore.update((e) => {
return {...e, isSuccess: true, isFetching: false, data: r};
});
});
}
}
</script>
{#if $tagStore.data != undefined}
<Head location={filter} bind:search bind:selected />
{/if}
{#if $tagStore.isFetching == true}
Fetching
{/if}
<div class="feed">
<div class="title">
{#if filter == 'user'}
<h1>
Vos <span>exercices</span>
</h1>
<p>
Vous retrouverez ici tous les exercices que vous avez créé ou copié depuis les exercices
publics
</p>
{:else}
<h1>
Tous les <span>exercices</span>
</h1>
<p>Vous retrouverez ici tous les exercices créés par les autres utilisateurs</p>
{/if}
</div>
{#if $exerciceStore.data != undefined}
{#each $exerciceStore.data.items.filter((e) => e != null && selected.every((t) => e.tags
.map((s) => s.id_code)
.includes(t.id_code))) as e}
<Card bind:exo={e} />
{/each}
{:else}
{#each Array(10) as i}
<div class="skeleton"><span /></div>
{/each}
{/if}
</div>
{#if $exerciceStore.data != undefined}
<Pagination bind:page={activePage} total={$exerciceStore.data.totalPage} />
{/if}
<style lang="scss">
@import '../../variables';
.skeleton {
width: 330px;
height: 250px;
opacity: .8;
span {
display: block;
height: 100%;
width: 100%;
background-color: $skeleton;
display: block;
position: relative;
border-radius: 4px;
background-color: $skeleton;
overflow: hidden;
&::after {
top: 0;
left: 0;
right: 0;
bottom: 0;
content: '';
position: absolute;
animation: waves 1.6s linear 0.5s infinite;
transform: translateX(-100%);
background: linear-gradient(
90deg,
transparent,
(lighten($color: $skeleton, $amount: 3), rgba(0, 0, 0, 0.04)),
transparent
);
}
}
}
@keyframes waves {
0% {
transform: translateX(-100%);
}
60% {
transform: translateX(100%);
}
100% {
transform: translateX(100%);
}
}
.feed {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-auto-flow: dense;
grid-gap: 32px;
margin: 0 auto;
margin-top: 20px;
}
.title {
grid-column: 1/3;
display: flex;
text-align: left;
justify-content: center;
flex-direction: column;
h1 {
font-size: 3.5em;
font-weight: bolder;
margin: 0;
}
p {
font-size: 1.1em;
}
span {
color: $primary;
}
}
</style>