From 750c9792be4c7972e4dbec8bea9e66ffc4dbd0c6 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Thu, 18 Dec 2025 13:56:58 -0600 Subject: [PATCH] Displayin etudes --- app/Actions/GetCurrentAuditionEtudeSet.php | 20 +++ .../{ => Admin}/AuditionEtudeController.php | 9 +- app/Http/Controllers/EtudesController.php | 28 +++ app/Http/Requests/EtudeUploadRequest.php | 2 +- app/Models/AuditionedEnsemble.php | 6 + app/Models/Instrument.php | 6 + app/Providers/AppServiceProvider.php | 2 + app/Services/AuditionEtudeService.php | 80 +++++++++ app/View/Components/Layout/App.php | 2 +- composer.json | 1 + composer.lock | 160 +++++++++++++++++- config/siteData.php | 26 ++- database/seeders/InstrumentSeeder.php | 5 + .../admin/audition_etude/create.blade.php | 40 ++++- resources/views/etudes.blade.php | 20 +++ routes/web.php | 4 +- 16 files changed, 394 insertions(+), 17 deletions(-) create mode 100644 app/Actions/GetCurrentAuditionEtudeSet.php rename app/Http/Controllers/{ => Admin}/AuditionEtudeController.php (90%) create mode 100644 app/Http/Controllers/EtudesController.php create mode 100644 app/Services/AuditionEtudeService.php create mode 100644 resources/views/etudes.blade.php diff --git a/app/Actions/GetCurrentAuditionEtudeSet.php b/app/Actions/GetCurrentAuditionEtudeSet.php new file mode 100644 index 0000000..d821480 --- /dev/null +++ b/app/Actions/GetCurrentAuditionEtudeSet.php @@ -0,0 +1,20 @@ +getCurrentSet(); + } + + public function getCurrentSet(?string $date = null): int + { + $date = $date ? Carbon::parse($date) : now(); + + return $date->month < 3 ? $date->year : $date->year + 1; + } +} diff --git a/app/Http/Controllers/AuditionEtudeController.php b/app/Http/Controllers/Admin/AuditionEtudeController.php similarity index 90% rename from app/Http/Controllers/AuditionEtudeController.php rename to app/Http/Controllers/Admin/AuditionEtudeController.php index 3bdb563..96dfe45 100644 --- a/app/Http/Controllers/AuditionEtudeController.php +++ b/app/Http/Controllers/Admin/AuditionEtudeController.php @@ -1,7 +1,8 @@ $fileSize, ]); + session([ + 'previous_instrument_id' => $request->instrument_id, + 'previous_auditioned_ensemble_id' => $request->auditioned_ensemble_id, + 'previous_set' => $request->set, + ]); + return redirect()->route('admin.etudes.index')->with('success', 'Etude uploaded successfully.'); } diff --git a/app/Http/Controllers/EtudesController.php b/app/Http/Controllers/EtudesController.php new file mode 100644 index 0000000..9ab8e37 --- /dev/null +++ b/app/Http/Controllers/EtudesController.php @@ -0,0 +1,28 @@ +withCount('etudes')->get(); + $schoolYear = $service->getActiveSchoolYear(); + $currentSet = []; + $etudes = []; + foreach ($ensembles as $ensemble) { + $thisSet = $service->getSetForEnsemble($ensemble); + $currentSet[$ensemble->id] = $thisSet; + $etudes[$ensemble->id] = $ensemble + ->etudes()->where('set', '=', $thisSet) + ->get()->keyBy('instrument_id'); + } + + return view('etudes', compact('ensembles', 'schoolYear', 'currentSet', 'instruments','etudes')); + } +} diff --git a/app/Http/Requests/EtudeUploadRequest.php b/app/Http/Requests/EtudeUploadRequest.php index 5df0f62..f3a916e 100644 --- a/app/Http/Requests/EtudeUploadRequest.php +++ b/app/Http/Requests/EtudeUploadRequest.php @@ -38,7 +38,7 @@ class EtudeUploadRequest extends FormRequest } }, ], - 'file_upload' => ['required', 'file', 'mimes:pdf', 'mimetypes:application/pdf', 'max:10240'], + 'file_upload' => ['required', 'file', 'mimes:pdf', 'mimetypes:application/pdf', 'max:51200'], ]; } } diff --git a/app/Models/AuditionedEnsemble.php b/app/Models/AuditionedEnsemble.php index 7a8d036..734a988 100644 --- a/app/Models/AuditionedEnsemble.php +++ b/app/Models/AuditionedEnsemble.php @@ -3,10 +3,16 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; class AuditionedEnsemble extends Model { protected $fillable = [ 'name', 'set_count', ]; + + public function etudes(): HasMany + { + return $this->hasMany(AuditionEtude::class); + } } diff --git a/app/Models/Instrument.php b/app/Models/Instrument.php index 48a9cb1..4e85cd9 100644 --- a/app/Models/Instrument.php +++ b/app/Models/Instrument.php @@ -3,10 +3,16 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; class Instrument extends Model { protected $fillable = [ 'instrument', 'score_order', ]; + + public function etudes(): HasMany + { + return $this->hasMany(AuditionEtude::class); + } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 85e8c63..3d55f57 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use App\Services\AuditionEtudeService; use App\Services\SiteDataService; use Illuminate\Support\ServiceProvider; @@ -13,6 +14,7 @@ class AppServiceProvider extends ServiceProvider public function register(): void { $this->app->singleton(SiteDataService::class); + $this->app->singleton(AuditionEtudeService::class); } /** diff --git a/app/Services/AuditionEtudeService.php b/app/Services/AuditionEtudeService.php new file mode 100644 index 0000000..acbfc10 --- /dev/null +++ b/app/Services/AuditionEtudeService.php @@ -0,0 +1,80 @@ +startYear = config('siteData.etude_start_year'); + $this->changeoverMonth = config('siteData.etude_changeover_month'); + } + + /** + * Get the audition year for a given date. + * + * The audition year follows a cycle based on the configured changeover month. + * Before the changeover month, returns the current calendar year. + * On or after the changeover month, returns the next calendar year. + * + * @param string|null $date Optional date string in 'YYYY-MM-DD' format. Defaults to the current date. + * @return int The audition year + * + * @example + * getCurrentAuditionYear('2024-01-15') // Returns 2024 (if changeover month is 3) + * getCurrentAuditionYear('2024-03-01') // Returns 2025 (if changeover month is 3) + * getCurrentAuditionYear() // Returns current audition year + */ + public function getCurrentAuditionYear(?string $date = null): int + { + $date = $date ? Carbon::parse($date) : now(); + + return $date->month < $this->changeoverMonth ? $date->year : $date->year + 1; + } + + /** + * Get the active school year as a string for a given date. + * + * @param string|null $date Optional date string in 'YYYY-MM-DD' format. Defaults to the current date. + * @return string The school year in "YYYY - YYYY" format + * + * @example + * getActiveSchoolYear('2024-01-15') // Returns "2023 - 2024" + * getActiveSchoolYear('2024-09-01') // Returns "2024 - 2025" + */ + public function getActiveSchoolYear(?string $date = null): string + { + $auditionYear = $this->getCurrentAuditionYear($date); + + return ($auditionYear - 1).' - '.$auditionYear; + } + + /** + * Get the current set number for an ensemble in a given year. + * + * Sets rotate annually based on the ensemble's set count. + * The rotation is calculated from the configured start year. + * + * @param AuditionedEnsemble $ensemble The ensemble to get the set for + * @param int|null $year Optional year. Defaults to current audition year. + * @return int The set number (1 to ensemble's set_count) + * + * @example + * getSetForEnsemble($ensemble, 2024) // Returns the set number for 2024 + */ + public function getSetForEnsemble(AuditionedEnsemble $ensemble, ?int $year = null): int + { + $year = $year ?? $this->getCurrentAuditionYear(); + $setCount = $ensemble->set_count; + $yearDiff = $year - $this->startYear; + + return ($yearDiff % $setCount) + 1; + } +} diff --git a/app/View/Components/Layout/App.php b/app/View/Components/Layout/App.php index 7cbe1bf..a97b9e9 100644 --- a/app/View/Components/Layout/App.php +++ b/app/View/Components/Layout/App.php @@ -30,7 +30,7 @@ class App extends Component ], [ 'name' => 'Audition Etudes', - 'link' => '#', + 'link' => route('etudes'), ], ]; } diff --git a/composer.json b/composer.json index c242131..a9eb71b 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "laravel/tinker": "^2.10.1" }, "require-dev": { + "barryvdh/laravel-debugbar": "^3.16", "fakerphp/faker": "^1.23", "laravel/boost": "^1.8", "laravel/pail": "^1.2.2", diff --git a/composer.lock b/composer.lock index c06f113..bb3329a 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "5157014187d3ae76a3586965840ec1f0", + "content-hash": "b97c7859ce60e3e2bd8fd47d5ed2f249", "packages": [ { "name": "bacon/bacon-qr-code", @@ -6445,6 +6445,91 @@ } ], "packages-dev": [ + { + "name": "barryvdh/laravel-debugbar", + "version": "v3.16.2", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-debugbar.git", + "reference": "730dbf8bf41f5691e026dd771e64dd54ad1b10b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/730dbf8bf41f5691e026dd771e64dd54ad1b10b3", + "reference": "730dbf8bf41f5691e026dd771e64dd54ad1b10b3", + "shasum": "" + }, + "require": { + "illuminate/routing": "^10|^11|^12", + "illuminate/session": "^10|^11|^12", + "illuminate/support": "^10|^11|^12", + "php": "^8.1", + "php-debugbar/php-debugbar": "^2.2.4", + "symfony/finder": "^6|^7" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "orchestra/testbench-dusk": "^7|^8|^9|^10", + "phpunit/phpunit": "^9.5.10|^10|^11", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Debugbar": "Barryvdh\\Debugbar\\Facades\\Debugbar" + }, + "providers": [ + "Barryvdh\\Debugbar\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "3.16-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Barryvdh\\Debugbar\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "PHP Debugbar integration for Laravel", + "keywords": [ + "debug", + "debugbar", + "dev", + "laravel", + "profiler", + "webprofiler" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-debugbar/issues", + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.16.2" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2025-12-03T14:52:46+00:00" + }, { "name": "brianium/paratest", "version": "v7.8.4", @@ -8059,6 +8144,79 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-debugbar/php-debugbar", + "version": "v2.2.4", + "source": { + "type": "git", + "url": "https://github.com/php-debugbar/php-debugbar.git", + "reference": "3146d04671f51f69ffec2a4207ac3bdcf13a9f35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/3146d04671f51f69ffec2a4207ac3bdcf13a9f35", + "reference": "3146d04671f51f69ffec2a4207ac3bdcf13a9f35", + "shasum": "" + }, + "require": { + "php": "^8", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^4|^5|^6|^7" + }, + "replace": { + "maximebf/debugbar": "self.version" + }, + "require-dev": { + "dbrekelmans/bdi": "^1", + "phpunit/phpunit": "^8|^9", + "symfony/panther": "^1|^2.1", + "twig/twig": "^1.38|^2.7|^3.0" + }, + "suggest": { + "kriswallsmith/assetic": "The best way to manage assets", + "monolog/monolog": "Log using Monolog", + "predis/predis": "Redis storage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "psr-4": { + "DebugBar\\": "src/DebugBar/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxime Bouroumeau-Fuseau", + "email": "maxime.bouroumeau@gmail.com", + "homepage": "http://maximebf.com" + }, + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Debug bar in the browser for php application", + "homepage": "https://github.com/php-debugbar/php-debugbar", + "keywords": [ + "debug", + "debug bar", + "debugbar", + "dev" + ], + "support": { + "issues": "https://github.com/php-debugbar/php-debugbar/issues", + "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.4" + }, + "time": "2025-07-22T14:01:30+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", diff --git a/config/siteData.php b/config/siteData.php index 709151f..5cf2191 100644 --- a/config/siteData.php +++ b/config/siteData.php @@ -2,15 +2,33 @@ return [ /* - - /* |-------------------------------------------------------------------------- - | Cache Data + | Etude Start Year |-------------------------------------------------------------------------- | - | Prefix and TTL for data cache keys + | A year in the past where all ensembles used set 1 | */ + 'etude_start_year' => env('ETUDE_START_YEAR', 2009), + + /* + |-------------------------------------------------------------------------- + | Etude Start Year + |-------------------------------------------------------------------------- + | + | A year in the past where all ensembles used set 1 + | + */ + 'etude_changeover_month' => env('ETUDE_CHANGEOVER_MONTH', 3), + + /* + |-------------------------------------------------------------------------- + | Cache Data + |-------------------------------------------------------------------------- + | + | Prefix and TTL for data cache keys + | + */ 'cache_key_prefix' => 'site_data_', 'cache_ttl' => env('SITE_DATA_CACHE_TTL', 86400), // seconds diff --git a/database/seeders/InstrumentSeeder.php b/database/seeders/InstrumentSeeder.php index bdde4c7..0d25ec4 100644 --- a/database/seeders/InstrumentSeeder.php +++ b/database/seeders/InstrumentSeeder.php @@ -34,7 +34,12 @@ class InstrumentSeeder extends Seeder ['instrument' => 'Euphonium TC', 'score_order' => 170], ['instrument' => 'Tuba', 'score_order' => 180], ['instrument' => 'Percussion', 'score_order' => 200], + ['instrument' => 'Drums', 'score_order' => 210], + ['instrument' => 'Vibes', 'score_order' => 220], ['instrument' => 'String Bass', 'score_order' => 300], + ['instrument' => 'Bass', 'score_order' => 400], + ['instrument' => 'Piano', 'score_order' => 410], + ['instrument' => 'Guitar', 'score_order' => 420], ]; Instrument::insert($defaultInstruments); diff --git a/resources/views/admin/audition_etude/create.blade.php b/resources/views/admin/audition_etude/create.blade.php index ef5c65f..d2c09d3 100644 --- a/resources/views/admin/audition_etude/create.blade.php +++ b/resources/views/admin/audition_etude/create.blade.php @@ -7,11 +7,14 @@
- +
-

There were {{ $errors->count() }} error(s) with your submission

+

There + were {{ $errors->count() }} error(s) with your submission

    @foreach($errors->all() as $error) @@ -24,13 +27,20 @@
@endif - +
Ensemble @foreach($ensembles as $ensemble) - + @endforeach
@@ -39,18 +49,31 @@ Instrument @foreach($instruments as $instrument) - + @endforeach
- +
- +
- Save Etude + Save + Etude +
@@ -65,6 +88,7 @@ }, @endforeach }; + function getSetCount(ensembleId) { // noinspection JSUnresolvedVariable return ensembles[ensembleId]?.setCount || ''; diff --git a/resources/views/etudes.blade.php b/resources/views/etudes.blade.php new file mode 100644 index 0000000..5f659e1 --- /dev/null +++ b/resources/views/etudes.blade.php @@ -0,0 +1,20 @@ + +
+ @foreach($ensembles as $ensemble) + + {{ $ensemble->name }}
{{ $schoolYear }}
Set {{ $currentSet[$ensemble->id] }}
+ +
+ @endforeach +
+
diff --git a/routes/web.php b/routes/web.php index 64ac3e6..bb98881 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,17 +1,19 @@ name('welcome'); Route::get('/audition-information', AuditionInformationPageController::class)->name('audition-information'); Route::get('/clinic-information', ClinicInformationPageController::class)->name('clinic-information'); +Route::get('/etudes', EtudesController::class)->name('etudes'); Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () { Route::get('/', DashboardController::class)->name('dashboard');