First not working app skeleton with nix support and dependency setup and generated logo not final structure
This commit is contained in:
130
templates/base.html
Normal file
130
templates/base.html
Normal file
@@ -0,0 +1,130 @@
|
||||
{{define "base"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{block "title" .}}QRank{{end}}</title>
|
||||
|
||||
<link rel="icon" type="image/png" href="/assets/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="/assets/favicon.ico">
|
||||
<link rel="shortcut icon" href="/assets/favicon.ico">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, "Helvetica Neue", Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #f7f7f9;
|
||||
color: #111
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 16px
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin: 12px 0;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, .06)
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 10px 14px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #ddd;
|
||||
background: #fafafa;
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #111;
|
||||
color: #fff;
|
||||
border-color: #111
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #ddd
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 12px;
|
||||
color: #444;
|
||||
margin-bottom: 6px;
|
||||
display: block
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 12px 16px;
|
||||
background: #fff;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
border-bottom: 1px solid #eee
|
||||
}
|
||||
|
||||
.nav a {
|
||||
margin-right: 12px;
|
||||
text-decoration: none;
|
||||
color: #111
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 12px;
|
||||
color: #666
|
||||
}
|
||||
|
||||
.list li {
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #f0f0f0
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 999px;
|
||||
background: #eee;
|
||||
font-size: 12px
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header">
|
||||
<div class="container">
|
||||
<div class="row" style="justify-content:space-between;align-items:center">
|
||||
<div><strong><a href="/" style="text-decoration:none;color:#111">QRank</a></strong></div>
|
||||
<div class="nav">
|
||||
<a href="/enter">Enter scores</a>
|
||||
<a href="/history">History</a>
|
||||
<a href="/leaderboard">Leaderboard</a>
|
||||
{{if .CurrentUser}}
|
||||
<a href="/me">@{{.CurrentUser.Username}}</a>
|
||||
{{else}}
|
||||
<a href="/login">Log in</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
{{block "content" .}}{{end}}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
{{end}}
|
||||
31
templates/enter.html
Normal file
31
templates/enter.html
Normal file
@@ -0,0 +1,31 @@
|
||||
{{define "enter"}}{{template "base" .}}{{end}}
|
||||
{{define "content"}}
|
||||
<div class="card">
|
||||
<h2>Enter a game</h2>
|
||||
{{if .Table}}<p class="small">Table: <span class="badge">{{.Table.Name}}</span></p>{{end}}
|
||||
<form method="POST" action="{{.PostAction}}">
|
||||
<div class="row">
|
||||
<div style="flex:1;min-width:280px">
|
||||
<h3>Team A</h3>
|
||||
<label class="label">Player A1</label>
|
||||
<input class="input" name="a1" value="{{.CurrentUser.Username}}">
|
||||
<label class="label">Player A2 (optional)</label>
|
||||
<input class="input" name="a2" placeholder="username or email">
|
||||
<label class="label">Score A</label>
|
||||
<input class="input" type="number" name="scoreA" value="10" min="0" required>
|
||||
</div>
|
||||
<div style="flex:1;min-width:280px">
|
||||
<h3>Team B</h3>
|
||||
<label class="label">Player B1</label>
|
||||
<input class="input" name="b1" placeholder="username or email">
|
||||
<label class="label">Player B2 (optional)</label>
|
||||
<input class="input" name="b2" placeholder="username or email">
|
||||
<label class="label">Score B</label>
|
||||
<input class="input" type="number" name="scoreB" value="8" min="0" required>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height:12px"></div>
|
||||
<button class="btn btn-primary" type="submit">Submit result</button>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
22
templates/history.html
Normal file
22
templates/history.html
Normal file
@@ -0,0 +1,22 @@
|
||||
{{define "history"}}{{template "base" .}}{{end}}
|
||||
{{define "content"}}
|
||||
<div class="card">
|
||||
<h2>Global history</h2>
|
||||
<ul class="list">
|
||||
{{range .Games}}
|
||||
<li>
|
||||
<div class="small">{{fmtTime .CreatedAt}}</div>
|
||||
<div>
|
||||
{{if .Table}}<span class="badge">{{.Table.Name}}</span> {{end}}
|
||||
Team A {{.ScoreA}} \u2013 {{.ScoreB}} Team B
|
||||
</div>
|
||||
<div class="small">
|
||||
{{range .PlayersA}}@{{.Username}} {{end}}vs {{range .PlayersB}}@{{.Username}} {{end}}
|
||||
</div>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="small">No games yet. Be the first!</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end}}
|
||||
13
templates/leaderboard.html
Normal file
13
templates/leaderboard.html
Normal file
@@ -0,0 +1,13 @@
|
||||
{{define "leaderboard"}}{{template "base" .}}{{end}}
|
||||
{{define "content"}}
|
||||
<div class="card">
|
||||
<h2>Leaderboard (by wins)</h2>
|
||||
<ol>
|
||||
{{range .Rows}}
|
||||
<li>@<a href="/u/{{.Slug}}">{{.Username}}</a> \u2014 {{.Wins}} wins ({{.Games}} games)</li>
|
||||
{{else}}
|
||||
<li class="small">No players yet.</li>
|
||||
{{end}}
|
||||
</ol>
|
||||
</div>
|
||||
{{end}}
|
||||
13
templates/login.html
Normal file
13
templates/login.html
Normal file
@@ -0,0 +1,13 @@
|
||||
{{define "login"}}{{template "base" .}}{{end}}
|
||||
{{define "content"}}
|
||||
<div class="card">
|
||||
<h2>Sign in with your email</h2>
|
||||
<p class="small">No password needed. We'll send you a magic link (for now it prints in the server logs).</p>
|
||||
<form method="POST" action="/login">
|
||||
<label class="label">Email</label>
|
||||
<input class="input" type="email" name="email" placeholder="you@example.com" required>
|
||||
<div style="height:8px"></div>
|
||||
<button class="btn btn-primary" type="submit">Send magic link</button>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
9
templates/sent.html
Normal file
9
templates/sent.html
Normal file
@@ -0,0 +1,9 @@
|
||||
{{define "sent"}}{{template "base" .}}{{end}}
|
||||
{{define "content"}}
|
||||
<div class="card">
|
||||
<h2>Check the server logs</h2>
|
||||
<p class="small">We just printed a magic link for <strong>{{.Email}}</strong>. Open it here to sign in.
|
||||
Token expires in 30 days.</p>
|
||||
<a class="btn" href="/login">Back</a>
|
||||
</div>
|
||||
{{end}}
|
||||
18
templates/user.html
Normal file
18
templates/user.html
Normal file
@@ -0,0 +1,18 @@
|
||||
{{define "user"}}{{template "base" .}}{{end}}
|
||||
{{define "content"}}
|
||||
<div class="card">
|
||||
<h2>@{{.Viewed.Username}}</h2>
|
||||
<p class="small">Joined {{fmtTime .Viewed.CreatedAt}}</p>
|
||||
<p>Games played: {{.Stats.Games}} Wins: {{.Stats.Wins}} Losses: {{.Stats.Losses}}</p>
|
||||
{{if .Own}}
|
||||
<hr>
|
||||
<h3>Update your profile</h3>
|
||||
<form method="POST" action="/me">
|
||||
<label class="label">Username</label>
|
||||
<input class="input" name="username" value="{{.Viewed.Username}}" required>
|
||||
<div style="height:8px"></div>
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user