Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Swagger/OpenAPI UI support -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.7.0</version>
</dependency>
<!-- Lombok (auto-generates getters, setters, constructors, etc.) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,56 +1,60 @@
package com.github.silversoth.task_manager.controller;

import com.github.silversoth.task_manager.dao.TaskRepository;
import com.github.silversoth.task_manager.service.TaskService;
import org.springframework.stereotype.Controller;

import com.github.silversoth.task_manager.entity.Task;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;


@Controller
@Tag(name = "Task Controller", description = "Handles task operations for the web app")
public class TaskController {
private final TaskRepository taskRepository;

public TaskController(TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}
private final TaskService taskService;

public TaskController(TaskService taskService) {
this.taskService = taskService;
}

@Operation(summary = "Redirect root URL to tasks page")
@GetMapping("/")
public String homeRedirect() {
return "redirect:/tasks";
}


@Operation(summary = "List all tasks and show form")
@GetMapping("/tasks")
public String listTasks(Model model) {
model.addAttribute("tasks", taskRepository.findAll());
model.addAttribute("tasks", taskService.getAllTasks());
model.addAttribute("task", new Task());
return "index";
}

@Operation(summary = "Save a new task")
@PostMapping("/tasks")
public String saveTask(@ModelAttribute Task task) {
taskRepository.save(task);
taskService.saveTask(task);
return "redirect:/tasks";
}

@Operation(summary = "Delete a task by ID")
@GetMapping("/tasks/delete/{id}")
public String deleteTask(@PathVariable Long id) {
taskRepository.deleteById(id);
taskService.deleteTask(id);
return "redirect:/tasks";
}

@Operation(summary = "Toggle completion status of a task")
@GetMapping("/tasks/complete/{id}")
public String completeTask(@PathVariable Long id) {
Task task = taskRepository.findById(id).orElse(null);
if (task != null) {
task.setCompleted(!task.isCompleted());
taskRepository.save(task);
}
taskService.toggleTaskCompletion(id);
return "redirect:/tasks";
}
}
32 changes: 6 additions & 26 deletions src/main/java/com/github/silversoth/task_manager/entity/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,20 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String description;
private boolean completed;

// Getters y setters

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public boolean isCompleted() {
return completed;
}

public void setCompleted(boolean completed) {
this.completed = completed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.github.silversoth.task_manager.service;

import com.github.silversoth.task_manager.entity.Task;

import java.util.List;

public interface TaskService {
List<Task> getAllTasks();
Task saveTask(Task task);
void deleteTask(Long id);
Task toggleTaskCompletion(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.github.silversoth.task_manager.service;

import com.github.silversoth.task_manager.dao.TaskRepository;
import com.github.silversoth.task_manager.entity.Task;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class TaskServiceImpl implements TaskService {

private final TaskRepository taskRepository;

public TaskServiceImpl(TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}

@Override
public List<Task> getAllTasks() {
return taskRepository.findAll();
}

@Override
public Task saveTask(Task task) {
return taskRepository.save(task);
}

@Override
public void deleteTask(Long id) {
taskRepository.deleteById(id);
}

@Override
public Task toggleTaskCompletion(Long id) {
Task task = taskRepository.findById(id).orElse(null);
if (task != null) {
task.setCompleted(!task.isCompleted());
return taskRepository.save(task);
}
return null;
}
}

37 changes: 25 additions & 12 deletions src/main/resources/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,49 @@
<title>Task Manager</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<!-- Bootstrap & Icons -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">

<body class="container mt-5">
<h1 class="mb-4">My Tasks</h1>
<div class="text-center mb-4">
<h2 class="fw-bold">📝 My Tasks</h2>
<p class="text-muted">Organize, track, and manage your tasks efficiently.</p>
</div>

<form th:action="@{/tasks}" th:object="${task}" method="post" class="mb-3">
<div class="input-group">
<input type="text" th:field="*{description}" class="form-control" placeholder="New task" required />
<button type="submit" class="btn btn-primary">Add</button>
<form th:action="@{/tasks}" th:object="${task}" method="post" class="mb-4">
<div class="input-group shadow-sm">
<input type="text" th:field="*{description}" class="form-control"
placeholder="Enter a new task..." required />
<button type="submit" class="btn btn-primary">
<i class="bi bi-plus"></i>
</button>
</div>
</form>

<table class="table table-striped">
<thead>
<table class="table table-striped align-middle">
<thead class="table-light">
<tr>
<th>Description</th>
<th>Completed</th>
<th>Actions</th>
<th scope="col">Description</th>
<th scope="col" class="text-center">Completed</th>
<th scope="col" class="text-end">Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="task : ${tasks}">
<td th:text="${task.description}"></td>
<td>
<td class="text-center">
<span th:text="${task.completed} ? '✔️' : '❌'"></span>
</td>
<td>
<td class="text-end">
<a th:href="@{'/tasks/complete/' + ${task.id}}" class="btn btn-success btn-sm">Complete</a>
<a th:href="@{'/tasks/delete/' + ${task.id}}" class="btn btn-danger btn-sm">Eliminate</a>
</td>
</tr>
</tbody>
</table>

</body>
</html>