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

194 lines
4.1 KiB
Svelte

<script lang="ts">
import type { Exercice } from '../../types/exo.type';
import { getContext } from 'svelte';
import ModalCard from './ModalCard.svelte';
import { goto } from '$app/navigation';
import { cloneExo } from '../../requests/exo.request';
import TagContainer from './TagContainer.svelte';
import PrivacyIndicator from './PrivacyIndicator.svelte';
import MdContentCopy from 'svelte-icons/md/MdContentCopy.svelte';
import type { Writable } from 'svelte/store';
export let exo: Exercice;
const { show } = getContext<{ show: Function }>('modal');
const { navigate } = getContext<{ navigate: Function }>('navigation');
const { isAuth } = getContext<{ isAuth: Writable<boolean> }>('auth');
const exerciceStore = getContext('exos');
const tagsStore = getContext('tags');
let opened = false;
const handleClick = () => {
opened = true;
navigate(`/exercices/${exo.id_code}`);
show(
ModalCard,
{
exo,
exos: exerciceStore,
tags: tagsStore
},
() => {
navigate(-1);
opened = false;
}
);
};
</script>
<div class="card" on:click={handleClick} on:dblclick={() => {}} on:keypress={() => {}}>
<h1>{exo.name}</h1>
<div class="examples">
{#if exo.examples != null}
<h2>Exemples</h2>
{#if !!exo.consigne}<p data-testid="consigne">{exo.consigne}</p>{/if}
{#each exo.examples.data.slice(0, 3) as ex}
<p>{ex.calcul}</p>
{/each}
{:else}
<p>Aucun exemple disponible</p>
{/if}
</div>
{#if !!$isAuth && exo.is_author && exo.original == null }
<div class="status">
<PrivacyIndicator color={exo.private == true ? 'red' : 'green'}>
{exo.private == true ? 'Privé' : 'Public'}</PrivacyIndicator
>
</div>
{:else if !exo.is_author}
<div class="status">
<PrivacyIndicator color={'blue'}>
Par <strong>{exo.author.username}</strong>
</PrivacyIndicator>
{#if !!$isAuth}
<div
data-testid="copy"
class="icon"
on:keydown={() => {}}
on:click|stopPropagation={() => {
cloneExo(exo.id_code).then((r) => {
goto('/exercices/' + r.id_code);
show(ModalCard, { exo: r }, () => {
goto('/exercices/user');
});
});
}}
>
<MdContentCopy />
</div>
{/if}
</div>
{:else if exo.is_author && exo.original != null}
<div class="status">
<PrivacyIndicator color="blue">Par <strong>{exo.original?.author}</strong></PrivacyIndicator>
</div>
{/if}
<div class="card-hover" />
{#if !!$isAuth}
<TagContainer bind:exo />
{/if}
<!-- TagContainer Must be directly after card-hover for the hover effect -->
</div>
<style lang="scss">
@import '../../variables';
* {
transition: 0.45s;
}
.icon {
width: 18px;
height: 18px;
transition: 0.3s;
cursor: pointer;
opacity: 0.7;
transform: scale(0.9);
&:hover {
transform: scale(1);
opacity: 1;
}
}
.status {
position: absolute;
top: 0;
right: 0;
margin: 10px;
z-index: 3;
display: flex;
align-items: center;
gap: 10px;
}
.examples {
color: gray;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 20px;
p {
margin: 10px;
margin-left: 18px;
font-size: 0.95em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
h2 {
font-size: 0.95em;
margin: 10px;
margin-left: 0;
}
}
.card-hover {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: 1;
border: 1px solid $border;
+ :global(div) {
transition: 0.45s;
}
&:hover {
border: 1px solid $primary;
+ :global(div) {
border: 1px solid $primary;
border-top: none;
}
}
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.75);
}
h1 {
font-size: 1.3em;
margin: 0;
position: relative;
z-index: 2;
max-width: 88%;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-wrap: break-word;
&:hover {
color: $primary;
}
}
.card {
border: 1px solid black;
padding: 20px;
cursor: pointer;
position: relative;
background-color: $background;
min-height: 250px;
max-height: 300px;
&:hover {
transform: translateX(10px) translateY(-10px);
}
}
</style>