Write tests - Write tests for what was done to this point that will be kept #11
|
|
@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Audition;
|
||||
use App\Models\Event;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
|
|
@ -14,16 +15,15 @@ use function compact;
|
|||
use function redirect;
|
||||
use function request;
|
||||
use function response;
|
||||
use function to_route;
|
||||
use function view;
|
||||
|
||||
class AuditionController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$auditions = Audition::with(['event', 'entries'])->orderBy('score_order')->orderBy('created_at', 'desc')->get();
|
||||
$auditions = Audition::with(['event'])->withCount('entries')->orderBy('score_order')->orderBy('created_at',
|
||||
'desc')->get();
|
||||
|
||||
return view('admin.auditions.index', ['auditions' => $auditions]);
|
||||
}
|
||||
|
|
@ -50,12 +50,16 @@ class AuditionController extends Controller
|
|||
'entry_fee' => ['required', 'numeric'],
|
||||
'minimum_grade' => ['required', 'integer'],
|
||||
'maximum_grade' => 'required|numeric|gte:minimum_grade',
|
||||
'scoring_guide_id' => 'nullable|exists:scoring_guides,id',
|
||||
], [
|
||||
'maximum_grade.gte' => 'The maximum grade must be greater than the minimum grade.',
|
||||
]);
|
||||
|
||||
$validData['for_seating'] = $request->get('for_seating') ? 1 : 0;
|
||||
$validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0;
|
||||
if (empty($alidData['scoring_guide_id'])) {
|
||||
$validData['scoring_guide_id'] = 0;
|
||||
}
|
||||
|
||||
Audition::create([
|
||||
'event_id' => $validData['event_id'],
|
||||
|
|
@ -66,9 +70,10 @@ class AuditionController extends Controller
|
|||
'maximum_grade' => $validData['maximum_grade'],
|
||||
'for_seating' => $validData['for_seating'],
|
||||
'for_advancement' => $validData['for_advancement'],
|
||||
'scoring_guide_id' => $validData['scoring_guide_id'],
|
||||
]);
|
||||
|
||||
return redirect('/admin/auditions');
|
||||
return to_route('admin.auditions.index')->with('success', 'Audition created successfully');
|
||||
}
|
||||
|
||||
public function edit(Audition $audition)
|
||||
|
|
@ -93,7 +98,7 @@ class AuditionController extends Controller
|
|||
'entry_deadline' => ['required', 'date'],
|
||||
'entry_fee' => ['required', 'numeric'],
|
||||
'minimum_grade' => ['required', 'integer'],
|
||||
'maximum_grade' => 'required|numeric|gt:minimum_grade',
|
||||
'maximum_grade' => 'required | numeric | gt:minimum_grade',
|
||||
], [
|
||||
'maximum_grade.gt' => 'The maximum grade must be greater than the minimum grade.',
|
||||
]);
|
||||
|
|
@ -112,7 +117,7 @@ class AuditionController extends Controller
|
|||
'for_advancement' => $validData['for_advancement'],
|
||||
]);
|
||||
|
||||
return redirect('/admin/auditions');
|
||||
return to_route('admin.auditions.index')->with('success', 'Audition updated successfully');
|
||||
}
|
||||
|
||||
public function reorder(Request $request)
|
||||
|
|
@ -144,6 +149,13 @@ class AuditionController extends Controller
|
|||
return response()->json(['status' => 'success']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the scoring guide for an audition
|
||||
* Used by AJAX call on the scoring guide index page
|
||||
* request should include scoring_guide_id and audition_id
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function scoringGuideUpdate(Request $request)
|
||||
{
|
||||
|
||||
|
|
@ -162,16 +174,12 @@ class AuditionController extends Controller
|
|||
|
||||
public function destroy(Audition $audition)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
// if($audition->entries->count() > 0) abort(403, 'Cannot delete an audition with entries.'
|
||||
if ($audition->entries->count() > 0) {
|
||||
return redirect()->route('admin.auditions.index')->with('error', 'Cannot delete an audition with entries.');
|
||||
}
|
||||
$audition->delete();
|
||||
|
||||
return redirect('/admin/auditions');
|
||||
return to_route('admin.auditions.index')->with('success', 'Audition deleted successfully');
|
||||
}
|
||||
|
||||
public function prepareDraw()
|
||||
|
|
@ -190,7 +198,8 @@ class AuditionController extends Controller
|
|||
return $audition->has_partial_draw();
|
||||
});
|
||||
|
||||
return view('admin.entries.prepare_draw', compact('nodraw_auditions', 'drawn_auditions', 'partial_draw_auditions'));
|
||||
return view('admin.entries.prepare_draw',
|
||||
compact('nodraw_auditions', 'drawn_auditions', 'partial_draw_auditions'));
|
||||
}
|
||||
|
||||
public function runDraw(Request $request)
|
||||
|
|
@ -203,6 +212,6 @@ class AuditionController extends Controller
|
|||
$audition->runDraw();
|
||||
}
|
||||
|
||||
return redirect('/admin/auditions/run_draw');
|
||||
return redirect(' / admin / auditions / run_draw');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Settings;
|
||||
use Illuminate\Http\Request;
|
||||
use function to_route;
|
||||
|
||||
class AuditionSettings extends Controller
|
||||
{
|
||||
|
|
@ -35,6 +36,6 @@ class AuditionSettings extends Controller
|
|||
Settings::set($key, $value);
|
||||
}
|
||||
|
||||
return view('admin.audition-settings')->with('success', 'Settings Saved');
|
||||
return to_route('audition-settings')->with('success', 'Settings Saved');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use App\Models\Event;
|
|||
use App\Models\SeatingLimit;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
use function redirect;
|
||||
|
||||
class EnsembleController extends Controller
|
||||
|
|
@ -16,16 +16,19 @@ class EnsembleController extends Controller
|
|||
public function index()
|
||||
{
|
||||
$events = Event::with('ensembles')->get();
|
||||
return view('admin.ensembles.index',compact('events'));
|
||||
|
||||
return view('admin.ensembles.index', compact('events'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
if(! Auth::user()->is_admin) abort(403);
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
request()->validate([
|
||||
'name' => 'required',
|
||||
'code' => ['required','max:6'],
|
||||
'event_id' => ['required','exists:events,id']
|
||||
'code' => ['required', 'max:6'],
|
||||
'event_id' => ['required', 'exists:events,id'],
|
||||
]);
|
||||
|
||||
Ensemble::create([
|
||||
|
|
@ -34,64 +37,78 @@ class EnsembleController extends Controller
|
|||
'event_id' => request('event_id'),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.ensembles.index')->with('success','Ensemble created successfully');
|
||||
return redirect()->route('admin.ensembles.index')->with('success', 'Ensemble created successfully');
|
||||
}
|
||||
|
||||
public function destroy(Request $request, Ensemble $ensemble)
|
||||
{
|
||||
if(! Auth::user()->is_admin) abort(403);
|
||||
if ($ensemble->seats->count() > 0) {
|
||||
return redirect()->route('admin.ensembles.index')->with('error', 'Ensemble has students seated and cannot be deleted');
|
||||
}
|
||||
$ensemble->delete();
|
||||
|
||||
return redirect()->route('admin.ensembles.index')->with('success', 'Ensemble deleted successfully');
|
||||
}
|
||||
|
||||
public function updateEnsemble(Request $request, Ensemble $ensemble)
|
||||
{
|
||||
if(! Auth::user()->is_admin) abort(403);
|
||||
request()->validate([
|
||||
'name' => 'required',
|
||||
'code' => 'required|max:6'
|
||||
'code' => 'required|max:6',
|
||||
]);
|
||||
|
||||
$ensemble->update([
|
||||
'name' => request('name'),
|
||||
'code' => request('code')
|
||||
'code' => request('code'),
|
||||
]);
|
||||
return redirect()->route('admin.ensembles.index')->with('success','Ensemble updated successfully');
|
||||
|
||||
return redirect()->route('admin.ensembles.index')->with('success', 'Ensemble updated successfully');
|
||||
}
|
||||
|
||||
public function seatingLimits(Ensemble $ensemble)
|
||||
{
|
||||
$ensembles = Ensemble::with('event')->orderBy('event_id')->get();
|
||||
$limits = [];
|
||||
$ensembles = Ensemble::with(['event'])->orderBy('event_id')->get();
|
||||
if ($ensemble->exists()) {
|
||||
$ensemble->load('seatingLimits');
|
||||
foreach ($ensemble->seatingLimits as $lim) {
|
||||
$limits[$lim->audition_id] = $lim->maximum_accepted;
|
||||
}
|
||||
return view('admin.ensembles.seatingLimits',compact('ensemble','ensembles'));
|
||||
}
|
||||
|
||||
return view('admin.ensembles.seatingLimits', compact('ensemble', 'ensembles', 'limits'));
|
||||
}
|
||||
|
||||
public function seatingLimitsSet(Request $request, Ensemble $ensemble)
|
||||
{
|
||||
$request->validate([
|
||||
'audition' => 'required',
|
||||
'audition.*' => ['integer','min:0']
|
||||
'audition.*' => ['integer', 'min:0'],
|
||||
]);
|
||||
|
||||
foreach($ensemble->auditions as $audition) {
|
||||
foreach ($ensemble->auditions as $audition) {
|
||||
SeatingLimit::upsert(
|
||||
[[
|
||||
[
|
||||
[
|
||||
'ensemble_id' => $ensemble->id,
|
||||
'audition_id' => $audition->id,
|
||||
'maximum_accepted' => $request->audition[$audition->id]
|
||||
]],
|
||||
uniqueBy: ['ensemble_id','audition_id'],
|
||||
'maximum_accepted' => $request->audition[$audition->id],
|
||||
],
|
||||
],
|
||||
uniqueBy: ['ensemble_id', 'audition_id'],
|
||||
update: ['maximum_accepted']
|
||||
);
|
||||
}
|
||||
return redirect()->route('admin.ensembles.seatingLimits')->with('success', 'Seating limits set for ' . $ensemble->name);
|
||||
|
||||
return redirect()->route('admin.ensembles.seatingLimits.ensemble', $ensemble)->with('success',
|
||||
'Seating limits set for '.$ensemble->name);
|
||||
}
|
||||
|
||||
public function updateEnsembleRank(Request $request)
|
||||
{
|
||||
if(! Auth::user()->is_admin) abort(403);
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$order = $request->input('order');
|
||||
$eventId = $request->input('event_id');
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ use App\Models\Student;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use function auditionSetting;
|
||||
use function compact;
|
||||
use function to_route;
|
||||
|
||||
class EntryController extends Controller
|
||||
{
|
||||
|
|
@ -62,21 +64,24 @@ class EntryController extends Controller
|
|||
|
||||
$entries = $entries->paginate(10);
|
||||
|
||||
return view('admin.entries.index', ['entries' => $entries,
|
||||
return view('admin.entries.index', [
|
||||
'entries' => $entries,
|
||||
'auditions' => $auditions,
|
||||
'schools' => $schools,
|
||||
'minGrade' => $minGrade,
|
||||
'maxGrade' => $maxGrade,
|
||||
'filters' => $filters]);
|
||||
'filters' => $filters,
|
||||
]);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$students = Student::with('school')->orderBy('last_name')->orderBy('first_name')->get();
|
||||
$auditions = Audition::orderBy('score_order')->get();
|
||||
$auditionsRaw = Audition::with('flags')->orderBy('score_order')->get();
|
||||
|
||||
$auditions = $auditionsRaw->reject(function ($audition) {
|
||||
return $audition->hasFlag('seats_published') || $audition->hasFlag('advancement_published');
|
||||
});
|
||||
|
||||
return view('admin.entries.create', ['students' => $students, 'auditions' => $auditions]);
|
||||
}
|
||||
|
|
@ -106,9 +111,16 @@ class EntryController extends Controller
|
|||
|
||||
public function edit(Entry $entry)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
if ($entry->audition->hasFlag('seats_published')) {
|
||||
return to_route('admin.entries.index')->with('error',
|
||||
'Entries in auditions with seats published cannot be modified');
|
||||
}
|
||||
|
||||
if ($entry->audition->hasFlag('advancement_published')) {
|
||||
return to_route('admin.entries.index')->with('error',
|
||||
'Entries in auditions with advancement results published cannot be modified');
|
||||
}
|
||||
|
||||
$students = Student::with('school')->orderBy('last_name')->orderBy('first_name')->get();
|
||||
$auditions = Audition::orderBy('score_order')->get();
|
||||
$scores = $entry->scoreSheets()->get();
|
||||
|
|
@ -119,31 +131,45 @@ class EntryController extends Controller
|
|||
|
||||
public function update(Request $request, Entry $entry)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
if ($entry->audition->hasFlag('seats_published')) {
|
||||
return to_route('admin.entries.index')->with('error',
|
||||
'Entries in auditions with seats published cannot be modified');
|
||||
}
|
||||
|
||||
if ($entry->audition->hasFlag('advancement_published')) {
|
||||
return to_route('admin.entries.index')->with('error',
|
||||
'Entries in auditions with advancement results published cannot be modified');
|
||||
}
|
||||
$validData = request()->validate([
|
||||
'student_id' => ['required', 'exists:students,id'],
|
||||
'audition_id' => ['required', 'exists:auditions,id'],
|
||||
]);
|
||||
|
||||
$validData['for_seating'] = $request->get('for_seating') ? 1 : 0;
|
||||
$validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0;
|
||||
|
||||
if (! auditionSetting('advanceTo')) {
|
||||
$validData['for_seating'] = 1;
|
||||
}
|
||||
|
||||
$entry->update([
|
||||
'student_id' => $validData['student_id'],
|
||||
'audition_id' => $validData['audition_id'],
|
||||
'for_seating' => $validData['for_seating'],
|
||||
'for_advancement' => $validData['for_advancement'],
|
||||
]);
|
||||
|
||||
return redirect('/admin/entries');
|
||||
return to_route('admin.entries.index')->with('success', 'Entry updated successfully');
|
||||
}
|
||||
|
||||
public function destroy(Request $request, Entry $entry)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
if ($entry->audition->hasFlag('seats_published')) {
|
||||
return to_route('admin.entries.index')->with('error',
|
||||
'Entries in auditions with seats published cannot be deleted');
|
||||
}
|
||||
|
||||
if ($entry->audition->hasFlag('advancement_published')) {
|
||||
return to_route('admin.entries.index')->with('error',
|
||||
'Entries in auditions with advancement results published cannot be deleted');
|
||||
}
|
||||
if (Seat::where('entry_id', $entry->id)->exists()) {
|
||||
return redirect()->route('admin.entries.index')->with('error', 'Cannot delete an entry that is seated');
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ class EventController extends Controller
|
|||
|
||||
public function destroy(Request $request, Event $event)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
if ($event->auditions()->count() > 0) {
|
||||
return redirect()->route('admin.events.index')->with('error',
|
||||
'Cannot delete an event with auditions');
|
||||
}
|
||||
$event->delete();
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@ class RoomController extends Controller
|
|||
|
||||
public function judgingAssignment() // Show form for assigning judges
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$usersWithoutRooms = User::doesntHave('rooms')->orderBy('last_name')->orderBy('first_name')->get();
|
||||
$usersWithRooms = User::has('rooms')->orderBy('last_name')->orderBy('first_name')->get();
|
||||
$rooms = Room::with(['judges.school', 'auditions'])->get();
|
||||
|
|
@ -100,7 +97,7 @@ class RoomController extends Controller
|
|||
$room->description = $validData['description'];
|
||||
$room->save();
|
||||
|
||||
return redirect()->route('admin.rooms.index')->with('success', 'Room updated.');
|
||||
return redirect()->route('admin.rooms.index')->with('success', 'Room updated successfully');
|
||||
}
|
||||
|
||||
public function destroy(Room $room)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ use App\Http\Controllers\Controller;
|
|||
use App\Models\School;
|
||||
use App\Models\SchoolEmailDomain;
|
||||
use App\Services\Invoice\InvoiceDataService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use function abort;
|
||||
|
|
@ -15,7 +14,7 @@ use function request;
|
|||
|
||||
class SchoolController extends Controller
|
||||
{
|
||||
protected $invoiceService;
|
||||
protected InvoiceDataService $invoiceService;
|
||||
|
||||
public function __construct(InvoiceDataService $invoiceController)
|
||||
{
|
||||
|
|
@ -36,7 +35,7 @@ class SchoolController extends Controller
|
|||
return view('admin.schools.index', compact('schools', 'schoolTotalFees'));
|
||||
}
|
||||
|
||||
public function show(Request $request, School $school)
|
||||
public function show(School $school)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
|
|
@ -50,16 +49,13 @@ class SchoolController extends Controller
|
|||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$school->loadCount('students');
|
||||
|
||||
return view('admin.schools.edit', ['school' => $school]);
|
||||
}
|
||||
|
||||
public function update(School $school)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
request()->validate([
|
||||
'name' => ['required'],
|
||||
'address' => ['required'],
|
||||
|
|
@ -76,7 +72,8 @@ class SchoolController extends Controller
|
|||
'zip' => request('zip'),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.schools.show', ['school' => $school->id])->with('success', 'School '.$school->name.' updated');
|
||||
return redirect()->route('admin.schools.show', ['school' => $school->id])->with('success',
|
||||
'School '.$school->name.' updated');
|
||||
}
|
||||
|
||||
public function create()
|
||||
|
|
@ -88,7 +85,7 @@ class SchoolController extends Controller
|
|||
return view('admin.schools.create');
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
public function store()
|
||||
{
|
||||
request()->validate([
|
||||
'name' => ['required'],
|
||||
|
|
@ -109,7 +106,18 @@ class SchoolController extends Controller
|
|||
return redirect('/admin/schools')->with('success', 'School '.$school->name.' created');
|
||||
}
|
||||
|
||||
public function add_domain(Request $request, School $school)
|
||||
public function destroy(School $school)
|
||||
{
|
||||
if ($school->students()->count() > 0) {
|
||||
return to_route('admin.schools.index')->with('error', 'You cannot delete a school with students.');
|
||||
}
|
||||
$name = $school->name;
|
||||
$school->delete();
|
||||
|
||||
return to_route('admin.schools.index')->with('success', 'School '.$school->name.' deleted');
|
||||
}
|
||||
|
||||
public function add_domain(School $school)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
|
|
@ -120,13 +128,14 @@ class SchoolController extends Controller
|
|||
]);
|
||||
SchoolEmailDomain::updateOrInsert([
|
||||
'school_id' => $school->id,
|
||||
'domain' => request('domain')], []);
|
||||
'domain' => request('domain'),
|
||||
]);
|
||||
|
||||
return redirect('/admin/schools/'.$school->id.'/edit')->with('success', 'Domain Added');
|
||||
return redirect()->route('admin.schools.show', $school)->with('success', 'Domain Added');
|
||||
|
||||
}
|
||||
|
||||
public function destroy_domain(Request $request, SchoolEmailDomain $domain)
|
||||
public function destroy_domain(SchoolEmailDomain $domain)
|
||||
{
|
||||
// Destroy the $domain
|
||||
$domain->delete();
|
||||
|
|
@ -135,7 +144,7 @@ class SchoolController extends Controller
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function viewInvoice(Request $request, School $school)
|
||||
public function viewInvoice(School $school)
|
||||
{
|
||||
$invoiceData = $this->invoiceService->allData($school->id);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Auth;
|
|||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
use function abort;
|
||||
use function auditionSetting;
|
||||
use function request;
|
||||
use function response;
|
||||
|
||||
|
|
@ -17,13 +18,10 @@ class ScoringGuideController extends Controller
|
|||
{
|
||||
public function index()
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
DB::table('auditions')
|
||||
->whereNull('scoring_guide_id')
|
||||
->update(['scoring_guide_id' => 0]);
|
||||
$guides = ScoringGuide::with('auditions')->orderBy('name')->get();
|
||||
$guides = ScoringGuide::with(['auditions'])->withCount('subscores')->orderBy('name')->get();
|
||||
|
||||
return view('admin.scoring.index', ['guides' => $guides]);
|
||||
}
|
||||
|
|
@ -42,15 +40,14 @@ class ScoringGuideController extends Controller
|
|||
'name' => request('name'),
|
||||
]);
|
||||
|
||||
return redirect('/admin/scoring');
|
||||
return redirect(route('admin.scoring.index'))->with('success', 'Scoring guide created');
|
||||
}
|
||||
|
||||
public function edit(Request $request, ScoringGuide $guide)
|
||||
public function edit(Request $request, ScoringGuide $guide, string $tab = 'detail')
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$tab = $request->query('tab') ?? 'detail';
|
||||
if ($tab == 'tiebreakOrder') {
|
||||
$subscores = SubscoreDefinition::where('scoring_guide_id', $guide->id)->orderBy('tiebreak_order')->get();
|
||||
} else {
|
||||
|
|
@ -93,9 +90,6 @@ class ScoringGuideController extends Controller
|
|||
|
||||
public function subscore_store(Request $request, ScoringGuide $guide)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
if (! $guide->exists()) {
|
||||
abort(409);
|
||||
}
|
||||
|
|
@ -109,6 +103,9 @@ class ScoringGuideController extends Controller
|
|||
|
||||
$for_seating = $request->has('for_seating') ? (bool) $request->input('for_seating') : false;
|
||||
$for_advance = $request->has('for_advance') ? (bool) $request->input('for_advance') : false;
|
||||
if (! auditionSetting('advanceTo')) {
|
||||
$for_seating = true;
|
||||
}
|
||||
|
||||
$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;
|
||||
|
|
@ -124,7 +121,7 @@ class ScoringGuideController extends Controller
|
|||
'for_advance' => $for_advance,
|
||||
]);
|
||||
|
||||
return redirect('/admin/scoring/guides/'.$guide->id.'/edit')->with('success', 'Subscore added');
|
||||
return redirect(route('admin.scoring.edit', $guide))->with('success', 'Subscore added');
|
||||
}
|
||||
|
||||
public function subscore_update(ScoringGuide $guide, SubscoreDefinition $subscore)
|
||||
|
|
@ -149,6 +146,10 @@ class ScoringGuideController extends Controller
|
|||
$for_seating = request()->has('for_seating') ? (bool) request()->input('for_seating') : false;
|
||||
$for_advance = request()->has('for_advance') ? (bool) request()->input('for_advance') : false;
|
||||
|
||||
if (! auditionSetting('advanceTo')) {
|
||||
$for_seating = true;
|
||||
}
|
||||
|
||||
$subscore->update([
|
||||
'name' => $validateData['name'],
|
||||
'max_score' => $validateData['max_score'],
|
||||
|
|
@ -178,7 +179,6 @@ class ScoringGuideController extends Controller
|
|||
|
||||
}
|
||||
|
||||
|
||||
public function reorder_display(Request $request)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
|
|
@ -187,7 +187,7 @@ class ScoringGuideController extends Controller
|
|||
$order = $request->order;
|
||||
foreach ($order as $index => $id) {
|
||||
$subscore = SubscoreDefinition::find($id);
|
||||
$subscore->update(['display_order' => $index]);
|
||||
$subscore->update(['display_order' => $index + 1]);
|
||||
}
|
||||
|
||||
return response()->json(['status' => 'success']);
|
||||
|
|
@ -202,7 +202,7 @@ class ScoringGuideController extends Controller
|
|||
$order = $request->order;
|
||||
foreach ($order as $index => $id) {
|
||||
$subscore = SubscoreDefinition::find($id);
|
||||
$subscore->update(['tiebreak_order' => $index]);
|
||||
$subscore->update(['tiebreak_order' => $index + 1]);
|
||||
}
|
||||
|
||||
return response()->json(['status' => 'success']);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ use App\Models\Student;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use function abort;
|
||||
use function to_route;
|
||||
use function view;
|
||||
|
||||
class StudentController extends Controller
|
||||
|
|
@ -19,7 +21,7 @@ class StudentController extends Controller
|
|||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$students = Student::with(['school', 'entries'])->orderBy('last_name')->orderBy('first_name')->paginate(15);
|
||||
$students = Student::with(['school'])->withCount('entries')->orderBy('last_name')->orderBy('first_name')->paginate(15);
|
||||
|
||||
return view('admin.students.index', ['students' => $students]);
|
||||
}
|
||||
|
|
@ -66,8 +68,9 @@ class StudentController extends Controller
|
|||
$minGrade = Audition::min('minimum_grade');
|
||||
$maxGrade = Audition::max('maximum_grade');
|
||||
$schools = School::orderBy('name')->get();
|
||||
|
||||
return view('admin.students.edit', ['student' => $student, 'schools' => $schools, 'minGrade' => $minGrade, 'maxGrade' => $maxGrade]);
|
||||
$student->loadCount('entries');
|
||||
return view('admin.students.edit',
|
||||
['student' => $student, 'schools' => $schools, 'minGrade' => $minGrade, 'maxGrade' => $maxGrade]);
|
||||
}
|
||||
|
||||
public function update(Request $request, Student $student)
|
||||
|
|
@ -84,7 +87,8 @@ class StudentController extends Controller
|
|||
|
||||
foreach ($student->entries as $entry) {
|
||||
if ($entry->audition->minimum_grade > request('grade') || $entry->audition->maximum_grade < request('grade')) {
|
||||
return redirect('/admin/students/'.$student->id.'/edit')->with('error', 'This student is entered in an audition that is not available to their new grade.');
|
||||
return redirect('/admin/students/'.$student->id.'/edit')->with('error',
|
||||
'This student is entered in an audition that is not available to their new grade.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,4 +102,16 @@ class StudentController extends Controller
|
|||
return redirect('/admin/students');
|
||||
|
||||
}
|
||||
|
||||
public function destroy(Student $student)
|
||||
{
|
||||
Log::debug('Deleting student '.$student->id);
|
||||
if($student->entries()->count() > 0) {
|
||||
return to_route('admin.students.index')->with('error', 'You cannot delete a student with entries.');
|
||||
}
|
||||
$name = $student->full_name();
|
||||
$student->delete();
|
||||
|
||||
return to_route('admin.students.index')->with('success', 'Student '.$name.' deleted successfully.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Events\AuditionChange;
|
||||
use App\Events\RoomJudgeChange;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Mail\NewUserPassword;
|
||||
use App\Models\School;
|
||||
|
|
@ -18,28 +16,39 @@ class UserController extends Controller
|
|||
{
|
||||
public function index()
|
||||
{
|
||||
if (! Auth::user()->is_admin) abort(403);
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$users = User::with('school')->orderBy('last_name')->orderBy('first_name')->get();
|
||||
|
||||
return view('admin.users.index', ['users' => $users]);
|
||||
}
|
||||
|
||||
public function edit(User $user)
|
||||
{
|
||||
if (! Auth::user()->is_admin) abort(403);
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$schools = School::orderBy('name')->get();
|
||||
return view('admin.users.edit', ['user' => $user,'schools' => $schools]);
|
||||
|
||||
return view('admin.users.edit', ['user' => $user, 'schools' => $schools]);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
if (! Auth::user()->is_admin) abort(403);
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$schools = School::orderBy('name')->get();
|
||||
|
||||
return view('admin.users.create', ['schools' => $schools]);
|
||||
}
|
||||
|
||||
public function update(Request $request, User $user)
|
||||
{
|
||||
if (! Auth::user()->is_admin) abort(403);
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
request()->validate([
|
||||
'first_name' => ['required'],
|
||||
|
|
@ -47,7 +56,7 @@ class UserController extends Controller
|
|||
'email' => ['required', 'email'],
|
||||
'cell_phone' => ['required'],
|
||||
'judging_preference' => ['required'],
|
||||
'school_id' => ['required','exists:schools,id'],
|
||||
'school_id' => ['required', 'exists:schools,id'],
|
||||
]);
|
||||
|
||||
$user->update([
|
||||
|
|
@ -56,8 +65,9 @@ class UserController extends Controller
|
|||
'email' => request('email'),
|
||||
'cell_phone' => request('cell_phone'),
|
||||
'judging_preference' => request('judging_preference'),
|
||||
'school_id' => request('school_id')
|
||||
'school_id' => request('school_id'),
|
||||
]);
|
||||
|
||||
return redirect('/admin/users');
|
||||
}
|
||||
|
||||
|
|
@ -66,10 +76,10 @@ class UserController extends Controller
|
|||
$request->validate([
|
||||
'first_name' => ['required'],
|
||||
'last_name' => ['required'],
|
||||
'email' => ['required', 'email','unique:users'],
|
||||
'email' => ['required', 'email', 'unique:users'],
|
||||
]);
|
||||
|
||||
// Genearte a random password
|
||||
// Generate a random password
|
||||
$randomPassword = Str::random(12);
|
||||
|
||||
$user = \App\Models\User::make([
|
||||
|
|
@ -81,9 +91,9 @@ class UserController extends Controller
|
|||
'password' => Hash::make($randomPassword),
|
||||
]);
|
||||
|
||||
if (!is_null(request('school_id'))) {
|
||||
if (! is_null(request('school_id'))) {
|
||||
$request->validate([
|
||||
'school_id' => ['exists:schools,id']
|
||||
'school_id' => ['exists:schools,id'],
|
||||
]);
|
||||
}
|
||||
$user->school_id = request('school_id');
|
||||
|
|
@ -93,4 +103,13 @@ class UserController extends Controller
|
|||
|
||||
return redirect('/admin/users');
|
||||
}
|
||||
|
||||
public function destroy(Request $request, User $user)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$user->delete();
|
||||
return redirect()->route('admin.users.index')->with('success', 'User deleted successfully');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class EntryController extends Controller
|
|||
}
|
||||
$entry->delete();
|
||||
|
||||
return redirect('/entries')->with('success', 'The '.$entry->audition->name.'entry for '.$entry->student->full_name().'has been deleted.');
|
||||
return redirect()->route('entries.index')->with('success', 'The '.$entry->audition->name.'entry for '.$entry->student->full_name().'has been deleted.');
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,14 +16,13 @@ class FilterController extends Controller
|
|||
$filters['first_name'] = request('first_name_filter') ? request('first_name_filter') : null;
|
||||
$filters['last_name'] = request('last_name_filter') ? request('last_name_filter') : null;
|
||||
|
||||
// session(['admin_entry_filter', $filters]);
|
||||
session(['adminEntryFilters' => $filters]);
|
||||
return redirect('/admin/entries');
|
||||
return redirect('/admin/entries')->with('success', 'Filters Applied');
|
||||
}
|
||||
|
||||
public function clearAdminEntryFilter(Request $request)
|
||||
{
|
||||
session()->forget('adminEntryFilters');
|
||||
return redirect('/admin/entries');
|
||||
return redirect('/admin/entries')->with('success', 'Filters Cleared');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ namespace App\Http\Controllers;
|
|||
use App\Models\Audition;
|
||||
use App\Models\School;
|
||||
use App\Models\Student;
|
||||
use App\Models\User;
|
||||
use App\Rules\UniqueFullNameAtSchool;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use function abort;
|
||||
use function redirect;
|
||||
|
||||
|
|
@ -20,9 +20,13 @@ class StudentController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$students = Auth::user()->students()->with('entries')->get();
|
||||
if (! Auth::user()->school_id) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$students = Auth::user()->students()->withCount('entries')->get();
|
||||
$auditions = Audition::all();
|
||||
return view('students.index',['students' => $students, 'auditions' => $auditions]);
|
||||
|
||||
return view('students.index', ['students' => $students, 'auditions' => $auditions]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -38,10 +42,15 @@ class StudentController extends Controller
|
|||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
if ($request->user()->cannot('create', Student::class)) abort(403);
|
||||
if ($request->user()->cannot('create', Student::class)) {
|
||||
abort(403);
|
||||
}
|
||||
$request->validate([
|
||||
'first_name' => ['required'],
|
||||
'last_name' => ['required', new UniqueFullNameAtSchool(request('first_name'),request('last_name'), Auth::user()->school_id)],
|
||||
'last_name' => [
|
||||
'required',
|
||||
new UniqueFullNameAtSchool(request('first_name'), request('last_name'), Auth::user()->school_id),
|
||||
],
|
||||
'grade' => ['required', 'integer'],
|
||||
]);
|
||||
|
||||
|
|
@ -49,10 +58,10 @@ class StudentController extends Controller
|
|||
'first_name' => request('first_name'),
|
||||
'last_name' => request('last_name'),
|
||||
'grade' => request('grade'),
|
||||
'school_id' => Auth::user()->school_id
|
||||
'school_id' => Auth::user()->school_id,
|
||||
]);
|
||||
|
||||
$request->session()->put('auditionMessages',['success','I did it again ma']);
|
||||
$request->session()->put('auditionMessages', ['success', 'I did it again ma']);
|
||||
|
||||
return redirect('/students');
|
||||
}
|
||||
|
|
@ -70,7 +79,10 @@ class StudentController extends Controller
|
|||
*/
|
||||
public function edit(Request $request, Student $student)
|
||||
{
|
||||
if ($request->user()->cannot('update', $student)) abort(403);
|
||||
if ($request->user()->cannot('update', $student)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
return view('students.edit', ['student' => $student]);
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +91,9 @@ class StudentController extends Controller
|
|||
*/
|
||||
public function update(Request $request, Student $student)
|
||||
{
|
||||
if ($request->user()->cannot('update', $student)) abort(403);
|
||||
if ($request->user()->cannot('update', $student)) {
|
||||
abort(403);
|
||||
}
|
||||
request()->validate([
|
||||
'first_name' => ['required'],
|
||||
'last_name' => ['required'],
|
||||
|
|
@ -89,13 +103,12 @@ class StudentController extends Controller
|
|||
$student->update([
|
||||
'first_name' => request('first_name'),
|
||||
'last_name' => request('last_name'),
|
||||
'grade' => request('grade')
|
||||
'grade' => request('grade'),
|
||||
]);
|
||||
|
||||
// TODO if a students grade is changed, we need to be sure they are still eligible for the auditions in which they are entered.
|
||||
|
||||
|
||||
return redirect('/students');
|
||||
return redirect('/students')->with('success', 'Student updated successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -103,8 +116,11 @@ class StudentController extends Controller
|
|||
*/
|
||||
public function destroy(Request $request, Student $student)
|
||||
{
|
||||
if ($request->user()->cannot('delete', $student)) abort(403);
|
||||
if ($request->user()->cannot('delete', $student)) {
|
||||
abort(403);
|
||||
}
|
||||
$student->delete();
|
||||
return redirect('/students');
|
||||
|
||||
return redirect(route('students.index'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class CheckIfAdmin
|
|||
return $next($request);
|
||||
}
|
||||
|
||||
return redirect('/')->with('error', 'You do not have admin access.');
|
||||
return redirect(route('dashboard'))->with('error', 'You are not authorized to perform this action');
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use function redirect;
|
||||
use function route;
|
||||
|
||||
class CheckIfHasSchool
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if (Auth::check() && Auth::user()->school_id) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return redirect(route('dashboard'))->with('error', 'You do not have a school to view students for.');
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -10,8 +10,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
use function now;
|
||||
|
||||
class Audition extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
|
@ -26,7 +24,6 @@ class Audition extends Model
|
|||
|
||||
protected $scored_entries_count; //Set by TabulationService
|
||||
|
||||
|
||||
public function event(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Event::class);
|
||||
|
|
@ -175,12 +172,14 @@ class Audition extends Model
|
|||
}
|
||||
|
||||
$this->flags()->create(['flag_name' => $flag]);
|
||||
$this->load('flags');
|
||||
}
|
||||
|
||||
public function removeFlag($flag): void
|
||||
{
|
||||
// remove related auditionFlag where flag_name = $flag
|
||||
$this->flags()->where('flag_name', $flag)->delete();
|
||||
$this->load('flags');
|
||||
}
|
||||
|
||||
public function scopeOpen(Builder $query): void
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -40,4 +41,16 @@ class Ensemble extends Model
|
|||
{
|
||||
return $this->hasMany(Seat::class);
|
||||
}
|
||||
|
||||
public function scopeForAudition(Builder $query, $audition_id): Builder
|
||||
{
|
||||
$audition = Audition::find($audition_id);
|
||||
// get instances of this class where the event_id is equal to the event_id of the audition with $audition_id
|
||||
return $query->where('event_id', $audition->event_id);
|
||||
}
|
||||
|
||||
public function scopeForEvent(Builder $query, $event_id): Builder
|
||||
{
|
||||
return $query->where('event_id', $event_id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,14 +75,15 @@ class Entry extends Model
|
|||
if ($this->hasFlag($flag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->flags()->create(['flag_name' => $flag]);
|
||||
$this->load('flags');
|
||||
}
|
||||
|
||||
public function removeFlag($flag): void
|
||||
{
|
||||
// remove related auditionFlag where flag_name = $flag
|
||||
$this->flags()->where('flag_name', $flag)->delete();
|
||||
$this->load('flags');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -45,12 +45,14 @@ class Room extends Model
|
|||
public function addJudge($userId): void
|
||||
{
|
||||
$this->judges()->attach($userId);
|
||||
$this->load('judges');
|
||||
AuditionChange::dispatch();
|
||||
}
|
||||
|
||||
public function removeJudge($userId): void
|
||||
{
|
||||
$this->judges()->detach($userId);
|
||||
$this->load('judges');
|
||||
AuditionChange::dispatch();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
class RoomUser extends Model
|
||||
{
|
||||
protected $table = 'room_user';
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
@ -16,7 +19,7 @@ class RoomUser extends Model
|
|||
|
||||
public function judge(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
public function room(): BelongsTo
|
||||
|
|
|
|||
|
|
@ -38,11 +38,6 @@ class ScoreSheet extends Model
|
|||
);
|
||||
}
|
||||
|
||||
public function getSubscore($id)
|
||||
{
|
||||
return $this->subscores[$id]['score'] ?? false;
|
||||
}
|
||||
|
||||
public function isValid()
|
||||
{
|
||||
// TODO move to either TabulationService or a specific service for scoreValidation
|
||||
|
|
|
|||
|
|
@ -21,7 +21,19 @@ class Student extends Model
|
|||
|
||||
public function users(): HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(User::class, School::class);
|
||||
return $this->hasManyThrough(
|
||||
User::class, // The target model we want to access
|
||||
School::class, // The intermediate model through which we access the target model
|
||||
'id', // The foreign key on the intermediate model
|
||||
'school_id', // The foreign key on the target model
|
||||
'school_id', // The local key
|
||||
'id' // The local key on the intermediate model
|
||||
);
|
||||
}
|
||||
|
||||
public function directors(): HasManyThrough
|
||||
{
|
||||
return $this->users();
|
||||
}
|
||||
|
||||
public function entries(): HasMany
|
||||
|
|
@ -32,8 +44,9 @@ class Student extends Model
|
|||
public function full_name(bool $last_name_first = false): string
|
||||
{
|
||||
if ($last_name_first) {
|
||||
return ($this->last_name.', '.$this->first_name);
|
||||
return $this->last_name.', '.$this->first_name;
|
||||
}
|
||||
|
||||
return $this->first_name.' '.$this->last_name;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class User extends Authenticatable implements MustVerifyEmail
|
||||
{
|
||||
|
|
@ -131,7 +132,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
*
|
||||
* @return SchoolEmailDomain[]
|
||||
*/
|
||||
public function possibleSchools()
|
||||
public function possibleSchools(): Collection
|
||||
{
|
||||
if ($this->school_id) {
|
||||
$return[] = $this->school;
|
||||
|
|
@ -148,7 +149,11 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
return true;
|
||||
}
|
||||
|
||||
return $this->is_tab;
|
||||
if ($this->is_tab) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function scoreSheets(): HasMany
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ class EntryObserver
|
|||
*/
|
||||
public function created(Entry $entry): void
|
||||
{
|
||||
AuditionChange::dispatch();
|
||||
EntryChange::dispatch($entry->audition_id);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -22,8 +21,7 @@ class EntryObserver
|
|||
*/
|
||||
public function updated(Entry $entry): void
|
||||
{
|
||||
AuditionChange::dispatch();
|
||||
EntryChange::dispatch($entry->audition_id);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -31,8 +29,7 @@ class EntryObserver
|
|||
*/
|
||||
public function deleted(Entry $entry): void
|
||||
{
|
||||
AuditionChange::dispatch();
|
||||
EntryChange::dispatch($entry->audition_id);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -40,8 +37,7 @@ class EntryObserver
|
|||
*/
|
||||
public function restored(Entry $entry): void
|
||||
{
|
||||
AuditionChange::dispatch();
|
||||
EntryChange::dispatch($entry->audition_id);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -49,6 +45,6 @@ class EntryObserver
|
|||
*/
|
||||
public function forceDeleted(Entry $entry): void
|
||||
{
|
||||
EntryChange::dispatch($entry->audition_id);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ class StudentObserver
|
|||
*/
|
||||
public function updated(Student $student): void
|
||||
{
|
||||
AuditionChange::dispatch();
|
||||
EntryChange::dispatch();
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -30,7 +29,7 @@ class StudentObserver
|
|||
*/
|
||||
public function deleted(Student $student): void
|
||||
{
|
||||
AuditionChange::dispatch();
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace App\Policies;
|
|||
|
||||
use App\Models\Entry;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
|
||||
use function is_null;
|
||||
|
||||
class EntryPolicy
|
||||
|
|
@ -14,7 +14,7 @@ class EntryPolicy
|
|||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -22,8 +22,11 @@ class EntryPolicy
|
|||
*/
|
||||
public function view(User $user, Entry $entry): bool
|
||||
{
|
||||
if($user->is_admin) return true;
|
||||
return $user->school_id == $entry->student()->school_id;
|
||||
if ($user->is_admin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $user->school_id == $entry->student->school_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -31,7 +34,10 @@ class EntryPolicy
|
|||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
if($user->is_admin) return true;
|
||||
if ($user->is_admin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ! is_null($user->school_id);
|
||||
}
|
||||
|
||||
|
|
@ -40,8 +46,11 @@ class EntryPolicy
|
|||
*/
|
||||
public function update(User $user, Entry $entry): bool
|
||||
{
|
||||
if($user->is_admin) return true;
|
||||
return $user->school_id == $entry->student()->school_id;
|
||||
if ($user->is_admin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $user->school_id == $entry->student->school_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -49,13 +58,15 @@ class EntryPolicy
|
|||
*/
|
||||
public function delete(User $user, Entry $entry): bool
|
||||
{
|
||||
if($user->is_admin) return true;
|
||||
if ($user->is_admin) {
|
||||
return true;
|
||||
}
|
||||
// Return false if $entry->audition->entry_deadline is in the past, continue if not
|
||||
if ($entry->audition->entry_deadline < now()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $user->school_id == $entry->student()->school_id;
|
||||
return $user->school_id == $entry->student->school_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -63,7 +74,7 @@ class EntryPolicy
|
|||
*/
|
||||
public function restore(User $user, Entry $entry): bool
|
||||
{
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,6 +82,6 @@ class EntryPolicy
|
|||
*/
|
||||
public function forceDelete(User $user, Entry $entry): bool
|
||||
{
|
||||
//
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace App\Policies;
|
|||
use App\Models\Entry;
|
||||
use App\Models\Student;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
|
||||
use function is_null;
|
||||
|
||||
class StudentPolicy
|
||||
|
|
@ -31,7 +31,10 @@ class StudentPolicy
|
|||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
if($user->is_admin) return true;
|
||||
if ($user->is_admin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ! is_null($user->school_id);
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +44,10 @@ class StudentPolicy
|
|||
public function update(User $user, Student $student): bool
|
||||
{
|
||||
|
||||
if($user->is_admin) return true;
|
||||
if ($user->is_admin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $user->school_id == $student->school_id;
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +56,10 @@ class StudentPolicy
|
|||
*/
|
||||
public function delete(User $user, Student $student): bool
|
||||
{
|
||||
if (Entry::where('student_id','=',$student->id)->exists()) return false; // Don't allow deletion of a student with entries
|
||||
if (Entry::where('student_id', '=', $student->id)->exists()) {
|
||||
return false;
|
||||
} // Don't allow deletion of a student with entries
|
||||
|
||||
return $user->school_id == $student->school_id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class UniqueFullNameAtSchool implements ValidationRule
|
|||
$this->school_id = $schoolID;
|
||||
}
|
||||
|
||||
public function passes($attributies, $value)
|
||||
public function studentExists()
|
||||
{
|
||||
return Student::where('first_name', $this->first_name)
|
||||
->where('last_name', $this->last_name)
|
||||
|
|
@ -38,6 +38,8 @@ class UniqueFullNameAtSchool implements ValidationRule
|
|||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
//
|
||||
if($this->studentExists()) {
|
||||
$fail($this->message());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,9 +69,6 @@ class AuditionService
|
|||
|
||||
public function clearCache(): void
|
||||
{
|
||||
if (App::environment('local')) {
|
||||
Session::flash('success', 'Audition Cache Cleared');
|
||||
}
|
||||
Cache::forget($this->cacheKey);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
"codedge/laravel-fpdf": "^1.12",
|
||||
"laravel/fortify": "^1.21",
|
||||
"laravel/framework": "^11.0",
|
||||
"laravel/pail": "^1.1",
|
||||
"laravel/tinker": "^2.9",
|
||||
"predis/predis": "^2.2",
|
||||
"symfony/http-client": "^7.1",
|
||||
|
|
@ -16,6 +17,7 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "^3.13",
|
||||
"brianium/paratest": "^7.4",
|
||||
"fakerphp/faker": "^1.23",
|
||||
"laravel/pint": "^1.13",
|
||||
"laravel/sail": "^1.26",
|
||||
|
|
@ -23,6 +25,7 @@
|
|||
"nunomaduro/collision": "^8.0",
|
||||
"pestphp/pest": "^2.34",
|
||||
"pestphp/pest-plugin-laravel": "^2.4",
|
||||
"sinnbeck/laravel-dom-assertions": "^1.5",
|
||||
"spatie/laravel-ignition": "^2.4"
|
||||
},
|
||||
"autoload": {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "8a539bb700e8acfbb39c896521c16609",
|
||||
"content-hash": "7aab57ef52f0152526434decd76ef1e1",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
|
|
@ -1491,6 +1491,84 @@
|
|||
},
|
||||
"time": "2024-05-21T17:57:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/pail",
|
||||
"version": "v1.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/pail.git",
|
||||
"reference": "c22fe771277971eb9cd224955996bcf39c1a710d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/pail/zipball/c22fe771277971eb9cd224955996bcf39c1a710d",
|
||||
"reference": "c22fe771277971eb9cd224955996bcf39c1a710d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"ext-pcntl": "*",
|
||||
"illuminate/console": "^10.24|^11.0",
|
||||
"illuminate/contracts": "^10.24|^11.0",
|
||||
"illuminate/log": "^10.24|^11.0",
|
||||
"illuminate/process": "^10.24|^11.0",
|
||||
"illuminate/support": "^10.24|^11.0",
|
||||
"nunomaduro/termwind": "^1.15|^2.0",
|
||||
"php": "^8.2",
|
||||
"symfony/console": "^6.0|^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "^1.13",
|
||||
"orchestra/testbench": "^8.12|^9.0",
|
||||
"pestphp/pest": "^2.20",
|
||||
"pestphp/pest-plugin-type-coverage": "^2.3",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"symfony/var-dumper": "^6.3|^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Pail\\PailServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Pail\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
},
|
||||
{
|
||||
"name": "Nuno Maduro",
|
||||
"email": "enunomaduro@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Easily delve into your Laravel application's log files directly from the command line.",
|
||||
"homepage": "https://github.com/laravel/pail",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"logs",
|
||||
"php",
|
||||
"tail"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/pail/issues",
|
||||
"source": "https://github.com/laravel/pail"
|
||||
},
|
||||
"time": "2024-05-08T18:19:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
"version": "v0.1.22",
|
||||
|
|
@ -9301,6 +9379,76 @@
|
|||
],
|
||||
"time": "2023-02-07T11:34:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sinnbeck/laravel-dom-assertions",
|
||||
"version": "v1.5.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sinnbeck/laravel-dom-assertions.git",
|
||||
"reference": "a2ce7540023fac4e6e010cbe5396b7aad9d22765"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sinnbeck/laravel-dom-assertions/zipball/a2ce7540023fac4e6e010cbe5396b7aad9d22765",
|
||||
"reference": "a2ce7540023fac4e6e010cbe5396b7aad9d22765",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"illuminate/testing": "^9.0|^10.0|^11.0",
|
||||
"php": "^8.0",
|
||||
"symfony/css-selector": "^6.0|^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "^1.2",
|
||||
"nunomaduro/larastan": "^2.2",
|
||||
"orchestra/testbench": "^7.0|^8.0|^9.0",
|
||||
"pestphp/pest": "^1.0|^2.34",
|
||||
"phpstan/extension-installer": "^1.2",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpstan/phpstan-phpunit": "^1.1",
|
||||
"vimeo/psalm": "^4.29|^5.22"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Sinnbeck\\DomAssertions\\DomAssertionsServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Sinnbeck\\DomAssertions\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "René Sinnbeck",
|
||||
"email": "rene.sinnbeck@gmail.com",
|
||||
"homepage": "https://sinnbeck.dev",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"homepage": "https://github.com/sinnbeck/laravel-dom-assertions",
|
||||
"keywords": [
|
||||
"assertions",
|
||||
"blade",
|
||||
"dom",
|
||||
"laravel",
|
||||
"view"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sinnbeck/laravel-dom-assertions/issues",
|
||||
"source": "https://github.com/sinnbeck/laravel-dom-assertions/tree/v1.5.3"
|
||||
},
|
||||
"time": "2024-06-17T12:30:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/backtrace",
|
||||
"version": "1.6.1",
|
||||
|
|
|
|||
|
|
@ -41,14 +41,18 @@ class AuditionFactory extends Factory
|
|||
|
||||
return [
|
||||
'event_id' => $event->id,
|
||||
'name' => $this->faker->randomElement($instruments).$this->faker->randomNumber(1),
|
||||
'score_order' => 1,
|
||||
#'name' => $this->faker->randomElement($instruments).$this->faker->numberBetween(1, 1000),
|
||||
'name' => 'New Instrument ' . $this->faker->unique()->words(4,true),
|
||||
'score_order' => $this->faker->numberBetween(2, 50),
|
||||
'entry_deadline' => Carbon::tomorrow(),
|
||||
'entry_fee' => 1000,
|
||||
'minimum_grade' => 7,
|
||||
'maximum_grade' => 12,
|
||||
'minimum_grade' => $this->faker->numberBetween(7, 9),
|
||||
'maximum_grade' => $this->faker->numberBetween(8, 12),
|
||||
'for_seating' => 1,
|
||||
'for_advancement' => 1,
|
||||
'room_id' => null,
|
||||
'order_in_room' => 0,
|
||||
'scoring_guide_id' => null,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -58,4 +62,17 @@ class AuditionFactory extends Factory
|
|||
fn (array $attributes) => ['entry_deadline' => $entryDeadline ?? Carbon::yesterday()]
|
||||
);
|
||||
}
|
||||
public function seatingOnly(): self
|
||||
{
|
||||
return $this->state(
|
||||
fn (array $attributes) => ['for_advancement' => 0]
|
||||
);
|
||||
}
|
||||
|
||||
public function advancementOnly(): self
|
||||
{
|
||||
return $this->state(
|
||||
fn (array $attributes) => ['for_seating' => 0]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Ensemble>
|
||||
*/
|
||||
class EnsembleFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->name,
|
||||
'event_id' => \App\Models\Event::factory(),
|
||||
'code' => $this->faker->randomLetter().$this->faker->randomLetter,
|
||||
'rank' => $this->faker->numberBetween(1, 10),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ class EntryFactory extends Factory
|
|||
'draw_number' => null,
|
||||
'for_seating' => 1,
|
||||
'for_advancement' => 1,
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class EventFactory extends Factory
|
|||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->name(),
|
||||
'name' => $this->faker->unique()->name(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ class RoomFactory extends Factory
|
|||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'Room ' . fake()->numberBetween(7,500),
|
||||
'description' => fake()->sentence()
|
||||
'name' => 'Room '.fake()->unique()->numberBetween(7, 500),
|
||||
'description' => fake()->sentence(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\School;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\SchoolEmailDomain>
|
||||
*/
|
||||
class SchoolEmailDomainFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$school = School::factory()->create();
|
||||
return [
|
||||
'school_id' => $school->id,
|
||||
'domain' => $this->faker->unique()->domainName,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ class ScoringGuideFactory extends Factory
|
|||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
'name' => $this->faker->sentence(3),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\ScoringGuide;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
|
|
@ -16,8 +17,45 @@ class SubscoreDefinitionFactory extends Factory
|
|||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$sg = ScoringGuide::factory()->create();
|
||||
|
||||
return [
|
||||
//
|
||||
'scoring_guide_id' => $sg->id,
|
||||
'name' => $this->faker->word,
|
||||
'max_score' => 100,
|
||||
'weight' => $this->faker->numberBetween(1, 4),
|
||||
'display_order' => $this->faker->numberBetween(1, 20),
|
||||
'tiebreak_order' => $this->faker->numberBetween(1, 20),
|
||||
'for_seating' => 1,
|
||||
'for_advance' => 1,
|
||||
];
|
||||
}
|
||||
public function seatingOnly(): self
|
||||
{
|
||||
return $this->state(
|
||||
fn (array $attributes) => ['for_advance' => 0]
|
||||
);
|
||||
}
|
||||
|
||||
public function advanceOnly(): self
|
||||
{
|
||||
return $this->state(
|
||||
fn (array $attributes) => ['for_seating' => 0]
|
||||
);
|
||||
}
|
||||
|
||||
public function displayFirst(): self
|
||||
{
|
||||
return $this->state(
|
||||
fn (array $attributes) => ['display_order' => 0]
|
||||
);
|
||||
}
|
||||
|
||||
public function tiebreakFirst(): self
|
||||
{
|
||||
return $this->state(
|
||||
fn (array $attributes) => ['tiebreak_order' => 0]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Room;
|
||||
use App\Models\ScoringGuide;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
|
|
@ -16,10 +13,10 @@ return new class extends Migration
|
|||
if (! Room::find(0)) {
|
||||
$room = Room::create([
|
||||
'id' => 0,
|
||||
'name' => 'No Guide Assigned'
|
||||
'name' => 'No Guide Assigned',
|
||||
]);
|
||||
$room->update([
|
||||
'id' => 0
|
||||
'id' => 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Room;
|
||||
use App\Models\ScoringGuide;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
|
@ -20,10 +19,10 @@ return new class extends Migration
|
|||
if (! ScoringGuide::find(0)) {
|
||||
$sg = ScoringGuide::create([
|
||||
'id' => 0,
|
||||
'name' => 'No Guide Assigned'
|
||||
'name' => 'No Guide Assigned',
|
||||
]);
|
||||
$sg->update([
|
||||
'id' => 0
|
||||
'id' => 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\SiteSetting;
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class SampleSettingsSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'auditionName',
|
||||
'setting_value' => 'Somewhere Band Directors Association',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'auditionAbbreviation',
|
||||
'setting_value' => 'SBDA',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'registrationCode',
|
||||
'setting_value' => 'secret',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'advanceTo',
|
||||
'setting_value' => 'OMEA',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'judging_enabled',
|
||||
'setting_value' => '1',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'organizerName',
|
||||
'setting_value' => 'John Doe',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'organizerEmail',
|
||||
'setting_value' => 'jdoe@sbda.null',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'olympic_scoring',
|
||||
'setting_value' => '0',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'fee_structure',
|
||||
'setting_value' => 'oneFeePerEntry',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'late_fee',
|
||||
'setting_value' => '1000',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'school_fee',
|
||||
'setting_value' => '2500',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'payment_address',
|
||||
'setting_value' => '143 Sousa Lane',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'payment_city',
|
||||
'setting_value' => 'Maud',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'payment_state',
|
||||
'setting_value' => 'OK',
|
||||
]);
|
||||
SiteSetting::create([
|
||||
'setting_key' => 'payment_zip',
|
||||
'setting_value' => '77777',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<x-layout.app>
|
||||
<x-slot:page_title>Audition Settings</x-slot:page_title>
|
||||
<x-layout.page-section-container>
|
||||
<x-form.form method="POST" action="{{ route('audition-settings-save') }}">
|
||||
<x-form.form id="settingsForm" method="POST" action="{{ route('audition-settings-save') }}">
|
||||
|
||||
<x-layout.page-section>
|
||||
<x-slot:section_name>Group Information</x-slot:section_name>
|
||||
|
|
@ -60,6 +60,15 @@
|
|||
|
||||
</x-form.body-grid>
|
||||
</x-layout.page-section>
|
||||
<x-layout.page-section>
|
||||
<x-slot:section_name>Payment Address</x-slot:section_name>
|
||||
<x-form.body-grid columns="12" class="m-3">
|
||||
<x-form.field label_text="Payment Address" name="payment_address" colspan="5" :value="auditionSetting('payment_address')"/>
|
||||
<x-form.field label_text="Payment City" name="payment_city" colspan="3" :value="auditionSetting('payment_city')"/>
|
||||
<x-form.field label_text="Payment State" name="payment_state" colspan="2" :value="auditionSetting('payment_state')"/>
|
||||
<x-form.field label_text="Payment Zip" type="number" name="payment_zip" colspan="2" :value="auditionSetting('payment_zip')"/>
|
||||
</x-form.body-grid>
|
||||
</x-layout.page-section>
|
||||
|
||||
<div class="grid grid-cols-12">
|
||||
<div class="col-span-2 col-start-11 my-5 mr-3">
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@
|
|||
<x-card.card class="max-w-lg mx-auto">
|
||||
<x-card.heading>
|
||||
Edit Audition
|
||||
<x-slot:right_side>
|
||||
@if($audition->entries->count() == 0)
|
||||
<x-delete-resource-modal title="Delete Audition {{ $audition->name }}" action="{{ route('admin.auditions.destroy', $audition) }}">
|
||||
Please confirm that you would like to delete the audition {{ $audition->name }}. This action cannot be undone.
|
||||
</x-delete-resource-modal>
|
||||
@endif
|
||||
</x-slot:right_side>
|
||||
{{-- TODO implement a way to update multiple auditions as once --}}
|
||||
</x-card.heading>
|
||||
<x-form.form method="PATCH" action="/admin/auditions/{{ $audition->id }}">
|
||||
|
|
@ -39,18 +46,13 @@
|
|||
|
||||
</x-form.body-grid>
|
||||
<x-form.footer submit-button-text="Update Audition" class="pb-4 !justify-between">
|
||||
<div>
|
||||
@if($audition->entries->count() == 0)
|
||||
<x-form.red-trash-button form="deleteResource" size="20"></x-form.red-trash-button>
|
||||
@endif
|
||||
</div>
|
||||
<div></div>
|
||||
<div>
|
||||
<x-form.button>Edit Audition</x-form.button>
|
||||
</div>
|
||||
</x-form.footer>
|
||||
|
||||
</x-form.form>
|
||||
<x-form.delete-form action="/admin/auditions/{{ $audition->id }}"></x-form.delete-form>
|
||||
</x-card.card>
|
||||
</x-layout.app>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<x-layout.app>
|
||||
<x-slot:page_title>Audition Administration</x-slot:page_title>
|
||||
<x-card.card>
|
||||
<x-table.table with_title_area sortable="false">
|
||||
<x-table.table with_title_area sortable="false" id="auditions-table">
|
||||
<x-slot:title class="ml-3">Auditions</x-slot:title>
|
||||
<x-slot:subtitle class="ml-3">Drag to reorder. Double click to edit.</x-slot:subtitle>
|
||||
<x-slot:title_block_right class="mr-3">
|
||||
<x-form.button href="/admin/auditions/create">New Audition</x-form.button>
|
||||
<x-form.button href="{{ route('admin.auditions.create') }}">New Audition</x-form.button>
|
||||
</x-slot:title_block_right>
|
||||
|
||||
<thead>
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
<div x-data="sortableList()" x-init="init">
|
||||
<x-table.body id="sortable-list">
|
||||
@foreach($auditions as $audition)
|
||||
<tr data-id="{{ $audition->id }}"
|
||||
<tr data-id="{{ $audition->id }}" id="auditionRow-{{ $audition->id }}"
|
||||
@dblclick="window.location.href='/admin/auditions/{{ $audition->id }}/edit'">
|
||||
<x-table.td>{{ $audition->event->name }}</x-table.td>
|
||||
<x-table.td>{{ $audition->name }}</x-table.td>
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
@endif
|
||||
</x-table.td>
|
||||
@endif
|
||||
<x-table.td>{{ $audition->entries->count() }}</x-table.td>
|
||||
<x-table.td>{{ $audition->entries_count }}</x-table.td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table.body>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
</thead>
|
||||
<x-table.body>
|
||||
@foreach($event->ensembles as $ensemble)
|
||||
<tr data-id="{{ $ensemble->id }}">
|
||||
<tr data-id="{{ $ensemble->id }}" id="ensembleRow-{{$ensemble->id}}">
|
||||
<x-table.td class="handle">
|
||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M5 7h14M5 12h14M5 17h14"/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<x-modal>
|
||||
<x-slot:button_text>{{ $ensemble->name }}</x-slot:button_text>
|
||||
<x-slot:title class="font-semibold">Rename Ensemble {{ $ensemble->name }}</x-slot:title>
|
||||
<x-form.form method="PATCH" action="{{ route('admin.ensembles.updateEnsemble', ['ensemble' => $ensemble->rank]) }}">
|
||||
<x-form.form method="PATCH" action="{{ route('admin.ensembles.update', ['ensemble' => $ensemble->rank]) }}">
|
||||
<x-form.body-grid columns="4">
|
||||
<x-form.field colspan="2" label_text="New Name" value="{{ $ensemble->name }}" name="name" />
|
||||
<x-form.field colspan="1" label_text="New Code" value="{{ $ensemble->code }}" name="code" />
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
@php
|
||||
$limits = [];
|
||||
foreach ($ensemble->seatingLimits as $lim) {
|
||||
$limits[$lim->audition_id] = $lim->maximum_accepted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \App\Models\Ensemble $ensemble The ensemble for which a seating form is shown
|
||||
* @var array $limits An array of audition_id => maximum_accepted for the ensemble
|
||||
**/
|
||||
@endphp
|
||||
<x-card.card class="mt-5 max-w-md mx-auto">
|
||||
<x-card.heading>{{ $ensemble->name }}</x-card.heading>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,14 @@
|
|||
`{{ route('admin.ensembles.seatingLimits') }}/${event.target.value}`">
|
||||
<option value=""></option>
|
||||
@foreach($ensembles as $optionEnsemble)
|
||||
<option value ="{{$optionEnsemble->id}}">{{$optionEnsemble->event->name}} - {{$optionEnsemble->name}}</option>
|
||||
@php
|
||||
if ($ensemble && $ensemble->id == $optionEnsemble->id) {
|
||||
$selected = 'selected';
|
||||
} else {
|
||||
$selected = '';
|
||||
}
|
||||
@endphp
|
||||
<option value ="{{$optionEnsemble->id}}" {{$selected}}>{{$optionEnsemble->event->name}} - {{$optionEnsemble->name}}</option>
|
||||
@endforeach
|
||||
</x-form.select>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<x-layout.app>
|
||||
<x-card.card class="mx-auto max-w-2xl">
|
||||
<x-card.heading>Create Entry</x-card.heading>
|
||||
<x-form.form method="POST" action="/admin/entries">
|
||||
<x-form.form id='createEntryForm' method="POST" action="/admin/entries">
|
||||
<x-form.body-grid columns="3" x-data="studentAuditionFilter()">
|
||||
|
||||
<x-form.select name="student_id" colspan="2" x-model="selectedStudentId" @change="filterAuditions">
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
<input type="hidden" name="for_seating" value="on">
|
||||
@endif
|
||||
</x-form.body-grid>
|
||||
<x-form.footer>
|
||||
<x-form.footer class="mb-5">
|
||||
<x-form.button>Create Entry</x-form.button>
|
||||
</x-form.footer>
|
||||
</x-form.form>
|
||||
|
|
|
|||
|
|
@ -5,19 +5,13 @@
|
|||
Edit Entry #{{ $entry->id }}
|
||||
|
||||
<x-slot:right_side>
|
||||
@if(! Seat::where('entry_id', $entry->id)->exists())
|
||||
<form method="POST" action="{{ route('admin.entries.destroy',['entry' => $entry->id]) }}">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<x-form.red-trash-button type="submit" />
|
||||
</form>
|
||||
@else
|
||||
Seated: {{ $entry->seat->ensemble->name }} #{{ $entry->seat->seat }}
|
||||
@endif
|
||||
<x-delete-resource-modal action="{{route('admin.entries.destroy',$entry->id)}}" title="Delete entry #{{ $entry->id }}">
|
||||
Confirm you would like to delete entry #{{$entry->id}} by {{$entry->student->full_name()}} on {{$entry->audition->name}}.
|
||||
</x-delete-resource-modal>
|
||||
</x-slot:right_side>
|
||||
|
||||
</x-card.heading>
|
||||
<x-form.form method="PATCH" action="/admin/entries/{{ $entry->id }}">
|
||||
<x-form.form id='entryEditForm' method="PATCH" action="/admin/entries/{{ $entry->id }}">
|
||||
<x-form.body-grid columns="6">
|
||||
@if(! Seat::where('entry_id', $entry->id)->exists())
|
||||
<x-form.select name="student_id" colspan="4" disabled>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
{{-- Filter Control--}}
|
||||
<x-card.card>
|
||||
<x-card.heading>Set Filters</x-card.heading>
|
||||
<x-form.form action="/filters/admin_entry_filter" method="POST">
|
||||
<x-form.form action="{{ route('admin_entry_filter.set') }}" method="POST">
|
||||
<x-form.body-grid columns="12">
|
||||
<x-form.field name="id_filter" label_text="Entry ID" colspan="2" value="{{ $filters['id'] ?? '' }}"/>
|
||||
<x-form.select name="audition_filter" colspan="4">
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
<x-form.field name="last_name_filter" colspan="6" label_text="Last Name" value="{{ ($filters['last_name'] ?? null) }}"/>
|
||||
</x-form.body-grid>
|
||||
<x-form.footer class="pb-4">
|
||||
<x-form.button-nocolor href="/filters/admin_entry_filter/clear">Clear Filters</x-form.button-nocolor>
|
||||
<x-form.button-nocolor href="{{ route('admin_entry_filter.clear') }}">Clear Filters</x-form.button-nocolor>
|
||||
<x-form.button>Apply Filters</x-form.button>
|
||||
</x-form.footer>
|
||||
</x-form.form>
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
<x-slot:title class="ml-3">Entries</x-slot:title>
|
||||
<x-slot:subtitle class="ml-3">Double click row to edit</x-slot:subtitle>
|
||||
<x-slot:title_block_right class="mr-3">
|
||||
<x-form.button href="/admin/entries/create">New Entry</x-form.button>
|
||||
<x-form.button href="{{ route('admin.entries.create') }}">New Entry</x-form.button>
|
||||
</x-slot:title_block_right>
|
||||
|
||||
<thead>
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
</thead>
|
||||
<x-table.body>
|
||||
@foreach($entries as $entry)
|
||||
<tr @dblclick="window.location.href='{{ route('admin.entries.edit',['entry' => $entry->id]) }}'">
|
||||
<tr @dblclick="window.location.href='{{ route('admin.entries.edit', ['entry' => $entry->id]) }}'">
|
||||
<x-table.td><a href="/admin/entries/{{ $entry->id }}/edit"> {{ $entry->id }} </a></x-table.td>
|
||||
<x-table.td>{{ $entry->audition->name }}</x-table.td>
|
||||
<x-table.td>{{ $entry->student->full_name() }}</x-table.td>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
<x-card.card x-data="{ showModal: false }" class="relative">
|
||||
@if($room->id != '0')
|
||||
@include('admin.rooms.index-edit-room-modal')
|
||||
@endif
|
||||
<x-card.heading @click=" showModal = ! showModal">
|
||||
{{ $room->name }}
|
||||
<x-slot:subheading>{{ $room->description }}</x-slot:subheading>
|
||||
<x-slot:right_side>
|
||||
@if($room->entries->count() === 0 and $room->id != '0')
|
||||
@if($room->auditions->count() === 0 and $room->id != '0')
|
||||
<div class="flex justify-end">
|
||||
<x-form.form method="DELETE"
|
||||
action="{{ route('admin.rooms.destroy', ['room'=>$room->id]) }}"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<x-layout.app>
|
||||
<x-slot:page_title>Rooms</x-slot:page_title>
|
||||
<x-slot:title_bar_right><x-form.button href="/admin/rooms/create">New Room</x-form.button></x-slot:title_bar_right>
|
||||
<x-slot:title_bar_right><x-form.button href="{{route('admin.rooms.create')}}">New Room</x-form.button></x-slot:title_bar_right>
|
||||
<!--suppress JSUnresolvedReference -->
|
||||
<div class="grid md:grid-cols-4 gap-5" x-data="roomManager()">
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
@if($room->id == 0)
|
||||
@continue
|
||||
@endif
|
||||
<li class=" rounded-xl border border-gray-200 bg-gray-50 "> {{-- card wrapper --}}
|
||||
<li id="room-{{$room->id}}-card" class=" rounded-xl border border-gray-200 bg-gray-50 "> {{-- card wrapper --}}
|
||||
<div class="flex items-center gap-x-4 border-b border-gray-900/5 bg-white pt-2 pb-6 px-6"> {{-- card header --}}
|
||||
<div class="text-sm font-medium leading-6 text-gray-900">
|
||||
<p class="text-sm font-medium leading-6 text-gray-900">{{ $room->name }}</p>
|
||||
|
|
@ -60,8 +60,8 @@
|
|||
<div class="flex justify-between items-center gap-x-4 py-1"> {{-- Judge Line --}}
|
||||
<dt>
|
||||
<p>
|
||||
<span class="text-gray-700">{{ $judge->full_name() }}, </span>
|
||||
<span class="text-gray-500 text-xs">{{ $judge->school->name }}</span>
|
||||
<span class="text-gray-700">{{ $judge->full_name() }} </span>
|
||||
<span class="text-gray-500 text-xs">{{ $judge->school->name ?? '' }}</span>
|
||||
</p>
|
||||
<p class="text-gray-500 text-xs">{{ $judge->judging_preference }}</p>
|
||||
</dt>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
</x-card.heading>
|
||||
|
||||
|
||||
<x-form.form method="POST" action="/admin/schools" class="!mt-4">
|
||||
<x-form.form method="POST" action="{{ route('admin.schools.store') }}" class="!mt-4">
|
||||
<x-form.body-grid columns="6" class="max-w-full">
|
||||
<x-form.field name="name" label_text="School Name" colspan="6"/>
|
||||
<x-form.field name="address" label_text="School Address" colspan="6"/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,54 @@
|
|||
<x-layout.app>
|
||||
|
||||
<x-school.school-edit-form :form_action="'admin/schools/' . $school->id " :school="$school" />
|
||||
<x-card.card class="mx-auto max-w-xl">
|
||||
<x-card.heading>
|
||||
Edit School
|
||||
@if($school->students_count === 0)
|
||||
<x-slot:right_side>
|
||||
<x-delete-resource-modal action="{{ route('admin.schools.destroy',$school) }}" title="Delete school {{ $school->name }}">
|
||||
Confirm you would like to delete the school {{ $school->name }}. This action cannot be undone.
|
||||
</x-delete-resource-modal>
|
||||
</x-slot:right_side>
|
||||
@endif
|
||||
</x-card.heading>
|
||||
<x-form.form method="PATCH" action="{{ route('admin.schools.update',$school) }}">
|
||||
<x-form.body-grid>
|
||||
<x-form.field name="name" label_text="Name" colspan="6" value="{{ $school->name }}" />
|
||||
<x-form.field name="address" label_text="Address" colspan="6" value="{{ $school->address }}" />
|
||||
<x-form.field name="city" label_text="City" colspan="3" value="{{ $school->city }}" />
|
||||
<x-form.field name="state" label_text="State" colspan="2" value="{{ $school->state }}" />
|
||||
<x-form.field name="zip" label_text="Zip" colspan="1" value="{{ $school->zip }}" />
|
||||
</x-form.body-grid>
|
||||
<x-form.footer>
|
||||
<x-form.button class="mb-5">Update School</x-form.button>
|
||||
</x-form.footer>
|
||||
</x-form.form>
|
||||
</x-card.card>
|
||||
|
||||
<x-school.school-domain-form :school="$school" />
|
||||
<x-card.card class="mx-auto max-w-sm mt-8">
|
||||
<x-card.heading>Associated Domains</x-card.heading>
|
||||
<x-card.list.body>
|
||||
@foreach($school->emailDomains as $domain)
|
||||
<x-card.list.row class="!py-1.5 align-middle">
|
||||
<form method="POST" action="{{ route('admin.schools.destroy_domain',$domain) }}" id="deleteDomain{{$domain->id}}">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit">
|
||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10S2 17.523 2 12Zm7.707-3.707a1 1 0 0 0-1.414 1.414L10.586 12l-2.293 2.293a1 1 0 1 0 1.414 1.414L12 13.414l2.293 2.293a1 1 0 0 0 1.414-1.414L13.414 12l2.293-2.293a1 1 0 0 0-1.414-1.414L12 10.586 9.707 8.293Z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
|
||||
</button><span class="px-3">{{ $domain->domain }}</span>
|
||||
</form>
|
||||
</x-card.list.row>
|
||||
@endforeach
|
||||
<x-card.list.row class="!py-1.5">
|
||||
<form method="POST" action="{{ route('admin.schools.add_domain',$school) }}" class="grid sm:grid-cols-2 gap-4">
|
||||
@csrf
|
||||
<x-form.field name="domain" label_text="Add Domain" /><x-form.button class="sm:mt-6">Add Domain</x-form.button>
|
||||
</form>
|
||||
</x-card.list.row>
|
||||
</x-card.list.body>
|
||||
</x-card.card>
|
||||
|
||||
</x-layout.app>
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@
|
|||
<x-table.body>
|
||||
@foreach($schools as $school)
|
||||
<tr>
|
||||
<x-table.td><a href="/admin/schools/{{ $school->id }}">{{ $school->name }}</a></x-table.td>
|
||||
<x-table.td><a href="{{ route('admin.schools.show',$school) }}">{{ $school->name }}</a></x-table.td>
|
||||
<x-table.td>
|
||||
<a href="{{ route('admin.schools.invoice',$school->id) }}">
|
||||
<a href="{{ route('admin.schools.invoice',$school) }}">
|
||||
${{ number_format($schoolTotalFees[$school->id],2) }}
|
||||
</a>
|
||||
</x-table.td>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<x-card.list.body>
|
||||
@foreach($school->emailDomains as $domain)
|
||||
<x-card.list.row class="!py-1.5 align-middle">
|
||||
<form method="POST" action="/admin/schools/domain/{{ $domain->id }}" id="deleteDomain{{$domain->id}}">
|
||||
<form method="POST" action="{{ route('admin.schools.destroy_domain',$domain) }}" id="deleteDomain{{$domain->id}}">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit">
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
</x-card.list.row>
|
||||
@endforeach
|
||||
<x-card.list.row class="!py-1.5">
|
||||
<form method="POST" action="/admin/schools/{{ $school->id }}/add_domain" class="grid sm:grid-cols-2 gap-4">
|
||||
<form method="POST" action="{{ route('admin.schools.add_domain',$school) }}" class="grid sm:grid-cols-2 gap-4">
|
||||
@csrf
|
||||
<x-form.field name="domain" label_text="Add Domain" /><x-form.button class="sm:mt-6">Add Domain</x-form.button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@
|
|||
<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>
|
||||
<a href="{{ route('admin.scoring.edit',['guide'=>$guide, 'tab'=>'detail']) }}" class="{{ $tab == 'detail' ? $active_classes : $normal_classes }}">Details</a>
|
||||
<a href="{{ route('admin.scoring.edit',['guide'=>$guide, '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>--}}
|
||||
<a href="{{ route('admin.scoring.edit',['guide'=>$guide, 'tab'=>'tiebreakOrder']) }}" class="{{ $tab == 'tiebreakOrder' ? $active_classes : $normal_classes }}">Tiebreak Order</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
let auditionId = itemEl.getAttribute('data-id');
|
||||
|
||||
// Make an AJAX request to update the audition_guide_id
|
||||
fetch('/admin/scoring/assign_guide_to_audition', {
|
||||
fetch('{{route('ajax.assignScoringGuideToAudition')}}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
|
|
|||
|
|
@ -17,14 +17,14 @@
|
|||
@continue
|
||||
@endif
|
||||
<tr>
|
||||
<x-table.td>{{ $guide->name }} <span class="text-xs text-gray-400">{{ $guide->subscores->count() }} subscores</span></x-table.td>
|
||||
<x-table.td class="text-right text-indigo-600"><a href="/admin/scoring/guides/{{ $guide->id }}/edit">Edit</a></x-table.td>
|
||||
<x-table.td>{{ $guide->name }} <span class="text-xs text-gray-400">{{ $guide->subscores_count }} subscores</span></x-table.td>
|
||||
<x-table.td class="text-right text-indigo-600"><a href="{{ route('admin.scoring.edit', $guide) }}">Edit</a></x-table.td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table.body>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<x-form.form method="POST" action="/admin/scoring/guides" class="!px-0 !py-0">
|
||||
<x-form.form method="POST" action="{{ route('admin.scoring.store') }}" class="!px-0 !py-0">
|
||||
<x-table.td>
|
||||
<x-form.field name="name" label_text="Add New Scoring Guide" />
|
||||
</x-table.td>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<x-layout.app>
|
||||
<x-card.card class="mx-auto max-w-xl">
|
||||
<x-card.heading>Create Student</x-card.heading>
|
||||
<x-form.form method="POST" action="/admin/students">
|
||||
<x-form.form method="POST" action="{{ route('admin.students.store') }}">
|
||||
<x-form.body-grid columns="12">
|
||||
<x-form.field name="first_name" label_text="First Name" colspan="5" />
|
||||
<x-form.field name="last_name" label_text="Last Name" colspan="5" />
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
</x-form.select>
|
||||
</x-form.body-grid>
|
||||
<x-form.footer>
|
||||
<x-form.footer class="pb-5">
|
||||
<x-form.button>Create Student</x-form.button>
|
||||
</x-form.footer>
|
||||
</x-form.form>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,19 @@
|
|||
<x-layout.app>
|
||||
<x-card.card class="mx-auto max-w-xl">
|
||||
<x-card.heading>Edit Student</x-card.heading>
|
||||
<x-form.form method="PATCH" action="/admin/students/{{ $student->id }}">
|
||||
<x-form.body-grid columns="12">
|
||||
<x-form.field name="first_name" label_text="First Name" colspan="5" value="{{ $student->first_name }}" />
|
||||
<x-form.field name="last_name" label_text="Last Name" colspan="5" value="{{ $student->last_name }}" />
|
||||
<x-card.heading>
|
||||
Edit Student
|
||||
@if($student->entries_count === 0)
|
||||
<x-slot:right_side>
|
||||
<x-delete-resource-modal title="Delete Student {{ $student->full_name() }} from {{ $student->school->name }}" :action="route('admin.students.destroy',$student)">
|
||||
Please confirm you'd like to delete this student. This action cannot be undone.
|
||||
</x-delete-resource-modal>
|
||||
</x-slot:right_side>
|
||||
@endif
|
||||
</x-card.heading>
|
||||
<x-form.form method="PATCH" action="{{ route('admin.students.update',$student) }}">
|
||||
<x-form.body-grid columns="8">
|
||||
<x-form.field name="first_name" label_text="First Name" colspan="3" value="{{ $student->first_name }}" />
|
||||
<x-form.field name="last_name" label_text="Last Name" colspan="3" value="{{ $student->last_name }}" />
|
||||
<x-form.select name="grade" colspan="2">
|
||||
<x-slot:label>Grade</x-slot:label>
|
||||
@php($n = $minGrade)
|
||||
|
|
@ -13,7 +22,7 @@
|
|||
@php($n++);
|
||||
@endwhile
|
||||
</x-form.select>
|
||||
<x-form.select name="school_id" colspan="12">
|
||||
<x-form.select name="school_id" colspan="8">
|
||||
<x-slot:label>School</x-slot:label>
|
||||
@foreach ($schools as $school)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<x-slot:title class="ml-3">Students</x-slot:title>
|
||||
<x-slot:subtitle class="ml-3">Click name to edit</x-slot:subtitle>
|
||||
<x-slot:title_block_right class="mr-3">
|
||||
<x-form.button href="/admin/students/create">New Student</x-form.button>
|
||||
<x-form.button href="{{ route('admin.students.create') }}">New Student</x-form.button>
|
||||
</x-slot:title_block_right>
|
||||
|
||||
<thead>
|
||||
|
|
@ -20,10 +20,10 @@
|
|||
<x-table.body>
|
||||
@foreach($students as $student)
|
||||
<tr>
|
||||
<x-table.td><a href="/admin/students/{{ $student->id }}/edit">{{ $student->full_name(true) }}</a></x-table.td>
|
||||
<x-table.td><a href="{{ route('admin.students.edit',$student) }}">{{ $student->full_name(true) }}</a></x-table.td>
|
||||
<x-table.td>{{ $student->school->name }}</x-table.td>
|
||||
<x-table.td>{{ $student->grade }}</x-table.td>
|
||||
<x-table.td>{{ $student->entries->count() }}</x-table.td>
|
||||
<x-table.td>{{ $student->entries_count }}</x-table.td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table.body>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<x-layout.app>
|
||||
<x-card.card class="mx-auto max-w-lg">
|
||||
<x-card.heading>Create User</x-card.heading>
|
||||
<x-form.form method="POST" action="/admin/users">
|
||||
<x-form.form method="POST" action="{{ route('admin.users.store') }}">
|
||||
<x-form.body-grid>
|
||||
<x-form.field name="first_name" label_text="First Name" colspan="3" />
|
||||
<x-form.field name="last_name" label_text="Last Name" colspan="3" />
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
</x-form.select>
|
||||
</x-form.body-grid>
|
||||
<x-form.footer>
|
||||
<x-form.footer class="pb-5">
|
||||
<x-form.button>Create User</x-form.button>
|
||||
</x-form.footer>
|
||||
</x-form.form>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,18 @@
|
|||
<x-layout.app>
|
||||
<x-card.card class="mx-auto max-w-lg">
|
||||
<x-card.heading>Edit User</x-card.heading>
|
||||
<x-form.form method="PATCH" action="/admin/users/{{ $user->id }}">
|
||||
<x-card.heading>
|
||||
Edit User
|
||||
<x-slot:right_side>
|
||||
@if($user->id != Auth::user()->id)
|
||||
<form method="POST" action="{{ route('admin.users.destroy',['user' => $user->id]) }}">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<x-form.red-trash-button type="submit" />
|
||||
</form>
|
||||
@endif
|
||||
</x-slot:right_side>
|
||||
</x-card.heading>
|
||||
<x-form.form method="PATCH" action="{{ route('admin.users.update', $user) }}">
|
||||
<x-form.body-grid>
|
||||
<x-form.field name="first_name" label_text="First Name" colspan="3" value="{{ $user->first_name }}" />
|
||||
<x-form.field name="last_name" label_text="Last Name" colspan="3" value="{{ $user->last_name }}" />
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
<x-card.card>
|
||||
<x-table.table with_title_area>
|
||||
<x-slot:title class="ml-3">Users</x-slot:title>
|
||||
<x-slot:subtitle class="ml-3">Click name to edit</x-slot:subtitle>
|
||||
<x-slot:subtitle class="ml-3">Click name to edit or delete</x-slot:subtitle>
|
||||
<x-slot:title_block_right class="mr-3">
|
||||
<x-form.button href="/admin/users/create">New User</x-form.button>
|
||||
<x-form.button href="{{ route('admin.users.create') }}">New User</x-form.button>
|
||||
</x-slot:title_block_right>
|
||||
|
||||
<thead>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<x-table.body>
|
||||
@foreach($users as $user)
|
||||
<tr>
|
||||
<x-table.td><a href="/admin/users/{{ $user->id }}/edit">{{ $user->full_name(true) }}</a></x-table.td>
|
||||
<x-table.td><a href="{{ route('admin.users.edit',$user) }}">{{ $user->full_name(true) }}</a></x-table.td>
|
||||
<x-table.td>{{ $user->has_school() ? $user->school->name : ' ' }}</x-table.td>
|
||||
<x-table.td>{{ $user->email }}</x-table.td>
|
||||
<x-table.td>{{ $user->cell_phone }}</x-table.td>
|
||||
|
|
@ -32,7 +32,3 @@
|
|||
</x-table.table>
|
||||
</x-card.card>
|
||||
</x-layout.app>
|
||||
|
||||
|
||||
|
||||
{{ $user->has_school() ? $user->school->name : 'No School' }}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,134 @@
|
|||
@php
|
||||
/**
|
||||
* @var int $size=20 Size of the icon
|
||||
* @var string $title Title of the modal
|
||||
* @var string $method='DELETE' method used by the form
|
||||
* @var string $action action used for the form
|
||||
*/
|
||||
@endphp
|
||||
@props(['size' => 20,'title','method'=>'DELETE','action'])
|
||||
|
||||
<div
|
||||
x-data="{ 'showModal': false }"
|
||||
@keydown.escape="showModal = false"
|
||||
>
|
||||
<!-- Trigger for Modal -->
|
||||
<button type="button" @click="showModal = true" class="rounded-lg bg-red-600 p-1.5 text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600">
|
||||
{{-- trash button to show modal --}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="{{ $size }}" height="{{ $size }}" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
|
||||
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/>
|
||||
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/>
|
||||
</svg>
|
||||
|
||||
</button>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="relative z-10"
|
||||
aria-labelledby="modal-title"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
x-show="showModal"
|
||||
x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
x-cloak>
|
||||
<!--
|
||||
Background backdrop, show/hide based on modal state.
|
||||
|
||||
Entering: "ease-out duration-300"
|
||||
From: "opacity-0"
|
||||
To: "opacity-100"
|
||||
Leaving: "ease-in duration-200"
|
||||
From: "opacity-100"
|
||||
To: "opacity-0"
|
||||
-->
|
||||
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
|
||||
|
||||
<div class="fixed inset-0 z-10 w-screen overflow-y-auto">
|
||||
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0"
|
||||
x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-cloak
|
||||
x-show="showModal">
|
||||
<!--
|
||||
Modal panel, show/hide based on modal state.
|
||||
|
||||
Entering: "ease-out duration-300"
|
||||
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
To: "opacity-100 translate-y-0 sm:scale-100"
|
||||
Leaving: "ease-in duration-200"
|
||||
From: "opacity-100 translate-y-0 sm:scale-100"
|
||||
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
-->
|
||||
<div
|
||||
class="relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6"
|
||||
x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-cloak
|
||||
x-show="showModal"
|
||||
@click.away="showModal = false">
|
||||
<div class="absolute right-0 top-0 hidden pr-4 pt-4 sm:block">
|
||||
<button type="button"
|
||||
@click="showModal = false"
|
||||
class="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
|
||||
<span class="sr-only">Close</span>
|
||||
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div
|
||||
class="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||
<svg class="h-6 w-6 text-red-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900" id="modal-title">
|
||||
{{ $title }}
|
||||
</h3>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ $slot }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
|
||||
<form method="{{ $method == 'GET' ? 'GET':'POST' }}" action="{{$action}}">
|
||||
@csrf
|
||||
@if(! in_array($method, ['POST','GET']))
|
||||
@method($method)
|
||||
@endif
|
||||
<button type="submit"
|
||||
class="inline-flex w-full justify-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 sm:ml-3 sm:w-auto">
|
||||
Delete
|
||||
</button>
|
||||
</form>
|
||||
<button type="button"
|
||||
@click="showModal = false"
|
||||
class="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -10,5 +10,4 @@
|
|||
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/>
|
||||
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/>
|
||||
</svg>
|
||||
</svg>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
@props(['color' => 'currentColor'])
|
||||
@props(['color' => 'currentColor', 'title'=>false])
|
||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
@if($title)<title>{{ $title }}</title>@endif
|
||||
<path stroke="{{$color}}" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 11.917 9.724 16.5 19 7.5"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
@props(['color' => 'currentColor'])
|
||||
@props(['color' => 'currentColor', 'title' => false])
|
||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
@if($title)<title>{{ $title }}</title>@endif
|
||||
<path stroke="{{ $color }}" stroke-linecap="round" stroke-width="2" d="m6 6 12 12m3-6a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@props(['title' => false])
|
||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
@if($title)<title>{{ $title }}</title>@endif
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M5 7h14M5 12h14M5 17h14"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 346 B |
|
|
@ -1,4 +1,5 @@
|
|||
@props(['color' => 'currentColor'])
|
||||
@props(['color' => 'currentColor','title'=>false])
|
||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="{{ $color }}" viewBox="0 0 24 24">
|
||||
@if($title)<title>{{ $title }}</title>@endif
|
||||
<path fill-rule="evenodd" d="M8.97 14.316H5.004c-.322 0-.64-.08-.925-.232a2.022 2.022 0 0 1-.717-.645 2.108 2.108 0 0 1-.242-1.883l2.36-7.201C5.769 3.54 5.96 3 7.365 3c2.072 0 4.276.678 6.156 1.256.473.145.925.284 1.35.404h.114v9.862a25.485 25.485 0 0 0-4.238 5.514c-.197.376-.516.67-.901.83a1.74 1.74 0 0 1-1.21.048 1.79 1.79 0 0 1-.96-.757 1.867 1.867 0 0 1-.269-1.211l1.562-4.63ZM19.822 14H17V6a2 2 0 1 1 4 0v6.823c0 .65-.527 1.177-1.177 1.177Z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
@props(['color' => 'currentColor'])
|
||||
@props(['color' => 'currentColor','title'=>false])
|
||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="{{ $color }}" viewBox="0 0 24 24">
|
||||
@if($title)<title>{{ $title }}</title>@endif
|
||||
<path fill-rule="evenodd" d="M15.03 9.684h3.965c.322 0 .64.08.925.232.286.153.532.374.717.645a2.109 2.109 0 0 1 .242 1.883l-2.36 7.201c-.288.814-.48 1.355-1.884 1.355-2.072 0-4.276-.677-6.157-1.256-.472-.145-.924-.284-1.348-.404h-.115V9.478a25.485 25.485 0 0 0 4.238-5.514 1.8 1.8 0 0 1 .901-.83 1.74 1.74 0 0 1 1.21-.048c.396.13.736.397.96.757.225.36.32.788.269 1.211l-1.562 4.63ZM4.177 10H7v8a2 2 0 1 1-4 0v-6.823C3 10.527 3.527 10 4.176 10Z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{{-- <button type="button" class="inline-flex items-center gap-x-1 text-sm font-semibold leading-6 text-gray-900" aria-expanded="false" @on:click=" open = ! open">--}}
|
||||
|
||||
<button type="button" class="inline-flex items-center gap-x-1 text-white rounded-md px-3 py-2 text-sm font-medium hover:bg-indigo-500 hover:bg-opacity-75" aria-expanded="false" @click=" open = ! open" @click.outside=" open = false">
|
||||
<span>Admin</span>
|
||||
<span>Administration</span>
|
||||
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -14,16 +14,16 @@
|
|||
</div>
|
||||
<div class="hidden md:block">
|
||||
<div class="ml-10 flex items-baseline space-x-4">
|
||||
<x-layout.navbar.nav-link href="/dashboard" :active="request()->is('dashboard')">Dashboard
|
||||
<x-layout.navbar.nav-link href="{{ route('dashboard') }}" :active="request()->is('dashboard')">Dashboard
|
||||
</x-layout.navbar.nav-link>
|
||||
@if(Auth::user()->school_id)
|
||||
<x-layout.navbar.nav-link href="/students" :active="request()->is('students')">Students
|
||||
<x-layout.navbar.nav-link href="{{ route('students.index') }}" :active="request()->is('students')">Students
|
||||
</x-layout.navbar.nav-link>
|
||||
<x-layout.navbar.nav-link href="/entries" :active="request()->is('entries')">Entries
|
||||
<x-layout.navbar.nav-link href="{{ route('entries.index') }}" :active="request()->is('entries')">Entries
|
||||
</x-layout.navbar.nav-link>
|
||||
@endif
|
||||
@if(Auth::user()->isJudge() AND Settings::get('judging_enabled'))
|
||||
<x-layout.navbar.nav-link href="/judging" :active="request()->is('judging')">Judging
|
||||
<x-layout.navbar.nav-link href="{{ route('judging.index') }}" :active="request()->is('judging')">Judging
|
||||
</x-layout.navbar.nav-link>
|
||||
@endif
|
||||
@if(Auth::user()->is_admin)
|
||||
|
|
@ -164,8 +164,7 @@
|
|||
<!-- Current: "bg-indigo-700 text-white", Default: "text-white hover:bg-indigo-500 hover:bg-opacity-75" -->
|
||||
<a href="/dashboard" class="bg-indigo-700 text-white block rounded-md px-3 py-2 text-base font-medium"
|
||||
aria-current="page">Dashboard</a>
|
||||
<a href="/students"
|
||||
class="text-white hover:bg-indigo-500 hover:bg-opacity-75 block rounded-md px-3 py-2 text-base font-medium">Students</a>
|
||||
|
||||
</div>
|
||||
<div class="border-t border-indigo-700 pb-3 pt-4">
|
||||
<div class="flex items-center px-5">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<x-layout.app>
|
||||
<x-slot:page_title>Dashboard</x-slot:page_title>
|
||||
@if(! Auth::user()->school_id)
|
||||
You aren't currently associated with a school. <a href="/my_school" class="text-blue-600">Click here to choose or create one.</a>
|
||||
<p class="pb-5">You aren't currently associated with a school. <a href="/my_school" class="text-blue-600">Click here to choose or create one.</a></p>
|
||||
@endif
|
||||
<div class="grid sm:grid-cols-2 md:grid-cols-4">
|
||||
<div>{{-- Column 1 --}}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<x-layout.page-section-container>
|
||||
<x-layout.page-section>
|
||||
<x-slot:section_name>Add Entry</x-slot:section_name>
|
||||
<x-form.form method="POST" action="/entries" class="pt-6 pb-8">
|
||||
<x-form.form method="POST" action="{{ route('entries.store') }}" class="pt-6 pb-8">
|
||||
|
||||
<x-form.body-grid columns="6" class="max-w-full" x-data="studentAuditionFilter()">
|
||||
|
||||
|
|
@ -81,23 +81,33 @@
|
|||
@if(auditionSetting('advanceTo'))
|
||||
<x-table.td>
|
||||
@if($entry->for_seating)
|
||||
<x-icons.checkmark color="green" />
|
||||
<div aria-label="{{ $entry->student->full_name() }} on {{ $entry->audition->name }} is entered for seating. Entry ID {{ $entry->id }}">
|
||||
<x-icons.checkmark color="green"/>
|
||||
</div>
|
||||
@else
|
||||
<x-icons.circle-slash-no color="red" />
|
||||
<div aria-label="{{ $entry->student->full_name() }} on {{ $entry->audition->name }} is not entered for seating. Entry ID {{ $entry->id }}">
|
||||
<x-icons.circle-slash-no color="red"/>
|
||||
</div>
|
||||
@endif
|
||||
</x-table.td>
|
||||
<x-table.td>
|
||||
@if($entry->for_advancement)
|
||||
<x-icons.checkmark color="green" />
|
||||
<div aria-label="{{ $entry->student->full_name() }} on {{ $entry->audition->name }} is entered for advancement. Entry ID {{ $entry->id }}">
|
||||
<x-icons.checkmark color="green"/>
|
||||
|
||||
</div>
|
||||
@else
|
||||
<x-icons.circle-slash-no color="red" />
|
||||
<div aria-label="{{ $entry->student->full_name() }} on {{ $entry->audition->name }} is not entered for advancement. Entry ID {{ $entry->id }}">
|
||||
<x-icons.circle-slash-no color="red"/>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
</x-table.td>
|
||||
@endif
|
||||
|
||||
<x-table.td for_button>
|
||||
@if( $entry->audition->entry_deadline >= now())
|
||||
<form method="POST" action="/entries/{{ $entry->id }}" class="inline">
|
||||
<form method="POST" action="{{ route('entries.destroy',$entry) }}" class="inline">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<x-table.button
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
@foreach($entries as $entry)
|
||||
<tr>
|
||||
<x-table.td>
|
||||
<a href="/judging/entry/{{$entry->id}}">
|
||||
<a href="{{ route('judging.entryScoreSheet',$entry) }}">
|
||||
{{ $audition->name }} {{ $entry->draw_number }}
|
||||
</a>
|
||||
</x-table.td>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<x-card.heading>{{ $room->name }}</x-card.heading>
|
||||
<x-card.list.body>
|
||||
@foreach($room->auditions as $audition)
|
||||
<a href="/judging/audition/{{$audition->id}}">
|
||||
<a href="{{ route('judging.auditionEntryList', $audition) }}">
|
||||
<x-card.list.row class="!py-3 ml-3">{{ $audition->name }}</x-card.list.row>
|
||||
</a>
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<x-card.card>
|
||||
<x-card.heading>Edit Student</x-card.heading>
|
||||
|
||||
<x-form.form method="PATCH" class="!pt-2 !pb-6 !space-y-2" action="/students/{{ $student->id }}">
|
||||
<x-form.form method="PATCH" class="!pt-2 !pb-6 !space-y-2" action="{{route('students.update',$student)}}">
|
||||
<x-form.field name="first_name" label_text="First Name" type="text" value="{{ $student->first_name }}"/>
|
||||
<x-form.field name="last_name" label_text="Last Name" type="text" value="{{ $student->last_name }}"/>
|
||||
<x-form.field name="grade" label_text="Grade" type="number" class="mb-3" value="{{ $student->grade }}"/>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<x-layout.page-section-container>
|
||||
<x-layout.page-section>
|
||||
<x-slot:section_name>Add Student</x-slot:section_name>
|
||||
<x-form.form method="POST" action="/students" class="mb-6 mt-3">
|
||||
<x-form.form method="POST" action="{{ route('students.store') }}" class="mb-6 mt-3">
|
||||
<x-form.body-grid columns="8" class="max-w-full">
|
||||
<x-form.field name="first_name" label_text="First Name" colspan="3"/>
|
||||
<x-form.field name="last_name" label_text="Last Name" colspan="3"/>
|
||||
|
|
@ -46,10 +46,10 @@
|
|||
<tr>
|
||||
<x-table.td first>{{ $student->full_name(true) }}</x-table.td>
|
||||
<x-table.td>{{ $student->grade }}</x-table.td>
|
||||
<x-table.td>{{ $student->entries->count() }}</x-table.td>
|
||||
<x-table.td>{{ $student->entries_count }}</x-table.td>
|
||||
<x-table.td for_button>
|
||||
@if( $student->entries->count() > 0)
|
||||
<form method="POST" action="/students/{{ $student->id }}" class="inline">
|
||||
@if( $student->entries_count === 0)
|
||||
<form method="POST" action="{{ route('students.destroy',$student) }}" class="inline">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<x-table.button
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
</form>
|
||||
|
|
||||
@endif
|
||||
<x-table.button href="/students/{{ $student->id }}/edit">Edit</x-table.button>
|
||||
<x-table.button href="{{ route('students.edit',$student) }}">Edit</x-table.button>
|
||||
</x-table.td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
@php use Illuminate\Support\Facades\Auth; @endphp
|
||||
@push('scripts')
|
||||
{{-- Code from https://codepen.io/ryangjchandler/pen/WNQQKeR--}}
|
||||
<script src="{{ asset('js/sort_table_by_column.js') }}"></script>
|
||||
@endpush
|
||||
<x-layout.app>
|
||||
<x-slot:page_title>Students</x-slot:page_title>
|
||||
|
||||
<x-table.container class="mx-auto max-w-2xl" x-data="data()">
|
||||
<x-table.title_above_table>
|
||||
<x-slot:title>Students <x-badge_pill>{{ $students->count() }}</x-badge_pill></x-slot:title>
|
||||
<x-slot:subtitle>Before submitting entries, you must enter your students</x-slot:subtitle>
|
||||
<x-slot:button>Add Student</x-slot:button>
|
||||
</x-table.title_above_table>
|
||||
|
||||
<x-table.table>
|
||||
<x-table.table_header_row>
|
||||
<x-table.th first @click="sortByColumn" class="cursor-pointer select-none">Name</x-table.th>
|
||||
<x-table.th @click="sortByColumn" class="cursor-pointer select-none">Grade</x-table.th>
|
||||
<x-table.th :placeholder="true">
|
||||
<span class="sr-only">Edit</span>
|
||||
</x-table.th>
|
||||
<x-table.body x-ref="tbody">
|
||||
@foreach($students as $student)
|
||||
<tr>
|
||||
<x-table.td :first="true">{{ $student->full_name(true) }}</x-table.td>
|
||||
<x-table.td>{{ $student->grade }}</x-table.td>
|
||||
<x-table.td_right_link sr_text=", {{ $student->full_name() }}">
|
||||
<x-slot:a href="/students/{{ $student->id }}/edit">Edit</x-slot:a>
|
||||
</x-table.td_right_link>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table.body>
|
||||
</x-table.table_header_row>
|
||||
</x-table.table>
|
||||
</x-table.container>
|
||||
</x-layout.app>
|
||||
|
|
@ -5,10 +5,10 @@ use App\Http\Middleware\CheckIfAdmin;
|
|||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware(['auth', 'verified', CheckIfAdmin::class])->prefix('admin/')->group(function () {
|
||||
Route::view('/', 'admin.dashboard');
|
||||
Route::view('/', 'admin.dashboard')->name('admin.dashboard');
|
||||
|
||||
Route::post('/auditions/roomUpdate', [\App\Http\Controllers\Admin\AuditionController::class, 'roomUpdate']); // Endpoint for JS assigning auditions to rooms
|
||||
Route::post('/scoring/assign_guide_to_audition', [\App\Http\Controllers\Admin\AuditionController::class, 'scoringGuideUpdate']); // Endpoint for JS assigning scoring guides to auditions
|
||||
Route::post('/scoring/assign_guide_to_audition', [\App\Http\Controllers\Admin\AuditionController::class, 'scoringGuideUpdate'])->name('ajax.assignScoringGuideToAudition'); // Endpoint for JS assigning scoring guides to auditions
|
||||
|
||||
Route::get('/settings', [\App\Http\Controllers\Admin\AuditionSettings::class, 'index'])->name('audition-settings');
|
||||
Route::post('/settings', [\App\Http\Controllers\Admin\AuditionSettings::class, 'save'])->name('audition-settings-save');
|
||||
|
|
@ -19,7 +19,7 @@ Route::middleware(['auth', 'verified', CheckIfAdmin::class])->prefix('admin/')->
|
|||
Route::post('/', 'store')->name('admin.ensembles.store');
|
||||
Route::delete('/{ensemble}', 'destroy')->name('admin.ensembles.destroy');
|
||||
Route::post('/updateEnsembleRank', 'updateEnsembleRank')->name('admin.ensembles.updateEnsembleRank');
|
||||
Route::patch('/{ensemble}', 'updateEnsemble')->name('admin.ensembles.updateEnsemble');
|
||||
Route::patch('/{ensemble}', 'updateEnsemble')->name('admin.ensembles.update');
|
||||
Route::get('/seating-limits', 'seatingLimits')->name('admin.ensembles.seatingLimits');
|
||||
Route::get('/seating-limits/{ensemble}', 'seatingLimits')->name('admin.ensembles.seatingLimits.ensemble');
|
||||
Route::post('/seating-limits/{ensemble}', 'seatingLimitsSet')->name('admin.ensembles.seatingLimits.ensemble.set');
|
||||
|
|
@ -49,7 +49,7 @@ Route::middleware(['auth', 'verified', CheckIfAdmin::class])->prefix('admin/')->
|
|||
Route::prefix('scoring')->controller(\App\Http\Controllers\Admin\ScoringGuideController::class)->group(function () {
|
||||
Route::get('/', 'index')->name('admin.scoring.index'); // Scoring Setup Homepage
|
||||
Route::post('/guides', 'store')->name('admin.scoring.store'); // Save a new scoring guide
|
||||
Route::get('/guides/{guide}/edit', 'edit')->name('admin.scoring.edit'); // Edit scoring guide
|
||||
Route::get('/guides/{guide}/edit/{tab?}', 'edit')->name('admin.scoring.edit'); // Edit scoring guide
|
||||
Route::patch('/guides/{guide}/edit', 'update')->name('admin.scoring.update'); // Save changes to audition guide (rename)
|
||||
Route::post('/guides/{guide}/subscore', 'subscore_store')->name('admin.scoring.subscore_store'); // Save a new subscore
|
||||
Route::patch('/guides/{guide}/subscore/{subscore}', 'subscore_update')->name('admin.scoring.subscore_update'); // Modify a subscore
|
||||
|
|
@ -75,21 +75,22 @@ Route::middleware(['auth', 'verified', CheckIfAdmin::class])->prefix('admin/')->
|
|||
// Admin Entries Routes
|
||||
Route::prefix('entries')->controller(\App\Http\Controllers\Admin\EntryController::class)->group(function () {
|
||||
Route::get('/', 'index')->name('admin.entries.index');
|
||||
Route::get('/create', 'create');
|
||||
Route::post('/', 'store');
|
||||
Route::get('/create', 'create')->name('admin.entries.create');
|
||||
Route::post('/', 'store')->name('admin.entries.store');
|
||||
Route::get('/{entry}/edit', 'edit')->name('admin.entries.edit');
|
||||
Route::patch('/{entry}', 'update');
|
||||
Route::patch('/{entry}', 'update')->name('admin.entries.update');
|
||||
Route::delete('/{entry}', 'destroy')->name('admin.entries.destroy');
|
||||
|
||||
});
|
||||
|
||||
// Admin Student Routes
|
||||
Route::prefix('students')->controller(\App\Http\Controllers\Admin\StudentController::class)->group(function () {
|
||||
Route::get('/', 'index');
|
||||
Route::get('/create', 'create');
|
||||
Route::post('/', 'store');
|
||||
Route::get('/{student}/edit', 'edit');
|
||||
Route::patch('/{student}', 'update');
|
||||
Route::get('/', 'index')->name('admin.students.index');
|
||||
Route::get('/create', 'create')->name('admin.students.create');
|
||||
Route::post('/', 'store')->name('admin.students.store');
|
||||
Route::get('/{student}/edit', 'edit')->name('admin.students.edit');
|
||||
Route::patch('/{student}', 'update')->name('admin.students.update');
|
||||
Route::delete('/{student}', 'destroy')->name('admin.students.destroy');
|
||||
});
|
||||
|
||||
// Admin School Routes
|
||||
|
|
@ -103,16 +104,17 @@ Route::middleware(['auth', 'verified', CheckIfAdmin::class])->prefix('admin/')->
|
|||
Route::patch('/{school}', 'update')->name('admin.schools.update');
|
||||
Route::post('/', 'store')->name('admin.schools.store');
|
||||
Route::delete('/domain/{domain}', 'destroy_domain')->name('admin.schools.destroy_domain');
|
||||
Route::delete('/{school}', 'destroy')->name('admin.schools.destroy');
|
||||
|
||||
});
|
||||
|
||||
// Admin User Routes
|
||||
Route::prefix('users')->controller(\App\Http\Controllers\Admin\UserController::class)->group(function () {
|
||||
Route::get('/', 'index');
|
||||
Route::get('/create', 'create');
|
||||
Route::post('/', 'store');
|
||||
Route::get('/{user}/edit', 'edit');
|
||||
Route::patch('/{user}', 'update');
|
||||
Route::delete('/{user}', 'destroy');
|
||||
Route::get('/', 'index')->name('admin.users.index');
|
||||
Route::get('/create', 'create')->name('admin.users.create');
|
||||
Route::post('/', 'store')->name('admin.users.store');
|
||||
Route::get('/{user}/edit', 'edit')->name('admin.users.edit');
|
||||
Route::patch('/{user}', 'update')->name('admin.users.update');
|
||||
Route::delete('/{user}', 'destroy')->name('admin.users.destroy');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,3 +6,9 @@ use Illuminate\Support\Facades\Artisan;
|
|||
Artisan::command('inspire', function () {
|
||||
$this->comment(Inspiring::quote());
|
||||
})->purpose('Display an inspiring quote')->hourly();
|
||||
|
||||
Artisan::command('logs:remove', function () {
|
||||
exec('rm -f '.storage_path('logs/*.log'));
|
||||
exec('rm -f '.base_path('*.log'));
|
||||
$this->comment('Logs have been removed!');
|
||||
})->describe('Remove log files');
|
||||
|
|
|
|||
|
|
@ -19,32 +19,32 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
|||
|
||||
// Entry Related Routes
|
||||
Route::middleware(['auth', 'verified', 'can:create,App\Models\Entry'])->controller(EntryController::class)->group(function () {
|
||||
Route::get('/entries', 'index');
|
||||
Route::get('/entries/create', 'create');
|
||||
Route::post('/entries', 'store');
|
||||
Route::delete('/entries/{entry}', 'destroy');
|
||||
Route::get('/entries', 'index')->name('entries.index');
|
||||
Route::get('/entries/create', 'create')->name('entries.create');
|
||||
Route::post('/entries', 'store')->name('entries.store');
|
||||
Route::delete('/entries/{entry}', 'destroy')->name('entries.destroy');
|
||||
});
|
||||
|
||||
// User Related Routes
|
||||
Route::middleware(['auth', 'verified'])->controller(UserController::class)->group(function () {
|
||||
Route::patch('/users/{user}/set_school', 'set_school');
|
||||
Route::patch('/users/{$user}', 'update');
|
||||
Route::patch('/users/{user}/set_school', 'set_school')->name('users.set_school');
|
||||
Route::patch('/users/{$user}', 'update')->name('users.update');
|
||||
});
|
||||
|
||||
// Student Related Routes
|
||||
Route::middleware(['auth', 'verified', 'can:create,App\Models\Student'])->controller(StudentController::class)->group(function () {
|
||||
Route::get('/students', 'index');
|
||||
Route::post('students', 'store');
|
||||
Route::get('/students/{student}/edit', 'edit');
|
||||
Route::patch('/students/{student}', 'update');
|
||||
Route::delete('/students/{student}', 'destroy');
|
||||
Route::get('/students', 'index')->name('students.index');
|
||||
Route::post('students', 'store')->name('students.store');
|
||||
Route::get('/students/{student}/edit', 'edit')->name('students.edit');
|
||||
Route::patch('/students/{student}', 'update')->name('students.update');
|
||||
Route::delete('/students/{student}', 'destroy')->name('students.destroy');
|
||||
});
|
||||
|
||||
// School Related Routes
|
||||
Route::middleware(['auth', 'verified'])->controller(SchoolController::class)->group(function () {
|
||||
Route::get('/schools/create', 'create');
|
||||
Route::post('/schools', 'store');
|
||||
Route::get('/schools/{school}/edit', 'edit');
|
||||
Route::get('/schools/{school}', 'show')->name('schools.show');
|
||||
Route::patch('/schools/{school}', 'update');
|
||||
Route::get('/schools/create', 'create')->name('schools.create');
|
||||
Route::post('/schools', 'store')->name('schools.store');
|
||||
Route::get('/schools/{school}/edit', 'edit')->name('schools.edit');
|
||||
Route::get('/schools/{school}', 'show')->name('schools.show')->name('schools.show');
|
||||
Route::patch('/schools/{school}', 'update')->name('schools.update');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ Route::get('/results', [App\Http\Controllers\ResultsPage::class, '__invoke'])->n
|
|||
|
||||
// Filter Related Routes
|
||||
Route::prefix('filters')->middleware(['auth', 'verified'])->controller(FilterController::class)->group(function () {
|
||||
Route::post('/admin_entry_filter', 'adminEntryFilter');
|
||||
Route::get('/admin_entry_filter/clear', 'clearAdminEntryFilter');
|
||||
Route::post('/admin_entry_filter', 'adminEntryFilter')->name('admin_entry_filter.set');
|
||||
Route::get('/admin_entry_filter/clear', 'clearAdminEntryFilter')->name('admin_entry_filter.clear');
|
||||
});
|
||||
|
||||
//Route::get('/my_school', [SchoolController::class, 'my_school'])->middleware('auth','verified');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Audition;
|
||||
use App\Models\AuditionFlag;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('has an audition', function () {
|
||||
|
||||
$audition = Audition::factory()->create();
|
||||
// Arrange
|
||||
$flag = AuditionFlag::create([
|
||||
'audition_id' => $audition->id,
|
||||
'flag_name' => 'Test Flag',
|
||||
]);
|
||||
|
||||
// Act and Assert
|
||||
expect($flag->audition->name)->toBe($audition->name);
|
||||
|
||||
});
|
||||
|
|
@ -1,6 +1,12 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Audition;
|
||||
use App\Models\AuditionFlag;
|
||||
use App\Models\Entry;
|
||||
use App\Models\Event;
|
||||
use App\Models\Room;
|
||||
use App\Models\ScoringGuide;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
|
@ -63,3 +69,102 @@ it('only returns published advancement auditions for advancementPublished scope'
|
|||
->first()->id->toEqual($published->id);
|
||||
|
||||
});
|
||||
|
||||
it('has an event', function () {
|
||||
// Arrange
|
||||
$event = Event::factory()->create(['name' => 'Symphonic Concert Wind Ensemble Band']);
|
||||
$audition = Audition::factory()->create(['event_id' => $event->id]);
|
||||
// Act & Assert
|
||||
expect($audition->event->name)->toEqual('Symphonic Concert Wind Ensemble Band');
|
||||
|
||||
});
|
||||
|
||||
it('has entries', function () {
|
||||
// Arrange
|
||||
$audition = Audition::factory()->create();
|
||||
Entry::factory()->count(10)->create(['audition_id' => $audition->id]);
|
||||
// Act & Assert
|
||||
expect($audition->entries->count())->toEqual(10);
|
||||
});
|
||||
|
||||
it('has a room', function () {
|
||||
// Arrange
|
||||
$room = Room::factory()->create(['name' => 'Room 1']);
|
||||
$audition = Audition::factory()->create(['room_id' => $room->id]);
|
||||
|
||||
// Act & Assert
|
||||
expect($audition->room->name)->toEqual('Room 1');
|
||||
|
||||
});
|
||||
|
||||
it('has a scoring guide', function () {
|
||||
// Arrange
|
||||
$sg = ScoringGuide::factory()->create(['name' => 'Sight Reading']);
|
||||
$audition = Audition::factory()->create(['scoring_guide_id' => $sg->id]);
|
||||
// Act & Assert
|
||||
expect($audition->scoringGuide->name)->toEqual('Sight Reading');
|
||||
|
||||
});
|
||||
|
||||
it('displays the entry fee', function () {
|
||||
// Arrange
|
||||
$audition = Audition::factory()->create(['entry_fee' => 1000]);
|
||||
// Act & Assert
|
||||
expect($audition->display_fee())->toEqual('$10.00');
|
||||
});
|
||||
|
||||
it('has many judges', function () {
|
||||
// Arrange
|
||||
$room = Room::factory()->create();
|
||||
$audition = Audition::factory()->create(['room_id' => $room->id]);
|
||||
$judges = User::factory()->count(5)->create();
|
||||
foreach ($judges as $judge) {
|
||||
$room->addJudge($judge->id);
|
||||
}
|
||||
// Act & Assert
|
||||
expect($audition->judges->count())->toEqual(5);
|
||||
});
|
||||
|
||||
it('has a judges_count available', function () {
|
||||
// Arrange
|
||||
$room = Room::factory()->create();
|
||||
$audition = Audition::factory()->create(['room_id' => $room->id]);
|
||||
$judges = User::factory()->count(5)->create();
|
||||
foreach ($judges as $judge) {
|
||||
$room->addJudge($judge->id);
|
||||
}
|
||||
// Act & Assert
|
||||
expect($audition->judges_count)->toEqual(5);
|
||||
});
|
||||
|
||||
it('can have flags', function () {
|
||||
// Arrange
|
||||
$audition = Audition::factory()->create();
|
||||
AuditionFlag::create(['audition_id' => $audition->id, 'flag_name' => 'seats_published']);
|
||||
AuditionFlag::create(['audition_id' => $audition->id, 'flag_name' => 'advance_published']);
|
||||
// Act
|
||||
// Assert
|
||||
expect($audition->hasFlag('seats_published'))->toBeTrue();
|
||||
expect($audition->hasFlag('notaflag'))->toBeFalse();
|
||||
expect($audition->flags->count())->toEqual(2);
|
||||
});
|
||||
|
||||
it('can add flags', function () {
|
||||
// Arrange
|
||||
$audition = Audition::factory()->create();
|
||||
// Act
|
||||
$audition->addFlag('seats_published');
|
||||
// Assert
|
||||
expect($audition->hasFlag('seats_published'))->toBeTrue();
|
||||
});
|
||||
|
||||
it('can remove flags', function () {
|
||||
// Arrange
|
||||
$audition = Audition::factory()->create();
|
||||
AuditionFlag::create(['audition_id' => $audition->id, 'flag_name' => 'seats_published']);
|
||||
// Act & Assert
|
||||
$audition->addFlag('seats_published');
|
||||
expect($audition->hasFlag('seats_published'))->toBeTrue();
|
||||
$audition->removeFlag('seats_published');
|
||||
expect($audition->hasFlag('seats_published'))->toBeFalse();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Audition;
|
||||
use App\Models\Ensemble;
|
||||
use App\Models\Entry;
|
||||
use App\Models\Event;
|
||||
use App\Models\Seat;
|
||||
use App\Models\SeatingLimit;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('has an event', function () {
|
||||
$event = Event::factory()->create();
|
||||
$ensemble = Ensemble::factory()->create(['event_id' => $event->id]);
|
||||
expect($ensemble->event)->toBeInstanceOf(Event::class)
|
||||
->and($ensemble->event->name)->toBe($event->name);
|
||||
});
|
||||
|
||||
it('has auditions in score order', function () {
|
||||
// Arrange
|
||||
$ensemble = Ensemble::factory()->create();
|
||||
$oboe = Audition::factory()->create(['event_id' => $ensemble->event_id, 'name' => 'Oboe', 'score_order' => 2]);
|
||||
$flute = Audition::factory()->create(['event_id' => $ensemble->event_id, 'name' => 'Flute', 'score_order' => 1]);
|
||||
$clarinet = Audition::factory()->create(['event_id' => $ensemble->event_id, 'name' => 'Clarinet',
|
||||
'score_order' => 3,
|
||||
]);
|
||||
// Act & Assert
|
||||
expect($ensemble->auditions)->toHaveCount(3)
|
||||
->sequence(
|
||||
fn ($seatingLimit) => $seatingLimit->audition_id === $flute->id,
|
||||
fn ($seatingLimit) => $seatingLimit->audition_id === $oboe->id,
|
||||
fn ($seatingLimit) => $seatingLimit->audition_id === $clarinet->id,
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
it('has seating limits',
|
||||
function () {
|
||||
// Arrange
|
||||
$ensemble = Ensemble::factory()->create();
|
||||
$auditions = Audition::factory()->count(3)->create(['event_id' => $ensemble->event_id]);
|
||||
foreach ($auditions as $audition) {
|
||||
SeatingLimit::create([
|
||||
'ensemble_id' => $ensemble->id, 'audition_id' => $audition->id,
|
||||
'maximum_accepted' => fake()->numberBetween(1, 10),
|
||||
]);
|
||||
}
|
||||
// Act & Assert
|
||||
expect($ensemble->seatingLimits)->toHaveCount(3);
|
||||
});
|
||||
|
||||
it('has seats', function () {
|
||||
// Arrange
|
||||
$ensemble = Ensemble::factory()->create();
|
||||
$audition = Audition::factory()->create(['event_id' => $ensemble->event_id]);
|
||||
$entry = Entry::factory()->create(['audition_id' => $audition->id]);
|
||||
$seat = Seat::create([
|
||||
'ensemble_id' => $ensemble->id,
|
||||
'audition_id' => $audition->id,
|
||||
'seat' => 1,
|
||||
'entry_id' => $entry->id,
|
||||
]);
|
||||
// Act & Assert
|
||||
expect($ensemble->seats)->toHaveCount(1)
|
||||
->and($ensemble->seats->first()->seat)->toBe(1);
|
||||
|
||||
});
|
||||
|
||||
it('returns only ensembles for a given audition in the audition scope', function () {
|
||||
// Arrange
|
||||
$audition = Audition::factory()->create();
|
||||
$ensemble = Ensemble::factory()->create(['event_id' => $audition->event_id]);
|
||||
$ensemble2 = Ensemble::factory()->create(['event_id' => $audition->event_id]);
|
||||
$ensemble3 = Ensemble::factory()->create();
|
||||
// Act & Assert
|
||||
expect(Ensemble::forAudition($audition->id)->get())->toHaveCount(2);
|
||||
});
|
||||
|
||||
it('returns only ensembles for a given event in the event scope', function () {
|
||||
// Arrange
|
||||
$event = Event::factory()->create();
|
||||
$ensemble = Ensemble::factory()->create(['event_id' => $event->id]);
|
||||
$ensemble2 = Ensemble::factory()->create(['event_id' => $event->id]);
|
||||
$ensemble3 = Ensemble::factory()->create();
|
||||
// Act & Assert
|
||||
expect(Ensemble::forEvent($event->id)->get())->toHaveCount(2);
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Entry;
|
||||
use App\Models\EntryFlag;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('has an entry', function () {
|
||||
$entry = Entry::factory()->create();
|
||||
$entryFlag = EntryFlag::create(['entry_id' => $entry->id, 'flag_name' => 'declined']);
|
||||
|
||||
// Act & Assert
|
||||
expect($entryFlag->entry->id)->toBe($entry->id)
|
||||
->and($entryFlag->entry)->toBeInstanceOf(Entry::class);
|
||||
});
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Audition;
|
||||
use App\Models\Ensemble;
|
||||
use App\Models\Entry;
|
||||
use App\Models\EntryFlag;
|
||||
use App\Models\JudgeAdvancementVote;
|
||||
use App\Models\School;
|
||||
use App\Models\ScoreSheet;
|
||||
use App\Models\Seat;
|
||||
use App\Models\Student;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('has a student', function () {
|
||||
// Arrange
|
||||
$student = Student::factory()->create();
|
||||
$entry = Entry::factory()->create(['student_id' => $student->id]);
|
||||
// Act and Assert
|
||||
expect($entry->student->first_name)->toBe($student->first_name)
|
||||
->and($entry->student)->toBeInstanceOf(Student::class);
|
||||
});
|
||||
|
||||
test('has an audition', function () {
|
||||
// Arrange
|
||||
$audition = Audition::factory()->create();
|
||||
$entry = Entry::factory()->create(['audition_id' => $audition->id]);
|
||||
// Act and Assert
|
||||
expect($entry->audition)->toBeInstanceOf(Audition::class)
|
||||
->and($entry->audition->name)->toBe($audition->name);
|
||||
|
||||
});
|
||||
|
||||
test('has a school', function () {
|
||||
// Arrange
|
||||
$student = Student::factory()->create();
|
||||
$school = $student->school;
|
||||
$entry = Entry::factory()->create(['student_id' => $student->id]);
|
||||
// Act and Assert
|
||||
expect($entry->school->name)->toBe($school->name)
|
||||
->and($entry->school)->toBeInstanceOf(School::class);
|
||||
});
|
||||
|
||||
test('has score sheets', function () {
|
||||
// Arrange
|
||||
$judge = User::factory()->create();
|
||||
$judge2 = User::factory()->create();
|
||||
$entry = Entry::factory()->create();
|
||||
$ss = ScoreSheet::create([
|
||||
'entry_id' => $entry->id,
|
||||
'user_id' => $judge->id,
|
||||
'subscores' => json_encode(['subscore1' => 10, 'subscore2' => 20]),
|
||||
]);
|
||||
$ss2 = ScoreSheet::create([
|
||||
'entry_id' => $entry->id,
|
||||
'user_id' => $judge2->id,
|
||||
'subscores' => json_encode(['subscore1' => 10, 'subscore2' => 20]),
|
||||
]);
|
||||
// Act and Assert
|
||||
expect($entry->scoreSheets->count())->toBe(2)
|
||||
->and($entry->scoreSheets->first())->toBeInstanceOf(ScoreSheet::class);
|
||||
});
|
||||
|
||||
test('has advancement votes', function () {
|
||||
$entry = Entry::factory()->create();
|
||||
$judge = User::factory()->create();
|
||||
$judge2 = User::factory()->create();
|
||||
JudgeAdvancementVote::create(['user_id' => $judge->id, 'entry_id' => $entry->id, 'vote' => 'yes']);
|
||||
JudgeAdvancementVote::create(['user_id' => $judge2->id, 'entry_id' => $entry->id, 'vote' => 'no']);
|
||||
// Act and Assert
|
||||
expect($entry->advancementVotes->count())->toBe(2)
|
||||
->and($entry->advancementVotes->first())->toBeInstanceOf(JudgeAdvancementVote::class);
|
||||
});
|
||||
|
||||
it('can have flags and can check for a specific flag', function () {
|
||||
// Arrange
|
||||
$entry = Entry::factory()->create();
|
||||
EntryFlag::create(['entry_id' => $entry->id, 'flag_name' => 'declined']);
|
||||
EntryFlag::create(['entry_id' => $entry->id, 'flag_name' => 'no-show']);
|
||||
// Act & Assert
|
||||
expect($entry->flags->count())->toBe(2)
|
||||
->and($entry->flags->first()->flag_name)->toBe('declined')
|
||||
->and($entry->hasFlag('declined'))->toBeTrue()
|
||||
->and($entry->hasFlag('random'))->toBeFalse();
|
||||
});
|
||||
|
||||
it('can set and remove a flag', function () {
|
||||
// Arrange
|
||||
$entry = Entry::factory()->create();
|
||||
// Act
|
||||
$entry->addFlag('Test Flag');
|
||||
$entry->addFlag('Second Flag');
|
||||
// Assert
|
||||
expect($entry->hasFlag('Test Flag'))->toBeTrue()
|
||||
->and($entry->hasFlag('Second Flag'))->toBeTrue()
|
||||
->and($entry->hasFlag('random'))->toBeFalse();
|
||||
$entry->removeFlag('Test Flag');
|
||||
expect($entry->hasFlag('Test Flag'))->toBeFalse()
|
||||
->and($entry->hasFlag('Second Flag'))->toBeTrue();
|
||||
});
|
||||
|
||||
it('always has a score sheet count available', function () {
|
||||
// Arrange
|
||||
// Arrange
|
||||
$judge = User::factory()->create();
|
||||
$judge2 = User::factory()->create();
|
||||
$entry = Entry::factory()->create();
|
||||
$ss = ScoreSheet::create([
|
||||
'entry_id' => $entry->id,
|
||||
'user_id' => $judge->id,
|
||||
'subscores' => json_encode(['subscore1' => 10, 'subscore2' => 20]),
|
||||
]);
|
||||
$ss2 = ScoreSheet::create([
|
||||
'entry_id' => $entry->id,
|
||||
'user_id' => $judge2->id,
|
||||
'subscores' => json_encode(['subscore1' => 10, 'subscore2' => 20]),
|
||||
]);
|
||||
// Act & Assert
|
||||
expect($entry->score_sheets_count)->toBe(2);
|
||||
});
|
||||
|
||||
it('has a seat', function () {
|
||||
// Arrange
|
||||
$entry = Entry::factory()->create();
|
||||
$ensemble = Ensemble::factory()->create();
|
||||
$seat = Seat::create([
|
||||
'ensemble_id' => $ensemble->id,
|
||||
'audition_id' => $entry->audition_id,
|
||||
'seat' => fake()->numberBetween(1, 15),
|
||||
'entry_id' => $entry->id,
|
||||
]);
|
||||
// Act & Assert
|
||||
expect($entry->seat->seat)->toBe($seat->seat)
|
||||
->and($entry->seat->ensemble_id)->toBe($ensemble->id)
|
||||
->and($entry->seat->audition_id)->toBe($entry->audition_id)
|
||||
->and($entry->seat)->toBeInstanceOf(Seat::class);
|
||||
|
||||
});
|
||||
|
||||
it('has a forSeating scope that only returns those entries entered for seating', function () {
|
||||
// Arrange
|
||||
$noSeatStudent = Student::factory()->create(['first_name' => 'Advance Only']);
|
||||
$noAdvanceStudent = Student::factory()->create(['first_name' => 'Seating Only']);
|
||||
Entry::factory()->create(['student_id' => $noSeatStudent->id, 'for_seating' => false, 'for_advancement' => true]);
|
||||
Entry::factory()->create([
|
||||
'student_id' => $noAdvanceStudent->id, 'for_seating' => true,
|
||||
'for_advancement' => false,
|
||||
]);
|
||||
Entry::factory()->count(10)->create(['for_seating' => true, 'for_advancement' => true]);
|
||||
Entry::factory()->count(5)->create(['for_seating' => false, 'for_advancement' => true]);
|
||||
// Act & Assert
|
||||
expect(Entry::forSeating()->count())->toBe(11)
|
||||
->and(Entry::forSeating()->get()->first())->toBeInstanceOf(Entry::class)
|
||||
->and(Entry::forSeating()->get()->first()->student->first_name)->toBe('Seating Only');
|
||||
});
|
||||
|
||||
it('has a forAdvancement scope that only returns those entries entered for advancement', function () {
|
||||
// Arrange
|
||||
$noSeatStudent = Student::factory()->create(['first_name' => 'Advance Only']);
|
||||
$noAdvanceStudent = Student::factory()->create(['first_name' => 'Seating Only']);
|
||||
Entry::factory()->create(['student_id' => $noSeatStudent->id, 'for_seating' => false, 'for_advancement' => true]);
|
||||
Entry::factory()->create([
|
||||
'student_id' => $noAdvanceStudent->id, 'for_seating' => true,
|
||||
'for_advancement' => false,
|
||||
]);
|
||||
Entry::factory()->count(10)->create(['for_seating' => true, 'for_advancement' => true]);
|
||||
Entry::factory()->count(5)->create(['for_seating' => false, 'for_advancement' => true]);
|
||||
// Act & Assert
|
||||
expect(Entry::forAdvancement()->count())->toBe(16)
|
||||
->and(Entry::forAdvancement()->get()->first())->toBeInstanceOf(Entry::class)
|
||||
->and(Entry::forAdvancement()->get()->first()->student->first_name)->toBe('Advance Only');
|
||||
});
|
||||
|
||||
it('has an available scope that returns only auditions without a flag that would prevent seating', function () {
|
||||
Entry::factory()->count(10)->create();
|
||||
Entry::factory()->create()->addFlag('declined');
|
||||
Entry::factory()->create()->addFlag('no-show');
|
||||
Entry::factory()->create()->addFlag('failed-prelim');
|
||||
// Act & Assert
|
||||
expect(Entry::all()->count())->toBe(13)
|
||||
->and(Entry::available()->count())->toBe(10)
|
||||
->and(Entry::available()->get()->first())->toBeInstanceOf(Entry::class)
|
||||
->and(Entry::available()->get()->first()->flags->count())->toBe(0);
|
||||
});
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Entry;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('only returns entries for seating with forSeating scope', function () {
|
||||
// Arrange
|
||||
Entry::factory()->advanceOnly()->create();
|
||||
$seatingEntry = Entry::factory()->create();
|
||||
|
||||
// Act & Assert
|
||||
expect(Entry::forSeating()->get())
|
||||
->toHaveCount(1)
|
||||
->first()->id->toEqual($seatingEntry->id);
|
||||
});
|
||||
|
||||
it('only returns entries for advancement with for forAdvancement scope', function () {
|
||||
// Arrange
|
||||
Entry::factory()->seatingOnly()->create();
|
||||
$advancementEntry = Entry::factory()->create();
|
||||
|
||||
// Act & Assert
|
||||
expect(Entry::forAdvancement()->get())
|
||||
->toHaveCount(1)
|
||||
->first()->id->toEqual($advancementEntry->id);
|
||||
});
|
||||
|
||||
it('only returns entries that do not have a declined, no-show, or failed-prelim flag with available scope',
|
||||
function () {
|
||||
// Arrange
|
||||
$availableEntry = Entry::factory()->create();
|
||||
$declinedEntry = Entry::factory()->create();
|
||||
$noShowEntry = Entry::factory()->create();
|
||||
$failedPrelimEntry = Entry::factory()->create();
|
||||
$declinedEntry->addFlag('declined');
|
||||
$noShowEntry->addFlag('no-show');
|
||||
$failedPrelimEntry->addFlag('failed-prelim');
|
||||
|
||||
// Act & Assert
|
||||
expect(Entry::available()->get())
|
||||
->toHaveCount(1)
|
||||
->first()->id->toEqual($availableEntry->id);
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Audition;
|
||||
use App\Models\Ensemble;
|
||||
use App\Models\Event;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('has auditions', function () {
|
||||
$event = Event::factory()->create();
|
||||
$ddAudition = Audition::factory()->create(['event_id' => $event->id, 'name' => 'Digereedoo']);
|
||||
Audition::factory()->count(7)->create(['event_id' => $event->id]);
|
||||
|
||||
expect($event->auditions->count())->toBe(8)
|
||||
->and($event->auditions->first()->name)->toBe('Digereedoo');
|
||||
});
|
||||
|
||||
it('has ensembles', function () {
|
||||
// Arrange
|
||||
$event = Event::factory()->create();
|
||||
$ensemble = Ensemble::factory()->create(['event_id' => $event->id, 'name' => 'Symphonic Concert Wind Band']);
|
||||
Ensemble::factory()->count(7)->create();
|
||||
// Act & Assert
|
||||
expect($event->ensembles->count())->toBe(1)
|
||||
->and($event->ensembles->first()->name)->toBe('Symphonic Concert Wind Band');
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Entry;
|
||||
use App\Models\JudgeAdvancementVote;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->judge = User::factory()->create();
|
||||
$this->entry = Entry::factory()->create();
|
||||
$this->vote = JudgeAdvancementVote::create([
|
||||
'user_id' => $this->judge->id,
|
||||
'entry_id' => $this->entry->id,
|
||||
'vote' => 'pass',
|
||||
]);
|
||||
});
|
||||
|
||||
test('has a judge', function () {
|
||||
expect($this->vote->judge)->toBeInstanceOf(User::class)
|
||||
->and($this->vote->judge->first_name)->toBe($this->judge->first_name);
|
||||
});
|
||||
|
||||
test('has an entry', function () {
|
||||
expect($this->vote->entry)->toBeInstanceOf(Entry::class)
|
||||
->and($this->vote->entry->student->first_name)->toBe($this->entry->student->first_name);
|
||||
});
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Audition;
|
||||
use App\Models\Entry;
|
||||
use App\Models\Room;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->room = Room::factory()->create();
|
||||
$otherRoom = Room::factory()->create();
|
||||
$auditions = Audition::factory()->count(3)->create(['room_id' => $this->room->id]);
|
||||
foreach ($auditions as $audition) {
|
||||
Entry::factory()->count(5)->create(['audition_id' => $audition->id]);
|
||||
}
|
||||
$otherAuditions = Audition::factory()->count(3)->create(['room_id' => $otherRoom->id]);
|
||||
foreach ($otherAuditions as $audition) {
|
||||
Entry::factory()->count(5)->create(['audition_id' => $audition->id]);
|
||||
}
|
||||
});
|
||||
|
||||
test('created 30 entries in prep', function () {
|
||||
expect(Entry::all()->count())->toBe(30);
|
||||
});
|
||||
|
||||
it('has auditions', function () {
|
||||
expect($this->room->auditions->count())->toBe(3)
|
||||
->and($this->room->auditions->first())->toBeInstanceOf(Audition::class);
|
||||
});
|
||||
|
||||
it('has entries', function () {
|
||||
expect($this->room->entries->count())->toBe(15)
|
||||
->and($this->room->entries->first())->toBeInstanceOf(Entry::class);
|
||||
});
|
||||
|
||||
it('has users', function () {
|
||||
$user = User::factory()->create();
|
||||
$this->room->users()->attach($user->id);
|
||||
expect($this->room->users->count())->toBe(1)
|
||||
->and($this->room->users->first()->first_name)->toBe($user->first_name);
|
||||
});
|
||||
|
||||
it('has judges', function () {
|
||||
$user = User::factory()->create();
|
||||
$this->room->judges()->attach($user->id);
|
||||
expect($this->room->judges->count())->toBe(1)
|
||||
->and($this->room->judges->first()->first_name)->toBe($user->first_name);
|
||||
});
|
||||
|
||||
it('can add a judge', function () {
|
||||
$user = User::factory()->create();
|
||||
$this->room->addJudge($user->id);
|
||||
expect($this->room->judges->count())->toBe(1)
|
||||
->and($this->room->judges->first()->first_name)->toBe($user->first_name);
|
||||
});
|
||||
|
||||
it('can remove a judge', function () {
|
||||
// Arrange
|
||||
$user = User::factory()->create();
|
||||
$this->room->addJudge($user->id);
|
||||
// Act & Assert
|
||||
expect($this->room->judges->count())->toBe(1)
|
||||
->and($this->room->judges->first()->first_name)->toBe($user->first_name);
|
||||
// Re Act
|
||||
$this->room->removeJudge($user->id);
|
||||
// Reassert
|
||||
expect($this->room->judges->count())->toBe(0);
|
||||
});
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Room;
|
||||
use App\Models\RoomUser;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->user = User::factory()->create();
|
||||
$this->room = Room::factory()->create();
|
||||
$this->roomUser = RoomUser::create(['user_id' => $this->user->id, 'room_id' => $this->room->id]);
|
||||
});
|
||||
|
||||
it('has a user', function () {
|
||||
expect($this->roomUser->user->first_name)->toBe($this->user->first_name);
|
||||
});
|
||||
|
||||
it('has a judge', function () {
|
||||
expect($this->roomUser->judge->first_name)->toBe($this->user->first_name);
|
||||
});
|
||||
|
||||
it('has a room', function () {
|
||||
expect($this->roomUser->room->name)->toBe($this->room->name);
|
||||
});
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
use App\Models\School;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('has a school', function () {
|
||||
$school = School::factory()->create();
|
||||
$schoolEmailDomain = $school->emailDomains()->create([
|
||||
'domain' => 'example.com',
|
||||
]);
|
||||
expect($schoolEmailDomain->school->id)->toBe($school->id);
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue