wad-lab 1.0.8 → 1.1.0

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 (62) hide show
  1. package/bin/index.js +15 -8
  2. package/package.json +1 -1
  3. package/templates/springboot-hospital-api/.mvn/wrapper/maven-wrapper.properties +3 -0
  4. package/templates/springboot-hospital-api/mvnw +295 -0
  5. package/templates/springboot-hospital-api/mvnw.cmd +189 -0
  6. package/templates/springboot-hospital-api/pom.xml +41 -0
  7. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/HospitalApplication.java +12 -0
  8. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/controller/HospitalController.java +50 -0
  9. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/model/Appointment.java +95 -0
  10. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/repository/AppointmentRepository.java +15 -0
  11. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/service/HospitalService.java +54 -0
  12. package/templates/springboot-hospital-api/src/main/resources/application.properties +3 -0
  13. package/templates/springboot-hospital-api/src/test/java/com/example/hospital/HospitalApplicationTests.java +12 -0
  14. package/templates/springboot-library-api/.mvn/wrapper/maven-wrapper.properties +3 -0
  15. package/templates/springboot-library-api/mvnw +295 -0
  16. package/templates/springboot-library-api/mvnw.cmd +189 -0
  17. package/templates/springboot-library-api/pom.xml +42 -0
  18. package/templates/springboot-library-api/src/main/java/com/example/library/LibraryApplication.java +12 -0
  19. package/templates/springboot-library-api/src/main/java/com/example/library/controller/LibraryController.java +51 -0
  20. package/templates/springboot-library-api/src/main/java/com/example/library/model/Book.java +76 -0
  21. package/templates/springboot-library-api/src/main/java/com/example/library/model/CategoryAnalytics.java +41 -0
  22. package/templates/springboot-library-api/src/main/java/com/example/library/repository/BookRepository.java +13 -0
  23. package/templates/springboot-library-api/src/main/java/com/example/library/service/LibraryService.java +60 -0
  24. package/templates/springboot-library-api/src/main/resources/application.properties +3 -0
  25. package/templates/vue-game-rps/index.html +12 -0
  26. package/templates/vue-game-rps/package.json +19 -0
  27. package/templates/vue-game-rps/src/App.vue +125 -0
  28. package/templates/vue-game-rps/src/main.js +5 -0
  29. package/templates/vue-game-rps/src/stores/rpsStore.js +43 -0
  30. package/templates/vue-game-rps/vite.config.js +6 -0
  31. package/templates/vue-game-tictactoe/index.html +12 -0
  32. package/templates/vue-game-tictactoe/package.json +19 -0
  33. package/templates/vue-game-tictactoe/src/App.vue +105 -0
  34. package/templates/vue-game-tictactoe/src/main.js +5 -0
  35. package/templates/vue-game-tictactoe/src/stores/tictactoeStore.js +61 -0
  36. package/templates/vue-game-tictactoe/vite.config.js +6 -0
  37. package/templates/vue-game-whackamole/index.html +12 -0
  38. package/templates/vue-game-whackamole/package.json +19 -0
  39. package/templates/vue-game-whackamole/src/App.vue +104 -0
  40. package/templates/vue-game-whackamole/src/main.js +7 -0
  41. package/templates/vue-game-whackamole/src/stores/moleStore.js +71 -0
  42. package/templates/vue-game-whackamole/vite.config.js +6 -0
  43. package/templates/vue-hospital-portal/index.html +12 -0
  44. package/templates/vue-hospital-portal/package.json +20 -0
  45. package/templates/vue-hospital-portal/src/App.vue +107 -0
  46. package/templates/vue-hospital-portal/src/main.js +9 -0
  47. package/templates/vue-hospital-portal/src/router/index.js +17 -0
  48. package/templates/vue-hospital-portal/src/stores/hospitalStore.js +91 -0
  49. package/templates/vue-hospital-portal/src/views/HospitalBillingView.vue +271 -0
  50. package/templates/vue-hospital-portal/src/views/OPDRegistrationView.vue +453 -0
  51. package/templates/vue-hospital-portal/src/views/PatientListView.vue +315 -0
  52. package/templates/vue-hospital-portal/vite.config.js +6 -0
  53. package/templates/vue-library-system/index.html +12 -0
  54. package/templates/vue-library-system/package.json +20 -0
  55. package/templates/vue-library-system/src/App.vue +91 -0
  56. package/templates/vue-library-system/src/main.js +9 -0
  57. package/templates/vue-library-system/src/router/index.js +29 -0
  58. package/templates/vue-library-system/src/stores/libraryStore.js +87 -0
  59. package/templates/vue-library-system/src/views/BookCatalogView.vue +432 -0
  60. package/templates/vue-library-system/src/views/LoanManagerView.vue +296 -0
  61. package/templates/vue-library-system/src/views/MembershipView.vue +269 -0
  62. package/templates/vue-library-system/vite.config.js +6 -0
@@ -0,0 +1,315 @@
1
+ <script setup>
2
+ import { ref, computed } from 'vue'
3
+ import { useHospitalStore } from '../stores/hospitalStore'
4
+
5
+ const hospital = useHospitalStore()
6
+ const filterBed = ref('ALL')
7
+ const searchQuery = ref('')
8
+ const notice = ref('')
9
+
10
+ const filteredPatients = computed(() => {
11
+ return hospital.patients.filter((p) => {
12
+ const matchesBed = filterBed.value === 'ALL' || p.bedType === filterBed.value
13
+ const matchesSearch = p.name.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
14
+ p.doctor.toLowerCase().includes(searchQuery.value.toLowerCase())
15
+ return matchesBed && matchesSearch
16
+ })
17
+ })
18
+
19
+ function handleDischarge(id, name) {
20
+ hospital.dischargePatient(id)
21
+ notice.value = `Patient ${name} has been discharged.`
22
+ setTimeout(() => {
23
+ notice.value = ''
24
+ }, 3000)
25
+ }
26
+ </script>
27
+
28
+ <template>
29
+ <div class="patient-list-page">
30
+ <div class="header-row">
31
+ <div>
32
+ <h2>Admitted Patients Directory</h2>
33
+ <p class="subtitle">Currently admitted: {{ hospital.totalPatients }} patient(s)</p>
34
+ </div>
35
+ <router-link to="/" class="btn-admit-link">+ Admit New Patient</router-link>
36
+ </div>
37
+
38
+ <div v-if="notice" class="alert alert-info">
39
+ {{ notice }}
40
+ </div>
41
+
42
+ <div class="filter-bar">
43
+ <input
44
+ v-model="searchQuery"
45
+ type="text"
46
+ placeholder="Search patient or doctor..."
47
+ class="search-input"
48
+ />
49
+ <div class="filter-tabs">
50
+ <button
51
+ :class="['tab-btn', filterBed === 'ALL' ? 'tab-active' : '']"
52
+ @click="filterBed = 'ALL'"
53
+ >
54
+ All ({{ hospital.patients.length }})
55
+ </button>
56
+ <button
57
+ :class="['tab-btn', filterBed === 'General Ward' ? 'tab-active' : '']"
58
+ @click="filterBed = 'General Ward'"
59
+ >
60
+ General Ward
61
+ </button>
62
+ <button
63
+ :class="['tab-btn', filterBed === 'ICU' ? 'tab-active' : '']"
64
+ @click="filterBed = 'ICU'"
65
+ >
66
+ ICU
67
+ </button>
68
+ </div>
69
+ </div>
70
+
71
+ <div v-if="filteredPatients.length === 0" class="empty-state">
72
+ <p>No admitted patients found matching current criteria.</p>
73
+ </div>
74
+
75
+ <div v-else class="table-container">
76
+ <table class="patient-table">
77
+ <thead>
78
+ <tr>
79
+ <th>Patient</th>
80
+ <th>Age</th>
81
+ <th>Bed Type</th>
82
+ <th>Doctor</th>
83
+ <th>Vitals (BP / HR / Temp)</th>
84
+ <th>Risk Level</th>
85
+ <th>Bill ($)</th>
86
+ <th>Actions</th>
87
+ </tr>
88
+ </thead>
89
+ <tbody>
90
+ <tr v-for="patient in filteredPatients" :key="patient.id">
91
+ <td class="font-bold">{{ patient.name }}</td>
92
+ <td>{{ patient.age }} yrs</td>
93
+ <td>
94
+ <span :class="['bed-badge', patient.bedType === 'ICU' ? 'bed-icu' : 'bed-general']">
95
+ {{ patient.bedType }}
96
+ </span>
97
+ </td>
98
+ <td>{{ patient.doctor }}</td>
99
+ <td>
100
+ <div class="vitals-chip">
101
+ <span>BP: {{ patient.vitals.bp }}</span>
102
+ <span>HR: {{ patient.vitals.hr }} bpm</span>
103
+ <span>{{ patient.vitals.temp }}°F</span>
104
+ </div>
105
+ </td>
106
+ <td>
107
+ <span :class="['risk-badge', 'risk-' + (patient.risk ? patient.risk.toLowerCase() : 'normal')]">
108
+ {{ patient.risk || 'Normal' }}
109
+ </span>
110
+ </td>
111
+ <td class="bill-cell">${{ patient.bill }}</td>
112
+ <td>
113
+ <button
114
+ class="btn-discharge"
115
+ @click="handleDischarge(patient.id, patient.name)"
116
+ >
117
+ Discharge
118
+ </button>
119
+ </td>
120
+ </tr>
121
+ </tbody>
122
+ </table>
123
+ </div>
124
+ </div>
125
+ </template>
126
+
127
+ <style scoped>
128
+ .patient-list-page {
129
+ display: flex;
130
+ flex-direction: column;
131
+ gap: 16px;
132
+ }
133
+
134
+ .header-row {
135
+ display: flex;
136
+ justify-content: space-between;
137
+ align-items: center;
138
+ }
139
+
140
+ h2 {
141
+ margin: 0;
142
+ font-size: 20px;
143
+ color: #1a202c;
144
+ }
145
+
146
+ .subtitle {
147
+ margin: 4px 0 0 0;
148
+ font-size: 13px;
149
+ color: #718096;
150
+ }
151
+
152
+ .btn-admit-link {
153
+ background-color: #2b6cb0;
154
+ color: white;
155
+ text-decoration: none;
156
+ font-size: 13px;
157
+ font-weight: 600;
158
+ padding: 8px 14px;
159
+ border-radius: 4px;
160
+ }
161
+
162
+ .alert-info {
163
+ background-color: #ebf8ff;
164
+ color: #2b6cb0;
165
+ border: 1px solid #bee3f8;
166
+ padding: 10px 14px;
167
+ border-radius: 4px;
168
+ font-size: 14px;
169
+ }
170
+
171
+ .filter-bar {
172
+ display: flex;
173
+ justify-content: space-between;
174
+ gap: 15px;
175
+ flex-wrap: wrap;
176
+ align-items: center;
177
+ }
178
+
179
+ .search-input {
180
+ flex: 1;
181
+ min-width: 200px;
182
+ padding: 8px 12px;
183
+ border: 1px solid #cbd5e0;
184
+ border-radius: 5px;
185
+ font-size: 14px;
186
+ }
187
+
188
+ .filter-tabs {
189
+ display: flex;
190
+ gap: 6px;
191
+ }
192
+
193
+ .tab-btn {
194
+ padding: 6px 12px;
195
+ border: 1px solid #cbd5e0;
196
+ background-color: #ffffff;
197
+ border-radius: 4px;
198
+ cursor: pointer;
199
+ font-size: 13px;
200
+ color: #4a5568;
201
+ }
202
+
203
+ .tab-active {
204
+ background-color: #2b6cb0;
205
+ color: #ffffff;
206
+ border-color: #2b6cb0;
207
+ }
208
+
209
+ .empty-state {
210
+ background-color: #ffffff;
211
+ padding: 30px;
212
+ text-align: center;
213
+ border: 1px solid #e2e8f0;
214
+ border-radius: 6px;
215
+ color: #718096;
216
+ }
217
+
218
+ .table-container {
219
+ overflow-x: auto;
220
+ background-color: #ffffff;
221
+ border: 1px solid #e2e8f0;
222
+ border-radius: 6px;
223
+ }
224
+
225
+ .patient-table {
226
+ width: 100%;
227
+ border-collapse: collapse;
228
+ font-size: 13px;
229
+ text-align: left;
230
+ }
231
+
232
+ .patient-table th {
233
+ background-color: #f7fafc;
234
+ color: #4a5568;
235
+ font-weight: 700;
236
+ padding: 12px 14px;
237
+ border-bottom: 2px solid #e2e8f0;
238
+ }
239
+
240
+ .patient-table td {
241
+ padding: 12px 14px;
242
+ border-bottom: 1px solid #edf2f7;
243
+ color: #2d3748;
244
+ }
245
+
246
+ .font-bold {
247
+ font-weight: 600;
248
+ }
249
+
250
+ .bed-badge {
251
+ font-size: 11px;
252
+ font-weight: 600;
253
+ padding: 3px 8px;
254
+ border-radius: 12px;
255
+ }
256
+
257
+ .bed-general {
258
+ background-color: #e2e8f0;
259
+ color: #2d3748;
260
+ }
261
+
262
+ .bed-icu {
263
+ background-color: #feebc8;
264
+ color: #c05621;
265
+ }
266
+
267
+ .vitals-chip {
268
+ display: flex;
269
+ gap: 8px;
270
+ font-size: 12px;
271
+ color: #4a5568;
272
+ }
273
+
274
+ .risk-badge {
275
+ font-size: 11px;
276
+ font-weight: 700;
277
+ padding: 3px 8px;
278
+ border-radius: 12px;
279
+ text-transform: uppercase;
280
+ }
281
+
282
+ .risk-high {
283
+ background-color: #fed7d7;
284
+ color: #9b2c2c;
285
+ }
286
+
287
+ .risk-moderate {
288
+ background-color: #feebc8;
289
+ color: #c05621;
290
+ }
291
+
292
+ .risk-normal {
293
+ background-color: #c6f6d5;
294
+ color: #22543d;
295
+ }
296
+
297
+ .bill-cell {
298
+ font-weight: 600;
299
+ }
300
+
301
+ .btn-discharge {
302
+ background-color: #e53e3e;
303
+ color: #ffffff;
304
+ border: none;
305
+ padding: 6px 12px;
306
+ border-radius: 4px;
307
+ font-size: 12px;
308
+ font-weight: 600;
309
+ cursor: pointer;
310
+ }
311
+
312
+ .btn-discharge:hover {
313
+ background-color: #c53030;
314
+ }
315
+ </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>Vue Library System</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,20 @@
1
+ {
2
+ "name": "vue-library-system",
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
+ "pinia": "^4.1.0",
13
+ "vue": "^3.5.44",
14
+ "vue-router": "^5.4.0"
15
+ },
16
+ "devDependencies": {
17
+ "@vitejs/plugin-vue": "^6.0.10",
18
+ "vite": "^8.3.4"
19
+ }
20
+ }
@@ -0,0 +1,91 @@
1
+ <script setup>
2
+ </script>
3
+
4
+ <template>
5
+ <div class="app-layout">
6
+ <header class="app-header">
7
+ <div class="brand">
8
+ <h1 class="brand-title">Library Management System</h1>
9
+ </div>
10
+ <nav class="nav-links">
11
+ <router-link to="/">Catalog</router-link>
12
+ <router-link to="/members">Members</router-link>
13
+ <router-link to="/loans">Issue/Return Loans</router-link>
14
+ </nav>
15
+ </header>
16
+
17
+ <main class="content-container">
18
+ <router-view />
19
+ </main>
20
+ </div>
21
+ </template>
22
+
23
+ <style>
24
+ * {
25
+ box-sizing: border-box;
26
+ }
27
+
28
+ body {
29
+ margin: 0;
30
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
31
+ color: #1e293b;
32
+ background-color: #f1f5f9;
33
+ }
34
+ </style>
35
+
36
+ <style scoped>
37
+ .app-layout {
38
+ min-height: 100vh;
39
+ display: flex;
40
+ flex-direction: column;
41
+ }
42
+
43
+ .app-header {
44
+ background-color: #0f172a;
45
+ color: white;
46
+ padding: 16px 32px;
47
+ display: flex;
48
+ justify-content: space-between;
49
+ align-items: center;
50
+ border-bottom: 2px solid #1e293b;
51
+ }
52
+
53
+ .brand-title {
54
+ margin: 0;
55
+ font-size: 18px;
56
+ font-weight: 700;
57
+ letter-spacing: -0.025em;
58
+ }
59
+
60
+ .nav-links {
61
+ display: flex;
62
+ gap: 12px;
63
+ }
64
+
65
+ .nav-links a {
66
+ color: #94a3b8;
67
+ text-decoration: none;
68
+ font-size: 14px;
69
+ font-weight: 500;
70
+ padding: 8px 14px;
71
+ border-radius: 6px;
72
+ transition: all 0.2s ease;
73
+ }
74
+
75
+ .nav-links a:hover {
76
+ color: #f8fafc;
77
+ background-color: #1e293b;
78
+ }
79
+
80
+ .nav-links a.router-link-active {
81
+ color: white;
82
+ background-color: #2563eb;
83
+ }
84
+
85
+ .content-container {
86
+ max-width: 1000px;
87
+ width: 100%;
88
+ margin: 28px auto;
89
+ padding: 0 20px;
90
+ }
91
+ </style>
@@ -0,0 +1,9 @@
1
+ import { createApp } from 'vue'
2
+ import { createPinia } from 'pinia'
3
+ import App from './App.vue'
4
+ import router from './router'
5
+
6
+ const app = createApp(App)
7
+ app.use(createPinia())
8
+ app.use(router)
9
+ app.mount('#app')
@@ -0,0 +1,29 @@
1
+ import { createRouter, createWebHistory } from 'vue-router'
2
+ import BookCatalogView from '../views/BookCatalogView.vue'
3
+ import MembershipView from '../views/MembershipView.vue'
4
+ import LoanManagerView from '../views/LoanManagerView.vue'
5
+
6
+ const routes = [
7
+ {
8
+ path: '/',
9
+ name: 'Catalog',
10
+ component: BookCatalogView
11
+ },
12
+ {
13
+ path: '/members',
14
+ name: 'Members',
15
+ component: MembershipView
16
+ },
17
+ {
18
+ path: '/loans',
19
+ name: 'Loans',
20
+ component: LoanManagerView
21
+ }
22
+ ]
23
+
24
+ const router = createRouter({
25
+ history: createWebHistory(),
26
+ routes
27
+ })
28
+
29
+ export default router
@@ -0,0 +1,87 @@
1
+ import { defineStore } from 'pinia'
2
+
3
+ export const useLibraryStore = defineStore('library', {
4
+ state: () => ({
5
+ books: [
6
+ { id: 1, title: 'Clean Code', author: 'Robert C. Martin', isbn: '978-0132350884', copies: 3, category: 'Computer Science' },
7
+ { id: 2, title: 'JavaScript: The Good Parts', author: 'Douglas Crockford', isbn: '978-0596517748', copies: 2, category: 'Web Dev' },
8
+ { id: 3, title: 'Introduction to Algorithms', author: 'CLRS', isbn: '978-0262033848', copies: 1, category: 'Algorithms' }
9
+ ],
10
+ members: [
11
+ { id: 'MEM-101', name: 'David Miller', email: 'david@example.com', membershipType: 'Premium', borrowedBooks: [] }
12
+ ],
13
+ borrowedRecords: [
14
+ { id: 1, memberId: 'MEM-101', bookTitle: 'Clean Code', issueDate: '2026-10-01', returnDue: '2026-10-15', fine: 0, returned: false }
15
+ ]
16
+ }),
17
+ getters: {
18
+ availableBooks: (state) => state.books.filter((b) => b.copies > 0),
19
+ activeLoansCount: (state) => state.borrowedRecords.filter((r) => !r.returned).length,
20
+ totalFines: (state) => state.borrowedRecords.reduce((sum, r) => sum + (r.fine || 0), 0)
21
+ },
22
+ actions: {
23
+ registerMember(member) {
24
+ const newMember = {
25
+ id: member.id || `MEM-${100 + this.members.length + 1}`,
26
+ name: member.name,
27
+ email: member.email,
28
+ membershipType: member.membershipType || 'Standard',
29
+ borrowedBooks: []
30
+ }
31
+ this.members.push(newMember)
32
+ return newMember
33
+ },
34
+ issueBook(bookId, memberId) {
35
+ const book = this.books.find((b) => b.id === Number(bookId))
36
+ const member = this.members.find((m) => m.id === memberId)
37
+ if (!book || book.copies <= 0 || !member) {
38
+ return false
39
+ }
40
+ book.copies--
41
+ const today = new Date()
42
+ const issueDate = today.toISOString().split('T')[0]
43
+ const due = new Date(today)
44
+ due.setDate(due.getDate() + 14)
45
+ const returnDue = due.toISOString().split('T')[0]
46
+
47
+ const record = {
48
+ id: Date.now(),
49
+ memberId: member.id,
50
+ bookTitle: book.title,
51
+ issueDate,
52
+ returnDue,
53
+ fine: 0,
54
+ returned: false
55
+ }
56
+ this.borrowedRecords.push(record)
57
+ if (!member.borrowedBooks) {
58
+ member.borrowedBooks = []
59
+ }
60
+ member.borrowedBooks.push(book.title)
61
+ return true
62
+ },
63
+ returnBook(recordId, daysLate = 0) {
64
+ const record = this.borrowedRecords.find((r) => r.id === Number(recordId))
65
+ if (!record || record.returned) {
66
+ return false
67
+ }
68
+ const late = Math.max(0, Number(daysLate) || 0)
69
+ record.fine = late * 2
70
+ record.returned = true
71
+
72
+ const book = this.books.find((b) => b.title === record.bookTitle)
73
+ if (book) {
74
+ book.copies++
75
+ }
76
+
77
+ const member = this.members.find((m) => m.id === record.memberId)
78
+ if (member && Array.isArray(member.borrowedBooks)) {
79
+ const index = member.borrowedBooks.indexOf(record.bookTitle)
80
+ if (index !== -1) {
81
+ member.borrowedBooks.splice(index, 1)
82
+ }
83
+ }
84
+ return true
85
+ }
86
+ }
87
+ })