mirror of
https://github.com/crocofied/CoreControl.git
synced 2025-12-20 17:07:19 +00:00
Last Login saved & Success Messages
This commit is contained in:
parent
7551b0b494
commit
db7af1eba3
@ -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
46
components/Success.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user