Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions client/src/components/PasswordInput.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { useState } from "react";

const PasswordInput = ({ value, onChange, placeholder = "Password", name, required = true, className = "" }) => {
const [show, setShow] = useState(false);

return (
<div className="relative w-full">
<input
type={show ? "text" : "password"}
value={value}
onChange={onChange}
placeholder={placeholder}
name={name}
required={required}
className={`p-3 border border-gray-300 dark:border-gray-600 rounded w-full text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 bg-white dark:bg-gray-900 pr-12 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all duration-150 ${className}`}
autoComplete="new-password"
/>
<button
type="button"
tabIndex={-1}
onClick={() => setShow((s) => !s)}
className="absolute inset-y-0 right-0 flex items-center justify-center bg-transparent border-none focus:outline-none z-50 min-w-0 min-h-0 p-0 overflow-visible mr-2"
aria-label={show ? "Hide password" : "Show password"}
>
{show ? (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" className="text-gray-900 dark:text-white" style={{display:'block'}}>
<path d="M1 12C2.73 7.61 7 4.5 12 4.5c5 0 9.27 3.11 11 7.5-1.73 4.39-6 7.5-11 7.5-5 0-9.27-3.11-11-7.5z" fill="currentColor"/>
<circle cx="12" cy="12" r="3.5" fill="#fff"/>
<circle cx="12" cy="12" r="2" fill="currentColor"/>
<line x1="3" y1="3" x2="21" y2="21" stroke="currentColor" strokeWidth="2" style={{display: show ? 'block' : 'none'}}/>
</svg>
) : (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" className="text-gray-900 dark:text-white" style={{display:'block'}}>
<path d="M1 12C2.73 7.61 7 4.5 12 4.5c5 0 9.27 3.11 11 7.5-1.73 4.39-6 7.5-11 7.5-5 0-9.27-3.11-11-7.5z" fill="currentColor"/>
<circle cx="12" cy="12" r="3.5" fill="#fff"/>
<circle cx="12" cy="12" r="2" fill="currentColor"/>
</svg>
)}
</button>
</div>
);
};

export default PasswordInput;
7 changes: 4 additions & 3 deletions client/src/pages/ForgotPassword.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ export default function ForgotPassword() {

return (
<div className="auth-page-bg flex items-center justify-center min-h-screen px-4">
<div className="max-w-md w-full p-8 bg-white rounded-lg shadow-xl border border-gray-200">
<h2 className="text-3xl font-bold mb-6 text-center text-gray-900">Forgot Password</h2>
<div className="max-w-md w-full p-8 bg-white dark:bg-gray-950 rounded-lg shadow-xl border border-gray-200 dark:border-gray-800">
<h2 className="text-3xl font-bold mb-6 text-center text-gray-900 dark:text-white">Forgot Password</h2>
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
<input
type="email"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
className="p-3 border border-gray-300 rounded text-gray-900 placeholder-gray-400"
className="p-3 border border-gray-300 rounded text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-gray-500 dark:bg-gray-950"

/>
{message && <p className="text-green-600">{message}</p>}
{error && <p className="text-red-600">{error}</p>}
Expand Down
28 changes: 14 additions & 14 deletions client/src/pages/LoginPage.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { useNavigate, Link } from "react-router-dom";
import PasswordInput from "../components/PasswordInput";

function LoginPage() {
const navigate = useNavigate();
Expand Down Expand Up @@ -49,38 +50,37 @@ function LoginPage() {
};

return (
<div className="auth-page-bg flex items-center justify-center min-h-screen px-4">
<div className="max-w-md w-full p-8 bg-white rounded-lg shadow-xl border border-gray-200">
<h2 className="text-3xl font-bold mb-6 text-center text-gray-900">
<div className="flex items-center justify-center min-h-screen px-4 bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 dark:from-gray-900 dark:via-gray-800 dark:to-gray-900">
<div className="max-w-md w-full p-8 bg-white dark:bg-gray-950 rounded-2xl shadow-2xl border border-gray-200 dark:border-gray-800">
<h2 className="text-3xl font-extrabold mb-8 text-center text-gray-900 dark:text-white tracking-tight">
Login to SentiLog
</h2>
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
<form onSubmit={handleSubmit} className="flex flex-col gap-6">
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
className="p-3 border border-gray-300 rounded text-gray-900 placeholder-gray-400"
className="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-900 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all duration-150"
/>
<input
type="password"
placeholder="Password"
<PasswordInput
value={password}
onChange={(e) => setPassword(e.target.value)}
required
className="p-3 border border-gray-300 rounded text-gray-900 placeholder-gray-400"
placeholder="Password"
name="password"
className="w-full"
/>
{error && <p className="text-red-600">{error}</p>}
{error && <p className="text-red-500 text-center font-medium">{error}</p>}
<button
type="submit"
className="w-full bg-blue-600 text-white py-3 rounded hover:bg-blue-700 transition"
className="w-full bg-blue-600 dark:bg-blue-700 text-white py-3 rounded-lg font-semibold hover:bg-blue-700 dark:hover:bg-blue-800 transition-all duration-150 shadow-md"
>
Login
</button>
</form>
<div style={{ textAlign: 'right', marginBottom: '10px' }}>
<Link to="/forgot-password">Forgot Password?</Link>
<div className="text-right mt-2 mb-2">
<Link to="/forgot-password" className="text-blue-600 dark:text-blue-400 hover:underline font-semibold">Forgot Password?</Link>
</div>
</div>
</div>
Expand Down
19 changes: 7 additions & 12 deletions client/src/pages/ResetPassword.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
import PasswordInput from '../components/PasswordInput';
import { useSearchParams, useNavigate } from 'react-router-dom';
import axios from 'axios';

Expand Down Expand Up @@ -30,32 +31,26 @@ export default function ResetPassword() {
setTimeout(() => navigate('/login'), 2000);
} catch (err) {
setError(err.response?.data?.message || 'Something went wrong');
if (import.meta.env.MODE !== "production") {
console.error("Network error during password reset:", err);
}
}
};

return (
<div className="auth-page-bg flex items-center justify-center min-h-screen px-4">
<div className="max-w-md w-full p-8 bg-white rounded-lg shadow-xl border border-gray-200">
<div className="max-w-md w-full p-8 bg-white dark:bg-gray-950 rounded-lg shadow-xl border border-gray-200 dark:border-gray-800">
<h2 className="text-3xl font-bold mb-6 text-center text-gray-900">Reset Password</h2>
<form onSubmit={handleReset} className="flex flex-col gap-5">
<input
type="password"
<PasswordInput
placeholder="New Password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
required
className="p-3 border border-gray-300 rounded"
name="newPassword"
className="mb-2"
/>
<input
type="password"
<PasswordInput
placeholder="Confirm Password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
className="p-3 border border-gray-300 rounded"
name="confirmPassword"
/>
{message && <p className="text-green-600">{message}</p>}
{error && <p className="text-red-600">{error}</p>}
Expand Down
35 changes: 16 additions & 19 deletions client/src/pages/SignupPage.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { useNavigate, Link } from "react-router-dom";
import PasswordInput from "../components/PasswordInput";

function SignupPage() {
const navigate = useNavigate();
Expand Down Expand Up @@ -62,20 +63,20 @@ function SignupPage() {
};

return (
<div className="auth-page-bg flex items-center justify-center min-h-screen px-4">
<div className="max-w-md w-full p-8 bg-white rounded-lg shadow-xl border border-gray-200">
<h2 className="text-3xl font-bold mb-6 text-center text-gray-900">
<div className="flex items-center justify-center min-h-screen px-4 bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 dark:from-gray-900 dark:via-gray-800 dark:to-gray-900">
<div className="max-w-md w-full p-8 bg-white dark:bg-gray-950 rounded-2xl shadow-2xl border border-gray-200 dark:border-gray-800">
<h2 className="text-3xl font-extrabold mb-8 text-center text-gray-900 dark:text-white tracking-tight">
Create your account
</h2>
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
<form onSubmit={handleSubmit} className="flex flex-col gap-6">
<input
type="text"
name="firstname"
placeholder="First Name"
value={form.firstname}
onChange={handleChange}
required
className="p-3 border border-gray-300 rounded text-gray-900 placeholder-gray-400"
className="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-900 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all duration-150"
/>
<input
type="text"
Expand All @@ -84,7 +85,7 @@ function SignupPage() {
value={form.lastname}
onChange={handleChange}
required
className="p-3 border border-gray-300 rounded text-gray-900 placeholder-gray-400"
className="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-900 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all duration-150"
/>
<input
type="email"
Expand All @@ -93,31 +94,27 @@ function SignupPage() {
value={form.email}
onChange={handleChange}
required
className="p-3 border border-gray-300 rounded text-gray-900 placeholder-gray-400"
className="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-900 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all duration-150"
/>
<input
type="password"
<PasswordInput
name="password"
placeholder="Password"
value={form.password}
onChange={handleChange}
required
className="p-3 border border-gray-300 rounded"

placeholder="Password"
className="w-full"
/>

{success && <p className="text-green-600">{success}</p>}
{error && <p className="text-red-600">{error}</p>}
{success && <p className="text-green-500 text-center font-medium">{success}</p>}
{error && <p className="text-red-500 text-center font-medium">{error}</p>}
<button
type="submit"
className="w-full bg-blue-600 text-white py-3 rounded hover:bg-blue-700 transition"
className="w-full bg-blue-600 dark:bg-blue-700 text-white py-3 rounded-lg font-semibold hover:bg-blue-700 dark:hover:bg-blue-800 transition-all duration-150 shadow-md"
>
Signup
</button>
</form>
<p className="mt-4 text-center text-gray-700">
<p className="mt-6 text-center text-gray-700 dark:text-gray-300">
Already have an account?{" "}
<Link to="/login" className="text-blue-600 hover:underline">
<Link to="/login" className="text-blue-600 dark:text-blue-400 hover:underline font-semibold">
Login
</Link>
</p>
Expand Down
Loading