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

168 lines
4.9 KiB
Svelte

<script lang="ts">
import { form, field } from "svelte-forms";
import { required, max, min } from "svelte-forms/validators";
import FileInput from "../forms/FileInput.svelte";
import InputWithLabel from "../forms/InputWithLabel.svelte";
import { getContext } from "svelte";
import { createExo, editExo } from "../../requests/exo.request";
import type { Exercice } from "../../types/exo.type";
import { checkFile, errorMsg } from "../../utils/forms";
import { compareObject } from "../../utils/utils";
import { goto } from "$app/navigation";
import ModalCard from "./ModalCard.svelte";
export let editing = true;
export let updateExo: Function = (e: Exercice) => {
};
export let exo: Exercice | null = null;
export let cancel: Function;
const { alert } = getContext<{ alert: Function }>("alert");
const { show } = getContext<{ show: Function }>("modal");
// "Legally" initiate empty FileList for model field (simple list raises warning)
/* let list = new DataTransfer();
let file = new File(['content'], !editing || exo == null ? 'filename.py' : exo.exo_source);
list.items.add(file);
!editing && list.items.remove(0); */
// Initiate fields and form
const name = field("name", !!exo ? exo.name : "", [required(), max(50), min(5)], {
checkOnInit: true
});
const consigne = field("consigne", !!exo && exo.consigne != null ? exo.consigne : "", [max(200)], { checkOnInit: true });
const prv = field("private", !!exo ? exo.private : false);
const model = field("model", [], [checkFile(), required()], {
checkOnInit: !editing
});
const myForm = form(name, consigne, prv, model);
const exerciceStore = getContext<{ exerciceStore: any }>("exerciceStore");
const tagsStore = getContext<{ tagsStore: any }>("tagsStore");
const { navigate } = getContext<{ navigate: Function }>("navigation");
const { success, error } = getContext<{ success: Function, error: Function }>("notif");
let loading = false
</script>
<form
action=""
on:submit|preventDefault={() => {
loading = true
if (editing && exo != null) {
editExo(exo.id_code, {
name: $name.value,
consigne: $consigne.value,
private: $prv.value,
...($model.dirty == true && { file: $model.value[0] })
}).then((r) => {
loading=false
success('Exercice modifié !', `Exercice ${r.data.name} modifié avec succès !`)
exo=r.data
updateExo(r.data);
cancel()
}).catch((e) => {
loading=false
console.log(e)
error('Erreur', 'Une erreur est survenue lors de la modification de l\'exercice')
});
} else {
createExo({
name: $name.value,
consigne: $consigne.value,
private: $prv.value,
file: $model.value[0]
}).then((r) => {
loading=false
updateExo(r.data);
success('Exercice créé !', `Exercice ${r.data.name} créé avec succès !`)
goto(`/exercices/${r.data.id_code}`)
//cancel()
show(
ModalCard,
{
exo: r.data,
exos: exerciceStore,
tags: tagsStore
},
() => {
navigate(-1)
}, true
);
}).catch((e) => {
loading=false
error('Erreur', 'Une erreur est survenue lors de la création de l\'exercice')
});
}
}}
>
<InputWithLabel
type="text"
bind:value={$name.value}
maxlength="50"
minlength="5"
required
label="Nom"
errors={errorMsg($myForm, 'name')}
name="name"
/>
<InputWithLabel
type="text"
bind:value={$consigne.value}
maxlength="200"
label="Consigne"
errors={errorMsg($myForm, 'consigne')}
name="consigne"
/>
<div>
<input type="checkbox" bind:checked={$prv.value} name="private" id="private" />
<label for="private">Privé</label>
</div>
<FileInput bind:value={$model.value} accept=".py" id_code={exo?.id_code}
defaultValue={editing &&exo!= null? exo.exo_source: null} />
<div class="wp-100">
<button class="primary-btn" disabled={!$myForm.valid}>
{#if !loading}
{editing ? "Modifier" : "Créer"}
{:else}
<span class="spinner"></span>
{/if}
</button>
<button
class="danger-btn"
on:click|preventDefault={() => {
if (exo != null && ($model.dirty || !compareObject({...exo, consigne: exo.consigne == null ? "": exo.consigne}, myForm.summary()))) {
alert({
title: 'Voulez-vous annuler ?',
description:
'Vous avez des modifications non enregistrées, êtes vous sur de vouloir annuler ?',
validate: cancel
});
} else {
cancel();
}
}}>Annuler
</button
>
</div>
</form>
<style>
form {
width: 100%;
display: flex;
flex-direction: column;
gap: 10px;
align-items: flex-start;
}
.spinner{
width: 15px;
height: 15px;
border-width: 2px!important;
}
</style>