aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/config/db.js2
-rw-r--r--server/models/User.js14
-rw-r--r--server/routes/auth.js63
-rw-r--r--server/server.js20
-rw-r--r--src/App.js21
-rw-r--r--src/components/Dashboard.js83
-rw-r--r--src/components/Login.js39
-rw-r--r--src/components/PrivateRoute.js17
-rw-r--r--src/firebase/firebaseConfig.js20
-rw-r--r--src/index.js16
10 files changed, 194 insertions, 101 deletions
diff --git a/server/config/db.js b/server/config/db.js
index c1f628a..9ae3c6b 100644
--- a/server/config/db.js
+++ b/server/config/db.js
@@ -1,4 +1,6 @@
const mongoose = require('mongoose');
+require('dotenv').config();
+
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URI, {
diff --git a/server/models/User.js b/server/models/User.js
index 6773c64..968673e 100644
--- a/server/models/User.js
+++ b/server/models/User.js
@@ -1,7 +1,15 @@
const mongoose = require('mongoose');
+
const UserSchema = new mongoose.Schema({
- username: { type: String, reauired: true, unique: true },
- password: { type: String, required: true },
- role: { type: String, default: 'admin' },
+ email: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ password: {
+ type: String,
+ required: true,
+ },
});
+
module.exports = mongoose.model('User', UserSchema);
diff --git a/server/routes/auth.js b/server/routes/auth.js
index 3fb0986..04a9d5b 100644
--- a/server/routes/auth.js
+++ b/server/routes/auth.js
@@ -1,57 +1,46 @@
const express = require('express');
const bcrypt = require('bcryptjs');
-const jwt = require('jsonwebtoken');
+const jwt = require('jwt-simple');
const User = require('../models/User');
+require('dotenv').config();
+
const router = express.Router();
+const secret = process.env.JWT_SECRET;
-// Register
+// Register new user
router.post('/register', async (req, res) => {
- const { username, password } = req.body;
+ const { email, password } = req.body;
try {
- let user = await User.findOne({ username });
- if (user) {
- return res.status(400).json({ msg: 'User already exists' });
- }
- user = new User({
- username,
- password,
- });
+ const user = await User.findOne({ email });
+ if (user) return res.status(400).json({ msg: 'User already exists' });
+
+ const newUser = new User({ email, password });
const salt = await bcrypt.genSalt(10);
- user.password = await bcrypt.hash(password, salt);
- await user.save();
- res.status(200).send('User registered');
+ newUser.password = await bcrypt.hash(password, salt);
+ await newUser.save();
+
+ const payload = { id: newUser.id };
+ const token = jwt.encode(payload, secret);
+ res.json({ token });
} catch (err) {
console.error(err.message);
res.status(500).send('Server error');
}
});
-// Login
+// Login user
router.post('/login', async (req, res) => {
- const { username, password } = req.body;
+ const { email, password } = req.body;
try {
- const user = await User.findOne({ username });
- if (!user) {
- return res.status(400).json({ msg: 'Invalid credentials' });
- }
+ const user = await User.findOne({ email });
+ if (!user) return res.status(400).json({ msg: 'Invalid credentials' });
+
const isMatch = await bcrypt.compare(password, user.password);
- if (!isMatch) {
- return res.status(400).json({ msg: 'Invalid credentials' });
- }
- const payload = {
- user: {
- id: user.id,
- },
- };
- jwt.sign(
- payload,
- process.env.JWT_SECRET,
- { expiresIn: '1h' },
- (err, token) => {
- if (err) throw err;
- res.json({ token });
- }
- );
+ if (!isMatch) return res.status(400).json({ msg: 'Invalid credentials' });
+
+ const payload = { id: user.id };
+ const token = jwt.encode(payload, secret);
+ res.json({ token });
} catch (err) {
console.error(err.message);
res.status(500).send('Server error');
diff --git a/server/server.js b/server/server.js
index caf4d9c..fcd02f6 100644
--- a/server/server.js
+++ b/server/server.js
@@ -1,14 +1,22 @@
const express = require('express');
-const connectDB = require('./config/db');
const cors = require('cors');
-const app = express();
+const bodyParser = require('body-parser');
+const connectDB = require('./config/db');
+const authRoutes = require('./routes/auth');
+
require('dotenv').config();
-connectDB();
+const app = express();
+const PORT = process.env.PORT || 8080;
+
+// Middleware
app.use(cors());
-app.use(express.json());
+app.use(bodyParser.json());
-app.use('/api/auth', require('./routes/auth'));
+// Connect to MongoDB
+connectDB();
+
+// Routes
+app.use('/api/auth', authRoutes);
-const PORT = process.env.PORT || 8080;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
diff --git a/src/App.js b/src/App.js
index ffc907d..437278a 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,19 +1,18 @@
-import React, { useState } from 'react';
+import React from 'react';
+import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Login from './components/Login';
+import Dashboard from './components/Dashboard';
+import PrivateRoute from './components/PrivateRoute';
const App = () => {
- const [isAuth, setIsAuth] = useState(false);
-
return (
- <div className="App">
- {isAuth ? <AdminPanel /> : <Login setAuth={setIsAuth} />}
- </div>
+ <Router>
+ <Switch>
+ <Route path="/login" component={Login} />
+ <PrivateRoute path="/dashboard" component={Dashboard} />
+ </Switch>
+ </Router>
);
};
-const AdminPanel = () => {
- // Admin panel logic
- return <div>Admin Panel</div>;
-};
-
export default App;
diff --git a/src/components/Dashboard.js b/src/components/Dashboard.js
new file mode 100644
index 0000000..cb14e26
--- /dev/null
+++ b/src/components/Dashboard.js
@@ -0,0 +1,83 @@
+import React, { useState, useEffect } from 'react';
+import { useHistory } from 'react-router-dom';
+import { auth, firestore } from '../firebase/firebaseConfig';
+import { getStorage, ref, uploadBytes, deleteObject } from "firebase/storage";
+import { collection, getDocs, addDoc, deleteDoc, doc } from "firebase/firestore";
+import { Bar } from 'react-chartjs-2';
+
+const Dashboard = () => {
+ const history = useHistory();
+ const [ads, setAds] = useState([]);
+ const [views, setViews] = useState([]);
+ const storage = getStorage();
+ const adsCollectionRef = collection(firestore, "ads");
+
+ useEffect(() => {
+ const fetchAds = async () => {
+ const adsSnapshot = await getDocs(adsCollectionRef);
+ setAds(adsSnapshot.docs.map(doc => ({ ...doc.data(), id: doc.id })));
+ };
+
+ const fetchViews = async () => {
+ // Assume we have a 'views' collection to track ad views
+ const viewsSnapshot = await getDocs(collection(firestore, "views"));
+ setViews(viewsSnapshot.docs.map(doc => doc.data()));
+ };
+
+ fetchAds();
+ fetchViews();
+ }, []);
+
+ const handleLogout = () => {
+ auth.signOut();
+ localStorage.removeItem('token');
+ history.push('/login');
+ };
+
+ const handleUpload = async (event) => {
+ const file = event.target.files[0];
+ const storageRef = ref(storage, `ads/${file.name}`);
+ await uploadBytes(storageRef, file);
+ await addDoc(adsCollectionRef, { name: file.name, url: `ads/${file.name}` });
+ setAds([...ads, { name: file.name, url: `ads/${file.name}` }]);
+ };
+
+ const handleDelete = async (id, url) => {
+ const storageRef = ref(storage, url);
+ await deleteObject(storageRef);
+ await deleteDoc(doc(firestore, "ads", id));
+ setAds(ads.filter(ad => ad.id !== id));
+ };
+
+ const viewData = {
+ labels: ads.map(ad => ad.name),
+ datasets: [
+ {
+ label: 'Ad Views',
+ data: views.map(view => view.count),
+ backgroundColor: 'rgba(75, 192, 192, 0.6)',
+ },
+ ],
+ };
+
+ return (
+ <div>
+ <h2>Dashboard</h2>
+ <button onClick={handleLogout}>Logout</button>
+ <input type="file" onChange={handleUpload} />
+ <div>
+ {ads.map(ad => (
+ <div key={ad.id}>
+ <p>{ad.name}</p>
+ <button onClick={() => handleDelete(ad.id, ad.url)}>Delete</button>
+ </div>
+ ))}
+ </div>
+ <div>
+ <Bar data={viewData} />
+ </div>
+ </div>
+ );
+};
+
+export default Dashboard;
diff --git a/src/components/Login.js b/src/components/Login.js
index 9a67051..64539c6 100644
--- a/src/components/Login.js
+++ b/src/components/Login.js
@@ -1,33 +1,32 @@
import React, { useState } from 'react';
import axios from 'axios';
+import { useHistory } from 'react-router-dom';
-const Login = ({ setAuth }) => {
- const [formData, setFormData] = useState({
- username: '',
- password: '',
- });
+const Login = () => {
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const history = useHistory();
- const { username, password } = formData;
-
- const onChange = (e) => setFormData({ ...formData, [e.target.name]: e.target.value });
-
- const onSubmit = async (e) => {
+ const handleSubmit = async (e) => {
e.preventDefault();
try {
- const res = await axios.post('/api/auth/login', formData);
- localStorage.setItem('token', res.data.token);
- setAuth(true);
- } catch (err) {
- console.error(err.response.data);
+ const response = await axios.post('/api/auth/login', { email, password });
+ localStorage.setItem('token', response.data.token);
+ history.push('/dashboard');
+ } catch (error) {
+ console.error('Error logging in:', error);
}
};
return (
- <form onSubmit={onSubmit}>
- <input type="text" name="username" value={username} onChange={onChange} required />
- <input type="password" name="password" value={password} onChange={onChange} required />
- <button type="submit">Login</button>
- </form>
+ <div>
+ <h2>Login</h2>
+ <form onSubmit={handleSubmit}>
+ <input type="email" placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} required />
+ <input type="password" placeholder="Password" value={password} onChange={(e) => setPassword(e.target.value)} required />
+ <button type="submit">Login</button>
+ </form>
+ </div>
);
};
diff --git a/src/components/PrivateRoute.js b/src/components/PrivateRoute.js
new file mode 100644
index 0000000..1296935
--- /dev/null
+++ b/src/components/PrivateRoute.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import { Route, Redirect } from 'react-router-dom';
+
+const PrivateRoute = ({ component: Component, ...rest }) => {
+ const isAuthenticated = !!localStorage.getItem('token');
+
+ return (
+ <Route
+ {...rest}
+ render={(props) =>
+ isAuthenticated ? <Component {...props} /> : <Redirect to="/login" />
+ }
+ />
+ );
+};
+
+export default PrivateRoute;
diff --git a/src/firebase/firebaseConfig.js b/src/firebase/firebaseConfig.js
index 12f2a35..87546fd 100644
--- a/src/firebase/firebaseConfig.js
+++ b/src/firebase/firebaseConfig.js
@@ -1,17 +1,17 @@
import firebase from 'firebase/app';
-import 'firebase/storage';
+import 'firebase/auth';
+import 'firebase/firestore';
const firebaseConfig = {
- apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
- authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
- projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
- storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
- messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
- appId: process.env.REACT_APP_FIREBASE_APP_ID,
+ apiKey: "YOUR_API_KEY",
+ authDomain: "YOUR_AUTH_DOMAIN",
+ projectId: "YOUR_PROJECT_ID",
+ storageBucket: "YOUR_STORAGE_BUCKET",
+ messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
+ appId: "YOUR_APP_ID"
};
firebase.initializeApp(firebaseConfig);
-const storage = firebase.storage();
-
-export { storage, firebase as default };
+export const auth = firebase.auth();
+export const firestore = firebase.firestore();
diff --git a/src/index.js b/src/index.js
index d563c0f..b597a44 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,17 +1,5 @@
import React from 'react';
-import ReactDOM from 'react-dom/client';
-import './index.css';
+import ReactDOM from 'react-dom';
import App from './App';
-import reportWebVitals from './reportWebVitals';
-const root = ReactDOM.createRoot(document.getElementById('root'));
-root.render(
- <React.StrictMode>
- <App />
- </React.StrictMode>
-);
-
-// If you want to start measuring performance in your app, pass a function
-// to log results (for example: reportWebVitals(console.log))
-// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
-reportWebVitals();
+ReactDOM.render(<App />, document.getElementById('root'));