Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
MONGO_URI=
JWT_SECRET=
NODE_ENV=
PORT=mongodb+srv://mukeshdhadhariya1_db_user:sKk4J4Rsmt1MzOEL@cluster0.fc8cebb.mongodb.net/
13 changes: 13 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"date-fns": "^4.1.0",
"dotenv": "^17.2.3",
"express": "^5.1.0",
"express-async-handler": "^1.2.0",
"framer-motion": "^12.23.22",
Expand Down
4 changes: 0 additions & 4 deletions server/.env.example

This file was deleted.

10 changes: 6 additions & 4 deletions server/controller/user.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const registerUser = asyncHandler(async (req, res) => {
});

export const loginUser = asyncHandler(async (req, res) => {

const { email, password } = req.body;

if (!email || !password) {
Expand All @@ -57,11 +58,12 @@ export const loginUser = asyncHandler(async (req, res) => {
// Set token in HTTP-only cookie
res.cookie("token", token, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
secure: false, // ❗ localhost uses HTTP, not HTTPS
sameSite: "lax",
maxAge: 24 * 60 * 60 * 1000,
});


return res.status(200).json({
success: true,
message: "Login successful",
Expand All @@ -78,8 +80,8 @@ export const loginUser = asyncHandler(async (req, res) => {
export const logoutUser = asyncHandler(async (req, res) => {
res.clearCookie("token", {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
secure: false,
sameSite: "lax",
});

return res.status(200).json({
Expand Down
3 changes: 1 addition & 2 deletions server/middleware/auth.middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import { User } from "../models/user.model.js";

export const authMiddleware = async (req, res, next) => {
try {
const token = req.headers.authorization?.split(" ")[1];
const token = req.cookies?.token || req.headers.authorization?.split(" ")[1];
if (!token) {
return res.status(401).json({ success: false, message: "No token provided" });
}

const decoded = jwt.verify(token, process.env.JWT_SECRET);

const user = await User.findById(decoded.id);
Expand Down
57 changes: 34 additions & 23 deletions server/mock-socket-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,21 @@ import http from 'http';
import { Server } from 'socket.io';
import cors from 'cors';
import cookieParser from "cookie-parser";
import userrouter from "./routes/user.route.js"
import dotenv from "dotenv";
import connectDB from "./utils/connect-db.js"

dotenv.config();

const app = express();
app.use(cors());
app.use(cors({
origin: ["http://localhost:5173"], // 👈 your React app
credentials: true, // 👈 allow cookies
}));
app.use(express.json());
app.use(cookieParser());
app.use("/api",userrouter)


const server = http.createServer(app);
const io = new Server(server, {
Expand Down Expand Up @@ -257,30 +268,30 @@ app.get('/info', (req, res) => {
});

const PORT = process.env.PORT || 3001;
dotenv.config();


// connectDB().then(
// server.listen(PORT, () => {
// console.log(`🚀 InvertorGuard Mock Socket.IO server running on port ${PORT}`);
// console.log(`📍 Health check: http://localhost:${PORT}/health`);
// console.log(`📍 Server info: http://localhost:${PORT}/info`);
// console.log(`🔌 Connect your React app to: http://localhost:${PORT}`);
// console.log(`👥 Ready for client connections...`);
// })
// ).catch((err)=>
// {
// console.log('database connection faield',err);
// });


server.listen(PORT, () => {
console.log(`🚀 InvertorGuard Mock Socket.IO server running on port ${PORT}`);
console.log(`📍 Health check: http://localhost:${PORT}/health`);
console.log(`📍 Server info: http://localhost:${PORT}/info`);
console.log(`🔌 Connect your React app to: http://localhost:${PORT}`);
console.log(`👥 Ready for client connections...`);
})
connectDB()
.then(() => {
server.listen(PORT, () => {
console.log(`🚀 InvertorGuard Mock Socket.IO server running on port ${PORT}`);
console.log(`📍 Health check: http://localhost:${PORT}/health`);
console.log(`📍 Server info: http://localhost:${PORT}/info`);
console.log(`🔌 Connect your React app to: http://localhost:${PORT}`);
console.log(`👥 Ready for client connections...`);
})
})
.catch((err) => {
console.error("❌ Database connection failed:", err);
});


// server.listen(PORT, () => {
// console.log(`🚀 InvertorGuard Mock Socket.IO server running on port ${PORT}`);
// console.log(`📍 Health check: http://localhost:${PORT}/health`);
// console.log(`📍 Server info: http://localhost:${PORT}/info`);
// console.log(`🔌 Connect your React app to: http://localhost:${PORT}`);
// console.log(`👥 Ready for client connections...`);
// })

// Graceful shutdown
process.on('SIGINT', () => {
Expand Down
2 changes: 1 addition & 1 deletion server/routes/user.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { authMiddleware } from "../middleware/auth.middleware.js";

const router = express.Router();

router.post("/register", registerUser);
router.post("/register", authMiddleware, registerUser);
router.post("/login", loginUser);
router.post("/logout", authMiddleware, logoutUser);

Expand Down
32 changes: 16 additions & 16 deletions server/utils/connect-db.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import mongoose from "mongoose";
import dotenv from "dotenv";
dotenv.config();

const connectDB=async ()=>{
try {

if(!process.env.MONGO_URI){
console.warn('MONGO_URI not found in .env - database features will be unavailable');
return;
}

await mongoose.connect(`${process.env.MONGO_URI}`)
const connectDB = async () => {
try {

if (!process.env.MONGO_URI) {
throw new Error("❌ Missing MONGO_URI in .env file!");
}

console.log(`\n mongodb connected`);
await mongoose.connect(process.env.MONGO_URI);

} catch (error) {
console.log(`✅ MongoDB connected successfully`);
} catch (error) {
console.error("❌ MongoDB connection error:", error.message);

console.warn("Mongodb connection error - database features will be unavailable:",error.message);

}
}
throw error;
}
};

export default connectDB;
export default connectDB;
101 changes: 45 additions & 56 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,81 +1,70 @@
// import { useState } from 'react'
// import reactLogo from './assets/react.svg'
// import viteLogo from '/vite.svg'
// import './App.css'

// function App() {
// const [count, setCount] = useState(0)

// return (
// <>
// <div>
// <a href="https://vite.dev" target="_blank">
// <img src={viteLogo} className="logo" alt="Vite logo" />
// </a>
// <a href="https://react.dev" target="_blank">
// <img src={reactLogo} className="logo react" alt="React logo" />
// </a>
// </div>
// <h1>Vite + React</h1>
// <div className="card">
// <button onClick={() => setCount((count) => count + 1)}>
// count is {count}
// </button>
// <p>
// Edit <code>src/App.jsx</code> and save to test HMR
// </p>
// </div>
// <p className="read-the-docs">
// Click on the Vite and React logos to learn more
// </p>
// </>
// )
// }

// export default App


import React from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { AppProvider, useApp } from './context/AppContext';
import { SocketProvider } from './context/SocketContext';
import { NotificationProvider } from './context/NotificationContext';
import { AuthProvider, useAuth } from './context/AuthContext';
import Dashboard from './pages/Dashboard';
import Logs from './pages/Logs';
import Settings from './pages/Settings';
import Navigation from './components/Navigation';
import Login from './pages/Login';
import Register from './pages/Register';

function App() {
return (
<AppProvider>
<NotificationProvider>
<SocketProvider>
<Router>
<InnerApp />
</Router>
</SocketProvider>
</NotificationProvider>
</AppProvider>
<AuthProvider>
<AppProvider>
<NotificationProvider>
<SocketProvider>
<Router>
<InnerApp />
</Router>
</SocketProvider>
</NotificationProvider>
</AppProvider>
</AuthProvider>
);
}

function InnerApp() {
const { state } = useApp();
const { user } = useAuth();
const toastTheme = state.theme === 'dark' ? 'dark' : 'light';
const isAuthenticated = !!user;

return (
<div className="min-h-screen bg-gray-50">
<Navigation />
<main className="lg:ml-64">
<Routes>
<Route path="/" element={<Navigate to="/dashboard" replace />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/logs" element={<Logs />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</main>
<div className={`min-h-screen ${state.theme === 'dark' ? 'bg-slate-900 text-white' : 'bg-gray-50'}`}>
<Routes>
{/* Public Routes */}
<Route path="/login" element={!isAuthenticated ? <Login /> : <Navigate to="/dashboard" />} />
<Route path="/register" element={!isAuthenticated ? <Register /> : <Navigate to="/dashboard" />} />

{/* Protected Routes */}
{isAuthenticated ? (
<Route
path="/*"
element={
<>
<Navigation />
<main className="lg:ml-64">
<Routes>
<Route path="/" element={<Navigate to="/dashboard" replace />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/logs" element={<Logs />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</main>
</>
}
/>
) : (
<Route path="/*" element={<Navigate to="/login" />} />
)}
</Routes>

<ToastContainer
position="top-right"
autoClose={5000}
Expand Down
28 changes: 28 additions & 0 deletions src/components/Navigation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ import React, { useState, useEffect } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { useApp } from '../context/AppContext';
import { useAuth } from '../context/AuthContext';
import { useNavigate } from 'react-router-dom';


const Navigation = () => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isDesktop, setIsDesktop] = useState(typeof window !== 'undefined' ? window.innerWidth >= 1024 : false);
const location = useLocation();
const { state } = useApp();
const { logoutUser } = useAuth();
const navigate = useNavigate();


useEffect(() => {
const handleResize = () => {
Expand Down Expand Up @@ -125,6 +131,28 @@ const Navigation = () => {
{/* System Info */}
<div className="mt-8 p-4 bg-gray-50 rounded-lg">
<h3 className="font-semibold text-gray-800 mb-3">System Info</h3>

{/* Logout Button */}
<div className="p-4 mt-6 border-t border-gray-200">
<button
onClick={async () => {
try {
await fetch("http://localhost:3000/api/logout", {
method: "POST",
credentials: "include",
});
} catch (err) {
console.error("Logout failed:", err);
}
logoutUser();
localStorage.removeItem("user");
navigate("/");
}}
className="w-full flex items-center justify-center px-4 py-3 rounded-lg bg-red-500 text-white font-semibold shadow-md hover:bg-red-600 transition-all duration-300"
>
🚪 Logout
</button>
</div>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-600">Battery</span>
Expand Down
Loading
Loading