feat: add database support

This commit is contained in:
Azerothwav 2024-12-02 11:04:54 +01:00
parent 34f101308a
commit 9a952e7e84
8 changed files with 242 additions and 69 deletions

View File

@ -3,10 +3,30 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\Todo;
class TodoController extends Controller class TodoController extends Controller
{ {
public function index() { public function index() {
return view('todo'); $todos = Todo::all();
return view('todo', ['todos' => $todos]);
}
public function store(Request $request) {
$validated = $request->validate([
'task' => 'required|string|max:255'
]);
$todo = Todo::create([
'task' => $validated['task']
]);
return response()->json($todo);
}
public function destroy($id) {
$todo = Todo::findOrFail($id);
$todo->delete();
return response()->json(['message' => 'Task deleted successfully']);
} }
} }

33
app/Models/Todo.php Normal file
View File

@ -0,0 +1,33 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Todo extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'task',
'completed'
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'completed' => 'boolean'
];
}
}

Binary file not shown.

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('todos', function (Blueprint $table) {
$table->id();
$table->string('task');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('todos');
}
};

View File

@ -9,50 +9,89 @@ function ajoutTache() {
return; return;
} }
// Créer un élément <div> pour la nouvelle tâche // Envoyer la tâche au serveur
var tacheDiv = document.createElement("div"); fetch('/todo', {
tacheDiv.className = "task"; //mise en forme css method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || ''
},
body: JSON.stringify({
task: tache
})
})
.then(response => response.json())
.then(todo => {
console.log(todo)
// Créer un élément <div> pour la nouvelle tâche
var tacheDiv = document.createElement("div");
tacheDiv.className = "task";
tacheDiv.dataset.id = todo.id;
// Créer une checkbox pour marquer la tâche comme terminée // Créer une checkbox pour marquer la tâche comme terminée
var checkbox = document.createElement("input"); var checkbox = document.createElement("input");
checkbox.type = "checkbox"; checkbox.type = "checkbox";
checkbox.onchange = function () { checkbox.onchange = function () {
toggleTaskCompletion(tacheDiv, checkbox); toggleTaskCompletion(tacheDiv, checkbox);
}; };
tacheDiv.appendChild(checkbox); tacheDiv.appendChild(checkbox);
// Créer un élément <span> pour afficher la tâche // Créer un élément <span> pour afficher la tâche
var tacheSpan = document.createElement("span"); var tacheSpan = document.createElement("span");
tacheSpan.textContent = tache; //récupère texte saisi dans la zone de texte tacheInput tacheSpan.textContent = todo.task;
tacheDiv.appendChild(tacheSpan); //pour afficher à la suite tacheDiv.appendChild(tacheSpan);
// Ajouter un bouton "Supprimer" // Ajouter un bouton "Supprimer"
var suppButton = document.createElement("button"); var suppButton = document.createElement("button");
suppButton.textContent = "Supprimer"; suppButton.textContent = "Supprimer";
suppButton.className = "supp"; suppButton.className = "supp";
suppButton.onclick = suppTache; // Associer la fonction de suppression suppButton.onclick = suppTache;
tacheDiv.appendChild(suppButton); tacheDiv.appendChild(suppButton);
// Ajouter un bouton "Modifier" // Ajouter un bouton "Modifier"
var modifButton = document.createElement("button"); var modifButton = document.createElement("button");
modifButton.textContent = "Modifier"; modifButton.textContent = "Modifier";
modifButton.className = "modif"; modifButton.className = "modif";
modifButton.onclick = function () { modifButton.onclick = function () {
modifTache(tacheDiv, tacheSpan); modifTache(tacheDiv, tacheSpan);
}; };
tacheDiv.appendChild(modifButton); tacheDiv.appendChild(modifButton);
// Ajouter la tâche au conteneur // Ajouter la tâche au conteneur
document.getElementById("listeTache").appendChild(tacheDiv); document.getElementById("listeTache").appendChild(tacheDiv);
// Réinitialiser le champ de saisie // Réinitialiser le champ de saisie
document.getElementById("tacheInput").value = ""; document.getElementById("tacheInput").value = "";
})
.catch(error => {
console.error('Erreur:', error);
alert("Une erreur est survenue lors de l'ajout de la tâche.");
});
} }
// Fonction pour supprimer une tâche // Fonction pour supprimer une tâche
function suppTache() { function suppTache() {
var tacheDiv = this.parentElement; var tacheDiv = this.parentElement;
tacheDiv.remove(); var taskId = tacheDiv.dataset.id;
fetch('/todo/' + taskId, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || ''
}
})
.then(response => {
if (response.ok) {
tacheDiv.remove();
} else {
throw new Error('Erreur lors de la suppression');
}
})
.catch(error => {
console.error('Erreur:', error);
alert("Une erreur est survenue lors de la suppression de la tâche.");
});
} }
// Fonction pour marquer une tâche comme terminée (avec la checkbox) // Fonction pour marquer une tâche comme terminée (avec la checkbox)

View File

@ -9,50 +9,91 @@ function ajoutTache() {
return; return;
} }
// Créer un élément <div> pour la nouvelle tâche console.log('Here')
var tacheDiv = document.createElement("div");
tacheDiv.className = "task"; //mise en forme css
// Créer une checkbox pour marquer la tâche comme terminée // Envoyer la tâche au serveur
var checkbox = document.createElement("input"); fetch('/todo', {
checkbox.type = "checkbox"; method: 'POST',
checkbox.onchange = function () { headers: {
toggleTaskCompletion(tacheDiv, checkbox); 'Content-Type': 'application/json',
}; 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
tacheDiv.appendChild(checkbox); },
body: JSON.stringify({
task: tache
})
})
.then(response => response.json())
.then(todo => {
console.log(todo)
// Créer un élément <div> pour la nouvelle tâche
var tacheDiv = document.createElement("div");
tacheDiv.className = "task";
tacheDiv.dataset.id = todo.id;
// Créer un élément <span> pour afficher la tâche // Créer une checkbox pour marquer la tâche comme terminée
var tacheSpan = document.createElement("span"); var checkbox = document.createElement("input");
tacheSpan.textContent = tache; //récupère texte saisi dans la zone de texte tacheInput checkbox.type = "checkbox";
tacheDiv.appendChild(tacheSpan); //pour afficher à la suite checkbox.onchange = function () {
toggleTaskCompletion(tacheDiv, checkbox);
};
tacheDiv.appendChild(checkbox);
// Ajouter un bouton "Supprimer" // Créer un élément <span> pour afficher la tâche
var suppButton = document.createElement("button"); var tacheSpan = document.createElement("span");
suppButton.textContent = "Supprimer"; tacheSpan.textContent = todo.task;
suppButton.className = "supp"; tacheDiv.appendChild(tacheSpan);
suppButton.onclick = suppTache; // Associer la fonction de suppression
tacheDiv.appendChild(suppButton);
// Ajouter un bouton "Modifier" // Ajouter un bouton "Supprimer"
var modifButton = document.createElement("button"); var suppButton = document.createElement("button");
modifButton.textContent = "Modifier"; suppButton.textContent = "Supprimer";
modifButton.className = "modif"; suppButton.className = "supp";
modifButton.onclick = function () { suppButton.onclick = suppTache;
modifTache(tacheDiv, tacheSpan); tacheDiv.appendChild(suppButton);
};
tacheDiv.appendChild(modifButton);
// Ajouter la tâche au conteneur // Ajouter un bouton "Modifier"
document.getElementById("listeTache").appendChild(tacheDiv); var modifButton = document.createElement("button");
modifButton.textContent = "Modifier";
modifButton.className = "modif";
modifButton.onclick = function () {
modifTache(tacheDiv, tacheSpan);
};
tacheDiv.appendChild(modifButton);
// Réinitialiser le champ de saisie // Ajouter la tâche au conteneur
document.getElementById("tacheInput").value = ""; document.getElementById("listeTache").appendChild(tacheDiv);
// Réinitialiser le champ de saisie
document.getElementById("tacheInput").value = "";
})
.catch(error => {
console.error('Erreur:', error);
alert("Une erreur est survenue lors de l'ajout de la tâche.");
});
} }
// Fonction pour supprimer une tâche // Fonction pour supprimer une tâche
function suppTache() { function suppTache() {
var tacheDiv = this.parentElement; var tacheDiv = this.parentElement;
tacheDiv.remove(); var taskId = tacheDiv.dataset.id;
fetch('/todo/' + taskId, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || ''
}
})
.then(response => {
if (response.ok) {
tacheDiv.remove();
} else {
throw new Error('Erreur lors de la suppression');
}
})
.catch(error => {
console.error('Erreur:', error);
alert("Une erreur est survenue lors de la suppression de la tâche.");
});
} }
// Fonction pour marquer une tâche comme terminée (avec la checkbox) // Fonction pour marquer une tâche comme terminée (avec la checkbox)

View File

@ -3,6 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Document</title> <title>Document</title>
@vite('resources/css/app.css') @vite('resources/css/app.css')
<link href="{{ asset('css/todo.css') }}" rel="stylesheet"> <link href="{{ asset('css/todo.css') }}" rel="stylesheet">
@ -14,7 +15,16 @@
<input class="border-2" type="text" id="tacheInput" placeholder="Ajouter une tâche..."> <input class="border-2" type="text" id="tacheInput" placeholder="Ajouter une tâche...">
<button onclick="ajoutTache()">Ajouter</button> <button onclick="ajoutTache()">Ajouter</button>
</div> </div>
<div id="listeTache" class="w-[30dvw] h-[70dvh] overflow-y-scroll"></div> <div id="listeTache" class="w-[30dvw] h-[70dvh] overflow-y-scroll">
@foreach($todos as $todo)
<div class="task" data-id="{{ $todo->id }}">
<input type="checkbox" onchange="toggleTaskCompletion(this.parentElement, this)">
<span>{{ $todo->task }}</span>
<button class="supp" onclick="suppTache.call(this)">Supprimer</button>
<button class="modif" onclick="modifTache(this.parentElement, this.previousElementSibling.previousElementSibling)">Modifier</button>
</div>
@endforeach
</div>
</div> </div>
<script src="{{ asset('js/todo.js')}}"></script> <script src="{{ asset('js/todo.js')}}"></script>
</body> </body>

View File

@ -11,3 +11,5 @@ Route::get('/', [HomeController::class, 'index'])->name('route0');
Route::get('/about', [AboutController::class, 'index'])->name('route1'); Route::get('/about', [AboutController::class, 'index'])->name('route1');
Route::get('/todo', [TodoController::class, 'index'])->name('route2'); Route::get('/todo', [TodoController::class, 'index'])->name('route2');
Route::post('/todo', [TodoController::class, 'store'])->name('route3');
Route::delete('/todo/{id}', [TodoController::class, 'destroy'])->name('route4');