we have fixtures ladies and gentleman
This commit is contained in:
@@ -1,15 +1,85 @@
|
||||
package seasonsview
|
||||
|
||||
import "git.haelnorr.com/h/oslstats/internal/db"
|
||||
import "git.haelnorr.com/h/oslstats/internal/permissions"
|
||||
import "git.haelnorr.com/h/oslstats/internal/contexts"
|
||||
import "fmt"
|
||||
|
||||
templ SeasonLeagueFixturesPage(season *db.Season, league *db.League) {
|
||||
templ SeasonLeagueFixturesPage(season *db.Season, league *db.League, fixtures []*db.Fixture) {
|
||||
@SeasonLeagueLayout("fixtures", season, league) {
|
||||
@SeasonLeagueFixtures()
|
||||
@SeasonLeagueFixtures(season, league, fixtures)
|
||||
}
|
||||
}
|
||||
|
||||
templ SeasonLeagueFixtures() {
|
||||
<div class="bg-surface0 border border-surface1 rounded-lg p-8 text-center">
|
||||
<p class="text-subtext0 text-lg">Coming Soon...</p>
|
||||
templ SeasonLeagueFixtures(season *db.Season, league *db.League, fixtures []*db.Fixture) {
|
||||
{{
|
||||
permCache := contexts.Permissions(ctx)
|
||||
canManage := permCache.HasPermission(permissions.FixturesManage)
|
||||
|
||||
// Group fixtures by game week (only allocated ones)
|
||||
type gameWeekGroup struct {
|
||||
Week int
|
||||
Fixtures []*db.Fixture
|
||||
}
|
||||
groups := []gameWeekGroup{}
|
||||
groupMap := map[int]int{} // week -> index in groups
|
||||
for _, f := range fixtures {
|
||||
if f.GameWeek == nil {
|
||||
continue
|
||||
}
|
||||
idx, exists := groupMap[*f.GameWeek]
|
||||
if !exists {
|
||||
idx = len(groups)
|
||||
groupMap[*f.GameWeek] = idx
|
||||
groups = append(groups, gameWeekGroup{Week: *f.GameWeek, Fixtures: []*db.Fixture{}})
|
||||
}
|
||||
groups[idx].Fixtures = append(groups[idx].Fixtures, f)
|
||||
}
|
||||
}}
|
||||
<div>
|
||||
if canManage {
|
||||
<div class="flex justify-end mb-4">
|
||||
<a
|
||||
href={ templ.SafeURL(fmt.Sprintf("/seasons/%s/leagues/%s/fixtures/manage", season.ShortName, league.ShortName)) }
|
||||
class="rounded-lg px-4 py-2 hover:cursor-pointer text-center text-sm
|
||||
bg-blue hover:bg-blue/80 text-mantle transition"
|
||||
>
|
||||
Manage Fixtures
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
if len(groups) == 0 {
|
||||
<div class="bg-surface0 border border-surface1 rounded-lg p-8 text-center">
|
||||
<p class="text-subtext0 text-lg">No fixtures scheduled yet.</p>
|
||||
</div>
|
||||
} else {
|
||||
<div class="space-y-4">
|
||||
for _, group := range groups {
|
||||
<div class="bg-surface0 border border-surface1 rounded-lg overflow-hidden">
|
||||
<div class="bg-mantle border-b border-surface1 px-4 py-3">
|
||||
<h3 class="text-lg font-bold text-text">Game Week { fmt.Sprint(group.Week) }</h3>
|
||||
</div>
|
||||
<div class="divide-y divide-surface1">
|
||||
for _, fixture := range group.Fixtures {
|
||||
<div class="px-4 py-3 flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-xs font-mono text-subtext0 bg-mantle px-2 py-0.5 rounded">
|
||||
R{ fmt.Sprint(fixture.Round) }
|
||||
</span>
|
||||
<span class="text-text">
|
||||
{ fixture.HomeTeam.Name }
|
||||
</span>
|
||||
<span class="text-subtext0 text-sm">vs</span>
|
||||
<span class="text-text">
|
||||
{ fixture.AwayTeam.Name }
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
477
internal/view/seasonsview/season_league_fixtures_manage.templ
Normal file
477
internal/view/seasonsview/season_league_fixtures_manage.templ
Normal file
@@ -0,0 +1,477 @@
|
||||
package seasonsview
|
||||
|
||||
import "git.haelnorr.com/h/oslstats/internal/db"
|
||||
import "git.haelnorr.com/h/oslstats/internal/view/baseview"
|
||||
import "encoding/json"
|
||||
import "fmt"
|
||||
|
||||
type FixtureJSON struct {
|
||||
ID int `json:"id"`
|
||||
HomeTeam string `json:"homeTeam"`
|
||||
AwayTeam string `json:"awayTeam"`
|
||||
Round int `json:"round"`
|
||||
GameWeek *int `json:"gameWeek"`
|
||||
}
|
||||
|
||||
func fixtureToJSON(f *db.Fixture) FixtureJSON {
|
||||
return FixtureJSON{
|
||||
ID: f.ID,
|
||||
HomeTeam: f.HomeTeam.Name,
|
||||
AwayTeam: f.AwayTeam.Name,
|
||||
Round: f.Round,
|
||||
GameWeek: f.GameWeek,
|
||||
}
|
||||
}
|
||||
|
||||
func fixturesToJSON(fixtures []*db.Fixture) string {
|
||||
data := make([]FixtureJSON, len(fixtures))
|
||||
for i, f := range fixtures {
|
||||
data[i] = fixtureToJSON(f)
|
||||
}
|
||||
b, _ := json.Marshal(data)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
templ SeasonLeagueManageFixturesPage(season *db.Season, league *db.League, fixtures []*db.Fixture) {
|
||||
@baseview.Layout(fmt.Sprintf("%s - %s - Manage Fixtures", season.Name, league.Name)) {
|
||||
<div class="max-w-screen-2xl mx-auto px-4 py-8">
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<a
|
||||
href={ templ.SafeURL(fmt.Sprintf("/seasons/%s/leagues/%s/fixtures", season.ShortName, league.ShortName)) }
|
||||
class="rounded-lg px-4 py-2 hover:cursor-pointer text-center
|
||||
bg-surface1 hover:bg-surface2 text-text transition"
|
||||
>
|
||||
← Back to Fixtures
|
||||
</a>
|
||||
<h1 class="text-2xl font-bold text-text">Manage Fixtures - { season.Name } - { league.Name }</h1>
|
||||
</div>
|
||||
@SeasonLeagueManageFixtures(season, league, fixtures)
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
templ SeasonLeagueManageFixtures(season *db.Season, league *db.League, fixtures []*db.Fixture) {
|
||||
<div
|
||||
id="manage-fixtures-content"
|
||||
x-data={ fmt.Sprintf("fixturesManager(%s, '%s', '%s')", fixturesToJSON(fixtures), season.ShortName, league.ShortName) }
|
||||
x-cloak
|
||||
>
|
||||
<!-- Controls -->
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<!-- Generate -->
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
x-model.number="generateRounds"
|
||||
min="1"
|
||||
max="20"
|
||||
placeholder="Rounds"
|
||||
class="w-24 py-2 px-3 rounded-lg text-sm bg-base border-2 border-overlay0
|
||||
focus:border-blue outline-none text-text"
|
||||
/>
|
||||
<button
|
||||
@click="generate()"
|
||||
:disabled="isGenerating || generateRounds < 1"
|
||||
class="rounded-lg px-4 py-2 hover:cursor-pointer text-center text-sm
|
||||
bg-blue hover:bg-blue/80 text-mantle transition
|
||||
disabled:bg-blue/40 disabled:cursor-not-allowed"
|
||||
>
|
||||
<span x-text="isGenerating ? 'Generating...' : 'Generate Round'"></span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Clear All -->
|
||||
<button
|
||||
x-show="allFixtures.length > 0"
|
||||
@click="clearAll()"
|
||||
class="rounded-lg px-4 py-2 hover:cursor-pointer text-center text-sm
|
||||
bg-red hover:bg-red/80 text-mantle transition"
|
||||
>
|
||||
Clear All
|
||||
</button>
|
||||
<!-- Save -->
|
||||
<button
|
||||
x-show="unsavedChanges"
|
||||
@click="save()"
|
||||
:disabled="isSaving || !canSave()"
|
||||
class="rounded-lg px-4 py-2 hover:cursor-pointer text-center text-sm
|
||||
bg-green hover:bg-green/75 text-mantle transition
|
||||
disabled:bg-green/40 disabled:cursor-not-allowed ml-auto"
|
||||
>
|
||||
<span x-text="isSaving ? 'Saving...' : 'Save'"></span>
|
||||
</button>
|
||||
<span
|
||||
x-show="unsavedChanges && !canSave()"
|
||||
class="text-yellow text-xs ml-2"
|
||||
>
|
||||
All game weeks must have at least 1 fixture
|
||||
</span>
|
||||
</div>
|
||||
<!-- Main content panels -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
||||
<!-- LEFT PANEL: Game Weeks -->
|
||||
<div class="lg:col-span-2 bg-surface0 border border-surface1 rounded-lg p-4 min-h-96">
|
||||
<!-- List View -->
|
||||
<div x-show="selectedGameWeek === null">
|
||||
<h3 class="text-lg font-bold text-text mb-4">Game Weeks</h3>
|
||||
<div x-show="allGameWeekNumbers.length === 0" class="text-subtext0 text-sm italic mb-4">
|
||||
No game weeks yet. Add one to start allocating fixtures.
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<template x-for="week in allGameWeekNumbers" :key="week">
|
||||
<div
|
||||
class="bg-mantle border border-surface1 rounded-lg p-4
|
||||
hover:bg-surface1 transition group relative"
|
||||
:class="{ 'border-blue/50': dropTarget === week }"
|
||||
@click="selectGameWeek(week)"
|
||||
@dragover.prevent="dropTarget = week"
|
||||
@dragleave="if (dropTarget === week) dropTarget = null"
|
||||
@drop.prevent="onDrop(week)"
|
||||
>
|
||||
<div class="flex items-center justify-between hover:cursor-pointer">
|
||||
<div>
|
||||
<span class="font-semibold text-text" x-text="'Game Week ' + week"></span>
|
||||
<span class="text-subtext0 text-sm ml-2">
|
||||
(<span x-text="getFixtureCount(week)"></span>
|
||||
<span x-text="getFixtureCount(week) === 1 ? 'fixture' : 'fixtures'"></span>)
|
||||
</span>
|
||||
</div>
|
||||
<!-- Preview of first few fixtures -->
|
||||
<div class="flex items-center gap-2">
|
||||
<template x-for="f in getPreview(week)" :key="f.id">
|
||||
<span class="text-xs text-subtext0 bg-surface0 px-2 py-0.5 rounded">
|
||||
<span x-text="f.homeTeam"></span> vs <span x-text="f.awayTeam"></span>
|
||||
</span>
|
||||
</template>
|
||||
<span
|
||||
x-show="getFixtureCount(week) > 3"
|
||||
class="text-xs text-subtext1"
|
||||
x-text="'+ ' + (getFixtureCount(week) - 3) + ' more'"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<!-- Add Game Week -->
|
||||
<button
|
||||
@click="addGameWeek()"
|
||||
class="w-full mt-3 py-3 border-2 border-dashed border-surface1 rounded-lg
|
||||
text-subtext0 hover:text-text hover:border-surface2
|
||||
transition hover:cursor-pointer text-sm"
|
||||
>
|
||||
+ Add Game Week
|
||||
</button>
|
||||
</div>
|
||||
<!-- Detail View -->
|
||||
<div x-show="selectedGameWeek !== null">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<button
|
||||
@click="backToList()"
|
||||
class="text-blue hover:text-blue/80 transition hover:cursor-pointer text-sm"
|
||||
>
|
||||
← Back
|
||||
</button>
|
||||
<h3 class="text-lg font-bold text-text" x-text="'Game Week ' + selectedGameWeek"></h3>
|
||||
<span class="text-subtext0 text-sm">
|
||||
(<span x-text="getFixtureCount(selectedGameWeek)"></span>
|
||||
<span x-text="getFixtureCount(selectedGameWeek) === 1 ? 'fixture' : 'fixtures'"></span>)
|
||||
</span>
|
||||
<!-- Delete Week (only if empty) -->
|
||||
<button
|
||||
x-show="getFixtureCount(selectedGameWeek) === 0"
|
||||
@click="deleteGameWeek(selectedGameWeek)"
|
||||
class="ml-auto text-red hover:text-red/80 transition hover:cursor-pointer text-sm"
|
||||
>
|
||||
Delete Week
|
||||
</button>
|
||||
</div>
|
||||
<!-- Drop Zone -->
|
||||
<div
|
||||
class="bg-mantle border-2 rounded-lg p-4 min-h-48 transition-colors"
|
||||
:class="dropTarget === selectedGameWeek ? 'border-blue/50' : 'border-surface1'"
|
||||
@dragover.prevent="dropTarget = selectedGameWeek"
|
||||
@dragleave="if (dropTarget === selectedGameWeek) dropTarget = null"
|
||||
@drop.prevent="onDrop(selectedGameWeek)"
|
||||
>
|
||||
<div x-show="getFixtureCount(selectedGameWeek) === 0" class="text-subtext1 text-sm italic text-center py-8">
|
||||
Drop fixtures here
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<template x-for="fixture in getGameWeekFixtures(selectedGameWeek)" :key="fixture.id">
|
||||
<div
|
||||
draggable="true"
|
||||
@dragstart="onDragStart($event, fixture)"
|
||||
@dragend="onDragEnd()"
|
||||
class="bg-surface0 border border-surface1 rounded-lg px-4 py-3
|
||||
cursor-grab active:cursor-grabbing hover:bg-surface1 transition
|
||||
flex items-center justify-between"
|
||||
:class="{ 'opacity-50': draggedFixture && draggedFixture.id === fixture.id }"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-xs font-mono text-subtext0 bg-mantle px-2 py-0.5 rounded">
|
||||
R<span x-text="fixture.round"></span>
|
||||
</span>
|
||||
<span class="text-text" x-text="fixture.homeTeam"></span>
|
||||
<span class="text-subtext0 text-sm">vs</span>
|
||||
<span class="text-text" x-text="fixture.awayTeam"></span>
|
||||
</div>
|
||||
<button
|
||||
@click.stop="unallocateFixture(fixture)"
|
||||
class="text-subtext0 hover:text-red transition hover:cursor-pointer text-xs"
|
||||
title="Remove from game week"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- RIGHT PANEL: Unallocated Fixtures -->
|
||||
<div class="bg-surface0 border border-surface1 rounded-lg p-4 min-h-96">
|
||||
<h3 class="text-lg font-bold text-text mb-4">
|
||||
Unallocated
|
||||
<span class="text-subtext0 font-normal text-sm">
|
||||
(<span x-text="unallocatedFixtures.length"></span>)
|
||||
</span>
|
||||
</h3>
|
||||
<div
|
||||
class="space-y-2 max-h-[600px] overflow-y-auto transition-colors rounded-lg p-1"
|
||||
:class="dropTarget === 'unallocated' ? 'bg-surface1/30' : ''"
|
||||
@dragover.prevent="dropTarget = 'unallocated'"
|
||||
@dragleave="if (dropTarget === 'unallocated') dropTarget = null"
|
||||
@drop.prevent="onDrop('unallocated')"
|
||||
>
|
||||
<div x-show="unallocatedFixtures.length === 0" class="text-subtext1 text-sm italic text-center py-8">
|
||||
<span x-show="allFixtures.length === 0">No fixtures generated yet.</span>
|
||||
<span x-show="allFixtures.length > 0">All fixtures allocated!</span>
|
||||
</div>
|
||||
<template x-for="fixture in unallocatedFixtures" :key="fixture.id">
|
||||
<div
|
||||
draggable="true"
|
||||
@dragstart="onDragStart($event, fixture)"
|
||||
@dragend="onDragEnd()"
|
||||
class="bg-mantle border border-surface1 rounded-lg px-4 py-3
|
||||
cursor-grab active:cursor-grabbing hover:bg-surface1 transition"
|
||||
:class="{ 'opacity-50': draggedFixture && draggedFixture.id === fixture.id }"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-xs font-mono text-subtext0 bg-surface0 px-2 py-0.5 rounded">
|
||||
R<span x-text="fixture.round"></span>
|
||||
</span>
|
||||
<span class="text-text" x-text="fixture.homeTeam"></span>
|
||||
<span class="text-subtext0 text-sm">vs</span>
|
||||
<span class="text-text" x-text="fixture.awayTeam"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Alpine.js component -->
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('fixturesManager', (initialFixtures, seasonShortName, leagueShortName) => ({
|
||||
allFixtures: initialFixtures || [],
|
||||
seasonShortName: seasonShortName,
|
||||
leagueShortName: leagueShortName,
|
||||
|
||||
// UI state
|
||||
selectedGameWeek: null,
|
||||
unsavedChanges: false,
|
||||
isSaving: false,
|
||||
isGenerating: false,
|
||||
generateRounds: 1,
|
||||
|
||||
// Drag state
|
||||
draggedFixture: null,
|
||||
dropTarget: null,
|
||||
|
||||
// Computed
|
||||
get unallocatedFixtures() {
|
||||
return this.allFixtures
|
||||
.filter(f => f.gameWeek === null)
|
||||
.sort((a, b) => a.round - b.round || a.id - b.id);
|
||||
},
|
||||
|
||||
get allGameWeekNumbers() {
|
||||
const weeks = new Set();
|
||||
for (const f of this.allFixtures) {
|
||||
if (f.gameWeek !== null) {
|
||||
weeks.add(f.gameWeek);
|
||||
}
|
||||
}
|
||||
// Also include manually added empty weeks
|
||||
for (const w of this._emptyWeeks || []) {
|
||||
weeks.add(w);
|
||||
}
|
||||
return [...weeks].sort((a, b) => a - b);
|
||||
},
|
||||
|
||||
// Track empty weeks that user created
|
||||
_emptyWeeks: [],
|
||||
|
||||
getGameWeekFixtures(week) {
|
||||
return this.allFixtures
|
||||
.filter(f => f.gameWeek === week)
|
||||
.sort((a, b) => a.round - b.round || a.id - b.id);
|
||||
},
|
||||
|
||||
getFixtureCount(week) {
|
||||
return this.allFixtures.filter(f => f.gameWeek === week).length;
|
||||
},
|
||||
|
||||
getPreview(week) {
|
||||
return this.getGameWeekFixtures(week).slice(0, 3);
|
||||
},
|
||||
|
||||
// Game week management
|
||||
addGameWeek() {
|
||||
const existing = this.allGameWeekNumbers;
|
||||
const next = existing.length > 0 ? Math.max(...existing) + 1 : 1;
|
||||
this._emptyWeeks.push(next);
|
||||
this.unsavedChanges = true;
|
||||
},
|
||||
|
||||
deleteGameWeek(week) {
|
||||
if (this.getFixtureCount(week) > 0) return;
|
||||
this._emptyWeeks = this._emptyWeeks.filter(w => w !== week);
|
||||
if (this.selectedGameWeek === week) {
|
||||
this.selectedGameWeek = null;
|
||||
}
|
||||
this.unsavedChanges = true;
|
||||
},
|
||||
|
||||
selectGameWeek(week) {
|
||||
this.selectedGameWeek = week;
|
||||
},
|
||||
|
||||
backToList() {
|
||||
this.selectedGameWeek = null;
|
||||
},
|
||||
|
||||
// Drag and drop
|
||||
onDragStart(event, fixture) {
|
||||
this.draggedFixture = fixture;
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
event.dataTransfer.setData('text/plain', fixture.id);
|
||||
},
|
||||
|
||||
onDragEnd() {
|
||||
this.draggedFixture = null;
|
||||
this.dropTarget = null;
|
||||
},
|
||||
|
||||
onDrop(target) {
|
||||
if (!this.draggedFixture) return;
|
||||
|
||||
const fixture = this.allFixtures.find(f => f.id === this.draggedFixture.id);
|
||||
if (!fixture) return;
|
||||
|
||||
if (target === 'unallocated') {
|
||||
fixture.gameWeek = null;
|
||||
} else {
|
||||
fixture.gameWeek = target;
|
||||
// Remove from empty weeks if it now has fixtures
|
||||
this._emptyWeeks = this._emptyWeeks.filter(w => w !== target);
|
||||
}
|
||||
|
||||
this.unsavedChanges = true;
|
||||
this.draggedFixture = null;
|
||||
this.dropTarget = null;
|
||||
},
|
||||
|
||||
unallocateFixture(fixture) {
|
||||
const f = this.allFixtures.find(ff => ff.id === fixture.id);
|
||||
if (f) {
|
||||
const oldWeek = f.gameWeek;
|
||||
f.gameWeek = null;
|
||||
// If the old week is now empty, track it
|
||||
if (oldWeek !== null && this.getFixtureCount(oldWeek) === 0) {
|
||||
this._emptyWeeks.push(oldWeek);
|
||||
}
|
||||
this.unsavedChanges = true;
|
||||
}
|
||||
},
|
||||
|
||||
// Validation
|
||||
canSave() {
|
||||
const weeks = this.allGameWeekNumbers;
|
||||
if (weeks.length === 0) return false;
|
||||
for (const week of weeks) {
|
||||
if (this.getFixtureCount(week) === 0) return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// Server actions
|
||||
generate() {
|
||||
if (this.generateRounds < 1) return;
|
||||
this.isGenerating = true;
|
||||
|
||||
const form = new FormData();
|
||||
form.append('season_short_name', this.seasonShortName);
|
||||
form.append('league_short_name', this.leagueShortName);
|
||||
form.append('round', this.generateRounds);
|
||||
|
||||
htmx.ajax('POST', '/fixtures/generate', {
|
||||
target: '#manage-fixtures-content',
|
||||
swap: 'outerHTML',
|
||||
values: Object.fromEntries(form)
|
||||
}).finally(() => {
|
||||
this.isGenerating = false;
|
||||
});
|
||||
},
|
||||
|
||||
save() {
|
||||
if (!this.canSave()) return;
|
||||
this.isSaving = true;
|
||||
|
||||
const form = new FormData();
|
||||
form.append('season_short_name', this.seasonShortName);
|
||||
form.append('league_short_name', this.leagueShortName);
|
||||
|
||||
this.allFixtures.forEach((f, i) => {
|
||||
form.append('allocations[' + i + '][id]', f.id);
|
||||
form.append('allocations[' + i + '][game_week]', f.gameWeek !== null ? f.gameWeek : 0);
|
||||
});
|
||||
|
||||
fetch('/fixtures/update-game-weeks', {
|
||||
method: 'POST',
|
||||
body: form
|
||||
}).then(response => {
|
||||
if (response.ok) {
|
||||
this.unsavedChanges = false;
|
||||
}
|
||||
this.isSaving = false;
|
||||
}).catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
},
|
||||
|
||||
clearAll() {
|
||||
const seasonShort = this.seasonShortName;
|
||||
const leagueShort = this.leagueShortName;
|
||||
|
||||
window.dispatchEvent(new CustomEvent('confirm-action', {
|
||||
detail: {
|
||||
title: 'Clear All Fixtures',
|
||||
message: 'This will delete all fixtures for this league. This action cannot be undone.',
|
||||
action: () => {
|
||||
htmx.ajax('DELETE',
|
||||
'/seasons/' + seasonShort + '/leagues/' + leagueShort + '/fixtures',
|
||||
{
|
||||
target: '#manage-fixtures-content',
|
||||
swap: 'outerHTML'
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
}
|
||||
Reference in New Issue
Block a user