feat: ✨ add reset password button in crud views

This commit is contained in:
Alexis Gousseau 2026-05-21 13:27:47 +02:00
parent 6f299846e4
commit 76e83eac49
No known key found for this signature in database
GPG key ID: 7F3C786EE12DBB72
6 changed files with 117 additions and 11 deletions

View file

@ -86,7 +86,22 @@ class AuthenticatedSessionController extends Controller
return $status === Password::RESET_LINK_SENT
? to_route(config('uwil-backend.routes.name') . 'login')
: back();
: back()->with('error', trans('passwords.throttled'));
}
/**
* Send a reset password link to the user.
*
* @param \App\Models\User $user
* @return \Illuminate\Http\RedirectResponse
*/
public function sendResetPasswordLink(User $user): \Illuminate\Http\RedirectResponse
{
$status = Password::broker('backend')->sendResetLink(['email' => $user->email]);
return $status === Password::RESET_LINK_SENT
? back()->with('success', trans('passwords.sent'))
: back()->with('error', trans('passwords.throttled'));
}
/**
@ -130,6 +145,6 @@ class AuthenticatedSessionController extends Controller
return $status === Password::PASSWORD_RESET
? to_route(config('uwil-backend.routes.name') . 'login')
: back();
: back()->with('error', trans('passwords.throttled'));
}
}

View file

@ -17,8 +17,9 @@ return [
"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.",
"mail_sent_user_desc" => "Un e-mail de réinitialisation du mot de passe à été envoyé l'adresse :email.",
'reset_password' => 'Réinitialiser mot de passe',
'reset_password_desc' => 'Formulaire de réinitialisation du mot de passe de votre compte au back office.',
"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
@ -39,6 +40,4 @@ return [
mot de passe en cliquant sur le bouton suivant:',
'email_title_reset_password' => 'Réinitialisation du mot de passe',
'email_title_reset_complete' => 'Mot de passe modifié',
'reset_password' => 'Réinitialiser mot de passe',
'reset_password_desc' => 'Formulaire de réinitialisation du mot de passe de votre compte au back office.',
];

View file

@ -0,0 +1,75 @@
// * Packages
import { router } from "@inertiajs/react";
import { route } from "ziggy-js";
import { LoaderCircleIcon, SendIcon } from "lucide-react";
import { useState } from "react";
// * Other
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import useTrans from "@/hooks/use-translations";
import { useToast } from "@/hooks/use-toast";
import { UserModel } from "@/back/types/global";
export default function BtnResetPassword({ model }: { model: UserModel }) {
const { toast } = useToast();
const [isSending, setIsSending] = useState(false);
// Translations.
const transResetPassword = useTrans("auth.reset_password");
const transMailSent = useTrans("auth.mail_sent");
const transMailSentDesc = useTrans("auth.mail_sent_user_desc", {
params: { email: model.email },
});
const handleSendResetLink = () => {
setIsSending(true);
router.post(
route("back.users.send-reset-password-link", model),
{},
{
onSuccess: () => {
toast({
title: transMailSent,
description: transMailSentDesc,
});
},
onError: () => {
toast({
title: "nope",
description: "nope",
variant: "destructive",
});
},
onFinish: () => {
setIsSending(false);
},
},
);
};
return (
<form
onSubmit={(e) => {
e.preventDefault();
handleSendResetLink();
}}
>
<BtnOptionnalLinkWithTooltip
content={
<>
{transResetPassword}
{isSending ? (
<LoaderCircleIcon className="animate-spin" />
) : (
<SendIcon />
)}
</>
}
tooltipContent={useTrans("auth.send_link")}
disabled={isSending}
variant="secondary"
size="default"
type="submit"
/>
</form>
);
}

View file

@ -6,6 +6,7 @@ import { ArrowLeftIcon } from "lucide-react";
import AuthenticatedLayout from "@/back/Layouts/AuthenticatedLayout";
import ModelActions from "@/back/Components/ModelActions";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import BtnResetPassword from "@/back/Components/BtnResetPassword";
import Form from "@/back/Pages/Users/Form";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
@ -42,7 +43,7 @@ export default function Edit({
viewAny && (
<div className="flex justify-end items-center gap-x-1.5">
<BtnOptionnalLinkWithTooltip
link={route("back.users.index")}
link={route(`back.${modelName}.index`)}
content={<ArrowLeftIcon />}
tooltipContent={<p>{transBackToList}</p>}
/>
@ -51,11 +52,17 @@ export default function Edit({
);
};
const afterNode = () => <BtnResetPassword model={model} />;
return (
<AuthenticatedLayout title={transTitle} beforeNode={beforeNode()}>
<AuthenticatedLayout
title={transTitle}
beforeNode={beforeNode()}
afterNode={afterNode()}
>
<ModelActions
actions={actionModels}
modelRoute="users"
modelRoute={modelName}
model={model}
modelUpdatedAt={model.updated_at.toString()}
/>

View file

@ -21,6 +21,7 @@ import AuthenticatedLayout from "@/back/Layouts/AuthenticatedLayout";
import DetailsTable from "@/back/Components/Table/DetailsTable";
import ModelActions from "@/back/Components/ModelActions";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import BtnResetPassword from "@/back/Components/BtnResetPassword";
import Views from "@/back/lib/actions";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { AuthProp, SingleResource, UserModel } from "@/back/types/global";
@ -299,8 +300,14 @@ export default function Show({
);
};
const afterNode = () => <BtnResetPassword model={model} />;
return (
<AuthenticatedLayout title={transTitle} beforeNode={beforeNode()}>
<AuthenticatedLayout
title={transTitle}
beforeNode={beforeNode()}
afterNode={afterNode()}
>
<ModelActions
actions={actionModels}
modelRoute={modelName}

View file

@ -1,6 +1,9 @@
<?php
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Back\UserController;
use Illuminate\Support\Facades\Route;
Route::resource('users', UserController::class);
Route::post('users/{user}/send-reset-password-link', [AuthenticatedSessionController::class, 'sendResetPasswordLink'])
->name('users.send-reset-password-link');
Route::resource('users', UserController::class);