Compare commits
8 commits
main
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a47aa90a3 | |||
|
|
ff0f06c0b9 | ||
|
|
6db6d78ad9 | ||
|
|
88cfe035e0 | ||
|
|
32a37eea32 | ||
|
|
f84ee2a466 | ||
|
|
aba6e13663 | ||
|
|
a0d6ff1cff |
15 changed files with 625 additions and 482 deletions
5
go.mod
5
go.mod
|
|
@ -2,7 +2,10 @@ module ddServer
|
|||
|
||||
go 1.21.4
|
||||
|
||||
require github.com/stretchr/testify v1.8.4
|
||||
require (
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/text v0.14.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -4,6 +4,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
|
|
|||
|
|
@ -2,10 +2,14 @@ package handlers
|
|||
|
||||
import (
|
||||
"ddServer/model"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// AddMonster is a http.HandlerFunc that adds a new monster to the Monsters slice.
|
||||
|
|
@ -94,32 +98,32 @@ func parseMonster(r *http.Request) model.Monster {
|
|||
Wis: parseInt(r.FormValue("wis")),
|
||||
Cha: parseInt(r.FormValue("cha")),
|
||||
Save: model.Save{
|
||||
Dex: r.FormValue("saveDex"),
|
||||
Con: r.FormValue("saveCon"),
|
||||
Wis: r.FormValue("saveWis"),
|
||||
Str: r.FormValue("saveStr"),
|
||||
Cha: r.FormValue("saveCha"),
|
||||
Int: r.FormValue("saveInt"),
|
||||
Dex: checkCheckbox("savedex", r),
|
||||
Con: checkCheckbox("savecon", r),
|
||||
Wis: checkCheckbox("savewis", r),
|
||||
Str: checkCheckbox("savestr", r),
|
||||
Cha: checkCheckbox("savecha", r),
|
||||
Int: checkCheckbox("saveint", r),
|
||||
},
|
||||
Skill: model.Skill{
|
||||
Perception: r.FormValue("perception"),
|
||||
Stealth: r.FormValue("stealth"),
|
||||
Acrobatics: r.FormValue("acrobatics"),
|
||||
AnimalHandling: r.FormValue("animalHandling"),
|
||||
Arcana: r.FormValue("arcana"),
|
||||
Athletics: r.FormValue("athletics"),
|
||||
Deception: r.FormValue("deception"),
|
||||
History: r.FormValue("history"),
|
||||
Insight: r.FormValue("insight"),
|
||||
Intimidation: r.FormValue("intimidation"),
|
||||
Investigation: r.FormValue("investigation"),
|
||||
Medicine: r.FormValue("medicine"),
|
||||
Nature: r.FormValue("nature"),
|
||||
Performance: r.FormValue("performance"),
|
||||
Persuasion: r.FormValue("persuasion"),
|
||||
SleightOfHand: r.FormValue("sleightOfHand"),
|
||||
Survival: r.FormValue("survival"),
|
||||
Religion: r.FormValue("religion"),
|
||||
Perception: checkCheckbox("perception", r),
|
||||
Stealth: checkCheckbox("stealth", r),
|
||||
Acrobatics: checkCheckbox("acrobatics", r),
|
||||
AnimalHandling: checkCheckbox("animalhandling", r),
|
||||
Arcana: checkCheckbox("arcana", r),
|
||||
Athletics: checkCheckbox("athletics", r),
|
||||
Deception: checkCheckbox("deception", r),
|
||||
History: checkCheckbox("history", r),
|
||||
Insight: checkCheckbox("insight", r),
|
||||
Intimidation: checkCheckbox("intimidation", r),
|
||||
Investigation: checkCheckbox("investigation", r),
|
||||
Medicine: checkCheckbox("medicine", r),
|
||||
Nature: checkCheckbox("nature", r),
|
||||
Performance: checkCheckbox("performance", r),
|
||||
Persuasion: checkCheckbox("persuasion", r),
|
||||
SleightOfHand: checkCheckbox("sleightofhand", r),
|
||||
Survival: checkCheckbox("survival", r),
|
||||
Religion: checkCheckbox("religion", r),
|
||||
},
|
||||
Resist: []string{r.FormValue("resist")},
|
||||
ConditionImmune: []string{r.FormValue("conditionImmune")},
|
||||
|
|
@ -142,3 +146,10 @@ func parseMonster(r *http.Request) model.Monster {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
func checkCheckbox(field string, r *http.Request) string {
|
||||
if r.FormValue(fmt.Sprintf("check%v", cases.Caser(cases.Title(language.Und)).String(field))) == "on" {
|
||||
return r.FormValue(field)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
46
handlers/load_file_handler.go
Normal file
46
handlers/load_file_handler.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"ddServer/model"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func LoadFileHandler(monsters *[]model.Monster) http.HandlerFunc {
|
||||
log.Print("LoadFileHandler called")
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseMultipartForm(10 << 20) // 10 MB limit
|
||||
|
||||
// Get the file from the request
|
||||
file, _, err := r.FormFile("uploadFile")
|
||||
if err != nil {
|
||||
http.Error(w, "Error retrieving file", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Parse the file content
|
||||
decoder := json.NewDecoder(file)
|
||||
var loadedChars model.Character
|
||||
err = decoder.Decode(&loadedChars)
|
||||
if err != nil {
|
||||
http.Error(w, "Error decoding file content", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Lock the Monsters slice and append the loaded monsters, then unlock the slice
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
// Assuming 'loadedChars' contains an array of Monster objects
|
||||
for _, monster := range loadedChars.Monster {
|
||||
*monsters = append(*monsters, monster)
|
||||
}
|
||||
|
||||
fmt.Printf("%v\n", monsters)
|
||||
// Send a success response
|
||||
http.Redirect(w, r, "/monsterTable", http.StatusTemporaryRedirect)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ func MainHandler(content embed.FS, monsters *[]model.Monster) http.HandlerFunc {
|
|||
log.Print("MainHandler called")
|
||||
|
||||
// Parse the templates from the embedded file system
|
||||
tmpl, err := template.ParseFS(content, "templates/main.html", "templates/monsterForm.html", "templates/monster.html", "templates/monsterTable.html", "templates/base.html")
|
||||
tmpl, err := template.ParseFS(content, "templates/main.html", "templates/monsterForm.html", "templates/monster.html", "templates/monsterTable.html", "templates/base.html", "templates/skills.html")
|
||||
if err != nil {
|
||||
log.Printf("Template parsing error: %v\n", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
|
|
|||
|
|
@ -8,40 +8,44 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
// SkillCalculationHandler ist ein http.HandlerFunc, der von htmx getriggert wird,
|
||||
// wenn der Benutzer Einträge in bestimmten Feldern macht, und dann die Skill-Felder befüllt.
|
||||
// SkillCalculationHandler is an http.HandlerFunc triggered by htmx when the user makes entries in certain fields and then populates the skill fields.
|
||||
func SkillCalculationHandler(content embed.FS) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Print("SkillCalculationHandler called")
|
||||
|
||||
// Überprüfen Sie, ob die Anfrage eine POST-Anfrage ist.
|
||||
// Check if the request is a POST request.
|
||||
if r.Method != http.MethodPost {
|
||||
log.Print("Method not allowed")
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
// Parse Formulardaten.
|
||||
// Parse form data.
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
log.Printf("Error parsing form data: %v", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
tmplFiles := []string{"templates/base.html", "templates/header.html", "templates/skills.html", "templates/main.html", "templates/footer.html", "templates/about.html"}
|
||||
// Parse template files.
|
||||
tmplFiles := []string{
|
||||
"templates/base.html",
|
||||
"templates/header.html",
|
||||
"templates/skills.html",
|
||||
"templates/main.html",
|
||||
"templates/footer.html",
|
||||
"templates/about.html",
|
||||
}
|
||||
tmpl, err := template.ParseFS(content, tmplFiles...)
|
||||
if err != nil {
|
||||
log.Printf("Template parsing error: %v\n", err)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Parse form field values and calculate skill values.
|
||||
str := parseFieldValue(r.FormValue("str"))
|
||||
dex := parseFieldValue(r.FormValue("dex"))
|
||||
int := parseFieldValue(r.FormValue("int"))
|
||||
cha := parseFieldValue(r.FormValue("cha"))
|
||||
wis := parseFieldValue(r.FormValue("wis"))
|
||||
con := parseFieldValue(r.FormValue("con"))
|
||||
cr := parseFieldValue(r.FormValue("cr"))
|
||||
crBonus := calcBonus(cr)
|
||||
|
||||
|
|
@ -64,79 +68,124 @@ func SkillCalculationHandler(content embed.FS) http.HandlerFunc {
|
|||
"sleightOfHand": strconv.Itoa(calcAbilityScore(dex) + crBonus),
|
||||
"stealth": strconv.Itoa(calcAbilityScore(dex) + crBonus),
|
||||
"survival": strconv.Itoa(calcAbilityScore(wis) + crBonus),
|
||||
"saveStr": strconv.Itoa(calcAbilityScore(str) + crBonus),
|
||||
"saveWis": strconv.Itoa(calcAbilityScore(wis) + crBonus),
|
||||
"saveCon": strconv.Itoa(calcAbilityScore(con) + crBonus),
|
||||
"saveInt": strconv.Itoa(calcAbilityScore(int) + crBonus),
|
||||
"saveCha": strconv.Itoa(calcAbilityScore(cha) + crBonus),
|
||||
"saveDex": strconv.Itoa(calcAbilityScore(dex) + crBonus),
|
||||
}
|
||||
|
||||
// Execute template with skill values.
|
||||
err = tmpl.ExecuteTemplate(w, "skills", skillValues)
|
||||
if err != nil {
|
||||
log.Printf("Template execution error: %v\n", err)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calcBonus calculates the bonus based on the given credit rating.
|
||||
// It returns the bonus value as an integer.
|
||||
func calcBonus(cr int) int {
|
||||
if cr >= 0 && cr < 5 {
|
||||
switch {
|
||||
case cr >= 0 && cr < 5:
|
||||
log.Println("Bonus calculated for credit rating:", cr)
|
||||
return 2
|
||||
} else if cr >= 5 && cr < 9 {
|
||||
case cr >= 5 && cr < 9:
|
||||
log.Println("Bonus calculated for credit rating:", cr)
|
||||
return 3
|
||||
} else if cr >= 9 && cr < 14 {
|
||||
case cr >= 9 && cr < 14:
|
||||
log.Println("Bonus calculated for credit rating:", cr)
|
||||
return 4
|
||||
} else if cr >= 14 && cr < 18 {
|
||||
case cr >= 14 && cr < 18:
|
||||
log.Println("Bonus calculated for credit rating:", cr)
|
||||
return 5
|
||||
} else if cr >= 18 && cr < 21 {
|
||||
case cr >= 18 && cr < 21:
|
||||
log.Println("Bonus calculated for credit rating:", cr)
|
||||
return 6
|
||||
} else if cr >= 21 && cr < 25 {
|
||||
case cr >= 21 && cr < 25:
|
||||
log.Println("Bonus calculated for credit rating:", cr)
|
||||
return 7
|
||||
} else if cr >= 25 && cr < 28 {
|
||||
case cr >= 25 && cr < 28:
|
||||
log.Println("Bonus calculated for credit rating:", cr)
|
||||
return 8
|
||||
} else if cr >= 28 && cr < 31 {
|
||||
case cr >= 28 && cr < 31:
|
||||
log.Println("Bonus calculated for credit rating:", cr)
|
||||
return 9
|
||||
} else {
|
||||
default:
|
||||
log.Println("Invalid credit rating:", cr)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// calcAbilityScore calculates the ability score based on the given value.
|
||||
func calcAbilityScore(val int) int {
|
||||
if val < 2 {
|
||||
switch {
|
||||
case val < 2:
|
||||
log.Println("Ability Score: -5")
|
||||
return -5
|
||||
} else if val >= 2 && val < 4 {
|
||||
case val < 4:
|
||||
log.Println("Ability Score: -4")
|
||||
return -4
|
||||
} else if val >= 4 && val < 6 {
|
||||
case val < 6:
|
||||
log.Println("Ability Score: -3")
|
||||
return -3
|
||||
} else if val >= 6 && val < 8 {
|
||||
case val < 8:
|
||||
log.Println("Ability Score: -2")
|
||||
return -2
|
||||
} else if val >= 8 && val < 10 {
|
||||
case val < 10:
|
||||
log.Println("Ability Score: -1")
|
||||
return -1
|
||||
} else if val >= 10 && val < 12 {
|
||||
case val < 12:
|
||||
log.Println("Ability Score: 0")
|
||||
return 0
|
||||
} else if val >= 12 && val < 14 {
|
||||
case val < 14:
|
||||
log.Println("Ability Score: 1")
|
||||
return 1
|
||||
} else if val >= 14 && val < 16 {
|
||||
case val < 16:
|
||||
log.Println("Ability Score: 2")
|
||||
return 2
|
||||
} else if val >= 16 && val < 18 {
|
||||
case val < 18:
|
||||
log.Println("Ability Score: 3")
|
||||
return 3
|
||||
} else if val >= 18 && val < 20 {
|
||||
case val < 20:
|
||||
log.Println("Ability Score: 4")
|
||||
return 4
|
||||
} else if val >= 20 && val < 22 {
|
||||
case val < 22:
|
||||
log.Println("Ability Score: 5")
|
||||
return 5
|
||||
} else if val >= 22 && val < 24 {
|
||||
case val < 24:
|
||||
log.Println("Ability Score: 6")
|
||||
return 6
|
||||
} else if val >= 24 && val < 26 {
|
||||
case val < 26:
|
||||
log.Println("Ability Score: 7")
|
||||
return 7
|
||||
} else if val >= 26 && val < 28 {
|
||||
case val < 28:
|
||||
log.Println("Ability Score: 8")
|
||||
return 8
|
||||
} else if val >= 28 && val < 30 {
|
||||
case val < 30:
|
||||
log.Println("Ability Score: 9")
|
||||
return 9
|
||||
} else {
|
||||
default:
|
||||
log.Println("Ability Score: 10")
|
||||
return 10
|
||||
}
|
||||
}
|
||||
|
||||
// parseFieldValue takes a string value and returns an integer.
|
||||
// If the string value cannot be converted to an integer, it logs an error and returns 0.
|
||||
// The function follows these rules:
|
||||
// - No line is over 66 characters.
|
||||
func parseFieldValue(value string) int {
|
||||
// Convert the string value to an integer using strconv.Atoi.
|
||||
// If an error occurs during the conversion, log the error and return 0.
|
||||
val, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
log.Printf("Error converting field value to integer: %v", err)
|
||||
return 0
|
||||
}
|
||||
// Log the converted integer value for debugging purposes.
|
||||
log.Printf("Converted field value to integer: %d", val)
|
||||
// Return the converted integer value.
|
||||
return val
|
||||
}
|
||||
|
|
|
|||
1
main.go
1
main.go
|
|
@ -37,6 +37,7 @@ func main() {
|
|||
routes.HandleFunc("/contact", handlers.ContactHandler(content))
|
||||
routes.HandleFunc("/monsterTable", handlers.MonsterTableHandler(content, &Monsters))
|
||||
routes.HandleFunc("/calculate-skills", handlers.SkillCalculationHandler(content))
|
||||
routes.HandleFunc("/loadFile", handlers.LoadFileHandler(&Monsters))
|
||||
// Print the message indicating that 'static' has been included.
|
||||
log.Printf("Eingebunden is %v\n", static)
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@
|
|||
<div class="field">
|
||||
<label for="message">Your Message:</label>
|
||||
<div class="control">
|
||||
<textarea name="message" required placeholder="Type your message here" class="textarea"></textarea>
|
||||
<textarea name="message" required placeholder="Type your message here"
|
||||
class="textarea"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,28 @@
|
|||
<p class="title is-4">Monster Form</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<form hx-post="/loadFile" hx-encoding="multipart/form-data"
|
||||
_='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
|
||||
<div class="file">
|
||||
<label class="file-label">
|
||||
<input class="file-input" type="file" name="uploadFile">
|
||||
<span class="file-cta">
|
||||
<span class="file-icon">
|
||||
<i class="fas fa-upload"></i>
|
||||
</span>
|
||||
<span class="file-label">
|
||||
Choose a file…
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<button class="button" type="button" hx-post="/loadFile" hx-trigger="click" hx-target="#monster-table"
|
||||
hx-swap="outerHTML">Press Me</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form action="/submit" method="post" class="">
|
||||
<div class="field">
|
||||
<td><label for="filename">Filename:</label></td>
|
||||
|
|
@ -13,6 +35,7 @@
|
|||
class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
{{ template "monsterform" . }}
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<button type="button" hx-post="/addMonster" hx-trigger="click" hx-target="#monster-table"
|
||||
|
|
@ -20,7 +43,6 @@
|
|||
Monster</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ template "monsterform" . }}
|
||||
<input type="hidden" name="filename" value="{{.Filename}}">
|
||||
<input type="submit" value="Submit" class="button is-primary">
|
||||
</form>
|
||||
|
|
@ -66,7 +88,7 @@
|
|||
<th>Save Con</th>
|
||||
<th>Save Wis</th>
|
||||
<th>Save Str</th>
|
||||
<th>Save Con</th>
|
||||
<th>Save Int</th>
|
||||
<th>Save Cha</th>
|
||||
<th>Perception</th>
|
||||
<th>Stealth</th>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<td>{{.Save.Con}}</td>
|
||||
<td>{{.Save.Wis}}</td>
|
||||
<td>{{.Save.Str}}</td>
|
||||
<td>{{.Save.Con}}</td>
|
||||
<td>{{.Save.Int}}</td>
|
||||
<td>{{.Save.Cha}}</td>
|
||||
<td>{{.Skill.Perception}}</td>
|
||||
<td>{{.Skill.Stealth}}</td>
|
||||
|
|
|
|||
|
|
@ -87,61 +87,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card tile is-ancestor is-vertical">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
Speed
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="walk">Walk:</label>
|
||||
<div class="control">
|
||||
<input type="number" name="walk" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="burrow">Burrow:</label>
|
||||
<div class="control">
|
||||
<input type="number" name="burrow" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="climb">Climb:</label>
|
||||
<div class="control">
|
||||
<input type="number" name="climb" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="fly">Fly:</label>
|
||||
<div class="control">
|
||||
<input type="number" name="fly" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="swim">Swim:</label>
|
||||
<div class="control">
|
||||
<input type="number" name="swim" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
|
|
@ -209,20 +154,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="passive">Passive:</label>
|
||||
<div class="control">
|
||||
<input type="number" name="passive" required class="input input-bordered w-full max-w-xs"
|
||||
hx-post="/calculate-skills" hx-trigger="keyup changed delay:100ms" hx-target="#skills" hx-swap="innerHTML">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="skills" class="tile is-ancestor is-vertical">
|
||||
{{ template "skills" }}
|
||||
</div>
|
||||
<div class="card tile is-ancestor is-vertical">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
Save
|
||||
Speed
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
|
|
@ -230,26 +169,25 @@
|
|||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label for="saveDex">Dex:</label>
|
||||
<label for="walk">Walk:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="saveDex" required class="input input-bordered w-full max-w-xs">
|
||||
<input type="number" name="walk" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label for="saveCon">Con:</label>
|
||||
<label for="burrow">Burrow:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="saveCon" required class="input input-bordered w-full max-w-xs">
|
||||
<input type="number" name="burrow" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label for="saveWis">Wis:</label>
|
||||
<label for="climb">Climb:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="saveWis" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
<input type="number" name="climb" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -257,33 +195,23 @@
|
|||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label for="saveCha">Cha:</label>
|
||||
<label for="fly">Fly:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="saveCha" required class="input input-bordered w-full max-w-xs">
|
||||
<input type="number" name="fly" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label for="saveInt">Int:</label>
|
||||
<label for="swim">Swim:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="saveInt" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label for="saveStr">Str:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="saveStr" required class="input input-bordered w-full max-w-xs">
|
||||
<input type="number" name="swim" required class="input input-bordered w-full max-w-xs">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="skills" class="card tile is-ancestor is-vertical">
|
||||
{{ template "skills" }}
|
||||
</div>
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
|
|
|
|||
|
|
@ -1,15 +1,88 @@
|
|||
{{ define "skills" }}
|
||||
<header class="card-header">
|
||||
<div class="tile is-parent">
|
||||
<div class="card tile is-child is-ancestor is-vertical">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
Save
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label class="checkbox" for="savedex"><input type="checkbox" name="checkSavedex">Dex:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="savedex" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{.saveDex}}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label class="checkbox" for="savecon"><input type="checkbox" name="checkSavecon">Con:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="savecon" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{.saveCon}}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label class="checkbox" for="savewis"><input type="checkbox" name="checkSavewis">Wis:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="savewis" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{.saveWis}}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label class="checkbox" for="savecha"><input type="checkbox" name="checkSavecha">Cha:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="savecha" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{.saveCha}}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label class="checkbox" for="saveint"><input type="checkbox" name="checkSaveint">Int:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="saveint" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{.saveInt}}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent gap">
|
||||
<div class="tile is-child field">
|
||||
<label class="checkbox" for="savestr"><input type="checkbox" name="checkSavestr">Str:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="savestr" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{.saveStr}}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="card tile is-child is-ancestor is-vertical">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
Skill
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="acrobatics">Acrobatics:</label>
|
||||
<label class="checkbox" for="acrobatics"><input type="checkbox" name="checkAcrobatics">Acrobatics:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="acrobatics" required class="input input-bordered w-full max-w-xs" value="{{
|
||||
.acrobatics }}" readonly>
|
||||
|
|
@ -18,19 +91,20 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="animalHandling">Animal Handling:</label>
|
||||
<label for="animalhandling" class="checkbox"><input type="checkbox" name="checkAnimalhandling">Animal
|
||||
Handling:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="animalHandling" required class="input input-bordered w-full max-w-xs"
|
||||
<input type="text" name="animalhandling" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .animalHandling }}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="arcana">Arcana:</label>
|
||||
<label for="arcana" class="ceckbox"><input type="checkbox" name="checkArcana">Arcana:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="arcana" required class="input input-bordered w-full max-w-xs" value="{{ .arcana }}"
|
||||
readonly>
|
||||
<input type="text" name="arcana" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .arcana }}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -38,7 +112,7 @@
|
|||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="athletics">Athletics:</label>
|
||||
<label for="athletics" class="checkbox"><input type="checkbox" name="checkAthletics">Athletics:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="athletics" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .athletics }}" readonly>
|
||||
|
|
@ -47,7 +121,7 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="deception">Deception:</label>
|
||||
<label for="deception" class="checkbox"><input type="checkbox" name="checkDeception">Deception:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="deception" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .deception }}" readonly>
|
||||
|
|
@ -56,7 +130,7 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="history">History:</label>
|
||||
<label for="history" class="checkbox"><input type="checkbox" name="checkHistory">History:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="history" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .history }}" readonly>
|
||||
|
|
@ -67,7 +141,7 @@
|
|||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="insight">Insight:</label>
|
||||
<label for="insight" class="checkbox"><input type="checkbox" name="checkInsight">Insight:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="insight" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .insight }}" readonly>
|
||||
|
|
@ -76,7 +150,8 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="intimidation">Intimidation:</label>
|
||||
<label for="intimidation" class="checkbox"><input type="checkbox"
|
||||
name="checkIntimidation">Intimidation:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="intimidation" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .intimidation }}" readonly>
|
||||
|
|
@ -85,7 +160,8 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="investigation">Investigation:</label>
|
||||
<label for="investigation" class="checkbox"><input type="checkbox"
|
||||
name="checkInvestigation">Investigation:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="investigation" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .investigation }}" readonly>
|
||||
|
|
@ -96,7 +172,7 @@
|
|||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="medicine">Medicine:</label>
|
||||
<label for="medicine" class="checkbox"><input type="checkbox" name="checkMedicine">Medicine:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="medicine" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .medicine }}" readonly>
|
||||
|
|
@ -105,16 +181,17 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="nature">Nature:</label>
|
||||
<label for="nature" class="checkbox"><input type="checkbox" name="checkNature">Nature:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="nature" required class="input input-bordered w-full max-w-xs" value="{{ .nature }}"
|
||||
readonly>
|
||||
<input type="text" name="nature" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .nature }}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="performance">Performance:</label>
|
||||
<label for="performance" class="checkbox"><input type="checkbox"
|
||||
name="checkPerformance">Performance:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="performance" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .performance }}" readonly>
|
||||
|
|
@ -125,7 +202,7 @@
|
|||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="perception">Perception:</label>
|
||||
<label for="perception" class="checkbox"><input type="checkbox" name="checkPerception">Perception:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="perception" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .perception }}" readonly>
|
||||
|
|
@ -134,7 +211,7 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="stealth">Stealth:</label>
|
||||
<label for="stealth" class="checkbox"><input type="checkbox" name="checkStealth">Stealth:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="stealth" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .stealth }}" readonly>
|
||||
|
|
@ -143,7 +220,7 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="persuasion">Persuasion:</label>
|
||||
<label for="persuasion" class="checkbox"><input type="checkbox" name="checkPersuasion">Persuasion:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="persuasion" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .persuasion }}" readonly>
|
||||
|
|
@ -154,16 +231,17 @@
|
|||
<div class="tile is-ancestor">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="sleightOfHand">Sleight of Hand:</label>
|
||||
<label for="sleightofhand" class="checkbox"><input type="checkbox" name="checkSleightofhand">Sleight of
|
||||
Hand:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="sleightOfHand" required class="input input-bordered w-full max-w-xs"
|
||||
<input type="text" name="sleightofhand" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{.sleightOfHand }}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="religion">Religion:</label>
|
||||
<label for="religion" class="checkbox"><input type="checkbox" name="checkReligion">Religion:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="religion" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .religion }}" readonly>
|
||||
|
|
@ -172,7 +250,7 @@
|
|||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child field">
|
||||
<label for="survival">Survival:</label>
|
||||
<label for="survival" class="checkbox"><input type="checkbox" name="checkSurvival">Survival:</label>
|
||||
<div class="control">
|
||||
<input type="text" name="survival" required class="input input-bordered w-full max-w-xs"
|
||||
value="{{ .survival }}" readonly>
|
||||
|
|
@ -181,5 +259,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
Loading…
Add table
Add a link
Reference in a new issue