veritabanı bağlantısı kur kayıt verilerini orda sakla ve giriş yapanların bilgilerini oradan doğrula
Browse files- login.html +2 -2
- package.json +23 -0
- script.js +96 -19
- server.js +120 -0
- signup.html +2 -2
login.html
CHANGED
|
@@ -35,8 +35,8 @@
|
|
| 35 |
<h1 class="text-2xl font-bold">Welcome Back</h1>
|
| 36 |
<p class="text-white/80">Access your global shopping account</p>
|
| 37 |
</div>
|
| 38 |
-
<form class="p-6">
|
| 39 |
-
|
| 40 |
<label for="email" class="block text-gray-700 text-sm font-medium mb-1">Email Address</label>
|
| 41 |
<input type="email" id="email" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary" required>
|
| 42 |
</div>
|
|
|
|
| 35 |
<h1 class="text-2xl font-bold">Welcome Back</h1>
|
| 36 |
<p class="text-white/80">Access your global shopping account</p>
|
| 37 |
</div>
|
| 38 |
+
<form id="login-form" class="p-6">
|
| 39 |
+
<div class="mb-4">
|
| 40 |
<label for="email" class="block text-gray-700 text-sm font-medium mb-1">Email Address</label>
|
| 41 |
<input type="email" id="email" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary" required>
|
| 42 |
</div>
|
package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
```json
|
| 2 |
+
{
|
| 3 |
+
"name": "bavulumkatar-api",
|
| 4 |
+
"version": "1.0.0",
|
| 5 |
+
"description": "API for BavulumKatar'da",
|
| 6 |
+
"main": "server.js",
|
| 7 |
+
"scripts": {
|
| 8 |
+
"start": "node server.js",
|
| 9 |
+
"dev": "nodemon server.js"
|
| 10 |
+
},
|
| 11 |
+
"dependencies": {
|
| 12 |
+
"bcryptjs": "^2.4.3",
|
| 13 |
+
"cors": "^2.8.5",
|
| 14 |
+
"dotenv": "^16.0.3",
|
| 15 |
+
"express": "^4.18.2",
|
| 16 |
+
"jsonwebtoken": "^9.0.0",
|
| 17 |
+
"mongoose": "^7.3.1"
|
| 18 |
+
},
|
| 19 |
+
"devDependencies": {
|
| 20 |
+
"nodemon": "^2.0.22"
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
```
|
script.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
// Main JavaScript for BavulumKatar'da
|
| 2 |
document.addEventListener('DOMContentLoaded', function() {
|
| 3 |
// Initialize animations
|
|
@@ -7,11 +8,16 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
| 7 |
element.style.animationDelay = `${index * 0.1}s`;
|
| 8 |
});
|
| 9 |
|
| 10 |
-
// Form validation for signup
|
| 11 |
const signupForm = document.getElementById('signup-form');
|
| 12 |
if (signupForm) {
|
| 13 |
-
signupForm.addEventListener('submit', function(e) {
|
| 14 |
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
const password = document.getElementById('password').value;
|
| 16 |
const confirmPassword = document.getElementById('confirmPassword').value;
|
| 17 |
|
|
@@ -25,34 +31,105 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
| 25 |
return;
|
| 26 |
}
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
});
|
| 32 |
}
|
| 33 |
-
|
|
|
|
| 34 |
const loginForm = document.getElementById('login-form');
|
| 35 |
if (loginForm) {
|
| 36 |
-
loginForm.addEventListener('submit', function(e) {
|
| 37 |
e.preventDefault();
|
|
|
|
| 38 |
const email = document.getElementById('email').value;
|
| 39 |
const password = document.getElementById('password').value;
|
| 40 |
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
}
|
| 45 |
-
|
| 46 |
-
// Form is valid, proceed with submission
|
| 47 |
-
alert('Login successful! Redirecting...');
|
| 48 |
-
window.location.href = 'orders.html'; // Redirect to orders page after login
|
| 49 |
});
|
| 50 |
}
|
| 51 |
|
| 52 |
-
//
|
| 53 |
if (window.location.pathname.includes('orders.html')) {
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
}
|
| 58 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
// Main JavaScript for BavulumKatar'da
|
| 3 |
document.addEventListener('DOMContentLoaded', function() {
|
| 4 |
// Initialize animations
|
|
|
|
| 8 |
element.style.animationDelay = `${index * 0.1}s`;
|
| 9 |
});
|
| 10 |
|
| 11 |
+
// Form validation and submission for signup
|
| 12 |
const signupForm = document.getElementById('signup-form');
|
| 13 |
if (signupForm) {
|
| 14 |
+
signupForm.addEventListener('submit', async function(e) {
|
| 15 |
e.preventDefault();
|
| 16 |
+
|
| 17 |
+
const firstName = document.getElementById('firstName').value;
|
| 18 |
+
const lastName = document.getElementById('lastName').value;
|
| 19 |
+
const email = document.getElementById('email').value;
|
| 20 |
+
const phone = document.getElementById('phone').value;
|
| 21 |
const password = document.getElementById('password').value;
|
| 22 |
const confirmPassword = document.getElementById('confirmPassword').value;
|
| 23 |
|
|
|
|
| 31 |
return;
|
| 32 |
}
|
| 33 |
|
| 34 |
+
try {
|
| 35 |
+
const response = await fetch('http://localhost:5000/api/register', {
|
| 36 |
+
method: 'POST',
|
| 37 |
+
headers: {
|
| 38 |
+
'Content-Type': 'application/json'
|
| 39 |
+
},
|
| 40 |
+
body: JSON.stringify({
|
| 41 |
+
firstName,
|
| 42 |
+
lastName,
|
| 43 |
+
email,
|
| 44 |
+
phone,
|
| 45 |
+
password
|
| 46 |
+
})
|
| 47 |
+
});
|
| 48 |
+
|
| 49 |
+
const data = await response.json();
|
| 50 |
+
|
| 51 |
+
if (!response.ok) {
|
| 52 |
+
throw new Error(data.message || 'Registration failed');
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
// Save token and redirect
|
| 56 |
+
localStorage.setItem('token', data.token);
|
| 57 |
+
window.location.href = 'orders.html';
|
| 58 |
+
} catch (err) {
|
| 59 |
+
alert(err.message || 'Registration failed. Please try again.');
|
| 60 |
+
console.error(err);
|
| 61 |
+
}
|
| 62 |
});
|
| 63 |
}
|
| 64 |
+
|
| 65 |
+
// Form validation and submission for login
|
| 66 |
const loginForm = document.getElementById('login-form');
|
| 67 |
if (loginForm) {
|
| 68 |
+
loginForm.addEventListener('submit', async function(e) {
|
| 69 |
e.preventDefault();
|
| 70 |
+
|
| 71 |
const email = document.getElementById('email').value;
|
| 72 |
const password = document.getElementById('password').value;
|
| 73 |
|
| 74 |
+
try {
|
| 75 |
+
const response = await fetch('http://localhost:5000/api/login', {
|
| 76 |
+
method: 'POST',
|
| 77 |
+
headers: {
|
| 78 |
+
'Content-Type': 'application/json'
|
| 79 |
+
},
|
| 80 |
+
body: JSON.stringify({ email, password })
|
| 81 |
+
});
|
| 82 |
+
|
| 83 |
+
const data = await response.json();
|
| 84 |
+
|
| 85 |
+
if (!response.ok) {
|
| 86 |
+
throw new Error(data.message || 'Login failed');
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
// Save token and redirect
|
| 90 |
+
localStorage.setItem('token', data.token);
|
| 91 |
+
window.location.href = 'orders.html';
|
| 92 |
+
} catch (err) {
|
| 93 |
+
alert(err.message || 'Login failed. Please try again.');
|
| 94 |
+
console.error(err);
|
| 95 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
});
|
| 97 |
}
|
| 98 |
|
| 99 |
+
// Check authentication on protected pages
|
| 100 |
if (window.location.pathname.includes('orders.html')) {
|
| 101 |
+
const token = localStorage.getItem('token');
|
| 102 |
+
if (!token) {
|
| 103 |
+
window.location.href = 'login.html';
|
| 104 |
+
return;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
// Fetch user data or orders here
|
| 108 |
+
feather.replace();
|
| 109 |
}
|
| 110 |
+
});
|
| 111 |
+
|
| 112 |
+
// Helper function for authenticated requests
|
| 113 |
+
async function authFetch(url, options = {}) {
|
| 114 |
+
const token = localStorage.getItem('token');
|
| 115 |
+
|
| 116 |
+
if (!token) {
|
| 117 |
+
window.location.href = 'login.html';
|
| 118 |
+
return;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
options.headers = {
|
| 122 |
+
...options.headers,
|
| 123 |
+
'x-auth-token': token
|
| 124 |
+
};
|
| 125 |
+
|
| 126 |
+
const response = await fetch(url, options);
|
| 127 |
+
|
| 128 |
+
if (response.status === 401) {
|
| 129 |
+
localStorage.removeItem('token');
|
| 130 |
+
window.location.href = 'login.html';
|
| 131 |
+
return;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
return response;
|
| 135 |
+
}
|
server.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
require('dotenv').config();
|
| 2 |
+
const express = require('express');
|
| 3 |
+
const mongoose = require('mongoose');
|
| 4 |
+
const bcrypt = require('bcryptjs');
|
| 5 |
+
const cors = require('cors');
|
| 6 |
+
const jwt = require('jsonwebtoken');
|
| 7 |
+
|
| 8 |
+
const app = express();
|
| 9 |
+
|
| 10 |
+
// Middleware
|
| 11 |
+
app.use(cors());
|
| 12 |
+
app.use(express.json());
|
| 13 |
+
|
| 14 |
+
// MongoDB Connection
|
| 15 |
+
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost/bavulumkatar_db', {
|
| 16 |
+
useNewUrlParser: true,
|
| 17 |
+
useUnifiedTopology: true
|
| 18 |
+
})
|
| 19 |
+
.then(() => console.log('MongoDB connected'))
|
| 20 |
+
.catch(err => console.log(err));
|
| 21 |
+
|
| 22 |
+
// User Model
|
| 23 |
+
const UserSchema = new mongoose.Schema({
|
| 24 |
+
firstName: { type: String, required: true },
|
| 25 |
+
lastName: { type: String, required: true },
|
| 26 |
+
email: { type: String, required: true, unique: true },
|
| 27 |
+
phone: { type: String },
|
| 28 |
+
password: { type: String, required: true },
|
| 29 |
+
createdAt: { type: Date, default: Date.now }
|
| 30 |
+
});
|
| 31 |
+
|
| 32 |
+
const User = mongoose.model('User', UserSchema);
|
| 33 |
+
|
| 34 |
+
// Register Endpoint
|
| 35 |
+
app.post('/api/register', async (req, res) => {
|
| 36 |
+
try {
|
| 37 |
+
const { firstName, lastName, email, phone, password } = req.body;
|
| 38 |
+
|
| 39 |
+
// Check if user exists
|
| 40 |
+
const existingUser = await User.findOne({ email });
|
| 41 |
+
if (existingUser) {
|
| 42 |
+
return res.status(400).json({ message: 'Email already exists' });
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
// Hash password
|
| 46 |
+
const salt = await bcrypt.genSalt(10);
|
| 47 |
+
const hashedPassword = await bcrypt.hash(password, salt);
|
| 48 |
+
|
| 49 |
+
// Create user
|
| 50 |
+
const user = new User({
|
| 51 |
+
firstName,
|
| 52 |
+
lastName,
|
| 53 |
+
email,
|
| 54 |
+
phone,
|
| 55 |
+
password: hashedPassword
|
| 56 |
+
});
|
| 57 |
+
|
| 58 |
+
await user.save();
|
| 59 |
+
|
| 60 |
+
// Create token
|
| 61 |
+
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET || 'secret', {
|
| 62 |
+
expiresIn: '30d'
|
| 63 |
+
});
|
| 64 |
+
|
| 65 |
+
res.status(201).json({ token, user: { id: user._id, email: user.email } });
|
| 66 |
+
} catch (err) {
|
| 67 |
+
console.error(err);
|
| 68 |
+
res.status(500).json({ message: 'Server error' });
|
| 69 |
+
}
|
| 70 |
+
});
|
| 71 |
+
|
| 72 |
+
// Login Endpoint
|
| 73 |
+
app.post('/api/login', async (req, res) => {
|
| 74 |
+
try {
|
| 75 |
+
const { email, password } = req.body;
|
| 76 |
+
|
| 77 |
+
// Find user
|
| 78 |
+
const user = await User.findOne({ email });
|
| 79 |
+
if (!user) {
|
| 80 |
+
return res.status(400).json({ message: 'Invalid credentials' });
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
// Check password
|
| 84 |
+
const isMatch = await bcrypt.compare(password, user.password);
|
| 85 |
+
if (!isMatch) {
|
| 86 |
+
return res.status(400).json({ message: 'Invalid credentials' });
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
// Create token
|
| 90 |
+
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET || 'secret', {
|
| 91 |
+
expiresIn: '30d'
|
| 92 |
+
});
|
| 93 |
+
|
| 94 |
+
res.json({ token, user: { id: user._id, email: user.email } });
|
| 95 |
+
} catch (err) {
|
| 96 |
+
console.error(err);
|
| 97 |
+
res.status(500).json({ message: 'Server error' });
|
| 98 |
+
}
|
| 99 |
+
});
|
| 100 |
+
|
| 101 |
+
// Protected Route Example
|
| 102 |
+
app.get('/api/me', async (req, res) => {
|
| 103 |
+
try {
|
| 104 |
+
const token = req.header('x-auth-token');
|
| 105 |
+
if (!token) return res.status(401).json({ message: 'No token, authorization denied' });
|
| 106 |
+
|
| 107 |
+
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'secret');
|
| 108 |
+
const user = await User.findById(decoded.id).select('-password');
|
| 109 |
+
|
| 110 |
+
if (!user) return res.status(404).json({ message: 'User not found' });
|
| 111 |
+
|
| 112 |
+
res.json(user);
|
| 113 |
+
} catch (err) {
|
| 114 |
+
console.error(err);
|
| 115 |
+
res.status(500).json({ message: 'Server error' });
|
| 116 |
+
}
|
| 117 |
+
});
|
| 118 |
+
|
| 119 |
+
const PORT = process.env.PORT || 5000;
|
| 120 |
+
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
|
signup.html
CHANGED
|
@@ -35,8 +35,8 @@
|
|
| 35 |
<h1 class="text-2xl font-bold">Create Your Account</h1>
|
| 36 |
<p class="text-white/80">Join our global shopping community</p>
|
| 37 |
</div>
|
| 38 |
-
<form class="p-6">
|
| 39 |
-
|
| 40 |
<div>
|
| 41 |
<label for="firstName" class="block text-gray-700 text-sm font-medium mb-1">First Name</label>
|
| 42 |
<input type="text" id="firstName" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary" required>
|
|
|
|
| 35 |
<h1 class="text-2xl font-bold">Create Your Account</h1>
|
| 36 |
<p class="text-white/80">Join our global shopping community</p>
|
| 37 |
</div>
|
| 38 |
+
<form id="signup-form" class="p-6">
|
| 39 |
+
<div class="grid grid-cols-2 gap-4 mb-4">
|
| 40 |
<div>
|
| 41 |
<label for="firstName" class="block text-gray-700 text-sm font-medium mb-1">First Name</label>
|
| 42 |
<input type="text" id="firstName" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary" required>
|