Esta es la cuarta entrega (wow) de Creando un Crud con Laminas, vamos a marcar una tarea como completada: agregando un botón para ver los detalles de la tarea, incluir un botón para marcar como finalizada y mostrando una etiqueta cuando la tarea esta terminada.
Así que comencemos:
Marcar tarea como completada
Para esta vista vamos a mostrar los datos de la tarea, con dos botones para marcar la tarea como completada y otro para regresar al listado. Vamos a crear una nueva vista dentro del directorio de vistas que se llame show.phtml, con el siguiente código:
<h1>Detalles de la task # <?= $task->id ?></h1>
<div class="card w-75">
<div class="card-header">
<h4><?= $task->title ?></h4>
<p>
<small class="text-muted">Creada <?= $task-> ?></small>
</p>
</div>
<div class="card-body">
<p class="card-text">
<?= $task->description ?>
</p>
<?php if ($task->finished === 0): ?>
<a href="<?= $this->url('todo-app', [
'action' => 'finished',
'id' => $task->id
]) ?>" class="btn btn-primary">Marcar como terminada</a>
<?php else: ?>
<p>
<span class="badge badge-danger">Finished</span>
</p>
<?php endif; ?>
<a href="<?= $this->url('todo-app') ?>" class="btn btn-secondary">Regresar</a>
</div>
</div>
Podemos observar que se usa un componente card de bootstrap, el cual se le especifica el título de la tarea mediante: $task->title dentro de un h4. Después se muestra la fecha cuando se creó la tarea. A continuación dentro del card-body, agregamos la descripción de la task con $task->description para luego tener una pequeña lógica; si $task->finished es igual a 0 entonces mostramos un botón para marcar la task como terminada de lo contrario mostramos un label con la leyenda “Finished” y por último tenemos un botón para regresar al listado de tareas.
Ahora en nuestro controlador ToDoController.php agregamos la siguiente acción:
public function finishedAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
try {
$task = $this->table->getTask($id);
} catch (\Exception $e) {
return $this->redirect()->toRoute('todo-app', ['action' => 'index']);
}
$task->finished = 1;
$task->finishDate = new \DateTime();
try {
$this->table->saveTask($task);
} catch (\Exception $e){
\error_log("error updating", $e->getMessage());
}
return $this->redirect()->toRoute('todo-app', ['action' => 'show', 'id' => $id]);
}
La acción se llama finishedAction(), dentro de esta primero obtenemos el id de la task que viene a través de la url mediante el parámetro id, una vez que tenemos el id buscamos la task mediante: $this->table->getTask($id)
, sino la encontramos hacemos un redirect al listado.
Una vez que hemos encontrado la task lo que hacemos es setear la propiedad finished a 1; indicando que se ha terminado la task. También seteamos la propiedad finishDate con la fecha actual y por último persistimos los cambios de la tarea en la base de datos mediante el método saveTask() al cual se le pasa el objeto task y por último redireccionamos al acción show que es la que estamos mirando actualmente.
Ahora en el método saveTask() del archivo TaskTable.php necesitamos hacer unos ajustes para que nos tome la fecha de finalización de la tarea y de la propiedad finished. En el array $data
, cambiamos la propiedad por lo siguiente:
'finish_date' => $task->finishDate ? $task->finishDate->format('Y-m-d H:i:s'): null,
En el código anterior se setea la fecha con el formato Año-mes-día Hora:minuto:segundo si es que se ha especificado, de lo contrario se setea en null.
Y dentro del mismo array modificamos la key finished para setear lo que nos especifiquen en la propiedad finished (1 o 0):
'finished' => $task->finished
Continuamos con el archivo Task.php dentro de la carpeta Model, en el método exchangeArray(), vamos a modificar las propiedades finisheDate y finished con lo siguiente:
$this->finishDate = !empty($data['finish_date']) ? $data['finish_date'] : null;
$this->finished = !empty($data['finished']) ? $data['finished'] : 0;
Lo cual setean las propiedades con el contenido de $data['finish_date']
y $data['finished']
respectivamente si es que estas no están vacías, de lo contrario se setean en null y 0.
Ahora en el listado vamos a agregar una etiqueta <a>
para ver los detalles de la task como sigue:
<a class="btn btn-info btn-sm p-1" href="<?= $this->url('todo-app', [
'action' => 'show',
'id' => $task->id
]) ?>">
Ver
</a>
Esto crea una etiqueta <a>
con el link para ver los detalles de la task seleccionada y se le pasa como parámetro el id de la task. El listado quedará algo así:
Al darle click al botón de ver nos llevará a la descripción de la task la cual si no está terminada se mostrará con el botón azul para marcar como terminada.
De lo contrario si ya fue marcada como completada la podrás mirar como sigue:
Es todo por ahora, en la quinta parte vamos a eliminar una tarea y posteriormente para una sexta parte haremos una refactorización así que mantenganse atentos.
Su amigo y servidor Peter.
Saludos y happy coding :)