server/frontend/fic/src/lib/components/ExerciceHints.svelte

147 lines
4.7 KiB
Svelte

<script>
import {
Card,
CardBody,
CardHeader,
CardText,
Icon,
ListGroup,
ListGroupItem,
Spinner,
} from '@sveltestrap/sveltestrap';
import { my } from '$lib/stores/my.js';
import { settings } from '$lib/stores/settings.js';
export let hints = [];
export let exercice = {};
export let locked_theme = false;
let hints_submitted = {};
function waitDiff(i, hint) {
my.refresh((my) => {
let openedHint = false;
if (my && my.exercices[exercice.id].hints) {
my.exercices[exercice.id].hints.forEach((h) => {
if (h.id == hint.id && (h.content || h.file)) {
openedHint = true;
}
})
}
if (openedHint) {
hints_submitted[hint.id] = false;
hinterror = "";
} else if (i > 0) {
setTimeout(waitDiff, 650, i-1, hint);
}
})
}
function showHint(hint) {
hint.hidden = false;
hints = hints; // Force Svelte update
}
async function openHint(hint) {
if (!confirm("Êtes-vous sûr de vouloir utiliser " + (hint.cost * $settings.hintCurrentCoefficient) + " points pour dévoiler cet indice ?")) {
return;
}
hints_submitted[hint.id] = true;
hinterror = "";
const response = await fetch(
"openhint/" + exercice.id,
{
method: "POST",
headers: {'Accept': 'application/json'},
body: JSON.stringify({ id: hint.id }),
}
)
if (response.status < 300) {
waitDiff(15, hint);
} else {
hints_submitted[hint.id] = false;
let data = "";
try {
data = await response.json();
} catch(e) {
data = null;
}
if (data && data.errmsg)
hinterror = data.errmsg;
}
}
let hinterror = "";
</script>
{#if hints.length}
<Card class="mb-2">
<CardHeader class="bg-info text-light">
<Icon name="lightbulb-fill" />
Indices
</CardHeader>
{#if hinterror}
<CardBody>
<CardText class="text-danger">
{hinterror}
</CardText>
</CardBody>
{/if}
<ListGroup>
{#each hints as hint (hint.id)}
<ListGroupItem tag="a" href="{hint.file}" target="_self" class="d-flex align-items-center">
{#if hint.file}
<h1 class="me-3">
<Icon name="arrow-down-circle" />
</h1>
{/if}
<div class="flex-fill" style="min-width:0">
<h4 class="fw-bold">{hint.title}</h4>
{#if hint.file}
<p style="overflow-x: auto">
Cliquez ici pour télécharger l'indice.<br>
b2sum&nbsp;:
<samp class="cksum" title="Somme de contrôle BLAKE2b : {hint.content}">{hint.content}</samp>
</p>
{:else if hint.content && !hint.hidden}
<p>{@html hint.content}</p>
{:else}
<p>
Débloquer cet indice vous fera perdre {hint.cost * $settings.hintCurrentCoefficient} {hint.cost * $settings.hintCurrentCoefficient == 1 ? "point" : "points"}.
</p>
{/if}
</div>
{#if !(hint.content || hint.file) || (!hint.file && hint.hidden)}
<div>
{#if !(hint.content || hint.file)}
<button type="button" on:click={openHint(hint)} class="btn btn-info" class:disabled={hints_submitted[hint.id]} disabled={$settings.disablesubmitbutton || locked_theme}>
{#if hints_submitted[hint.id]}
<Spinner size="sm" class="me-2" />
{:else}
<Icon name="lock" aria-hidden="true" />
{/if}
Débloquer
</button>
{/if}
{#if !hint.file && hint.hidden}
<button type="button" on:click={() => showHint(hint)} class="btn btn-info">
<Icon name="lock" aria-hidden="true" />
Afficher
</button>
{/if}
</div>
{/if}
</ListGroupItem>
{/each}
</ListGroup>
</Card>
{/if}