feat: 🚨 resolve php errors
This commit is contained in:
parent
cc45c363b5
commit
6e6f3d55b5
30 changed files with 264 additions and 238 deletions
|
|
@ -106,17 +106,23 @@ class MakeUser extends Command
|
|||
/**
|
||||
* Ask for a role and return the corresponding RoleEnum.
|
||||
*
|
||||
* @return object
|
||||
* @return object{name: string, value: int|string, label: string}
|
||||
*/
|
||||
private function askRole(): object
|
||||
{
|
||||
$options = collect(UserRoleRegistry::all())->mapWithKeys(fn(object $role) => [
|
||||
Str::ucFirst($role->label) => $role
|
||||
]);
|
||||
$roles = UserRoleRegistry::all();
|
||||
$defaultRole = UserRoleRegistry::get('client');
|
||||
|
||||
$choice = $this->choice('Role', $options->keys()->all(), Str::ucFirst(UserRoleRegistry::get('client')->label));
|
||||
$options = collect($roles)->mapWithKeys(
|
||||
fn(object $role) => [Str::ucFirst($role->label) => $role]);
|
||||
|
||||
$choice = $this->choice(
|
||||
'Role',
|
||||
$options->keys()->all(),
|
||||
Str::ucFirst($defaultRole->label),
|
||||
);
|
||||
$choiceKey = is_string($choice) ? $choice : (string) $choice[0];
|
||||
return $options->get($choiceKey) ?? UserRoleRegistry::get('client');
|
||||
return $options->get($choiceKey) ?? $defaultRole;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -54,4 +54,3 @@ enum NoticeTypeEnum: int
|
|||
return self::CLASSES;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,11 +48,11 @@ class InvoiceCompanyController extends BackendController
|
|||
$query,
|
||||
$search,
|
||||
null,
|
||||
// TODO: Fields here.
|
||||
'name',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
// TODO: Translations here.
|
||||
trans('validation.attributes.name'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
|
|
@ -104,7 +104,7 @@ class InvoiceCompanyController extends BackendController
|
|||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$invoice_company = new InvoiceCompany();
|
||||
$invoice_company->inertiaFill($request->validated());
|
||||
$invoice_company->fill($request->validated());
|
||||
|
||||
if ($invoice_company->saveOrFail()) {
|
||||
return redirect()->route("back.$this->modelName.edit", $invoice_company)
|
||||
|
|
@ -136,7 +136,7 @@ class InvoiceCompanyController extends BackendController
|
|||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\InvoiceCompanies\UpdateInvoiceCompanyRequest $request
|
||||
* @param \App\Models\InvoiceCompany $invoice_company
|
||||
* @param \App\Models\InvoiceCompany $invoice_company
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
|
|
@ -144,7 +144,7 @@ class InvoiceCompanyController extends BackendController
|
|||
InvoiceCompany $invoice_company
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return DB::transaction(function () use ($request, $invoice_company) {
|
||||
$invoice_company->inertiaFill($request->validated());
|
||||
$invoice_company->fill($request->validated());
|
||||
|
||||
if ($invoice_company->saveOrFail()) {
|
||||
return redirect()->route("back.$this->modelName.edit", $invoice_company)
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ class InvoicePackageController extends BackendController
|
|||
$query,
|
||||
$search,
|
||||
null,
|
||||
// TODO: Fields here.
|
||||
'name',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
// TODO: Translations here.
|
||||
trans('validation.attributes.name'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
|
|
@ -104,7 +104,7 @@ class InvoicePackageController extends BackendController
|
|||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$invoice_package = new InvoicePackage();
|
||||
$invoice_package->inertiaFill($request->validated());
|
||||
$invoice_package->fill($request->validated());
|
||||
|
||||
if ($invoice_package->saveOrFail()) {
|
||||
return redirect()->route("back.$this->modelName.edit", $invoice_package)
|
||||
|
|
@ -136,7 +136,7 @@ class InvoicePackageController extends BackendController
|
|||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\InvoicePackages\UpdateInvoicePackageRequest $request
|
||||
* @param \App\Models\InvoicePackage $invoice_package
|
||||
* @param \App\Models\InvoicePackage $invoice_package
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
|
|
@ -144,7 +144,7 @@ class InvoicePackageController extends BackendController
|
|||
InvoicePackage $invoice_package
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return DB::transaction(function () use ($request, $invoice_package) {
|
||||
$invoice_package->inertiaFill($request->validated());
|
||||
$invoice_package->fill($request->validated());
|
||||
|
||||
if ($invoice_package->saveOrFail()) {
|
||||
return redirect()->route("back.$this->modelName.edit", $invoice_package)
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ class NoticeController extends BackendController
|
|||
$query,
|
||||
$search,
|
||||
null,
|
||||
// TODO: Fields here.
|
||||
'title',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
// TODO: Translations here.
|
||||
trans('validation.attributes.title'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
|
|
@ -104,7 +104,7 @@ class NoticeController extends BackendController
|
|||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$notice = new Notice();
|
||||
$notice->inertiaFill($request->validated());
|
||||
$notice->fill($request->validated());
|
||||
|
||||
if ($notice->saveOrFail()) {
|
||||
return redirect()->route("back.$this->modelName.edit", $notice)
|
||||
|
|
@ -136,7 +136,7 @@ class NoticeController extends BackendController
|
|||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\Notices\UpdateNoticeRequest $request
|
||||
* @param \App\Models\Notice $notice
|
||||
* @param \App\Models\Notice $notice
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
|
|
@ -144,7 +144,7 @@ class NoticeController extends BackendController
|
|||
Notice $notice
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return DB::transaction(function () use ($request, $notice) {
|
||||
$notice->inertiaFill($request->validated());
|
||||
$notice->fill($request->validated());
|
||||
|
||||
if ($notice->saveOrFail()) {
|
||||
return redirect()->route("back.$this->modelName.edit", $notice)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class StoreNoticeRequest extends FormRequest
|
|||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'title' => 'required|string|min:3|max:255',
|
||||
'title' => 'required|string|between:3,255',
|
||||
'message' => ['required', 'string', new WysiwygLength()],
|
||||
'type' => ['required', 'integer', new Enum(NoticeTypeEnum::class)],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -10,15 +10,20 @@ class LinkResetPasswordMail extends Mailable
|
|||
{
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param string $url
|
||||
* @param mixed $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
public string $url,
|
||||
public mixed $user,
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope(): \Illuminate\Mail\Mailables\Envelope
|
||||
|
|
@ -35,7 +40,7 @@ class LinkResetPasswordMail extends Mailable
|
|||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content(): \Illuminate\Mail\Mailables\Content
|
||||
|
|
|
|||
|
|
@ -57,4 +57,4 @@ class ResetPassword extends Mailable
|
|||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
use Uwil\LaravelActivityLogs\Traits\HasActivityLog;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasCache;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasModelNaming;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasUwilImages;
|
||||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
|
|
@ -22,10 +21,10 @@ class InvoiceCompany extends Model
|
|||
{
|
||||
use HasActivityLog;
|
||||
use HasCache;
|
||||
/** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Database\Factories\InvoiceCompanyFactory> */
|
||||
use HasFactory;
|
||||
use HasModelNaming;
|
||||
use HasTranslations;
|
||||
use HasUwilImages;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
use Uwil\LaravelActivityLogs\Traits\HasActivityLog;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasCache;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasModelNaming;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasUwilImages;
|
||||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
|
|
@ -24,10 +23,10 @@ class InvoicePackage extends Model
|
|||
{
|
||||
use HasActivityLog;
|
||||
use HasCache;
|
||||
/** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Database\Factories\InvoicePackageFactory> */
|
||||
use HasFactory;
|
||||
use HasModelNaming;
|
||||
use HasTranslations;
|
||||
use HasUwilImages;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
use Uwil\LaravelActivityLogs\Traits\HasActivityLog;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasCache;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasModelNaming;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasUwilImages;
|
||||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
|
|
@ -25,10 +24,10 @@ class Notice extends Model
|
|||
{
|
||||
use HasActivityLog;
|
||||
use HasCache;
|
||||
/** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Database\Factories\NoticeFactory> */
|
||||
use HasFactory;
|
||||
use HasModelNaming;
|
||||
use HasTranslations;
|
||||
use HasUwilImages;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class User extends BackendUser
|
|||
url(route('back.reset-password', ['token' => $token], false)),
|
||||
urlencode($this->getEmailForPasswordReset())
|
||||
);
|
||||
|
||||
|
||||
Mail::send(new LinkResetPasswordMail($url, $this));
|
||||
}
|
||||
|
||||
|
|
@ -52,10 +52,10 @@ class User extends BackendUser
|
|||
/**
|
||||
* Get the user's associated password.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\UserPassword>
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\UserPassword,\App\Models\User>
|
||||
*/
|
||||
public function userPassword(): \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
{
|
||||
return $this->hasOne(UserPassword::class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ namespace App\Models;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property \App\Models\User $user_id User associated.
|
||||
* @property string $password User password.
|
||||
* @property integer $id Id of the user password.
|
||||
* @property \App\Models\User $user_id Associated user.
|
||||
* @property string $password Password of the user.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date on which the password was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date on which the password was updated.
|
||||
*/
|
||||
|
|
@ -22,4 +23,4 @@ class UserPassword extends Model
|
|||
'user_id',
|
||||
'password',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,4 +19,4 @@ class AppServiceProvider extends ServiceProvider
|
|||
UserRoleRegistry::add(4, 'developper', trans('enums.user-role.developper'));
|
||||
UserRoleRegistry::add(5, 'client', trans('enums.user-role.client'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class InvoiceCompanyFactory extends Factory
|
|||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
"name" => fake()->word(),
|
||||
"name" => fake()->words(3, true),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class InvoicePackageFactory extends Factory
|
|||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
"name" => fake()->word(),
|
||||
"name" => fake()->words(3, true),
|
||||
"amount" => fake()->randomFloat(2, 1, 1000),
|
||||
"published" => fake()->boolean(75),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class NoticeFactory extends Factory
|
|||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
"title" => fake()->word(),
|
||||
"title" => fake()->words(3, true),
|
||||
"message" => sprintf("<p>%s</p>", fake()->text(\rand(20, 40))),
|
||||
"type" => fake()->randomElement(NoticeTypeEnum::cases()),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ return new class extends Migration
|
|||
public function up(): void
|
||||
{
|
||||
Schema::create('user_password_reset_tokens', function (Blueprint $table): void {
|
||||
$table->string('email')->primary();
|
||||
$table->string('token');
|
||||
$table->timestamp('created_at')->nullable();
|
||||
$table->string('email')->primary()->comment('Email of the user.');
|
||||
$table->string('token')->comment('Token of the password reset.');
|
||||
$table->timestamp('created_at')->nullable()->comment('Date the reset password was created.');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,25 +3,25 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'failed' => 'Ces identifiants ne correspondent pas à nos enregistrements.',
|
||||
'password' => 'Le mot de passe fourni est incorrect.',
|
||||
'throttle' => 'Tentatives de connexion trop nombreuses. Veuillez réessayer dans :seconds secondes.',
|
||||
"login" => "Se connecter",
|
||||
"remember" => "Se souvenir de moi",
|
||||
"forgot_password" => "Mot de passe oublié",
|
||||
"forgot_password_desc" => "Renseignez votre email pour recevoir un lien de réinitialisation.",
|
||||
"description" => "Connectez-vous afin d'accéder à notre outil <strong>:appName</strong> !",
|
||||
"connected" => "Connecté !",
|
||||
"connected_desc" => "Vous êtes à présent authentifié au Support UWIL.",
|
||||
"send_link" => "Envoyer le lien",
|
||||
"mail_sent" => "Mail envoyé !",
|
||||
"mail_sent_desc" => "Si un compte est associé à l'adresse :email, un e-mail de réinitialisation du mot de passe
|
||||
'failed' => 'Ces identifiants ne correspondent pas à nos enregistrements.',
|
||||
'password' => 'Le mot de passe fourni est incorrect.',
|
||||
'throttle' => 'Tentatives de connexion trop nombreuses. Veuillez réessayer dans :seconds secondes.',
|
||||
"login" => "Se connecter",
|
||||
"remember" => "Se souvenir de moi",
|
||||
"forgot_password" => "Mot de passe oublié",
|
||||
"forgot_password_desc" => "Renseignez votre email pour recevoir un lien de réinitialisation.",
|
||||
"description" => "Connectez-vous afin d'accéder à notre outil <strong>:appName</strong> !",
|
||||
"connected" => "Connecté !",
|
||||
"connected_desc" => "Vous êtes à présent authentifié au Support UWIL.",
|
||||
"send_link" => "Envoyer le lien",
|
||||
"mail_sent" => "Mail envoyé !",
|
||||
"mail_sent_desc" => "Si un compte est associé à l'adresse :email, un e-mail de réinitialisation du mot de passe
|
||||
vous sera envoyé dans quelques instants.",
|
||||
"reset_password" => "Réinitialisation du mot de passe",
|
||||
"reset_password_desc" => "Choisissez un nouveau mot de passe pour votre compte.",
|
||||
"reset_your_password" => "Réinitialiser votre mot de passe",
|
||||
"reset_sent" => "Réinitialisation du mot de passe effectué !",
|
||||
"reset_sent_desc" => "Mot de passe mis à jour avec succès. Vous pouvez dès à présent vous connecter
|
||||
"reset_password" => "Réinitialisation du mot de passe",
|
||||
"reset_password_desc" => "Choisissez un nouveau mot de passe pour votre compte.",
|
||||
"reset_your_password" => "Réinitialiser votre mot de passe",
|
||||
"reset_sent" => "Réinitialisation du mot de passe effectué !",
|
||||
"reset_sent_desc" => "Mot de passe mis à jour avec succès. Vous pouvez dès à présent vous connecter
|
||||
avec vos nouveaux identifiants.",
|
||||
'email_hello' => 'Bonjour !',
|
||||
'email_get_reset_password' => 'Vous recevez cet e-mail parce que nous avons reçu une demande de réinitialisation
|
||||
|
|
|
|||
|
|
@ -982,7 +982,7 @@ export const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|||
}, [minSelection, maxSelection, multiple]);
|
||||
|
||||
return (
|
||||
<div className="w-full flex flex-col w-full justify-start items-start gap-1.5">
|
||||
<div className="w-full flex flex-col justify-start items-start gap-1.5">
|
||||
<div className="sr-only">
|
||||
<div aria-live="polite" aria-atomic="true" role="status">
|
||||
{politeMessage}
|
||||
|
|
@ -1054,143 +1054,159 @@ export const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|||
responsiveSettings.compactMode && "gap-0.5",
|
||||
)}
|
||||
>
|
||||
{selectedValues
|
||||
.slice(0, responsiveSettings.maxCount)
|
||||
.map((value) => {
|
||||
const option = getOptionByValue(value);
|
||||
const IconComponent = option?.icon;
|
||||
const customStyle = option?.style;
|
||||
if (!option) {
|
||||
return null;
|
||||
}
|
||||
const badgeStyle: CSSProperties = {
|
||||
animationDuration: `${animation}s`,
|
||||
...(customStyle?.badgeColor && {
|
||||
backgroundColor: customStyle.badgeColor,
|
||||
}),
|
||||
...(customStyle?.gradient && {
|
||||
background: customStyle.gradient,
|
||||
color: "white",
|
||||
}),
|
||||
};
|
||||
return (
|
||||
<Badge
|
||||
key={value}
|
||||
className={cn(
|
||||
getBadgeAnimationClass(),
|
||||
multiSelectVariants({ variant }),
|
||||
customStyle?.gradient &&
|
||||
"text-white border-transparent",
|
||||
responsiveSettings.compactMode &&
|
||||
"text-xs px-1.5 py-0.5",
|
||||
screenSize === "mobile" &&
|
||||
"max-w-[120px] truncate",
|
||||
singleLine && "flex-shrink-0 whitespace-nowrap",
|
||||
"[&>svg]:pointer-events-auto",
|
||||
)}
|
||||
style={{
|
||||
...badgeStyle,
|
||||
animationDuration: `${
|
||||
animationConfig?.duration || animation
|
||||
}s`,
|
||||
animationDelay: `${animationConfig?.delay || 0}s`,
|
||||
}}
|
||||
>
|
||||
{IconComponent && !responsiveSettings.hideIcons && (
|
||||
<IconComponent
|
||||
{multiple
|
||||
? selectedValues
|
||||
.slice(0, responsiveSettings.maxCount)
|
||||
.map((value) => {
|
||||
const option = getOptionByValue(value);
|
||||
const IconComponent = option?.icon;
|
||||
const customStyle = option?.style;
|
||||
if (!option) {
|
||||
return null;
|
||||
}
|
||||
const badgeStyle: CSSProperties = {
|
||||
animationDuration: `${animation}s`,
|
||||
...(customStyle?.badgeColor && {
|
||||
backgroundColor: customStyle.badgeColor,
|
||||
}),
|
||||
...(customStyle?.gradient && {
|
||||
background: customStyle.gradient,
|
||||
color: "white",
|
||||
}),
|
||||
};
|
||||
return (
|
||||
<Badge
|
||||
key={value}
|
||||
className={cn(
|
||||
"h-4 w-4 mr-2",
|
||||
getBadgeAnimationClass(),
|
||||
multiSelectVariants({ variant }),
|
||||
customStyle?.gradient &&
|
||||
"text-white border-transparent",
|
||||
responsiveSettings.compactMode &&
|
||||
"h-3 w-3 mr-1",
|
||||
customStyle?.iconColor && "text-current",
|
||||
"text-xs px-1.5 py-0.5",
|
||||
screenSize === "mobile" &&
|
||||
"max-w-[120px] truncate",
|
||||
singleLine &&
|
||||
"flex-shrink-0 whitespace-nowrap",
|
||||
"[&>svg]:pointer-events-auto",
|
||||
)}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...(customStyle?.iconColor && {
|
||||
style: {
|
||||
color: customStyle.iconColor,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
<span
|
||||
className={cn(
|
||||
screenSize === "mobile" && "truncate",
|
||||
)}
|
||||
>
|
||||
{option.label}
|
||||
</span>
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
toggleOption(value);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (
|
||||
event.key === "Enter" ||
|
||||
event.key === " "
|
||||
) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
toggleOption(value);
|
||||
}
|
||||
}}
|
||||
aria-label={`Remove ${option.label} from selection`}
|
||||
className="ml-2 h-4 w-4 cursor-pointer hover:bg-white/20 rounded-sm -m-0.5 focus:outline-none focus:ring-1 focus:ring-white/50"
|
||||
>
|
||||
<XCircleIcon
|
||||
className={cn(
|
||||
"h-3 w-3",
|
||||
responsiveSettings.compactMode &&
|
||||
"h-2.5 w-2.5",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</Badge>
|
||||
);
|
||||
})
|
||||
.filter(Boolean)}
|
||||
{selectedValues.length > responsiveSettings.maxCount && (
|
||||
<Badge
|
||||
className={cn(
|
||||
"bg-transparent text-foreground border-foreground/1 hover:bg-transparent",
|
||||
getBadgeAnimationClass(),
|
||||
multiSelectVariants({
|
||||
variant,
|
||||
}),
|
||||
responsiveSettings.compactMode &&
|
||||
"text-xs px-1.5 py-0.5",
|
||||
singleLine && "flex-shrink-0 whitespace-nowrap",
|
||||
"[&>svg]:pointer-events-auto",
|
||||
)}
|
||||
style={{
|
||||
animationDuration: `${animationConfig?.duration || animation}s`,
|
||||
animationDelay: `${animationConfig?.delay || 0}s`,
|
||||
}}
|
||||
>
|
||||
{`+ ${
|
||||
selectedValues.length - responsiveSettings.maxCount
|
||||
} ${transMore}`}
|
||||
<XCircleIcon
|
||||
style={{
|
||||
...badgeStyle,
|
||||
animationDuration: `${
|
||||
animationConfig?.duration || animation
|
||||
}s`,
|
||||
animationDelay: `${animationConfig?.delay || 0}s`,
|
||||
}}
|
||||
>
|
||||
{IconComponent &&
|
||||
!responsiveSettings.hideIcons && (
|
||||
<IconComponent
|
||||
className={cn(
|
||||
"h-4 w-4 mr-2",
|
||||
responsiveSettings.compactMode &&
|
||||
"h-3 w-3 mr-1",
|
||||
customStyle?.iconColor &&
|
||||
"text-current",
|
||||
)}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...(customStyle?.iconColor && {
|
||||
style: {
|
||||
color: customStyle.iconColor,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
<span
|
||||
className={cn(
|
||||
screenSize === "mobile" && "truncate",
|
||||
)}
|
||||
>
|
||||
{option.label}
|
||||
</span>
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
toggleOption(value);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (
|
||||
event.key === "Enter" ||
|
||||
event.key === " "
|
||||
) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
toggleOption(value);
|
||||
}
|
||||
}}
|
||||
aria-label={`Remove ${option.label} from selection`}
|
||||
className="ml-2 h-4 w-4 cursor-pointer hover:bg-white/20 rounded-sm -m-0.5 focus:outline-none focus:ring-1 focus:ring-white/50"
|
||||
>
|
||||
<XCircleIcon
|
||||
className={cn(
|
||||
"h-3 w-3",
|
||||
responsiveSettings.compactMode &&
|
||||
"h-2.5 w-2.5",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</Badge>
|
||||
);
|
||||
})
|
||||
.filter(Boolean)
|
||||
: selectedValues
|
||||
.slice(0, responsiveSettings.maxCount)
|
||||
.map((value) => {
|
||||
const option = getOptionByValue(value);
|
||||
if (!option) {
|
||||
return null;
|
||||
}
|
||||
return <span>{option.label}</span>;
|
||||
})}
|
||||
{multiple &&
|
||||
selectedValues.length > responsiveSettings.maxCount && (
|
||||
<Badge
|
||||
className={cn(
|
||||
"ml-2 h-4 w-4 cursor-pointer",
|
||||
responsiveSettings.compactMode && "ml-1 h-3 w-3",
|
||||
"bg-transparent text-foreground border-foreground/1 hover:bg-transparent",
|
||||
getBadgeAnimationClass(),
|
||||
multiSelectVariants({
|
||||
variant,
|
||||
}),
|
||||
responsiveSettings.compactMode &&
|
||||
"text-xs px-1.5 py-0.5",
|
||||
singleLine && "flex-shrink-0 whitespace-nowrap",
|
||||
"[&>svg]:pointer-events-auto",
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
clearExtraOptions();
|
||||
style={{
|
||||
animationDuration: `${animationConfig?.duration || animation}s`,
|
||||
animationDelay: `${animationConfig?.delay || 0}s`,
|
||||
}}
|
||||
/>
|
||||
</Badge>
|
||||
)}
|
||||
>
|
||||
{`+ ${
|
||||
selectedValues.length - responsiveSettings.maxCount
|
||||
} ${transMore}`}
|
||||
<XCircleIcon
|
||||
className={cn(
|
||||
"ml-2 h-4 w-4 cursor-pointer",
|
||||
responsiveSettings.compactMode && "ml-1 h-3 w-3",
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
clearExtraOptions();
|
||||
}}
|
||||
/>
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<Button
|
||||
type="button"
|
||||
role="button"
|
||||
variant="ghost"
|
||||
tabIndex={0}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
handleClear();
|
||||
}}
|
||||
|
|
@ -1218,7 +1234,7 @@ export const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-between w-full mx-auto gap-2">
|
||||
<p className="text-start text-sm whitespace-pre-line">
|
||||
<p className="text-start text-sm text-muted-foreground whitespace-pre-line">
|
||||
{placeholder}
|
||||
</p>
|
||||
<ChevronsUpDownIcon className="h-4 cursor-pointer opacity-50 group-hover/button:opacity-60" />
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {
|
|||
ChevronDownIcon,
|
||||
MoreHorizontalIcon,
|
||||
HomeIcon,
|
||||
SquareArrowOutUpRightIcon,
|
||||
TelescopeIcon,
|
||||
} from "lucide-react";
|
||||
import { route } from "ziggy-js";
|
||||
|
|
@ -134,7 +133,6 @@ export default function AppSidebar() {
|
|||
// Translations.
|
||||
const transPages = useTrans("uwil-backend::back.pages");
|
||||
const transDashboard = useTrans("uwil-backend::back.dashboard");
|
||||
const transWebsite = useTrans("uwil-backend::back.your_website");
|
||||
const transModules = useTrans("uwil-backend::back.modules");
|
||||
const transAdmin = useTrans("uwil-backend::enums.user-role.admin");
|
||||
const transTelescope = useTrans("uwil-backend::back.telescope");
|
||||
|
|
@ -150,12 +148,6 @@ export default function AppSidebar() {
|
|||
show: true,
|
||||
icon: HomeIcon,
|
||||
},
|
||||
{
|
||||
title: transWebsite,
|
||||
link: "/",
|
||||
show: true,
|
||||
icon: SquareArrowOutUpRightIcon,
|
||||
},
|
||||
...SidebarRegistry.getAll(auth, "pages"),
|
||||
],
|
||||
},
|
||||
|
|
|
|||
7
resources/ts/back/types/global.d.ts
vendored
7
resources/ts/back/types/global.d.ts
vendored
|
|
@ -16,20 +16,17 @@ type DefaultModel = {
|
|||
id: number;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
deleted_at: Date;
|
||||
};
|
||||
|
||||
// User type, with policies.
|
||||
type UserModel = {
|
||||
policies: ModelPolicy;
|
||||
id: number;
|
||||
type UserModel = DefaultModel & {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
role: { value: number; label: string; name: string };
|
||||
published: boolean;
|
||||
published_at: Date;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
};
|
||||
|
||||
// Pagination-related types.
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ const useTrans = (key: string, options: UseTransOptions = {}): string => {
|
|||
const parts = keyword.split("|");
|
||||
if (parts.length !== 2) {
|
||||
throw new Error(
|
||||
"The input string must contain exactly one '|' character.",
|
||||
`The input string '${keyword}' must contain exactly one '|' character.`,
|
||||
);
|
||||
}
|
||||
keyword = choice === 1 ? parts[0].trim() : parts[1].trim();
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
// * Other
|
||||
import { Model } from "@/back/types/global";
|
||||
import { DefaultModel } from "@/back/types/global";
|
||||
|
||||
/**
|
||||
* Extract ids from model relation pivot and format options
|
||||
* for a multi select component.
|
||||
*/
|
||||
export function mapPivotOptions<T extends Model, D extends Model>(
|
||||
export function mapPivotOptions<T extends DefaultModel, D extends DefaultModel>(
|
||||
model: T[],
|
||||
data?: D[],
|
||||
valueKey?: keyof T,
|
||||
|
|
@ -32,7 +32,7 @@ export function mapPivotOptions<T extends Model, D extends Model>(
|
|||
return { options, defaultValue };
|
||||
}
|
||||
|
||||
export function extractIdsFromDatabasePivotRelation<D extends Model>(
|
||||
export function extractIdsFromDatabasePivotRelation<D extends DefaultModel>(
|
||||
data?: D[],
|
||||
): number[] {
|
||||
return data ? data.map((item) => item.id) : [];
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ Route::prefix(config('uwil-backend.routes.prefix'))
|
|||
->name('login');
|
||||
Route::post('login', [AuthenticatedSessionController::class, 'postLogin'])
|
||||
->name('login.post');
|
||||
|
||||
|
||||
Route::get('forgot-password', [AuthenticatedSessionController::class, 'forgotPassword'])
|
||||
->name('forgot-password');
|
||||
Route::post('forgot-password', [AuthenticatedSessionController::class, 'postForgotPassword'])
|
||||
->name('forgot-password.post');
|
||||
|
||||
|
||||
Route::get('reset-password/{token}', [AuthenticatedSessionController::class, 'resetPassword'])
|
||||
->name('reset-password');
|
||||
Route::post('reset-password', [AuthenticatedSessionController::class, 'postResetPassword'])
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Set specific back routes here.
|
||||
// ex: Route::resource('stories', OriginalStoryController::class);.
|
||||
|
|
@ -1 +0,0 @@
|
|||
<?php
|
||||
|
|
@ -13,15 +13,18 @@ Breadcrumbs::for('back.invoice-companies.index', function (Generator $trail) {
|
|||
Breadcrumbs::for('back.invoice-companies.create', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-companies.index');
|
||||
$trail->push(
|
||||
Str::ucfirst(trans_choice('models.classes.invoice-companies', 1)),
|
||||
route('back.invoice-companies.create')
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.create')),
|
||||
route('back.invoice-companies.create'),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.invoice-companies.edit', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-companies.index');
|
||||
$trail->push(Str::ucfirst(trans('uwil-backend::crud.actions.edit')), route('back.invoice-companies.edit', [
|
||||
'invoice_company' => request()->invoice_company
|
||||
]));
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.edit')),
|
||||
route('back.invoice-companies.edit', [
|
||||
'invoice_company' => request()->invoice_company,
|
||||
]),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.invoice-companies.duplicate', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-companies.index');
|
||||
|
|
@ -29,9 +32,12 @@ Breadcrumbs::for('back.invoice-companies.duplicate', function (Generator $trail)
|
|||
});
|
||||
Breadcrumbs::for('back.invoice-companies.show', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-companies.index');
|
||||
$trail->push(Str::ucfirst(trans('uwil-backend::crud.actions.visualize')), route('back.invoice-companies.show', [
|
||||
'invoice_company' => request()->invoice_company
|
||||
]));
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.visualize')),
|
||||
route('back.invoice-companies.show', [
|
||||
'invoice_company' => request()->invoice_company,
|
||||
]),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.invoice-companies.trash', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-companies.index');
|
||||
|
|
|
|||
|
|
@ -13,15 +13,18 @@ Breadcrumbs::for('back.invoice-packages.index', function (Generator $trail) {
|
|||
Breadcrumbs::for('back.invoice-packages.create', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-packages.index');
|
||||
$trail->push(
|
||||
Str::ucfirst(trans_choice('models.classes.invoice-packages', 1)),
|
||||
route('back.invoice-packages.create')
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.create')),
|
||||
route('back.invoice-packages.create'),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.invoice-packages.edit', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-packages.index');
|
||||
$trail->push(Str::ucfirst(trans('uwil-backend::crud.actions.edit')), route('back.invoice-packages.edit', [
|
||||
'invoice_package' => request()->invoice_package
|
||||
]));
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.edit')),
|
||||
route('back.invoice-packages.edit', [
|
||||
'invoice_package' => request()->invoice_package,
|
||||
]),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.invoice-packages.duplicate', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-packages.index');
|
||||
|
|
@ -29,9 +32,12 @@ Breadcrumbs::for('back.invoice-packages.duplicate', function (Generator $trail)
|
|||
});
|
||||
Breadcrumbs::for('back.invoice-packages.show', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-packages.index');
|
||||
$trail->push(Str::ucfirst(trans('uwil-backend::crud.actions.visualize')), route('back.invoice-packages.show', [
|
||||
'invoice_package' => request()->invoice_package
|
||||
]));
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.visualize')),
|
||||
route('back.invoice-packages.show', [
|
||||
'invoice_package' => request()->invoice_package,
|
||||
])
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.invoice-packages.trash', function (Generator $trail) {
|
||||
$trail->parent('back.invoice-packages.index');
|
||||
|
|
|
|||
|
|
@ -13,15 +13,18 @@ Breadcrumbs::for('back.notices.index', function (Generator $trail) {
|
|||
Breadcrumbs::for('back.notices.create', function (Generator $trail) {
|
||||
$trail->parent('back.notices.index');
|
||||
$trail->push(
|
||||
Str::ucfirst(trans_choice('models.classes.notices', 1)),
|
||||
route('back.notices.create')
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.create')),
|
||||
route('back.notices.create'),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.notices.edit', function (Generator $trail) {
|
||||
$trail->parent('back.notices.index');
|
||||
$trail->push(Str::ucfirst(trans('uwil-backend::crud.actions.edit')), route('back.notices.edit', [
|
||||
'notice' => request()->notice
|
||||
]));
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.edit')),
|
||||
route('back.notices.edit', [
|
||||
'notice' => request()->notice,
|
||||
]),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.notices.duplicate', function (Generator $trail) {
|
||||
$trail->parent('back.notices.index');
|
||||
|
|
@ -29,9 +32,12 @@ Breadcrumbs::for('back.notices.duplicate', function (Generator $trail) {
|
|||
});
|
||||
Breadcrumbs::for('back.notices.show', function (Generator $trail) {
|
||||
$trail->parent('back.notices.index');
|
||||
$trail->push(Str::ucfirst(trans('uwil-backend::crud.actions.visualize')), route('back.notices.show', [
|
||||
'notice' => request()->notice
|
||||
]));
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.visualize')),
|
||||
route('back.notices.show', [
|
||||
'notice' => request()->notice,
|
||||
]),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('back.notices.trash', function (Generator $trail) {
|
||||
$trail->parent('back.notices.index');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue