Spaces:
Sleeping
Sleeping
Commit ·
7263c0e
1
Parent(s): 33d1c37
Upload 33 files (#2)
Browse files- Upload 33 files (dccb160d2456e01ab8ab4ef9787dd508a3f62afb)
- app.py +33 -0
- config.py +19 -0
- requirements.txt +21 -0
- routes/__pycache__/auth.cpython-312.pyc +0 -0
- routes/__pycache__/chatbot.cpython-312.pyc +0 -0
- routes/__pycache__/dashboard.cpython-312.pyc +0 -0
- routes/__pycache__/upload.cpython-312.pyc +0 -0
- routes/auth.py +37 -0
- routes/chatbot.py +95 -0
- routes/dashboard.py +20 -0
- routes/upload.py +197 -0
- static/css/style.css +342 -0
- static/js/chatbot.js +24 -0
- static/uploads/2025-01-26T17-12_export.csv +11 -0
- static/uploads/2026-04-10T06-45_export.csv +2 -0
- static/uploads/20260508201204_energy_data.csv +36 -0
- static/uploads/20260508201757_energy_data_new (1).xlsx +0 -0
- static/uploads/20260508201815_leaderboard (10).csv +8 -0
- static/uploads/20260508202505_leaderboard (10).csv +8 -0
- static/uploads/20260508203002_energy_data.csv +36 -0
- static/uploads/20260509125750_leaderboard (10).csv +8 -0
- static/uploads/Ai questions.csv +1 -0
- static/uploads/data.csv +8 -0
- static/uploads/energy_data.csv +36 -0
- static/uploads/energy_data_new (1).xlsx +0 -0
- static/uploads/energy_data_new.xlsx +0 -0
- static/uploads/leaderboard (10).csv +8 -0
- templates/analytics.html +116 -0
- templates/chatbot.html +182 -0
- templates/dashboard.html +323 -0
- templates/index.html +0 -0
- templates/login.html +105 -0
- templates/register.html +103 -0
app.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flask import Flask
|
| 2 |
+
from config import Config
|
| 3 |
+
from models.database import db
|
| 4 |
+
from routes.auth import auth_bp
|
| 5 |
+
from routes.dashboard import dashboard_bp
|
| 6 |
+
from routes.chatbot import chatbot_bp
|
| 7 |
+
from routes.upload import upload_bp
|
| 8 |
+
|
| 9 |
+
app = Flask(__name__)
|
| 10 |
+
app.config.from_object(Config)
|
| 11 |
+
|
| 12 |
+
db.init_app(app)
|
| 13 |
+
|
| 14 |
+
# ✅ safer DB init
|
| 15 |
+
with app.app_context():
|
| 16 |
+
db.create_all()
|
| 17 |
+
|
| 18 |
+
# Blueprints
|
| 19 |
+
app.register_blueprint(auth_bp)
|
| 20 |
+
app.register_blueprint(dashboard_bp)
|
| 21 |
+
app.register_blueprint(chatbot_bp)
|
| 22 |
+
app.register_blueprint(upload_bp)
|
| 23 |
+
|
| 24 |
+
# =========================
|
| 25 |
+
# ELECTRON SAFE RUN CONFIG
|
| 26 |
+
# =========================
|
| 27 |
+
if __name__ == "__main__":
|
| 28 |
+
app.run(
|
| 29 |
+
host="127.0.0.1",
|
| 30 |
+
port=5000,
|
| 31 |
+
debug=False, # ❌ MUST BE FALSE
|
| 32 |
+
use_reloader=False # 🔥 CRITICAL FIX
|
| 33 |
+
)
|
config.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from dotenv import load_dotenv
|
| 3 |
+
|
| 4 |
+
load_dotenv()
|
| 5 |
+
|
| 6 |
+
class Config:
|
| 7 |
+
SECRET_KEY = os.getenv("SECRET_KEY", "your_secret_key")
|
| 8 |
+
|
| 9 |
+
SQLALCHEMY_DATABASE_URI = os.getenv(
|
| 10 |
+
"DATABASE_URL",
|
| 11 |
+
"mysql+pymysql://root:@localhost/smart_dashboard"
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
| 15 |
+
UPLOAD_FOLDER = "static/uploads"
|
| 16 |
+
|
| 17 |
+
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
| 18 |
+
GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-3.1-flash-lite-preview")
|
| 19 |
+
TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
|
requirements.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Flask==3.0.3
|
| 3 |
+
Flask-SQLAlchemy==3.1.1
|
| 4 |
+
PyMySQL==1.1.1
|
| 5 |
+
pandas==2.2.2
|
| 6 |
+
numpy==1.26.4
|
| 7 |
+
groq==0.9.0
|
| 8 |
+
Werkzeug==3.0.3
|
| 9 |
+
python-dotenv==1.0.1
|
| 10 |
+
langchain==0.2.1
|
| 11 |
+
langchain-community==0.2.1
|
| 12 |
+
langchain-google-genai
|
| 13 |
+
duckduckgo-search
|
| 14 |
+
beautifulsoup4
|
| 15 |
+
faiss-cpu==1.8.0
|
| 16 |
+
plotly==5.22.0
|
| 17 |
+
matplotlib==3.9.0
|
| 18 |
+
scikit-learn==1.5.0
|
| 19 |
+
gunicorn==22.0.0
|
| 20 |
+
requests==2.32.3
|
| 21 |
+
|
routes/__pycache__/auth.cpython-312.pyc
ADDED
|
Binary file (2.34 kB). View file
|
|
|
routes/__pycache__/chatbot.cpython-312.pyc
ADDED
|
Binary file (3.15 kB). View file
|
|
|
routes/__pycache__/dashboard.cpython-312.pyc
ADDED
|
Binary file (950 Bytes). View file
|
|
|
routes/__pycache__/upload.cpython-312.pyc
ADDED
|
Binary file (5.8 kB). View file
|
|
|
routes/auth.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flask import Blueprint, render_template, request, redirect, url_for, session
|
| 2 |
+
from werkzeug.security import generate_password_hash, check_password_hash
|
| 3 |
+
from models.database import db
|
| 4 |
+
from models.user import User
|
| 5 |
+
|
| 6 |
+
auth_bp = Blueprint("auth", __name__)
|
| 7 |
+
|
| 8 |
+
@auth_bp.route("/")
|
| 9 |
+
def home():
|
| 10 |
+
return render_template("login.html")
|
| 11 |
+
|
| 12 |
+
@auth_bp.route("/register", methods=["GET", "POST"])
|
| 13 |
+
def register():
|
| 14 |
+
if request.method == "POST":
|
| 15 |
+
username = request.form["username"]
|
| 16 |
+
email = request.form["email"]
|
| 17 |
+
password = generate_password_hash(request.form["password"])
|
| 18 |
+
|
| 19 |
+
user = User(username=username, email=email, password=password)
|
| 20 |
+
db.session.add(user)
|
| 21 |
+
db.session.commit()
|
| 22 |
+
return redirect(url_for("auth.home"))
|
| 23 |
+
|
| 24 |
+
return render_template("register.html")
|
| 25 |
+
|
| 26 |
+
@auth_bp.route("/login", methods=["POST"])
|
| 27 |
+
def login():
|
| 28 |
+
email = request.form["email"]
|
| 29 |
+
password = request.form["password"]
|
| 30 |
+
|
| 31 |
+
user = User.query.filter_by(email=email).first()
|
| 32 |
+
|
| 33 |
+
if user and check_password_hash(user.password, password):
|
| 34 |
+
session["user_id"] = user.id
|
| 35 |
+
return redirect(url_for("dashboard.dashboard"))
|
| 36 |
+
|
| 37 |
+
return "Invalid credentials"
|
routes/chatbot.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flask import Blueprint, request, jsonify, render_template
|
| 2 |
+
import os
|
| 3 |
+
import traceback
|
| 4 |
+
|
| 5 |
+
from chatbot.data_query import query_dashboard_data
|
| 6 |
+
from chatbot.llm_handler import general_chatbot
|
| 7 |
+
from chatbot.rag_store import load_csv, get_dataframe
|
| 8 |
+
|
| 9 |
+
chatbot_bp = Blueprint("chatbot", __name__)
|
| 10 |
+
|
| 11 |
+
UPLOAD_FOLDER = "static/uploads"
|
| 12 |
+
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
| 13 |
+
|
| 14 |
+
# -----------------------------
|
| 15 |
+
# PAGE
|
| 16 |
+
# -----------------------------
|
| 17 |
+
@chatbot_bp.route("/chatbot")
|
| 18 |
+
def chatbot_page():
|
| 19 |
+
return render_template("chatbot.html")
|
| 20 |
+
|
| 21 |
+
# -----------------------------
|
| 22 |
+
# FILE UPLOAD (RAG MEMORY LOADER)
|
| 23 |
+
# -----------------------------
|
| 24 |
+
@chatbot_bp.route("/upload", methods=["POST"])
|
| 25 |
+
def upload_file():
|
| 26 |
+
try:
|
| 27 |
+
file = request.files["file"]
|
| 28 |
+
|
| 29 |
+
filepath = os.path.join(UPLOAD_FOLDER, "data.csv")
|
| 30 |
+
file.save(filepath)
|
| 31 |
+
|
| 32 |
+
df = load_csv(filepath)
|
| 33 |
+
|
| 34 |
+
return jsonify({
|
| 35 |
+
"status": "success",
|
| 36 |
+
"message": "File uploaded & loaded into RAG",
|
| 37 |
+
"rows": len(df)
|
| 38 |
+
})
|
| 39 |
+
|
| 40 |
+
except Exception as e:
|
| 41 |
+
return jsonify({
|
| 42 |
+
"status": "error",
|
| 43 |
+
"message": str(e)
|
| 44 |
+
})
|
| 45 |
+
|
| 46 |
+
# -----------------------------
|
| 47 |
+
# CHAT API
|
| 48 |
+
# -----------------------------
|
| 49 |
+
@chatbot_bp.route("/chat", methods=["POST"])
|
| 50 |
+
def chat():
|
| 51 |
+
try:
|
| 52 |
+
data = request.get_json()
|
| 53 |
+
user_message = data.get("message", "")
|
| 54 |
+
|
| 55 |
+
# -----------------------------
|
| 56 |
+
# SAFE DATAFRAME FETCH
|
| 57 |
+
# -----------------------------
|
| 58 |
+
df = get_dataframe()
|
| 59 |
+
|
| 60 |
+
# 🔥 FIX: if accidentally returns function/method
|
| 61 |
+
if callable(df):
|
| 62 |
+
df = df()
|
| 63 |
+
|
| 64 |
+
dashboard_keywords = [
|
| 65 |
+
"dashboard", "chart", "graph", "data", "csv",
|
| 66 |
+
"sales", "energy", "report", "analytics",
|
| 67 |
+
"average", "max", "min", "sum", "trend", "upload",
|
| 68 |
+
"who", "score", "compare", "highest", "lowest"
|
| 69 |
+
]
|
| 70 |
+
|
| 71 |
+
user_lower = user_message.lower()
|
| 72 |
+
|
| 73 |
+
# -----------------------------
|
| 74 |
+
# RAG MODE (DATA QUERY)
|
| 75 |
+
# -----------------------------
|
| 76 |
+
if df is not None and any(word in user_lower for word in dashboard_keywords):
|
| 77 |
+
answer = query_dashboard_data(df, user_message)
|
| 78 |
+
|
| 79 |
+
# -----------------------------
|
| 80 |
+
# LLM MODE
|
| 81 |
+
# -----------------------------
|
| 82 |
+
else:
|
| 83 |
+
answer = general_chatbot(user_message)
|
| 84 |
+
|
| 85 |
+
return jsonify({
|
| 86 |
+
"status": "success",
|
| 87 |
+
"response": answer
|
| 88 |
+
})
|
| 89 |
+
|
| 90 |
+
except Exception as e:
|
| 91 |
+
return jsonify({
|
| 92 |
+
"status": "error",
|
| 93 |
+
"response": str(e),
|
| 94 |
+
"trace": traceback.format_exc() # 🔥 helps debugging exact line
|
| 95 |
+
})
|
routes/dashboard.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flask import Blueprint, render_template, session, redirect, url_for
|
| 2 |
+
|
| 3 |
+
dashboard_bp = Blueprint("dashboard", __name__)
|
| 4 |
+
|
| 5 |
+
# DASHBOARD PAGE
|
| 6 |
+
@dashboard_bp.route("/dashboard")
|
| 7 |
+
def dashboard():
|
| 8 |
+
if "user_id" not in session:
|
| 9 |
+
return redirect(url_for("auth.home"))
|
| 10 |
+
|
| 11 |
+
return render_template("dashboard.html")
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
# ANALYTICS PAGE
|
| 15 |
+
@dashboard_bp.route("/analytics")
|
| 16 |
+
def analytics():
|
| 17 |
+
if "user_id" not in session:
|
| 18 |
+
return redirect(url_for("auth.home"))
|
| 19 |
+
|
| 20 |
+
return render_template("analytics.html")
|
routes/upload.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flask import Blueprint, request, jsonify
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import os
|
| 4 |
+
import traceback
|
| 5 |
+
from datetime import datetime
|
| 6 |
+
|
| 7 |
+
from config import Config
|
| 8 |
+
from chatbot.rag_store import load_csv
|
| 9 |
+
from models.database import db
|
| 10 |
+
from models.uploaded_file import UploadedFile
|
| 11 |
+
|
| 12 |
+
upload_bp = Blueprint("upload", __name__, url_prefix="/api")
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
@upload_bp.route("/upload", methods=["POST"])
|
| 16 |
+
def upload_file():
|
| 17 |
+
try:
|
| 18 |
+
# =========================
|
| 19 |
+
# FILE VALIDATION
|
| 20 |
+
# =========================
|
| 21 |
+
if "file" not in request.files:
|
| 22 |
+
return jsonify({
|
| 23 |
+
"success": False,
|
| 24 |
+
"error": "No file uploaded"
|
| 25 |
+
})
|
| 26 |
+
|
| 27 |
+
file = request.files["file"]
|
| 28 |
+
|
| 29 |
+
if file.filename == "":
|
| 30 |
+
return jsonify({
|
| 31 |
+
"success": False,
|
| 32 |
+
"error": "No selected file"
|
| 33 |
+
})
|
| 34 |
+
|
| 35 |
+
# =========================
|
| 36 |
+
# CREATE UPLOAD DIRECTORY
|
| 37 |
+
# =========================
|
| 38 |
+
os.makedirs(Config.UPLOAD_FOLDER, exist_ok=True)
|
| 39 |
+
|
| 40 |
+
# UNIQUE FILE NAME
|
| 41 |
+
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
| 42 |
+
safe_filename = f"{timestamp}_{file.filename}"
|
| 43 |
+
|
| 44 |
+
filepath = os.path.join(Config.UPLOAD_FOLDER, safe_filename)
|
| 45 |
+
|
| 46 |
+
# SAVE FILE
|
| 47 |
+
file.save(filepath)
|
| 48 |
+
|
| 49 |
+
# =========================
|
| 50 |
+
# LOAD INTO RAG STORE
|
| 51 |
+
# =========================
|
| 52 |
+
try:
|
| 53 |
+
load_csv(filepath)
|
| 54 |
+
except Exception as rag_error:
|
| 55 |
+
return jsonify({
|
| 56 |
+
"success": False,
|
| 57 |
+
"error": f"RAG load failed: {str(rag_error)}"
|
| 58 |
+
})
|
| 59 |
+
|
| 60 |
+
# =========================
|
| 61 |
+
# READ CSV FILE
|
| 62 |
+
# =========================
|
| 63 |
+
try:
|
| 64 |
+
df = pd.read_csv(filepath, encoding="utf-8")
|
| 65 |
+
except:
|
| 66 |
+
df = pd.read_csv(filepath, encoding="latin1")
|
| 67 |
+
|
| 68 |
+
# CLEAN DATA
|
| 69 |
+
df.dropna(how="all", inplace=True)
|
| 70 |
+
df.dropna(axis=1, how="all", inplace=True)
|
| 71 |
+
|
| 72 |
+
if df.empty:
|
| 73 |
+
return jsonify({
|
| 74 |
+
"success": False,
|
| 75 |
+
"error": "CSV file is empty"
|
| 76 |
+
})
|
| 77 |
+
|
| 78 |
+
df.columns = [str(col).strip() for col in df.columns]
|
| 79 |
+
|
| 80 |
+
# =========================
|
| 81 |
+
# COLUMN DETECTION
|
| 82 |
+
# =========================
|
| 83 |
+
numeric_cols = []
|
| 84 |
+
text_cols = []
|
| 85 |
+
|
| 86 |
+
for col in df.columns:
|
| 87 |
+
converted = pd.to_numeric(df[col], errors="coerce")
|
| 88 |
+
|
| 89 |
+
if converted.notna().sum() > 0:
|
| 90 |
+
numeric_cols.append(col)
|
| 91 |
+
df[col] = converted.fillna(0)
|
| 92 |
+
else:
|
| 93 |
+
text_cols.append(col)
|
| 94 |
+
|
| 95 |
+
# =========================
|
| 96 |
+
# LABEL COLUMN
|
| 97 |
+
# =========================
|
| 98 |
+
label_col = text_cols[0] if text_cols else df.columns[0]
|
| 99 |
+
|
| 100 |
+
labels = df[label_col].astype(str).fillna("").tolist()[:50]
|
| 101 |
+
|
| 102 |
+
# =========================
|
| 103 |
+
# DATASETS
|
| 104 |
+
# =========================
|
| 105 |
+
datasets = []
|
| 106 |
+
|
| 107 |
+
for col in numeric_cols:
|
| 108 |
+
if col == label_col:
|
| 109 |
+
continue
|
| 110 |
+
|
| 111 |
+
datasets.append({
|
| 112 |
+
"label": col,
|
| 113 |
+
"data": df[col].tolist()[:50]
|
| 114 |
+
})
|
| 115 |
+
|
| 116 |
+
# FALLBACK
|
| 117 |
+
if not datasets:
|
| 118 |
+
first_col = df.columns[0]
|
| 119 |
+
|
| 120 |
+
datasets.append({
|
| 121 |
+
"label": first_col,
|
| 122 |
+
"data": pd.to_numeric(
|
| 123 |
+
df[first_col],
|
| 124 |
+
errors="coerce"
|
| 125 |
+
).fillna(0).tolist()[:50]
|
| 126 |
+
})
|
| 127 |
+
|
| 128 |
+
labels = [f"Row {i+1}" for i in range(len(datasets[0]["data"]))]
|
| 129 |
+
|
| 130 |
+
# =========================
|
| 131 |
+
# SUMMARY
|
| 132 |
+
# =========================
|
| 133 |
+
summary = {}
|
| 134 |
+
|
| 135 |
+
for col in numeric_cols:
|
| 136 |
+
try:
|
| 137 |
+
summary[col] = {
|
| 138 |
+
"sum": float(df[col].sum()),
|
| 139 |
+
"avg": float(df[col].mean()),
|
| 140 |
+
"max": float(df[col].max()),
|
| 141 |
+
"min": float(df[col].min())
|
| 142 |
+
}
|
| 143 |
+
except:
|
| 144 |
+
pass
|
| 145 |
+
|
| 146 |
+
# =========================
|
| 147 |
+
# CHART DATA JSON
|
| 148 |
+
# =========================
|
| 149 |
+
chart_data = {
|
| 150 |
+
"rows": len(df),
|
| 151 |
+
"columns": list(df.columns),
|
| 152 |
+
"label_column": label_col,
|
| 153 |
+
"numeric_columns": numeric_cols,
|
| 154 |
+
"text_columns": text_cols,
|
| 155 |
+
"labels": labels,
|
| 156 |
+
"datasets": datasets,
|
| 157 |
+
"summary": summary
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
# =========================
|
| 161 |
+
# SAVE TO MYSQL DATABASE
|
| 162 |
+
# =========================
|
| 163 |
+
uploaded_file = UploadedFile(
|
| 164 |
+
filename=safe_filename,
|
| 165 |
+
filepath=filepath,
|
| 166 |
+
chart_data=chart_data
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
db.session.add(uploaded_file)
|
| 170 |
+
db.session.commit()
|
| 171 |
+
|
| 172 |
+
# =========================
|
| 173 |
+
# DEBUG LOG
|
| 174 |
+
# =========================
|
| 175 |
+
print("✅ FILE SAVED TO MYSQL:", safe_filename)
|
| 176 |
+
print("DB ID:", uploaded_file.id)
|
| 177 |
+
|
| 178 |
+
# =========================
|
| 179 |
+
# RESPONSE
|
| 180 |
+
# =========================
|
| 181 |
+
return jsonify({
|
| 182 |
+
"success": True,
|
| 183 |
+
"message": "CSV uploaded, processed, and stored successfully",
|
| 184 |
+
"file_id": uploaded_file.id,
|
| 185 |
+
**chart_data
|
| 186 |
+
})
|
| 187 |
+
|
| 188 |
+
except Exception as e:
|
| 189 |
+
db.session.rollback()
|
| 190 |
+
|
| 191 |
+
print("❌ UPLOAD ERROR:")
|
| 192 |
+
print(traceback.format_exc())
|
| 193 |
+
|
| 194 |
+
return jsonify({
|
| 195 |
+
"success": False,
|
| 196 |
+
"error": str(e)
|
| 197 |
+
})
|
static/css/style.css
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* =========================
|
| 2 |
+
RESET & BASE STYLES
|
| 3 |
+
========================= */
|
| 4 |
+
* {
|
| 5 |
+
margin: 0;
|
| 6 |
+
padding: 0;
|
| 7 |
+
box-sizing: border-box;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
body {
|
| 11 |
+
font-family: 'Segoe UI', Arial, sans-serif;
|
| 12 |
+
background: #f4f7fa;
|
| 13 |
+
color: #333;
|
| 14 |
+
line-height: 1.5;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
/* =========================
|
| 18 |
+
DASHBOARD LAYOUT
|
| 19 |
+
========================= */
|
| 20 |
+
.dashboard-layout {
|
| 21 |
+
display: flex;
|
| 22 |
+
min-height: 100vh;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
/* =========================
|
| 26 |
+
SIDEBAR
|
| 27 |
+
========================= */
|
| 28 |
+
.sidebar {
|
| 29 |
+
width: 260px;
|
| 30 |
+
background: linear-gradient(180deg, #0f172a, #1e293b);
|
| 31 |
+
color: white;
|
| 32 |
+
padding: 25px 18px;
|
| 33 |
+
position: fixed;
|
| 34 |
+
top: 0;
|
| 35 |
+
left: 0;
|
| 36 |
+
bottom: 0;
|
| 37 |
+
overflow-y: auto;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
.sidebar h2 {
|
| 41 |
+
text-align: center;
|
| 42 |
+
font-size: 24px;
|
| 43 |
+
margin-bottom: 25px;
|
| 44 |
+
letter-spacing: 1px;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
.sidebar ul {
|
| 48 |
+
list-style: none;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
.sidebar ul li {
|
| 52 |
+
padding: 12px 14px;
|
| 53 |
+
margin-bottom: 10px;
|
| 54 |
+
border-radius: 10px;
|
| 55 |
+
cursor: pointer;
|
| 56 |
+
transition: 0.25s ease;
|
| 57 |
+
position: relative;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
.sidebar ul li:hover {
|
| 61 |
+
background: rgba(255, 255, 255, 0.12);
|
| 62 |
+
transform: translateX(4px);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
/* active indicator */
|
| 66 |
+
.sidebar ul li::before {
|
| 67 |
+
content: "";
|
| 68 |
+
position: absolute;
|
| 69 |
+
left: 0;
|
| 70 |
+
top: 0;
|
| 71 |
+
width: 4px;
|
| 72 |
+
height: 100%;
|
| 73 |
+
background: #00c6ff;
|
| 74 |
+
transform: scaleY(0);
|
| 75 |
+
transition: 0.3s;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
.sidebar ul li:hover::before {
|
| 79 |
+
transform: scaleY(1);
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
/* =========================
|
| 83 |
+
MAIN CONTENT
|
| 84 |
+
========================= */
|
| 85 |
+
.main-content {
|
| 86 |
+
margin-left: 260px;
|
| 87 |
+
flex: 1;
|
| 88 |
+
padding: 30px;
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
/* HEADER */
|
| 92 |
+
header {
|
| 93 |
+
margin-bottom: 25px;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
header h1 {
|
| 97 |
+
font-size: 32px;
|
| 98 |
+
color: #0f172a;
|
| 99 |
+
font-weight: 700;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
/* =========================
|
| 103 |
+
UPLOAD SECTION
|
| 104 |
+
========================= */
|
| 105 |
+
.upload-section {
|
| 106 |
+
background: white;
|
| 107 |
+
padding: 20px;
|
| 108 |
+
border-radius: 16px;
|
| 109 |
+
box-shadow: 0 6px 18px rgba(0,0,0,0.08);
|
| 110 |
+
margin-bottom: 25px;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
.upload-section form {
|
| 114 |
+
display: flex;
|
| 115 |
+
align-items: center;
|
| 116 |
+
gap: 12px;
|
| 117 |
+
flex-wrap: wrap;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
.upload-section input[type="file"] {
|
| 121 |
+
padding: 10px;
|
| 122 |
+
border: 1px solid #ddd;
|
| 123 |
+
border-radius: 10px;
|
| 124 |
+
background: #f9fafb;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
.upload-section button {
|
| 128 |
+
padding: 12px 20px;
|
| 129 |
+
background: linear-gradient(135deg, #007bff, #00c6ff);
|
| 130 |
+
color: white;
|
| 131 |
+
border: none;
|
| 132 |
+
border-radius: 10px;
|
| 133 |
+
cursor: pointer;
|
| 134 |
+
font-weight: 600;
|
| 135 |
+
transition: 0.25s ease;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
.upload-section button:hover {
|
| 139 |
+
transform: scale(1.05);
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
/* =========================
|
| 143 |
+
KPI CARDS
|
| 144 |
+
========================= */
|
| 145 |
+
.kpi-cards {
|
| 146 |
+
display: grid;
|
| 147 |
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
| 148 |
+
gap: 18px;
|
| 149 |
+
margin-bottom: 30px;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
.card {
|
| 153 |
+
background: white;
|
| 154 |
+
padding: 22px;
|
| 155 |
+
border-radius: 16px;
|
| 156 |
+
box-shadow: 0 6px 18px rgba(0,0,0,0.08);
|
| 157 |
+
text-align: center;
|
| 158 |
+
font-size: 16px;
|
| 159 |
+
font-weight: 600;
|
| 160 |
+
transition: 0.25s ease;
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
.card:hover {
|
| 164 |
+
transform: translateY(-5px);
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
/* =========================
|
| 168 |
+
CHART SECTION
|
| 169 |
+
========================= */
|
| 170 |
+
.chart-section {
|
| 171 |
+
background: white;
|
| 172 |
+
padding: 25px;
|
| 173 |
+
border-radius: 16px;
|
| 174 |
+
box-shadow: 0 6px 18px rgba(0,0,0,0.08);
|
| 175 |
+
min-height: 420px;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
/* =========================
|
| 179 |
+
CHATBOT TOGGLE BUTTON (BOTTOM RIGHT)
|
| 180 |
+
========================= */
|
| 181 |
+
#chatbot-toggle {
|
| 182 |
+
position: fixed;
|
| 183 |
+
bottom: 20px;
|
| 184 |
+
right: 20px;
|
| 185 |
+
width: 62px;
|
| 186 |
+
height: 62px;
|
| 187 |
+
border-radius: 50%;
|
| 188 |
+
border: none;
|
| 189 |
+
background: linear-gradient(135deg, #007bff, #00c6ff);
|
| 190 |
+
color: white;
|
| 191 |
+
font-size: 26px;
|
| 192 |
+
cursor: pointer;
|
| 193 |
+
box-shadow: 0 6px 18px rgba(0,0,0,0.3);
|
| 194 |
+
z-index: 9999;
|
| 195 |
+
transition: all 0.25s ease;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
#chatbot-toggle:hover {
|
| 199 |
+
transform: scale(1.1);
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
/* =========================
|
| 203 |
+
CHATBOT WINDOW (BOTTOM RIGHT)
|
| 204 |
+
========================= */
|
| 205 |
+
#chatbot-widget {
|
| 206 |
+
position: fixed;
|
| 207 |
+
bottom: 95px;
|
| 208 |
+
right: 20px;
|
| 209 |
+
width: 360px;
|
| 210 |
+
height: 520px;
|
| 211 |
+
background: white;
|
| 212 |
+
display: none;
|
| 213 |
+
flex-direction: column;
|
| 214 |
+
border-radius: 18px;
|
| 215 |
+
box-shadow: 0 10px 30px rgba(0,0,0,0.25);
|
| 216 |
+
overflow: hidden;
|
| 217 |
+
z-index: 9999;
|
| 218 |
+
transition: all 0.25s ease;
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
/* CHAT HEADER */
|
| 222 |
+
#chat-header {
|
| 223 |
+
background: linear-gradient(135deg, #007bff, #00c6ff);
|
| 224 |
+
color: white;
|
| 225 |
+
padding: 14px 16px;
|
| 226 |
+
display: flex;
|
| 227 |
+
justify-content: space-between;
|
| 228 |
+
align-items: center;
|
| 229 |
+
font-weight: 600;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
#chat-header button {
|
| 233 |
+
background: transparent;
|
| 234 |
+
border: none;
|
| 235 |
+
color: white;
|
| 236 |
+
font-size: 20px;
|
| 237 |
+
cursor: pointer;
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
/* CHAT MESSAGES */
|
| 241 |
+
#chat-messages {
|
| 242 |
+
flex: 1;
|
| 243 |
+
padding: 12px;
|
| 244 |
+
overflow-y: auto;
|
| 245 |
+
background: #f4f7fa;
|
| 246 |
+
display: flex;
|
| 247 |
+
flex-direction: column;
|
| 248 |
+
gap: 10px;
|
| 249 |
+
scroll-behavior: smooth;
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
/* USER MESSAGE */
|
| 253 |
+
.user-message {
|
| 254 |
+
align-self: flex-end;
|
| 255 |
+
background: #007bff;
|
| 256 |
+
color: white;
|
| 257 |
+
padding: 10px 12px;
|
| 258 |
+
border-radius: 14px 14px 0 14px;
|
| 259 |
+
max-width: 80%;
|
| 260 |
+
font-size: 14px;
|
| 261 |
+
word-break: break-word;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
/* BOT MESSAGE */
|
| 265 |
+
.bot-message {
|
| 266 |
+
align-self: flex-start;
|
| 267 |
+
background: white;
|
| 268 |
+
color: #333;
|
| 269 |
+
padding: 10px 12px;
|
| 270 |
+
border-radius: 14px 14px 14px 0;
|
| 271 |
+
max-width: 80%;
|
| 272 |
+
font-size: 14px;
|
| 273 |
+
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
/* CHAT INPUT AREA */
|
| 277 |
+
#chat-input-area {
|
| 278 |
+
display: flex;
|
| 279 |
+
padding: 10px;
|
| 280 |
+
border-top: 1px solid #ddd;
|
| 281 |
+
background: white;
|
| 282 |
+
position: sticky;
|
| 283 |
+
bottom: 0;
|
| 284 |
+
}
|
| 285 |
+
|
| 286 |
+
#chat-input {
|
| 287 |
+
flex: 1;
|
| 288 |
+
padding: 10px;
|
| 289 |
+
border: 1px solid #ccc;
|
| 290 |
+
border-radius: 10px;
|
| 291 |
+
outline: none;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
#chat-input:focus {
|
| 295 |
+
border-color: #007bff;
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
#chat-input-area button {
|
| 299 |
+
margin-left: 8px;
|
| 300 |
+
padding: 10px 14px;
|
| 301 |
+
border: none;
|
| 302 |
+
background: #007bff;
|
| 303 |
+
color: white;
|
| 304 |
+
border-radius: 10px;
|
| 305 |
+
cursor: pointer;
|
| 306 |
+
transition: 0.2s;
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
#chat-input-area button:hover {
|
| 310 |
+
background: #0056b3;
|
| 311 |
+
}
|
| 312 |
+
|
| 313 |
+
/* =========================
|
| 314 |
+
RESPONSIVE DESIGN
|
| 315 |
+
========================= */
|
| 316 |
+
@media (max-width: 768px) {
|
| 317 |
+
.sidebar {
|
| 318 |
+
width: 200px;
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
.main-content {
|
| 322 |
+
margin-left: 200px;
|
| 323 |
+
padding: 20px;
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
#chatbot-widget {
|
| 327 |
+
width: 90%;
|
| 328 |
+
right: 5%;
|
| 329 |
+
height: 70%;
|
| 330 |
+
}
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
/* =========================
|
| 334 |
+
SMOOTH BUTTON ANIMATION
|
| 335 |
+
========================= */
|
| 336 |
+
button {
|
| 337 |
+
transition: all 0.2s ease;
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
button:active {
|
| 341 |
+
transform: scale(0.95);
|
| 342 |
+
}
|
static/js/chatbot.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
window.sendMessage = async function () {
|
| 2 |
+
const inputField = document.getElementById("user-input");
|
| 3 |
+
const input = inputField.value.trim();
|
| 4 |
+
|
| 5 |
+
if (!input) return;
|
| 6 |
+
|
| 7 |
+
const chatBody = document.getElementById("chat-body");
|
| 8 |
+
|
| 9 |
+
chatBody.innerHTML += `<p><strong>You:</strong> ${input}</p>`;
|
| 10 |
+
|
| 11 |
+
inputField.value = "";
|
| 12 |
+
|
| 13 |
+
const response = await fetch("/chat", {
|
| 14 |
+
method: "POST",
|
| 15 |
+
headers: { "Content-Type": "application/json" },
|
| 16 |
+
body: JSON.stringify({ message: input })
|
| 17 |
+
});
|
| 18 |
+
|
| 19 |
+
const data = await response.json();
|
| 20 |
+
|
| 21 |
+
chatBody.innerHTML += `<p><strong>Bot:</strong> ${data.response}</p>`;
|
| 22 |
+
|
| 23 |
+
chatBody.scrollTop = chatBody.scrollHeight;
|
| 24 |
+
};
|
static/uploads/2025-01-26T17-12_export.csv
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
,question,product,price,features,ratings,discount,Timestamp
|
| 2 |
+
30,can you tell me some more offers,Unknown,,,,,2025-01-26T22:42:03.025
|
| 3 |
+
31,tell me about smartphone,"""Smartphone X""",$499,"""5G, 128GB storage""",4.5,15,2025-01-26T22:42:03.025
|
| 4 |
+
32,summer offers,"AC,Aircoolers","5,50,06,000",capacity additional life,4.6,40%,2025-01-26T22:42:03.025
|
| 5 |
+
33,what is the price of smartphone,iPhone 13,999,"Camera, 5G",4.5,20%,2025-01-26T22:42:03.025
|
| 6 |
+
34,what is the price of iPhone,iPhone 13,999,"Camera, 5G",4.5,20%,2025-01-26T22:42:03.025
|
| 7 |
+
35,what is the price of laptops,"""MacBook Pro""",$1999,"""16GB RAM, M1 chip""",4.9,5,2025-01-26T22:42:03.025
|
| 8 |
+
36,can we exploit latest laptop price,"""MacBook Pro""",$1999,"""16GB RAM, M1 chip""",4.9,5,2025-01-26T22:42:03.025
|
| 9 |
+
37,what is the price of laptops,"""MacBook Pro""",$1999,"""16GB RAM, M1 chip""",4.9,5,2025-01-26T22:42:03.025
|
| 10 |
+
38,can you give some latest mobile models with my mobile phones,oneplus phone,999,"Camera, OLED",4.5,,2025-01-26T22:42:03.025
|
| 11 |
+
39,what is the price of iPhone,$799,10%,4.7,"6.1-inch display, A15 Bionic chip, 12MP camera",2025-01-26 21:12:01.191016,2025-01-26T22:42:03.025
|
static/uploads/2026-04-10T06-45_export.csv
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
,name,score,timestamp
|
| 2 |
+
0,sss,15,2026-03-02T15:55:51.576026+00:00
|
static/uploads/20260508201204_energy_data.csv
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
company,month,energy_consumption_kwh,renewable_energy_percent,carbon_emission_tons,waste_recycled_percent,water_usage_liters,sustainability_score
|
| 2 |
+
GreenTech Industries,January,86,46,82,17,22,14
|
| 3 |
+
GreenTech Industries,February,42,78,18,61,81,61
|
| 4 |
+
GreenTech Industries,March,56,65,97,42,36,81
|
| 5 |
+
GreenTech Industries,April,11,87,53,41,76,59
|
| 6 |
+
GreenTech Industries,May,58,10,80,23,80,43
|
| 7 |
+
GreenTech Industries,July,17,79,92,71,66,60
|
| 8 |
+
GreenTech Industries,August,34,99,28,86,88,69
|
| 9 |
+
GreenTech Industries,September,89,52,62,32,53,61
|
| 10 |
+
GreenTech Industries,October,88,92,99,93,98,45
|
| 11 |
+
GreenTech Industries,November,71,62,71,89,44,89
|
| 12 |
+
GreenTech Industries,December,26,80,54,58,25,90
|
| 13 |
+
EcoSmart Solutions,January,72,38,29,75,74,62
|
| 14 |
+
EcoSmart Solutions,February,82,44,71,35,39,57
|
| 15 |
+
EcoSmart Solutions,March,61,75,74,67,98,49
|
| 16 |
+
EcoSmart Solutions,April,82,26,85,47,61,100
|
| 17 |
+
EcoSmart Solutions,May,28,27,56,48,62,18
|
| 18 |
+
EcoSmart Solutions,June,16,91,26,36,73,24
|
| 19 |
+
EcoSmart Solutions,July,90,14,25,16,35,85
|
| 20 |
+
EcoSmart Solutions,August,57,56,54,55,15,55
|
| 21 |
+
EcoSmart Solutions,September,98,59,43,71,91,65
|
| 22 |
+
EcoSmart Solutions,October,100,77,49,57,69,63
|
| 23 |
+
EcoSmart Solutions,November,43,67,61,59,55,53
|
| 24 |
+
EcoSmart Solutions,December,14,55,73,19,63,84
|
| 25 |
+
SunPower Manufacturing,January,47,96,53,46,95,78
|
| 26 |
+
SunPower Manufacturing,February,89,30,100,44,30,10
|
| 27 |
+
SunPower Manufacturing,March,61,95,38,95,64,57
|
| 28 |
+
SunPower Manufacturing,April,29,84,48,56,72,97
|
| 29 |
+
SunPower Manufacturing,May,46,26,56,97,80,78
|
| 30 |
+
SunPower Manufacturing,June,20,65,33,70,47,29
|
| 31 |
+
SunPower Manufacturing,July,22,51,27,71,20,87
|
| 32 |
+
SunPower Manufacturing,August,21,63,24,17,94,73
|
| 33 |
+
SunPower Manufacturing,September,96,84,47,27,56,18
|
| 34 |
+
SunPower Manufacturing,October,28,84,93,53,86,98
|
| 35 |
+
SunPower Manufacturing,November,80,72,71,48,46,100
|
| 36 |
+
SunPower Manufacturing,December,58,62,98,86,52,53
|
static/uploads/20260508201757_energy_data_new (1).xlsx
ADDED
|
Binary file (12 kB). View file
|
|
|
static/uploads/20260508201815_leaderboard (10).csv
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name,score,question,answer,correct,topic,avatar
|
| 2 |
+
ashif,40,"What is 5 * 12?, Who won the first-ever IPL match?, What is the square root of 64?, Which IPL team is known as the 'Yellow Army'?","60, Kolkata Knight Riders, 8, Chennai Super Kings","Yes, Yes, Yes, Yes","Math, IPL",🐱
|
| 3 |
+
Muthuraja L,30,"What is 5 * 12?, What is the chemical symbol for water?, What is the speed of light?, What is 15 + 7?","60, 299792458 m/s, 299792458 m/s, 22","Yes, No, Yes, Yes","Math, Science",🐱
|
| 4 |
+
Muthuraja L,30,"What is 5 * 12?, Which IPL team is known as the 'Yellow Army'?, What is the value of pi?, Who won the first-ever IPL match?","60, Chennai Super Kings, 3.14, Royal Challengers Bangalore","Yes, Yes, Yes, No","Math, IPL",🐱
|
| 5 |
+
vignesh,20,"What is the powerhouse of the cell?, Who hit the most sixes in the 2020 IPL season?, Who is the all-time highest run-scorer in IPL history?, Who developed the theory of relativity?","Nucleus, Shivam Dube, Virat Kohli, Albert Einstein","No, No, Yes, Yes","Science, IPL",🎮
|
| 6 |
+
Muthuraja L,2,,,,,🐱
|
| 7 |
+
faizal,0,"What planet is known as the Red Planet?, What is the speed of light?, Which team has won the maximum number of IPL titles?, Which IPL player has the most wickets?","Venus, 150000000 m/s, Delhi Capitals, Jasprit Bumrah","No, No, No, No","Science, IPL",🐱
|
| 8 |
+
vignesh,0,,,,"Science, Math",👽
|
static/uploads/20260508202505_leaderboard (10).csv
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name,score,question,answer,correct,topic,avatar
|
| 2 |
+
ashif,40,"What is 5 * 12?, Who won the first-ever IPL match?, What is the square root of 64?, Which IPL team is known as the 'Yellow Army'?","60, Kolkata Knight Riders, 8, Chennai Super Kings","Yes, Yes, Yes, Yes","Math, IPL",🐱
|
| 3 |
+
Muthuraja L,30,"What is 5 * 12?, What is the chemical symbol for water?, What is the speed of light?, What is 15 + 7?","60, 299792458 m/s, 299792458 m/s, 22","Yes, No, Yes, Yes","Math, Science",🐱
|
| 4 |
+
Muthuraja L,30,"What is 5 * 12?, Which IPL team is known as the 'Yellow Army'?, What is the value of pi?, Who won the first-ever IPL match?","60, Chennai Super Kings, 3.14, Royal Challengers Bangalore","Yes, Yes, Yes, No","Math, IPL",🐱
|
| 5 |
+
vignesh,20,"What is the powerhouse of the cell?, Who hit the most sixes in the 2020 IPL season?, Who is the all-time highest run-scorer in IPL history?, Who developed the theory of relativity?","Nucleus, Shivam Dube, Virat Kohli, Albert Einstein","No, No, Yes, Yes","Science, IPL",🎮
|
| 6 |
+
Muthuraja L,2,,,,,🐱
|
| 7 |
+
faizal,0,"What planet is known as the Red Planet?, What is the speed of light?, Which team has won the maximum number of IPL titles?, Which IPL player has the most wickets?","Venus, 150000000 m/s, Delhi Capitals, Jasprit Bumrah","No, No, No, No","Science, IPL",🐱
|
| 8 |
+
vignesh,0,,,,"Science, Math",👽
|
static/uploads/20260508203002_energy_data.csv
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
company,month,energy_consumption_kwh,renewable_energy_percent,carbon_emission_tons,waste_recycled_percent,water_usage_liters,sustainability_score
|
| 2 |
+
GreenTech Industries,January,86,46,82,17,22,14
|
| 3 |
+
GreenTech Industries,February,42,78,18,61,81,61
|
| 4 |
+
GreenTech Industries,March,56,65,97,42,36,81
|
| 5 |
+
GreenTech Industries,April,11,87,53,41,76,59
|
| 6 |
+
GreenTech Industries,May,58,10,80,23,80,43
|
| 7 |
+
GreenTech Industries,July,17,79,92,71,66,60
|
| 8 |
+
GreenTech Industries,August,34,99,28,86,88,69
|
| 9 |
+
GreenTech Industries,September,89,52,62,32,53,61
|
| 10 |
+
GreenTech Industries,October,88,92,99,93,98,45
|
| 11 |
+
GreenTech Industries,November,71,62,71,89,44,89
|
| 12 |
+
GreenTech Industries,December,26,80,54,58,25,90
|
| 13 |
+
EcoSmart Solutions,January,72,38,29,75,74,62
|
| 14 |
+
EcoSmart Solutions,February,82,44,71,35,39,57
|
| 15 |
+
EcoSmart Solutions,March,61,75,74,67,98,49
|
| 16 |
+
EcoSmart Solutions,April,82,26,85,47,61,100
|
| 17 |
+
EcoSmart Solutions,May,28,27,56,48,62,18
|
| 18 |
+
EcoSmart Solutions,June,16,91,26,36,73,24
|
| 19 |
+
EcoSmart Solutions,July,90,14,25,16,35,85
|
| 20 |
+
EcoSmart Solutions,August,57,56,54,55,15,55
|
| 21 |
+
EcoSmart Solutions,September,98,59,43,71,91,65
|
| 22 |
+
EcoSmart Solutions,October,100,77,49,57,69,63
|
| 23 |
+
EcoSmart Solutions,November,43,67,61,59,55,53
|
| 24 |
+
EcoSmart Solutions,December,14,55,73,19,63,84
|
| 25 |
+
SunPower Manufacturing,January,47,96,53,46,95,78
|
| 26 |
+
SunPower Manufacturing,February,89,30,100,44,30,10
|
| 27 |
+
SunPower Manufacturing,March,61,95,38,95,64,57
|
| 28 |
+
SunPower Manufacturing,April,29,84,48,56,72,97
|
| 29 |
+
SunPower Manufacturing,May,46,26,56,97,80,78
|
| 30 |
+
SunPower Manufacturing,June,20,65,33,70,47,29
|
| 31 |
+
SunPower Manufacturing,July,22,51,27,71,20,87
|
| 32 |
+
SunPower Manufacturing,August,21,63,24,17,94,73
|
| 33 |
+
SunPower Manufacturing,September,96,84,47,27,56,18
|
| 34 |
+
SunPower Manufacturing,October,28,84,93,53,86,98
|
| 35 |
+
SunPower Manufacturing,November,80,72,71,48,46,100
|
| 36 |
+
SunPower Manufacturing,December,58,62,98,86,52,53
|
static/uploads/20260509125750_leaderboard (10).csv
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name,score,question,answer,correct,topic,avatar
|
| 2 |
+
ashif,40,"What is 5 * 12?, Who won the first-ever IPL match?, What is the square root of 64?, Which IPL team is known as the 'Yellow Army'?","60, Kolkata Knight Riders, 8, Chennai Super Kings","Yes, Yes, Yes, Yes","Math, IPL",🐱
|
| 3 |
+
Muthuraja L,30,"What is 5 * 12?, What is the chemical symbol for water?, What is the speed of light?, What is 15 + 7?","60, 299792458 m/s, 299792458 m/s, 22","Yes, No, Yes, Yes","Math, Science",🐱
|
| 4 |
+
Muthuraja L,30,"What is 5 * 12?, Which IPL team is known as the 'Yellow Army'?, What is the value of pi?, Who won the first-ever IPL match?","60, Chennai Super Kings, 3.14, Royal Challengers Bangalore","Yes, Yes, Yes, No","Math, IPL",🐱
|
| 5 |
+
vignesh,20,"What is the powerhouse of the cell?, Who hit the most sixes in the 2020 IPL season?, Who is the all-time highest run-scorer in IPL history?, Who developed the theory of relativity?","Nucleus, Shivam Dube, Virat Kohli, Albert Einstein","No, No, Yes, Yes","Science, IPL",🎮
|
| 6 |
+
Muthuraja L,2,,,,,🐱
|
| 7 |
+
faizal,0,"What planet is known as the Red Planet?, What is the speed of light?, Which team has won the maximum number of IPL titles?, Which IPL player has the most wickets?","Venus, 150000000 m/s, Delhi Capitals, Jasprit Bumrah","No, No, No, No","Science, IPL",🐱
|
| 8 |
+
vignesh,0,,,,"Science, Math",👽
|
static/uploads/Ai questions.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
topic,question,option_1,option_2,option_3,option_4,answer
|
static/uploads/data.csv
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name,score,question,answer,correct,topic,avatar
|
| 2 |
+
ashif,40,"What is 5 * 12?, Who won the first-ever IPL match?, What is the square root of 64?, Which IPL team is known as the 'Yellow Army'?","60, Kolkata Knight Riders, 8, Chennai Super Kings","Yes, Yes, Yes, Yes","Math, IPL",🐱
|
| 3 |
+
Muthuraja L,30,"What is 5 * 12?, What is the chemical symbol for water?, What is the speed of light?, What is 15 + 7?","60, 299792458 m/s, 299792458 m/s, 22","Yes, No, Yes, Yes","Math, Science",🐱
|
| 4 |
+
Muthuraja L,30,"What is 5 * 12?, Which IPL team is known as the 'Yellow Army'?, What is the value of pi?, Who won the first-ever IPL match?","60, Chennai Super Kings, 3.14, Royal Challengers Bangalore","Yes, Yes, Yes, No","Math, IPL",🐱
|
| 5 |
+
vignesh,20,"What is the powerhouse of the cell?, Who hit the most sixes in the 2020 IPL season?, Who is the all-time highest run-scorer in IPL history?, Who developed the theory of relativity?","Nucleus, Shivam Dube, Virat Kohli, Albert Einstein","No, No, Yes, Yes","Science, IPL",🎮
|
| 6 |
+
Muthuraja L,2,,,,,🐱
|
| 7 |
+
faizal,0,"What planet is known as the Red Planet?, What is the speed of light?, Which team has won the maximum number of IPL titles?, Which IPL player has the most wickets?","Venus, 150000000 m/s, Delhi Capitals, Jasprit Bumrah","No, No, No, No","Science, IPL",🐱
|
| 8 |
+
vignesh,0,,,,"Science, Math",👽
|
static/uploads/energy_data.csv
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
company,month,energy_consumption_kwh,renewable_energy_percent,carbon_emission_tons,waste_recycled_percent,water_usage_liters,sustainability_score
|
| 2 |
+
GreenTech Industries,January,86,46,82,17,22,14
|
| 3 |
+
GreenTech Industries,February,42,78,18,61,81,61
|
| 4 |
+
GreenTech Industries,March,56,65,97,42,36,81
|
| 5 |
+
GreenTech Industries,April,11,87,53,41,76,59
|
| 6 |
+
GreenTech Industries,May,58,10,80,23,80,43
|
| 7 |
+
GreenTech Industries,July,17,79,92,71,66,60
|
| 8 |
+
GreenTech Industries,August,34,99,28,86,88,69
|
| 9 |
+
GreenTech Industries,September,89,52,62,32,53,61
|
| 10 |
+
GreenTech Industries,October,88,92,99,93,98,45
|
| 11 |
+
GreenTech Industries,November,71,62,71,89,44,89
|
| 12 |
+
GreenTech Industries,December,26,80,54,58,25,90
|
| 13 |
+
EcoSmart Solutions,January,72,38,29,75,74,62
|
| 14 |
+
EcoSmart Solutions,February,82,44,71,35,39,57
|
| 15 |
+
EcoSmart Solutions,March,61,75,74,67,98,49
|
| 16 |
+
EcoSmart Solutions,April,82,26,85,47,61,100
|
| 17 |
+
EcoSmart Solutions,May,28,27,56,48,62,18
|
| 18 |
+
EcoSmart Solutions,June,16,91,26,36,73,24
|
| 19 |
+
EcoSmart Solutions,July,90,14,25,16,35,85
|
| 20 |
+
EcoSmart Solutions,August,57,56,54,55,15,55
|
| 21 |
+
EcoSmart Solutions,September,98,59,43,71,91,65
|
| 22 |
+
EcoSmart Solutions,October,100,77,49,57,69,63
|
| 23 |
+
EcoSmart Solutions,November,43,67,61,59,55,53
|
| 24 |
+
EcoSmart Solutions,December,14,55,73,19,63,84
|
| 25 |
+
SunPower Manufacturing,January,47,96,53,46,95,78
|
| 26 |
+
SunPower Manufacturing,February,89,30,100,44,30,10
|
| 27 |
+
SunPower Manufacturing,March,61,95,38,95,64,57
|
| 28 |
+
SunPower Manufacturing,April,29,84,48,56,72,97
|
| 29 |
+
SunPower Manufacturing,May,46,26,56,97,80,78
|
| 30 |
+
SunPower Manufacturing,June,20,65,33,70,47,29
|
| 31 |
+
SunPower Manufacturing,July,22,51,27,71,20,87
|
| 32 |
+
SunPower Manufacturing,August,21,63,24,17,94,73
|
| 33 |
+
SunPower Manufacturing,September,96,84,47,27,56,18
|
| 34 |
+
SunPower Manufacturing,October,28,84,93,53,86,98
|
| 35 |
+
SunPower Manufacturing,November,80,72,71,48,46,100
|
| 36 |
+
SunPower Manufacturing,December,58,62,98,86,52,53
|
static/uploads/energy_data_new (1).xlsx
ADDED
|
Binary file (12 kB). View file
|
|
|
static/uploads/energy_data_new.xlsx
ADDED
|
Binary file (13.8 kB). View file
|
|
|
static/uploads/leaderboard (10).csv
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name,score,question,answer,correct,topic,avatar
|
| 2 |
+
ashif,40,"What is 5 * 12?, Who won the first-ever IPL match?, What is the square root of 64?, Which IPL team is known as the 'Yellow Army'?","60, Kolkata Knight Riders, 8, Chennai Super Kings","Yes, Yes, Yes, Yes","Math, IPL",🐱
|
| 3 |
+
Muthuraja L,30,"What is 5 * 12?, What is the chemical symbol for water?, What is the speed of light?, What is 15 + 7?","60, 299792458 m/s, 299792458 m/s, 22","Yes, No, Yes, Yes","Math, Science",🐱
|
| 4 |
+
Muthuraja L,30,"What is 5 * 12?, Which IPL team is known as the 'Yellow Army'?, What is the value of pi?, Who won the first-ever IPL match?","60, Chennai Super Kings, 3.14, Royal Challengers Bangalore","Yes, Yes, Yes, No","Math, IPL",🐱
|
| 5 |
+
vignesh,20,"What is the powerhouse of the cell?, Who hit the most sixes in the 2020 IPL season?, Who is the all-time highest run-scorer in IPL history?, Who developed the theory of relativity?","Nucleus, Shivam Dube, Virat Kohli, Albert Einstein","No, No, Yes, Yes","Science, IPL",🎮
|
| 6 |
+
Muthuraja L,2,,,,,🐱
|
| 7 |
+
faizal,0,"What planet is known as the Red Planet?, What is the speed of light?, Which team has won the maximum number of IPL titles?, Which IPL player has the most wickets?","Venus, 150000000 m/s, Delhi Capitals, Jasprit Bumrah","No, No, No, No","Science, IPL",🐱
|
| 8 |
+
vignesh,0,,,,"Science, Math",👽
|
templates/analytics.html
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
<!DOCTYPE html>
|
| 3 |
+
<html lang="en">
|
| 4 |
+
<head>
|
| 5 |
+
<meta charset="UTF-8">
|
| 6 |
+
<title>Smart AI CRM Analytics</title>
|
| 7 |
+
|
| 8 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
| 9 |
+
<script src="{{ url_for('static', filename='js/chatbot.js') }}"></script>
|
| 10 |
+
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
| 11 |
+
|
| 12 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 13 |
+
</head>
|
| 14 |
+
<body>
|
| 15 |
+
|
| 16 |
+
<div class="dashboard-layout">
|
| 17 |
+
|
| 18 |
+
<!-- SAME SIDEBAR -->
|
| 19 |
+
<div class="sidebar">
|
| 20 |
+
<h2>CRM AI</h2>
|
| 21 |
+
<ul>
|
| 22 |
+
<li><a href="/dashboard">Dashboard</a></li>
|
| 23 |
+
<li><a href="/analytics">Analytics</a></li>
|
| 24 |
+
<li>Energy Data</li>
|
| 25 |
+
<li>Reports</li>
|
| 26 |
+
</ul>
|
| 27 |
+
</div>
|
| 28 |
+
|
| 29 |
+
<!-- MAIN CONTENT -->
|
| 30 |
+
<div class="main-content">
|
| 31 |
+
|
| 32 |
+
<header>
|
| 33 |
+
<h1>Analytics Dashboard</h1>
|
| 34 |
+
</header>
|
| 35 |
+
|
| 36 |
+
<!-- CHART ONLY -->
|
| 37 |
+
<div class="chart-section">
|
| 38 |
+
<canvas id="myChart"></canvas>
|
| 39 |
+
</div>
|
| 40 |
+
|
| 41 |
+
</div>
|
| 42 |
+
</div>
|
| 43 |
+
|
| 44 |
+
<!-- SAME CHATBOT -->
|
| 45 |
+
<button id="chatbot-toggle" onclick="toggleChatbot()">💬</button>
|
| 46 |
+
|
| 47 |
+
<div id="chatbot-widget">
|
| 48 |
+
|
| 49 |
+
<div id="chat-header">
|
| 50 |
+
<span>🤖 AI Assistant</span>
|
| 51 |
+
<button onclick="toggleChatbot()">✖</button>
|
| 52 |
+
</div>
|
| 53 |
+
|
| 54 |
+
<div id="chat-messages">
|
| 55 |
+
<div class="bot-message">
|
| 56 |
+
<strong>Bot:</strong> Hello! Ask me about dashboard, CSV data, or sustainability insights.
|
| 57 |
+
</div>
|
| 58 |
+
</div>
|
| 59 |
+
|
| 60 |
+
<div id="chat-input-area">
|
| 61 |
+
<input type="text" id="chat-input" placeholder="Ask something..."
|
| 62 |
+
onkeypress="if(event.key==='Enter') sendMessage()">
|
| 63 |
+
<button onclick="sendMessage()">Send</button>
|
| 64 |
+
</div>
|
| 65 |
+
|
| 66 |
+
</div>
|
| 67 |
+
|
| 68 |
+
<script>
|
| 69 |
+
window.onload = async function () {
|
| 70 |
+
const fileId = localStorage.getItem("uploadedFileId");
|
| 71 |
+
|
| 72 |
+
if (!fileId) {
|
| 73 |
+
alert("No uploaded file found.");
|
| 74 |
+
window.location.href = "/dashboard";
|
| 75 |
+
return;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
try {
|
| 79 |
+
const res = await fetch(`/analytics-data/${fileId}`);
|
| 80 |
+
const result = await res.json();
|
| 81 |
+
|
| 82 |
+
if (!result.success || !result.data) {
|
| 83 |
+
alert("No analytics data found.");
|
| 84 |
+
window.location.href = "/dashboard";
|
| 85 |
+
return;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
const data = result.data;
|
| 89 |
+
const ctx = document.getElementById("myChart").getContext("2d");
|
| 90 |
+
|
| 91 |
+
new Chart(ctx, {
|
| 92 |
+
type: "bar",
|
| 93 |
+
data: {
|
| 94 |
+
labels: data.labels,
|
| 95 |
+
datasets: data.datasets
|
| 96 |
+
},
|
| 97 |
+
options: {
|
| 98 |
+
responsive: true,
|
| 99 |
+
maintainAspectRatio: false,
|
| 100 |
+
scales: {
|
| 101 |
+
y: {
|
| 102 |
+
beginAtZero: true
|
| 103 |
+
}
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
});
|
| 107 |
+
|
| 108 |
+
} catch (err) {
|
| 109 |
+
alert("Failed to load analytics data.");
|
| 110 |
+
window.location.href = "/dashboard";
|
| 111 |
+
}
|
| 112 |
+
};
|
| 113 |
+
</script>
|
| 114 |
+
</body>
|
| 115 |
+
</html>
|
| 116 |
+
|
templates/chatbot.html
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<title>AI Chatbot</title>
|
| 6 |
+
|
| 7 |
+
<style>
|
| 8 |
+
/* CHATBOT BUTTON */
|
| 9 |
+
#chatbot-toggle {
|
| 10 |
+
position: fixed;
|
| 11 |
+
bottom: 20px;
|
| 12 |
+
right: 20px;
|
| 13 |
+
background: #007bff;
|
| 14 |
+
color: white;
|
| 15 |
+
border: none;
|
| 16 |
+
padding: 15px;
|
| 17 |
+
border-radius: 50%;
|
| 18 |
+
cursor: pointer;
|
| 19 |
+
font-size: 18px;
|
| 20 |
+
z-index: 1000;
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
/* CHATBOT WINDOW */
|
| 24 |
+
#chatbot-widget {
|
| 25 |
+
position: fixed;
|
| 26 |
+
bottom: 80px;
|
| 27 |
+
right: 20px;
|
| 28 |
+
width: 320px;
|
| 29 |
+
height: 420px;
|
| 30 |
+
background: white;
|
| 31 |
+
border-radius: 10px;
|
| 32 |
+
box-shadow: 0 0 15px rgba(0,0,0,0.2);
|
| 33 |
+
display: none;
|
| 34 |
+
flex-direction: column;
|
| 35 |
+
overflow: hidden;
|
| 36 |
+
z-index: 1000;
|
| 37 |
+
font-family: Arial;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
/* HEADER */
|
| 41 |
+
#chat-header {
|
| 42 |
+
background: #007bff;
|
| 43 |
+
color: white;
|
| 44 |
+
padding: 10px;
|
| 45 |
+
display: flex;
|
| 46 |
+
justify-content: space-between;
|
| 47 |
+
align-items: center;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
/* CHAT BODY */
|
| 51 |
+
#chat-messages {
|
| 52 |
+
flex: 1;
|
| 53 |
+
padding: 10px;
|
| 54 |
+
overflow-y: auto;
|
| 55 |
+
font-size: 14px;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
/* INPUT AREA */
|
| 59 |
+
#chat-input-area {
|
| 60 |
+
display: flex;
|
| 61 |
+
border-top: 1px solid #ddd;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
#chat-input {
|
| 65 |
+
flex: 1;
|
| 66 |
+
padding: 10px;
|
| 67 |
+
border: none;
|
| 68 |
+
outline: none;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
#chat-input-area button {
|
| 72 |
+
padding: 10px;
|
| 73 |
+
background: #007bff;
|
| 74 |
+
color: white;
|
| 75 |
+
border: none;
|
| 76 |
+
cursor: pointer;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
/* MESSAGES */
|
| 80 |
+
.user-message {
|
| 81 |
+
text-align: right;
|
| 82 |
+
margin: 5px 0;
|
| 83 |
+
color: #333;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
.bot-message {
|
| 87 |
+
text-align: left;
|
| 88 |
+
margin: 5px 0;
|
| 89 |
+
color: #007bff;
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
.error-message {
|
| 93 |
+
color: red;
|
| 94 |
+
}
|
| 95 |
+
</style>
|
| 96 |
+
</head>
|
| 97 |
+
|
| 98 |
+
<body>
|
| 99 |
+
|
| 100 |
+
<!-- CHATBOT WINDOW -->
|
| 101 |
+
<div id="chatbot-widget">
|
| 102 |
+
|
| 103 |
+
<div id="chat-header">
|
| 104 |
+
<span>🤖 AI Assistant</span>
|
| 105 |
+
<button onclick="toggleChatbot()">✖</button>
|
| 106 |
+
</div>
|
| 107 |
+
|
| 108 |
+
<div id="chat-messages">
|
| 109 |
+
<div class="bot-message">
|
| 110 |
+
<strong>Bot:</strong> Hello! Ask me about your dashboard, sustainability, or any general questions.
|
| 111 |
+
</div>
|
| 112 |
+
</div>
|
| 113 |
+
|
| 114 |
+
<div id="chat-input-area">
|
| 115 |
+
<input type="text" id="chat-input" placeholder="Ask something..."
|
| 116 |
+
onkeypress="if(event.key==='Enter') sendMessage()">
|
| 117 |
+
<button onclick="sendMessage()">Send</button>
|
| 118 |
+
</div>
|
| 119 |
+
|
| 120 |
+
</div>
|
| 121 |
+
|
| 122 |
+
<!-- FLOAT BUTTON -->
|
| 123 |
+
<button id="chatbot-toggle" onclick="toggleChatbot()">💬</button>
|
| 124 |
+
|
| 125 |
+
<script>
|
| 126 |
+
function toggleChatbot() {
|
| 127 |
+
const widget = document.getElementById("chatbot-widget");
|
| 128 |
+
widget.style.display = (widget.style.display === "flex") ? "none" : "flex";
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
async function sendMessage() {
|
| 132 |
+
const input = document.getElementById("chat-input");
|
| 133 |
+
const message = input.value.trim();
|
| 134 |
+
if (!message) return;
|
| 135 |
+
|
| 136 |
+
const chatBox = document.getElementById("chat-messages");
|
| 137 |
+
|
| 138 |
+
// USER MESSAGE
|
| 139 |
+
chatBox.innerHTML += `
|
| 140 |
+
<div class="user-message"><strong>You:</strong> ${message}</div>
|
| 141 |
+
`;
|
| 142 |
+
|
| 143 |
+
input.value = "";
|
| 144 |
+
|
| 145 |
+
// TYPING INDICATOR
|
| 146 |
+
chatBox.innerHTML += `
|
| 147 |
+
<div class="bot-message" id="typing">Bot: Typing...</div>
|
| 148 |
+
`;
|
| 149 |
+
|
| 150 |
+
chatBox.scrollTop = chatBox.scrollHeight;
|
| 151 |
+
|
| 152 |
+
try {
|
| 153 |
+
const res = await fetch("/chat", {
|
| 154 |
+
method: "POST",
|
| 155 |
+
headers: {"Content-Type": "application/json"},
|
| 156 |
+
body: JSON.stringify({ message })
|
| 157 |
+
});
|
| 158 |
+
|
| 159 |
+
const data = await res.json();
|
| 160 |
+
|
| 161 |
+
document.getElementById("typing")?.remove();
|
| 162 |
+
|
| 163 |
+
chatBox.innerHTML += `
|
| 164 |
+
<div class="bot-message"><strong>Bot:</strong> ${data.response}</div>
|
| 165 |
+
`;
|
| 166 |
+
}
|
| 167 |
+
catch (err) {
|
| 168 |
+
document.getElementById("typing")?.remove();
|
| 169 |
+
|
| 170 |
+
chatBox.innerHTML += `
|
| 171 |
+
<div class="bot-message error-message">
|
| 172 |
+
Bot: Error connecting to server.
|
| 173 |
+
</div>
|
| 174 |
+
`;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
chatBox.scrollTop = chatBox.scrollHeight;
|
| 178 |
+
}
|
| 179 |
+
</script>
|
| 180 |
+
|
| 181 |
+
</body>
|
| 182 |
+
</html>
|
templates/dashboard.html
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<title>Smart AI CRM Dashboard</title>
|
| 6 |
+
|
| 7 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 8 |
+
|
| 9 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
| 10 |
+
|
| 11 |
+
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
| 12 |
+
|
| 13 |
+
<style>
|
| 14 |
+
/* CHAT FLOAT BUTTON */
|
| 15 |
+
/* ================= UPLOAD SECTION STYLING ================= */
|
| 16 |
+
|
| 17 |
+
.upload-section {
|
| 18 |
+
margin: 20px 0;
|
| 19 |
+
display: flex;
|
| 20 |
+
justify-content: flex-start;
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
#uploadForm {
|
| 24 |
+
display: flex;
|
| 25 |
+
align-items: center;
|
| 26 |
+
gap: 12px;
|
| 27 |
+
background: #f5f7ff;
|
| 28 |
+
padding: 15px 20px;
|
| 29 |
+
border-radius: 12px;
|
| 30 |
+
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
| 31 |
+
width: fit-content;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
/* FILE INPUT CUSTOM DESIGN */
|
| 35 |
+
#uploadForm input[type="file"] {
|
| 36 |
+
border: 2px dashed #007bff;
|
| 37 |
+
padding: 10px;
|
| 38 |
+
border-radius: 8px;
|
| 39 |
+
background: white;
|
| 40 |
+
cursor: pointer;
|
| 41 |
+
transition: 0.3s ease;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
/* Hover effect */
|
| 45 |
+
#uploadForm input[type="file"]:hover {
|
| 46 |
+
border-color: #0056b3;
|
| 47 |
+
background: #f0f8ff;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
/* BUTTON STYLE */
|
| 51 |
+
#uploadForm button {
|
| 52 |
+
padding: 10px 18px;
|
| 53 |
+
background: linear-gradient(135deg, #007bff, #00c6ff);
|
| 54 |
+
color: white;
|
| 55 |
+
border: none;
|
| 56 |
+
border-radius: 8px;
|
| 57 |
+
font-weight: bold;
|
| 58 |
+
cursor: pointer;
|
| 59 |
+
transition: 0.3s ease;
|
| 60 |
+
box-shadow: 0 3px 8px rgba(0,123,255,0.3);
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
/* Hover button */
|
| 64 |
+
#uploadForm button:hover {
|
| 65 |
+
transform: scale(1.05);
|
| 66 |
+
box-shadow: 0 5px 15px rgba(0,123,255,0.4);
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
/* FILE NAME TEXT LOOK (optional enhancement) */
|
| 70 |
+
#uploadForm input[type="file"]::file-selector-button {
|
| 71 |
+
background: #007bff;
|
| 72 |
+
color: white;
|
| 73 |
+
border: none;
|
| 74 |
+
padding: 8px 12px;
|
| 75 |
+
border-radius: 6px;
|
| 76 |
+
cursor: pointer;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
#uploadForm input[type="file"]::file-selector-button:hover {
|
| 80 |
+
background: #0056b3;
|
| 81 |
+
}
|
| 82 |
+
#chatbot-toggle {
|
| 83 |
+
position: fixed;
|
| 84 |
+
bottom: 20px;
|
| 85 |
+
right: 20px;
|
| 86 |
+
background: #007bff;
|
| 87 |
+
color: white;
|
| 88 |
+
border: none;
|
| 89 |
+
padding: 15px;
|
| 90 |
+
border-radius: 50%;
|
| 91 |
+
cursor: pointer;
|
| 92 |
+
font-size: 18px;
|
| 93 |
+
z-index: 1000;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
/* CHAT WINDOW */
|
| 97 |
+
#chatbot-widget {
|
| 98 |
+
position: fixed;
|
| 99 |
+
bottom: 80px;
|
| 100 |
+
right: 20px;
|
| 101 |
+
width: 320px;
|
| 102 |
+
height: 420px;
|
| 103 |
+
background: white;
|
| 104 |
+
border-radius: 10px;
|
| 105 |
+
box-shadow: 0 0 15px rgba(0,0,0,0.2);
|
| 106 |
+
display: none;
|
| 107 |
+
flex-direction: column;
|
| 108 |
+
overflow: hidden;
|
| 109 |
+
z-index: 1000;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
#chat-header {
|
| 113 |
+
background: #007bff;
|
| 114 |
+
color: white;
|
| 115 |
+
padding: 10px;
|
| 116 |
+
display: flex;
|
| 117 |
+
justify-content: space-between;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
#chat-messages {
|
| 121 |
+
flex: 1;
|
| 122 |
+
padding: 10px;
|
| 123 |
+
overflow-y: auto;
|
| 124 |
+
font-size: 14px;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
#chat-input-area {
|
| 128 |
+
display: flex;
|
| 129 |
+
border-top: 1px solid #ddd;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
#chat-input {
|
| 133 |
+
flex: 1;
|
| 134 |
+
padding: 10px;
|
| 135 |
+
border: none;
|
| 136 |
+
outline: none;
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
#chat-input-area button {
|
| 140 |
+
background: #007bff;
|
| 141 |
+
color: white;
|
| 142 |
+
border: none;
|
| 143 |
+
padding: 10px;
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
.user-message { text-align: right; margin: 5px; }
|
| 147 |
+
.bot-message { text-align: left; margin: 5px; color: #007bff; }
|
| 148 |
+
.error-message { color: red; }
|
| 149 |
+
|
| 150 |
+
/* LAYOUT */
|
| 151 |
+
.dashboard-layout {
|
| 152 |
+
display: flex;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
.sidebar {
|
| 156 |
+
width: 200px;
|
| 157 |
+
background: #111;
|
| 158 |
+
color: white;
|
| 159 |
+
height: 100vh;
|
| 160 |
+
padding: 10px;
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
.main-content {
|
| 164 |
+
flex: 1;
|
| 165 |
+
padding: 20px;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
.chart-section {
|
| 169 |
+
width: 100%;
|
| 170 |
+
height: 400px;
|
| 171 |
+
}
|
| 172 |
+
</style>
|
| 173 |
+
</head>
|
| 174 |
+
|
| 175 |
+
<body>
|
| 176 |
+
|
| 177 |
+
<div class="dashboard-layout">
|
| 178 |
+
|
| 179 |
+
<!-- SIDEBAR -->
|
| 180 |
+
<div class="sidebar">
|
| 181 |
+
<h2>CRM AI</h2>
|
| 182 |
+
<ul>
|
| 183 |
+
<li>Dashboard</li>
|
| 184 |
+
<li>Analytics</li>
|
| 185 |
+
<li>Reports</li>
|
| 186 |
+
</ul>
|
| 187 |
+
</div>
|
| 188 |
+
|
| 189 |
+
<!-- MAIN -->
|
| 190 |
+
<div class="main-content">
|
| 191 |
+
|
| 192 |
+
<h1>Smart AI Dashboard</h1>
|
| 193 |
+
|
| 194 |
+
<!-- UPLOAD -->
|
| 195 |
+
<form id="uploadForm">
|
| 196 |
+
<input type="file" name="file" required>
|
| 197 |
+
<button type="submit">Upload CSV</button>
|
| 198 |
+
</form>
|
| 199 |
+
|
| 200 |
+
<!-- CHART -->
|
| 201 |
+
<div class="chart-section">
|
| 202 |
+
<canvas id="myChart"></canvas>
|
| 203 |
+
</div>
|
| 204 |
+
|
| 205 |
+
</div>
|
| 206 |
+
</div>
|
| 207 |
+
|
| 208 |
+
<!-- CHAT BUTTON -->
|
| 209 |
+
<button id="chatbot-toggle" onclick="toggleChatbot()">💬</button>
|
| 210 |
+
|
| 211 |
+
<!-- CHAT WINDOW -->
|
| 212 |
+
<div id="chatbot-widget">
|
| 213 |
+
|
| 214 |
+
<div id="chat-header">
|
| 215 |
+
<span>🤖 AI Assistant</span>
|
| 216 |
+
<button onclick="toggleChatbot()">✖</button>
|
| 217 |
+
</div>
|
| 218 |
+
|
| 219 |
+
<div id="chat-messages">
|
| 220 |
+
<div class="bot-message">Bot: Hello! Ask anything about data or dashboard.</div>
|
| 221 |
+
</div>
|
| 222 |
+
|
| 223 |
+
<div id="chat-input-area">
|
| 224 |
+
<input type="text" id="chat-input" placeholder="Ask..."
|
| 225 |
+
onkeypress="if(event.key==='Enter') sendMessage()">
|
| 226 |
+
<button onclick="sendMessage()">Send</button>
|
| 227 |
+
</div>
|
| 228 |
+
|
| 229 |
+
</div>
|
| 230 |
+
|
| 231 |
+
<script>
|
| 232 |
+
|
| 233 |
+
let chartInstance = null;
|
| 234 |
+
|
| 235 |
+
/* ---------------- CHATBOT ---------------- */
|
| 236 |
+
function toggleChatbot() {
|
| 237 |
+
const widget = document.getElementById("chatbot-widget");
|
| 238 |
+
widget.style.display = widget.style.display === "flex" ? "none" : "flex";
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
async function sendMessage() {
|
| 242 |
+
const input = document.getElementById("chat-input");
|
| 243 |
+
const msg = input.value.trim();
|
| 244 |
+
if (!msg) return;
|
| 245 |
+
|
| 246 |
+
const chatBox = document.getElementById("chat-messages");
|
| 247 |
+
|
| 248 |
+
chatBox.innerHTML += `<div class="user-message">You: ${msg}</div>`;
|
| 249 |
+
input.value = "";
|
| 250 |
+
|
| 251 |
+
chatBox.innerHTML += `<div class="bot-message" id="typing">Bot: Thinking...</div>`;
|
| 252 |
+
|
| 253 |
+
try {
|
| 254 |
+
const res = await fetch("/chat", {
|
| 255 |
+
method: "POST",
|
| 256 |
+
headers: {"Content-Type": "application/json"},
|
| 257 |
+
body: JSON.stringify({ message: msg })
|
| 258 |
+
});
|
| 259 |
+
|
| 260 |
+
const data = await res.json();
|
| 261 |
+
document.getElementById("typing")?.remove();
|
| 262 |
+
|
| 263 |
+
chatBox.innerHTML += `<div class="bot-message">Bot: ${data.response}</div>`;
|
| 264 |
+
} catch (err) {
|
| 265 |
+
document.getElementById("typing")?.remove();
|
| 266 |
+
chatBox.innerHTML += `<div class="error-message">Bot: Server error</div>`;
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
chatBox.scrollTop = chatBox.scrollHeight;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
/* ---------------- CSV UPLOAD ---------------- */
|
| 273 |
+
document.getElementById("uploadForm").addEventListener("submit", async (e) => {
|
| 274 |
+
e.preventDefault();
|
| 275 |
+
|
| 276 |
+
const formData = new FormData(e.target);
|
| 277 |
+
|
| 278 |
+
const res = await fetch("/api/upload", {
|
| 279 |
+
method: "POST",
|
| 280 |
+
body: formData
|
| 281 |
+
});
|
| 282 |
+
|
| 283 |
+
const data = await res.json();
|
| 284 |
+
|
| 285 |
+
if (!data.success) {
|
| 286 |
+
alert(data.error || "Upload failed");
|
| 287 |
+
return;
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
drawChart(data);
|
| 291 |
+
});
|
| 292 |
+
|
| 293 |
+
/* ---------------- CHART ---------------- */
|
| 294 |
+
function drawChart(data) {
|
| 295 |
+
const ctx = document.getElementById("myChart").getContext("2d");
|
| 296 |
+
|
| 297 |
+
if (chartInstance) {
|
| 298 |
+
chartInstance.destroy();
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
chartInstance = new Chart(ctx, {
|
| 302 |
+
type: "bar",
|
| 303 |
+
data: {
|
| 304 |
+
labels: data.labels,
|
| 305 |
+
datasets: data.datasets.map(ds => ({
|
| 306 |
+
label: ds.label,
|
| 307 |
+
data: ds.data,
|
| 308 |
+
borderWidth: 1
|
| 309 |
+
}))
|
| 310 |
+
},
|
| 311 |
+
options: {
|
| 312 |
+
responsive: true,
|
| 313 |
+
scales: {
|
| 314 |
+
y: { beginAtZero: true }
|
| 315 |
+
}
|
| 316 |
+
}
|
| 317 |
+
});
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
</script>
|
| 321 |
+
|
| 322 |
+
</body>
|
| 323 |
+
</html>
|
templates/index.html
ADDED
|
File without changes
|
templates/login.html
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- login.html -->
|
| 2 |
+
|
| 3 |
+
<!DOCTYPE html>
|
| 4 |
+
<html lang="en">
|
| 5 |
+
<head>
|
| 6 |
+
<meta charset="UTF-8">
|
| 7 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 8 |
+
<title>Smart Dashboard Login</title>
|
| 9 |
+
|
| 10 |
+
<style>
|
| 11 |
+
*{
|
| 12 |
+
margin: 0;
|
| 13 |
+
padding: 0;
|
| 14 |
+
box-sizing: border-box;
|
| 15 |
+
font-family: Arial, sans-serif;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
body {
|
| 19 |
+
height: 100vh;
|
| 20 |
+
display: flex;
|
| 21 |
+
justify-content: center;
|
| 22 |
+
align-items: center;
|
| 23 |
+
background: linear-gradient(to right, #4facfe, #00f2fe);
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
.container {
|
| 27 |
+
width: 380px;
|
| 28 |
+
background: white;
|
| 29 |
+
padding: 35px;
|
| 30 |
+
border-radius: 15px;
|
| 31 |
+
box-shadow: 0 5px 20px rgba(0,0,0,0.2);
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
h2 {
|
| 35 |
+
text-align: center;
|
| 36 |
+
margin-bottom: 25px;
|
| 37 |
+
color: #333;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
form{
|
| 41 |
+
display: flex;
|
| 42 |
+
flex-direction: column;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
input {
|
| 46 |
+
width: 100%;
|
| 47 |
+
padding: 12px;
|
| 48 |
+
margin: 10px 0;
|
| 49 |
+
border: 1px solid #ccc;
|
| 50 |
+
border-radius: 8px;
|
| 51 |
+
font-size: 15px;
|
| 52 |
+
outline: none;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
input:focus{
|
| 56 |
+
border-color: #4facfe;
|
| 57 |
+
box-shadow: 0 0 5px rgba(79,172,254,0.5);
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
button {
|
| 61 |
+
width: 100%;
|
| 62 |
+
padding: 12px;
|
| 63 |
+
margin-top: 10px;
|
| 64 |
+
background: #007bff;
|
| 65 |
+
color: white;
|
| 66 |
+
border: none;
|
| 67 |
+
border-radius: 8px;
|
| 68 |
+
font-size: 16px;
|
| 69 |
+
cursor: pointer;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
button:hover{
|
| 73 |
+
background: #0056b3;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
a {
|
| 77 |
+
display: block;
|
| 78 |
+
text-align: center;
|
| 79 |
+
margin-top: 18px;
|
| 80 |
+
text-decoration: none;
|
| 81 |
+
color: #007bff;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
a:hover{
|
| 85 |
+
text-decoration: underline;
|
| 86 |
+
}
|
| 87 |
+
</style>
|
| 88 |
+
</head>
|
| 89 |
+
|
| 90 |
+
<body>
|
| 91 |
+
<div class="container">
|
| 92 |
+
<h2>Smart Dashboard Login</h2>
|
| 93 |
+
|
| 94 |
+
<form action="/login" method="POST">
|
| 95 |
+
<input type="email" name="email" placeholder="Email" required>
|
| 96 |
+
|
| 97 |
+
<input type="password" name="password" placeholder="Password" required>
|
| 98 |
+
|
| 99 |
+
<button type="submit">Login</button>
|
| 100 |
+
</form>
|
| 101 |
+
|
| 102 |
+
<a href="/register">Create New Account</a>
|
| 103 |
+
</div>
|
| 104 |
+
</body>
|
| 105 |
+
</html>
|
templates/register.html
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- register.html -->
|
| 2 |
+
|
| 3 |
+
<!DOCTYPE html>
|
| 4 |
+
<html lang="en">
|
| 5 |
+
<head>
|
| 6 |
+
<meta charset="UTF-8">
|
| 7 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 8 |
+
<title>Register</title>
|
| 9 |
+
|
| 10 |
+
<style>
|
| 11 |
+
*{
|
| 12 |
+
margin: 0;
|
| 13 |
+
padding: 0;
|
| 14 |
+
box-sizing: border-box;
|
| 15 |
+
font-family: Arial, sans-serif;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
body{
|
| 19 |
+
height: 100vh;
|
| 20 |
+
display: flex;
|
| 21 |
+
justify-content: center;
|
| 22 |
+
align-items: center;
|
| 23 |
+
background: linear-gradient(to right, #43e97b, #38f9d7);
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
.container{
|
| 27 |
+
background: #fff;
|
| 28 |
+
padding: 40px;
|
| 29 |
+
border-radius: 12px;
|
| 30 |
+
width: 350px;
|
| 31 |
+
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
| 32 |
+
text-align: center;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
.container h2{
|
| 36 |
+
margin-bottom: 25px;
|
| 37 |
+
color: #333;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
form{
|
| 41 |
+
display: flex;
|
| 42 |
+
flex-direction: column;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
input{
|
| 46 |
+
padding: 12px;
|
| 47 |
+
margin-bottom: 15px;
|
| 48 |
+
border: 1px solid #ccc;
|
| 49 |
+
border-radius: 8px;
|
| 50 |
+
font-size: 16px;
|
| 51 |
+
outline: none;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
input:focus{
|
| 55 |
+
border-color: #43e97b;
|
| 56 |
+
box-shadow: 0 0 5px rgba(67,233,123,0.5);
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
button{
|
| 60 |
+
padding: 12px;
|
| 61 |
+
background: #28a745;
|
| 62 |
+
color: white;
|
| 63 |
+
border: none;
|
| 64 |
+
border-radius: 8px;
|
| 65 |
+
font-size: 16px;
|
| 66 |
+
cursor: pointer;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
button:hover{
|
| 70 |
+
background: #1e7e34;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
a{
|
| 74 |
+
display: inline-block;
|
| 75 |
+
margin-top: 15px;
|
| 76 |
+
text-decoration: none;
|
| 77 |
+
color: #28a745;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
a:hover{
|
| 81 |
+
text-decoration: underline;
|
| 82 |
+
}
|
| 83 |
+
</style>
|
| 84 |
+
</head>
|
| 85 |
+
|
| 86 |
+
<body>
|
| 87 |
+
<div class="container">
|
| 88 |
+
<h2>Create Account</h2>
|
| 89 |
+
|
| 90 |
+
<form action="/register" method="POST">
|
| 91 |
+
<input type="text" name="username" placeholder="Username" required>
|
| 92 |
+
|
| 93 |
+
<input type="email" name="email" placeholder="Email" required>
|
| 94 |
+
|
| 95 |
+
<input type="password" name="password" placeholder="Password" required>
|
| 96 |
+
|
| 97 |
+
<button type="submit">Register</button>
|
| 98 |
+
</form>
|
| 99 |
+
|
| 100 |
+
<a href="/">Back to Login</a>
|
| 101 |
+
</div>
|
| 102 |
+
</body>
|
| 103 |
+
</html>
|