Last Login saved & Success Messages

This commit is contained in:
headlesdev 2025-05-17 22:01:37 +02:00
parent 7551b0b494
commit db7af1eba3
3 changed files with 104 additions and 38 deletions

View File

@ -39,6 +39,17 @@ export async function POST(request: NextRequest) {
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: body.remember ? "7d" : "1h" }); const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: body.remember ? "7d" : "1h" });
const lastLogin = new Date();
await prisma.user.update({
where: {
id: user.id,
},
data: {
lastLogin,
},
});
return NextResponse.json({ message: "Login successful", token }, { status: 200 }); return NextResponse.json({ message: "Login successful", token }, { status: 200 });
} catch (error: any) { } catch (error: any) {

46
components/Success.tsx Normal file
View File

@ -0,0 +1,46 @@
"use client";
import { useEffect } from "react";
type SuccessToastProps = {
message: string;
show: boolean;
onClose: () => void;
};
export default function SuccessToast({ message, show, onClose }: SuccessToastProps) {
useEffect(() => {
if (show) {
const timer = setTimeout(() => {
onClose();
}, 5000);
return () => clearTimeout(timer);
}
}, [show, onClose]);
if (!show) return null;
return (
<div className="toast toast-end">
<div className="alert alert-success alert-soft">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<div>
<span className="font-bold">SUCCESS: </span>
<span>{message}</span>
</div>
</div>
</div>
);
}

View File

@ -3,11 +3,13 @@
import { useState } from 'react'; import { useState } from 'react';
import axios from 'axios'; import axios from 'axios';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import SuccessToast from '../Success';
export const PasswordSettings = ({ onError }: { onError: (message: string) => void }) => { export const PasswordSettings = ({ onError }: { onError: (message: string) => void }) => {
const [oldPassword, setOldPassword] = useState(''); const [oldPassword, setOldPassword] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [passwordConfirm, setPasswordConfirm] = useState(''); const [passwordConfirm, setPasswordConfirm] = useState('');
const [success, setSuccess] = useState('');
const handleSave = async () => { const handleSave = async () => {
if (password !== passwordConfirm) return onError('Passwords do not match'); if (password !== passwordConfirm) return onError('Passwords do not match');
@ -23,52 +25,59 @@ export const PasswordSettings = ({ onError }: { onError: (message: string) => vo
if (response.data.message !== 'Password updated successfully') { if (response.data.message !== 'Password updated successfully') {
onError('Failed to update password'); onError('Failed to update password');
} }
setSuccess('Password updated successfully');
setOldPassword('');
setPassword('');
setPasswordConfirm('');
} catch (error: any) { } catch (error: any) {
onError(error.response?.data?.error || 'An error occurred'); onError(error.response?.data?.error || 'An error occurred');
} }
}; };
return ( return (
<div className="w-full bg-base-200 p-4 rounded-2xl border border-stone-800"> <div>
<h2 className="text-lg font-bold">Password Settings</h2> <div className="w-full bg-base-200 p-4 rounded-2xl border border-stone-800">
<p className="text-sm opacity-70">Manage your password</p> <h2 className="text-lg font-bold">Password Settings</h2>
<p className="text-sm opacity-70">Manage your password</p>
<div className="flex flex-col gap-4 pt-8">
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-4 pt-8">
<label htmlFor="oldPassword" className="text-sm font-bold">Old Password</label> <div className="flex flex-col gap-2">
<input <label htmlFor="oldPassword" className="text-sm font-bold">Old Password</label>
type="password" <input
id="oldPassword" type="password"
value={oldPassword} id="oldPassword"
onChange={(e) => setOldPassword(e.target.value)} value={oldPassword}
className="input w-full" onChange={(e) => setOldPassword(e.target.value)}
/> className="input w-full"
</div> />
<div className="flex flex-col gap-2"> </div>
<label htmlFor="password" className="text-sm font-bold">Password</label> <div className="flex flex-col gap-2">
<input <label htmlFor="password" className="text-sm font-bold">Password</label>
type="password" <input
id="password" type="password"
value={password} id="password"
onChange={(e) => setPassword(e.target.value)} value={password}
className="input w-full" onChange={(e) => setPassword(e.target.value)}
/> className="input w-full"
</div> />
<div className="flex flex-col gap-2"> </div>
<label htmlFor="passwordConfirm" className="text-sm font-bold">Confirm Password</label> <div className="flex flex-col gap-2">
<input <label htmlFor="passwordConfirm" className="text-sm font-bold">Confirm Password</label>
type="password" <input
id="passwordConfirm" type="password"
value={passwordConfirm} id="passwordConfirm"
onChange={(e) => setPasswordConfirm(e.target.value)} value={passwordConfirm}
className="input w-full" onChange={(e) => setPasswordConfirm(e.target.value)}
/> className="input w-full"
/>
</div>
</div> </div>
<button className="btn btn-primary mt-8 w-full" onClick={handleSave}>
Save Changes
</button>
</div> </div>
<SuccessToast message={success} show={success !== ''} onClose={() => setSuccess('')} />
<button className="btn btn-primary mt-8 w-full" onClick={handleSave}>
Save Changes
</button>
</div> </div>
); );
}; };