Feat: join team

This commit is contained in:
Grail Finder
2025-05-08 12:31:44 +03:00
parent b20f7ac6b7
commit 21948b23f4
9 changed files with 112 additions and 22 deletions

View File

@ -12,6 +12,8 @@
</div> </div>
{{else}} {{else}}
<!-- user has room id => send him to his room --> <!-- user has room id => send him to his room -->
<div id="room">
{{template "room" .}} {{template "room" .}}
</div>
{{end}} {{end}}
{{end}} {{end}}

View File

@ -0,0 +1,7 @@
{{define "teamlist"}}
<div class="playerlist border border-gray-300 rounded-lg p-4">
{{range .}}
<p>{{.}}</p>
{{end}}
</div>
{{end}}

View File

@ -5,9 +5,15 @@
<hr /> <hr />
<div class="flex justify-center"> <div class="flex justify-center">
<!-- Left Panel --> <!-- Left Panel -->
{{template "teamlist" .Room.BlueGuessers}}
{{if eq .State.Team ""}}
{{template "teampew" "blue"}} {{template "teampew" "blue"}}
{{end}}
<!-- Right Panel --> <!-- Right Panel -->
{{if eq .State.Team ""}}
{{template "teampew" "red"}} {{template "teampew" "red"}}
{{end}}
{{template "teamlist" .Room.RedGuessers}}
</div> </div>
<hr /> <hr />
<div id="cardtable"> <div id="cardtable">

View File

@ -1,8 +1,7 @@
{{define "teampew"}} {{define "teampew"}}
<!-- <div class="w-1/4 p-4 border-r"> -->
<div> <div>
<h2 class="text-xl mb-4">Join {{.}} Team</h2> <h2 class="text-xl mb-4">Join {{.}} Team</h2>
<form hx-post="/join-team" hx-target="#room-content"> <form hx-post="/join-team" hx-target="#ancestor">
<input type="hidden" name="team" value="{{.}}"> <input type="hidden" name="team" value="{{.}}">
<div class="mb-1"> <div class="mb-1">
<button type="submit" name="role" value="guesser" class="w-full bg-{{.}}-500 text-white py-2 px-4 rounded"> <button type="submit" name="role" value="guesser" class="w-full bg-{{.}}-500 text-white py-2 px-4 rounded">

View File

@ -60,6 +60,26 @@ func getStateByCtx(ctx context.Context) (*models.UserState, error) {
return us, nil return us, nil
} }
func saveStateByCtx(ctx context.Context, state *models.UserState) error {
username, ok := ctx.Value(models.CtxUsernameKey).(string)
if !ok {
log.Debug("no username in ctx")
return errors.New("no username in ctx")
}
return saveState(username, state)
}
func saveFullInfoByUsername(username string, fi *models.FullInfo) error {
// INFO: unfortunately working no transactions; so case are possible where first object is updated but the second is not
if err := saveState(username, fi.State); err != nil {
return err
}
if err := saveRoom(fi.Room); err != nil {
return err
}
return nil
}
// cache // cache
func saveState(username string, state *models.UserState) error { func saveState(username string, state *models.UserState) error {

View File

@ -59,7 +59,6 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
} }
// make sure username does not exists // make sure username does not exists
cleanName := utils.RemoveSpacesFromStr(username) cleanName := utils.RemoveSpacesFromStr(username)
// TODO: create user in db
// login user // login user
cookie, err := makeCookie(cleanName, r.RemoteAddr) cookie, err := makeCookie(cleanName, r.RemoteAddr)
if err != nil { if err != nil {
@ -73,16 +72,15 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
abortWithError(w, err.Error()) abortWithError(w, err.Error())
return return
} }
// session, ok :=r.Context().Value(models.CtxSessionKey).(*models.Session)
// if !ok{
// abortWithError(w, "failed to extract session from ctx")
// return
// }
// state := models.InitState(cleanName)
state := models.MakeTestState() state := models.MakeTestState()
state.State.Username = cleanName state.State.Username = cleanName
// save state to cache // save state to cache
saveState(cleanName, state.State) // if err := saveState(cleanName, state.State); err != nil {
if err := saveFullInfoByUsername(cleanName, state); err != nil {
log.Error("failed to save state", "error", err)
abortWithError(w, err.Error())
return
}
tmpl.ExecuteTemplate(w, "base", state) tmpl.ExecuteTemplate(w, "base", state)
} }

View File

@ -66,6 +66,19 @@ func HandleRoomEnter(w http.ResponseWriter, r *http.Request) {
abortWithError(w, msg) abortWithError(w, msg)
return return
} }
state, err := getStateByCtx(ctx)
if err != nil {
log.Error("failed to get state", "error", err)
abortWithError(w, err.Error())
return
}
state.RoomID = room.ID
// update state
if err := saveStateByCtx(ctx, state); err != nil {
log.Error("failed to update state", "error", err)
abortWithError(w, err.Error())
return
}
// send msg of created room // send msg of created room
// h.Broker.Notifier <- broker.NotificationEvent{ // h.Broker.Notifier <- broker.NotificationEvent{
// EventName: models.MsgRoomListUpdate, // EventName: models.MsgRoomListUpdate,
@ -82,23 +95,66 @@ func HandleRoomEnter(w http.ResponseWriter, r *http.Request) {
func HandleJoinTeam(w http.ResponseWriter, r *http.Request) { func HandleJoinTeam(w http.ResponseWriter, r *http.Request) {
// parse payload // parse payload
team := r.URL.Query().Get("team") // team := r.URL.Query().Get("team")
role := r.URL.Query().Get("role") // role := r.URL.Query().Get("role")
r.ParseForm()
team := r.PostFormValue("team")
role := r.PostFormValue("role")
if team == "" || role == "" { if team == "" || role == "" {
msg := "missing team or role" msg := "missing team or role"
log.Error(msg) log.Error(msg)
abortWithError(w, msg) abortWithError(w, msg)
// error
return return
} }
// get username // get username
// get state fi, _ := getFullInfoByCtx(r.Context())
// get room // get room
if role == "mime" {
if team == "blue" {
fi.Room.BlueMime = fi.State.Username
fi.State.Team = "blue"
fi.State.Role = "mime"
} else if team == "red" {
fi.Room.RedMime = fi.State.Username
fi.State.Team = "red"
fi.State.Role = "mime"
} else {
msg := "uknown team:" + team
log.Error(msg)
abortWithError(w, msg)
return
}
} else if role == "guesser" {
if team == "blue" {
fi.Room.BlueGuessers = append(fi.Room.BlueGuessers, fi.State.Username)
fi.State.Team = "red"
fi.State.Role = "guesser"
} else if team == "red" {
fi.Room.RedGuessers = append(fi.Room.RedGuessers, fi.State.Username)
fi.State.Team = "red"
fi.State.Role = "guesser"
} else {
msg := "uknown team:" + team
log.Error(msg)
abortWithError(w, msg)
return
}
} else {
msg := "uknown role:" + role
log.Error(msg)
abortWithError(w, msg)
return
}
if err := saveFullInfoByUsername(fi.State.Username, fi); err != nil {
log.Error("failed to save state", "error", err)
abortWithError(w, err.Error())
return
}
// return html // return html
tmpl, err := template.ParseGlob("components/*.html") tmpl, err := template.ParseGlob("components/*.html")
if err != nil { if err != nil {
abortWithError(w, err.Error()) abortWithError(w, err.Error())
return return
} }
tmpl.ExecuteTemplate(w, "base", nil) tmpl.ExecuteTemplate(w, "base", fi)
} }

View File

@ -23,7 +23,7 @@ func ListenToRequests(port string) error {
mux.HandleFunc("GET /", handlers.HandleHome) mux.HandleFunc("GET /", handlers.HandleHome)
mux.HandleFunc("POST /login", handlers.HandleFrontLogin) mux.HandleFunc("POST /login", handlers.HandleFrontLogin)
mux.HandleFunc("GET /room", handlers.HandleRoomEnter) mux.HandleFunc("GET /room", handlers.HandleRoomEnter)
mux.HandleFunc("GET /join-team", handlers.HandleJoinTeam) mux.HandleFunc("POST /join-team", handlers.HandleJoinTeam)
//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)

View File

@ -11,11 +11,11 @@ const (
// UserTeam // UserTeam
UserTeamBlue = "blue" UserTeamBlue = "blue"
UserTeamRed = "red" UserTeamRed = "red"
UserTeamNone = "none" UserTeamNone = ""
//UserRole //UserRole
UserRoleMime = "mime" UserRoleMime = "mime"
UserRoleGuesser = "guesser" UserRoleGuesser = "guesser"
UserRoleNone = "none" UserRoleNone = ""
) )
func StrToUserTeam(s string) UserTeam { func StrToUserTeam(s string) UserTeam {
@ -80,6 +80,8 @@ func MakeTestState() *FullInfo {
CreatedAt: time.Now(), CreatedAt: time.Now(),
CreatorName: "test-name", CreatorName: "test-name",
Cards: cards, Cards: cards,
RedGuessers: []string{"Adam", "Eve"},
BlueGuessers: []string{"Abel", "Kain"},
} }
us := &UserState{ us := &UserState{
Username: "test-name", Username: "test-name",