134 lines
4.4 KiB
Plaintext
134 lines
4.4 KiB
Plaintext
package seasonsview
|
|
|
|
import "git.haelnorr.com/h/oslstats/internal/db"
|
|
import "git.haelnorr.com/h/oslstats/internal/view/baseview"
|
|
import "fmt"
|
|
|
|
templ SeriesUploadResultPage(series *db.PlayoffSeries) {
|
|
{{
|
|
backURL := fmt.Sprintf("/series/%d", series.ID)
|
|
team1Name := seriesTeamName(series.Team1)
|
|
team2Name := seriesTeamName(series.Team2)
|
|
boLabel := fmt.Sprintf("BO%d", series.MatchesToWin*2-1)
|
|
maxGames := series.MatchesToWin*2 - 1
|
|
minGames := series.MatchesToWin
|
|
}}
|
|
@baseview.Layout(fmt.Sprintf("Upload Series Result — %s vs %s", team1Name, team2Name)) {
|
|
<div class="max-w-screen-md mx-auto px-4 py-8">
|
|
<!-- Header -->
|
|
<div class="bg-mantle border border-surface1 rounded-lg overflow-hidden mb-6">
|
|
<div class="bg-surface0 border-b border-surface1 px-6 py-6">
|
|
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-text mb-1">Upload Series Results</h1>
|
|
<p class="text-sm text-subtext1">
|
|
{ team1Name } vs { team2Name }
|
|
<span class="text-subtext0 ml-1">
|
|
{ series.Label } · { boLabel }
|
|
</span>
|
|
</p>
|
|
</div>
|
|
<a
|
|
href={ templ.SafeURL(backURL) }
|
|
class="rounded-lg px-4 py-2 hover:cursor-pointer text-center
|
|
bg-surface1 hover:bg-surface2 text-text transition"
|
|
>
|
|
Cancel
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Upload Form -->
|
|
<div
|
|
class="bg-mantle border border-surface1 rounded-lg overflow-hidden"
|
|
x-data={ fmt.Sprintf("{ gameCount: %d }", minGames) }
|
|
>
|
|
<div class="bg-surface0 border-b border-surface1 px-4 py-3">
|
|
<h2 class="text-lg font-bold text-text">Match Log Files</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<p class="text-sm text-subtext1 mb-6">
|
|
Upload the 3 period match log JSON files for each game in the series.
|
|
Select the number of games that were actually played.
|
|
</p>
|
|
<form
|
|
hx-post={ fmt.Sprintf("/series/%d/results/upload", series.ID) }
|
|
hx-swap="none"
|
|
hx-encoding="multipart/form-data"
|
|
class="space-y-6"
|
|
>
|
|
<!-- Game Count Selector -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-text mb-2">
|
|
Number of Games Played
|
|
</label>
|
|
<select
|
|
name="game_count"
|
|
x-model="gameCount"
|
|
class="w-full px-3 py-2 bg-base border border-surface1 rounded-lg text-text
|
|
focus:border-blue focus:outline-none hover:cursor-pointer"
|
|
>
|
|
for g := minGames; g <= maxGames; g++ {
|
|
<option
|
|
value={ fmt.Sprint(g) }
|
|
if g == minGames {
|
|
selected
|
|
}
|
|
>
|
|
{ fmt.Sprint(g) } games
|
|
</option>
|
|
}
|
|
</select>
|
|
<p class="text-xs text-subtext0 mt-1">
|
|
First team to { fmt.Sprint(series.MatchesToWin) } wins takes the series
|
|
({ fmt.Sprint(minGames) }-{ fmt.Sprint(maxGames) } games possible)
|
|
</p>
|
|
</div>
|
|
<!-- Per-Game File Inputs -->
|
|
for g := 1; g <= maxGames; g++ {
|
|
<div
|
|
x-show={ fmt.Sprintf("gameCount >= %d", g) }
|
|
x-cloak
|
|
class="border border-surface1 rounded-lg overflow-hidden"
|
|
>
|
|
<div class="bg-surface0 border-b border-surface1 px-4 py-2">
|
|
<h3 class="text-md font-semibold text-text">Game { fmt.Sprint(g) }</h3>
|
|
</div>
|
|
<div class="p-4 space-y-4">
|
|
for p := 1; p <= 3; p++ {
|
|
<div>
|
|
<label class="block text-sm font-medium text-subtext0 mb-1">
|
|
Period { fmt.Sprint(p) }
|
|
</label>
|
|
<input
|
|
type="file"
|
|
name={ fmt.Sprintf("game_%d_period_%d", g, p) }
|
|
accept=".json"
|
|
class="w-full px-3 py-2 bg-base border border-surface1 rounded-lg text-text
|
|
file:mr-4 file:py-1 file:px-3 file:rounded file:border-0
|
|
file:text-sm file:font-medium file:bg-blue file:text-mantle
|
|
file:hover:bg-blue/80 file:hover:cursor-pointer file:transition
|
|
focus:border-blue focus:outline-none"
|
|
/>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
<!-- Submit -->
|
|
<div class="pt-2">
|
|
<button
|
|
type="submit"
|
|
class="w-full px-4 py-3 bg-blue hover:bg-blue/80 text-mantle rounded-lg
|
|
font-medium transition hover:cursor-pointer text-lg"
|
|
>
|
|
Upload & Validate All Games
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|