Chore: Upgrade to Laravel 12 + remove Mary and Jetstream dependencies (#141)
* docs: remove requirement for setting APP_KEY manually * optimize date picker * clean up modals * spot light working * reorganization * add lazy load * wip * remove filament * styling
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Laravel\Fortify\Actions\ConfirmPassword;
|
||||
|
||||
trait ConfirmsPasswords
|
||||
{
|
||||
/**
|
||||
* Indicates if the user's password is being confirmed.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $confirmingPassword = false;
|
||||
|
||||
/**
|
||||
* The ID of the operation being confirmed.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $confirmableId = null;
|
||||
|
||||
/**
|
||||
* The user's password.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $confirmablePassword = '';
|
||||
|
||||
/**
|
||||
* Start confirming the user's password.
|
||||
*
|
||||
* @param string $confirmableId
|
||||
* @return void
|
||||
*/
|
||||
public function startConfirmingPassword(string $confirmableId)
|
||||
{
|
||||
$this->resetErrorBag();
|
||||
|
||||
if ($this->passwordIsConfirmed()) {
|
||||
return $this->dispatch('password-confirmed',
|
||||
id: $confirmableId,
|
||||
);
|
||||
}
|
||||
|
||||
$this->confirmingPassword = true;
|
||||
$this->confirmableId = $confirmableId;
|
||||
$this->confirmablePassword = '';
|
||||
|
||||
$this->dispatch('confirming-password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop confirming the user's password.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function stopConfirmingPassword()
|
||||
{
|
||||
$this->confirmingPassword = false;
|
||||
$this->confirmableId = null;
|
||||
$this->confirmablePassword = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the user's password.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function confirmPassword()
|
||||
{
|
||||
if (! app(ConfirmPassword::class)(app(StatefulGuard::class), Auth::user(), $this->confirmablePassword)) {
|
||||
throw ValidationException::withMessages([
|
||||
'confirmable_password' => [__('This password does not match our records.')],
|
||||
]);
|
||||
}
|
||||
|
||||
session(['auth.password_confirmed_at' => time()]);
|
||||
|
||||
$this->dispatch('password-confirmed',
|
||||
id: $this->confirmableId,
|
||||
);
|
||||
|
||||
$this->stopConfirmingPassword();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the user's password has been recently confirmed.
|
||||
*
|
||||
* @param int|null $maximumSecondsSinceConfirmation
|
||||
* @return void
|
||||
*/
|
||||
protected function ensurePasswordIsConfirmed($maximumSecondsSinceConfirmation = null)
|
||||
{
|
||||
$maximumSecondsSinceConfirmation = $maximumSecondsSinceConfirmation ?: config('auth.password_timeout', 900);
|
||||
|
||||
$this->passwordIsConfirmed($maximumSecondsSinceConfirmation) ? null : abort(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user's password has been recently confirmed.
|
||||
*
|
||||
* @param int|null $maximumSecondsSinceConfirmation
|
||||
* @return bool
|
||||
*/
|
||||
protected function passwordIsConfirmed($maximumSecondsSinceConfirmation = null)
|
||||
{
|
||||
$maximumSecondsSinceConfirmation = $maximumSecondsSinceConfirmation ?: config('auth.password_timeout', 900);
|
||||
|
||||
return (time() - session('auth.password_confirmed_at', 0)) < $maximumSecondsSinceConfirmation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait HasLocalizedMarkdown
|
||||
{
|
||||
public function localizedMarkdownPath($name)
|
||||
{
|
||||
$localName = preg_replace('#(\.md)$#i', '.'.app()->getLocale().'$1', $name);
|
||||
|
||||
return Arr::first([
|
||||
resource_path('markdown/'.$localName),
|
||||
resource_path('markdown/'.$name),
|
||||
], function ($path) {
|
||||
return file_exists($path);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
trait HasProfilePhoto
|
||||
{
|
||||
/**
|
||||
* Update the user's profile photo.
|
||||
*
|
||||
* @param string $storagePath
|
||||
* @return void
|
||||
*/
|
||||
public function updateProfilePhoto(UploadedFile $photo, $storagePath = 'profile-photos')
|
||||
{
|
||||
tap($this->profile_photo_path, function ($previous) use ($photo, $storagePath) {
|
||||
$this->forceFill([
|
||||
'profile_photo_path' => $photo->storePublicly(
|
||||
$storagePath, ['disk' => 'public']
|
||||
),
|
||||
])->save();
|
||||
|
||||
if ($previous) {
|
||||
Storage::disk('public')->delete($previous);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the user's profile photo.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteProfilePhoto()
|
||||
{
|
||||
if (is_null($this->profile_photo_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Storage::disk('public')->delete($this->profile_photo_path);
|
||||
|
||||
$this->forceFill([
|
||||
'profile_photo_path' => null,
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL to the user's profile photo.
|
||||
*/
|
||||
protected function profilePhotoUrl(): Attribute
|
||||
{
|
||||
return Attribute::get(function (): string {
|
||||
return $this->profile_photo_path
|
||||
? Storage::disk('public')->url($this->profile_photo_path)
|
||||
: $this->defaultProfilePhotoUrl();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default profile photo URL if no profile photo has been uploaded.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function defaultProfilePhotoUrl()
|
||||
{
|
||||
$name = trim(collect(explode(' ', $this->name))->map(function ($segment) {
|
||||
return mb_substr($segment, 0, 1);
|
||||
})->join(' '));
|
||||
|
||||
return 'https://ui-avatars.com/api/?name='.urlencode($name).'&color=7F9CF5&background=EBF4FF';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
|
||||
trait Toast
|
||||
{
|
||||
public function toast(
|
||||
string $type,
|
||||
string $title,
|
||||
?string $description = null,
|
||||
?string $position = null,
|
||||
string $icon = 'o-information-circle',
|
||||
string $css = 'alert-info',
|
||||
int $timeout = 3000,
|
||||
?string $redirectTo = null
|
||||
) {
|
||||
$toast = [
|
||||
'type' => $type,
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'position' => $position,
|
||||
'icon' => Blade::render("<x-ui.icon class='w-7 h-7' name='".$icon."' />"),
|
||||
'css' => $css,
|
||||
'timeout' => $timeout,
|
||||
];
|
||||
|
||||
$this->js('toast('.json_encode(['toast' => $toast]).')');
|
||||
|
||||
// session()->flash('ib.toast.title', $title);
|
||||
// session()->flash('ib.toast.description', $description);
|
||||
|
||||
if ($redirectTo) {
|
||||
return $this->redirect($redirectTo, navigate: true);
|
||||
}
|
||||
}
|
||||
|
||||
public function success(
|
||||
string $title,
|
||||
?string $description = null,
|
||||
?string $position = null,
|
||||
string $icon = 'o-check-circle',
|
||||
string $css = 'alert-success',
|
||||
int $timeout = 3000,
|
||||
?string $redirectTo = null
|
||||
) {
|
||||
return $this->toast('success', $title, $description, $position, $icon, $css, $timeout, $redirectTo);
|
||||
}
|
||||
|
||||
public function warning(
|
||||
string $title,
|
||||
?string $description = null,
|
||||
?string $position = null,
|
||||
string $icon = 'o-exclamation-triangle',
|
||||
string $css = 'alert-warning',
|
||||
int $timeout = 3000,
|
||||
?string $redirectTo = null
|
||||
) {
|
||||
return $this->toast('warning', $title, $description, $position, $icon, $css, $timeout, $redirectTo);
|
||||
}
|
||||
|
||||
public function error(
|
||||
string $title,
|
||||
?string $description = null,
|
||||
?string $position = null,
|
||||
string $icon = 'o-x-circle',
|
||||
string $css = 'alert-error',
|
||||
int $timeout = 3000,
|
||||
?string $redirectTo = null
|
||||
) {
|
||||
return $this->toast('error', $title, $description, $position, $icon, $css, $timeout, $redirectTo);
|
||||
}
|
||||
|
||||
public function info(
|
||||
string $title,
|
||||
?string $description = null,
|
||||
?string $position = null,
|
||||
string $icon = 'o-information-circle',
|
||||
string $css = 'alert-info',
|
||||
int $timeout = 3000,
|
||||
?string $redirectTo = null
|
||||
) {
|
||||
return $this->toast('info', $title, $description, $position, $icon, $css, $timeout, $redirectTo);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user