fix: CORS for localhost:3000, login with username or email, favicon
Made-with: Cursor
This commit is contained in:
@@ -18,7 +18,18 @@ export const config = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
cors: {
|
cors: {
|
||||||
origin: process.env.CORS_ORIGIN?.split(',') || ['http://localhost:3000'],
|
origin: (() => {
|
||||||
|
const envOrigins = process.env.CORS_ORIGIN?.split(',').map((o) => o.trim()).filter(Boolean);
|
||||||
|
const defaults = ['http://localhost:3000', 'http://localhost:5173'];
|
||||||
|
const origins = envOrigins?.length ? envOrigins : defaults;
|
||||||
|
// In development, always allow both common dev server origins
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
['http://localhost:3000', 'http://localhost:5173'].forEach((o) => {
|
||||||
|
if (!origins.includes(o)) origins.push(o);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return origins;
|
||||||
|
})(),
|
||||||
},
|
},
|
||||||
|
|
||||||
upload: {
|
upload: {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ router.post(
|
|||||||
router.post(
|
router.post(
|
||||||
'/login',
|
'/login',
|
||||||
[
|
[
|
||||||
body('email').isEmail().withMessage('البريد الإلكتروني غير صالح'),
|
body('email').trim().notEmpty().withMessage('البريد الإلكتروني أو اسم المستخدم مطلوب'),
|
||||||
body('password').notEmpty().withMessage('كلمة المرور مطلوبة'),
|
body('password').notEmpty().withMessage('كلمة المرور مطلوبة'),
|
||||||
],
|
],
|
||||||
validate,
|
validate,
|
||||||
|
|||||||
BIN
frontend/public/favicon.ico
Normal file
BIN
frontend/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -21,6 +21,9 @@ const readexPro = Readex_Pro({
|
|||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'ATMATA - نظام إدارة علاقات العملاء',
|
title: 'ATMATA - نظام إدارة علاقات العملاء',
|
||||||
description: 'Enterprise CRM System for Contact Management, Sales, HR, Inventory, Projects, and Marketing',
|
description: 'Enterprise CRM System for Contact Management, Sales, HR, Inventory, Projects, and Marketing',
|
||||||
|
icons: {
|
||||||
|
icon: '/favicon.ico',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { LogIn, Mail, Lock, Building2, AlertCircle } from 'lucide-react'
|
|||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
const { login } = useAuth()
|
const { login } = useAuth()
|
||||||
const [email, setEmail] = useState('')
|
const [emailOrUsername, setEmailOrUsername] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
@@ -18,7 +18,7 @@ export default function LoginPage() {
|
|||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await login(email, password)
|
await login(emailOrUsername, password)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setError(err.message || 'فشل تسجيل الدخول. الرجاء المحاولة مرة أخرى.')
|
setError(err.message || 'فشل تسجيل الدخول. الرجاء المحاولة مرة أخرى.')
|
||||||
} finally {
|
} finally {
|
||||||
@@ -50,20 +50,21 @@ export default function LoginPage() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="space-y-6">
|
<form onSubmit={handleSubmit} className="space-y-6">
|
||||||
{/* Email Field */}
|
{/* Email or Username Field */}
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="email" className="block text-sm font-semibold text-gray-700 mb-2">
|
<label htmlFor="emailOrUsername" className="block text-sm font-semibold text-gray-700 mb-2">
|
||||||
البريد الإلكتروني
|
البريد الإلكتروني أو اسم المستخدم
|
||||||
</label>
|
</label>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-400" />
|
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-400" />
|
||||||
<input
|
<input
|
||||||
id="email"
|
id="emailOrUsername"
|
||||||
type="email"
|
type="text"
|
||||||
value={email}
|
value={emailOrUsername}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
onChange={(e) => setEmailOrUsername(e.target.value)}
|
||||||
required
|
required
|
||||||
placeholder="example@atmata.com"
|
placeholder="admin أو example@atmata.com"
|
||||||
|
autoComplete="username"
|
||||||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all"
|
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user