From: Daniel Karbach Date: Thu, 10 Jul 2025 12:18:40 +0000 (+0200) Subject: use event banners X-Git-Url: http://git.localhorst.tv/?a=commitdiff_plain;h=50963416d48c86c51bcee60cb843f142d0cb2f5e;p=alttp.git use event banners --- diff --git a/app/Http/Controllers/EventController.php b/app/Http/Controllers/EventController.php index 94db805..9d42b32 100644 --- a/app/Http/Controllers/EventController.php +++ b/app/Http/Controllers/EventController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use App\Models\Event; use Carbon\Carbon; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\Request; class EventController extends Controller @@ -68,4 +69,18 @@ class EventController extends Controller return $event->toJson(); } + public function web(Request $request, string $name) { + $event = Event::where('name', '=', $name)->first(); + if ($event) { + $view = view('app') + ->with('title', $event->getTranslatedTitle()) + ->with('description', $event->getTranslatedShort()); + if ($event->banner) { + $view = $view->with('image', url($event->banner)); + } + return $view; + } + throw new ModelNotFoundException(); + } + } diff --git a/app/Models/Event.php b/app/Models/Event.php index 331a384..8272f49 100644 --- a/app/Models/Event.php +++ b/app/Models/Event.php @@ -18,6 +18,20 @@ class Event extends Model return $this->hasMany(Episode::class); } + public function getTranslatedTitle(): string { + if ($this->description) { + return $this->description->getTranslatedProperty('title'); + } + return $this->title; + } + + public function getTranslatedShort(): string { + if ($this->description) { + return $this->description->getTranslatedProperty('short'); + } + return ''; + } + protected $casts = [ 'end' => 'datetime', 'start' => 'datetime', diff --git a/resources/js/components/episodes/Item.jsx b/resources/js/components/episodes/Item.jsx index 612c5ea..75f2c63 100644 --- a/resources/js/components/episodes/Item.jsx +++ b/resources/js/components/episodes/Item.jsx @@ -48,14 +48,14 @@ const Item = ({ episode, onAddRestream, onApply, onEditRestream }) => {
{episode.title || episode.event ? -
+

{episode.title || episode.event.title} -

+ : null} {episode.comment ? -
+

{episode.comment} -

+

: null}
diff --git a/resources/js/components/events/Detail.jsx b/resources/js/components/events/Detail.jsx index 6589548..d89bae1 100644 --- a/resources/js/components/events/Detail.jsx +++ b/resources/js/components/events/Detail.jsx @@ -30,6 +30,11 @@ const Detail = ({ actions, event }) => { : null}
+ {event.banner ? +
+
+
+ : null} {event.description ? : null} @@ -46,6 +51,7 @@ Detail.propTypes = { editContent: PropTypes.func, }), event: PropTypes.shape({ + banner: PropTypes.string, description: PropTypes.shape({ }), end: PropTypes.string, diff --git a/resources/js/components/events/Item.jsx b/resources/js/components/events/Item.jsx index 9217d56..0806454 100644 --- a/resources/js/components/events/Item.jsx +++ b/resources/js/components/events/Item.jsx @@ -45,19 +45,27 @@ const Item = ({ event }) => { : null}
: null} - {event.description? -
- -
- : null} +
+ {event.banner ? + +
+
+
+ + : null} + {event.description? + + : null} +
; }; Item.propTypes = { event: PropTypes.shape({ + banner: PropTypes.string, corner: PropTypes.string, description: PropTypes.shape({ }), diff --git a/resources/js/pages/Event.jsx b/resources/js/pages/Event.jsx index ef52e9f..ad2dd61 100644 --- a/resources/js/pages/Event.jsx +++ b/resources/js/pages/Event.jsx @@ -151,6 +151,10 @@ export const Component = () => { content={getTranslation(event.description, 'short', i18n.language)} /> : null} + {event.banner ? + + + : null} diff --git a/resources/js/pages/Front.jsx b/resources/js/pages/Front.jsx index f0485ed..a83b631 100644 --- a/resources/js/pages/Front.jsx +++ b/resources/js/pages/Front.jsx @@ -31,7 +31,7 @@ const Front = () => { - +
{t('front.circus')} diff --git a/resources/js/pages/Schedule.jsx b/resources/js/pages/Schedule.jsx index 2b6a623..98f321e 100644 --- a/resources/js/pages/Schedule.jsx +++ b/resources/js/pages/Schedule.jsx @@ -13,7 +13,7 @@ import ApplyDialog from '../components/episodes/ApplyDialog'; import Filter from '../components/episodes/Filter'; import List from '../components/episodes/List'; import RestreamDialog from '../components/episodes/RestreamDialog'; -import { invertEventFilter, toggleEventFilter } from '../helpers/Episode'; +import { invertEventFilter } from '../helpers/Episode'; import { useUser } from '../hooks/user'; export const Component = () => { @@ -138,8 +138,8 @@ export const Component = () => { setRestreamChannel(null); setRestreamEpisode(null); setShowRestreamDialog(false); - } catch (e) { - toastr.error(t('episodes.restreamDialog.removeError')); + } catch (error) { + toastr.error(t('episodes.restreamDialog.removeError', { error })); } }, []); @@ -170,8 +170,8 @@ export const Component = () => { ...newChannel, })); toastr.success(t('episodes.restreamDialog.editSuccess')); - } catch (e) { - toastr.error(t('episodes.restreamDialog.editError')); + } catch (error) { + toastr.error(t('episodes.restreamDialog.editError', { error })); } }, []); @@ -196,8 +196,8 @@ export const Component = () => { ...newChannel, })); toastr.success(t('episodes.restreamDialog.crewSuccess')); - } catch (e) { - toastr.error(t('episodes.restreamDialog.crewError')); + } catch (error) { + toastr.error(t('episodes.restreamDialog.crewError', { error })); } }, []); diff --git a/resources/sass/episodes.scss b/resources/sass/episodes.scss index 02d2a70..b76df22 100644 --- a/resources/sass/episodes.scss +++ b/resources/sass/episodes.scss @@ -17,6 +17,8 @@ background-size: 6rem auto; background-repeat: no-repeat; background-position: left bottom; + display: flex; + flex-direction: column; min-height: 8rem; &.is-active { @@ -27,6 +29,13 @@ .episode-start { width: 4rem; } + .episode-title { + font-weight: normal; + line-height: var(--bs-body-line-height); + } + .episode-comment { + margin-bottom: 0; + } @include media-breakpoint-up(md) { .episode-body { margin-left: 5rem; @@ -64,6 +73,7 @@ img { max-height: 3rem; + height: 3rem; width: auto; border-radius: 50%; margin: 0 0.5rem 0 0; @@ -79,6 +89,7 @@ img { max-height: 2rem; + height: 2rem; width: auto; border-radius: 50%; margin: 0 0.25rem 0 0; diff --git a/resources/sass/events.scss b/resources/sass/events.scss index 918e9bf..5cbade2 100644 --- a/resources/sass/events.scss +++ b/resources/sass/events.scss @@ -12,3 +12,21 @@ width: 10rem; } } + +.event-banner-container { + position: relative; + margin-bottom: 1.5em; + padding-top: 25%; + @include media-breakpoint-up(md) { + padding-top: 20%; + } +} +.event-banner { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-position: center center; + background-size: cover; +} diff --git a/routes/web.php b/routes/web.php index 2dcf298..57a0d1a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -20,23 +20,25 @@ use Jakyeru\Larascord\Http\Controllers\DiscordController; Route::get('/sitemap.xml', [SitemapXmlController::class, 'index']); -Route::get('/dungeons/{name}', function($name) { +Route::get('/events/{name}', 'App\Http\Controllers\EventController@web'); + +Route::get('/dungeons/{name}', function ($name) { return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'dungeon', 'name' => $name]); }); -Route::get('/locations/{name}', function($name) { +Route::get('/locations/{name}', function ($name) { return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'location', 'name' => $name]); }); -Route::get('/modes/{name}', function($name) { +Route::get('/modes/{name}', function ($name) { return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'mode', 'name' => $name]); }); -Route::get('/rulesets/{name}', function($name) { +Route::get('/rulesets/{name}', function ($name) { return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'ruleset', 'name' => $name]); }); -Route::get('/tech/{name}', function($name) { +Route::get('/tech/{name}', function ($name) { return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'tech', 'name' => $name]); });