finish map buying
This commit is contained in:
parent
53f778c323
commit
cb532efc39
@ -32,7 +32,7 @@ h3 { font-size: 1.4rem; font-weight: bold; }
|
||||
h4 { font-size: 1.1rem; font-weight: bold; }
|
||||
|
||||
div#container {
|
||||
width: 90vw;
|
||||
max-width: 1024px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0px auto;
|
||||
@ -357,13 +357,9 @@ table {
|
||||
}
|
||||
}
|
||||
|
||||
table.item-shop {
|
||||
table.shop {
|
||||
width: 80%;
|
||||
margin: 0px auto;
|
||||
|
||||
td:first-child {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
div.modal {
|
||||
|
@ -14,6 +14,17 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Map acts as a representation of owned/unowned maps in the town stores.
|
||||
type Map struct {
|
||||
ID int
|
||||
Name string
|
||||
Cost int
|
||||
Owned bool
|
||||
X int
|
||||
Y int
|
||||
TP int
|
||||
}
|
||||
|
||||
func RegisterTownRoutes(r *router.Router) {
|
||||
group := r.Group("/town")
|
||||
group.Use(middleware.RequireAuth())
|
||||
@ -21,9 +32,11 @@ func RegisterTownRoutes(r *router.Router) {
|
||||
|
||||
group.Get("/", showTown)
|
||||
group.Get("/inn", showInn)
|
||||
group.Get("/shop", showShop)
|
||||
group.WithMiddleware(middleware.CSRF(auth.Manager)).Post("/inn", rest)
|
||||
group.Get("/shop", showShop)
|
||||
group.Get("/shop/buy/:id", buyItem)
|
||||
group.Get("/maps", showMaps)
|
||||
group.Get("/maps/buy/:id", buyMap)
|
||||
}
|
||||
|
||||
func showTown(ctx router.Ctx, _ []string) {
|
||||
@ -133,3 +146,77 @@ func buyItem(ctx router.Ctx, params []string) {
|
||||
|
||||
ctx.Redirect("/town/shop", 302)
|
||||
}
|
||||
|
||||
func showMaps(ctx router.Ctx, _ []string) {
|
||||
var errorHTML string
|
||||
if flash := auth.GetFlashMessage(ctx); flash != nil {
|
||||
errorHTML = `<div style="color: red; margin-bottom: 1rem;">` + flash.Message + "</div>"
|
||||
}
|
||||
|
||||
town := ctx.UserValue("town").(*towns.Town)
|
||||
user := ctx.UserValue("user").(*users.User)
|
||||
|
||||
maplist := helpers.NewOrderedMap[int, Map]()
|
||||
towns, _ := towns.All()
|
||||
var mapped []int
|
||||
if user.Towns != "" {
|
||||
mapped = user.GetTownIDs()
|
||||
}
|
||||
for _, town := range towns {
|
||||
var owned bool
|
||||
if mapped != nil && slices.Contains(mapped, town.ID) {
|
||||
owned = true
|
||||
} else {
|
||||
owned = false
|
||||
}
|
||||
|
||||
maplist.Set(town.ID, Map{
|
||||
ID: town.ID,
|
||||
Name: town.Name,
|
||||
Cost: town.MapCost,
|
||||
Owned: owned,
|
||||
X: town.X,
|
||||
Y: town.Y,
|
||||
TP: town.TPCost,
|
||||
})
|
||||
}
|
||||
|
||||
components.RenderPage(ctx, town.Name+" Maps", "town/maps.html", map[string]any{
|
||||
"town": town,
|
||||
"maplist": maplist.ToSlice(),
|
||||
"error_message": errorHTML,
|
||||
})
|
||||
}
|
||||
|
||||
func buyMap(ctx router.Ctx, params []string) {
|
||||
id, err := strconv.Atoi(params[0])
|
||||
if err != nil {
|
||||
auth.SetFlashMessage(ctx, "error", "Error purchasing map; "+err.Error())
|
||||
ctx.Redirect("/town/maps", 302)
|
||||
return
|
||||
}
|
||||
|
||||
mapped, err := towns.Find(id)
|
||||
if err != nil {
|
||||
auth.SetFlashMessage(ctx, "error", "Error purchasing map; "+err.Error())
|
||||
ctx.Redirect("/town/maps", 302)
|
||||
return
|
||||
}
|
||||
|
||||
user := ctx.UserValue("user").(*users.User)
|
||||
if user.Gold < mapped.MapCost {
|
||||
auth.SetFlashMessage(ctx, "error", "You don't have enough gold to buy the map to "+mapped.Name)
|
||||
ctx.Redirect("/town/maps", 302)
|
||||
return
|
||||
}
|
||||
|
||||
user.Set("Gold", user.Gold-mapped.MapCost)
|
||||
if user.Towns == "" {
|
||||
user.Set("Towns", params[0])
|
||||
} else {
|
||||
user.Set("Towns", user.Towns+","+params[0])
|
||||
}
|
||||
user.Save()
|
||||
|
||||
ctx.Redirect("/town/maps", 302)
|
||||
}
|
||||
|
119
templates/town/maps.html
Normal file
119
templates/town/maps.html
Normal file
@ -0,0 +1,119 @@
|
||||
{include "layout.html"}
|
||||
|
||||
{block "content"}
|
||||
<div class="town shop">
|
||||
<div class="title"><h3>{town.Name} Maps</h3></div>
|
||||
{error_message}
|
||||
<section>
|
||||
<p>Buying maps will put the town in your Travel To box, and it won't cost you as many TP to get there.</p>
|
||||
<p>Click a town name to purchase its map.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<table class="shop">
|
||||
{for map in maplist}
|
||||
<tr>
|
||||
<td>
|
||||
{if map.Owned == false}
|
||||
{if user.Gold >= map.Cost}
|
||||
<a class="buy-item" data-item="{map.Name} Map" data-cost="{map.Cost}" href="/town/maps/buy/{map.ID}">{map.Name}</a>
|
||||
{else}
|
||||
<span class="light">{map.Name}</span>
|
||||
{/if}
|
||||
{else}
|
||||
{map.Name}
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{if map.Owned == false}
|
||||
{if user.Gold >= map.Cost}
|
||||
{map.Cost}G
|
||||
{else}
|
||||
{map.Cost}G <span class="light">(can't afford)</span>
|
||||
{/if}
|
||||
{else}
|
||||
<span>{map.X}, {map.Y}</span><br>
|
||||
<span>TP Cost: {map.TP}</span>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/for}
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>If you've changed your mind, you may also return back to <a href="/town">town</a>.</p>
|
||||
</section>
|
||||
|
||||
<div id="shop-modal" class="modal">
|
||||
<div class="content">
|
||||
<p id="msg">Are you sure you want to buy this item?</p>
|
||||
<div class="buttons">
|
||||
<button id="confirm" class="btn btn-primary">Buy Now</button>
|
||||
<button id="cancel" class="btn">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block "scripts"}
|
||||
<script>
|
||||
class ShopModal {
|
||||
constructor() {
|
||||
this.modal = document.querySelector("#shop-modal")
|
||||
this.message = this.modal.querySelector("#msg")
|
||||
this.confirmBtn = this.modal.querySelector("#confirm")
|
||||
this.cancelBtn = this.modal.querySelector("#cancel")
|
||||
this.currentUrl = null
|
||||
|
||||
this.init()
|
||||
}
|
||||
|
||||
init() {
|
||||
document.querySelectorAll('.buy-item').forEach(link => {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
this.show(link.href, link.dataset.item, link.dataset.cost)
|
||||
})
|
||||
})
|
||||
|
||||
this.confirmBtn.addEventListener('click', () => this.confirm())
|
||||
this.cancelBtn.addEventListener('click', () => this.hide())
|
||||
|
||||
this.modal.addEventListener('click', (e) => {
|
||||
if (e.target === this.modal) this.hide()
|
||||
})
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && this.modal.style.display === 'block') {
|
||||
this.hide()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
show(url, itemName, itemCost) {
|
||||
this.currentUrl = url
|
||||
this.message.textContent = `Are you sure you want to buy ${itemName} for ${itemCost}G?`
|
||||
this.modal.style.display = 'block'
|
||||
this.confirmBtn.focus()
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.modal.style.display = 'none'
|
||||
this.currentUrl = null
|
||||
}
|
||||
|
||||
confirm() {
|
||||
if (this.currentUrl) {
|
||||
window.location.href = this.currentUrl
|
||||
}
|
||||
this.hide()
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new ShopModal()
|
||||
})
|
||||
</script>
|
||||
{/block}
|
Loading…
x
Reference in New Issue
Block a user