BootCamp Tutorial 4: Vue.js Advanced API Integration with Role-Based Access
π Learning Objectives
In this tutorial, we will integrate API endpoints with Vue.js while maintaining separation of concerns by keeping API calls modular. You will learn: β
Fetching and displaying tasks
β
Managing users and approving/rejecting them
β
Updating and deleting tasks
β
Assigning tasks to users
β
Displaying statistics for Admin & Manager
By the end, you will have a complete Vue.js dashboard to manage tasks & users efficiently.
π Setting Up API Handling in Vue
Before creating pages, letβs set up a file to handle API interactions in a structured way.
π src/services/api.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import axios from "axios";
const API_URL = "http://127.0.0.1:5000";
const token = localStorage.getItem("token");
const api = axios.create({
baseURL: API_URL,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
export const fetchTasks = () => api.get("/tasks");
export const fetchTaskById = (taskId) => api.get(`/task/${taskId}`);
export const updateTask = (taskId, data) => api.put(`/task/${taskId}`, data);
export const deleteTask = (taskId) => api.delete(`/task/${taskId}`);
export const fetchPendingUsers = () => api.get("/users/pending");
export const approveUser = (userId) => api.put(`/users/${userId}/approve`);
export const rejectUser = (userId) => api.delete(`/users/${userId}/reject`);
export const assignTask = (taskId, userId) => api.put(`/task/${taskId}/assign`, { user_id: userId });
export const fetchStats = () => api.get("/stats");
export default api;
1οΈβ£ Fetching & Displaying Tasks
π src/views/TaskList.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<template>
<div>
<h2>Task Management</h2>
<button @click="fetchTaskList">Refresh</button>
<table>
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Description</th>
<th>Status</th>
<th>Deadline</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="task in tasks" :key="task.id">
<td>{{ task.id }}</td>
<td>{{ task.title }}</td>
<td>{{ task.description || 'N/A' }}</td>
<td>{{ task.status }}</td>
<td>{{ task.deadline || 'No deadline' }}</td>
<td>
<button @click="editTask(task)">Edit</button>
<button @click="deleteTaskById(task.id)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { fetchTasks, deleteTask } from "@/services/api.js";
export default {
data() {
return {
tasks: [],
};
},
methods: {
async fetchTaskList() {
const response = await fetchTasks();
this.tasks = response.data;
},
async deleteTaskById(taskId) {
if (confirm("Are you sure you want to delete this task?")) {
await deleteTask(taskId);
this.fetchTaskList();
}
},
editTask(task) {
this.$router.push({ name: "EditTask", params: { taskId: task.id } });
},
},
mounted() {
this.fetchTaskList();
},
};
</script>
2οΈβ£ Editing Tasks
π src/views/EditTask.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<template>
<div>
<h2>Edit Task</h2>
<form @submit.prevent="updateTaskData">
<label>Title:</label>
<input v-model="task.title" required />
<label>Description:</label>
<input v-model="task.description" />
<label>Status:</label>
<select v-model="task.status">
<option>pending</option>
<option>in-progress</option>
<option>completed</option>
</select>
<button type="submit">Update Task</button>
</form>
</div>
</template>
<script>
import { fetchTaskById, updateTask } from "@/services/api.js";
export default {
data() {
return {
task: {
title: "",
description: "",
status: "pending",
},
};
},
async mounted() {
const taskId = this.$route.params.taskId;
const response = await fetchTaskById(taskId);
this.task = response.data;
},
methods: {
async updateTaskData() {
await updateTask(this.$route.params.taskId, this.task);
this.$router.push("/tasks");
},
},
};
</script>
3οΈβ£ User Approvals
π src/views/UserApproval.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<template>
<div>
<h2>Pending User Approvals</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>Username</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="user in pendingUsers" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>
<button @click="approveUserById(user.id)">Approve</button>
<button @click="rejectUserById(user.id)">Reject</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { fetchPendingUsers, approveUser, rejectUser } from "@/services/api.js";
export default {
data() {
return {
pendingUsers: [],
};
},
async mounted() {
const response = await fetchPendingUsers();
this.pendingUsers = response.data;
},
methods: {
async approveUserById(userId) {
await approveUser(userId);
this.fetchPendingUsers();
},
async rejectUserById(userId) {
await rejectUser(userId);
this.fetchPendingUsers();
},
},
};
</script>
4οΈβ£ Assigning Tasks
π src/views/AssignTask.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template>
<div>
<h2>Assign Task</h2>
<label>Select User:</label>
<select v-model="selectedUser">
<option v-for="user in users" :key="user.id" :value="user.id">
{{ user.username }}
</option>
</select>
<button @click="assignTaskToUser">Assign</button>
</div>
</template>
<script>
import { assignTask, fetchPendingUsers } from "@/services/api.js";
export default {
data() {
return {
users: [],
selectedUser: null,
};
},
async mounted() {
const response = await fetchPendingUsers();
this.users = response.data;
},
methods: {
async assignTaskToUser() {
await assignTask(this.$route.params.taskId, this.selectedUser);
alert("Task Assigned!");
},
},
};
</script>
5οΈβ£ Fetching System Statistics
π src/views/Stats.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div>
<h2>System Statistics</h2>
<p>Total Users: {{ stats.total_users }}</p>
<p>Total Tasks: {{ stats.total_tasks }}</p>
<p>Completed Tasks: {{ stats.completed_tasks }}</p>
</div>
</template>
<script>
import { fetchStats } from "@/services/api.js";
export default {
data() {
return {
stats: {},
};
},
async mounted() {
const response = await fetchStats();
this.stats = response.data;
},
};
</script>
π― Summary
- π₯ Task Management (List, Edit, Delete, Assign)
- β User Approvals (Approve/Reject)
- π Fetching Statistics
- π οΈ Role-Based API Handling
This completes our Vue.js API Integration with Role-Based Access! π