Files
oslstats/internal/view/seasonsview/edit_form.templ
2026-02-12 21:10:49 +11:00

191 lines
6.6 KiB
Plaintext

package seasonsview
import "git.haelnorr.com/h/oslstats/internal/view/datepicker"
import "git.haelnorr.com/h/oslstats/internal/db"
import "time"
templ EditForm(season *db.Season, allLeagues []*db.League) {
{{
// Format dates for display (DD/MM/YYYY)
startDateStr := formatDateInput(season.StartDate)
endDateStr := ""
if !season.EndDate.IsZero() {
endDateStr = formatDateInput(season.EndDate.Time)
}
finalsStartDateStr := ""
if !season.FinalsStartDate.IsZero() {
finalsStartDateStr = formatDateInput(season.FinalsStartDate.Time)
}
finalsEndDateStr := ""
if !season.FinalsEndDate.IsZero() {
finalsEndDateStr = formatDateInput(season.FinalsEndDate.Time)
}
}}
<form
hx-post={ "/seasons/" + season.ShortName + "/edit" }
hx-swap="none"
x-data={ templ.JSFuncCall("editSeasonFormData", startDateStr, endDateStr, finalsStartDateStr, finalsEndDateStr).CallInline }
@submit="handleSubmit()"
@htmx:after-request="if(submitTimeout) clearTimeout(submitTimeout); const redirect = $event.detail.xhr.getResponseHeader('HX-Redirect'); if(redirect) return; if(!$event.detail.successful && $event.detail.xhr.status !== 409) { isSubmitting=false; buttonText='Save Changes'; generalError='An error occurred. Please try again.'; }"
>
<script>
function editSeasonFormData(
initialStart,
initialEnd,
initialFinalsStart,
initialFinalsEnd,
) {
return {
canSubmit: true,
buttonText: "Save Changes",
// Date validation state
startDateError: "",
startDateIsEmpty: initialStart === "",
endDateError: "",
finalsStartDateError: "",
finalsEndDateError: "",
// Form state
isSubmitting: false,
generalError: "",
submitTimeout: null,
// Reset date errors
resetStartDateErr() {
this.startDateError = "";
},
resetEndDateErr() {
this.endDateError = "";
},
resetFinalsStartDateErr() {
this.finalsStartDateError = "";
},
resetFinalsEndDateErr() {
this.finalsEndDateError = "";
},
// Check if form can be submitted
updateCanSubmit() {
this.canSubmit = !this.startDateIsEmpty;
},
// Handle form submission
handleSubmit() {
this.isSubmitting = true;
this.buttonText = "Saving...";
this.generalError = "";
// Set timeout for 10 seconds
this.submitTimeout = setTimeout(() => {
this.isSubmitting = false;
this.buttonText = "Save Changes";
this.generalError = "Request timed out. Please try again.";
}, 10000);
},
};
}
</script>
<div class="bg-mantle border border-surface1 rounded-lg">
<!-- Header Section -->
<div class="bg-surface0 border-b border-surface1 px-6 py-8 rounded-t-lg">
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
<div>
<h1 class="text-4xl font-bold text-text mb-2">Edit { season.Name }</h1>
<div class="flex items-center gap-2">
<span class="inline-block bg-blue px-3 py-1 rounded-full text-sm font-semibold text-mantle">
{ season.ShortName }
</span>
<select
id="slap_version"
name="slap_version"
class="py-1 pl-3 pr-2 rounded-full text-sm bg-base border-2 border-overlay0 focus:border-blue outline-none"
required
>
<option value="rebound" selected?={ season.SlapVersion == "rebound" }>Rebound</option>
<option value="slapshot1" selected?={ season.SlapVersion == "slapshot1" }>Slapshot 1</option>
</select>
</div>
</div>
<div class="flex gap-2">
<button
x-bind:disabled="!canSubmit || isSubmitting"
x-text="buttonText"
type="submit"
class="rounded-lg px-4 py-2 hover:cursor-pointer text-center
bg-blue hover:bg-blue/75 text-mantle transition font-semibold
disabled:bg-blue/40 disabled:cursor-not-allowed"
></button>
<a
href={ templ.SafeURL("/seasons/" + season.ShortName) }
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>
<!-- Information Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 p-6">
<!-- Regular Season Section -->
<div class="bg-surface0 border border-surface1 rounded-lg p-6">
<h2 class="text-2xl font-bold text-text mb-4 flex items-center gap-2">
<span class="text-blue">●</span>
Regular Season
</h2>
<div class="space-y-4">
@datepicker.DatePickerWithDefault("start_date", "start_date", "Start Date", "DD/MM/YYYY", true, "startDateIsEmpty = $el.value === ''; resetStartDateErr(); if(startDateIsEmpty) { startDateError='Start date is required'; } updateCanSubmit();", startDateStr)
<p
class="text-xs text-red -mt-2"
x-show="startDateError && !isSubmitting"
x-cloak
x-text="startDateError"
></p>
@datepicker.DatePickerWithDefault("end_date", "end_date", "End Date (Optional)", "DD/MM/YYYY", false, "resetEndDateErr();", endDateStr)
<p
class="text-xs text-red -mt-2"
x-show="endDateError && !isSubmitting"
x-cloak
x-text="endDateError"
></p>
</div>
</div>
<!-- Finals Section -->
<div class="bg-surface0 border border-surface1 rounded-lg p-6">
<h2 class="text-2xl font-bold text-text mb-4 flex items-center gap-2">
<span class="text-yellow">★</span>
Finals
</h2>
<div class="space-y-4">
@datepicker.DatePickerWithDefault("finals_start_date", "finals_start_date", "Start Date (Optional)", "DD/MM/YYYY", false, "resetFinalsStartDateErr();", finalsStartDateStr)
<p
class="text-xs text-red -mt-2"
x-show="finalsStartDateError && !isSubmitting"
x-cloak
x-text="finalsStartDateError"
></p>
@datepicker.DatePickerWithDefault("finals_end_date", "finals_end_date", "End Date (Optional)", "DD/MM/YYYY", false, "resetFinalsEndDateErr();", finalsEndDateStr)
<p
class="text-xs text-red -mt-2"
x-show="finalsEndDateError && !isSubmitting"
x-cloak
x-text="finalsEndDateError"
></p>
</div>
</div>
</div>
<!-- Leagues Section -->
@LeaguesSection(season, allLeagues)
<!-- General Error Message -->
<div
class="px-6 pb-6"
x-show="generalError"
x-cloak
>
<div class="bg-red/10 border border-red rounded-lg p-4">
<p class="text-sm text-red text-center" x-text="generalError"></p>
</div>
</div>
</div>
</form>
}
func formatDateInput(t time.Time) string {
return t.Format("02/01/2006")
}