mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-app.git
synced 2025-12-13 23:56:47 +00:00
✨ Implement SeoTrait across components for improved SEO integration.
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
<?php
|
||||
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
new #[Layout('components.layouts.auth')]
|
||||
class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public string $password = '';
|
||||
|
||||
/**
|
||||
@@ -17,7 +21,7 @@ new #[Layout('components.layouts.auth')] class extends Component {
|
||||
'password' => ['required', 'string'],
|
||||
]);
|
||||
|
||||
if (! Auth::guard('web')->validate([
|
||||
if (!Auth::guard('web')->validate([
|
||||
'email' => Auth::user()->email,
|
||||
'password' => $this->password,
|
||||
])) {
|
||||
@@ -39,7 +43,7 @@ new #[Layout('components.layouts.auth')] class extends Component {
|
||||
/>
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
<x-auth-session-status class="text-center" :status="session('status')"/>
|
||||
|
||||
<form wire:submit="confirmPassword" class="flex flex-col gap-6">
|
||||
<!-- Password -->
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<?php
|
||||
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
new #[Layout('components.layouts.auth')]
|
||||
class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public string $email = '';
|
||||
|
||||
/**
|
||||
@@ -23,10 +27,11 @@ new #[Layout('components.layouts.auth')] class extends Component {
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header :title="__('Forgot password')" :description="__('Enter your email to receive a password reset link')" />
|
||||
<x-auth-header :title="__('Forgot password')"
|
||||
:description="__('Enter your email to receive a password reset link')"/>
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
<x-auth-session-status class="text-center" :status="session('status')"/>
|
||||
|
||||
<form wire:submit="sendPasswordResetLink" class="flex flex-col gap-6">
|
||||
<!-- Email Address -->
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -8,7 +9,10 @@ use Illuminate\Validation\Rules;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
new #[Layout('components.layouts.auth')]
|
||||
class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public string $name = '';
|
||||
public string $email = '';
|
||||
public string $password = '';
|
||||
@@ -21,7 +25,7 @@ new #[Layout('components.layouts.auth')] class extends Component {
|
||||
{
|
||||
$validated = $this->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:' . User::class],
|
||||
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
|
||||
'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
@@ -36,10 +40,11 @@ new #[Layout('components.layouts.auth')] class extends Component {
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header :title="__('Create an account')" :description="__('Enter your details below to create your account')" />
|
||||
<x-auth-header :title="__('Create an account')"
|
||||
:description="__('Enter your details below to create your account')"/>
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
<x-auth-session-status class="text-center" :status="session('status')"/>
|
||||
|
||||
<form wire:submit="register" class="flex flex-col gap-6">
|
||||
<!-- Name -->
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
@@ -10,7 +11,10 @@ use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
new #[Layout('components.layouts.auth')]
|
||||
class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
#[Locked]
|
||||
public string $token = '';
|
||||
public string $email = '';
|
||||
@@ -69,10 +73,10 @@ new #[Layout('components.layouts.auth')] class extends Component {
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header :title="__('Reset password')" :description="__('Please enter your new password below')" />
|
||||
<x-auth-header :title="__('Reset password')" :description="__('Please enter your new password below')"/>
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
<x-auth-session-status class="text-center" :status="session('status')"/>
|
||||
|
||||
<form wire:submit="resetPassword" class="flex flex-col gap-6">
|
||||
<!-- Email Address -->
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
<?php
|
||||
|
||||
use App\Livewire\Actions\Logout;
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
new #[Layout('components.layouts.auth')]
|
||||
class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
/**
|
||||
* Send an email verification notification to the user.
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
use App\Models\City;
|
||||
use App\Models\Country;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public string $name = '';
|
||||
public ?int $country_id = null;
|
||||
public float $latitude = 0;
|
||||
@@ -51,7 +54,7 @@ new class extends Component {
|
||||
<flux:legend>{{ __('Basic Information') }}</flux:legend>
|
||||
|
||||
<div class="space-y-6">
|
||||
<flux:input label="{{ __('Name') }}" wire:model="name" required />
|
||||
<flux:input label="{{ __('Name') }}" wire:model="name" required/>
|
||||
|
||||
<flux:select label="{{ __('Country') }}" wire:model="country_id" required>
|
||||
<option value="">{{ __('Select a country') }}</option>
|
||||
@@ -66,8 +69,8 @@ new class extends Component {
|
||||
<flux:legend>{{ __('Coordinates') }}</flux:legend>
|
||||
|
||||
<div class="grid grid-cols-2 gap-x-4 gap-y-6">
|
||||
<flux:input label="{{ __('Latitude') }}" type="number" step="any" wire:model="latitude" required />
|
||||
<flux:input label="{{ __('Longitude') }}" type="number" step="any" wire:model="longitude" required />
|
||||
<flux:input label="{{ __('Latitude') }}" type="number" step="any" wire:model="latitude" required/>
|
||||
<flux:input label="{{ __('Longitude') }}" type="number" step="any" wire:model="longitude" required/>
|
||||
</div>
|
||||
</flux:fieldset>
|
||||
|
||||
@@ -75,8 +78,8 @@ new class extends Component {
|
||||
<flux:legend>{{ __('Demographics') }}</flux:legend>
|
||||
|
||||
<div class="grid grid-cols-2 gap-x-4 gap-y-6">
|
||||
<flux:input label="{{ __('Population') }}" type="number" wire:model="population" />
|
||||
<flux:input label="{{ __('Population Date') }}" wire:model="population_date" placeholder="e.g. 2024" />
|
||||
<flux:input label="{{ __('Population') }}" type="number" wire:model="population"/>
|
||||
<flux:input label="{{ __('Population Date') }}" wire:model="population_date" placeholder="e.g. 2024"/>
|
||||
</div>
|
||||
</flux:fieldset>
|
||||
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
use App\Models\City;
|
||||
use App\Models\Country;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public City $city;
|
||||
public string $name = '';
|
||||
public ?int $country_id = null;
|
||||
@@ -62,7 +65,7 @@ new class extends Component {
|
||||
<flux:legend>{{ __('Basic Information') }}</flux:legend>
|
||||
|
||||
<div class="space-y-6">
|
||||
<flux:input label="{{ __('Name') }}" wire:model="name" required />
|
||||
<flux:input label="{{ __('Name') }}" wire:model="name" required/>
|
||||
|
||||
<flux:select label="{{ __('Country') }}" wire:model="country_id" required>
|
||||
<option value="">{{ __('Select a country') }}</option>
|
||||
@@ -77,8 +80,8 @@ new class extends Component {
|
||||
<flux:legend>{{ __('Coordinates') }}</flux:legend>
|
||||
|
||||
<div class="grid grid-cols-2 gap-x-4 gap-y-6">
|
||||
<flux:input label="{{ __('Latitude') }}" type="number" step="any" wire:model="latitude" required />
|
||||
<flux:input label="{{ __('Longitude') }}" type="number" step="any" wire:model="longitude" required />
|
||||
<flux:input label="{{ __('Latitude') }}" type="number" step="any" wire:model="latitude" required/>
|
||||
<flux:input label="{{ __('Longitude') }}" type="number" step="any" wire:model="longitude" required/>
|
||||
</div>
|
||||
</flux:fieldset>
|
||||
|
||||
@@ -86,8 +89,8 @@ new class extends Component {
|
||||
<flux:legend>{{ __('Demographics') }}</flux:legend>
|
||||
|
||||
<div class="grid grid-cols-2 gap-x-4 gap-y-6">
|
||||
<flux:input label="{{ __('Population') }}" type="number" wire:model="population" />
|
||||
<flux:input label="{{ __('Population Date') }}" wire:model="population_date" placeholder="e.g. 2024" />
|
||||
<flux:input label="{{ __('Population') }}" type="number" wire:model="population"/>
|
||||
<flux:input label="{{ __('Population Date') }}" wire:model="population_date" placeholder="e.g. 2024"/>
|
||||
</div>
|
||||
</flux:fieldset>
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
use App\Models\City;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
new class extends Component {
|
||||
use WithPagination;
|
||||
use SeoTrait;
|
||||
|
||||
public $country = 'de';
|
||||
public $search = '';
|
||||
@@ -38,7 +40,8 @@ new class extends Component {
|
||||
clearable
|
||||
/>
|
||||
@auth
|
||||
<flux:button class="cursor-pointer" :href="route_with_country('cities.create')" icon="plus" variant="primary">
|
||||
<flux:button class="cursor-pointer" :href="route_with_country('cities.create')" icon="plus"
|
||||
variant="primary">
|
||||
{{ __('Create City') }}
|
||||
</flux:button>
|
||||
@endauth
|
||||
@@ -81,7 +84,9 @@ new class extends Component {
|
||||
<flux:table.cell>
|
||||
<div class="flex gap-2">
|
||||
@auth
|
||||
<flux:button size="xs" :href="route('cities.edit',['city' => $city, 'country' => $country])" icon="pencil">
|
||||
<flux:button size="xs"
|
||||
:href="route('cities.edit',['city' => $city, 'country' => $country])"
|
||||
icon="pencil">
|
||||
{{ __('Edit') }}
|
||||
</flux:button>
|
||||
@endauth
|
||||
|
||||
@@ -4,10 +4,13 @@ use App\Models\City;
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseEvent;
|
||||
use App\Models\Venue;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public Course $course;
|
||||
public ?CourseEvent $event = null;
|
||||
|
||||
@@ -63,7 +66,8 @@ new class extends Component {
|
||||
session()->flash('status', __('Event erfolgreich erstellt!'));
|
||||
}
|
||||
|
||||
$this->redirect(route('courses.landingpage', ['course' => $this->course, 'country' => $this->country]), navigate: true);
|
||||
$this->redirect(route('courses.landingpage', ['course' => $this->course, 'country' => $this->country]),
|
||||
navigate: true);
|
||||
}
|
||||
|
||||
public function delete(): void
|
||||
@@ -71,7 +75,8 @@ new class extends Component {
|
||||
if ($this->event) {
|
||||
$this->event->delete();
|
||||
session()->flash('status', __('Event erfolgreich gelöscht!'));
|
||||
$this->redirect(route('courses.landingpage', ['course' => $this->course, 'country' => $this->country]), navigate: true);
|
||||
$this->redirect(route('courses.landingpage', ['course' => $this->course, 'country' => $this->country]),
|
||||
navigate: true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,12 +176,14 @@ new class extends Component {
|
||||
<!-- Form Actions -->
|
||||
<div class="flex items-center justify-between pt-8 border-t border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center gap-4">
|
||||
<flux:button class="cursor-pointer" variant="ghost" type="button" :href="route('courses.landingpage', ['course' => $course, 'country' => $country])">
|
||||
<flux:button class="cursor-pointer" variant="ghost" type="button"
|
||||
:href="route('courses.landingpage', ['course' => $course, 'country' => $country])">
|
||||
{{ __('Abbrechen') }}
|
||||
</flux:button>
|
||||
|
||||
@if($event)
|
||||
<flux:button class="cursor-pointer" variant="danger" type="button" wire:click="delete" wire:confirm="{{ __('Bist du sicher, dass du dieses Event löschen möchtest?') }}">
|
||||
<flux:button class="cursor-pointer" variant="danger" type="button" wire:click="delete"
|
||||
wire:confirm="{{ __('Bist du sicher, dass du dieses Event löschen möchtest?') }}">
|
||||
{{ __('Event löschen') }}
|
||||
</flux:button>
|
||||
@endif
|
||||
@@ -235,10 +242,12 @@ new class extends Component {
|
||||
<flux:spacer/>
|
||||
|
||||
<flux:modal.close>
|
||||
<flux:button class="cursor-pointer" type="button" variant="ghost">{{ __('Abbrechen') }}</flux:button>
|
||||
<flux:button class="cursor-pointer" type="button"
|
||||
variant="ghost">{{ __('Abbrechen') }}</flux:button>
|
||||
</flux:modal.close>
|
||||
|
||||
<flux:button class="cursor-pointer" type="submit" variant="primary">{{ __('Ort erstellen') }}</flux:button>
|
||||
<flux:button class="cursor-pointer" type="submit"
|
||||
variant="primary">{{ __('Ort erstellen') }}</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
</flux:modal>
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\Lecturer;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
new class extends Component {
|
||||
use WithFileUploads;
|
||||
use SeoTrait;
|
||||
|
||||
#[Validate('image|max:10240')] // 10MB Max
|
||||
public $logo;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\Lecturer;
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
@@ -9,6 +10,7 @@ use Livewire\WithFileUploads;
|
||||
|
||||
new class extends Component {
|
||||
use WithFileUploads;
|
||||
use SeoTrait;
|
||||
|
||||
#[Validate('image|max:10240')] // 10MB Max
|
||||
public $logo;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
new class extends Component {
|
||||
use WithPagination;
|
||||
use SeoTrait;
|
||||
|
||||
public $country = 'de';
|
||||
public $search = '';
|
||||
@@ -67,8 +69,9 @@ new class extends Component {
|
||||
<flux:table.cell variant="strong">
|
||||
<flux:tooltip content="{{ $course->name }}">
|
||||
<div class="flex items-center gap-3">
|
||||
<flux:avatar :href="route('courses.landingpage', ['course' => $course, 'country' => $country])"
|
||||
src="{{ $course->getFirstMedia('logo') ? $course->getFirstMediaUrl('logo', 'thumb') : asset('android-chrome-512x512.png') }}"/>
|
||||
<flux:avatar
|
||||
:href="route('courses.landingpage', ['course' => $course, 'country' => $country])"
|
||||
src="{{ $course->getFirstMedia('logo') ? $course->getFirstMediaUrl('logo', 'thumb') : asset('android-chrome-512x512.png') }}"/>
|
||||
<div>
|
||||
<a href="{{ route('courses.landingpage', ['course' => $course, 'country' => $country]) }}">
|
||||
<span>{{ Str::limit($course->name, 30) }}</span>
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseEvent;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public Course $course;
|
||||
|
||||
public $country = 'de';
|
||||
@@ -39,7 +42,8 @@ new class extends Component {
|
||||
<flux:heading size="xl" class="mb-4">{{ $course->name }}</flux:heading>
|
||||
@if($course->lecturer)
|
||||
<flux:subheading class="text-gray-600 dark:text-gray-400 flex items-center gap-2">
|
||||
<flux:avatar size="xs" src="{{ $course->lecturer->getFirstMedia('avatar') ? $course->lecturer->getFirstMediaUrl('avatar', 'thumb') : asset('img/einundzwanzig.png') }}"/>
|
||||
<flux:avatar size="xs"
|
||||
src="{{ $course->lecturer->getFirstMedia('avatar') ? $course->lecturer->getFirstMediaUrl('avatar', 'thumb') : asset('img/einundzwanzig.png') }}"/>
|
||||
{{ $course->lecturer->name }}
|
||||
</flux:subheading>
|
||||
@endif
|
||||
@@ -58,36 +62,43 @@ new class extends Component {
|
||||
<flux:heading size="lg">{{ __('Über den Dozenten') }}</flux:heading>
|
||||
|
||||
<div class="flex items-start gap-4 p-4 bg-zinc-50 dark:bg-zinc-900 rounded-lg">
|
||||
<flux:avatar size="lg" src="{{ $course->lecturer->getFirstMedia('avatar') ? $course->lecturer->getFirstMediaUrl('avatar', 'preview') : asset('img/einundzwanzig.png') }}"/>
|
||||
<flux:avatar size="lg"
|
||||
src="{{ $course->lecturer->getFirstMedia('avatar') ? $course->lecturer->getFirstMediaUrl('avatar', 'preview') : asset('img/einundzwanzig.png') }}"/>
|
||||
<div class="flex-1">
|
||||
<flux:heading size="md" class="mb-1">{{ $course->lecturer->name }}</flux:heading>
|
||||
@if($course->lecturer->subtitle)
|
||||
<flux:text class="text-sm text-zinc-600 dark:text-zinc-400 mb-2">{{ $course->lecturer->subtitle }}</flux:text>
|
||||
<flux:text
|
||||
class="text-sm text-zinc-600 dark:text-zinc-400 mb-2">{{ $course->lecturer->subtitle }}</flux:text>
|
||||
@endif
|
||||
@if($course->lecturer->intro)
|
||||
<x-markdown class="prose prose-sm whitespace-pre-wrap">{!! $course->lecturer->intro !!}</x-markdown>
|
||||
<x-markdown
|
||||
class="prose prose-sm whitespace-pre-wrap">{!! $course->lecturer->intro !!}</x-markdown>
|
||||
@endif
|
||||
|
||||
<!-- Lecturer Social Links -->
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
@if($course->lecturer->website)
|
||||
<flux:button href="{{ $course->lecturer->website }}" target="_blank" variant="ghost" size="xs">
|
||||
<flux:button href="{{ $course->lecturer->website }}" target="_blank" variant="ghost"
|
||||
size="xs">
|
||||
<flux:icon.globe-alt class="w-4 h-4 mr-1"/>
|
||||
Website
|
||||
</flux:button>
|
||||
@endif
|
||||
|
||||
@if($course->lecturer->twitter_username)
|
||||
<flux:button href="https://twitter.com/{{ $course->lecturer->twitter_username }}" target="_blank" variant="ghost" size="xs">
|
||||
<flux:button href="https://twitter.com/{{ $course->lecturer->twitter_username }}"
|
||||
target="_blank" variant="ghost" size="xs">
|
||||
<svg class="w-4 h-4 mr-1" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
|
||||
<path
|
||||
d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
|
||||
</svg>
|
||||
Twitter
|
||||
</flux:button>
|
||||
@endif
|
||||
|
||||
@if($course->lecturer->nostr)
|
||||
<flux:button href="https://njump.me/{{ $course->lecturer->nostr }}" target="_blank" variant="ghost" size="xs">
|
||||
<flux:button href="https://njump.me/{{ $course->lecturer->nostr }}" target="_blank"
|
||||
variant="ghost" size="xs">
|
||||
<flux:icon.bolt class="w-4 h-4 mr-1"/>
|
||||
Nostr
|
||||
</flux:button>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Lecturer;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
new class extends Component {
|
||||
use WithFileUploads;
|
||||
use SeoTrait;
|
||||
|
||||
#[Validate('image|max:10240')] // 10MB Max
|
||||
public $avatar;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Lecturer;
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
@@ -8,6 +9,7 @@ use Livewire\WithFileUploads;
|
||||
|
||||
new class extends Component {
|
||||
use WithFileUploads;
|
||||
use SeoTrait;
|
||||
|
||||
#[Validate('image|max:10240')] // 10MB Max
|
||||
public $avatar;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Lecturer;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
new class extends Component {
|
||||
use WithPagination;
|
||||
use SeoTrait;
|
||||
|
||||
public $country = 'de';
|
||||
public $search = '';
|
||||
@@ -18,7 +20,9 @@ new class extends Component {
|
||||
public function with(): array
|
||||
{
|
||||
return [
|
||||
'lecturers' => Lecturer::with(['createdBy', 'coursesEvents' => fn($query) => $query->where('from', '>=', now())->orderBy('from', 'asc')])
|
||||
'lecturers' => Lecturer::with([
|
||||
'createdBy', 'coursesEvents' => fn($query) => $query->where('from', '>=', now())->orderBy('from', 'asc')
|
||||
])
|
||||
->withExists([
|
||||
'coursesEvents as has_future_events' => fn($query) => $query->where('from', '>=', now())
|
||||
])
|
||||
@@ -26,9 +30,10 @@ new class extends Component {
|
||||
'coursesEvents as future_events_count' => fn($query) => $query->where('from', '>=', now())
|
||||
])
|
||||
->when($this->search, fn($query)
|
||||
=> $query->where('name', 'ilike', '%'.$this->search.'%')
|
||||
->orWhere('description', 'ilike', '%'.$this->search.'%')
|
||||
->orWhere('subtitle', 'ilike', '%'.$this->search.'%'),
|
||||
=> $query
|
||||
->where('name', 'ilike', '%'.$this->search.'%')
|
||||
->orWhere('description', 'ilike', '%'.$this->search.'%')
|
||||
->orWhere('subtitle', 'ilike', '%'.$this->search.'%'),
|
||||
)
|
||||
->orderByDesc('has_future_events')
|
||||
->orderBy('name', 'asc')
|
||||
@@ -47,7 +52,8 @@ new class extends Component {
|
||||
clearable
|
||||
/>
|
||||
@auth
|
||||
<flux:button class="cursor-pointer" :href="route_with_country('lecturers.create')" icon="plus" variant="primary">
|
||||
<flux:button class="cursor-pointer" :href="route_with_country('lecturers.create')" icon="plus"
|
||||
variant="primary">
|
||||
{{ __('Dozenten anlegen') }}
|
||||
</flux:button>
|
||||
@endauth
|
||||
@@ -69,7 +75,8 @@ new class extends Component {
|
||||
<flux:table.row :key="$lecturer->id">
|
||||
<flux:table.cell variant="strong" class="flex items-center gap-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<flux:avatar size="lg" src="{{ $lecturer->getFirstMedia('avatar') ? $lecturer->getFirstMediaUrl('avatar', 'thumb') : asset('img/einundzwanzig.png') }}"/>
|
||||
<flux:avatar size="lg"
|
||||
src="{{ $lecturer->getFirstMedia('avatar') ? $lecturer->getFirstMediaUrl('avatar', 'thumb') : asset('img/einundzwanzig.png') }}"/>
|
||||
<div>
|
||||
<div class="font-semibold">{{ $lecturer->name }}</div>
|
||||
@if($lecturer->active)
|
||||
@@ -108,7 +115,8 @@ new class extends Component {
|
||||
<flux:table.cell>
|
||||
<div class="flex gap-2">
|
||||
@if($lecturer->website)
|
||||
<flux:link :href="$lecturer->website" external variant="subtle" title="{{ __('Website') }}">
|
||||
<flux:link :href="$lecturer->website" external variant="subtle"
|
||||
title="{{ __('Website') }}">
|
||||
<flux:icon.globe-alt variant="mini"/>
|
||||
</flux:link>
|
||||
@endif
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
use App\Models\Meetup;
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public Meetup $meetup;
|
||||
public ?MeetupEvent $event = null;
|
||||
|
||||
@@ -56,7 +59,8 @@ new class extends Component {
|
||||
session()->flash('status', __('Event erfolgreich erstellt!'));
|
||||
}
|
||||
|
||||
$this->redirect(route('meetups.landingpage', ['meetup' => $this->meetup, 'country' => $this->country]), navigate: true);
|
||||
$this->redirect(route('meetups.landingpage', ['meetup' => $this->meetup, 'country' => $this->country]),
|
||||
navigate: true);
|
||||
}
|
||||
|
||||
public function delete(): void
|
||||
@@ -64,7 +68,8 @@ new class extends Component {
|
||||
if ($this->event) {
|
||||
$this->event->delete();
|
||||
session()->flash('status', __('Event erfolgreich gelöscht!'));
|
||||
$this->redirect(route('meetups.landingpage', ['meetup' => $this->meetup, 'country' => $this->country]), navigate: true);
|
||||
$this->redirect(route('meetups.landingpage', ['meetup' => $this->meetup, 'country' => $this->country]),
|
||||
navigate: true);
|
||||
}
|
||||
}
|
||||
}; ?>
|
||||
@@ -114,12 +119,14 @@ new class extends Component {
|
||||
<!-- Form Actions -->
|
||||
<div class="flex items-center justify-between pt-8 border-t border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center gap-4">
|
||||
<flux:button variant="ghost" type="button" :href="route_with_country('meetups.edit', ['meetup' => $meetup])">
|
||||
<flux:button variant="ghost" type="button"
|
||||
:href="route_with_country('meetups.edit', ['meetup' => $meetup])">
|
||||
{{ __('Abbrechen') }}
|
||||
</flux:button>
|
||||
|
||||
@if($event)
|
||||
<flux:button variant="danger" type="button" wire:click="delete" wire:confirm="{{ __('Bist du sicher, dass du dieses Event löschen möchtest?') }}">
|
||||
<flux:button variant="danger" type="button" wire:click="delete"
|
||||
wire:confirm="{{ __('Bist du sicher, dass du dieses Event löschen möchtest?') }}">
|
||||
{{ __('Event löschen') }}
|
||||
</flux:button>
|
||||
@endif
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
use App\Models\City;
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
new class extends Component {
|
||||
use WithFileUploads;
|
||||
use SeoTrait;
|
||||
|
||||
#[Validate('image|max:10240')] // 10MB Max
|
||||
public $logo;
|
||||
@@ -327,10 +329,12 @@ new class extends Component {
|
||||
<flux:spacer/>
|
||||
|
||||
<flux:modal.close>
|
||||
<flux:button class="cursor-pointer" type="button" variant="ghost">{{ __('Abbrechen') }}</flux:button>
|
||||
<flux:button class="cursor-pointer" type="button"
|
||||
variant="ghost">{{ __('Abbrechen') }}</flux:button>
|
||||
</flux:modal.close>
|
||||
|
||||
<flux:button class="cursor-pointer" type="submit" variant="primary">{{ __('Stadt erstellen') }}</flux:button>
|
||||
<flux:button class="cursor-pointer" type="submit"
|
||||
variant="primary">{{ __('Stadt erstellen') }}</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
</flux:modal>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use App\Models\City;
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
@@ -10,6 +11,7 @@ use Livewire\WithFileUploads;
|
||||
|
||||
new class extends Component {
|
||||
use WithFileUploads;
|
||||
use SeoTrait;
|
||||
|
||||
#[Validate('image|max:10240')] // 10MB Max
|
||||
public $logo;
|
||||
@@ -420,10 +422,12 @@ new class extends Component {
|
||||
<flux:spacer/>
|
||||
|
||||
<flux:modal.close>
|
||||
<flux:button class="cursor-pointer" type="button" variant="ghost">{{ __('Abbrechen') }}</flux:button>
|
||||
<flux:button class="cursor-pointer" type="button"
|
||||
variant="ghost">{{ __('Abbrechen') }}</flux:button>
|
||||
</flux:modal.close>
|
||||
|
||||
<flux:button class="cursor-pointer" type="submit" variant="primary">{{ __('Stadt erstellen') }}</flux:button>
|
||||
<flux:button class="cursor-pointer" type="submit"
|
||||
variant="primary">{{ __('Stadt erstellen') }}</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
</flux:modal>
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Models\User;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public MeetupEvent $event;
|
||||
public $country = 'de';
|
||||
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
use App\Models\Meetup;
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public Meetup $meetup;
|
||||
|
||||
public $country = 'de';
|
||||
@@ -39,7 +42,9 @@ new class extends Component {
|
||||
<flux:subheading class="text-gray-600 dark:text-gray-400">
|
||||
{{ $meetup->city->name }}, {{ $meetup->city->country->name }}
|
||||
</flux:subheading>
|
||||
<flux:button class="cursor-pointer" x-copy-to-clipboard="'{{ route('ics', ['meetup' => $meetup]) }}'" icon="calendar-date-range">{{ __('Kalender-Stream-URL kopieren') }}</flux:button>
|
||||
<flux:button class="cursor-pointer"
|
||||
x-copy-to-clipboard="'{{ route('ics', ['meetup' => $meetup]) }}'"
|
||||
icon="calendar-date-range">{{ __('Kalender-Stream-URL kopieren') }}</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -194,11 +199,13 @@ new class extends Component {
|
||||
<div class="flex items-center space-x-4 mb-6">
|
||||
<flux:heading size="xl">{{ __('Kommende Veranstaltungen') }}</flux:heading>
|
||||
@if(auth()->user() && auth()->user()->meetups()->find($meetup->id)?->exists)
|
||||
<flux:button :href="route_with_country('meetups.events.create', ['meetup' => $meetup])" variant="primary" icon="calendar">
|
||||
<flux:button :href="route_with_country('meetups.events.create', ['meetup' => $meetup])"
|
||||
variant="primary" icon="calendar">
|
||||
{{ __('Neues Event erstellen') }}
|
||||
</flux:button>
|
||||
@endif
|
||||
<flux:button class="cursor-pointer" x-copy-to-clipboard="'{{ route('ics', ['meetup' => $meetup]) }}'" icon="calendar-date-range">{{ __('Kalender-Stream-URL kopieren') }}</flux:button>
|
||||
<flux:button class="cursor-pointer" x-copy-to-clipboard="'{{ route('ics', ['meetup' => $meetup]) }}'"
|
||||
icon="calendar-date-range">{{ __('Kalender-Stream-URL kopieren') }}</flux:button>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
@@ -260,7 +267,8 @@ new class extends Component {
|
||||
<div class="mt-16">
|
||||
<div class="flex items-center space-x-4 mb-6">
|
||||
@if(auth()->user() && auth()->user()->meetups()->find($meetup->id)?->exists)
|
||||
<flux:button :href="route_with_country('meetups.events.create', ['meetup' => $meetup])" variant="primary" icon="calendar">
|
||||
<flux:button :href="route_with_country('meetups.events.create', ['meetup' => $meetup])"
|
||||
variant="primary" icon="calendar">
|
||||
{{ __('Neues Event erstellen') }}
|
||||
</flux:button>
|
||||
@endif
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Meetup;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public function with(): array
|
||||
{
|
||||
return [
|
||||
@@ -22,7 +25,7 @@ new class extends Component {
|
||||
<style>
|
||||
#map {
|
||||
height: 90vh;
|
||||
z-index: 0!important;
|
||||
z-index: 0 !important;
|
||||
}
|
||||
|
||||
#map:focus {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
//
|
||||
use SeoTrait;
|
||||
}; ?>
|
||||
|
||||
<section class="w-full">
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<?php
|
||||
|
||||
use App\Livewire\Actions\Logout;
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public string $password = '';
|
||||
|
||||
/**
|
||||
@@ -44,7 +47,7 @@ new class extends Component {
|
||||
</flux:subheading>
|
||||
</div>
|
||||
|
||||
<flux:input wire:model="password" :label="__('Password')" type="password" />
|
||||
<flux:input wire:model="password" :label="__('Password')" type="password"/>
|
||||
|
||||
<div class="flex justify-end space-x-2 rtl:space-x-reverse">
|
||||
<flux:modal.close>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
@@ -7,6 +8,8 @@ use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public string $current_password = '';
|
||||
public string $password = '';
|
||||
public string $password_confirmation = '';
|
||||
@@ -40,7 +43,8 @@ new class extends Component {
|
||||
<section class="w-full">
|
||||
@include('partials.settings-heading')
|
||||
|
||||
<x-settings.layout :heading="__('Update password')" :subheading="__('Ensure your account is using a long, random password to stay secure')">
|
||||
<x-settings.layout :heading="__('Update password')"
|
||||
:subheading="__('Ensure your account is using a long, random password to stay secure')">
|
||||
<form wire:submit="updatePassword" class="mt-6 space-y-6">
|
||||
<flux:input
|
||||
wire:model="current_password"
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use App\Traits\SeoTrait;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public string $name = '';
|
||||
public string $email = '';
|
||||
|
||||
@@ -74,7 +77,7 @@ new class extends Component {
|
||||
|
||||
<x-settings.layout :heading="__('Profile')" :subheading="__('Update your name and email address')">
|
||||
<form wire:submit="updateProfileInformation" class="my-6 w-full space-y-6">
|
||||
<flux:input wire:model="name" :label="__('Name')" type="text" required autofocus autocomplete="name" />
|
||||
<flux:input wire:model="name" :label="__('Name')" type="text" required autofocus autocomplete="name"/>
|
||||
|
||||
{{--<div>
|
||||
<flux:input wire:model="email" :label="__('Email')" type="email" required autocomplete="email" />
|
||||
@@ -144,6 +147,6 @@ new class extends Component {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<livewire:settings.delete-user-form />
|
||||
<livewire:settings.delete-user-form/>
|
||||
</x-settings.layout>
|
||||
</section>
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
use App\Models\Venue;
|
||||
use App\Models\City;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public string $name = '';
|
||||
public ?int $city_id = null;
|
||||
public string $street = '';
|
||||
@@ -45,7 +48,7 @@ new class extends Component {
|
||||
<flux:legend>{{ __('Venue Information') }}</flux:legend>
|
||||
|
||||
<div class="space-y-6">
|
||||
<flux:input label="{{ __('Name') }}" wire:model="name" required />
|
||||
<flux:input label="{{ __('Name') }}" wire:model="name" required/>
|
||||
|
||||
<flux:select label="{{ __('City') }}" wire:model="city_id" required>
|
||||
<option value="">{{ __('Select a city') }}</option>
|
||||
@@ -59,7 +62,7 @@ new class extends Component {
|
||||
@endforeach
|
||||
</flux:select>
|
||||
|
||||
<flux:input label="{{ __('Street') }}" wire:model="street" required />
|
||||
<flux:input label="{{ __('Street') }}" wire:model="street" required/>
|
||||
</div>
|
||||
</flux:fieldset>
|
||||
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
use App\Models\Venue;
|
||||
use App\Models\City;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
use SeoTrait;
|
||||
|
||||
public Venue $venue;
|
||||
public string $name = '';
|
||||
public ?int $city_id = null;
|
||||
@@ -53,7 +56,7 @@ new class extends Component {
|
||||
<flux:legend>{{ __('Venue Information') }}</flux:legend>
|
||||
|
||||
<div class="space-y-6">
|
||||
<flux:input label="{{ __('Name') }}" wire:model="name" required />
|
||||
<flux:input label="{{ __('Name') }}" wire:model="name" required/>
|
||||
|
||||
<flux:select label="{{ __('City') }}" wire:model="city_id" required>
|
||||
<option value="">{{ __('Select a city') }}</option>
|
||||
@@ -67,7 +70,7 @@ new class extends Component {
|
||||
@endforeach
|
||||
</flux:select>
|
||||
|
||||
<flux:input label="{{ __('Street') }}" wire:model="street" required />
|
||||
<flux:input label="{{ __('Street') }}" wire:model="street" required/>
|
||||
</div>
|
||||
</flux:fieldset>
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Venue;
|
||||
use App\Traits\SeoTrait;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
new class extends Component {
|
||||
use WithPagination;
|
||||
use SeoTrait;
|
||||
|
||||
public $country = 'de';
|
||||
public $search = '';
|
||||
@@ -38,7 +40,8 @@ new class extends Component {
|
||||
clearable
|
||||
/>
|
||||
@auth
|
||||
<flux:button class="cursor-pointer" :href="route_with_country('venues.create')" icon="plus" variant="primary">
|
||||
<flux:button class="cursor-pointer" :href="route_with_country('venues.create')" icon="plus"
|
||||
variant="primary">
|
||||
{{ __('Create Venue') }}
|
||||
</flux:button>
|
||||
@endauth
|
||||
@@ -75,7 +78,9 @@ new class extends Component {
|
||||
<flux:table.cell>
|
||||
<div class="flex gap-2">
|
||||
@auth
|
||||
<flux:button size="xs" :href="route('venues.edit', ['venue' => $venue, 'country' => $country])" icon="pencil">
|
||||
<flux:button size="xs"
|
||||
:href="route('venues.edit', ['venue' => $venue, 'country' => $country])"
|
||||
icon="pencil">
|
||||
{{ __('Edit') }}
|
||||
</flux:button>
|
||||
@endauth
|
||||
|
||||
Reference in New Issue
Block a user