Sorting working on scoring guides
This commit is contained in:
parent
eb68a5fc2b
commit
43647583e7
|
|
@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Auth;
|
||||||
use function abort;
|
use function abort;
|
||||||
use function dd;
|
use function dd;
|
||||||
use function request;
|
use function request;
|
||||||
|
use function response;
|
||||||
use function sendMessage;
|
use function sendMessage;
|
||||||
|
|
||||||
class ScoringGuideController extends Controller
|
class ScoringGuideController extends Controller
|
||||||
|
|
@ -36,11 +37,16 @@ class ScoringGuideController extends Controller
|
||||||
return redirect('/admin/scoring');
|
return redirect('/admin/scoring');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(ScoringGuide $guide)
|
public function edit(Request $request, ScoringGuide $guide)
|
||||||
{
|
{
|
||||||
if (! Auth::user()->is_admin) abort(403);
|
if (! Auth::user()->is_admin) abort(403);
|
||||||
$subscores = SubscoreDefinition::where('scoring_guide_id',$guide->id)->orderBy('display_order')->get();
|
$tab = $request->query('tab') ?? 'detail';
|
||||||
return view('admin.scoring.edit',['guide'=>$guide,'subscores'=>$subscores]);
|
if ($tab == 'tiebreakOrder') {
|
||||||
|
$subscores = SubscoreDefinition::where('scoring_guide_id', $guide->id)->orderBy('tiebreak_order')->get();
|
||||||
|
} else {
|
||||||
|
$subscores = SubscoreDefinition::where('scoring_guide_id', $guide->id)->orderBy('display_order')->get();
|
||||||
|
}
|
||||||
|
return view('admin.scoring.edit',['guide'=>$guide,'subscores'=>$subscores, 'tab'=>$tab]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(ScoringGuide $guide)
|
public function update(ScoringGuide $guide)
|
||||||
|
|
@ -64,8 +70,6 @@ class ScoringGuideController extends Controller
|
||||||
'name' => ['required'],
|
'name' => ['required'],
|
||||||
'max_score' => ['required','integer'],
|
'max_score' => ['required','integer'],
|
||||||
'weight'=>['required','integer'],
|
'weight'=>['required','integer'],
|
||||||
'display_order'=>['required','integer'],
|
|
||||||
'tiebreak_order'=>['required','integer'],
|
|
||||||
'for_seating'=>['nullable','boolean'],
|
'for_seating'=>['nullable','boolean'],
|
||||||
'for_advance'=>['nullable','boolean'],
|
'for_advance'=>['nullable','boolean'],
|
||||||
]);
|
]);
|
||||||
|
|
@ -73,17 +77,44 @@ class ScoringGuideController extends Controller
|
||||||
$for_seating = $request->has('for_seating') ? (bool) $request->input('for_seating') : false;
|
$for_seating = $request->has('for_seating') ? (bool) $request->input('for_seating') : false;
|
||||||
$for_advance = $request->has('for_advance') ? (bool) $request->input('for_advance') : false;
|
$for_advance = $request->has('for_advance') ? (bool) $request->input('for_advance') : false;
|
||||||
|
|
||||||
|
$display_order = SubscoreDefinition::where('scoring_guide_id','=',$guide->id)->max('display_order') + 1;
|
||||||
|
$tiebreak_order = SubscoreDefinition::where('scoring_guide_id','=',$guide->id)->max('tiebreak_order') + 1;
|
||||||
|
|
||||||
$subscore = SubscoreDefinition::create([
|
$subscore = SubscoreDefinition::create([
|
||||||
'scoring_guide_id' => $guide->id,
|
'scoring_guide_id' => $guide->id,
|
||||||
'name' => $validateData['name'],
|
'name' => $validateData['name'],
|
||||||
'max_score' => $validateData['max_score'],
|
'max_score' => $validateData['max_score'],
|
||||||
'weight' => $validateData['weight'],
|
'weight' => $validateData['weight'],
|
||||||
'display_order' => $validateData['display_order'],
|
'display_order' => $display_order,
|
||||||
'tiebreak_order' => $validateData['tiebreak_order'],
|
'tiebreak_order' => $tiebreak_order,
|
||||||
'for_seating' => $for_seating,
|
'for_seating' => $for_seating,
|
||||||
'for_advance' => $for_advance,
|
'for_advance' => $for_advance,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return redirect('/admin/scoring/guides/' . $guide->id . '/edit' )->with('success','Subscore added');
|
return redirect('/admin/scoring/guides/' . $guide->id . '/edit' )->with('success','Subscore added');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function reorder_display(Request $request)
|
||||||
|
{
|
||||||
|
if(! Auth::user()->is_admin) abort(403);
|
||||||
|
$order = $request->order;
|
||||||
|
foreach ($order as $index => $id) {
|
||||||
|
$subscore = SubscoreDefinition::find($id);
|
||||||
|
$subscore->update(['display_order' => $index]);
|
||||||
|
}
|
||||||
|
return response()->json(['status'=>'success']);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reorder_tiebreak(Request $request)
|
||||||
|
{
|
||||||
|
if(! Auth::user()->is_admin) abort(403);
|
||||||
|
$order = $request->order;
|
||||||
|
foreach ($order as $index => $id) {
|
||||||
|
$subscore = SubscoreDefinition::find($id);
|
||||||
|
$subscore->update(['tiebreak_order' => $index]);
|
||||||
|
}
|
||||||
|
return response()->json(['status'=>'success']);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
@php use App\Settings; @endphp
|
||||||
|
|
||||||
|
<x-table.table with_title_area >
|
||||||
|
<x-slot:title>Subscore Details</x-slot:title>
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<x-table.th>Name</x-table.th>
|
||||||
|
<x-table.th>Max Score</x-table.th>
|
||||||
|
<x-table.th>Weight</x-table.th>
|
||||||
|
<x-table.th>For Seating</x-table.th>
|
||||||
|
@if(Settings::advanceTo())
|
||||||
|
<x-table.th>For {{ Settings::advanceTo() }}</x-table.th>
|
||||||
|
@endif
|
||||||
|
<x-table.th spacer_only></x-table.th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<x-table.body>
|
||||||
|
@foreach ($subscores as $subscore)
|
||||||
|
<tr>
|
||||||
|
<x-table.td>{{ $subscore->name }}</x-table.td>
|
||||||
|
<x-table.td>{{ $subscore->max_score }}</x-table.td>
|
||||||
|
<x-table.td>{{ $subscore->weight }}</x-table.td>
|
||||||
|
<x-table.td>{{ $subscore->for_seating ? 'Yes' : 'No' }}</x-table.td>
|
||||||
|
@if(Settings::advanceTo())
|
||||||
|
<x-table.td>{{ $subscore->for_advance ? 'Yes' : 'No' }}</x-table.td>
|
||||||
|
@endif
|
||||||
|
<x-table.td>
|
||||||
|
{{-- This came from AI, consider--}}
|
||||||
|
{{-- <x-form.form method="PATCH" action="/admin/scoring/guides/{{ $guide->id }}/subscore/{{ $subscore->id }}">--}}
|
||||||
|
{{-- <x-table.button>Save</x-table.button>--}}
|
||||||
|
{{-- <x-table.button @click="if(confirm('Are you sure?')) { $dispatch('delete', {id: {{ $subscore->id }} }) }">Delete</x-table.button>--}}
|
||||||
|
{{-- <x-table.button @click="rename = ! rename">Rename</x-table.button>--}}
|
||||||
|
{{-- </x-form.form>--}}
|
||||||
|
|
||||||
|
</x-table.td>
|
||||||
|
</tr>
|
||||||
|
{{-- WHERE DID THIS EVEN COME FROM???--}}
|
||||||
|
{{-- <template x-on:delete.window="document.querySelector('form[action=\'/admin/scoring/guides/{{ $guide->id }}/subscore/\'+event.detail.id+\'\']').submit()"></template>--}}
|
||||||
|
@endforeach
|
||||||
|
</x-table.body>
|
||||||
|
<tfoot>
|
||||||
|
<tr><x-table.th class="!pb-0">Add Subscore</x-table.th></tr><tr>
|
||||||
|
<x-form.form method="POST" action="/admin/scoring/guides/{{ $guide->id }}/subscore">
|
||||||
|
<x-table.td><x-form.field name="name"></x-form.field></x-table.td>
|
||||||
|
<x-table.td><x-form.field name="max_score" type="number"></x-form.field></x-table.td>
|
||||||
|
<x-table.td><x-form.field name="weight" type="number"></x-form.field></x-table.td>
|
||||||
|
<x-table.td><x-form.toggle-checkbox name="for_seating" checked></x-form.toggle-checkbox></x-table.td>
|
||||||
|
@if(Settings::advanceTo())
|
||||||
|
<x-table.td><x-form.toggle-checkbox name="for_advance" checked></x-form.toggle-checkbox></x-table.td>
|
||||||
|
@endif
|
||||||
|
<td><x-table.button>Save</x-table.button></td>
|
||||||
|
</x-form.form>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</x-table.table>
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
@php use App\Settings; @endphp
|
||||||
|
|
||||||
|
<x-table.table with_title_area >
|
||||||
|
<x-slot:title class="-mb-5">Subscore Display Order</x-slot:title>
|
||||||
|
<div x-data="sortableListForTiebreak('/admin/scoring/reorder-display')" x-init="init">
|
||||||
|
<x-table.body id="sortable-list">
|
||||||
|
@foreach ($subscores as $subscore)
|
||||||
|
<tr data-id="{{ $subscore->id }}">
|
||||||
|
<x-table.td>{{ $subscore->name }}</x-table.td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</x-table.body>
|
||||||
|
</div>
|
||||||
|
</x-table.table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function sortableListForTiebreak(submitLink) {
|
||||||
|
return {
|
||||||
|
init() {
|
||||||
|
let el = document.getElementById('sortable-list');
|
||||||
|
let sortable = Sortable.create(el, {
|
||||||
|
onEnd: function (evt) {
|
||||||
|
let order = Array.from(el.children).map((item, index) => item.getAttribute('data-id'));
|
||||||
|
fetch(submitLink, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ order })
|
||||||
|
}).then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.status === 'success') {
|
||||||
|
console.log('Order updated successfully');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(data.status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
@php
|
||||||
|
$normal_classes = 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 w-1/4 border-b-2 py-4 px-1 text-center text-sm font-medium';
|
||||||
|
$active_classes = 'border-indigo-500 text-indigo-600 w-1/4 border-b-2 py-4 px-1 text-center text-sm font-medium';
|
||||||
|
@endphp
|
||||||
|
<div>
|
||||||
|
<div class="sm:hidden">
|
||||||
|
<label for="tabs" class="sr-only">Select a tab</label>
|
||||||
|
<!-- TODO Use an "onChange" listener to redirect the user to the selected tab URL. -->
|
||||||
|
<select id="tabs" name="tabs" class="block w-full rounded-md border-gray-300 focus:border-indigo-500 focus:ring-indigo-500">
|
||||||
|
<option>Details</option>
|
||||||
|
<option selected>Display Order</option>
|
||||||
|
<option>Tiebreak Order</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="hidden sm:block">
|
||||||
|
<div class="border-b border-gray-200">
|
||||||
|
<nav class="-mb-px flex" aria-label="Tabs">
|
||||||
|
<!-- Current: "border-indigo-500 text-indigo-600", Default: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700" -->
|
||||||
|
<a href="{{ request()->getPathInfo() }}?tab=detail" class="{{ $tab == 'detail' ? $active_classes : $normal_classes }}">Details</a>
|
||||||
|
<a href="{{ request()->getPathInfo() }}?tab=displayOrder" class="{{ $tab == 'displayOrder' ? $active_classes : $normal_classes }}">Display Order</a>
|
||||||
|
<a href="{{ request()->getPathInfo() }}?tab=tiebreakOrder" class="{{ $tab == 'tiebreakOrder' ? $active_classes : $normal_classes }}">Tiebreak Order</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
@php use App\Settings; @endphp
|
||||||
|
|
||||||
|
<x-table.table with_title_area >
|
||||||
|
<x-slot:title class="-mb-5">Subscore Display Order</x-slot:title>
|
||||||
|
<div x-data="sortableListForDisplay('/admin/scoring/reorder-tiebreak')" x-init="init">
|
||||||
|
<x-table.body id="sortable-list">
|
||||||
|
@foreach ($subscores as $subscore)
|
||||||
|
<tr data-id="{{ $subscore->id }}">
|
||||||
|
<x-table.td>{{ $subscore->name }}</x-table.td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</x-table.body>
|
||||||
|
</div>
|
||||||
|
</x-table.table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function sortableListForDisplay(endpoint) {
|
||||||
|
return {
|
||||||
|
init() {
|
||||||
|
let el = document.getElementById('sortable-list');
|
||||||
|
let sortable = Sortable.create(el, {
|
||||||
|
onEnd: function (evt) {
|
||||||
|
let order = Array.from(el.children).map((item, index) => item.getAttribute('data-id'));
|
||||||
|
fetch(endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ order })
|
||||||
|
}).then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.status === 'success') {
|
||||||
|
console.log('Order updated successfully');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(data.status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -1,86 +1,39 @@
|
||||||
@php use App\Settings; @endphp
|
@php use App\Settings; @endphp
|
||||||
<x-layout.app x-data="{ rename: false }">
|
<x-layout.app x-data="{ rename: false }">
|
||||||
<x-slot:page_title>Scoring Rules</x-slot:page_title>
|
<x-slot:page_title>Scoring Rules</x-slot:page_title>
|
||||||
|
{{-- MAIN CARD--}}
|
||||||
{{-- MAIN CARD--}}
|
<x-card.card x-show="! rename" class="max-w-xl mx-auto">
|
||||||
<x-card.card x-show="! rename">
|
|
||||||
<x-card.heading>
|
<x-card.heading>
|
||||||
<x-slot:subheading @click="rename = ! rename">Click here to rename</x-slot:subheading>
|
<x-slot:subheading @click="rename = ! rename">Click here to rename</x-slot:subheading>
|
||||||
Scoring Guide: {{ $guide->name }}
|
Scoring Guide: {{ $guide->name }}
|
||||||
</x-card.heading>
|
|
||||||
<div class="ml-6 -mt-2 mr-6">
|
|
||||||
<x-table.table with_title_area >
|
|
||||||
<x-slot:title>Subscores</x-slot:title>
|
|
||||||
|
|
||||||
<thead>
|
</x-card.heading>
|
||||||
<tr>
|
@include('admin.scoring.edit-tabs')
|
||||||
<x-table.th>Name</x-table.th>
|
<div class="ml-6 -mt-2 mr-6">
|
||||||
<x-table.th>Max Score</x-table.th>
|
@switch($tab)
|
||||||
<x-table.th>Weight</x-table.th>
|
@case('detail')
|
||||||
<x-table.th>Display Order</x-table.th>
|
@include('admin.scoring.edit-detail')
|
||||||
<x-table.th>Tiebreak Order</x-table.th>
|
@break
|
||||||
<x-table.th>For Seating</x-table.th>
|
@case('displayOrder')
|
||||||
@if(Settings::advanceTo())
|
@include('admin.scoring.edit-display-order')
|
||||||
<x-table.th>For {{ Settings::advanceTo() }}</x-table.th>
|
@break
|
||||||
@endif
|
@case('tiebreakOrder')
|
||||||
<x-table.th spacer_only></x-table.th>
|
@include('admin.scoring.edit-tiebreak-order')
|
||||||
</tr>
|
@break
|
||||||
</thead>
|
|
||||||
<x-table.body>
|
@endswitch
|
||||||
@foreach ($subscores as $subscore)
|
|
||||||
<tr>
|
|
||||||
<x-table.td>{{ $subscore->name }}</x-table.td>
|
|
||||||
<x-table.td>{{ $subscore->max_score }}</x-table.td>
|
|
||||||
<x-table.td>{{ $subscore->weight }}</x-table.td>
|
|
||||||
<x-table.td>{{ $subscore->display_order }}</x-table.td>
|
|
||||||
<x-table.td>{{ $subscore->tiebreak_order }}</x-table.td>
|
|
||||||
<x-table.td>{{ $subscore->for_seating ? 'Yes' : 'No' }}</x-table.td>
|
|
||||||
@if(Settings::advanceTo())
|
|
||||||
<x-table.td>{{ $subscore->for_advance ? 'Yes' : 'No' }}</x-table.td>
|
|
||||||
@endif
|
|
||||||
<x-table.td>
|
|
||||||
{{-- This came from AI, consider--}}
|
|
||||||
{{-- <x-form.form method="PATCH" action="/admin/scoring/guides/{{ $guide->id }}/subscore/{{ $subscore->id }}">--}}
|
|
||||||
{{-- <x-table.button>Save</x-table.button>--}}
|
|
||||||
{{-- <x-table.button @click="if(confirm('Are you sure?')) { $dispatch('delete', {id: {{ $subscore->id }} }) }">Delete</x-table.button>--}}
|
|
||||||
{{-- <x-table.button @click="rename = ! rename">Rename</x-table.button>--}}
|
|
||||||
{{-- </x-form.form>--}}
|
|
||||||
|
|
||||||
</x-table.td>
|
|
||||||
</tr>
|
|
||||||
<template x-on:delete.window="document.querySelector('form[action=\'/admin/scoring/guides/{{ $guide->id }}/subscore/\'+event.detail.id+\'\']').submit()"></template>
|
|
||||||
@endforeach
|
|
||||||
</x-table.body>
|
|
||||||
<tfoot>
|
|
||||||
<tr><x-table.th class="!pb-0">Add Subscore</x-table.th></tr><tr>
|
|
||||||
<x-form.form method="POST" action="/admin/scoring/guides/{{ $guide->id }}/subscore">
|
|
||||||
<x-table.td><x-form.field name="name"></x-form.field></x-table.td>
|
|
||||||
<x-table.td><x-form.field name="max_score" type="number"></x-form.field></x-table.td>
|
|
||||||
<x-table.td><x-form.field name="weight" type="number"></x-form.field></x-table.td>
|
|
||||||
<x-table.td><x-form.field name="display_order"></x-form.field></x-table.td>
|
|
||||||
<x-table.td><x-form.field name="tiebreak_order"></x-form.field></x-table.td>
|
|
||||||
<x-table.td><x-form.toggle-checkbox name="for_seating" checked></x-form.toggle-checkbox></x-table.td>
|
|
||||||
@if(Settings::advanceTo())
|
|
||||||
<x-table.td><x-form.toggle-checkbox name="for_advance"></x-form.toggle-checkbox></x-table.td>
|
|
||||||
@endif
|
|
||||||
<td><x-table.button>Save</x-table.button></td>
|
|
||||||
</x-form.form>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</x-table.table>
|
|
||||||
</div>
|
</div>
|
||||||
</x-card.card>
|
</x-card.card>
|
||||||
|
|
||||||
|
|
||||||
{{-- RENAME CARD--}}
|
{{-- RENAME CARD--}}
|
||||||
<x-card.card x-show="rename" @click.outside="rename = ! rename" x-cloak>
|
<x-card.card x-show="rename" @click.outside="rename = ! rename" x-cloak>
|
||||||
<x-card.heading>Rename</x-card.heading>
|
<x-card.heading>Rename</x-card.heading>
|
||||||
<x-form.form method="PATCH" action="/admin/scoring/guides/{{ $guide->id }}/edit" class="!pt-2">
|
<x-form.form method="PATCH" action="/admin/scoring/guides/{{ $guide->id }}/edit" class="!pt-2">
|
||||||
<x-form.field name="name" label_text="New Name" value="" />
|
<x-form.field name="name" label_text="New Name" value=""/>
|
||||||
<x-form.footer submit-button-text="Rename"></x-form.footer>
|
<x-form.footer submit-button-text="Rename"></x-form.footer>
|
||||||
</x-form.form>
|
</x-form.form>
|
||||||
</x-card.card>
|
</x-card.card>
|
||||||
<div class="mt-20">
|
<div class="mt-20">
|
||||||
@php(dump($guide))
|
|
||||||
</div>
|
</div>
|
||||||
</x-layout.app>
|
</x-layout.app>
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ Route::middleware(['auth','verified',CheckIfAdmin::class])->prefix('admin/')->gr
|
||||||
Route::get('/guides/{guide}/edit','edit'); // Edit scoring guide
|
Route::get('/guides/{guide}/edit','edit'); // Edit scoring guide
|
||||||
Route::patch('/guides/{guide}/edit','update'); // Save changes to audition guide (rename)
|
Route::patch('/guides/{guide}/edit','update'); // Save changes to audition guide (rename)
|
||||||
Route::post('/guides/{guide}/subscore','subscore_store'); // Save a new subscore
|
Route::post('/guides/{guide}/subscore','subscore_store'); // Save a new subscore
|
||||||
|
Route::post('/reorder-display','reorder_display');
|
||||||
|
Route::post('/reorder-tiebreak','reorder_tiebreak');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue