wad-lab 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/bin/index.js +477 -627
  2. package/package.json +1 -1
  3. package/templates/fullstack-springboot-vue/frontend/vue-axios-basic/src/App.vue +241 -429
  4. package/templates/fullstack-springboot-vue/frontend/vue-axios-basic/src/components/ItemFormModal.vue +183 -0
  5. package/templates/fullstack-springboot-vue/frontend/vue-axios-basic/src/components/ItemPatchModal.vue +193 -0
  6. package/templates/fullstack-springboot-vue/frontend/vue-axios-basic/src/components/ItemTable.vue +177 -0
  7. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia/src/App.vue +150 -441
  8. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia/src/components/ItemFormModal.vue +207 -0
  9. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia/src/components/ItemStats.vue +64 -0
  10. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia/src/components/ItemTable.vue +195 -0
  11. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/App.vue +41 -90
  12. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/components/ItemFormModal.vue +173 -0
  13. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/components/ItemTable.vue +102 -0
  14. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/components/NavBar.vue +57 -0
  15. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/views/DepartmentView.vue +132 -296
  16. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/views/EmployeeView.vue +126 -219
  17. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/components/ItemDetail.vue +115 -0
  18. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/components/ItemTable.vue +104 -0
  19. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/components/SideBar.vue +59 -0
  20. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/views/CompanyLayout.vue +2 -51
  21. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/views/DepartmentListView.vue +92 -250
  22. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/views/EmployeeDetailView.vue +59 -181
  23. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/views/EmployeeListView.vue +67 -315
  24. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/App.vue +19 -70
  25. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/components/ItemFormModal.vue +173 -0
  26. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/components/ItemPatchModal.vue +144 -0
  27. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/components/ItemTable.vue +102 -0
  28. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/components/NavBar.vue +53 -0
  29. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/views/DepartmentView.vue +107 -229
  30. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/views/EmployeeView.vue +143 -257
  31. package/templates/game-bingo/script.js +1 -1
  32. package/templates/game-memory-cards/script.js +2 -2
  33. package/templates/game-rock-paper-scissors/index.html +3 -3
  34. package/templates/game-rock-paper-scissors/script.js +2 -2
  35. package/templates/game-tic-tac-toe/script.js +2 -2
  36. package/templates/game-whack-a-mole/index.html +9 -9
  37. package/templates/servlet-basic/WEB-INF/ItemServlet.java +13 -0
  38. package/templates/servlet-basic/WEB-INF/classes/ItemServlet.class +0 -0
  39. package/templates/servlet-flow/WEB-INF/HelloServlet.java +34 -25
  40. package/templates/servlet-flow/WEB-INF/classes/HelloServlet.class +0 -0
  41. package/templates/servlet-jdbc/WEB-INF/JdbcItemServlet.java +13 -0
  42. package/templates/servlet-jdbc/WEB-INF/classes/JdbcItemServlet.class +0 -0
  43. package/templates/snippets/mongo-queries-cheatsheet.txt +105 -0
  44. package/templates/springboot-2model-aggregation-join/.mvn/wrapper/maven-wrapper.properties +3 -0
  45. package/templates/springboot-2model-aggregation-join/mvnw +295 -0
  46. package/templates/springboot-2model-aggregation-join/mvnw.cmd +189 -0
  47. package/templates/springboot-2model-aggregation-join/pom.xml +54 -0
  48. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/AggregationApplication.java +11 -0
  49. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/controller/DepartmentController.java +65 -0
  50. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/controller/EmployeeController.java +65 -0
  51. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/dto/DepartmentStatsDTO.java +15 -0
  52. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/dto/EmployeeJoinDTO.java +19 -0
  53. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/model/Department.java +20 -0
  54. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/model/Employee.java +21 -0
  55. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/repository/DepartmentRepository.java +9 -0
  56. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/repository/EmployeeRepository.java +9 -0
  57. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/service/DepartmentService.java +81 -0
  58. package/templates/springboot-2model-aggregation-join/src/main/java/com/example/aggregation/service/EmployeeService.java +80 -0
  59. package/templates/springboot-2model-aggregation-join/src/main/resources/application.properties +2 -0
  60. package/templates/springboot-2model-aggregation-join/src/test/java/com/example/aggregation/AggregationApplicationTests.java +13 -0
  61. package/templates/vue-2model-crud-patch/README.md +64 -0
  62. package/templates/vue-2model-crud-patch/index.html +12 -0
  63. package/templates/vue-2model-crud-patch/package-lock.json +1785 -0
  64. package/templates/vue-2model-crud-patch/package.json +21 -0
  65. package/templates/vue-2model-crud-patch/src/App.vue +63 -0
  66. package/templates/vue-2model-crud-patch/src/components/AnalyticsBoard.vue +291 -0
  67. package/templates/vue-2model-crud-patch/src/components/DepartmentFormModal.vue +138 -0
  68. package/templates/vue-2model-crud-patch/src/components/DepartmentPatchModal.vue +210 -0
  69. package/templates/vue-2model-crud-patch/src/components/DepartmentTable.vue +133 -0
  70. package/templates/vue-2model-crud-patch/src/components/EmployeeFormModal.vue +177 -0
  71. package/templates/vue-2model-crud-patch/src/components/EmployeePatchModal.vue +221 -0
  72. package/templates/vue-2model-crud-patch/src/components/EmployeeTable.vue +171 -0
  73. package/templates/vue-2model-crud-patch/src/components/NavBar.vue +156 -0
  74. package/templates/vue-2model-crud-patch/src/main.js +12 -0
  75. package/templates/vue-2model-crud-patch/src/router/index.js +33 -0
  76. package/templates/vue-2model-crud-patch/src/services/api.js +64 -0
  77. package/templates/vue-2model-crud-patch/src/stores/departmentStore.js +149 -0
  78. package/templates/vue-2model-crud-patch/src/stores/employeeStore.js +143 -0
  79. package/templates/vue-2model-crud-patch/src/style.css +415 -0
  80. package/templates/vue-2model-crud-patch/src/views/AnalyticsView.vue +59 -0
  81. package/templates/vue-2model-crud-patch/src/views/DepartmentsView.vue +135 -0
  82. package/templates/vue-2model-crud-patch/src/views/EmployeesView.vue +143 -0
  83. package/templates/vue-2model-crud-patch/vite.config.js +9 -0
  84. package/templates/vue-axios/src/App.vue +255 -264
  85. package/templates/vue-axios/src/components/ItemFormModal.vue +183 -0
  86. package/templates/vue-axios/src/components/ItemPatchModal.vue +193 -0
  87. package/templates/vue-axios/src/components/ItemTable.vue +177 -0
  88. package/templates/vue-axios-basic/src/App.vue +241 -429
  89. package/templates/vue-axios-basic/src/components/ItemFormModal.vue +183 -0
  90. package/templates/vue-axios-basic/src/components/ItemPatchModal.vue +193 -0
  91. package/templates/vue-axios-basic/src/components/ItemTable.vue +177 -0
  92. package/templates/vue-axios-pinia/src/App.vue +150 -441
  93. package/templates/vue-axios-pinia/src/components/ItemFormModal.vue +207 -0
  94. package/templates/vue-axios-pinia/src/components/ItemStats.vue +64 -0
  95. package/templates/vue-axios-pinia/src/components/ItemTable.vue +195 -0
  96. package/templates/vue-axios-router/src/App.vue +41 -90
  97. package/templates/vue-axios-router/src/components/ItemFormModal.vue +173 -0
  98. package/templates/vue-axios-router/src/components/ItemTable.vue +102 -0
  99. package/templates/vue-axios-router/src/components/NavBar.vue +57 -0
  100. package/templates/vue-axios-router/src/views/DepartmentView.vue +132 -296
  101. package/templates/vue-axios-router/src/views/EmployeeView.vue +126 -219
  102. package/templates/vue-axios-router-children/src/components/ItemDetail.vue +115 -0
  103. package/templates/vue-axios-router-children/src/components/ItemTable.vue +104 -0
  104. package/templates/vue-axios-router-children/src/components/SideBar.vue +59 -0
  105. package/templates/vue-axios-router-children/src/views/CompanyLayout.vue +2 -51
  106. package/templates/vue-axios-router-children/src/views/DepartmentListView.vue +92 -250
  107. package/templates/vue-axios-router-children/src/views/EmployeeDetailView.vue +59 -181
  108. package/templates/vue-axios-router-children/src/views/EmployeeListView.vue +67 -315
  109. package/templates/vue-axios-router-pinia/src/App.vue +19 -70
  110. package/templates/vue-axios-router-pinia/src/components/ItemFormModal.vue +173 -0
  111. package/templates/vue-axios-router-pinia/src/components/ItemPatchModal.vue +144 -0
  112. package/templates/vue-axios-router-pinia/src/components/ItemTable.vue +102 -0
  113. package/templates/vue-axios-router-pinia/src/components/NavBar.vue +53 -0
  114. package/templates/vue-axios-router-pinia/src/views/DepartmentView.vue +107 -229
  115. package/templates/vue-axios-router-pinia/src/views/EmployeeView.vue +143 -257
  116. package/templates/vue-banking-app/src/components/AccountOverview.vue +75 -0
  117. package/templates/vue-banking-app/src/components/TransactionForm.vue +89 -0
  118. package/templates/vue-banking-app/src/components/TransactionTable.vue +113 -0
  119. package/templates/vue-banking-app/src/stores/bankStore.js +16 -3
  120. package/templates/vue-banking-app/src/views/DashboardView.vue +23 -71
  121. package/templates/vue-banking-app/src/views/StatementView.vue +11 -158
  122. package/templates/vue-banking-app/src/views/TransactionFormView.vue +23 -121
  123. package/templates/vue-basics/src/App.vue +105 -76
  124. package/templates/vue-basics/src/components/CounterCard.vue +107 -0
  125. package/templates/vue-basics/src/components/ItemList.vue +99 -0
  126. package/templates/vue-basics/src/components/UserForm.vue +138 -0
  127. package/templates/vue-cart-router-pinia/src/components/CartSummary.vue +139 -0
  128. package/templates/vue-cart-router-pinia/src/components/CheckoutModal.vue +149 -0
  129. package/templates/vue-cart-router-pinia/src/components/ProductCard.vue +63 -0
  130. package/templates/vue-cart-router-pinia/src/stores/cartStore.js +11 -0
  131. package/templates/vue-cart-router-pinia/src/views/CartView.vue +52 -118
  132. package/templates/vue-cart-router-pinia/src/views/CheckoutView.vue +2 -5
  133. package/templates/vue-cart-router-pinia/src/views/ProductCatalogView.vue +20 -56
  134. package/templates/vue-employee-system/src/App.vue +75 -344
  135. package/templates/vue-employee-system/src/components/DepartmentFilter.vue +108 -0
  136. package/templates/vue-employee-system/src/components/EmployeeModal.vue +183 -0
  137. package/templates/vue-employee-system/src/components/EmployeeTable.vue +91 -0
  138. package/templates/vue-employee-system/src/stores/employeeStore.js +12 -0
  139. package/templates/vue-fetch/src/App.vue +261 -285
  140. package/templates/vue-fetch/src/components/FetchFormModal.vue +183 -0
  141. package/templates/vue-fetch/src/components/FetchPatchModal.vue +193 -0
  142. package/templates/vue-fetch/src/components/FetchTable.vue +177 -0
  143. package/templates/vue-food-ordering/src/components/CartSummary.vue +134 -0
  144. package/templates/vue-food-ordering/src/components/FoodMenu.vue +126 -0
  145. package/templates/vue-food-ordering/src/components/OrderModal.vue +150 -0
  146. package/templates/vue-food-ordering/src/views/MenuView.vue +11 -132
  147. package/templates/vue-food-ordering/src/views/OrderCartView.vue +31 -164
  148. package/templates/vue-game-rps/src/App.vue +29 -88
  149. package/templates/vue-game-tictactoe/src/App.vue +23 -53
  150. package/templates/vue-game-whackamole/src/App.vue +44 -63
  151. package/templates/vue-hospital-portal/src/components/AppointmentForm.vue +144 -0
  152. package/templates/vue-hospital-portal/src/components/DoctorCard.vue +73 -0
  153. package/templates/vue-hospital-portal/src/components/PatientTable.vue +123 -0
  154. package/templates/vue-hospital-portal/src/stores/hospitalStore.js +10 -1
  155. package/templates/vue-hospital-portal/src/views/OPDRegistrationView.vue +40 -416
  156. package/templates/vue-hospital-portal/src/views/PatientListView.vue +11 -301
  157. package/templates/vue-library-system/src/components/BookForm.vue +125 -0
  158. package/templates/vue-library-system/src/components/BookTable.vue +112 -0
  159. package/templates/vue-library-system/src/components/BorrowModal.vue +131 -0
  160. package/templates/vue-library-system/src/stores/libraryStore.js +26 -1
  161. package/templates/vue-library-system/src/views/BookCatalogView.vue +34 -415
  162. package/templates/vue-memory-game/src/App.vue +36 -40
  163. package/templates/vue-memory-game/src/stores/memoryStore.js +32 -37
  164. package/templates/vue-router/src/App.vue +24 -14
  165. package/templates/vue-router/src/components/AboutCard.vue +38 -0
  166. package/templates/vue-router/src/components/HomeHero.vue +75 -0
  167. package/templates/vue-router/src/components/NavBar.vue +54 -0
  168. package/templates/vue-router/src/views/ItemsLayout.vue +17 -9
  169. package/templates/vue-router/src/views/ListView.vue +106 -18
  170. package/templates/vue-router-pinia/src/App.vue +24 -14
  171. package/templates/vue-router-pinia/src/components/ItemFormModal.vue +163 -0
  172. package/templates/vue-router-pinia/src/components/ItemTable.vue +90 -0
  173. package/templates/vue-router-pinia/src/components/NavBar.vue +54 -0
  174. package/templates/vue-router-pinia/src/stores/itemStore.js +8 -1
  175. package/templates/vue-router-pinia/src/views/ListView.vue +78 -14
  176. package/templates/vue-router-pinia-springboot/frontend/src/App.vue +25 -8
  177. package/templates/vue-router-pinia-springboot/frontend/src/components/ItemFormModal.vue +183 -0
  178. package/templates/vue-router-pinia-springboot/frontend/src/components/ItemPatchModal.vue +193 -0
  179. package/templates/vue-router-pinia-springboot/frontend/src/components/ItemTable.vue +177 -0
  180. package/templates/vue-router-pinia-springboot/frontend/src/components/NavBar.vue +54 -0
  181. package/templates/vue-router-pinia-springboot/frontend/src/views/ListView.vue +92 -76
  182. package/templates/vue-springboot-mongo-aggregation/frontend/src/App.vue +184 -193
  183. package/templates/vue-springboot-mongo-aggregation/frontend/src/components/AnalyticsCards.vue +56 -0
  184. package/templates/vue-springboot-mongo-aggregation/frontend/src/components/CategorySummaryTable.vue +71 -0
  185. package/templates/vue-springboot-mongo-aggregation/frontend/src/components/ItemTable.vue +114 -0
  186. package/templates/vue-springboot-mongo-crud/frontend/src/App.vue +228 -158
  187. package/templates/vue-springboot-mongo-crud/frontend/src/components/ItemFormModal.vue +183 -0
  188. package/templates/vue-springboot-mongo-crud/frontend/src/components/ItemPatchModal.vue +193 -0
  189. package/templates/vue-springboot-mongo-crud/frontend/src/components/ItemTable.vue +177 -0
  190. package/templates/vue-symposium-system/src/App.vue +41 -256
  191. package/templates/vue-symposium-system/src/components/AttendeeTable.vue +100 -0
  192. package/templates/vue-symposium-system/src/components/EventCard.vue +67 -0
  193. package/templates/vue-symposium-system/src/components/RegistrationForm.vue +118 -0
  194. package/templates/vue-symposium-system/src/stores/symposiumStore.js +10 -0
  195. package/templates/vue-todo-pinia/src/App.vue +40 -138
  196. package/templates/vue-todo-pinia/src/components/TodoFilter.vue +74 -0
  197. package/templates/vue-todo-pinia/src/components/TodoInput.vue +53 -0
  198. package/templates/vue-todo-pinia/src/components/TodoList.vue +101 -0
  199. package/templates/vue-todo-pinia/src/stores/todoStore.js +6 -0
  200. package/templates/vue-todo-router/src/App.vue +5 -36
  201. package/templates/vue-todo-router/src/components/TodoForm.vue +78 -0
  202. package/templates/vue-todo-router/src/components/TodoList.vue +84 -0
  203. package/templates/vue-todo-router/src/components/TodoNavBar.vue +47 -0
  204. package/templates/vue-todo-router/src/data/todoState.js +7 -0
  205. package/templates/vue-todo-router/src/views/AddTodoView.vue +7 -66
  206. package/templates/vue-todo-router/src/views/TodoDetailView.vue +15 -1
  207. package/templates/vue-todo-router/src/views/TodoListView.vue +22 -64
@@ -0,0 +1,101 @@
1
+ <script setup>
2
+ defineProps({
3
+ todos: {
4
+ type: Array,
5
+ required: true
6
+ }
7
+ })
8
+
9
+ const emit = defineEmits(['toggle', 'patch', 'delete'])
10
+
11
+ function handlePatch(todo) {
12
+ const newText = prompt('Update task description:', todo.text)
13
+ if (newText && newText.trim() !== todo.text) {
14
+ emit('patch', { id: todo.id, text: newText.trim() })
15
+ }
16
+ }
17
+ </script>
18
+
19
+ <template>
20
+ <div>
21
+ <div v-if="todos.length === 0" class="empty-state">
22
+ No todos found. Add one above!
23
+ </div>
24
+
25
+ <ul v-else class="todo-list">
26
+ <li v-for="item in todos" :key="item.id" class="todo-item">
27
+ <label class="todo-label">
28
+ <input
29
+ type="checkbox"
30
+ :checked="item.done"
31
+ @change="emit('toggle', item.id)"
32
+ />
33
+ <span :class="{ completed: item.done }">{{ item.text }}</span>
34
+ </label>
35
+ <div class="actions">
36
+ <button type="button" class="btn-patch" @click="handlePatch(item)">Edit</button>
37
+ <button type="button" class="btn-delete" @click="emit('delete', item.id)">Delete</button>
38
+ </div>
39
+ </li>
40
+ </ul>
41
+ </div>
42
+ </template>
43
+
44
+ <style scoped>
45
+ .todo-list {
46
+ list-style: none;
47
+ padding: 0;
48
+ margin: 0;
49
+ }
50
+
51
+ .todo-item {
52
+ display: flex;
53
+ justify-content: space-between;
54
+ align-items: center;
55
+ padding: 10px 0;
56
+ border-bottom: 1px solid #eee;
57
+ }
58
+
59
+ .todo-label {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 8px;
63
+ cursor: pointer;
64
+ flex: 1;
65
+ }
66
+
67
+ .completed {
68
+ text-decoration: line-through;
69
+ color: #888;
70
+ }
71
+
72
+ .actions {
73
+ display: flex;
74
+ gap: 6px;
75
+ }
76
+
77
+ .btn-patch {
78
+ background: #f1f5f9;
79
+ border: 1px solid #cbd5e1;
80
+ padding: 4px 8px;
81
+ font-size: 12px;
82
+ border-radius: 4px;
83
+ cursor: pointer;
84
+ }
85
+
86
+ .btn-delete {
87
+ background: #fee2e2;
88
+ border: 1px solid #fca5a5;
89
+ color: #b91c1c;
90
+ padding: 4px 8px;
91
+ font-size: 12px;
92
+ border-radius: 4px;
93
+ cursor: pointer;
94
+ }
95
+
96
+ .empty-state {
97
+ text-align: center;
98
+ color: #888;
99
+ padding: 20px 0;
100
+ }
101
+ </style>
@@ -37,6 +37,12 @@ export const useTodoStore = defineStore('todo', {
37
37
  item.done = !item.done
38
38
  }
39
39
  },
40
+ patchTodo(id, partial) {
41
+ const item = this.todos.find((t) => t.id === id)
42
+ if (item) {
43
+ Object.assign(item, partial)
44
+ }
45
+ },
40
46
  deleteTodo(id) {
41
47
  this.todos = this.todos.filter((t) => t.id !== id)
42
48
  },
@@ -1,14 +1,10 @@
1
+ <script setup>
2
+ import TodoNavBar from './components/TodoNavBar.vue'
3
+ </script>
4
+
1
5
  <template>
2
6
  <div class="app-container">
3
- <header class="app-header">
4
- <h1>Vue Router Todo App</h1>
5
- <nav class="nav">
6
- <router-link to="/" class="nav-link">Task List</router-link>
7
- <span class="divider">|</span>
8
- <router-link to="/add" class="nav-link">Add New Task</router-link>
9
- </nav>
10
- </header>
11
-
7
+ <TodoNavBar />
12
8
  <main class="main-content">
13
9
  <router-view />
14
10
  </main>
@@ -22,33 +18,6 @@
22
18
  font-family: Arial, sans-serif;
23
19
  }
24
20
 
25
- .app-header {
26
- border-bottom: 2px solid #333;
27
- padding-bottom: 15px;
28
- margin-bottom: 20px;
29
- }
30
-
31
- .nav {
32
- display: flex;
33
- gap: 10px;
34
- align-items: center;
35
- }
36
-
37
- .nav-link {
38
- text-decoration: none;
39
- color: #2980b9;
40
- font-weight: bold;
41
- }
42
-
43
- .nav-link.router-link-exact-active {
44
- color: #27ae60;
45
- text-decoration: underline;
46
- }
47
-
48
- .divider {
49
- color: #aaa;
50
- }
51
-
52
21
  .main-content {
53
22
  padding: 10px 0;
54
23
  }
@@ -0,0 +1,78 @@
1
+ <script setup>
2
+ import { ref } from 'vue'
3
+
4
+ const emit = defineEmits(['submit'])
5
+
6
+ const title = ref('')
7
+ const description = ref('')
8
+
9
+ function handleSubmit() {
10
+ if (!title.value.trim()) return
11
+ emit('submit', { title: title.value.trim(), description: description.value.trim() })
12
+ title.value = ''
13
+ description.value = ''
14
+ }
15
+ </script>
16
+
17
+ <template>
18
+ <form @submit.prevent="handleSubmit" class="add-form">
19
+ <div class="form-group">
20
+ <label for="todo-title">Task Title:</label>
21
+ <input
22
+ id="todo-title"
23
+ type="text"
24
+ v-model="title"
25
+ placeholder="Enter task name..."
26
+ required
27
+ />
28
+ </div>
29
+
30
+ <div class="form-group">
31
+ <label for="todo-desc">Description (Optional):</label>
32
+ <textarea
33
+ id="todo-desc"
34
+ v-model="description"
35
+ placeholder="Add details about this task..."
36
+ rows="3"
37
+ ></textarea>
38
+ </div>
39
+
40
+ <button type="submit" class="btn btn-submit">Save Task</button>
41
+ </form>
42
+ </template>
43
+
44
+ <style scoped>
45
+ .add-form {
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: 15px;
49
+ }
50
+
51
+ .form-group {
52
+ display: flex;
53
+ flex-direction: column;
54
+ gap: 5px;
55
+ }
56
+
57
+ label {
58
+ font-weight: bold;
59
+ font-size: 14px;
60
+ }
61
+
62
+ input, textarea {
63
+ padding: 8px;
64
+ font-size: 14px;
65
+ border: 1px solid #ccc;
66
+ border-radius: 4px;
67
+ }
68
+
69
+ .btn-submit {
70
+ padding: 10px;
71
+ background-color: #27ae60;
72
+ color: white;
73
+ border: none;
74
+ border-radius: 4px;
75
+ font-size: 14px;
76
+ cursor: pointer;
77
+ }
78
+ </style>
@@ -0,0 +1,84 @@
1
+ <script setup>
2
+ defineProps({
3
+ todos: {
4
+ type: Array,
5
+ required: true
6
+ }
7
+ })
8
+
9
+ const emit = defineEmits(['toggle', 'patch', 'delete'])
10
+
11
+ function handlePatch(item) {
12
+ const newTitle = prompt('Edit task title:', item.title)
13
+ if (newTitle && newTitle.trim() !== item.title) {
14
+ emit('patch', { id: item.id, title: newTitle.trim() })
15
+ }
16
+ }
17
+ </script>
18
+
19
+ <template>
20
+ <ul class="task-list">
21
+ <li v-for="item in todos" :key="item.id" class="task-item">
22
+ <label class="task-label">
23
+ <input
24
+ type="checkbox"
25
+ :checked="item.done"
26
+ @change="emit('toggle', item.id)"
27
+ />
28
+ <span :class="{ completed: item.done }">{{ item.title }}</span>
29
+ </label>
30
+ <div class="actions">
31
+ <router-link :to="'/todo/' + item.id" class="btn btn-detail">Details</router-link>
32
+ <button type="button" class="btn btn-patch" @click="handlePatch(item)">Patch</button>
33
+ <button type="button" class="btn btn-delete" @click="emit('delete', item.id)">Delete</button>
34
+ </div>
35
+ </li>
36
+ </ul>
37
+ </template>
38
+
39
+ <style scoped>
40
+ .task-list {
41
+ list-style: none;
42
+ padding: 0;
43
+ margin: 0;
44
+ }
45
+
46
+ .task-item {
47
+ display: flex;
48
+ justify-content: space-between;
49
+ align-items: center;
50
+ padding: 10px 0;
51
+ border-bottom: 1px solid #eee;
52
+ }
53
+
54
+ .task-label {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: 8px;
58
+ cursor: pointer;
59
+ flex: 1;
60
+ }
61
+
62
+ .completed {
63
+ text-decoration: line-through;
64
+ color: #888;
65
+ }
66
+
67
+ .actions {
68
+ display: flex;
69
+ gap: 6px;
70
+ }
71
+
72
+ .btn {
73
+ padding: 4px 8px;
74
+ border-radius: 4px;
75
+ font-size: 12px;
76
+ cursor: pointer;
77
+ border: 1px solid transparent;
78
+ text-decoration: none;
79
+ }
80
+
81
+ .btn-detail { background: #e0f2fe; color: #0369a1; }
82
+ .btn-patch { background: #f3e8ff; color: #7e22ce; }
83
+ .btn-delete { background: #fee2e2; color: #b91c1c; }
84
+ </style>
@@ -0,0 +1,47 @@
1
+ <script setup>
2
+ </script>
3
+
4
+ <template>
5
+ <header class="app-header">
6
+ <h1>Vue Router Todo App</h1>
7
+ <nav class="nav">
8
+ <router-link to="/" class="nav-link">Task List</router-link>
9
+ <span class="divider">|</span>
10
+ <router-link to="/add" class="nav-link">Add New Task</router-link>
11
+ </nav>
12
+ </header>
13
+ </template>
14
+
15
+ <style scoped>
16
+ .app-header {
17
+ border-bottom: 2px solid #333;
18
+ padding-bottom: 15px;
19
+ margin-bottom: 20px;
20
+ }
21
+
22
+ .app-header h1 {
23
+ font-size: 24px;
24
+ margin-bottom: 8px;
25
+ }
26
+
27
+ .nav {
28
+ display: flex;
29
+ gap: 10px;
30
+ align-items: center;
31
+ }
32
+
33
+ .nav-link {
34
+ text-decoration: none;
35
+ color: #2980b9;
36
+ font-weight: bold;
37
+ }
38
+
39
+ .nav-link.router-link-exact-active {
40
+ color: #27ae60;
41
+ text-decoration: underline;
42
+ }
43
+
44
+ .divider {
45
+ color: #aaa;
46
+ }
47
+ </style>
@@ -25,6 +25,13 @@ export const todoState = reactive({
25
25
  }
26
26
  },
27
27
 
28
+ patchTodo(id, partial) {
29
+ const item = this.todos.find((t) => t.id === Number(id))
30
+ if (item) {
31
+ Object.assign(item, partial)
32
+ }
33
+ },
34
+
28
35
  deleteTodo(id) {
29
36
  const index = this.todos.findIndex((t) => t.id === Number(id))
30
37
  if (index !== -1) {
@@ -1,14 +1,12 @@
1
1
  <script setup>
2
- import { ref } from 'vue'
3
2
  import { useRouter } from 'vue-router'
4
3
  import { todoState } from '../data/todoState'
4
+ import TodoForm from '../components/TodoForm.vue'
5
5
 
6
6
  const router = useRouter()
7
- const title = ref('')
8
- const description = ref('')
9
7
 
10
- function handleSubmit() {
11
- todoState.addTodo(title.value, description.value)
8
+ function handleSubmit({ title, description }) {
9
+ todoState.addTodo(title, description)
12
10
  router.push('/')
13
11
  }
14
12
  </script>
@@ -16,70 +14,13 @@ function handleSubmit() {
16
14
  <template>
17
15
  <div>
18
16
  <h2>Add New Task</h2>
19
- <form @submit.prevent="handleSubmit" class="add-form">
20
- <div class="form-group">
21
- <label for="title">Task Title:</label>
22
- <input id="title" type="text" v-model="title" required placeholder="Enter task title" />
23
- </div>
24
-
25
- <div class="form-group">
26
- <label for="desc">Description:</label>
27
- <textarea id="desc" v-model="description" rows="3" placeholder="Enter optional details"></textarea>
28
- </div>
29
-
30
- <div class="form-actions">
31
- <button type="submit" class="btn btn-save">Save Task</button>
32
- <router-link to="/" class="btn btn-cancel">Cancel</router-link>
33
- </div>
34
- </form>
17
+ <TodoForm @submit="handleSubmit" />
35
18
  </div>
36
19
  </template>
37
20
 
38
21
  <style scoped>
39
- .add-form {
40
- display: flex;
41
- flex-direction: column;
42
- gap: 12px;
43
- max-width: 400px;
44
- }
45
-
46
- .form-group {
47
- display: flex;
48
- flex-direction: column;
49
- gap: 4px;
50
- }
51
-
52
- input, textarea {
53
- padding: 8px;
54
- font-size: 14px;
55
- border: 1px solid #ccc;
56
- border-radius: 4px;
57
- }
58
-
59
- .form-actions {
60
- display: flex;
61
- gap: 10px;
62
- margin-top: 10px;
63
- }
64
-
65
- .btn {
66
- padding: 8px 16px;
67
- border-radius: 4px;
68
- text-decoration: none;
69
- font-size: 14px;
70
- cursor: pointer;
71
- border: none;
72
- }
73
-
74
- .btn-save {
75
- background-color: #27ae60;
76
- color: white;
77
- }
78
-
79
- .btn-cancel {
80
- background-color: #95a5a6;
81
- color: white;
82
- display: inline-flex;
83
- align-items: center;
22
+ h2 {
23
+ font-size: 20px;
24
+ margin-bottom: 12px;
84
25
  }
85
26
  </style>
@@ -16,6 +16,14 @@ function handleDelete() {
16
16
  router.push('/')
17
17
  }
18
18
  }
19
+
20
+ function handlePatch() {
21
+ if (!todo.value) return
22
+ const newDesc = prompt('Update task description:', todo.value.description)
23
+ if (newDesc !== null) {
24
+ todoState.patchTodo(todo.value.id, { description: newDesc.trim() })
25
+ }
26
+ }
19
27
  </script>
20
28
 
21
29
  <template>
@@ -24,12 +32,13 @@ function handleDelete() {
24
32
  <p><strong>ID:</strong> {{ todo.id }}</p>
25
33
  <p><strong>Title:</strong> {{ todo.title }}</p>
26
34
  <p><strong>Description:</strong> {{ todo.description || 'No description provided' }}</p>
27
- <p><strong>Status:</strong> {{ todo.done ? 'Completed ✅' : 'Pending ⏳' }}</p>
35
+ <p><strong>Status:</strong> {{ todo.done ? 'Completed' : 'Pending' }}</p>
28
36
 
29
37
  <div class="actions">
30
38
  <button type="button" class="btn btn-toggle" @click="todoState.toggleTodo(todo.id)">
31
39
  Mark as {{ todo.done ? 'Pending' : 'Completed' }}
32
40
  </button>
41
+ <button type="button" class="btn btn-patch" @click="handlePatch">Patch Description</button>
33
42
  <button type="button" class="btn btn-delete" @click="handleDelete">Delete</button>
34
43
  <router-link to="/" class="btn btn-back">Back to List</router-link>
35
44
  </div>
@@ -70,6 +79,11 @@ function handleDelete() {
70
79
  color: white;
71
80
  }
72
81
 
82
+ .btn-patch {
83
+ background-color: #8e44ad;
84
+ color: white;
85
+ }
86
+
73
87
  .btn-delete {
74
88
  background-color: #e74c3c;
75
89
  color: white;
@@ -1,77 +1,35 @@
1
1
  <script setup>
2
2
  import { todoState } from '../data/todoState'
3
+ import TodoList from '../components/TodoList.vue'
4
+
5
+ function handleToggle(id) {
6
+ todoState.toggleTodo(id)
7
+ }
8
+
9
+ function handlePatch({ id, title }) {
10
+ todoState.patchTodo(id, { title })
11
+ }
12
+
13
+ function handleDelete(id) {
14
+ todoState.deleteTodo(id)
15
+ }
3
16
  </script>
4
17
 
5
18
  <template>
6
19
  <div>
7
20
  <h2>Task List</h2>
8
- <ul class="task-list">
9
- <li v-for="item in todoState.todos" :key="item.id" class="task-item">
10
- <label>
11
- <input
12
- type="checkbox"
13
- :checked="item.done"
14
- @change="todoState.toggleTodo(item.id)"
15
- />
16
- <span :class="{ completed: item.done }">{{ item.title }}</span>
17
- </label>
18
- <div class="actions">
19
- <router-link :to="'/todo/' + item.id" class="btn-link">View Details</router-link>
20
- <button type="button" class="btn-del" @click="todoState.deleteTodo(item.id)">Delete</button>
21
- </div>
22
- </li>
23
- </ul>
24
-
25
- <div v-if="todoState.todos.length === 0" class="empty">
26
- No tasks available. Click "Add Task" to create one.
27
- </div>
21
+ <TodoList
22
+ :todos="todoState.todos"
23
+ @toggle="handleToggle"
24
+ @patch="handlePatch"
25
+ @delete="handleDelete"
26
+ />
28
27
  </div>
29
28
  </template>
30
29
 
31
30
  <style scoped>
32
- .task-list {
33
- list-style: none;
34
- padding: 0;
35
- margin: 15px 0;
36
- }
37
-
38
- .task-item {
39
- display: flex;
40
- justify-content: space-between;
41
- align-items: center;
42
- padding: 10px 0;
43
- border-bottom: 1px solid #ddd;
44
- }
45
-
46
- .completed {
47
- text-decoration: line-through;
48
- color: #888;
49
- }
50
-
51
- .actions {
52
- display: flex;
53
- gap: 10px;
54
- align-items: center;
55
- }
56
-
57
- .btn-link {
58
- color: #2980b9;
59
- text-decoration: none;
60
- font-size: 13px;
61
- }
62
-
63
- .btn-del {
64
- background-color: #e74c3c;
65
- color: white;
66
- border: none;
67
- padding: 4px 8px;
68
- border-radius: 3px;
69
- cursor: pointer;
70
- }
71
-
72
- .empty {
73
- text-align: center;
74
- color: #888;
75
- padding: 20px 0;
31
+ h2 {
32
+ font-size: 20px;
33
+ margin-bottom: 12px;
76
34
  }
77
35
  </style>