wad-lab 1.0.9 → 1.1.1

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 (70) hide show
  1. package/bin/index.js +13 -5
  2. package/package.json +1 -1
  3. package/templates/servlet-session-tracking/WEB-INF/LoginServlet.java +46 -0
  4. package/templates/servlet-session-tracking/WEB-INF/LogoutServlet.java +39 -0
  5. package/templates/servlet-session-tracking/WEB-INF/ProfileServlet.java +83 -0
  6. package/templates/servlet-session-tracking/WEB-INF/classes/LoginServlet.class +0 -0
  7. package/templates/servlet-session-tracking/WEB-INF/classes/LogoutServlet.class +0 -0
  8. package/templates/servlet-session-tracking/WEB-INF/classes/ProfileServlet.class +0 -0
  9. package/templates/servlet-session-tracking/WEB-INF/web.xml +38 -0
  10. package/templates/servlet-session-tracking/index.html +36 -0
  11. package/templates/springboot-hospital-api/.mvn/wrapper/maven-wrapper.properties +3 -0
  12. package/templates/springboot-hospital-api/mvnw +295 -0
  13. package/templates/springboot-hospital-api/mvnw.cmd +189 -0
  14. package/templates/springboot-hospital-api/pom.xml +41 -0
  15. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/HospitalApplication.java +12 -0
  16. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/controller/HospitalController.java +50 -0
  17. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/model/Appointment.java +95 -0
  18. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/repository/AppointmentRepository.java +15 -0
  19. package/templates/springboot-hospital-api/src/main/java/com/example/hospital/service/HospitalService.java +54 -0
  20. package/templates/springboot-hospital-api/src/main/resources/application.properties +3 -0
  21. package/templates/springboot-hospital-api/src/test/java/com/example/hospital/HospitalApplicationTests.java +12 -0
  22. package/templates/springboot-library-api/.mvn/wrapper/maven-wrapper.properties +3 -0
  23. package/templates/springboot-library-api/mvnw +295 -0
  24. package/templates/springboot-library-api/mvnw.cmd +189 -0
  25. package/templates/springboot-library-api/pom.xml +42 -0
  26. package/templates/springboot-library-api/src/main/java/com/example/library/LibraryApplication.java +12 -0
  27. package/templates/springboot-library-api/src/main/java/com/example/library/controller/LibraryController.java +51 -0
  28. package/templates/springboot-library-api/src/main/java/com/example/library/model/Book.java +76 -0
  29. package/templates/springboot-library-api/src/main/java/com/example/library/model/CategoryAnalytics.java +41 -0
  30. package/templates/springboot-library-api/src/main/java/com/example/library/repository/BookRepository.java +13 -0
  31. package/templates/springboot-library-api/src/main/java/com/example/library/service/LibraryService.java +60 -0
  32. package/templates/springboot-library-api/src/main/resources/application.properties +3 -0
  33. package/templates/vue-game-rps/index.html +12 -0
  34. package/templates/vue-game-rps/package.json +19 -0
  35. package/templates/vue-game-rps/src/App.vue +125 -0
  36. package/templates/vue-game-rps/src/main.js +5 -0
  37. package/templates/vue-game-rps/src/stores/rpsStore.js +43 -0
  38. package/templates/vue-game-rps/vite.config.js +6 -0
  39. package/templates/vue-game-tictactoe/index.html +12 -0
  40. package/templates/vue-game-tictactoe/package.json +19 -0
  41. package/templates/vue-game-tictactoe/src/App.vue +105 -0
  42. package/templates/vue-game-tictactoe/src/main.js +5 -0
  43. package/templates/vue-game-tictactoe/src/stores/tictactoeStore.js +61 -0
  44. package/templates/vue-game-tictactoe/vite.config.js +6 -0
  45. package/templates/vue-game-whackamole/index.html +12 -0
  46. package/templates/vue-game-whackamole/package.json +19 -0
  47. package/templates/vue-game-whackamole/src/App.vue +104 -0
  48. package/templates/vue-game-whackamole/src/main.js +7 -0
  49. package/templates/vue-game-whackamole/src/stores/moleStore.js +71 -0
  50. package/templates/vue-game-whackamole/vite.config.js +6 -0
  51. package/templates/vue-hospital-portal/index.html +12 -0
  52. package/templates/vue-hospital-portal/package.json +20 -0
  53. package/templates/vue-hospital-portal/src/App.vue +107 -0
  54. package/templates/vue-hospital-portal/src/main.js +9 -0
  55. package/templates/vue-hospital-portal/src/router/index.js +17 -0
  56. package/templates/vue-hospital-portal/src/stores/hospitalStore.js +91 -0
  57. package/templates/vue-hospital-portal/src/views/HospitalBillingView.vue +271 -0
  58. package/templates/vue-hospital-portal/src/views/OPDRegistrationView.vue +453 -0
  59. package/templates/vue-hospital-portal/src/views/PatientListView.vue +315 -0
  60. package/templates/vue-hospital-portal/vite.config.js +6 -0
  61. package/templates/vue-library-system/index.html +12 -0
  62. package/templates/vue-library-system/package.json +20 -0
  63. package/templates/vue-library-system/src/App.vue +91 -0
  64. package/templates/vue-library-system/src/main.js +9 -0
  65. package/templates/vue-library-system/src/router/index.js +29 -0
  66. package/templates/vue-library-system/src/stores/libraryStore.js +87 -0
  67. package/templates/vue-library-system/src/views/BookCatalogView.vue +432 -0
  68. package/templates/vue-library-system/src/views/LoanManagerView.vue +296 -0
  69. package/templates/vue-library-system/src/views/MembershipView.vue +269 -0
  70. package/templates/vue-library-system/vite.config.js +6 -0
@@ -0,0 +1,41 @@
1
+ package com.example.library.model;
2
+
3
+ public class CategoryAnalytics {
4
+
5
+ private String category;
6
+ private int totalCopies;
7
+ private double averagePrice;
8
+
9
+ public CategoryAnalytics() {
10
+ }
11
+
12
+ public CategoryAnalytics(String category, int totalCopies, double averagePrice) {
13
+ this.category = category;
14
+ this.totalCopies = totalCopies;
15
+ this.averagePrice = averagePrice;
16
+ }
17
+
18
+ public String getCategory() {
19
+ return category;
20
+ }
21
+
22
+ public void setCategory(String category) {
23
+ this.category = category;
24
+ }
25
+
26
+ public int getTotalCopies() {
27
+ return totalCopies;
28
+ }
29
+
30
+ public void setTotalCopies(int totalCopies) {
31
+ this.totalCopies = totalCopies;
32
+ }
33
+
34
+ public double getAveragePrice() {
35
+ return averagePrice;
36
+ }
37
+
38
+ public void setAveragePrice(double averagePrice) {
39
+ this.averagePrice = averagePrice;
40
+ }
41
+ }
@@ -0,0 +1,13 @@
1
+ package com.example.library.repository;
2
+
3
+ import com.example.library.model.Book;
4
+ import org.springframework.data.mongodb.repository.MongoRepository;
5
+ import org.springframework.stereotype.Repository;
6
+
7
+ import java.util.List;
8
+
9
+ @Repository
10
+ public interface BookRepository extends MongoRepository<Book, String> {
11
+ List<Book> findByCategory(String category);
12
+ List<Book> findByAuthor(String author);
13
+ }
@@ -0,0 +1,60 @@
1
+ package com.example.library.service;
2
+
3
+ import com.example.library.model.Book;
4
+ import com.example.library.model.CategoryAnalytics;
5
+ import com.example.library.repository.BookRepository;
6
+ import org.springframework.data.mongodb.core.MongoTemplate;
7
+ import org.springframework.data.mongodb.core.aggregation.Aggregation;
8
+ import org.springframework.data.mongodb.core.aggregation.AggregationResults;
9
+ import org.springframework.stereotype.Service;
10
+
11
+ import java.util.List;
12
+ import java.util.Optional;
13
+
14
+ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
15
+
16
+ @Service
17
+ public class LibraryService {
18
+
19
+ private final BookRepository bookRepository;
20
+ private final MongoTemplate mongoTemplate;
21
+
22
+ public LibraryService(BookRepository bookRepository, MongoTemplate mongoTemplate) {
23
+ this.bookRepository = bookRepository;
24
+ this.mongoTemplate = mongoTemplate;
25
+ }
26
+
27
+ public List<Book> getAllBooks() {
28
+ return bookRepository.findAll();
29
+ }
30
+
31
+ public Optional<Book> getBookById(String id) {
32
+ return bookRepository.findById(id);
33
+ }
34
+
35
+ public Book addBook(Book book) {
36
+ return bookRepository.save(book);
37
+ }
38
+
39
+ public void deleteBook(String id) {
40
+ bookRepository.deleteById(id);
41
+ }
42
+
43
+ public List<CategoryAnalytics> getCategoryAnalytics() {
44
+ Aggregation aggregation = newAggregation(
45
+ group("category")
46
+ .sum("totalCopies").as("totalCopies")
47
+ .avg("price").as("averagePrice"),
48
+ project("totalCopies", "averagePrice")
49
+ .and("_id").as("category")
50
+ );
51
+
52
+ AggregationResults<CategoryAnalytics> results = mongoTemplate.aggregate(
53
+ aggregation,
54
+ "books",
55
+ CategoryAnalytics.class
56
+ );
57
+
58
+ return results.getMappedResults();
59
+ }
60
+ }
@@ -0,0 +1,3 @@
1
+ spring.data.mongodb.uri=mongodb://localhost:27017/library_db
2
+ spring.data.mongodb.database=library_db
3
+ server.port=8080
@@ -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 Rock Paper Scissors</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,19 @@
1
+ {
2
+ "name": "vue-game-rps",
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
+ },
15
+ "devDependencies": {
16
+ "@vitejs/plugin-vue": "^6.0.10",
17
+ "vite": "^8.3.4"
18
+ }
19
+ }
@@ -0,0 +1,125 @@
1
+ <template>
2
+ <div class="container">
3
+ <h1>Vue Rock Paper Scissors</h1>
4
+
5
+ <div class="scoreboard">
6
+ <div class="score-card">
7
+ <span class="label">Player:</span>
8
+ <span class="value">{{ store.playerScore }}</span>
9
+ </div>
10
+ <div class="score-card">
11
+ <span class="label">Computer:</span>
12
+ <span class="value">{{ store.computerScore }}</span>
13
+ </div>
14
+ <div class="score-card">
15
+ <span class="label">Ties:</span>
16
+ <span class="value">{{ store.ties }}</span>
17
+ </div>
18
+ </div>
19
+
20
+ <div class="choices">
21
+ <button @click="store.playRound('Rock')">✊ Rock</button>
22
+ <button @click="store.playRound('Paper')">✋ Paper</button>
23
+ <button @click="store.playRound('Scissors')">✌ Scissors</button>
24
+ </div>
25
+
26
+ <div class="results">
27
+ <div v-if="store.playerChoice && store.computerChoice" class="matchup">
28
+ <p>Player: <strong>{{ store.playerChoice }}</strong></p>
29
+ <p>Computer: <strong>{{ store.computerChoice }}</strong></p>
30
+ </div>
31
+ <p class="message">{{ store.resultMessage }}</p>
32
+ </div>
33
+
34
+ <button class="reset-btn" @click="store.resetGame">Reset Game</button>
35
+ </div>
36
+ </template>
37
+
38
+ <script setup>
39
+ import { useRpsStore } from './stores/rpsStore'
40
+
41
+ const store = useRpsStore()
42
+ </script>
43
+
44
+ <style scoped>
45
+ .container {
46
+ max-width: 500px;
47
+ margin: 40px auto;
48
+ padding: 20px;
49
+ text-align: center;
50
+ font-family: Arial, sans-serif;
51
+ }
52
+
53
+ .scoreboard {
54
+ display: flex;
55
+ justify-content: space-around;
56
+ margin: 20px 0;
57
+ padding: 12px;
58
+ background: #f0f0f0;
59
+ border-radius: 6px;
60
+ }
61
+
62
+ .score-card {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 4px;
66
+ }
67
+
68
+ .label {
69
+ font-weight: bold;
70
+ }
71
+
72
+ .value {
73
+ font-size: 1.4rem;
74
+ }
75
+
76
+ .choices {
77
+ display: flex;
78
+ justify-content: center;
79
+ gap: 12px;
80
+ margin: 20px 0;
81
+ }
82
+
83
+ button {
84
+ padding: 10px 16px;
85
+ font-size: 1rem;
86
+ cursor: pointer;
87
+ border: 1px solid #ccc;
88
+ border-radius: 4px;
89
+ background: #fff;
90
+ }
91
+
92
+ button:hover {
93
+ background: #e9e9e9;
94
+ }
95
+
96
+ .results {
97
+ margin: 20px 0;
98
+ padding: 15px;
99
+ border: 1px solid #ddd;
100
+ border-radius: 6px;
101
+ background: #fafafa;
102
+ }
103
+
104
+ .matchup {
105
+ display: flex;
106
+ justify-content: space-around;
107
+ margin-bottom: 10px;
108
+ }
109
+
110
+ .message {
111
+ font-size: 1.2rem;
112
+ font-weight: bold;
113
+ margin: 5px 0 0;
114
+ }
115
+
116
+ .reset-btn {
117
+ background: #e74c3c;
118
+ color: #fff;
119
+ border: none;
120
+ }
121
+
122
+ .reset-btn:hover {
123
+ background: #c0392b;
124
+ }
125
+ </style>
@@ -0,0 +1,5 @@
1
+ import { createApp } from 'vue'
2
+ import { createPinia } from 'pinia'
3
+ import App from './App.vue'
4
+
5
+ createApp(App).use(createPinia()).mount('#app')
@@ -0,0 +1,43 @@
1
+ import { defineStore } from 'pinia'
2
+
3
+ export const useRpsStore = defineStore('rps', {
4
+ state: () => ({
5
+ choices: ['Rock', 'Paper', 'Scissors'],
6
+ playerScore: 0,
7
+ computerScore: 0,
8
+ ties: 0,
9
+ playerChoice: null,
10
+ computerChoice: null,
11
+ resultMessage: 'Make your choice to play!'
12
+ }),
13
+ actions: {
14
+ playRound(choice) {
15
+ this.playerChoice = choice
16
+ const randomIndex = Math.floor(Math.random() * this.choices.length)
17
+ this.computerChoice = this.choices[randomIndex]
18
+
19
+ if (this.playerChoice === this.computerChoice) {
20
+ this.ties++
21
+ this.resultMessage = "It's a tie!"
22
+ } else if (
23
+ (this.playerChoice === 'Rock' && this.computerChoice === 'Scissors') ||
24
+ (this.playerChoice === 'Paper' && this.computerChoice === 'Rock') ||
25
+ (this.playerChoice === 'Scissors' && this.computerChoice === 'Paper')
26
+ ) {
27
+ this.playerScore++
28
+ this.resultMessage = 'You win!'
29
+ } else {
30
+ this.computerScore++
31
+ this.resultMessage = 'Computer wins!'
32
+ }
33
+ },
34
+ resetGame() {
35
+ this.playerScore = 0
36
+ this.computerScore = 0
37
+ this.ties = 0
38
+ this.playerChoice = null
39
+ this.computerChoice = null
40
+ this.resultMessage = 'Make your choice to play!'
41
+ }
42
+ }
43
+ })
@@ -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 Tic Tac Toe</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,19 @@
1
+ {
2
+ "name": "vue-game-tictactoe",
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
+ },
15
+ "devDependencies": {
16
+ "@vitejs/plugin-vue": "^6.0.10",
17
+ "vite": "^8.3.4"
18
+ }
19
+ }
@@ -0,0 +1,105 @@
1
+ <script setup>
2
+ import { useTicTacToeStore } from './stores/tictactoeStore'
3
+
4
+ const store = useTicTacToeStore()
5
+ </script>
6
+
7
+ <template>
8
+ <div class="game-container">
9
+ <h1>Vue Tic Tac Toe</h1>
10
+
11
+ <div class="status">
12
+ <span v-if="store.winner">Player {{ store.winner }} Wins! 🎉</span>
13
+ <span v-else-if="store.isDraw">Game Draw! 🤝</span>
14
+ <span v-else>Player {{ store.currentPlayer }}'s Turn</span>
15
+ </div>
16
+
17
+ <div class="board">
18
+ <button
19
+ v-for="(cell, index) in store.board"
20
+ :key="index"
21
+ type="button"
22
+ class="cell"
23
+ :disabled="cell !== '' || !!store.winner || store.isDraw"
24
+ @click="store.makeMove(index)"
25
+ >
26
+ {{ cell }}
27
+ </button>
28
+ </div>
29
+
30
+ <button type="button" class="btn-reset" @click="store.resetBoard">Reset Game</button>
31
+ </div>
32
+ </template>
33
+
34
+ <style>
35
+ body {
36
+ font-family: Arial, sans-serif;
37
+ display: flex;
38
+ justify-content: center;
39
+ align-items: center;
40
+ min-height: 100vh;
41
+ margin: 0;
42
+ background-color: #f5f5f5;
43
+ }
44
+
45
+ .game-container {
46
+ text-align: center;
47
+ background: #ffffff;
48
+ padding: 30px;
49
+ border: 1px solid #ccc;
50
+ border-radius: 8px;
51
+ }
52
+
53
+ h1 {
54
+ margin-top: 0;
55
+ }
56
+
57
+ .status {
58
+ margin: 15px 0;
59
+ font-size: 20px;
60
+ font-weight: bold;
61
+ }
62
+
63
+ .board {
64
+ display: grid;
65
+ grid-template-columns: repeat(3, 80px);
66
+ gap: 8px;
67
+ margin: 20px auto;
68
+ width: 256px;
69
+ }
70
+
71
+ .cell {
72
+ width: 80px;
73
+ height: 80px;
74
+ background-color: #f9f9f9;
75
+ border: 2px solid #555;
76
+ font-size: 36px;
77
+ font-weight: bold;
78
+ cursor: pointer;
79
+ display: flex;
80
+ justify-content: center;
81
+ align-items: center;
82
+ }
83
+
84
+ .cell:hover:not(:disabled) {
85
+ background-color: #eee;
86
+ }
87
+
88
+ .cell:disabled {
89
+ cursor: not-allowed;
90
+ }
91
+
92
+ .btn-reset {
93
+ padding: 10px 20px;
94
+ font-size: 16px;
95
+ background-color: #333;
96
+ color: white;
97
+ border: none;
98
+ border-radius: 4px;
99
+ cursor: pointer;
100
+ }
101
+
102
+ .btn-reset:hover {
103
+ background-color: #555;
104
+ }
105
+ </style>
@@ -0,0 +1,5 @@
1
+ import { createApp } from 'vue'
2
+ import { createPinia } from 'pinia'
3
+ import App from './App.vue'
4
+
5
+ createApp(App).use(createPinia()).mount('#app')
@@ -0,0 +1,61 @@
1
+ import { defineStore } from 'pinia'
2
+
3
+ export const useTicTacToeStore = defineStore('tictactoe', {
4
+ state: () => ({
5
+ board: Array(9).fill(''),
6
+ currentPlayer: 'X',
7
+ winner: null,
8
+ isDraw: false,
9
+ winningConditions: [
10
+ [0, 1, 2],
11
+ [3, 4, 5],
12
+ [6, 7, 8],
13
+ [0, 3, 6],
14
+ [1, 4, 7],
15
+ [2, 5, 8],
16
+ [0, 4, 8],
17
+ [2, 4, 6]
18
+ ]
19
+ }),
20
+ actions: {
21
+ checkWin() {
22
+ for (const [a, b, c] of this.winningConditions) {
23
+ if (this.board[a] && this.board[a] === this.board[b] && this.board[b] === this.board[c]) {
24
+ this.winner = this.currentPlayer
25
+ return true
26
+ }
27
+ }
28
+ return false
29
+ },
30
+ checkDraw() {
31
+ if (!this.board.includes('')) {
32
+ this.isDraw = true
33
+ return true
34
+ }
35
+ return false
36
+ },
37
+ makeMove(index) {
38
+ if (this.board[index] !== '' || this.winner || this.isDraw) {
39
+ return
40
+ }
41
+
42
+ this.board[index] = this.currentPlayer
43
+
44
+ if (this.checkWin()) {
45
+ return
46
+ }
47
+
48
+ if (this.checkDraw()) {
49
+ return
50
+ }
51
+
52
+ this.currentPlayer = this.currentPlayer === 'X' ? 'O' : 'X'
53
+ },
54
+ resetBoard() {
55
+ this.board = Array(9).fill('')
56
+ this.currentPlayer = 'X'
57
+ this.winner = null
58
+ this.isDraw = false
59
+ }
60
+ }
61
+ })
@@ -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 Whack A Mole</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,19 @@
1
+ {
2
+ "name": "vue-game-whackamole",
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
+ },
15
+ "devDependencies": {
16
+ "@vitejs/plugin-vue": "^5.2.1",
17
+ "vite": "^6.0.0"
18
+ }
19
+ }
@@ -0,0 +1,104 @@
1
+ <template>
2
+ <div class="game-container">
3
+ <h1>Vue Whack A Mole</h1>
4
+
5
+ <div class="status-bar">
6
+ <span>Score: {{ store.score }}</span>
7
+ <span>Time Left: {{ store.timeLeft }}s</span>
8
+ </div>
9
+
10
+ <button class="start-btn" :disabled="store.isPlaying" @click="store.startGame()">
11
+ Start Game
12
+ </button>
13
+
14
+ <div class="grid">
15
+ <div
16
+ v-for="i in 9"
17
+ :key="i - 1"
18
+ class="hole"
19
+ @click="store.whackMole(i - 1)"
20
+ >
21
+ <span v-if="store.activeHoleIndex === i - 1" class="mole">🐹</span>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <script setup>
28
+ import { useMoleStore } from './stores/moleStore'
29
+
30
+ const store = useMoleStore()
31
+ </script>
32
+
33
+ <style>
34
+ body {
35
+ margin: 0;
36
+ font-family: sans-serif;
37
+ display: flex;
38
+ justify-content: center;
39
+ align-items: center;
40
+ min-height: 100vh;
41
+ background-color: #f0f2f5;
42
+ }
43
+
44
+ .game-container {
45
+ text-align: center;
46
+ background: #ffffff;
47
+ padding: 24px;
48
+ border-radius: 12px;
49
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
50
+ width: 320px;
51
+ }
52
+
53
+ h1 {
54
+ margin-top: 0;
55
+ margin-bottom: 16px;
56
+ font-size: 24px;
57
+ }
58
+
59
+ .status-bar {
60
+ display: flex;
61
+ justify-content: space-between;
62
+ margin-bottom: 16px;
63
+ font-size: 16px;
64
+ font-weight: bold;
65
+ }
66
+
67
+ .start-btn {
68
+ padding: 10px 20px;
69
+ font-size: 16px;
70
+ background-color: #42b883;
71
+ color: white;
72
+ border: none;
73
+ border-radius: 6px;
74
+ cursor: pointer;
75
+ margin-bottom: 20px;
76
+ }
77
+
78
+ .start-btn:disabled {
79
+ background-color: #a8d5c2;
80
+ cursor: not-allowed;
81
+ }
82
+
83
+ .grid {
84
+ display: grid;
85
+ grid-template-columns: repeat(3, 1fr);
86
+ gap: 12px;
87
+ }
88
+
89
+ .hole {
90
+ width: 80px;
91
+ height: 80px;
92
+ background-color: #795548;
93
+ border-radius: 50%;
94
+ display: flex;
95
+ justify-content: center;
96
+ align-items: center;
97
+ cursor: pointer;
98
+ user-select: none;
99
+ }
100
+
101
+ .mole {
102
+ font-size: 40px;
103
+ }
104
+ </style>