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
38 changes: 38 additions & 0 deletions src/client/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
76 changes: 56 additions & 20 deletions src/client/App.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,59 @@
import React, { Component } from 'react';
import './app.css';
import ReactImage from './react.png';
// src/App.jsx
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { CartProvider } from "./context/CartContext";
import { WishlistProvider } from "./context/WishlistContext";
import Header from "./components/Header";
import Footer from "./components/Footer";
import HomePage from "./pages/HomePage";
import ProductsPage from "./pages/ProductsPage";
import ProductDetailPage from "./pages/ProductDetailPage";
import CartPage from "./pages/CartPage";
import LoginPage from "./pages/LoginPage";
import CheckoutPage from "./pages/CheckoutPage";
import WishlistPage from "./pages/WishlistPage";
import AboutPage from "./pages/AboutPage";
import ContactPage from "./pages/ContactPage";
import NotFoundPage from "./pages/NotFoundPage";
import CategoryPage from "./pages/CategoryPage";
import AdminProducts from "./dashboard/adminproducts";
import AdminOrders from "./dashboard/adminorders";

export default class App extends Component {
state = { username: null };
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

componentDidMount() {
fetch('/api/getUsername')
.then(res => res.json())
.then(user => this.setState({ username: user.username }));
}

render() {
const { username } = this.state;
return (
<div>
{username ? <h1>{`Hello ${username}`}</h1> : <h1>Loading.. please wait!</h1>}
<img src={ReactImage} alt="react" />
</div>
);
}
function App() {
return (
<BrowserRouter>
<WishlistProvider>
<CartProvider>
<div className="flex min-h-screen flex-col">
<Header />
<main className="flex-1">
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/products" element={<ProductsPage />} />
<Route path="/products/:slug" element={<ProductDetailPage />} />
<Route path="/cart" element={<CartPage />} />
<Route path="/wishlist" element={<WishlistPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/checkout" element={<CheckoutPage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
<Route path="/categories" element={<CategoryPage />} />
<Route path="*" element={<NotFoundPage />} />
<Route path="/adminproducts" element={<AdminProducts />} />
<Route path="/adminorders" element={<AdminOrders />} />
</Routes>
</main>
<Footer />
<ToastContainer position="top-right" autoClose={3000} />
</div>

</CartProvider>
</WishlistProvider>
</BrowserRouter>

);
}

export default App;
8 changes: 8 additions & 0 deletions src/client/App.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
32 changes: 32 additions & 0 deletions src/client/backend/modules.user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
trim: true,
minlength: 3
},
email: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true
},
password: {
type: String,
required: true,
minlength: 8
},
isAdmin: {
type: Boolean,
default: false
}
}, {
timestamps: true,
collection: 'signup'
});

const User = mongoose.model('User', userSchema);
module.exports = User;
70 changes: 70 additions & 0 deletions src/client/backend/routes/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../modules.user');

router.post('/signup', async (req, res) => {
const { username, email, password } = req.body;
console.log('Signup request:', { username, email, password: '****' });
try {
if (!username || !email || !password) {
return res.status(400).json({ message: 'All fields are required' });
}
if (password.length < 8) {
return res.status(400).json({ message: 'Password must be at least 8 characters' });
}
const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(400).json({ message: 'Email already exists' });
}
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({
username,
email,
password: hashedPassword,
});
await user.save();
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET || 'your-secret-key', {
expiresIn: '1h',
});
res.status(201).json({
token,
user: { id: user._id, username, email, isAdmin: user.isAdmin },
});
} catch (error) {
console.error('Signup error:', error.message);
res.status(500).json({ message: 'Server error', error: error.message });
}
});

router.post('/login', async (req, res) => {
const { email, password, rememberMe } = req.body;
console.log('Login request:', { email, password: '****', rememberMe });
try {
if (!email || !password) {
return res.status(400).json({ message: 'Email and password are required' });
}
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ message: 'Invalid email or password' });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ message: 'Invalid email or password' });
}
const expiresIn = rememberMe ? '7d' : '1h';
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET || 'your-secret-key', {
expiresIn,
});
res.json({
token,
user: { id: user._id, username: user.username, email, isAdmin: user.isAdmin },
});
} catch (error) {
console.error('Login error:', error.message);
res.status(500).json({ message: 'Server error', error: error.message });
}
});

module.exports = router;
46 changes: 46 additions & 0 deletions src/client/backend/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const dotenv = require('dotenv');
const rateLimit = require('express-rate-limit');
const authRoutes = require('./routes/auth');

dotenv.config();
const app = express();

// Update CORS to allow frontend port (e.g., 5173 or 3000)
app.use(cors({ origin: ['http://localhost:3000', 'http://localhost:5173'], credentials: true }));
app.use(express.json());

app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
});

const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: { message: 'Too many login attempts, please try again after 15 minutes' },
});
app.use('/api/auth/login', loginLimiter);

app.use('/api/auth', authRoutes);

app.get('/', (req, res) => {
res.send('Server is running...');
});

mongoose.connect(process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/auth', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log('✅ MongoDB Connected to auth database'))
.catch((error) => {
console.error('❌ MongoDB Connection Error:', error.message);
process.exit(1);
});

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`🚀 Server is running on http://localhost:${PORT}`);
});
Loading