191 lines
6.6 KiB
Plaintext
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")
|
|
}
|