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
@@ -1,285 +1,261 @@
1
- <script setup>
2
- import { ref, reactive, onMounted } from 'vue'
3
-
4
- const API_URL = 'http://localhost:8080/api/items'
5
-
6
- const items = ref([])
7
- const loading = ref(false)
8
- const errorMessage = ref('')
9
-
10
- const searchId = ref('')
11
- const selectedItem = ref(null)
12
-
13
- const createForm = reactive({
14
- name: '',
15
- description: '',
16
- price: 0
17
- })
18
-
19
- const editForm = reactive({
20
- id: '',
21
- name: '',
22
- description: '',
23
- price: 0
24
- })
25
-
26
- async function fetchAll() {
27
- loading.value = true
28
- errorMessage.value = ''
29
- try {
30
- const res = await fetch(API_URL)
31
- if (!res.ok) throw new Error('Failed to fetch items: ' + res.statusText)
32
- items.value = await res.json()
33
- } catch (err) {
34
- errorMessage.value = err.message
35
- } finally {
36
- loading.value = false
37
- }
38
- }
39
-
40
- async function fetchById(id) {
41
- if (!id) return
42
- loading.value = true
43
- errorMessage.value = ''
44
- try {
45
- const res = await fetch(API_URL + '/' + id)
46
- if (!res.ok) throw new Error('Failed to fetch item ' + id + ': ' + res.statusText)
47
- selectedItem.value = await res.json()
48
- } catch (err) {
49
- errorMessage.value = err.message
50
- } finally {
51
- loading.value = false
52
- }
53
- }
54
-
55
- async function createItem() {
56
- if (!createForm.name) return
57
- loading.value = true
58
- errorMessage.value = ''
59
- try {
60
- const res = await fetch(API_URL, {
61
- method: 'POST',
62
- headers: { 'Content-Type': 'application/json' },
63
- body: JSON.stringify({
64
- name: createForm.name,
65
- description: createForm.description,
66
- describtion: createForm.description,
67
- price: Number(createForm.price)
68
- })
69
- })
70
- if (!res.ok) throw new Error('Failed to create item: ' + res.statusText)
71
- createForm.name = ''
72
- createForm.description = ''
73
- createForm.price = 0
74
- await fetchAll()
75
- } catch (err) {
76
- errorMessage.value = err.message
77
- } finally {
78
- loading.value = false
79
- }
80
- }
81
-
82
- async function updateItem() {
83
- if (!editForm.id) return
84
- loading.value = true
85
- errorMessage.value = ''
86
- try {
87
- const res = await fetch(API_URL + '/' + editForm.id, {
88
- method: 'PUT',
89
- headers: { 'Content-Type': 'application/json' },
90
- body: JSON.stringify({
91
- id: editForm.id,
92
- name: editForm.name,
93
- description: editForm.description,
94
- describtion: editForm.description,
95
- price: Number(editForm.price)
96
- })
97
- })
98
- if (!res.ok) throw new Error('Failed to update item: ' + res.statusText)
99
- editForm.id = ''
100
- editForm.name = ''
101
- editForm.description = ''
102
- editForm.price = 0
103
- await fetchAll()
104
- } catch (err) {
105
- errorMessage.value = err.message
106
- } finally {
107
- loading.value = false
108
- }
109
- }
110
-
111
- async function deleteItem(id) {
112
- loading.value = true
113
- errorMessage.value = ''
114
- try {
115
- const res = await fetch(API_URL + '/' + id, {
116
- method: 'DELETE'
117
- })
118
- if (!res.ok) throw new Error('Failed to delete item: ' + res.statusText)
119
- if (selectedItem.value && selectedItem.value.id === id) {
120
- selectedItem.value = null
121
- }
122
- await fetchAll()
123
- } catch (err) {
124
- errorMessage.value = err.message
125
- } finally {
126
- loading.value = false
127
- }
128
- }
129
-
130
- async function patchItem(id, partial) {
131
- loading.value = true
132
- errorMessage.value = ''
133
- try {
134
- const res = await fetch(`http://localhost:8080/api/items/${id}`, {
135
- method: 'PATCH',
136
- headers: { 'Content-Type': 'application/json' },
137
- body: JSON.stringify(partial)
138
- })
139
- if (!res.ok) throw new Error('Failed to patch item: ' + res.statusText)
140
- await fetchAll()
141
- } catch (err) {
142
- errorMessage.value = err.message
143
- } finally {
144
- loading.value = false
145
- }
146
- }
147
-
148
- function promptPatch(item) {
149
- const newPrice = prompt('Enter new price:')
150
- if (newPrice !== null && newPrice !== '') {
151
- patchItem(item.id, { price: Number(newPrice) })
152
- }
153
- }
154
-
155
- function startEdit(item) {
156
- editForm.id = item.id
157
- editForm.name = item.name
158
- editForm.description = item.description || item.describtion || ''
159
- editForm.price = item.price
160
- }
161
-
162
- function cancelEdit() {
163
- editForm.id = ''
164
- editForm.name = ''
165
- editForm.description = ''
166
- editForm.price = 0
167
- }
168
-
169
- onMounted(() => {
170
- fetchAll()
171
- })
172
- </script>
173
-
174
- <template>
175
- <h2>Vue Fetch CRUD</h2>
176
- <br>
177
-
178
- <p v-if="loading">Loading...</p>
179
- <br v-if="loading">
180
-
181
- <p v-if="errorMessage">{{ errorMessage }}</p>
182
- <br v-if="errorMessage">
183
-
184
- <button @click="fetchAll">Refresh All (GET /api/items)</button>
185
- <br><br>
186
- <hr>
187
- <br>
188
-
189
- <h3>Create Item (POST /api/items)</h3>
190
- <br>
191
- <form @submit.prevent="createItem">
192
- <label for="create-name">Name:</label>
193
- <br>
194
- <input id="create-name" v-model="createForm.name" placeholder="Item Name" required>
195
- <br><br>
196
-
197
- <label for="create-desc">Description:</label>
198
- <br>
199
- <input id="create-desc" v-model="createForm.description" placeholder="Item Description" required>
200
- <br><br>
201
-
202
- <label for="create-price">Price:</label>
203
- <br>
204
- <input id="create-price" v-model.number="createForm.price" type="number" placeholder="Item Price" required>
205
- <br><br>
206
-
207
- <button type="submit">Create Item</button>
208
- </form>
209
-
210
- <br>
211
- <hr>
212
- <br>
213
-
214
- <h3>Update Item (PUT /api/items/:id)</h3>
215
- <br>
216
- <form @submit.prevent="updateItem">
217
- <label for="edit-id">Item ID:</label>
218
- <br>
219
- <input id="edit-id" v-model="editForm.id" placeholder="Item ID" required>
220
- <br><br>
221
-
222
- <label for="edit-name">Name:</label>
223
- <br>
224
- <input id="edit-name" v-model="editForm.name" placeholder="Item Name" required>
225
- <br><br>
226
-
227
- <label for="edit-desc">Description:</label>
228
- <br>
229
- <input id="edit-desc" v-model="editForm.description" placeholder="Item Description" required>
230
- <br><br>
231
-
232
- <label for="edit-price">Price:</label>
233
- <br>
234
- <input id="edit-price" v-model.number="editForm.price" type="number" placeholder="Item Price" required>
235
- <br><br>
236
-
237
- <button type="submit">Update Item</button>
238
- <button type="button" @click="cancelEdit">Clear</button>
239
- </form>
240
-
241
- <br>
242
- <hr>
243
- <br>
244
-
245
- <h3>Get Item By ID (GET /api/items/:id)</h3>
246
- <br>
247
- <input v-model="searchId" placeholder="Enter Item ID">
248
- <br><br>
249
- <button @click="fetchById(searchId)">Fetch By ID</button>
250
- <br><br>
251
-
252
- <div v-if="selectedItem">
253
- <h4>Item Details</h4>
254
- <p>ID: {{ selectedItem.id }}</p>
255
- <br>
256
- <p>Name: {{ selectedItem.name }}</p>
257
- <br>
258
- <p>Description: {{ selectedItem.description || selectedItem.describtion }}</p>
259
- <br>
260
- <p>Price: ${{ selectedItem.price }}</p>
261
- <br>
262
- <button @click="selectedItem = null">Close Details</button>
263
- </div>
264
-
265
- <br>
266
- <hr>
267
- <br>
268
-
269
- <h3>Items List (GET /api/items)</h3>
270
- <br>
271
-
272
- <p v-if="items.length === 0">No items loaded.</p>
273
-
274
- <ul v-if="items.length > 0">
275
- <li v-for="item in items" :key="item.id">
276
- <span>{{ item.name }} - {{ item.description || item.describtion }} - ${{ item.price }} (ID: {{ item.id }})</span>
277
- <br><br>
278
- <button @click="fetchById(item.id)">View Details</button>
279
- <button @click="startEdit(item)">Edit</button>
280
- <button @click="deleteItem(item.id)">Delete</button>
281
- <button @click="promptPatch(item)">Patch</button>
282
- <br><br>
283
- </li>
284
- </ul>
285
- </template>
1
+ <script setup>
2
+ import { ref, onMounted } from 'vue'
3
+ import FetchTable from './components/FetchTable.vue'
4
+ import FetchFormModal from './components/FetchFormModal.vue'
5
+ import FetchPatchModal from './components/FetchPatchModal.vue'
6
+
7
+ const API_URL = 'http://localhost:8080/api/items'
8
+
9
+ const items = ref([])
10
+ const loading = ref(false)
11
+ const errorMessage = ref('')
12
+ const selectedItem = ref(null)
13
+
14
+ const isFormModalOpen = ref(false)
15
+ const isEditMode = ref(false)
16
+ const activeItemData = ref(null)
17
+
18
+ const isPatchModalOpen = ref(false)
19
+ const activePatchItem = ref(null)
20
+
21
+ async function fetchAll() {
22
+ loading.value = true
23
+ errorMessage.value = ''
24
+ try {
25
+ const res = await fetch(API_URL)
26
+ if (!res.ok) throw new Error('Failed to fetch items: ' + res.statusText)
27
+ items.value = await res.json()
28
+ } catch (err) {
29
+ errorMessage.value = err.message
30
+ } finally {
31
+ loading.value = false
32
+ }
33
+ }
34
+
35
+ function openCreateModal() {
36
+ isEditMode.value = false
37
+ activeItemData.value = { name: '', description: '', price: 0 }
38
+ isFormModalOpen.value = true
39
+ }
40
+
41
+ function openEditModal(item) {
42
+ isEditMode.value = true
43
+ activeItemData.value = { ...item }
44
+ isFormModalOpen.value = true
45
+ }
46
+
47
+ function openPatchModal(item) {
48
+ activePatchItem.value = item
49
+ isPatchModalOpen.value = true
50
+ }
51
+
52
+ async function handleFormSubmit(payload) {
53
+ loading.value = true
54
+ errorMessage.value = ''
55
+ try {
56
+ if (isEditMode.value) {
57
+ const res = await fetch(API_URL + '/' + payload.id, {
58
+ method: 'PUT',
59
+ headers: { 'Content-Type': 'application/json' },
60
+ body: JSON.stringify(payload)
61
+ })
62
+ if (!res.ok) throw new Error('Failed to update item: ' + res.statusText)
63
+ } else {
64
+ const res = await fetch(API_URL, {
65
+ method: 'POST',
66
+ headers: { 'Content-Type': 'application/json' },
67
+ body: JSON.stringify(payload)
68
+ })
69
+ if (!res.ok) throw new Error('Failed to create item: ' + res.statusText)
70
+ }
71
+ isFormModalOpen.value = false
72
+ await fetchAll()
73
+ } catch (err) {
74
+ errorMessage.value = err.message
75
+ } finally {
76
+ loading.value = false
77
+ }
78
+ }
79
+
80
+ async function handlePatchSubmit({ id, partial }) {
81
+ loading.value = true
82
+ errorMessage.value = ''
83
+ try {
84
+ const res = await fetch(API_URL + '/' + id, {
85
+ method: 'PATCH',
86
+ headers: { 'Content-Type': 'application/json' },
87
+ body: JSON.stringify(partial)
88
+ })
89
+ if (!res.ok) throw new Error('Failed to patch item: ' + res.statusText)
90
+ isPatchModalOpen.value = false
91
+ await fetchAll()
92
+ } catch (err) {
93
+ errorMessage.value = err.message
94
+ } finally {
95
+ loading.value = false
96
+ }
97
+ }
98
+
99
+ async function handleDelete(id) {
100
+ if (!confirm('Are you sure you want to delete this item?')) return
101
+ loading.value = true
102
+ errorMessage.value = ''
103
+ try {
104
+ const res = await fetch(API_URL + '/' + id, {
105
+ method: 'DELETE'
106
+ })
107
+ if (!res.ok) throw new Error('Failed to delete item: ' + res.statusText)
108
+ if (selectedItem.value && selectedItem.value.id === id) {
109
+ selectedItem.value = null
110
+ }
111
+ await fetchAll()
112
+ } catch (err) {
113
+ errorMessage.value = err.message
114
+ } finally {
115
+ loading.value = false
116
+ }
117
+ }
118
+
119
+ function handleViewDetails(item) {
120
+ selectedItem.value = item
121
+ }
122
+
123
+ onMounted(() => {
124
+ fetchAll()
125
+ })
126
+ </script>
127
+
128
+ <template>
129
+ <div class="app-container">
130
+ <header class="app-header">
131
+ <h1>Vue Fetch CRUD with Child Components</h1>
132
+ <p>Modular: FetchTable, FetchFormModal, FetchPatchModal</p>
133
+ </header>
134
+
135
+ <div v-if="errorMessage" class="error-banner">
136
+ {{ errorMessage }}
137
+ </div>
138
+
139
+ <div v-if="selectedItem" class="detail-card">
140
+ <div class="detail-header">
141
+ <h3>Selected Item Details</h3>
142
+ <button type="button" class="btn-close" @click="selectedItem = null">Close</button>
143
+ </div>
144
+ <div class="detail-body">
145
+ <p><strong>ID:</strong> {{ selectedItem.id }}</p>
146
+ <p><strong>Name:</strong> {{ selectedItem.name }}</p>
147
+ <p><strong>Description:</strong> {{ selectedItem.description || selectedItem.describtion || 'N/A' }}</p>
148
+ <p><strong>Price:</strong> ${{ Number(selectedItem.price).toFixed(2) }}</p>
149
+ </div>
150
+ </div>
151
+
152
+ <FetchTable
153
+ :items="items"
154
+ :loading="loading"
155
+ @open-create="openCreateModal"
156
+ @edit="openEditModal"
157
+ @patch="openPatchModal"
158
+ @delete="handleDelete"
159
+ @view-details="handleViewDetails"
160
+ @refresh="fetchAll"
161
+ />
162
+
163
+ <FetchFormModal
164
+ :show="isFormModalOpen"
165
+ :is-edit="isEditMode"
166
+ :item-data="activeItemData"
167
+ @close="isFormModalOpen = false"
168
+ @submit="handleFormSubmit"
169
+ />
170
+
171
+ <FetchPatchModal
172
+ :show="isPatchModalOpen"
173
+ :item="activePatchItem"
174
+ @close="isPatchModalOpen = false"
175
+ @submit="handlePatchSubmit"
176
+ />
177
+ </div>
178
+ </template>
179
+
180
+ <style>
181
+ * {
182
+ box-sizing: border-box;
183
+ margin: 0;
184
+ padding: 0;
185
+ }
186
+
187
+ body {
188
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
189
+ background-color: #f4f6f8;
190
+ color: #333333;
191
+ }
192
+ </style>
193
+
194
+ <style scoped>
195
+ .app-container {
196
+ max-width: 1000px;
197
+ margin: 0 auto;
198
+ padding: 32px 16px;
199
+ }
200
+
201
+ .app-header {
202
+ margin-bottom: 24px;
203
+ }
204
+
205
+ .app-header h1 {
206
+ font-size: 26px;
207
+ color: #1a1a1a;
208
+ margin-bottom: 4px;
209
+ }
210
+
211
+ .app-header p {
212
+ color: #666666;
213
+ font-size: 14px;
214
+ }
215
+
216
+ .error-banner {
217
+ background-color: #ffebe9;
218
+ color: #cf222e;
219
+ border: 1px solid #ff818266;
220
+ padding: 12px 16px;
221
+ border-radius: 6px;
222
+ margin-bottom: 20px;
223
+ font-size: 14px;
224
+ }
225
+
226
+ .detail-card {
227
+ background: #ffffff;
228
+ border: 1px solid #d0d7de;
229
+ border-radius: 8px;
230
+ padding: 16px;
231
+ margin-bottom: 20px;
232
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
233
+ }
234
+
235
+ .detail-header {
236
+ display: flex;
237
+ justify-content: space-between;
238
+ align-items: center;
239
+ border-bottom: 1px solid #eaecef;
240
+ padding-bottom: 8px;
241
+ margin-bottom: 12px;
242
+ }
243
+
244
+ .detail-header h3 {
245
+ font-size: 16px;
246
+ color: #24292f;
247
+ }
248
+
249
+ .btn-close {
250
+ background: none;
251
+ border: none;
252
+ cursor: pointer;
253
+ color: #57606a;
254
+ font-size: 14px;
255
+ }
256
+
257
+ .detail-body p {
258
+ font-size: 14px;
259
+ margin-bottom: 6px;
260
+ }
261
+ </style>