wad-lab 1.1.6 → 1.1.7

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 (93) hide show
  1. package/package.json +1 -1
  2. package/templates/fullstack-springboot-vue/backend/src/main/java/com/example/company/controller/CompanyController.java +88 -74
  3. package/templates/fullstack-springboot-vue/backend/src/main/java/com/example/company/model/Employee.java +73 -73
  4. package/templates/fullstack-springboot-vue/backend/src/main/java/com/example/company/service/CompanyService.java +90 -60
  5. package/templates/fullstack-springboot-vue/frontend/vue-axios-basic/src/App.vue +429 -405
  6. package/templates/fullstack-springboot-vue/frontend/vue-axios-interceptor/src/App.vue +177 -159
  7. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia/src/App.vue +441 -427
  8. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia/src/stores/companyStore.js +126 -96
  9. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia-props/src/App.vue +84 -69
  10. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia-props/src/components/DepartmentSection.vue +164 -152
  11. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia-props/src/components/EmployeeSection.vue +193 -181
  12. package/templates/fullstack-springboot-vue/frontend/vue-axios-pinia-props/src/stores/companyStore.js +126 -35
  13. package/templates/fullstack-springboot-vue/frontend/vue-axios-props-emits/src/App.vue +191 -167
  14. package/templates/fullstack-springboot-vue/frontend/vue-axios-props-emits/src/components/DepartmentForm.vue +98 -98
  15. package/templates/fullstack-springboot-vue/frontend/vue-axios-props-emits/src/components/DepartmentList.vue +92 -91
  16. package/templates/fullstack-springboot-vue/frontend/vue-axios-props-emits/src/components/EmployeeForm.vue +128 -128
  17. package/templates/fullstack-springboot-vue/frontend/vue-axios-props-emits/src/components/EmployeeList.vue +95 -94
  18. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/App.vue +90 -90
  19. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/views/AddEmployeeView.vue +247 -247
  20. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/views/DepartmentView.vue +296 -273
  21. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/views/EmployeeView.vue +219 -196
  22. package/templates/fullstack-springboot-vue/frontend/vue-axios-router/src/views/HomeDashboardView.vue +263 -263
  23. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/views/DepartmentListView.vue +250 -231
  24. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/views/EmployeeDetailView.vue +181 -159
  25. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-children/src/views/EmployeeListView.vue +315 -295
  26. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/stores/companyStore.js +137 -70
  27. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/views/DepartmentView.vue +229 -209
  28. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia/src/views/EmployeeView.vue +257 -237
  29. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia-props/src/components/EntityTable.vue +106 -92
  30. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia-props/src/stores/companyStore.js +139 -84
  31. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia-props/src/views/ManageDepartmentsView.vue +73 -64
  32. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-pinia-props/src/views/ManageEmployeesView.vue +76 -67
  33. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-props/src/App.vue +59 -59
  34. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-props/src/components/DataCard.vue +72 -53
  35. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-props/src/views/DepartmentPage.vue +89 -77
  36. package/templates/fullstack-springboot-vue/frontend/vue-axios-router-props/src/views/EmployeePage.vue +128 -116
  37. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/controller/CompanyController.java +88 -74
  38. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/model/Employee.java +73 -73
  39. package/templates/springboot-2model-1controller-api/src/main/java/com/example/company/service/CompanyService.java +90 -60
  40. package/templates/springboot-course-registration/src/main/java/com/example/coursereg/controller/CourseController.java +46 -42
  41. package/templates/springboot-course-registration/src/main/java/com/example/coursereg/service/CourseService.java +70 -60
  42. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/controller/HospitalController.java +54 -50
  43. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/service/HospitalService.java +65 -54
  44. package/templates/springboot-library-api/src/main/java/com/example/library/controller/LibraryController.java +57 -51
  45. package/templates/springboot-library-api/src/main/java/com/example/library/service/LibraryService.java +70 -60
  46. package/templates/springboot-mockmvc/src/main/java/com/example/mockmvc/controller/ItemController.java +45 -41
  47. package/templates/springboot-mockmvc/src/main/java/com/example/mockmvc/service/ItemService.java +48 -38
  48. package/templates/springboot-mongo-aggregation/src/main/java/com/example/aggregation/controller/ItemController.java +45 -41
  49. package/templates/springboot-mongo-aggregation/src/main/java/com/example/aggregation/service/ItemService.java +48 -38
  50. package/templates/springboot-mongo-aggregation-mockmvc/src/main/java/com/example/aggmockmvc/controller/ItemController.java +45 -41
  51. package/templates/springboot-mongo-aggregation-mockmvc/src/main/java/com/example/aggmockmvc/service/ItemService.java +48 -38
  52. package/templates/springboot-mongo-crud/src/main/java/com/example/crud/controller/ItemController.java +45 -41
  53. package/templates/springboot-mongo-crud/src/main/java/com/example/crud/service/ItemService.java +48 -38
  54. package/templates/vue-axios/src/App.vue +264 -243
  55. package/templates/vue-axios/src/services/ItemService.js +27 -21
  56. package/templates/vue-axios-basic/src/App.vue +24 -0
  57. package/templates/vue-axios-interceptor/src/App.vue +177 -159
  58. package/templates/vue-axios-pinia/src/App.vue +14 -0
  59. package/templates/vue-axios-pinia/src/stores/companyStore.js +126 -96
  60. package/templates/vue-axios-pinia-props/src/App.vue +84 -69
  61. package/templates/vue-axios-pinia-props/src/components/DepartmentSection.vue +164 -152
  62. package/templates/vue-axios-pinia-props/src/components/EmployeeSection.vue +193 -181
  63. package/templates/vue-axios-pinia-props/src/stores/companyStore.js +126 -35
  64. package/templates/vue-axios-props-emits/src/App.vue +24 -0
  65. package/templates/vue-axios-props-emits/src/components/DepartmentList.vue +2 -1
  66. package/templates/vue-axios-props-emits/src/components/EmployeeList.vue +2 -1
  67. package/templates/vue-axios-router/src/views/DepartmentView.vue +23 -0
  68. package/templates/vue-axios-router/src/views/EmployeeView.vue +23 -0
  69. package/templates/vue-axios-router-children/src/views/DepartmentListView.vue +250 -231
  70. package/templates/vue-axios-router-children/src/views/EmployeeDetailView.vue +181 -159
  71. package/templates/vue-axios-router-children/src/views/EmployeeListView.vue +315 -295
  72. package/templates/vue-axios-router-pinia/src/stores/companyStore.js +137 -70
  73. package/templates/vue-axios-router-pinia/src/views/DepartmentView.vue +229 -209
  74. package/templates/vue-axios-router-pinia/src/views/EmployeeView.vue +257 -237
  75. package/templates/vue-axios-router-pinia-props/src/components/EntityTable.vue +106 -92
  76. package/templates/vue-axios-router-pinia-props/src/stores/companyStore.js +139 -84
  77. package/templates/vue-axios-router-pinia-props/src/views/ManageDepartmentsView.vue +73 -64
  78. package/templates/vue-axios-router-pinia-props/src/views/ManageEmployeesView.vue +76 -67
  79. package/templates/vue-axios-router-props/src/components/DataCard.vue +72 -53
  80. package/templates/vue-axios-router-props/src/views/DepartmentPage.vue +89 -77
  81. package/templates/vue-axios-router-props/src/views/EmployeePage.vue +128 -116
  82. package/templates/vue-fetch/src/App.vue +285 -259
  83. package/templates/vue-router-pinia-springboot/backend/src/main/java/com/example/crud/controller/ItemController.java +45 -41
  84. package/templates/vue-router-pinia-springboot/backend/src/main/java/com/example/crud/service/ItemService.java +45 -35
  85. package/templates/vue-router-pinia-springboot/frontend/src/services/ItemService.js +24 -21
  86. package/templates/vue-router-pinia-springboot/frontend/src/stores/itemStore.js +42 -37
  87. package/templates/vue-router-pinia-springboot/frontend/src/views/ListView.vue +76 -67
  88. package/templates/vue-springboot-mongo-aggregation/backend/src/main/java/com/example/aggregation/controller/ItemController.java +45 -41
  89. package/templates/vue-springboot-mongo-aggregation/backend/src/main/java/com/example/aggregation/service/ItemService.java +45 -35
  90. package/templates/vue-springboot-mongo-crud/backend/src/main/java/com/example/crud/controller/ItemController.java +45 -41
  91. package/templates/vue-springboot-mongo-crud/backend/src/main/java/com/example/crud/service/ItemService.java +45 -35
  92. package/templates/vue-springboot-mongo-crud/frontend/src/App.vue +158 -149
  93. package/templates/vue-springboot-mongo-crud/frontend/src/services/ItemService.js +24 -21
@@ -1,263 +1,263 @@
1
- <script setup>
2
- import { ref, computed, onMounted } from 'vue'
3
- import api from '../services/api'
4
-
5
- const departments = ref([])
6
- const employees = ref([])
7
- const loading = ref(false)
8
- const errorMessage = ref('')
9
-
10
- const totalDepartments = computed(() => departments.value.length)
11
- const totalEmployees = computed(() => employees.value.length)
12
-
13
- const totalPayroll = computed(() => {
14
- return employees.value.reduce((sum, emp) => sum + (Number(emp.salary) || 0), 0)
15
- })
16
-
17
- const averageSalary = computed(() => {
18
- if (employees.value.length === 0) return 0
19
- return Math.round(totalPayroll.value / employees.value.length)
20
- })
21
-
22
- async function fetchDashboardData() {
23
- loading.value = true
24
- errorMessage.value = ''
25
- try {
26
- const [deptRes, empRes] = await Promise.all([
27
- api.get('/departments'),
28
- api.get('/employees')
29
- ])
30
- departments.value = deptRes.data
31
- employees.value = empRes.data
32
- } catch (err) {
33
- errorMessage.value = err.message || 'Failed to load dashboard data'
34
- } finally {
35
- loading.value = false
36
- }
37
- }
38
-
39
- onMounted(() => {
40
- fetchDashboardData()
41
- })
42
- </script>
43
-
44
- <template>
45
- <div class="dashboard-view">
46
- <h2>Dashboard Overview</h2>
47
-
48
- <div v-if="loading" class="state-msg">Loading dashboard stats...</div>
49
- <div v-if="errorMessage" class="state-msg error">{{ errorMessage }}</div>
50
-
51
- <div class="stats-grid">
52
- <div class="stat-card">
53
- <h3>Departments</h3>
54
- <p class="stat-value">{{ totalDepartments }}</p>
55
- <router-link to="/departments" class="stat-link">View all departments &rarr;</router-link>
56
- </div>
57
-
58
- <div class="stat-card">
59
- <h3>Employees</h3>
60
- <p class="stat-value">{{ totalEmployees }}</p>
61
- <router-link to="/employees" class="stat-link">View all employees &rarr;</router-link>
62
- </div>
63
-
64
- <div class="stat-card">
65
- <h3>Total Payroll</h3>
66
- <p class="stat-value">${{ totalPayroll.toLocaleString() }}</p>
67
- <span class="stat-sub">Monthly expenditure</span>
68
- </div>
69
-
70
- <div class="stat-card">
71
- <h3>Average Salary</h3>
72
- <p class="stat-value">${{ averageSalary.toLocaleString() }}</p>
73
- <span class="stat-sub">Per employee</span>
74
- </div>
75
- </div>
76
-
77
- <div class="dashboard-sections">
78
- <div class="section-card">
79
- <div class="section-header">
80
- <h3>Departments Overview</h3>
81
- <router-link to="/departments" class="action-btn">Manage</router-link>
82
- </div>
83
- <ul v-if="departments.length > 0" class="item-list">
84
- <li v-for="dept in departments" :key="dept.id" class="list-row">
85
- <strong>{{ dept.name }}</strong>
86
- <span class="badge">{{ dept.code }}</span>
87
- </li>
88
- </ul>
89
- <p v-else class="empty-text">No departments recorded.</p>
90
- </div>
91
-
92
- <div class="section-card">
93
- <div class="section-header">
94
- <h3>Recent Employees</h3>
95
- <router-link to="/add-employee" class="action-btn">+ Add New</router-link>
96
- </div>
97
- <ul v-if="employees.length > 0" class="item-list">
98
- <li v-for="emp in employees.slice(-5)" :key="emp.id" class="list-row">
99
- <div>
100
- <strong>{{ emp.name }}</strong>
101
- <small class="muted-text">({{ emp.email }})</small>
102
- </div>
103
- <span class="salary-text">${{ Number(emp.salary || 0).toLocaleString() }}</span>
104
- </li>
105
- </ul>
106
- <p v-else class="empty-text">No employees recorded.</p>
107
- </div>
108
- </div>
109
- </div>
110
- </template>
111
-
112
- <style scoped>
113
- .dashboard-view {
114
- display: flex;
115
- flex-direction: column;
116
- gap: 20px;
117
- }
118
-
119
- h2 {
120
- margin: 0;
121
- color: #2c3e50;
122
- }
123
-
124
- .state-msg {
125
- padding: 10px;
126
- background-color: #f8f9fa;
127
- border: 1px solid #ddd;
128
- border-radius: 4px;
129
- }
130
-
131
- .state-msg.error {
132
- background-color: #fde8e8;
133
- color: #c0392b;
134
- border-color: #f5c6cb;
135
- }
136
-
137
- .stats-grid {
138
- display: grid;
139
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
140
- gap: 16px;
141
- }
142
-
143
- .stat-card {
144
- background: #ffffff;
145
- border: 1px solid #ddd;
146
- border-radius: 6px;
147
- padding: 16px;
148
- box-shadow: 0 1px 3px rgba(0,0,0,0.05);
149
- }
150
-
151
- .stat-card h3 {
152
- margin: 0 0 8px 0;
153
- font-size: 14px;
154
- color: #666;
155
- text-transform: uppercase;
156
- }
157
-
158
- .stat-value {
159
- margin: 0 0 10px 0;
160
- font-size: 28px;
161
- font-weight: bold;
162
- color: #2c3e50;
163
- }
164
-
165
- .stat-link {
166
- font-size: 13px;
167
- color: #3498db;
168
- text-decoration: none;
169
- }
170
-
171
- .stat-link:hover {
172
- text-decoration: underline;
173
- }
174
-
175
- .stat-sub {
176
- font-size: 13px;
177
- color: #888;
178
- }
179
-
180
- .dashboard-sections {
181
- display: grid;
182
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
183
- gap: 16px;
184
- }
185
-
186
- .section-card {
187
- background: #ffffff;
188
- border: 1px solid #ddd;
189
- border-radius: 6px;
190
- padding: 16px;
191
- box-shadow: 0 1px 3px rgba(0,0,0,0.05);
192
- }
193
-
194
- .section-header {
195
- display: flex;
196
- justify-content: space-between;
197
- align-items: center;
198
- margin-bottom: 12px;
199
- }
200
-
201
- .section-header h3 {
202
- margin: 0;
203
- font-size: 16px;
204
- color: #2c3e50;
205
- }
206
-
207
- .action-btn {
208
- font-size: 12px;
209
- padding: 4px 8px;
210
- background: #2c3e50;
211
- color: #ffffff;
212
- text-decoration: none;
213
- border-radius: 4px;
214
- }
215
-
216
- .action-btn:hover {
217
- background: #34495e;
218
- }
219
-
220
- .item-list {
221
- list-style: none;
222
- padding: 0;
223
- margin: 0;
224
- }
225
-
226
- .list-row {
227
- display: flex;
228
- justify-content: space-between;
229
- align-items: center;
230
- padding: 8px 0;
231
- border-bottom: 1px solid #eee;
232
- }
233
-
234
- .list-row:last-child {
235
- border-bottom: none;
236
- }
237
-
238
- .badge {
239
- background: #ecf0f1;
240
- color: #2c3e50;
241
- padding: 2px 6px;
242
- border-radius: 3px;
243
- font-size: 12px;
244
- font-family: monospace;
245
- }
246
-
247
- .muted-text {
248
- margin-left: 6px;
249
- color: #7f8c8d;
250
- font-size: 12px;
251
- }
252
-
253
- .salary-text {
254
- font-weight: bold;
255
- color: #27ae60;
256
- }
257
-
258
- .empty-text {
259
- color: #7f8c8d;
260
- font-size: 14px;
261
- margin: 8px 0;
262
- }
263
- </style>
1
+ <script setup>
2
+ import { ref, computed, onMounted } from 'vue'
3
+ import api from '../services/api'
4
+
5
+ const departments = ref([])
6
+ const employees = ref([])
7
+ const loading = ref(false)
8
+ const errorMessage = ref('')
9
+
10
+ const totalDepartments = computed(() => departments.value.length)
11
+ const totalEmployees = computed(() => employees.value.length)
12
+
13
+ const totalPayroll = computed(() => {
14
+ return employees.value.reduce((sum, emp) => sum + (Number(emp.salary) || 0), 0)
15
+ })
16
+
17
+ const averageSalary = computed(() => {
18
+ if (employees.value.length === 0) return 0
19
+ return Math.round(totalPayroll.value / employees.value.length)
20
+ })
21
+
22
+ async function fetchDashboardData() {
23
+ loading.value = true
24
+ errorMessage.value = ''
25
+ try {
26
+ const [deptRes, empRes] = await Promise.all([
27
+ api.get('/departments'),
28
+ api.get('/employees')
29
+ ])
30
+ departments.value = deptRes.data
31
+ employees.value = empRes.data
32
+ } catch (err) {
33
+ errorMessage.value = err.message || 'Failed to load dashboard data'
34
+ } finally {
35
+ loading.value = false
36
+ }
37
+ }
38
+
39
+ onMounted(() => {
40
+ fetchDashboardData()
41
+ })
42
+ </script>
43
+
44
+ <template>
45
+ <div class="dashboard-view">
46
+ <h2>Dashboard Overview</h2>
47
+
48
+ <div v-if="loading" class="state-msg">Loading dashboard stats...</div>
49
+ <div v-if="errorMessage" class="state-msg error">{{ errorMessage }}</div>
50
+
51
+ <div class="stats-grid">
52
+ <div class="stat-card">
53
+ <h3>Departments</h3>
54
+ <p class="stat-value">{{ totalDepartments }}</p>
55
+ <router-link to="/departments" class="stat-link">View all departments &rarr;</router-link>
56
+ </div>
57
+
58
+ <div class="stat-card">
59
+ <h3>Employees</h3>
60
+ <p class="stat-value">{{ totalEmployees }}</p>
61
+ <router-link to="/employees" class="stat-link">View all employees &rarr;</router-link>
62
+ </div>
63
+
64
+ <div class="stat-card">
65
+ <h3>Total Payroll</h3>
66
+ <p class="stat-value">${{ totalPayroll.toLocaleString() }}</p>
67
+ <span class="stat-sub">Monthly expenditure</span>
68
+ </div>
69
+
70
+ <div class="stat-card">
71
+ <h3>Average Salary</h3>
72
+ <p class="stat-value">${{ averageSalary.toLocaleString() }}</p>
73
+ <span class="stat-sub">Per employee</span>
74
+ </div>
75
+ </div>
76
+
77
+ <div class="dashboard-sections">
78
+ <div class="section-card">
79
+ <div class="section-header">
80
+ <h3>Departments Overview</h3>
81
+ <router-link to="/departments" class="action-btn">Manage</router-link>
82
+ </div>
83
+ <ul v-if="departments.length > 0" class="item-list">
84
+ <li v-for="dept in departments" :key="dept.id" class="list-row">
85
+ <strong>{{ dept.name }}</strong>
86
+ <span class="badge">{{ dept.code }}</span>
87
+ </li>
88
+ </ul>
89
+ <p v-else class="empty-text">No departments recorded.</p>
90
+ </div>
91
+
92
+ <div class="section-card">
93
+ <div class="section-header">
94
+ <h3>Recent Employees</h3>
95
+ <router-link to="/add-employee" class="action-btn">+ Add New</router-link>
96
+ </div>
97
+ <ul v-if="employees.length > 0" class="item-list">
98
+ <li v-for="emp in employees.slice(-5)" :key="emp.id" class="list-row">
99
+ <div>
100
+ <strong>{{ emp.name }}</strong>
101
+ <small class="muted-text">({{ emp.email }})</small>
102
+ </div>
103
+ <span class="salary-text">${{ Number(emp.salary || 0).toLocaleString() }}</span>
104
+ </li>
105
+ </ul>
106
+ <p v-else class="empty-text">No employees recorded.</p>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ </template>
111
+
112
+ <style scoped>
113
+ .dashboard-view {
114
+ display: flex;
115
+ flex-direction: column;
116
+ gap: 20px;
117
+ }
118
+
119
+ h2 {
120
+ margin: 0;
121
+ color: #2c3e50;
122
+ }
123
+
124
+ .state-msg {
125
+ padding: 10px;
126
+ background-color: #f8f9fa;
127
+ border: 1px solid #ddd;
128
+ border-radius: 4px;
129
+ }
130
+
131
+ .state-msg.error {
132
+ background-color: #fde8e8;
133
+ color: #c0392b;
134
+ border-color: #f5c6cb;
135
+ }
136
+
137
+ .stats-grid {
138
+ display: grid;
139
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
140
+ gap: 16px;
141
+ }
142
+
143
+ .stat-card {
144
+ background: #ffffff;
145
+ border: 1px solid #ddd;
146
+ border-radius: 6px;
147
+ padding: 16px;
148
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
149
+ }
150
+
151
+ .stat-card h3 {
152
+ margin: 0 0 8px 0;
153
+ font-size: 14px;
154
+ color: #666;
155
+ text-transform: uppercase;
156
+ }
157
+
158
+ .stat-value {
159
+ margin: 0 0 10px 0;
160
+ font-size: 28px;
161
+ font-weight: bold;
162
+ color: #2c3e50;
163
+ }
164
+
165
+ .stat-link {
166
+ font-size: 13px;
167
+ color: #3498db;
168
+ text-decoration: none;
169
+ }
170
+
171
+ .stat-link:hover {
172
+ text-decoration: underline;
173
+ }
174
+
175
+ .stat-sub {
176
+ font-size: 13px;
177
+ color: #888;
178
+ }
179
+
180
+ .dashboard-sections {
181
+ display: grid;
182
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
183
+ gap: 16px;
184
+ }
185
+
186
+ .section-card {
187
+ background: #ffffff;
188
+ border: 1px solid #ddd;
189
+ border-radius: 6px;
190
+ padding: 16px;
191
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
192
+ }
193
+
194
+ .section-header {
195
+ display: flex;
196
+ justify-content: space-between;
197
+ align-items: center;
198
+ margin-bottom: 12px;
199
+ }
200
+
201
+ .section-header h3 {
202
+ margin: 0;
203
+ font-size: 16px;
204
+ color: #2c3e50;
205
+ }
206
+
207
+ .action-btn {
208
+ font-size: 12px;
209
+ padding: 4px 8px;
210
+ background: #2c3e50;
211
+ color: #ffffff;
212
+ text-decoration: none;
213
+ border-radius: 4px;
214
+ }
215
+
216
+ .action-btn:hover {
217
+ background: #34495e;
218
+ }
219
+
220
+ .item-list {
221
+ list-style: none;
222
+ padding: 0;
223
+ margin: 0;
224
+ }
225
+
226
+ .list-row {
227
+ display: flex;
228
+ justify-content: space-between;
229
+ align-items: center;
230
+ padding: 8px 0;
231
+ border-bottom: 1px solid #eee;
232
+ }
233
+
234
+ .list-row:last-child {
235
+ border-bottom: none;
236
+ }
237
+
238
+ .badge {
239
+ background: #ecf0f1;
240
+ color: #2c3e50;
241
+ padding: 2px 6px;
242
+ border-radius: 3px;
243
+ font-size: 12px;
244
+ font-family: monospace;
245
+ }
246
+
247
+ .muted-text {
248
+ margin-left: 6px;
249
+ color: #7f8c8d;
250
+ font-size: 12px;
251
+ }
252
+
253
+ .salary-text {
254
+ font-weight: bold;
255
+ color: #27ae60;
256
+ }
257
+
258
+ .empty-text {
259
+ color: #7f8c8d;
260
+ font-size: 14px;
261
+ margin: 8px 0;
262
+ }
263
+ </style>