diff --git a/backend/middleware/authMiddleware.js b/backend/middleware/authMiddleware.js new file mode 100644 index 0000000..b16c7f2 --- /dev/null +++ b/backend/middleware/authMiddleware.js @@ -0,0 +1,16 @@ +import jwt from "jsonwebtoken"; + +const JWT_SECRET = process.env.JWT_SECRET || "supersecretkey"; + +export const authMiddleware = (req, res, next) => { + const token = req.headers.authorization?.split(" ")[1]; // Bearer token + if (!token) return res.status(401).json({ msg: "No token provided" }); + + try { + const decoded = jwt.verify(token, JWT_SECRET); + req.user = decoded; + next(); + } catch (err) { + res.status(401).json({ msg: "Invalid token" }); + } +}; diff --git a/backend/models/user.js b/backend/models/user.js new file mode 100644 index 0000000..83eca67 --- /dev/null +++ b/backend/models/user.js @@ -0,0 +1,8 @@ +import mongoose from "mongoose"; + +const userSchema = new mongoose.Schema({ + username: { type: String, required: true, unique: true }, + password: { type: String, required: true }, // hashed +}); + +export default mongoose.model("User", userSchema); diff --git a/backend/routes/authRoutes.js b/backend/routes/authRoutes.js new file mode 100644 index 0000000..0fe7600 --- /dev/null +++ b/backend/routes/authRoutes.js @@ -0,0 +1,11 @@ +import express from "express"; +import { register, login, protectedRoute } from "../controllers/authController.js"; +import { authMiddleware } from "../middleware/authMiddleware.js"; + +const router = express.Router(); + +router.post("/register", register); +router.post("/login", login); +router.get("/protected", authMiddleware, protectedRoute); + +export default router; diff --git a/src/index.css b/src/index.css index 30da0d3..5d09cb4 100644 --- a/src/index.css +++ b/src/index.css @@ -17,12 +17,6 @@ html, body { font-family: 'Lexend', system-ui, Avenir, Helvetica, Arial, sans-serif; /* apply Lexend globally */ } -body { - display: flex; - flex-direction: column; - width: 100%; -} - /* Optional: style scrollbar for future if needed */ ::-webkit-scrollbar { width: 6px; @@ -78,3 +72,70 @@ body { .scrollbar-thin::-webkit-scrollbar-thumb:hover { background-color: rgba(100, 100, 100, 0.7); } +/* Small devices: phones (up to 640px) */ +@media (max-width: 640px) { + header { + padding: 0.5rem 1rem; + font-size: 0.9rem; + } + + main { + padding: 1rem; + } + + footer { + padding: 1rem 0.5rem; + font-size: 0.8rem; + } +} + +/* Medium devices: tablets (641px to 768px) */ +@media (min-width: 641px) and (max-width: 768px) { + header { + padding: 1rem 2rem; + font-size: 1rem; + } + + main { + padding: 1.5rem; + } + + footer { + padding: 1.5rem; + font-size: 0.9rem; + } +} + +/* Large devices: laptops (769px to 1024px) */ +@media (min-width: 769px) and (max-width: 1024px) { + header { + padding: 1.5rem 3rem; + font-size: 1.1rem; + } + + main { + padding: 2rem; + } + + footer { + padding: 2rem; + font-size: 1rem; + } +} + +/* Extra large devices: desktops (1025px and up) */ +@media (min-width: 1025px) { + header { + padding: 2rem 4rem; + font-size: 1.2rem; + } + + main { + padding: 2.5rem; + } + + footer { + padding: 2.5rem; + font-size: 1rem; + } +} diff --git a/src/layout/MainLayout.jsx b/src/layout/MainLayout.jsx index d651db5..a14120d 100644 --- a/src/layout/MainLayout.jsx +++ b/src/layout/MainLayout.jsx @@ -4,20 +4,20 @@ import Footer from "../components/Footer"; const MainLayout = ({ children }) => { const location = useLocation(); - const hideFooterPaths = ["/about", "/chat"]; // Add any other routes where footer should be hidden + const hideFooterPaths = ["/about"]; const hideFooter = hideFooterPaths.includes(location.pathname); return ( -
+ {message} +
+ )} ++ Loading certifications... +
+ ); + if(error || !certifications) + return ( ++ {error || "Failed to load certifications"} +
+ ); + return ( +No certifications yet.
+ ) : ( +Issued By{cert.issuer}
++ Issued Date{cert.date} +
++ Expiry Date{cert.expiry} +
+ {cert.link && ( + + View Certificate + + )} +