Enha: attempt to do modal popup of clue; must be a better way
This commit is contained in:
		| @@ -45,3 +45,25 @@ tr{ | |||||||
|     border: 1px solid black; |     border: 1px solid black; | ||||||
|     background-color: darkorange; |     background-color: darkorange; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @keyframes fadeInDown { | ||||||
|  |   from { | ||||||
|  |     opacity: 0; | ||||||
|  |     transform: translateY(-1rem); | ||||||
|  |   } | ||||||
|  |   to { | ||||||
|  |     opacity: 1; | ||||||
|  |     transform: translateY(0); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @keyframes fadeOutUp { | ||||||
|  |   from { | ||||||
|  |     opacity: 1; | ||||||
|  |     transform: translateY(0); | ||||||
|  |   } | ||||||
|  |   to { | ||||||
|  |     opacity: 0; | ||||||
|  |     transform: translateY(-1rem); | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										53
									
								
								components/cluepopup.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								components/cluepopup.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | {{define "cluepopup"}} | ||||||
|  | <div hx-sse="swap:newClue" hx-swap="none" | ||||||
|  |     _="on htmx:sseMessage(mimeclue_{{.ID}}) | ||||||
|  |           -- Update content | ||||||
|  |         set match to event.detail.match(/(.*?)(\d+)$/) | ||||||
|  |           if match | ||||||
|  |             set clue to match[1] | ||||||
|  |             set number to match[2] | ||||||
|  |           else | ||||||
|  |             set clue to 'Invalid clue' | ||||||
|  |             set number to '0' | ||||||
|  |           end | ||||||
|  |            | ||||||
|  |           -- Cancel any previous timeout | ||||||
|  |           if window.clueTimeout then clearTimeout(window.clueTimeout) | ||||||
|  |            | ||||||
|  |           -- Show with animation | ||||||
|  |           remove .hidden from #clueModal | ||||||
|  |           remove .opacity-0.-translate-y-4 from #clueModal div | ||||||
|  |           add .opacity-100.translate-y-0 to #clueModal div | ||||||
|  |            | ||||||
|  |           -- Auto-hide after 3 seconds | ||||||
|  |           set window.clueTimeout to setTimeout(() =>  | ||||||
|  |             trigger closeModal | ||||||
|  |           end, 3000) | ||||||
|  |          | ||||||
|  |         on closeModal | ||||||
|  |           -- Hide with animation | ||||||
|  |           add .opacity-0.-translate-y-4 to #clueModal div | ||||||
|  |           wait 300ms | ||||||
|  |           add .hidden to #clueModal"> | ||||||
|  | <div id="clueModal"  | ||||||
|  |      class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full transition-opacity duration-300 ease-in-out"> | ||||||
|  |   <div class="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white  | ||||||
|  |               transform transition-all duration-300 ease-out  | ||||||
|  |               opacity-0 -translate-y-4"> | ||||||
|  |     <div class="mt-3 text-center"> | ||||||
|  |       <h3 class="text-lg leading-6 font-medium text-gray-900">New Clue Received! 🔍</h3> | ||||||
|  |       <div class="mt-2 px-7 py-3"> | ||||||
|  |         <p class="text-sm text-gray-500">Clue: <span id="modalClue" class="font-medium"></span></p> | ||||||
|  |         <p class="text-sm text-gray-500">Number: <span id="modalNumber" class="font-medium"></span></p> | ||||||
|  |       </div> | ||||||
|  |       <div class="items-center px-4 py-3"> | ||||||
|  |         <button _="on click trigger closeModal" | ||||||
|  |                 class="px-4 py-2 bg-green-500 text-white rounded-md hover:bg-green-700 transition-colors"> | ||||||
|  |           OK | ||||||
|  |         </button> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </div> | ||||||
|  | </div> | ||||||
|  | {{end}} | ||||||
| @@ -1,17 +1,21 @@ | |||||||
| {{define "mimeclue"}} | {{define "mimeclue"}} | ||||||
| <div class="flex gap-4 w-full"> | <div class="flex gap-4 w-full"> | ||||||
|  |     <form class="space-y-6" hx-post="/give-clue"> | ||||||
|         <input type="text"  |         <input type="text"  | ||||||
|                class="flex-1 px-4 py-2 text-lg border-2 border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" |                class="flex-1 px-4 py-2 text-lg border-2 border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" | ||||||
|  |                 name="clue" | ||||||
|                placeholder="Enter clue..." |                placeholder="Enter clue..." | ||||||
|                required> |                required> | ||||||
|         <input type="number"  |         <input type="number"  | ||||||
|                class="w-24 px-4 py-2 text-lg border-2 border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" |                class="w-24 px-4 py-2 text-lg border-2 border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" | ||||||
|                placeholder="Number"  |                placeholder="Number"  | ||||||
|            min="1"  |                 name="number" | ||||||
|  |                min="0"  | ||||||
|                max="9" |                max="9" | ||||||
|                required> |                required> | ||||||
|         <button type="submit" class="px-6 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors"> |         <button type="submit" class="px-6 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors"> | ||||||
|             Send |             Send | ||||||
|         </button> |         </button> | ||||||
|  |     </form> | ||||||
| </div> | </div> | ||||||
| {{end}} | {{end}} | ||||||
|   | |||||||
| @@ -45,5 +45,10 @@ | |||||||
|     {{template "mimeclue"}} |     {{template "mimeclue"}} | ||||||
|     {{end}} |     {{end}} | ||||||
|   </div> |   </div> | ||||||
|  |   <div> | ||||||
|  |   {{if .Room.MimeDone}} | ||||||
|  |   {{template "cluepop"}} | ||||||
|  |   {{end}} | ||||||
|  |   </div> | ||||||
| </div> | </div> | ||||||
| {{end}} | {{end}} | ||||||
|   | |||||||
| @@ -49,7 +49,10 @@ func HandleNameCheck(w http.ResponseWriter, r *http.Request) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | ||||||
| 	r.ParseForm() | 	if err := r.ParseForm(); err != nil { | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	username := r.PostFormValue("username") | 	username := r.PostFormValue("username") | ||||||
| 	if username == "" { | 	if username == "" { | ||||||
| 		msg := "username not provided" | 		msg := "username not provided" | ||||||
|   | |||||||
| @@ -240,3 +240,29 @@ func HandleJoinRoom(w http.ResponseWriter, r *http.Request) { | |||||||
| 	} | 	} | ||||||
| 	tmpl.ExecuteTemplate(w, "room", fi) | 	tmpl.ExecuteTemplate(w, "room", fi) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func HandleGiveClue(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	if err := r.ParseForm(); err != nil { | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	clue := r.PostFormValue("clue") | ||||||
|  | 	num := r.PostFormValue("number") | ||||||
|  | 	fi, err := getFullInfoByCtx(r.Context()) | ||||||
|  | 	if err != nil { | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	fi.Room.MimeDone = true | ||||||
|  | 	notify(models.NotifyMimePrefix+fi.Room.ID, clue+num) | ||||||
|  | 	if err := saveFullInfo(fi); err != nil { | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	// tmpl, err := template.ParseGlob("components/*.html") | ||||||
|  | 	// if err != nil { | ||||||
|  | 	// 	abortWithError(w, err.Error()) | ||||||
|  | 	// 	return | ||||||
|  | 	// } | ||||||
|  | 	// tmpl.ExecuteTemplate(w, "room", fi) | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.go
									
									
									
									
									
								
							| @@ -29,7 +29,7 @@ func ListenToRequests(port string) error { | |||||||
| 	mux.HandleFunc("POST /room-create", handlers.HandleCreateRoom) | 	mux.HandleFunc("POST /room-create", handlers.HandleCreateRoom) | ||||||
| 	mux.HandleFunc("GET /start-game", handlers.HandleStartGame) | 	mux.HandleFunc("GET /start-game", handlers.HandleStartGame) | ||||||
| 	mux.HandleFunc("GET /room-join", handlers.HandleJoinRoom) | 	mux.HandleFunc("GET /room-join", handlers.HandleJoinRoom) | ||||||
| 	// mux.HandleFunc("GET /roomlist", handlers.HandleRoomList) | 	mux.HandleFunc("POST /give-clue", handlers.HandleGiveClue) | ||||||
| 	//elements | 	//elements | ||||||
| 	mux.HandleFunc("GET /room/createform", handlers.HandleShowCreateForm) | 	mux.HandleFunc("GET /room/createform", handlers.HandleShowCreateForm) | ||||||
| 	mux.HandleFunc("GET /room/hideform", handlers.HandleHideCreateForm) | 	mux.HandleFunc("GET /room/hideform", handlers.HandleHideCreateForm) | ||||||
|   | |||||||
| @@ -9,4 +9,5 @@ var ( | |||||||
| 	CacheStatePrefix = "state-" | 	CacheStatePrefix = "state-" | ||||||
| 	// sse | 	// sse | ||||||
| 	NotifyRoomUpdatePrefix = "roomupdate_" | 	NotifyRoomUpdatePrefix = "roomupdate_" | ||||||
|  | 	NotifyMimePrefix       = "mimeclue_" | ||||||
| ) | ) | ||||||
|   | |||||||
| @@ -53,6 +53,7 @@ type Room struct { | |||||||
| 	BlueCounter uint8 | 	BlueCounter uint8 | ||||||
| 	RedCounter  uint8 | 	RedCounter  uint8 | ||||||
| 	RedTurn     bool // false is blue turn | 	RedTurn     bool // false is blue turn | ||||||
|  | 	MimeDone    bool | ||||||
| 	IsPublic    bool | 	IsPublic    bool | ||||||
| 	// GameSettings *GameSettings `json:"settings"` | 	// GameSettings *GameSettings `json:"settings"` | ||||||
| 	IsRunning bool   `json:"is_running"` | 	IsRunning bool   `json:"is_running"` | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder