From ba1d486d075a8b3a7e1848a9aca93b16a61ac8fe Mon Sep 17 00:00:00 2001 From: ramforth Date: Mon, 17 Nov 2025 02:17:15 +0100 Subject: [PATCH] Dashboard: Changed stylesheet and started prepping html for population. --- dashboard.html | 27 +++++++++++++++++ main.py | 18 +++++++++--- requirements.txt | 3 +- static/login.html | 5 ++++ static/style.css | 74 +++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 110 insertions(+), 17 deletions(-) create mode 100644 dashboard.html diff --git a/dashboard.html b/dashboard.html new file mode 100644 index 0000000..78df0e9 --- /dev/null +++ b/dashboard.html @@ -0,0 +1,27 @@ + + + + + + Dashboard - MultiChatOverlay + + + + + + + + +
+

Dashboard

+

Welcome, {{ user.username }}! You are successfully logged in.

+ +
+

Your unique overlay URL:

+ {{ overlay_url }} +
+ +

Logout

+
+ + \ No newline at end of file diff --git a/main.py b/main.py index fe04dc1..894744d 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,9 @@ import os -from fastapi import FastAPI, Request +from fastapi import FastAPI, Request, Depends from starlette.middleware.sessions import SessionMiddleware from starlette.staticfiles import StaticFiles from starlette.responses import FileResponse, RedirectResponse +from fastapi.templating import Jinja2Templates from contextlib import asynccontextmanager import models @@ -14,6 +15,7 @@ from config import settings # Import settings to get the secret key # Get the absolute path of the directory where this file is located BASE_DIR = os.path.dirname(os.path.abspath(__file__)) STATIC_DIR = os.path.join(BASE_DIR, "static") +TEMPLATES_DIR = os.path.join(BASE_DIR, "templates") @asynccontextmanager async def lifespan(app: FastAPI): @@ -26,6 +28,9 @@ async def lifespan(app: FastAPI): app = FastAPI(lifespan=lifespan) +# Configure Jinja2 templates +templates = Jinja2Templates(directory=TEMPLATES_DIR) + # Mount the 'static' directory using an absolute path for reliability app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static") @@ -41,12 +46,17 @@ async def read_root(): return FileResponse(os.path.join(STATIC_DIR, "login.html")) @app.get("/dashboard") -async def read_dashboard(request: Request): +async def read_dashboard(request: Request, db: Session = Depends(auth.get_db)): # This is our protected route. It checks if a user_id exists in the session. - if not request.session.get('user_id'): + user_id = request.session.get('user_id') + if not user_id: # If not, redirect them to the login page. return RedirectResponse(url="/") - return FileResponse(os.path.join(STATIC_DIR, "dashboard.html")) + + user = db.query(models.User).filter(models.User.id == user_id).first() + overlay_url = f"{settings.APP_BASE_URL}/overlay/{user.id}" + + return templates.TemplateResponse("dashboard.html", {"request": request, "user": user, "overlay_url": overlay_url}) @app.get("/logout") async def logout(request: Request): diff --git a/requirements.txt b/requirements.txt index bf2e335..aae419a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ sqlalchemy httpx cryptography python-dotenv -itsdangerous \ No newline at end of file +itsdangerous +jinja2 \ No newline at end of file diff --git a/static/login.html b/static/login.html index 95ed988..58b89f8 100644 --- a/static/login.html +++ b/static/login.html @@ -4,6 +4,11 @@ Login - MultiChatOverlay + + + + + diff --git a/static/style.css b/static/style.css index 497a492..8f981e9 100644 --- a/static/style.css +++ b/static/style.css @@ -1,27 +1,77 @@ body { - font-family: sans-serif; + /* Use a very dark grey background for contrast, making the container pop */ + font-family: 'Inter', sans-serif; + /* Suggest a modern font (requires import) */ display: flex; justify-content: center; align-items: center; - height: 100vh; - background-color: #f0f2f5; + min-height: 100vh; + /* Use min-height for responsiveness */ + background-color: #0d1117; + /* Dark Mode base color */ + background-image: linear-gradient(135deg, #0d1117 0%, #161b22 100%); + /* Subtle gradient */ margin: 0; + color: #e6edf3; + /* Light text color for contrast */ } .container { text-align: center; - padding: 40px; - background-color: white; - border-radius: 8px; - box-shadow: 0 4px 8px rgba(0,0,0,0.1); -} + padding: 50px; + /* Slightly more padding */ + background-color: #161b22; + /* Lighter dark-mode color for the box */ + border-radius: 12px; + /* Smoother corners */ + /* Modern, subtle layered shadows for depth */ + box-shadow: + 0 4px 15px rgba(0, 0, 0, 0.4), + /* Primary shadow */ + 0 10px 30px rgba(0, 0, 0, 0.7); + /* Deep, soft shadow */ + + /* Optional: Small border for definition */ + border: 1px solid #30363d; + + /* Slightly increase size */ + max-width: 380px; + width: 90%; +} .twitch-btn { - display: inline-block; + display: inline-flex; + /* Use flex for easy icon alignment if you add one */ + align-items: center; + justify-content: center; + + /* Use a slightly brighter, but still core Twitch purple */ background-color: #9146FF; color: white; - padding: 10px 20px; - border-radius: 5px; + padding: 12px 28px; + /* Slightly larger padding */ + border-radius: 8px; + /* Smoother corners */ text-decoration: none; - font-weight: bold; + font-weight: 600; + /* Medium bold */ + letter-spacing: 0.5px; + /* Better readability */ + transition: all 0.3s ease; + /* Enable smooth transitions */ + border: none; + cursor: pointer; + + /* Subtle inner shadow for 'pressed' look */ + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); +} + +/* Add a sleek hover effect */ +.twitch-btn:hover { + background-color: #772ce8; + /* Slightly darker purple on hover */ + transform: translateY(-2px); + /* Lift the button slightly */ + box-shadow: 0 6px 12px rgba(145, 70, 255, 0.3); + /* Glow effect on hover */ } \ No newline at end of file