From 6eb549260c96a9530894827fbe625adf814432be Mon Sep 17 00:00:00 2001 From: Laura Tonning Date: Mon, 2 Sep 2024 21:42:01 +0200 Subject: [PATCH] WIP --- composer.json | 6 +- ..._115206_add_description_to_plays_table.php | 21 +++ .../2024_08_25_115806_create_genres_table.php | 21 +++ ...25_115951_create_genre_monologue_table.php | 22 +++ ...4_08_25_185539_create_identities_table.php | 21 +++ ...190039_create_identity_monologue_table.php | 22 +++ .../2024_08_25_190152_create_ages_table.php | 21 +++ ...8_25_190239_create_age_monologue_table.php | 22 +++ ...08_25_194221_create_play_sources_table.php | 21 +++ ..._194321_create_play_play_sources_table.php | 23 +++ ..._203607_create_gender_identities_table.php | 21 +++ ...create_gender_identity_monologue_table.php | 22 +++ ...205442_migrate_play_and_monologue_data.php | 88 ++++++++++ public/css/monologues-backend.css | 92 +++++++--- public/css/monologues.css | 92 +++++++--- public/mix-manifest.json | 4 +- .../components/ctas/book-session.blade.php | 10 +- resources/views/layouts/monologues.blade.php | 21 ++- .../models/monologues/backend/form.blade.php | 62 +++---- .../models/monologues/backend/index.blade.php | 6 + .../monologues/frontend/index.blade.php | 38 ++-- .../models/monologues/frontend/show.blade.php | 165 ++++++++++++++---- .../views/models/plays/backend/form.blade.php | 52 +++--- .../models/plays/frontend/index.blade.php | 14 +- .../models/plays/frontend/show.blade.php | 42 ++++- src/Enums/CharacterSex.php | 9 + src/Enums/MonologueLength.php | 45 +++++ src/Http/Livewire/Monologues/Backend/Form.php | 42 ++++- .../Livewire/Monologues/Backend/Index.php | 26 ++- .../Livewire/Monologues/Frontend/Index.php | 61 ++++--- .../Livewire/Monologues/Frontend/Show.php | 12 +- src/Http/Livewire/Plays/Backend/Form.php | 34 ++++ src/Http/Livewire/Plays/Frontend/Index.php | 29 ++- src/Http/Livewire/Plays/Frontend/Show.php | 8 + src/Models/Age.php | 16 ++ src/Models/GenderIdentity.php | 16 ++ src/Models/Genre.php | 16 ++ src/Models/Identity.php | 16 ++ src/Models/Monologue.php | 75 +++++++- src/Models/MonologueUser.php | 2 +- src/Models/Play.php | 11 ++ src/Models/PlaySource.php | 16 ++ 42 files changed, 1129 insertions(+), 234 deletions(-) create mode 100644 database/migrations/2024_08_25_115206_add_description_to_plays_table.php create mode 100644 database/migrations/2024_08_25_115806_create_genres_table.php create mode 100644 database/migrations/2024_08_25_115951_create_genre_monologue_table.php create mode 100644 database/migrations/2024_08_25_185539_create_identities_table.php create mode 100644 database/migrations/2024_08_25_190039_create_identity_monologue_table.php create mode 100644 database/migrations/2024_08_25_190152_create_ages_table.php create mode 100644 database/migrations/2024_08_25_190239_create_age_monologue_table.php create mode 100644 database/migrations/2024_08_25_194221_create_play_sources_table.php create mode 100644 database/migrations/2024_08_25_194321_create_play_play_sources_table.php create mode 100644 database/migrations/2024_08_25_203607_create_gender_identities_table.php create mode 100644 database/migrations/2024_08_25_203707_create_gender_identity_monologue_table.php create mode 100644 database/migrations/2024_08_25_205442_migrate_play_and_monologue_data.php create mode 100644 src/Enums/MonologueLength.php create mode 100644 src/Models/Age.php create mode 100644 src/Models/GenderIdentity.php create mode 100644 src/Models/Genre.php create mode 100644 src/Models/Identity.php create mode 100644 src/Models/PlaySource.php diff --git a/composer.json b/composer.json index 287a9f8..ec44887 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,10 @@ } ], "repositories": [ + { + "type": "path", + "url": "/users/Tonning/Code/packages/astrogoat/strata" + }, { "type": "composer", "url": "https://packages.hlx.dev" @@ -25,7 +29,7 @@ "require": { "php": "^8.3", "astrogoat/cashier": "^0.3.0", - "astrogoat/strata": "^0.7.7", + "astrogoat/strata": "dev-update-index-filtering as 0.7.39", "illuminate/contracts": "^10.0", "spatie/laravel-package-tools": "^1.4.3" }, diff --git a/database/migrations/2024_08_25_115206_add_description_to_plays_table.php b/database/migrations/2024_08_25_115206_add_description_to_plays_table.php new file mode 100644 index 0000000..8e5df1f --- /dev/null +++ b/database/migrations/2024_08_25_115206_add_description_to_plays_table.php @@ -0,0 +1,21 @@ +string('description')->after('published_year'); + }); + } + + public function down(): void + { + Schema::table('plays', function (Blueprint $table) { + $table->dropColumn('description'); + }); + } +}; diff --git a/database/migrations/2024_08_25_115806_create_genres_table.php b/database/migrations/2024_08_25_115806_create_genres_table.php new file mode 100644 index 0000000..9dbc0f8 --- /dev/null +++ b/database/migrations/2024_08_25_115806_create_genres_table.php @@ -0,0 +1,21 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('genres'); + } +}; diff --git a/database/migrations/2024_08_25_115951_create_genre_monologue_table.php b/database/migrations/2024_08_25_115951_create_genre_monologue_table.php new file mode 100644 index 0000000..615b470 --- /dev/null +++ b/database/migrations/2024_08_25_115951_create_genre_monologue_table.php @@ -0,0 +1,22 @@ +foreignIdFor(Genre::class)->constrained(); + $table->foreignIdFor(Monologue::class)->constrained(); + }); + } + + public function down(): void + { + Schema::dropIfExists('genre_monologue'); + } +}; diff --git a/database/migrations/2024_08_25_185539_create_identities_table.php b/database/migrations/2024_08_25_185539_create_identities_table.php new file mode 100644 index 0000000..865712d --- /dev/null +++ b/database/migrations/2024_08_25_185539_create_identities_table.php @@ -0,0 +1,21 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('identities'); + } +}; diff --git a/database/migrations/2024_08_25_190039_create_identity_monologue_table.php b/database/migrations/2024_08_25_190039_create_identity_monologue_table.php new file mode 100644 index 0000000..bb3bd76 --- /dev/null +++ b/database/migrations/2024_08_25_190039_create_identity_monologue_table.php @@ -0,0 +1,22 @@ +foreignIdFor(Identity::class)->constrained(); + $table->foreignIdFor(Monologue::class)->constrained(); + }); + } + + public function down(): void + { + Schema::dropIfExists('identity_monologue'); + } +}; diff --git a/database/migrations/2024_08_25_190152_create_ages_table.php b/database/migrations/2024_08_25_190152_create_ages_table.php new file mode 100644 index 0000000..9c03f10 --- /dev/null +++ b/database/migrations/2024_08_25_190152_create_ages_table.php @@ -0,0 +1,21 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('ages'); + } +}; diff --git a/database/migrations/2024_08_25_190239_create_age_monologue_table.php b/database/migrations/2024_08_25_190239_create_age_monologue_table.php new file mode 100644 index 0000000..13a4e26 --- /dev/null +++ b/database/migrations/2024_08_25_190239_create_age_monologue_table.php @@ -0,0 +1,22 @@ +foreignIdFor(Age::class)->constrained(); + $table->foreignIdFor(Monologue::class)->constrained(); + }); + } + + public function down(): void + { + Schema::dropIfExists('age_monologue'); + } +}; diff --git a/database/migrations/2024_08_25_194221_create_play_sources_table.php b/database/migrations/2024_08_25_194221_create_play_sources_table.php new file mode 100644 index 0000000..a2b3f10 --- /dev/null +++ b/database/migrations/2024_08_25_194221_create_play_sources_table.php @@ -0,0 +1,21 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('play_sources'); + } +}; diff --git a/database/migrations/2024_08_25_194321_create_play_play_sources_table.php b/database/migrations/2024_08_25_194321_create_play_play_sources_table.php new file mode 100644 index 0000000..fc8504f --- /dev/null +++ b/database/migrations/2024_08_25_194321_create_play_play_sources_table.php @@ -0,0 +1,23 @@ +foreignIdFor(Play::class)->constrained(); + $table->foreignIdFor(PlaySource::class)->constrained(); + $table->string('url')->nullable(); + }); + } + + public function down(): void + { + Schema::dropIfExists('play_play_source'); + } +}; diff --git a/database/migrations/2024_08_25_203607_create_gender_identities_table.php b/database/migrations/2024_08_25_203607_create_gender_identities_table.php new file mode 100644 index 0000000..349d8a5 --- /dev/null +++ b/database/migrations/2024_08_25_203607_create_gender_identities_table.php @@ -0,0 +1,21 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('gender_identities'); + } +}; diff --git a/database/migrations/2024_08_25_203707_create_gender_identity_monologue_table.php b/database/migrations/2024_08_25_203707_create_gender_identity_monologue_table.php new file mode 100644 index 0000000..dac5978 --- /dev/null +++ b/database/migrations/2024_08_25_203707_create_gender_identity_monologue_table.php @@ -0,0 +1,22 @@ +foreignIdFor(GenderIdentity::class)->constrained(); + $table->foreignIdFor(Monologue::class)->constrained(); + }); + } + + public function down(): void + { + Schema::dropIfExists('gender_identity_monologue'); + } +}; diff --git a/database/migrations/2024_08_25_205442_migrate_play_and_monologue_data.php b/database/migrations/2024_08_25_205442_migrate_play_and_monologue_data.php new file mode 100644 index 0000000..c392d54 --- /dev/null +++ b/database/migrations/2024_08_25_205442_migrate_play_and_monologue_data.php @@ -0,0 +1,88 @@ +get() as $monologue) { + $this->convertSexToGenderIdentity($monologue); + $this->convertIdentities($monologue); + $this->convertAges($monologue); + } + + foreach (Play::all() as $play) { + $this->convertWhereToFindToSource($play); + $this->convertPlayTypeToMonologueGenre($play); + } + + Schema::table('plays', function (Blueprint $table) { + $table->dropColumn('where_to_find'); + $table->dropColumn('type'); + }); + + Schema::table('monologues', function (Blueprint $table) { + $table->dropColumn('sex'); + $table->dropColumn('identity'); + $table->dropColumn('type'); + }); + } + + public function down(): void + { +// Schema::table('plays', function (Blueprint $table) { +// $table->string('where_to_find')->nullable(); +// }); + } + + public function convertSexToGenderIdentity(Monologue $monologue): void + { + $monologue->genderIdentities()->firstOrCreate(['name' => $monologue->sex->fullName()]); + } + + public function convertAges(Monologue $monologue): void + { + if ($monologue->age) { + $monologue->ages()->firstOrCreate(['name' => trim($monologue->age)]); + } + } + + public function convertIdentities(Monologue $monologue): void + { + $identities = Str::of($monologue->identity) + ->replace(',', ';') + ->explode(';') + ->filter() + ->map(fn ($identity) => trim($identity)) + ->filter(); + + foreach ($identities as $identity) { + $monologue->identities()->firstOrCreate(['name' => $identity]); + } + } + + public function convertWhereToFindToSource(Play $play): void + { + $sources = Str::of($play->where_to_find) + ->replace(',', ';') + ->explode(';') + ->filter() + ->map(fn ($source) => trim($source)) + ->filter(); + + foreach ($sources as $source) { + $play->playSources()->firstOrCreate(['name' => $source]); + } + } + + public function convertPlayTypeToMonologueGenre(Play $play): void + { + foreach ($play->monologues()->withoutGlobalScopes()->get() as $monologue) { + $monologue->genres()->firstOrCreate(['name' => $play->type]); + } + } +}; diff --git a/public/css/monologues-backend.css b/public/css/monologues-backend.css index 26b175b..56c2b83 100644 --- a/public/css/monologues-backend.css +++ b/public/css/monologues-backend.css @@ -28,6 +28,8 @@ .monologues-z-10 { z-index: 10; } +.monologues-col-span-2 { grid-column: span 2 / span 2; } + .monologues-mx-auto { margin-left: auto; margin-right: auto; } .monologues--mr-2 { margin-right: -0.5rem; } @@ -54,6 +56,10 @@ .monologues-mt-6 { margin-top: 1.5rem; } +.monologues-ml-2 { margin-left: 0.5rem; } + +.monologues-ml-1 { margin-left: 0.25rem; } + .monologues-block { display: block; } .monologues-flex { display: flex; } @@ -68,6 +74,8 @@ .monologues-h-16 { height: 4rem; } +.monologues-h-5 { height: 1.25rem; } + .monologues-h-6 { height: 1.5rem; } .monologues-h-8 { height: 2rem; } @@ -78,9 +86,9 @@ .monologues-h-full { height: 100%; } -.monologues-h-5 { height: 1.25rem; } +.monologues-h-96 { height: 24rem; } -.monologues-h-4 { height: 1rem; } +.monologues-h-\[440px\] { height: 440px; } .monologues-min-h-full { min-height: 100%; } @@ -88,6 +96,8 @@ .monologues-w-48 { width: 12rem; } +.monologues-w-5 { width: 1.25rem; } + .monologues-w-6 { width: 1.5rem; } .monologues-w-8 { width: 2rem; } @@ -98,10 +108,12 @@ .monologues-w-auto { width: auto; } -.monologues-w-5 { width: 1.25rem; } +.monologues-w-full { width: 100%; } .monologues-w-4 { width: 1rem; } +.monologues-w-\[500px\] { width: 500px; } + .monologues-max-w-2xl { max-width: 42rem; } .monologues-max-w-7xl { max-width: 80rem; } @@ -114,6 +126,8 @@ .monologues-max-w-xs { max-width: 20rem; } +.monologues-flex-1 { flex: 1 1 0%; } + .monologues-flex-shrink-0 { flex-shrink: 0; } .monologues-origin-top-right { transform-origin: top right; } @@ -134,67 +148,89 @@ .monologues-grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } +.monologues-grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } + .monologues-flex-col { flex-direction: column; } .monologues-items-center { align-items: center; } +.monologues-justify-end { justify-content: flex-end; } + .monologues-justify-center { justify-content: center; } .monologues-justify-between { justify-content: space-between; } .monologues-gap-3 { gap: 0.75rem; } +.monologues-gap-4 { gap: 1rem; } + .monologues-gap-x-6 { -moz-column-gap: 1.5rem; column-gap: 1.5rem; } .monologues-space-y-1 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); } +.-monologues-space-y-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(-0.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(-0.5rem * var(--tw-space-y-reverse)); } + +.monologues-space-y-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); } + +.monologues-space-y-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(1rem * var(--tw-space-y-reverse)); } + +.-monologues-space-y-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(-1rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(-1rem * var(--tw-space-y-reverse)); } + +.monologues-space-y-3 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); } + +.monologues-space-x-3 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(0.75rem * var(--tw-space-x-reverse)); margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); } + +.monologues-space-x-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(1rem * var(--tw-space-x-reverse)); margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); } + .monologues-self-end { align-self: flex-end; } +.monologues-justify-self-end { justify-self: end; } + .monologues-overflow-hidden { overflow: hidden; } +.monologues-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + +.monologues-whitespace-normal { white-space: normal; } + .monologues-rounded-full { border-radius: 9999px; } .monologues-rounded-md { border-radius: 0.375rem; } +.monologues-rounded-3xl { border-radius: 1.5rem; } + .monologues-border-b { border-bottom-width: 1px; } +.monologues-border-b-2 { border-bottom-width: 2px; } + .monologues-border-l-4 { border-left-width: 4px; } .monologues-border-t { border-top-width: 1px; } -.monologues-border-b-2 { border-bottom-width: 2px; } - .monologues-border-gray-200 { --tw-border-opacity: 1; border-color: rgb(229 231 235 / var(--tw-border-opacity)); } .monologues-border-indigo-500 { --tw-border-opacity: 1; border-color: rgb(99 102 241 / var(--tw-border-opacity)); } .monologues-border-transparent { border-color: transparent; } +.monologues-bg-gray-100 { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } + +.monologues-bg-gray-200 { --tw-bg-opacity: 1; background-color: rgb(229 231 235 / var(--tw-bg-opacity)); } + .monologues-bg-gray-50 { --tw-bg-opacity: 1; background-color: rgb(249 250 251 / var(--tw-bg-opacity)); } .monologues-bg-gray-900 { --tw-bg-opacity: 1; background-color: rgb(17 24 39 / var(--tw-bg-opacity)); } -.monologues-bg-indigo-50 { --tw-bg-opacity: 1; background-color: rgb(238 242 255 / var(--tw-bg-opacity)); } - .monologues-bg-white { --tw-bg-opacity: 1; background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } .monologues-bg-white\/5 { background-color: rgb(255 255 255 / 0.05); } -.monologues-bg-gray-400 { --tw-bg-opacity: 1; background-color: rgb(156 163 175 / var(--tw-bg-opacity)); } - -.monologues-bg-gray-200 { --tw-bg-opacity: 1; background-color: rgb(229 231 235 / var(--tw-bg-opacity)); } - -.monologues-bg-fuchsia-600 { --tw-bg-opacity: 1; background-color: rgb(192 38 211 / var(--tw-bg-opacity)); } - -.monologues-bg-gray-600 { --tw-bg-opacity: 1; background-color: rgb(75 85 99 / var(--tw-bg-opacity)); } - -.monologues-bg-gray-100 { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } +.monologues-object-cover { -o-object-fit: cover; object-fit: cover; } .monologues-p-1 { padding: 0.25rem; } .monologues-p-2 { padding: 0.5rem; } -.monologues-p-4 { padding: 1rem; } +.monologues-px-1 { padding-left: 0.25rem; padding-right: 0.25rem; } .monologues-px-3 { padding-left: 0.75rem; padding-right: 0.75rem; } @@ -216,22 +252,20 @@ .monologues-py-8 { padding-top: 2rem; padding-bottom: 2rem; } -.monologues-px-1 { padding-left: 0.25rem; padding-right: 0.25rem; } - .monologues-pb-3 { padding-bottom: 0.75rem; } .monologues-pl-3 { padding-left: 0.75rem; } .monologues-pr-4 { padding-right: 1rem; } +.monologues-pt-1 { padding-top: 0.25rem; } + .monologues-pt-16 { padding-top: 4rem; } .monologues-pt-2 { padding-top: 0.5rem; } .monologues-pt-4 { padding-top: 1rem; } -.monologues-pt-1 { padding-top: 0.25rem; } - .monologues-text-center { text-align: center; } .monologues-text-right { text-align: right; } @@ -246,12 +280,16 @@ .monologues-text-xs { font-size: 0.75rem; line-height: 1rem; } +.monologues-text-xl { font-size: 1.25rem; line-height: 1.75rem; } + .monologues-font-bold { font-weight: 700; } .monologues-font-medium { font-weight: 500; } .monologues-font-semibold { font-weight: 600; } +.monologues-font-light { font-weight: 300; } + .monologues-uppercase { text-transform: uppercase; } .monologues-leading-6 { line-height: 1.5rem; } @@ -262,6 +300,8 @@ .monologues-tracking-wide { letter-spacing: 0.025em; } +.monologues-tracking-wider { letter-spacing: 0.05em; } + .monologues-text-gray-300 { --tw-text-opacity: 1; color: rgb(209 213 219 / var(--tw-text-opacity)); } .monologues-text-gray-400 { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } @@ -276,8 +316,6 @@ .monologues-text-gray-900 { --tw-text-opacity: 1; color: rgb(17 24 39 / var(--tw-text-opacity)); } -.monologues-text-indigo-700 { --tw-text-opacity: 1; color: rgb(67 56 202 / var(--tw-text-opacity)); } - .monologues-text-white { --tw-text-opacity: 1; color: rgb(255 255 255 / var(--tw-text-opacity)); } .monologues-underline { text-decoration-line: underline; } @@ -324,10 +362,10 @@ .hover\:monologues-text-gray-500:hover { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } -.hover\:monologues-text-gray-800:hover { --tw-text-opacity: 1; color: rgb(31 41 55 / var(--tw-text-opacity)); } - .hover\:monologues-text-gray-700:hover { --tw-text-opacity: 1; color: rgb(55 65 81 / var(--tw-text-opacity)); } +.hover\:monologues-text-gray-800:hover { --tw-text-opacity: 1; color: rgb(31 41 55 / var(--tw-text-opacity)); } + .focus\:monologues-outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; } .focus\:monologues-ring-2:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } @@ -356,8 +394,12 @@ .sm\:monologues-flex { display: flex; } + .sm\:monologues-grid { display: grid; } + .sm\:monologues-hidden { display: none; } + .sm\:monologues-grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } + .sm\:monologues-items-center { align-items: center; } .sm\:monologues-space-x-8 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(2rem * var(--tw-space-x-reverse)); margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); } diff --git a/public/css/monologues.css b/public/css/monologues.css index 26b175b..56c2b83 100644 --- a/public/css/monologues.css +++ b/public/css/monologues.css @@ -28,6 +28,8 @@ .monologues-z-10 { z-index: 10; } +.monologues-col-span-2 { grid-column: span 2 / span 2; } + .monologues-mx-auto { margin-left: auto; margin-right: auto; } .monologues--mr-2 { margin-right: -0.5rem; } @@ -54,6 +56,10 @@ .monologues-mt-6 { margin-top: 1.5rem; } +.monologues-ml-2 { margin-left: 0.5rem; } + +.monologues-ml-1 { margin-left: 0.25rem; } + .monologues-block { display: block; } .monologues-flex { display: flex; } @@ -68,6 +74,8 @@ .monologues-h-16 { height: 4rem; } +.monologues-h-5 { height: 1.25rem; } + .monologues-h-6 { height: 1.5rem; } .monologues-h-8 { height: 2rem; } @@ -78,9 +86,9 @@ .monologues-h-full { height: 100%; } -.monologues-h-5 { height: 1.25rem; } +.monologues-h-96 { height: 24rem; } -.monologues-h-4 { height: 1rem; } +.monologues-h-\[440px\] { height: 440px; } .monologues-min-h-full { min-height: 100%; } @@ -88,6 +96,8 @@ .monologues-w-48 { width: 12rem; } +.monologues-w-5 { width: 1.25rem; } + .monologues-w-6 { width: 1.5rem; } .monologues-w-8 { width: 2rem; } @@ -98,10 +108,12 @@ .monologues-w-auto { width: auto; } -.monologues-w-5 { width: 1.25rem; } +.monologues-w-full { width: 100%; } .monologues-w-4 { width: 1rem; } +.monologues-w-\[500px\] { width: 500px; } + .monologues-max-w-2xl { max-width: 42rem; } .monologues-max-w-7xl { max-width: 80rem; } @@ -114,6 +126,8 @@ .monologues-max-w-xs { max-width: 20rem; } +.monologues-flex-1 { flex: 1 1 0%; } + .monologues-flex-shrink-0 { flex-shrink: 0; } .monologues-origin-top-right { transform-origin: top right; } @@ -134,67 +148,89 @@ .monologues-grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } +.monologues-grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } + .monologues-flex-col { flex-direction: column; } .monologues-items-center { align-items: center; } +.monologues-justify-end { justify-content: flex-end; } + .monologues-justify-center { justify-content: center; } .monologues-justify-between { justify-content: space-between; } .monologues-gap-3 { gap: 0.75rem; } +.monologues-gap-4 { gap: 1rem; } + .monologues-gap-x-6 { -moz-column-gap: 1.5rem; column-gap: 1.5rem; } .monologues-space-y-1 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); } +.-monologues-space-y-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(-0.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(-0.5rem * var(--tw-space-y-reverse)); } + +.monologues-space-y-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); } + +.monologues-space-y-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(1rem * var(--tw-space-y-reverse)); } + +.-monologues-space-y-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(-1rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(-1rem * var(--tw-space-y-reverse)); } + +.monologues-space-y-3 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); } + +.monologues-space-x-3 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(0.75rem * var(--tw-space-x-reverse)); margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); } + +.monologues-space-x-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(1rem * var(--tw-space-x-reverse)); margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); } + .monologues-self-end { align-self: flex-end; } +.monologues-justify-self-end { justify-self: end; } + .monologues-overflow-hidden { overflow: hidden; } +.monologues-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + +.monologues-whitespace-normal { white-space: normal; } + .monologues-rounded-full { border-radius: 9999px; } .monologues-rounded-md { border-radius: 0.375rem; } +.monologues-rounded-3xl { border-radius: 1.5rem; } + .monologues-border-b { border-bottom-width: 1px; } +.monologues-border-b-2 { border-bottom-width: 2px; } + .monologues-border-l-4 { border-left-width: 4px; } .monologues-border-t { border-top-width: 1px; } -.monologues-border-b-2 { border-bottom-width: 2px; } - .monologues-border-gray-200 { --tw-border-opacity: 1; border-color: rgb(229 231 235 / var(--tw-border-opacity)); } .monologues-border-indigo-500 { --tw-border-opacity: 1; border-color: rgb(99 102 241 / var(--tw-border-opacity)); } .monologues-border-transparent { border-color: transparent; } +.monologues-bg-gray-100 { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } + +.monologues-bg-gray-200 { --tw-bg-opacity: 1; background-color: rgb(229 231 235 / var(--tw-bg-opacity)); } + .monologues-bg-gray-50 { --tw-bg-opacity: 1; background-color: rgb(249 250 251 / var(--tw-bg-opacity)); } .monologues-bg-gray-900 { --tw-bg-opacity: 1; background-color: rgb(17 24 39 / var(--tw-bg-opacity)); } -.monologues-bg-indigo-50 { --tw-bg-opacity: 1; background-color: rgb(238 242 255 / var(--tw-bg-opacity)); } - .monologues-bg-white { --tw-bg-opacity: 1; background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } .monologues-bg-white\/5 { background-color: rgb(255 255 255 / 0.05); } -.monologues-bg-gray-400 { --tw-bg-opacity: 1; background-color: rgb(156 163 175 / var(--tw-bg-opacity)); } - -.monologues-bg-gray-200 { --tw-bg-opacity: 1; background-color: rgb(229 231 235 / var(--tw-bg-opacity)); } - -.monologues-bg-fuchsia-600 { --tw-bg-opacity: 1; background-color: rgb(192 38 211 / var(--tw-bg-opacity)); } - -.monologues-bg-gray-600 { --tw-bg-opacity: 1; background-color: rgb(75 85 99 / var(--tw-bg-opacity)); } - -.monologues-bg-gray-100 { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } +.monologues-object-cover { -o-object-fit: cover; object-fit: cover; } .monologues-p-1 { padding: 0.25rem; } .monologues-p-2 { padding: 0.5rem; } -.monologues-p-4 { padding: 1rem; } +.monologues-px-1 { padding-left: 0.25rem; padding-right: 0.25rem; } .monologues-px-3 { padding-left: 0.75rem; padding-right: 0.75rem; } @@ -216,22 +252,20 @@ .monologues-py-8 { padding-top: 2rem; padding-bottom: 2rem; } -.monologues-px-1 { padding-left: 0.25rem; padding-right: 0.25rem; } - .monologues-pb-3 { padding-bottom: 0.75rem; } .monologues-pl-3 { padding-left: 0.75rem; } .monologues-pr-4 { padding-right: 1rem; } +.monologues-pt-1 { padding-top: 0.25rem; } + .monologues-pt-16 { padding-top: 4rem; } .monologues-pt-2 { padding-top: 0.5rem; } .monologues-pt-4 { padding-top: 1rem; } -.monologues-pt-1 { padding-top: 0.25rem; } - .monologues-text-center { text-align: center; } .monologues-text-right { text-align: right; } @@ -246,12 +280,16 @@ .monologues-text-xs { font-size: 0.75rem; line-height: 1rem; } +.monologues-text-xl { font-size: 1.25rem; line-height: 1.75rem; } + .monologues-font-bold { font-weight: 700; } .monologues-font-medium { font-weight: 500; } .monologues-font-semibold { font-weight: 600; } +.monologues-font-light { font-weight: 300; } + .monologues-uppercase { text-transform: uppercase; } .monologues-leading-6 { line-height: 1.5rem; } @@ -262,6 +300,8 @@ .monologues-tracking-wide { letter-spacing: 0.025em; } +.monologues-tracking-wider { letter-spacing: 0.05em; } + .monologues-text-gray-300 { --tw-text-opacity: 1; color: rgb(209 213 219 / var(--tw-text-opacity)); } .monologues-text-gray-400 { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } @@ -276,8 +316,6 @@ .monologues-text-gray-900 { --tw-text-opacity: 1; color: rgb(17 24 39 / var(--tw-text-opacity)); } -.monologues-text-indigo-700 { --tw-text-opacity: 1; color: rgb(67 56 202 / var(--tw-text-opacity)); } - .monologues-text-white { --tw-text-opacity: 1; color: rgb(255 255 255 / var(--tw-text-opacity)); } .monologues-underline { text-decoration-line: underline; } @@ -324,10 +362,10 @@ .hover\:monologues-text-gray-500:hover { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } -.hover\:monologues-text-gray-800:hover { --tw-text-opacity: 1; color: rgb(31 41 55 / var(--tw-text-opacity)); } - .hover\:monologues-text-gray-700:hover { --tw-text-opacity: 1; color: rgb(55 65 81 / var(--tw-text-opacity)); } +.hover\:monologues-text-gray-800:hover { --tw-text-opacity: 1; color: rgb(31 41 55 / var(--tw-text-opacity)); } + .focus\:monologues-outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; } .focus\:monologues-ring-2:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } @@ -356,8 +394,12 @@ .sm\:monologues-flex { display: flex; } + .sm\:monologues-grid { display: grid; } + .sm\:monologues-hidden { display: none; } + .sm\:monologues-grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } + .sm\:monologues-items-center { align-items: center; } .sm\:monologues-space-x-8 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(2rem * var(--tw-space-x-reverse)); margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); } diff --git a/public/mix-manifest.json b/public/mix-manifest.json index af98b21..40017b0 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,4 +1,4 @@ { - "/css/monologues-backend.css": "/css/monologues-backend.css?id=854071e040bb420a0f419c80d522b771", - "/css/monologues.css": "/css/monologues.css?id=854071e040bb420a0f419c80d522b771" + "/css/monologues-backend.css": "/css/monologues-backend.css?id=cda586acfe2a14bfc930253829a535a0", + "/css/monologues.css": "/css/monologues.css?id=cda586acfe2a14bfc930253829a535a0" } diff --git a/resources/views/components/ctas/book-session.blade.php b/resources/views/components/ctas/book-session.blade.php index 576d438..0e7c397 100644 --- a/resources/views/components/ctas/book-session.blade.php +++ b/resources/views/components/ctas/book-session.blade.php @@ -1,5 +1,5 @@
-
+

Boost your monologue.
Make strong choices.

Book a session with PK to boost you monologue performance to stand out with casting directors.

- App screenshot +
+ App screenshot +
diff --git a/resources/views/layouts/monologues.blade.php b/resources/views/layouts/monologues.blade.php index 02c0c5a..fcbcf60 100644 --- a/resources/views/layouts/monologues.blade.php +++ b/resources/views/layouts/monologues.blade.php @@ -41,12 +41,21 @@ class="monologues-border-b monologues-border-gray-200 monologues-bg-white"
-{{--
--}} -{{-- Your Company--}} -{{-- Your Company--}} -{{--
--}} +
+ Monologue Database + + + + + + + + + + + + +
-
+
- - - @foreach(CharacterSex::cases() as $sex) - - @endforeach - - - - - - -
- -
by {{ $model->play->playwright }}
- @if($model->play->published_year) -
Published in {{ $model->play->published_year }}
- @endif -
{{ $model->play->type }}
-
- Edit Play -
+ +
+ +
by {{ $model->play->playwright }}
+ @if($model->play->published_year) +
Published in {{ $model->play->published_year }}
+ @endif +
{{ $model->play->type }}
+ - +
+
+ + + @foreach($this->syncableRelationships() as $relationship) + + @endforeach diff --git a/resources/views/models/monologues/backend/index.blade.php b/resources/views/models/monologues/backend/index.blade.php index a773579..146781d 100644 --- a/resources/views/models/monologues/backend/index.blade.php +++ b/resources/views/models/monologues/backend/index.blade.php @@ -44,6 +44,12 @@ @endif + @if($this->shouldShowColumn('genre')) + + {{ $monologue->genres()->pluck('name')->implode(',') }} + + @endif + @if($this->shouldShowColumn('published_year')) {{ $monologue->play->published_year }} diff --git a/resources/views/models/monologues/frontend/index.blade.php b/resources/views/models/monologues/frontend/index.blade.php index 5b0cb8e..532bef5 100644 --- a/resources/views/models/monologues/frontend/index.blade.php +++ b/resources/views/models/monologues/frontend/index.blade.php @@ -2,20 +2,20 @@ @include('lego::models._includes.indexes.filters') @include('lego::models._includes.indexes.headers') - View + View @include('lego::models._includes.indexes.header-filters') - @foreach($models->loadMissing('play') as $monologue) + @forelse($models->loadMissing('play') as $monologue) @if($this->shouldShowColumn('play_id')) @@ -35,21 +35,33 @@ @endif - @if($this->shouldShowColumn('sex')) + @if($this->shouldShowColumn('gender_identities')) - {{ $monologue->sex }} + @foreach($monologue->genderIdentities as $gender) + + {{ $gender->name }} + + @endforeach @endif - @if($this->shouldShowColumn('age')) + @if($this->shouldShowColumn('ages')) - {{ $monologue->age }} + @foreach($monologue->ages as $age) + + {{ $age->name }} + + @endforeach @endif - @if($this->shouldShowColumn('identity')) + @if($this->shouldShowColumn('identities')) - {{ $monologue->identity }} + @foreach($monologue->identities as $identity) + + {{ $identity->name }} + + @endforeach @endif @@ -58,7 +70,13 @@ - @endforeach + @empty + + +
No results found
+
+
+ @endforelse @include('lego::models._includes.indexes.pagination') diff --git a/resources/views/models/monologues/frontend/show.blade.php b/resources/views/models/monologues/frontend/show.blade.php index 9223b58..b9cceff 100644 --- a/resources/views/models/monologues/frontend/show.blade.php +++ b/resources/views/models/monologues/frontend/show.blade.php @@ -1,14 +1,24 @@ @php use Illuminate\Support\Str; @endphp - + + + + {{ $monologue->play->title }} + + + + by {{ $monologue->play->playwright }} {{ $monologue->play->published_year ? ' (' . $monologue->play->published_year . ')' : '' }} + @foreach($monologue->genres as $genre) + + {{ $genre->name }} + + @endforeach + {{-- --}} {{-- --}} {{-- --}} - + Book session with PK--}} {{--
--}} - - - - {{ $monologue->character }} - +
+
+ @if($monologue->description) + + {!! nl2br($monologue->description) !!} + + @endif + + @if($monologue->play->description) + + {!! nl2br($monologue->play->description) !!} + + @endif + +
+ + + +
+ {!! nl2br($monologue->excerptsFirstLine) !!} +
+
+
+ + +
+ {!! nl2br($monologue->excerptsLastLine) !!} +
+
+
+
+
+ + @hasanyrole(['admin', 'editor', 'manager']) + + {!! nl2br($monologue->text) !!} + + @endhasanyrole +
- - {{ $monologue->sex }} - +
+ + - - {{ $monologue->identity }} - + + + @foreach($monologue->genderIdentities as $genderIdentity) + name}"]) }}"> + + {{ $genderIdentity->name }} + + + @endforeach + + - - {{ $monologue->age }} - + + + @foreach($monologue->identities as $identity) + name}"]) }}"> + + {{ $identity->name }} + + + @endforeach + + - - {{ $monologue->type }} - + + + @foreach($monologue->ages as $age) + name}"]) }}"> + + {{ $age->name }} + + + @endforeach + + + - - "{{ Str::finish($monologue->excerpt, '...') }}" - + + @foreach($monologue->play->playSources as $source) + + + {{ $source->name }} + - - {{ $monologue->play->where_to_find }} - + @if($source->pivot->url) + +
+
Link
+
+
+ + + + @endif +
+ @endforeach +
- - {{ $monologue->created_at->diffForHumans() }} ({{ $monologue->created_at->toFormattedDateString() }}) - - - + + + + {{ $monologue->length()->value }} + + +
+
+
+
+{{-- {{ $monologue->length()->value }} length.--}} + {{ $monologue->wordCount }} words + {{ $monologue->characterCount }} characters +
+
+
+
diff --git a/resources/views/models/plays/backend/form.blade.php b/resources/views/models/plays/backend/form.blade.php index 4499b77..5fe8f61 100644 --- a/resources/views/models/plays/backend/form.blade.php +++ b/resources/views/models/plays/backend/form.blade.php @@ -1,7 +1,8 @@ @php use Helix\Fabrick\Icon; use Illuminate\Support\Str; - use Astrogoat\Monologues\Enums\TheatricalType; + use Astrogoat\Monologues\Models\Genre; + use Astrogoat\Monologues\Models\PlaySource;use Astrogoat\Monologues\Enums\TheatricalType; use Helix\Lego\Enums\AppAsset; @endphp @@ -31,13 +32,13 @@ class="{{ $this->modelSupportsSoftDeletes() && $model->trashed() ? 'sh-line-thro @if($this->modelSupportsSoftDeletes() && $model->trashed()) - This product has be archived + This play has be archived @endif -
+
-
-
{{ $year }} @endforeach +
+ - - - @foreach(TheatricalType::cases() as $type) - - @endforeach - - - + +
+ @foreach($this->syncableRelationships['playSources'] as $sourceId) + @php($source = PlaySource::find($sourceId)) +
+
{{ $source->name }}
+ +
+ @endforeach
@@ -87,7 +88,8 @@ class="{{ $this->modelSupportsSoftDeletes() && $model->trashed() ? 'sh-line-thro @if($model->exists) - View All + View + All @@ -120,6 +122,12 @@ class="{{ $this->modelSupportsSoftDeletes() && $model->trashed() ? 'sh-line-thro {{ $this->model->monologues()->paginate(15)->links() }} + @foreach($this->syncableRelationships() as $relationship) + + @endforeach + @include('lego::models._includes.indexes.filters') @@ -44,9 +40,13 @@ @endif - @if($this->shouldShowColumn('type')) + @if($this->shouldShowColumn('genre')) - {{ $play->type }} + @foreach($this->getGenres($play) as $genre) + + {{ $genre }} + + @endforeach @endif diff --git a/resources/views/models/plays/frontend/show.blade.php b/resources/views/models/plays/frontend/show.blade.php index 08fbd9e..a1b4b41 100644 --- a/resources/views/models/plays/frontend/show.blade.php +++ b/resources/views/models/plays/frontend/show.blade.php @@ -1,13 +1,22 @@ -
- {{ $play->title }} + + + by {{ $play->playwright }} {{ $play->published_year ? ' (' . $play->published_year . ')' : '' }} + @foreach($this->getGenres() as $genre) + + {{ $genre }} + + @endforeach + Character - Excerpt - + First line + Gender + Age + Identity @foreach($play->monologues()->paginate(15) as $monologue) @@ -15,7 +24,28 @@ {{ $monologue->character }} - {{ Str::limit($monologue->excerpt, 60) }} + {{ Str::limit($monologue->excerptsFirstLine, 40) }} + + + @foreach($monologue->genderIdentities as $gender) + + {{ $gender->name }} + + @endforeach + + + @foreach($monologue->ages as $age) + + {{ $age->name }} + + @endforeach + + + @foreach($monologue->identities as $identity) + + {{ $identity->name }} + + @endforeach @@ -27,4 +57,4 @@ {{ $play->monologues()->paginate(15)->links() }} -
+ diff --git a/src/Enums/CharacterSex.php b/src/Enums/CharacterSex.php index 3628fc7..01b8549 100644 --- a/src/Enums/CharacterSex.php +++ b/src/Enums/CharacterSex.php @@ -2,8 +2,17 @@ namespace Astrogoat\Monologues\Enums; +/** @deprecated */ enum CharacterSex: string { case M = 'M'; case F = 'F'; + + public function fullName() + { + return match ($this) { + self::M => 'Male', + self::F => 'Female', + }; + } } diff --git a/src/Enums/MonologueLength.php b/src/Enums/MonologueLength.php new file mode 100644 index 0000000..d13e29c --- /dev/null +++ b/src/Enums/MonologueLength.php @@ -0,0 +1,45 @@ +wordCount; + + if ($wordCount <= 200) { + return MonologueLength::SHORT; + } elseif ($wordCount <= 400) { + return MonologueLength::MEDIUM; + } else { + return MonologueLength::LONG; + } + } + + public function progressBarWidth(): int + { + return match ($this) { + self::SHORT => 33, + self::MEDIUM => 66, + self::LONG => 100, + + }; + } + + public function color(): string + { + return match ($this) { + self::SHORT => 'blue', + self::MEDIUM => 'indigo', + self::LONG => 'purple', + + }; + } +} diff --git a/src/Http/Livewire/Monologues/Backend/Form.php b/src/Http/Livewire/Monologues/Backend/Form.php index 3affec4..9a746e4 100644 --- a/src/Http/Livewire/Monologues/Backend/Form.php +++ b/src/Http/Livewire/Monologues/Backend/Form.php @@ -2,15 +2,23 @@ namespace Astrogoat\Monologues\Http\Livewire\Monologues\Backend; -use Astrogoat\Monologues\Enums\CharacterSex; -use Astrogoat\Monologues\Models\Monologue; -use Astrogoat\Monologues\Models\Play; -use Helix\Lego\Http\Livewire\Models\Form as BaseForm; use Illuminate\Support\Str; use Illuminate\Validation\Rule; +use Astrogoat\Monologues\Models\Play; +use Astrogoat\Monologues\Models\Genre; +use Astrogoat\Monologues\Models\Monologue; +use Astrogoat\Monologues\Enums\CharacterSex; +use Helix\Lego\Services\SyncableRelationship; +use Astrogoat\Monologues\Models\Age; +use Astrogoat\Monologues\Models\Identity; +use Helix\Lego\Http\Livewire\Models\Form as BaseForm; +use Helix\Lego\Http\Livewire\Traits\SyncsRelationships; +use Astrogoat\Monologues\Models\GenderIdentity; class Form extends BaseForm { + use SyncsRelationships; + public Play $play; protected bool $canBeDeleted = true; @@ -61,10 +69,10 @@ public function model(): string public function displayTitle(int $limit = 50): string { $title = match (true) { - filled($this->model->excerpt) => $this->model->excerpt, + filled($this->model->excerpt) => Str::of($this->model->excerpt)->remove('[First line]')->prepend($this->model->character . ': '), filled($this->model->description) => $this->model->description, filled($this->model->text) => $this->model->text, - default => '[ ... ]', + default => '[Untitled]', }; return Str::limit($title, $limit); @@ -75,6 +83,28 @@ public function redirectAfterDeletionRoute(): string return route('lego.monologues.plays.edit', $this->play); } + public function syncableRelationships(): array + { + return [ + SyncableRelationship::relationship(Genre::class) + ->name('genres') + ->inverseRelationshipName('monologues') + ->labelProperty('name'), + SyncableRelationship::relationship(GenderIdentity::class) + ->name('genderIdentities') + ->labelProperty('name') + ->inverseRelationshipName('monologues'), + SyncableRelationship::relationship(Age::class) + ->name('ages') + ->labelProperty('name') + ->inverseRelationshipName('monologues'), + SyncableRelationship::relationship(Identity::class) + ->name('identities') + ->labelProperty('name') + ->inverseRelationshipName('monologues'), + ]; + } + public function view(): string { return 'monologues::models.monologues.backend.form'; diff --git a/src/Http/Livewire/Monologues/Backend/Index.php b/src/Http/Livewire/Monologues/Backend/Index.php index 1af132a..13b3589 100644 --- a/src/Http/Livewire/Monologues/Backend/Index.php +++ b/src/Http/Livewire/Monologues/Backend/Index.php @@ -2,12 +2,17 @@ namespace Astrogoat\Monologues\Http\Livewire\Monologues\Backend; +use Astrogoat\Monologues\Models\Genre; use Astrogoat\Monologues\Models\Monologue; use Helix\Lego\Http\Livewire\Models\Index as BaseIndex; use Illuminate\Database\Eloquent\Builder; class Index extends BaseIndex { + public array $casts = [ + 'genre' => 'array', + ]; + public function model(): string { return Monologue::class; @@ -20,6 +25,7 @@ public function columns(): array 'character' => 'Character', 'excerpt' => 'Excerpt', 'playwright' => 'Playwright', + 'genre' => 'Genre', 'published_year' => 'Year', 'deleted_at' => 'Archived', ]; @@ -30,13 +36,29 @@ public function mainSearchColumn(): string|false return 'play_id'; } - public function scopePlayId(Builder $query, $value) + public function genreFilterOptions(): array { - return $query->whereHas('play', function (Builder $builder) use ($value) { + return Genre::all()->pluck('name', 'name')->toArray(); + } + + public function scopePlayId(Builder $query, $value): void + { + $query->whereHas('play', function (Builder $builder) use ($value) { $builder->where('title', 'like', "{$value}%"); }); } + public function scopeGenre(Builder $query, $values): void + { + if (in_array('All', $values)) { + return; + } + + $query->whereHas('genres', function (Builder $builder) use ($values) { + $builder->whereIn('name', $values); + }); + } + public function render() { return view('monologues::models.monologues.backend.index', [ diff --git a/src/Http/Livewire/Monologues/Frontend/Index.php b/src/Http/Livewire/Monologues/Frontend/Index.php index ad60cf6..ee9135f 100644 --- a/src/Http/Livewire/Monologues/Frontend/Index.php +++ b/src/Http/Livewire/Monologues/Frontend/Index.php @@ -2,8 +2,12 @@ namespace Astrogoat\Monologues\Http\Livewire\Monologues\Frontend; +use Illuminate\Support\Arr; +use Astrogoat\Monologues\Models\Age; +use Astrogoat\Monologues\Models\Identity; use Astrogoat\Monologues\Enums\CharacterSex; use Astrogoat\Monologues\Models\Monologue; +use Astrogoat\Monologues\Models\GenderIdentity; use Helix\Lego\Http\Livewire\Models\Index as BaseIndex; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; @@ -12,15 +16,13 @@ class Index extends BaseIndex { public array $casts = [ 'sex' => 'array', - 'age' => 'array', - 'identity' => 'array', + 'ages' => 'array', + 'gender_identities' => 'array', + 'identities' => 'array', ]; public array $sortableColumns = [ 'character' => 'Character', - 'sex' => 'Sex', - 'age' => 'Age', - 'identity' => 'Identity', ]; protected Collection $monologues; @@ -41,9 +43,9 @@ public function columns(): array 'play_id' => 'Play', 'playwright' => 'Playwright', 'character' => 'Character', - 'sex' => 'Sex', - 'age' => 'Age', - 'identity' => 'Identity', + 'gender_identities' => 'Gender', + 'ages' => 'Age', + 'identities' => 'Identity', ]; } @@ -66,29 +68,40 @@ public function scopePlaywright(Builder $query, $value) }); } - public function sexFilterOptions(): array + public function genderIdentitiesFilterOptions(): array { - return collect(CharacterSex::cases()) - ->mapWithKeys(fn (CharacterSex $sex) => [$sex->value => $sex->value]) - ->toArray(); + return GenderIdentity::query()->orderBy('name')->pluck('name', 'name')->toArray(); } - public function ageFilterOptions(): array + public function scopeGenderIdentities(Builder $query, $value): Builder { - return $this->monologues->pluck('age') - ->unique() - ->filter() - ->mapWithKeys(fn ($age) => [$age => $age]) - ->toArray(); + return $query->whereHas('genderIdentities', function (Builder $builder) use ($value) { + $builder->whereIn('name', explode(',', $value)); + }); + } + + public function identitiesFilterOptions(): array + { + return Identity::query()->orderBy('name')->pluck('name', 'name')->toArray(); + } + + public function scopeIdentities(Builder $query, $value): Builder + { + return $query->whereHas('identities', function (Builder $builder) use ($value) { + $builder->whereIn('name', explode(',', $value)); + }); + } + + public function agesFilterOptions(): array + { + return Age::query()->orderBy('name')->pluck('name', 'name')->toArray(); } - public function identityFilterOptions(): array + public function scopeAges(Builder $query, $value): Builder { - return $this->monologues->pluck('identity') - ->unique() - ->filter() - ->mapWithKeys(fn ($identity) => [$identity => $identity]) - ->toArray(); + return $query->whereHas('ages', function (Builder $builder) use ($value) { + $builder->whereIn('name', explode(',', $value)); + }); } public function render() diff --git a/src/Http/Livewire/Monologues/Frontend/Show.php b/src/Http/Livewire/Monologues/Frontend/Show.php index f70268e..18a3de8 100644 --- a/src/Http/Livewire/Monologues/Frontend/Show.php +++ b/src/Http/Livewire/Monologues/Frontend/Show.php @@ -46,7 +46,7 @@ public function previous() return; } - return $this->redirect(route('monologues.show', $previous)); + return $this->redirect(route('monologue-database.monologues.show', $previous)); } public function next() @@ -57,16 +57,12 @@ public function next() return; } - return $this->redirect(route('monologues.show', $next)); + return $this->redirect(route('monologue-database.monologues.show', $next)); } - // public function bookmark() - // { - // - // } - public function render() { - return view('monologues::models.monologues.frontend.show')->extends('monologues::layouts.monologues'); + return view('monologues::models.monologues.frontend.show') + ->extends('monologues::layouts.monologues'); } } diff --git a/src/Http/Livewire/Plays/Backend/Form.php b/src/Http/Livewire/Plays/Backend/Form.php index 0d7b2be..20e7159 100644 --- a/src/Http/Livewire/Plays/Backend/Form.php +++ b/src/Http/Livewire/Plays/Backend/Form.php @@ -3,14 +3,48 @@ namespace Astrogoat\Monologues\Http\Livewire\Plays\Backend; use Astrogoat\Monologues\Models\Play; +use Astrogoat\Monologues\Models\Genre; +use Astrogoat\Monologues\Models\PlaySource; +use Helix\Lego\Services\SyncableRelationship; use Helix\Lego\Http\Livewire\Models\Form as BaseForm; use Helix\Lego\Rules\SlugRule; +use Helix\Lego\Http\Livewire\Traits\SyncsRelationships; +use Helix\Lego\Http\Livewire\Traits\RequireConfirmation; +use Astrogoat\Monologues\Models\GenderIdentity; class Form extends BaseForm { + use RequireConfirmation; + use SyncsRelationships; + + public array $playSources = []; + public function mount($play = null) { $this->setModel($play); + + foreach ($this->model->playSources as $playSource) { + $this->playSources[$playSource->id] = $playSource->pivot->url; + } + } + + public function saving() + { + $data = collect($this->playSources)->mapWithKeys(function ($url, $sourceId) { + return [$sourceId => ['url' => $url]]; + })->toArray(); + + $this->model->playSources()->sync($data); + } + + public function syncableRelationships(): array + { + return [ + SyncableRelationship::relationship(PlaySource::class) + ->name('playSources') + ->inverseRelationshipName('plays') + ->labelProperty('name'), + ]; } public function rules(): array diff --git a/src/Http/Livewire/Plays/Frontend/Index.php b/src/Http/Livewire/Plays/Frontend/Index.php index d36e348..d18e34f 100644 --- a/src/Http/Livewire/Plays/Frontend/Index.php +++ b/src/Http/Livewire/Plays/Frontend/Index.php @@ -2,14 +2,17 @@ namespace Astrogoat\Monologues\Http\Livewire\Plays\Frontend; -use Astrogoat\Monologues\Enums\TheatricalType; +use Astrogoat\Monologues\Models\Genre; +use Illuminate\Database\Eloquent\Builder; +use Astrogoat\Monologues\Models\Monologue; use Astrogoat\Monologues\Models\Play; use Helix\Lego\Http\Livewire\Models\Index as BaseIndex; class Index extends BaseIndex { public array $casts = [ - 'type' => 'array', + 'genre' => 'array', + 'monologues_count' => 'int', ]; public function model(): string @@ -24,7 +27,7 @@ public function columns(): array 'playwright' => 'Playwright', 'published_year' => 'Year', 'monologues_count' => 'Monologues', - 'type' => 'Type', + 'genre' => 'Genre', ]; } @@ -33,11 +36,23 @@ public function mainSearchColumn(): string|false return 'title'; } - public function typeFilterOptions(): array + public function genreFilterOptions(): array { - return collect(TheatricalType::cases()) - ->mapWithKeys(fn (TheatricalType $case) => [$case->value => $case->value]) - ->toArray(); + return Genre::query()->orderBy('name')->pluck('name', 'name')->toArray(); + } + + public function scopeGenre(Builder $query, $value) + { + return $query->whereHas('monologues.genres', function (Builder $builder) use ($value) { + $builder->whereIn('name', explode(',', $value)); + }); + } + + public function getGenres(Play $play): array + { + return $play->monologues->map(function (Monologue $monologue) { + return $monologue->genres->pluck('name'); + })->flatten()->unique()->toArray(); } public function render() diff --git a/src/Http/Livewire/Plays/Frontend/Show.php b/src/Http/Livewire/Plays/Frontend/Show.php index 7361c23..98831f2 100644 --- a/src/Http/Livewire/Plays/Frontend/Show.php +++ b/src/Http/Livewire/Plays/Frontend/Show.php @@ -4,11 +4,19 @@ use Astrogoat\Monologues\Models\Play; use Livewire\Component; +use Astrogoat\Monologues\Models\Monologue; class Show extends Component { public Play $play; + public function getGenres(): array + { + return $this->play->monologues->map(function (Monologue $monologue) { + return $monologue->genres->pluck('name'); + })->flatten()->unique()->toArray(); + } + public function render() { return view('monologues::models.plays.frontend.show') diff --git a/src/Models/Age.php b/src/Models/Age.php new file mode 100644 index 0000000..89b19dc --- /dev/null +++ b/src/Models/Age.php @@ -0,0 +1,16 @@ +belongsToMany(Monologue::class); + } +} diff --git a/src/Models/GenderIdentity.php b/src/Models/GenderIdentity.php new file mode 100644 index 0000000..8ba5970 --- /dev/null +++ b/src/Models/GenderIdentity.php @@ -0,0 +1,16 @@ +belongsToMany(Monologue::class); + } +} diff --git a/src/Models/Genre.php b/src/Models/Genre.php new file mode 100644 index 0000000..1c4add7 --- /dev/null +++ b/src/Models/Genre.php @@ -0,0 +1,16 @@ +belongsToMany(Monologue::class); + } +} diff --git a/src/Models/Identity.php b/src/Models/Identity.php new file mode 100644 index 0000000..aa8ddca --- /dev/null +++ b/src/Models/Identity.php @@ -0,0 +1,16 @@ +belongsToMany(Monologue::class); + } +} diff --git a/src/Models/Monologue.php b/src/Models/Monologue.php index 495a43a..41bfb46 100644 --- a/src/Models/Monologue.php +++ b/src/Models/Monologue.php @@ -2,14 +2,17 @@ namespace Astrogoat\Monologues\Models; -use Astrogoat\Monologues\Enums\CharacterSex; -use Astrogoat\Monologues\Scopes\AccessScope; use Helix\Fabrick\Icon; -use Helix\Lego\Models\Model; use Helix\Lego\Models\User; -use Illuminate\Database\Eloquent\Attributes\ScopedBy; +use Illuminate\Support\Str; +use Helix\Lego\Models\Model; use Illuminate\Database\Eloquent\Builder; +use Astrogoat\Monologues\Enums\CharacterSex; +use Astrogoat\Monologues\Scopes\AccessScope; use Illuminate\Database\Eloquent\SoftDeletes; +use Astrogoat\Monologues\Enums\MonologueLength; +use Illuminate\Database\Eloquent\Attributes\ScopedBy; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; #[ScopedBy([AccessScope::class])] class Monologue extends Model @@ -32,14 +35,76 @@ public function play() return $this->belongsTo(Play::class); } + public function genres(): BelongsToMany + { + return $this->belongsToMany(Genre::class); + } + + public function identities(): BelongsToMany + { + return $this->belongsToMany(Identity::class); + } + + public function ages(): BelongsToMany + { + return $this->belongsToMany(Age::class); + } + + public function genderIdentities(): BelongsToMany + { + return $this->belongsToMany(GenderIdentity::class); + } + public function scopeForUser(Builder $query, User|MonologueUser $user) { if ($user instanceof User) { $user = MonologueUser::wrap($user); } - // dd($this, $this->created_at, $user->lastOrder); + if ($user->user->hasRole('admin')) { + return; + } + + if (! $user->lastOrder) { + $query->where('created_at', '>', now()->addDay()); // Trick to not show any monologues if they don't have an order. + + return; + } $query->where('created_at', '<', $user->lastOrder->created_at); } + + public function getExcerptsFirstLineAttribute() + { + return Str::of($this->excerpt) + ->replace(' lines]', ' line]') + ->before('[Last line]') + ->remove('[First line]') + ->trim() + ->toString(); + } + + public function getExcerptsLastLineAttribute() + { + return Str::of($this->excerpt) + ->replace(' lines]', ' line]') + ->after('[Last line] ') + ->trim() + ->toString(); + } + + public function getWordCountAttribute(): int + { + return str_word_count($this->text); + } + + public function getCharacterCountAttribute(): int + { + return Str::length($this->text); + } + + public function length(): MonologueLength + { + return MonologueLength::fromMonologue($this); + } } diff --git a/src/Models/MonologueUser.php b/src/Models/MonologueUser.php index f18e518..8dbbc87 100644 --- a/src/Models/MonologueUser.php +++ b/src/Models/MonologueUser.php @@ -13,7 +13,7 @@ class MonologueUser extends Model { protected $table = 'users'; - private User $user; + public User $user; public function getForeignKey(): string { diff --git a/src/Models/Play.php b/src/Models/Play.php index d4bde1a..3c52a7c 100644 --- a/src/Models/Play.php +++ b/src/Models/Play.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Spatie\Sluggable\HasSlug; use Spatie\Sluggable\SlugOptions; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Play extends Model { @@ -32,6 +33,16 @@ public function monologues(): HasMany return $this->hasMany(Monologue::class); } + public function playTypes(): BelongsToMany + { + return $this->belongsToMany(Genre::class); + } + + public function playSources(): BelongsToMany + { + return $this->belongsToMany(PlaySource::class)->withPivot('url'); + } + public static function icon(): string { return Icon::BOOK_OPEN; diff --git a/src/Models/PlaySource.php b/src/Models/PlaySource.php new file mode 100644 index 0000000..06e8e93 --- /dev/null +++ b/src/Models/PlaySource.php @@ -0,0 +1,16 @@ +belongsToMany(Play::class); + } +}