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