From 76e83eac49441a8069c976b897c8f7d9bbedfbae Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Thu, 21 May 2026 13:27:47 +0200 Subject: [PATCH] feat: :sparkles: add reset password button in crud views --- .../Auth/AuthenticatedSessionController.php | 19 ++++- lang/fr/auth.php | 7 +- .../ts/back/Components/BtnResetPassword.tsx | 75 +++++++++++++++++++ resources/ts/back/Pages/Users/Edit.tsx | 13 +++- resources/ts/back/Pages/Users/Show.tsx | 9 ++- routes/back/users.php | 5 +- 6 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 resources/ts/back/Components/BtnResetPassword.tsx diff --git a/app/Http/Controllers/Auth/AuthenticatedSessionController.php b/app/Http/Controllers/Auth/AuthenticatedSessionController.php index 6079f06..4b6d99c 100644 --- a/app/Http/Controllers/Auth/AuthenticatedSessionController.php +++ b/app/Http/Controllers/Auth/AuthenticatedSessionController.php @@ -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')); } } diff --git a/lang/fr/auth.php b/lang/fr/auth.php index 26f21b8..6f8065b 100644 --- a/lang/fr/auth.php +++ b/lang/fr/auth.php @@ -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.', ]; diff --git a/resources/ts/back/Components/BtnResetPassword.tsx b/resources/ts/back/Components/BtnResetPassword.tsx new file mode 100644 index 0000000..a0d66dd --- /dev/null +++ b/resources/ts/back/Components/BtnResetPassword.tsx @@ -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 ( +
{ + e.preventDefault(); + handleSendResetLink(); + }} + > + + {transResetPassword} + {isSending ? ( + + ) : ( + + )} + + } + tooltipContent={useTrans("auth.send_link")} + disabled={isSending} + variant="secondary" + size="default" + type="submit" + /> + + ); +} diff --git a/resources/ts/back/Pages/Users/Edit.tsx b/resources/ts/back/Pages/Users/Edit.tsx index ff4762f..84ced3f 100644 --- a/resources/ts/back/Pages/Users/Edit.tsx +++ b/resources/ts/back/Pages/Users/Edit.tsx @@ -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 && (
} tooltipContent={

{transBackToList}

} /> @@ -51,11 +52,17 @@ export default function Edit({ ); }; + const afterNode = () => ; + return ( - + diff --git a/resources/ts/back/Pages/Users/Show.tsx b/resources/ts/back/Pages/Users/Show.tsx index afe89ca..742b8c0 100644 --- a/resources/ts/back/Pages/Users/Show.tsx +++ b/resources/ts/back/Pages/Users/Show.tsx @@ -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 = () => ; + return ( - + name('users.send-reset-password-link'); +Route::resource('users', UserController::class); \ No newline at end of file