style updates, split aside components, add get town by coords
This commit is contained in:
parent
58fe999675
commit
574bde5f28
@ -46,6 +46,15 @@ section#game {
|
||||
margin: 1rem 0;
|
||||
border-top: 2px solid #000;
|
||||
|
||||
& > aside > section:not(:last-child) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
& > aside > section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
& > aside#left {
|
||||
grid-column: 1;
|
||||
border-right: 2px solid #000;
|
||||
@ -86,7 +95,7 @@ a {
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.title {
|
||||
div.title {
|
||||
border: solid 1px black;
|
||||
background-color: #eeeeee;
|
||||
font-weight: bold;
|
||||
@ -106,3 +115,51 @@ footer {
|
||||
}
|
||||
}
|
||||
|
||||
ul.unstyled {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
form#move-compass {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-image: url('/assets/images/compass.webp');
|
||||
margin: 0.5rem auto;
|
||||
|
||||
& > div.mid {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: transparent; /* Hide the text */
|
||||
background-size: cover; /* Ensure the background image fills the button */
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(225, 16, 16, 0.5);
|
||||
}
|
||||
|
||||
&#north {
|
||||
width: 128px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
&#west {
|
||||
width: 63px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
&#east {
|
||||
width: 63px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
&#south {
|
||||
width: 128px;
|
||||
height: 38px;
|
||||
}
|
||||
}
|
||||
}
|
@ -43,32 +43,7 @@ func Start(port string) error {
|
||||
// Setup route handlers
|
||||
routes.RegisterAuthRoutes(r)
|
||||
|
||||
// Dashboard (protected route)
|
||||
r.WithMiddleware(middleware.RequireAuth("/login")).Get("/dashboard", func(ctx router.Ctx, params []string) {
|
||||
currentUser := middleware.GetCurrentUser(ctx)
|
||||
totalSessions, activeSessions := auth.Manager.SessionStats()
|
||||
|
||||
pageData := components.NewPageData(
|
||||
"Dashboard - Dragon Knight",
|
||||
fmt.Sprintf("Welcome back, %s!", currentUser.Username),
|
||||
)
|
||||
|
||||
additionalData := map[string]any{
|
||||
"total_sessions": totalSessions,
|
||||
"active_sessions": activeSessions,
|
||||
"authenticated": true,
|
||||
"username": currentUser.Username,
|
||||
}
|
||||
|
||||
if err := components.RenderPage(ctx, pageData, additionalData); err != nil {
|
||||
ctx.SetStatusCode(fasthttp.StatusInternalServerError)
|
||||
fmt.Fprintf(ctx, "Template error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// Hello world endpoint (public)
|
||||
r.Get("/", func(ctx router.Ctx, params []string) {
|
||||
// Get current user if authenticated
|
||||
currentUser := middleware.GetCurrentUser(ctx)
|
||||
var username string
|
||||
if currentUser != nil {
|
||||
@ -77,21 +52,12 @@ func Start(port string) error {
|
||||
username = "Guest"
|
||||
}
|
||||
|
||||
totalSessions, activeSessions := auth.Manager.SessionStats()
|
||||
|
||||
pageData := components.NewPageData(
|
||||
"Dragon Knight",
|
||||
fmt.Sprintf("Hello %s!", username),
|
||||
)
|
||||
|
||||
additionalData := map[string]any{
|
||||
"total_sessions": totalSessions,
|
||||
"active_sessions": activeSessions,
|
||||
"authenticated": currentUser != nil,
|
||||
"username": username,
|
||||
}
|
||||
|
||||
if err := components.RenderPage(ctx, pageData, additionalData); err != nil {
|
||||
if err := components.RenderPage(ctx, pageData, nil); err != nil {
|
||||
ctx.SetStatusCode(fasthttp.StatusInternalServerError)
|
||||
fmt.Fprintf(ctx, "Template error: %v", err)
|
||||
return
|
||||
|
91
internal/template/components/asides.go
Normal file
91
internal/template/components/asides.go
Normal file
@ -0,0 +1,91 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"dk/internal/middleware"
|
||||
"dk/internal/router"
|
||||
"dk/internal/template"
|
||||
"dk/internal/towns"
|
||||
"dk/internal/users"
|
||||
)
|
||||
|
||||
// LeftAside generates the left sidebar content
|
||||
func LeftAside(ctx router.Ctx) string {
|
||||
if !middleware.IsAuthenticated(ctx) {
|
||||
return ""
|
||||
}
|
||||
|
||||
leftSideTmpl, err := template.Cache.Load("leftside.html")
|
||||
if err != nil {
|
||||
return "leftside failed to load?"
|
||||
}
|
||||
|
||||
currentUser := middleware.GetCurrentUser(ctx)
|
||||
if currentUser == nil {
|
||||
return "no currentUser?"
|
||||
}
|
||||
|
||||
user, err := users.Find(currentUser.ID)
|
||||
if err != nil {
|
||||
return "user not found?"
|
||||
}
|
||||
|
||||
cardinalX := "E"
|
||||
if user.X < 0 {
|
||||
cardinalX = "W"
|
||||
}
|
||||
|
||||
cardinalY := "S"
|
||||
if user.Y < 0 {
|
||||
cardinalY = "N"
|
||||
}
|
||||
|
||||
townname := ""
|
||||
if user.Currently == "In Town" {
|
||||
town, err := towns.ByCoords(user.X, user.Y)
|
||||
if err != nil {
|
||||
townname = "error finding town"
|
||||
}
|
||||
townname = "<b>In " + town.Name + "</b>"
|
||||
}
|
||||
|
||||
leftSideData := map[string]any{
|
||||
"user": user.ToMap(),
|
||||
"cardinalX": cardinalX,
|
||||
"cardinalY": cardinalY,
|
||||
"townname": townname,
|
||||
"townlist": "@TODO",
|
||||
}
|
||||
|
||||
return leftSideTmpl.RenderNamed(leftSideData)
|
||||
}
|
||||
|
||||
// RightAside generates the right sidebar content
|
||||
func RightAside(ctx router.Ctx) string {
|
||||
if !middleware.IsAuthenticated(ctx) {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Load and render the rightside template with user data
|
||||
rightSideTmpl, err := template.Cache.Load("rightside.html")
|
||||
if err != nil {
|
||||
return "" // Silently fail - sidebar is optional
|
||||
}
|
||||
|
||||
// Get the current user from session
|
||||
currentUser := middleware.GetCurrentUser(ctx)
|
||||
if currentUser == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
user, err := users.Find(currentUser.ID)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Pass the user object directly to the template
|
||||
rightSideData := map[string]any{
|
||||
"user": user.ToMap(),
|
||||
}
|
||||
|
||||
return rightSideTmpl.RenderNamed(rightSideData)
|
||||
}
|
@ -9,7 +9,6 @@ import (
|
||||
"dk/internal/middleware"
|
||||
"dk/internal/router"
|
||||
"dk/internal/template"
|
||||
"dk/internal/users"
|
||||
)
|
||||
|
||||
// GenerateTopNav generates the top navigation HTML based on authentication status
|
||||
@ -28,68 +27,6 @@ func GenerateTopNav(ctx router.Ctx) string {
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateLeftSide generates the left sidebar content for authenticated users
|
||||
func GenerateLeftSide(ctx router.Ctx) string {
|
||||
if !middleware.IsAuthenticated(ctx) {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Load and render the leftside template with user data
|
||||
leftSideTmpl, err := template.Cache.Load("leftside.html")
|
||||
if err != nil {
|
||||
return "" // Silently fail - sidebar is optional
|
||||
}
|
||||
|
||||
// Get the current user from session
|
||||
currentUser := middleware.GetCurrentUser(ctx)
|
||||
if currentUser == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
user, err := users.Find(currentUser.ID)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Pass the user object directly to the template
|
||||
leftSideData := map[string]any{
|
||||
"user": user.ToMap(),
|
||||
}
|
||||
|
||||
return leftSideTmpl.RenderNamed(leftSideData)
|
||||
}
|
||||
|
||||
// GenerateRightSide generates the right sidebar content for authenticated users
|
||||
func GenerateRightSide(ctx router.Ctx) string {
|
||||
if !middleware.IsAuthenticated(ctx) {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Load and render the rightside template with user data
|
||||
rightSideTmpl, err := template.Cache.Load("rightside.html")
|
||||
if err != nil {
|
||||
return "" // Silently fail - sidebar is optional
|
||||
}
|
||||
|
||||
// Get the current user from session
|
||||
currentUser := middleware.GetCurrentUser(ctx)
|
||||
if currentUser == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
user, err := users.Find(currentUser.ID)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Pass the user object directly to the template
|
||||
rightSideData := map[string]any{
|
||||
"user": user.ToMap(),
|
||||
}
|
||||
|
||||
return rightSideTmpl.RenderNamed(rightSideData)
|
||||
}
|
||||
|
||||
// PageData holds common page template data
|
||||
type PageData struct {
|
||||
Title string
|
||||
@ -106,7 +43,7 @@ type PageData struct {
|
||||
// RenderPage renders a page using the layout template with common data and additional custom data
|
||||
func RenderPage(ctx router.Ctx, pageData PageData, additionalData map[string]any) error {
|
||||
if template.Cache == nil || auth.Manager == nil {
|
||||
return fmt.Errorf("singleton template.Cache or auth.Manager not initialized")
|
||||
return fmt.Errorf("template.Cache or auth.Manager not initialized")
|
||||
}
|
||||
|
||||
layoutTmpl, err := template.Cache.Load("layout.html")
|
||||
@ -132,10 +69,10 @@ func RenderPage(ctx router.Ctx, pageData PageData, additionalData map[string]any
|
||||
|
||||
// Set defaults for empty fields
|
||||
if data["leftside"] == "" {
|
||||
data["leftside"] = GenerateLeftSide(ctx)
|
||||
data["leftside"] = LeftAside(ctx)
|
||||
}
|
||||
if data["rightside"] == "" {
|
||||
data["rightside"] = GenerateRightSide(ctx)
|
||||
data["rightside"] = RightAside(ctx)
|
||||
}
|
||||
if data["numqueries"] == "" {
|
||||
data["numqueries"] = "0"
|
||||
|
@ -158,6 +158,31 @@ func ByMaxTPCost(maxCost int) ([]*Town, error) {
|
||||
return towns, nil
|
||||
}
|
||||
|
||||
// ByCoords retrieves a town by its x, y coordinates
|
||||
func ByCoords(x, y int) (*Town, error) {
|
||||
town := &Town{}
|
||||
|
||||
query := `SELECT id, name, x, y, inn_cost, map_cost, tp_cost, shop_list
|
||||
FROM towns WHERE x = ? AND y = ? LIMIT 1`
|
||||
err := database.Query(query, func(stmt *sqlite.Stmt) error {
|
||||
town.ID = stmt.ColumnInt(0)
|
||||
town.Name = stmt.ColumnText(1)
|
||||
town.X = stmt.ColumnInt(2)
|
||||
town.Y = stmt.ColumnInt(3)
|
||||
town.InnCost = stmt.ColumnInt(4)
|
||||
town.MapCost = stmt.ColumnInt(5)
|
||||
town.TPCost = stmt.ColumnInt(6)
|
||||
town.ShopList = stmt.ColumnText(7)
|
||||
return nil
|
||||
}, x, y)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve towns by distance: %w", err)
|
||||
}
|
||||
|
||||
return town, nil
|
||||
}
|
||||
|
||||
// ByDistance retrieves towns within a certain distance from a point
|
||||
func ByDistance(fromX, fromY, maxDistance int) ([]*Town, error) {
|
||||
var towns []*Town
|
||||
|
@ -1,46 +1,32 @@
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td class="title"><img src="/assets/images/button_location.gif" alt="Location" title="Location"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Currently: {user.Currently}<br>
|
||||
Longitude: {user.X}<br>
|
||||
Latitude: {user.Y}<br>
|
||||
<section>
|
||||
<div class="title"><img src="/assets/images/button_location.gif" alt="Location" title="Location"></div>
|
||||
|
||||
<div><b>{user.Currently}</b></div>
|
||||
<div>{user.X}{cardinalX}, {user.Y}{cardinalY}</div>
|
||||
|
||||
<a href="javascript:openmappopup()">View Map</a>
|
||||
<br><br>
|
||||
<form action="/move" method="post">
|
||||
<center>
|
||||
<input name="north" type="submit" value="North"><br>
|
||||
<input name="west" type="submit" value="West"><input name="east" type="submit" value="East"><br>
|
||||
<input name="south" type="submit" value="South">
|
||||
</center>
|
||||
|
||||
<form id="move-compass" action="/move" method="post" >
|
||||
<button id="north" name="direction" value="north">North</button>
|
||||
<div class="mid">
|
||||
<button id="west" name="direction" value="west">West</button>
|
||||
<button id="east" name="direction" value="east">East</button>
|
||||
</div>
|
||||
<button id="south" name="direction" value="south">South</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<br>
|
||||
<section>
|
||||
<div class="title"><img src="/assets/images/button_towns.gif" alt="Towns" title="Towns"></div>
|
||||
<div>{townname}</div>
|
||||
<div>{townlist}</div>
|
||||
</section>
|
||||
|
||||
<table width="100%">
|
||||
<tr><td class="title"><img src="/assets/images/button_towns.gif" alt="Towns" title="Towns"></td></tr>
|
||||
<tr>
|
||||
<td>
|
||||
{townname}
|
||||
{townlist}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
|
||||
<table width="100%">
|
||||
<tr><td class="title"><img src="/assets/images/button_functions.gif" alt="Functions" title="Functions"></td></tr>
|
||||
<tr><td>
|
||||
<a href="/">Home</a><br>
|
||||
<section id="functions">
|
||||
<div class="title"><img src="/assets/images/button_functions.gif" alt="Functions" title="Functions"></div>
|
||||
<a href="/">Home</a>
|
||||
<a href="/forum">Forum</a>
|
||||
<a href="/change-password">Change Password</a><br>
|
||||
<a href="#">Log Out</a><br>
|
||||
<a href="/change-password">Change Password</a>
|
||||
<a href="#">Log Out</a>
|
||||
<a href="/help">Help</a>
|
||||
</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
Loading…
x
Reference in New Issue
Block a user