wad-lab 1.1.2 → 1.1.3

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 (145) hide show
  1. package/bin/index.js +12 -1
  2. package/package.json +1 -1
  3. package/templates/springboot-2model-1controller-api/pom.xml +42 -0
  4. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/CompanyApplication.java +11 -0
  5. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/controller/CompanyController.java +74 -0
  6. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/model/Department.java +51 -0
  7. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/model/Employee.java +73 -0
  8. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/repository/DepartmentRepository.java +12 -0
  9. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/repository/EmployeeRepository.java +12 -0
  10. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/service/CompanyService.java +60 -0
  11. package/templates/springboot-2model-1controller-api/src/main/resources/application.properties +4 -0
  12. package/templates/vue-axios-basic/index.html +12 -0
  13. package/templates/{frontend → vue-axios-basic}/package.json +6 -9
  14. package/templates/vue-axios-basic/src/App.vue +405 -0
  15. package/templates/{frontend → vue-axios-basic}/src/main.js +0 -2
  16. package/templates/vue-axios-basic/src/services/api.js +7 -0
  17. package/templates/vue-axios-basic/vite.config.js +9 -0
  18. package/templates/{frontend → vue-axios-interceptor}/index.html +2 -3
  19. package/templates/vue-axios-interceptor/package.json +20 -0
  20. package/templates/vue-axios-interceptor/src/App.vue +159 -0
  21. package/templates/vue-axios-interceptor/src/components/ToastNotification.vue +47 -0
  22. package/templates/vue-axios-interceptor/src/main.js +7 -0
  23. package/templates/vue-axios-interceptor/src/services/api.js +32 -0
  24. package/templates/vue-axios-interceptor/src/stores/toastStore.js +23 -0
  25. package/templates/vue-axios-interceptor/vite.config.js +6 -0
  26. package/templates/vue-axios-pinia/index.html +12 -0
  27. package/templates/vue-axios-pinia/package.json +20 -0
  28. package/templates/vue-axios-pinia/src/App.vue +427 -0
  29. package/templates/vue-axios-pinia/src/main.js +5 -0
  30. package/templates/vue-axios-pinia/src/services/api.js +7 -0
  31. package/templates/vue-axios-pinia/src/stores/companyStore.js +96 -0
  32. package/templates/vue-axios-pinia/vite.config.js +9 -0
  33. package/templates/vue-axios-pinia-props/index.html +12 -0
  34. package/templates/vue-axios-pinia-props/package.json +20 -0
  35. package/templates/vue-axios-pinia-props/src/App.vue +69 -0
  36. package/templates/vue-axios-pinia-props/src/components/DepartmentSection.vue +152 -0
  37. package/templates/vue-axios-pinia-props/src/components/EmployeeSection.vue +181 -0
  38. package/templates/vue-axios-pinia-props/src/main.js +5 -0
  39. package/templates/vue-axios-pinia-props/src/services/api.js +7 -0
  40. package/templates/vue-axios-pinia-props/src/stores/companyStore.js +35 -0
  41. package/templates/vue-axios-pinia-props/vite.config.js +6 -0
  42. package/templates/vue-axios-props-emits/index.html +12 -0
  43. package/templates/vue-axios-props-emits/package.json +19 -0
  44. package/templates/vue-axios-props-emits/src/App.vue +167 -0
  45. package/templates/vue-axios-props-emits/src/components/DepartmentForm.vue +98 -0
  46. package/templates/vue-axios-props-emits/src/components/DepartmentList.vue +91 -0
  47. package/templates/vue-axios-props-emits/src/components/EmployeeForm.vue +128 -0
  48. package/templates/vue-axios-props-emits/src/components/EmployeeList.vue +94 -0
  49. package/templates/vue-axios-props-emits/src/main.js +4 -0
  50. package/templates/vue-axios-props-emits/src/services/api.js +7 -0
  51. package/templates/vue-axios-props-emits/vite.config.js +9 -0
  52. package/templates/vue-axios-router/index.html +12 -0
  53. package/templates/vue-axios-router/package.json +20 -0
  54. package/templates/vue-axios-router/src/App.vue +90 -0
  55. package/templates/vue-axios-router/src/main.js +5 -0
  56. package/templates/vue-axios-router/src/router/index.js +19 -0
  57. package/templates/vue-axios-router/src/services/api.js +7 -0
  58. package/templates/vue-axios-router/src/views/AddEmployeeView.vue +247 -0
  59. package/templates/vue-axios-router/src/views/DepartmentView.vue +273 -0
  60. package/templates/vue-axios-router/src/views/EmployeeView.vue +196 -0
  61. package/templates/vue-axios-router/src/views/HomeDashboardView.vue +263 -0
  62. package/templates/vue-axios-router/vite.config.js +6 -0
  63. package/templates/vue-axios-router-children/index.html +12 -0
  64. package/templates/vue-axios-router-children/package.json +20 -0
  65. package/templates/vue-axios-router-children/src/App.vue +20 -0
  66. package/templates/vue-axios-router-children/src/main.js +5 -0
  67. package/templates/vue-axios-router-children/src/router/index.js +42 -0
  68. package/templates/vue-axios-router-children/src/services/api.js +7 -0
  69. package/templates/vue-axios-router-children/src/views/CompanyLayout.vue +75 -0
  70. package/templates/vue-axios-router-children/src/views/CompanyOverview.vue +109 -0
  71. package/templates/vue-axios-router-children/src/views/DepartmentListView.vue +231 -0
  72. package/templates/vue-axios-router-children/src/views/EmployeeDetailView.vue +159 -0
  73. package/templates/vue-axios-router-children/src/views/EmployeeListView.vue +295 -0
  74. package/templates/vue-axios-router-children/vite.config.js +6 -0
  75. package/templates/vue-axios-router-pinia/index.html +12 -0
  76. package/templates/vue-axios-router-pinia/package.json +21 -0
  77. package/templates/vue-axios-router-pinia/src/App.vue +92 -0
  78. package/templates/vue-axios-router-pinia/src/main.js +9 -0
  79. package/templates/vue-axios-router-pinia/src/router/index.js +17 -0
  80. package/templates/vue-axios-router-pinia/src/services/api.js +7 -0
  81. package/templates/vue-axios-router-pinia/src/stores/companyStore.js +70 -0
  82. package/templates/vue-axios-router-pinia/src/views/DashboardView.vue +77 -0
  83. package/templates/vue-axios-router-pinia/src/views/DepartmentView.vue +209 -0
  84. package/templates/vue-axios-router-pinia/src/views/EmployeeView.vue +237 -0
  85. package/templates/vue-axios-router-pinia/vite.config.js +6 -0
  86. package/templates/vue-axios-router-pinia-props/index.html +12 -0
  87. package/templates/vue-axios-router-pinia-props/package.json +21 -0
  88. package/templates/vue-axios-router-pinia-props/src/App.vue +67 -0
  89. package/templates/vue-axios-router-pinia-props/src/components/EntityForm.vue +101 -0
  90. package/templates/vue-axios-router-pinia-props/src/components/EntityTable.vue +92 -0
  91. package/templates/vue-axios-router-pinia-props/src/components/SummaryBadge.vue +43 -0
  92. package/templates/vue-axios-router-pinia-props/src/main.js +9 -0
  93. package/templates/vue-axios-router-pinia-props/src/router/index.js +29 -0
  94. package/templates/vue-axios-router-pinia-props/src/services/api.js +29 -0
  95. package/templates/vue-axios-router-pinia-props/src/stores/companyStore.js +84 -0
  96. package/templates/vue-axios-router-pinia-props/src/views/ManageDepartmentsView.vue +64 -0
  97. package/templates/vue-axios-router-pinia-props/src/views/ManageEmployeesView.vue +67 -0
  98. package/templates/vue-axios-router-pinia-props/src/views/OverviewView.vue +38 -0
  99. package/templates/vue-axios-router-pinia-props/vite.config.js +6 -0
  100. package/templates/vue-axios-router-props/index.html +12 -0
  101. package/templates/vue-axios-router-props/package.json +20 -0
  102. package/templates/vue-axios-router-props/src/App.vue +59 -0
  103. package/templates/vue-axios-router-props/src/components/DataCard.vue +53 -0
  104. package/templates/vue-axios-router-props/src/components/EntryForm.vue +117 -0
  105. package/templates/vue-axios-router-props/src/main.js +7 -0
  106. package/templates/vue-axios-router-props/src/router/index.js +23 -0
  107. package/templates/vue-axios-router-props/src/services/api.js +7 -0
  108. package/templates/vue-axios-router-props/src/views/DepartmentPage.vue +77 -0
  109. package/templates/vue-axios-router-props/src/views/EmployeePage.vue +116 -0
  110. package/templates/vue-axios-router-props/vite.config.js +6 -0
  111. package/templates/backend/.gitattributes +0 -2
  112. package/templates/backend/.idea/compiler.xml +0 -21
  113. package/templates/backend/.idea/encodings.xml +0 -6
  114. package/templates/backend/.idea/jarRepositories.xml +0 -20
  115. package/templates/backend/.idea/misc.xml +0 -12
  116. package/templates/backend/.idea/vcs.xml +0 -6
  117. package/templates/backend/pom.xml +0 -104
  118. package/templates/backend/src/main/java/com/example/crud/CrudApplication.java +0 -13
  119. package/templates/backend/src/main/java/com/example/crud/controller/ItemController.java +0 -42
  120. package/templates/backend/src/main/java/com/example/crud/model/Item.java +0 -20
  121. package/templates/backend/src/main/java/com/example/crud/repository/ItemRepository.java +0 -9
  122. package/templates/backend/src/main/java/com/example/crud/service/ItemService.java +0 -37
  123. package/templates/backend/src/main/resources/application.properties +0 -4
  124. package/templates/backend/src/test/java/com/example/crud/CrudApplicationTests.java +0 -13
  125. package/templates/frontend/.vscode/extensions.json +0 -3
  126. package/templates/frontend/README.md +0 -38
  127. package/templates/frontend/jsconfig.json +0 -8
  128. package/templates/frontend/public/favicon.ico +0 -0
  129. package/templates/frontend/src/App.vue +0 -50
  130. package/templates/frontend/src/assets/base.css +0 -86
  131. package/templates/frontend/src/assets/logo.svg +0 -1
  132. package/templates/frontend/src/assets/main.css +0 -35
  133. package/templates/frontend/src/components/HelloWorld.vue +0 -44
  134. package/templates/frontend/src/components/TheWelcome.vue +0 -95
  135. package/templates/frontend/src/components/WelcomeItem.vue +0 -87
  136. package/templates/frontend/src/components/icons/IconCommunity.vue +0 -7
  137. package/templates/frontend/src/components/icons/IconDocumentation.vue +0 -7
  138. package/templates/frontend/src/components/icons/IconEcosystem.vue +0 -7
  139. package/templates/frontend/src/components/icons/IconSupport.vue +0 -7
  140. package/templates/frontend/src/components/icons/IconTooling.vue +0 -19
  141. package/templates/frontend/src/services/ItemService.js +0 -21
  142. package/templates/frontend/vite.config.js +0 -18
  143. /package/templates/{backend → springboot-2model-1controller-api}/.mvn/wrapper/maven-wrapper.properties +0 -0
  144. /package/templates/{backend → springboot-2model-1controller-api}/mvnw +0 -0
  145. /package/templates/{backend → springboot-2model-1controller-api}/mvnw.cmd +0 -0
@@ -0,0 +1,231 @@
1
+ <template>
2
+ <div class="departments-page">
3
+ <header class="page-header">
4
+ <h1>Departments</h1>
5
+ <p>Manage company departments.</p>
6
+ </header>
7
+
8
+ <section class="card form-card">
9
+ <h2>Add New Department</h2>
10
+ <form @submit.prevent="createDepartment" class="form">
11
+ <div class="form-row">
12
+ <div class="form-group">
13
+ <label for="dept-name">Department Name</label>
14
+ <input
15
+ id="dept-name"
16
+ v-model="form.name"
17
+ type="text"
18
+ required
19
+ placeholder="e.g. Finance"
20
+ />
21
+ </div>
22
+ <div class="form-group">
23
+ <label for="dept-code">Department Code</label>
24
+ <input
25
+ id="dept-code"
26
+ v-model="form.code"
27
+ type="text"
28
+ required
29
+ placeholder="e.g. FIN"
30
+ />
31
+ </div>
32
+ </div>
33
+ <button type="submit" class="btn btn-primary">Add Department</button>
34
+ </form>
35
+ </section>
36
+
37
+ <section class="card table-card">
38
+ <h2>All Departments</h2>
39
+ <table class="data-table">
40
+ <thead>
41
+ <tr>
42
+ <th>ID</th>
43
+ <th>Name</th>
44
+ <th>Code</th>
45
+ <th>Actions</th>
46
+ </tr>
47
+ </thead>
48
+ <tbody>
49
+ <tr v-if="departments.length === 0">
50
+ <td colspan="4" class="empty">No departments found.</td>
51
+ </tr>
52
+ <tr v-for="dept in departments" :key="dept.id">
53
+ <td>{{ dept.id }}</td>
54
+ <td>{{ dept.name }}</td>
55
+ <td><code>{{ dept.code }}</code></td>
56
+ <td>
57
+ <button @click="deleteDepartment(dept.id)" class="btn btn-danger">Delete</button>
58
+ </td>
59
+ </tr>
60
+ </tbody>
61
+ </table>
62
+ </section>
63
+ </div>
64
+ </template>
65
+
66
+ <script setup>
67
+ import { ref, reactive, onMounted } from 'vue'
68
+ import api from '../services/api'
69
+
70
+ const departments = ref([])
71
+ const form = reactive({
72
+ name: '',
73
+ code: ''
74
+ })
75
+
76
+ const fetchDepartments = async () => {
77
+ try {
78
+ const res = await api.get('/departments')
79
+ departments.value = Array.isArray(res.data) ? res.data : []
80
+ } catch (err) {
81
+ departments.value = []
82
+ }
83
+ }
84
+
85
+ const createDepartment = async () => {
86
+ try {
87
+ await api.post('/departments', {
88
+ name: form.name,
89
+ code: form.code
90
+ })
91
+ form.name = ''
92
+ form.code = ''
93
+ await fetchDepartments()
94
+ } catch (err) {
95
+ alert('Failed to add department')
96
+ }
97
+ }
98
+
99
+ const deleteDepartment = async (id) => {
100
+ try {
101
+ await api.delete(`/departments/${id}`)
102
+ await fetchDepartments()
103
+ } catch (err) {
104
+ alert('Failed to delete department')
105
+ }
106
+ }
107
+
108
+ onMounted(() => {
109
+ fetchDepartments()
110
+ })
111
+ </script>
112
+
113
+ <style scoped>
114
+ .departments-page {
115
+ max-width: 900px;
116
+ }
117
+
118
+ .page-header {
119
+ margin-bottom: 24px;
120
+ }
121
+
122
+ .page-header h1 {
123
+ font-size: 1.75rem;
124
+ margin-bottom: 6px;
125
+ color: #1e293b;
126
+ }
127
+
128
+ .page-header p {
129
+ color: #64748b;
130
+ }
131
+
132
+ .card {
133
+ background: #ffffff;
134
+ padding: 24px;
135
+ border-radius: 8px;
136
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
137
+ margin-bottom: 24px;
138
+ }
139
+
140
+ .card h2 {
141
+ font-size: 1.2rem;
142
+ margin-bottom: 16px;
143
+ color: #334155;
144
+ }
145
+
146
+ .form-row {
147
+ display: flex;
148
+ gap: 16px;
149
+ margin-bottom: 16px;
150
+ }
151
+
152
+ .form-group {
153
+ flex: 1;
154
+ display: flex;
155
+ flex-direction: column;
156
+ gap: 6px;
157
+ }
158
+
159
+ label {
160
+ font-size: 0.875rem;
161
+ font-weight: 500;
162
+ color: #475569;
163
+ }
164
+
165
+ input {
166
+ padding: 8px 12px;
167
+ border: 1px solid #cbd5e1;
168
+ border-radius: 6px;
169
+ font-size: 0.95rem;
170
+ }
171
+
172
+ input:focus {
173
+ outline: none;
174
+ border-color: #2563eb;
175
+ }
176
+
177
+ .btn {
178
+ padding: 8px 16px;
179
+ border: none;
180
+ border-radius: 6px;
181
+ cursor: pointer;
182
+ font-weight: 500;
183
+ transition: opacity 0.2s;
184
+ }
185
+
186
+ .btn:hover {
187
+ opacity: 0.9;
188
+ }
189
+
190
+ .btn-primary {
191
+ background-color: #2563eb;
192
+ color: #ffffff;
193
+ }
194
+
195
+ .btn-danger {
196
+ background-color: #ef4444;
197
+ color: #ffffff;
198
+ }
199
+
200
+ .data-table {
201
+ width: 100%;
202
+ border-collapse: collapse;
203
+ }
204
+
205
+ .data-table th,
206
+ .data-table td {
207
+ padding: 12px;
208
+ text-align: left;
209
+ border-bottom: 1px solid #e2e8f0;
210
+ }
211
+
212
+ .data-table th {
213
+ background-color: #f8fafc;
214
+ font-size: 0.875rem;
215
+ color: #475569;
216
+ font-weight: 600;
217
+ }
218
+
219
+ .data-table td code {
220
+ background-color: #f1f5f9;
221
+ padding: 2px 6px;
222
+ border-radius: 4px;
223
+ font-size: 0.85rem;
224
+ }
225
+
226
+ .empty {
227
+ text-align: center;
228
+ color: #94a3b8;
229
+ padding: 24px;
230
+ }
231
+ </style>
@@ -0,0 +1,159 @@
1
+ <template>
2
+ <div class="employee-detail-page">
3
+ <div class="header-actions">
4
+ <router-link to="/company/employees" class="btn btn-secondary">&larr; Back to Employees</router-link>
5
+ </div>
6
+
7
+ <div v-if="loading" class="card">
8
+ <p>Loading employee details...</p>
9
+ </div>
10
+
11
+ <div v-else-if="error" class="card error-card">
12
+ <p>{{ error }}</p>
13
+ </div>
14
+
15
+ <div v-else-if="employee" class="card detail-card">
16
+ <header class="detail-header">
17
+ <h1>{{ employee.name }}</h1>
18
+ <span class="badge">ID: {{ employee.id }}</span>
19
+ </header>
20
+
21
+ <div class="detail-grid">
22
+ <div class="detail-item">
23
+ <span class="detail-label">Email Address</span>
24
+ <span class="detail-value">{{ employee.email }}</span>
25
+ </div>
26
+
27
+ <div class="detail-item">
28
+ <span class="detail-label">Department ID</span>
29
+ <span class="detail-value">{{ employee.departmentId }}</span>
30
+ </div>
31
+
32
+ <div class="detail-item">
33
+ <span class="detail-label">Salary</span>
34
+ <span class="detail-value">${{ Number(employee.salary).toLocaleString() }}</span>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </template>
40
+
41
+ <script setup>
42
+ import { ref, onMounted } from 'vue'
43
+ import { useRoute } from 'vue-router'
44
+ import api from '../services/api'
45
+
46
+ const route = useRoute()
47
+ const employee = ref(null)
48
+ const loading = ref(true)
49
+ const error = ref('')
50
+
51
+ const fetchEmployee = async () => {
52
+ const id = route.params.id
53
+ loading.value = true
54
+ error.value = ''
55
+ try {
56
+ const res = await api.get(`/employees/${id}`)
57
+ employee.value = res.data
58
+ } catch (err) {
59
+ error.value = 'Failed to load employee details.'
60
+ } finally {
61
+ loading.value = false
62
+ }
63
+ }
64
+
65
+ onMounted(() => {
66
+ fetchEmployee()
67
+ })
68
+ </script>
69
+
70
+ <style scoped>
71
+ .employee-detail-page {
72
+ max-width: 650px;
73
+ }
74
+
75
+ .header-actions {
76
+ margin-bottom: 20px;
77
+ }
78
+
79
+ .btn {
80
+ padding: 8px 16px;
81
+ border: none;
82
+ border-radius: 6px;
83
+ cursor: pointer;
84
+ font-weight: 500;
85
+ text-decoration: none;
86
+ display: inline-flex;
87
+ align-items: center;
88
+ transition: opacity 0.2s;
89
+ }
90
+
91
+ .btn:hover {
92
+ opacity: 0.9;
93
+ }
94
+
95
+ .btn-secondary {
96
+ background-color: #64748b;
97
+ color: #ffffff;
98
+ }
99
+
100
+ .card {
101
+ background: #ffffff;
102
+ padding: 28px;
103
+ border-radius: 8px;
104
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
105
+ }
106
+
107
+ .error-card {
108
+ color: #ef4444;
109
+ }
110
+
111
+ .detail-header {
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: space-between;
115
+ border-bottom: 1px solid #e2e8f0;
116
+ padding-bottom: 16px;
117
+ margin-bottom: 20px;
118
+ }
119
+
120
+ .detail-header h1 {
121
+ font-size: 1.5rem;
122
+ color: #1e293b;
123
+ }
124
+
125
+ .badge {
126
+ background-color: #e2e8f0;
127
+ color: #475569;
128
+ font-size: 0.85rem;
129
+ font-weight: 600;
130
+ padding: 4px 10px;
131
+ border-radius: 20px;
132
+ }
133
+
134
+ .detail-grid {
135
+ display: flex;
136
+ flex-direction: column;
137
+ gap: 16px;
138
+ }
139
+
140
+ .detail-item {
141
+ display: flex;
142
+ flex-direction: column;
143
+ gap: 4px;
144
+ }
145
+
146
+ .detail-label {
147
+ font-size: 0.85rem;
148
+ color: #64748b;
149
+ font-weight: 500;
150
+ text-transform: uppercase;
151
+ letter-spacing: 0.05em;
152
+ }
153
+
154
+ .detail-value {
155
+ font-size: 1.1rem;
156
+ color: #0f172a;
157
+ font-weight: 600;
158
+ }
159
+ </style>
@@ -0,0 +1,295 @@
1
+ <template>
2
+ <div class="employees-page">
3
+ <header class="page-header">
4
+ <h1>Employees</h1>
5
+ <p>Manage company employees and view their profiles.</p>
6
+ </header>
7
+
8
+ <section class="card form-card">
9
+ <h2>Add New Employee</h2>
10
+ <form @submit.prevent="createEmployee" class="form">
11
+ <div class="form-row">
12
+ <div class="form-group">
13
+ <label for="emp-name">Full Name</label>
14
+ <input
15
+ id="emp-name"
16
+ v-model="form.name"
17
+ type="text"
18
+ required
19
+ placeholder="e.g. Jane Doe"
20
+ />
21
+ </div>
22
+ <div class="form-group">
23
+ <label for="emp-email">Email</label>
24
+ <input
25
+ id="emp-email"
26
+ v-model="form.email"
27
+ type="email"
28
+ required
29
+ placeholder="e.g. jane@example.com"
30
+ />
31
+ </div>
32
+ </div>
33
+ <div class="form-row">
34
+ <div class="form-group">
35
+ <label for="emp-dept">Department</label>
36
+ <select id="emp-dept" v-model="form.departmentId" required>
37
+ <option value="" disabled>Select Department</option>
38
+ <option v-for="dept in departments" :key="dept.id" :value="dept.id">
39
+ {{ dept.name }} ({{ dept.code }})
40
+ </option>
41
+ </select>
42
+ </div>
43
+ <div class="form-group">
44
+ <label for="emp-salary">Salary</label>
45
+ <input
46
+ id="emp-salary"
47
+ v-model.number="form.salary"
48
+ type="number"
49
+ min="0"
50
+ step="any"
51
+ required
52
+ placeholder="e.g. 75000"
53
+ />
54
+ </div>
55
+ </div>
56
+ <button type="submit" class="btn btn-primary">Add Employee</button>
57
+ </form>
58
+ </section>
59
+
60
+ <section class="card table-card">
61
+ <h2>All Employees</h2>
62
+ <table class="data-table">
63
+ <thead>
64
+ <tr>
65
+ <th>ID</th>
66
+ <th>Name</th>
67
+ <th>Email</th>
68
+ <th>Department</th>
69
+ <th>Salary</th>
70
+ <th>Actions</th>
71
+ </tr>
72
+ </thead>
73
+ <tbody>
74
+ <tr v-if="employees.length === 0">
75
+ <td colspan="6" class="empty">No employees found.</td>
76
+ </tr>
77
+ <tr v-for="emp in employees" :key="emp.id">
78
+ <td>{{ emp.id }}</td>
79
+ <td>{{ emp.name }}</td>
80
+ <td>{{ emp.email }}</td>
81
+ <td>{{ getDepartmentName(emp.departmentId) }}</td>
82
+ <td>${{ Number(emp.salary).toLocaleString() }}</td>
83
+ <td class="action-cell">
84
+ <router-link :to="'/company/employees/' + emp.id" class="btn btn-info">View</router-link>
85
+ <button @click="deleteEmployee(emp.id)" class="btn btn-danger">Delete</button>
86
+ </td>
87
+ </tr>
88
+ </tbody>
89
+ </table>
90
+ </section>
91
+ </div>
92
+ </template>
93
+
94
+ <script setup>
95
+ import { ref, reactive, onMounted } from 'vue'
96
+ import api from '../services/api'
97
+
98
+ const employees = ref([])
99
+ const departments = ref([])
100
+
101
+ const form = reactive({
102
+ name: '',
103
+ email: '',
104
+ departmentId: '',
105
+ salary: ''
106
+ })
107
+
108
+ const fetchDepartments = async () => {
109
+ try {
110
+ const res = await api.get('/departments')
111
+ departments.value = Array.isArray(res.data) ? res.data : []
112
+ } catch (err) {
113
+ departments.value = []
114
+ }
115
+ }
116
+
117
+ const fetchEmployees = async () => {
118
+ try {
119
+ const res = await api.get('/employees')
120
+ employees.value = Array.isArray(res.data) ? res.data : []
121
+ } catch (err) {
122
+ employees.value = []
123
+ }
124
+ }
125
+
126
+ const createEmployee = async () => {
127
+ try {
128
+ await api.post('/employees', {
129
+ name: form.name,
130
+ email: form.email,
131
+ departmentId: Number(form.departmentId),
132
+ salary: Number(form.salary)
133
+ })
134
+ form.name = ''
135
+ form.email = ''
136
+ form.departmentId = ''
137
+ form.salary = ''
138
+ await fetchEmployees()
139
+ } catch (err) {
140
+ alert('Failed to add employee')
141
+ }
142
+ }
143
+
144
+ const deleteEmployee = async (id) => {
145
+ try {
146
+ await api.delete(`/employees/${id}`)
147
+ await fetchEmployees()
148
+ } catch (err) {
149
+ alert('Failed to delete employee')
150
+ }
151
+ }
152
+
153
+ const getDepartmentName = (deptId) => {
154
+ const dept = departments.value.find((d) => d.id === deptId)
155
+ return dept ? dept.name : `Dept #${deptId}`
156
+ }
157
+
158
+ onMounted(() => {
159
+ fetchDepartments()
160
+ fetchEmployees()
161
+ })
162
+ </script>
163
+
164
+ <style scoped>
165
+ .employees-page {
166
+ max-width: 960px;
167
+ }
168
+
169
+ .page-header {
170
+ margin-bottom: 24px;
171
+ }
172
+
173
+ .page-header h1 {
174
+ font-size: 1.75rem;
175
+ margin-bottom: 6px;
176
+ color: #1e293b;
177
+ }
178
+
179
+ .page-header p {
180
+ color: #64748b;
181
+ }
182
+
183
+ .card {
184
+ background: #ffffff;
185
+ padding: 24px;
186
+ border-radius: 8px;
187
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
188
+ margin-bottom: 24px;
189
+ }
190
+
191
+ .card h2 {
192
+ font-size: 1.2rem;
193
+ margin-bottom: 16px;
194
+ color: #334155;
195
+ }
196
+
197
+ .form-row {
198
+ display: flex;
199
+ gap: 16px;
200
+ margin-bottom: 16px;
201
+ }
202
+
203
+ .form-group {
204
+ flex: 1;
205
+ display: flex;
206
+ flex-direction: column;
207
+ gap: 6px;
208
+ }
209
+
210
+ label {
211
+ font-size: 0.875rem;
212
+ font-weight: 500;
213
+ color: #475569;
214
+ }
215
+
216
+ input,
217
+ select {
218
+ padding: 8px 12px;
219
+ border: 1px solid #cbd5e1;
220
+ border-radius: 6px;
221
+ font-size: 0.95rem;
222
+ }
223
+
224
+ input:focus,
225
+ select:focus {
226
+ outline: none;
227
+ border-color: #2563eb;
228
+ }
229
+
230
+ .btn {
231
+ padding: 8px 16px;
232
+ border: none;
233
+ border-radius: 6px;
234
+ cursor: pointer;
235
+ font-weight: 500;
236
+ text-decoration: none;
237
+ display: inline-flex;
238
+ align-items: center;
239
+ justify-content: center;
240
+ transition: opacity 0.2s;
241
+ }
242
+
243
+ .btn:hover {
244
+ opacity: 0.9;
245
+ }
246
+
247
+ .btn-primary {
248
+ background-color: #2563eb;
249
+ color: #ffffff;
250
+ }
251
+
252
+ .btn-info {
253
+ background-color: #0284c7;
254
+ color: #ffffff;
255
+ font-size: 0.875rem;
256
+ padding: 6px 12px;
257
+ }
258
+
259
+ .btn-danger {
260
+ background-color: #ef4444;
261
+ color: #ffffff;
262
+ font-size: 0.875rem;
263
+ padding: 6px 12px;
264
+ }
265
+
266
+ .action-cell {
267
+ display: flex;
268
+ gap: 8px;
269
+ }
270
+
271
+ .data-table {
272
+ width: 100%;
273
+ border-collapse: collapse;
274
+ }
275
+
276
+ .data-table th,
277
+ .data-table td {
278
+ padding: 12px;
279
+ text-align: left;
280
+ border-bottom: 1px solid #e2e8f0;
281
+ }
282
+
283
+ .data-table th {
284
+ background-color: #f8fafc;
285
+ font-size: 0.875rem;
286
+ color: #475569;
287
+ font-weight: 600;
288
+ }
289
+
290
+ .empty {
291
+ text-align: center;
292
+ color: #94a3b8;
293
+ padding: 24px;
294
+ }
295
+ </style>
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from 'vite'
2
+ import vue from '@vitejs/plugin-vue'
3
+
4
+ export default defineConfig({
5
+ plugins: [vue()]
6
+ })
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Company Management</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="/src/main.js"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "vue-axios-router-pinia",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "axios": "^1.7.7",
13
+ "pinia": "^4.1.0",
14
+ "vue": "^3.5.44",
15
+ "vue-router": "^5.4.0"
16
+ },
17
+ "devDependencies": {
18
+ "@vitejs/plugin-vue": "^6.0.10",
19
+ "vite": "^8.3.4"
20
+ }
21
+ }