9-Gestor de Tareas con Blade y Arreglo en Laravel
Gestor de Tareas con Blade y Arreglo en Laravel
Aquí te mostraré una versión simplificada donde las tareas se manejan con un arreglo en lugar de una base de datos. Esto es útil para aprendizaje o prototipado rápido.
1. Modificamos el controlador (app/Http/Controllers/TaskController.php)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
class TaskController extends Controller
{
public function index()
{
// Obtener tareas de la sesión o inicializar arreglo vacío
$tasks = Session::get('tasks', []);
return view('tasks.index', compact('tasks'));
}
public function create()
{
return view('tasks.create');
}
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|max:255',
'description' => 'nullable',
]);
// Obtener tareas existentes
$tasks = Session::get('tasks', []);
// Agregar nueva tarea
$newTask = [
'id' => uniqid(),
'title' => $validated['title'],
'description' => $validated['description'] ?? '',
'completed' => false,
'created_at' => now()->toDateTimeString(),
];
array_push($tasks, $newTask);
// Guardar en sesión
Session::put('tasks', $tasks);
return redirect()->route('tasks.index')
->with('success', 'Tarea creada correctamente');
}
public function show($id)
{
$tasks = Session::get('tasks', []);
// Buscar tarea por ID
$task = collect($tasks)->firstWhere('id', $id);
if (!$task) {
abort(404);
}
return view('tasks.show', compact('task'));
}
public function edit($id)
{
$tasks = Session::get('tasks', []);
$task = collect($tasks)->firstWhere('id', $id);
if (!$task) {
abort(404);
}
return view('tasks.edit', compact('task'));
}
public function update(Request $request, $id)
{
$validated = $request->validate([
'title' => 'required|max:255',
'description' => 'nullable',
'completed' => 'boolean',
]);
$tasks = Session::get('tasks', []);
// Actualizar tarea
$tasks = array_map(function ($task) use ($id, $validated) {
if ($task['id'] === $id) {
return [
'id' => $id,
'title' => $validated['title'],
'description' => $validated['description'] ?? '',
'completed' => $validated['completed'] ?? false,
'created_at' => $task['created_at'],
];
}
return $task;
}, $tasks);
Session::put('tasks', $tasks);
return redirect()->route('tasks.show', $id)
->with('success', 'Tarea actualizada correctamente');
}
public function destroy($id)
{
$tasks = Session::get('tasks', []);
// Filtrar para eliminar la tarea
$tasks = array_filter($tasks, function ($task) use ($id) {
return $task['id'] !== $id;
});
Session::put('tasks', $tasks);
return redirect()->route('tasks.index')
->with('success', 'Tarea eliminada correctamente');
}
}Explicación de array_filter.
2. Modificamos la vista de índice (resources/views/tasks/index.blade.php)
@extends('layouts.app')
@section('title', 'Lista de Tareas')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>Lista de Tareas</h1>
<a href="{{ route('tasks.create') }}" class="btn btn-primary">Nueva Tarea</a>
</div>
@if(empty($tasks))
<div class="alert alert-info">No hay tareas registradas.</div>
@else
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Título</th>
<th>Estado</th>
<th>Fecha</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
@foreach($tasks as $task)
<tr>
<td>{{ substr($task['id'], 0, 8) }}</td>
<td>{{ $task['title'] }}</td>
<td>
<span class="badge {{ $task['completed'] ? 'bg-success' : 'bg-warning' }}">
{{ $task['completed'] ? 'Completada' : 'Pendiente' }}
</span>
</td>
<td>{{ \Carbon\Carbon::parse($task['created_at'])->format('d/m/Y') }}</td>
<td>
<a href="{{ route('tasks.show', $task['id']) }}" class="btn btn-sm btn-info">Ver</a>
<a href="{{ route('tasks.edit', $task['id']) }}" class="btn btn-sm btn-warning">Editar</a>
<form action="{{ route('tasks.destroy', $task['id']) }}" method="POST" style="display: inline;">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger">Eliminar</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
@endsection3. Modificamos la vista de creación (resources/views/tasks/create.blade.php)
@extends('layouts.app')
@section('title', 'Crear Nueva Tarea')
@section('content')
<div class="card">
<div class="card-header">
<h2>Nueva Tarea</h2>
</div>
<div class="card-body">
<form action="{{ route('tasks.store') }}" method="POST">
@csrf
<div class="mb-3">
<label for="title" class="form-label">Título*</label>
<input type="text" class="form-control @error('title') is-invalid @enderror"
id="title" name="title" value="{{ old('title') }}" required>
@error('title')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="description" class="form-label">Descripción</label>
<textarea class="form-control @error('description') is-invalid @enderror"
id="description" name="description" rows="3">{{ old('description') }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-primary">Guardar</button>
<a href="{{ route('tasks.index') }}" class="btn btn-secondary">Cancelar</a>
</form>
</div>
</div>
@endsection4. Modificamos la vista de edición (resources/views/tasks/edit.blade.php)
@extends('layouts.app')
@section('title', 'Editar Tarea')
@section('content')
<div class="card">
<div class="card-header">
<h2>Editar Tarea: {{ $task['title'] }}</h2>
</div>
<div class="card-body">
<form action="{{ route('tasks.update', $task['id']) }}" method="POST">
@csrf
@method('PUT')
<div class="mb-3">
<label for="title" class="form-label">Título*</label>
<input type="text" class="form-control @error('title') is-invalid @enderror"
id="title" name="title" value="{{ old('title', $task['title']) }}" required>
@error('title')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="description" class="form-label">Descripción</label>
<textarea class="form-control @error('description') is-invalid @enderror"
id="description" name="description" rows="3">{{ old('description', $task['description']) }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="completed"
name="completed" {{ $task['completed'] ? 'checked' : '' }}>
<label class="form-check-label" for="completed">Completada</label>
</div>
<button type="submit" class="btn btn-primary">Actualizar</button>
<a href="{{ route('tasks.index') }}" class="btn btn-secondary">Cancelar</a>
</form>
</div>
</div>
@endsection5. Vista de detalles (resources/views/tasks/show.blade.php)
@extends('layouts.app')
@section('title', 'Detalles de la Tarea')
@section('content')
<div class="card">
<div class="card-header">
<h2>Detalles de la Tarea</h2>
</div>
<div class="card-body">
<div class="mb-3">
<h5 class="card-title">{{ $task['title'] }}</h5>
<span class="badge {{ $task['completed'] ? 'bg-success' : 'bg-warning' }}">
{{ $task['completed'] ? 'Completada' : 'Pendiente' }}
</span>
</div>
<p class="card-text">{{ $task['description'] }}</p>
<div class="mt-4">
<p><strong>Creada:</strong> {{ \Carbon\Carbon::parse($task['created_at'])->format('d/m/Y H:i') }}</p>
</div>
<div class="mt-4">
<a href="{{ route('tasks.edit', $task['id']) }}" class="btn btn-warning">Editar</a>
<form action="{{ route('tasks.destroy', $task['id']) }}" method="POST" style="display: inline;">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">Eliminar</button>
</form>
<a href="{{ route('tasks.index') }}" class="btn btn-secondary">Volver</a>
</div>
</div>
</div>
@endsectionCaracterísticas clave de esta implementación:
Almacenamiento en sesión: Usamos
Sessionde Laravel para persistir los datos entre requestsManejo de IDs: Generamos IDs únicos con
uniqid()Colecciones: Usamos
collect()para trabajar con métodos de colección en arreglosValidación: Mantenemos el sistema de validación de Laravel
Mensajes flash: Usamos
with()para mensajes de éxito/error
Notas importantes:
Los datos solo persisten durante la sesión actual (se pierden al cerrar el navegador)
Esta implementación es para propósitos educativos, no para producción
Para una aplicación real, deberías usar una base de datos
El sistema de rutas y controladores sigue el mismo patrón que con base de datos
Este ejemplo te muestra cómo trabajar con Blade y Laravel usando estructuras de datos simples, lo que puede ser muy útil para prototipado rápido o para entender los conceptos básicos antes de pasar a una implementación con base de datos.
Comentarios
Publicar un comentario