harshnarayan12 commited on
Commit
073bb25
·
verified ·
1 Parent(s): f9ed489

Upload 32 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ static/treeman.png filter=lfs diff=lfs merge=lfs -text
scripts/__init__.py ADDED
File without changes
scripts/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (182 Bytes). View file
 
scripts/db/__pycache__/session.cpython-310.pyc ADDED
Binary file (709 Bytes). View file
 
scripts/db/create_article_tables.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from backend.scripts.migration_schemas.resources_models import Base
2
+ from backend.scripts.db.session import engine
3
+ from sqlalchemy import inspect
4
+
5
+ def create_tables():
6
+ inspector = inspect(engine)
7
+ existing_tables = inspector.get_table_names()
8
+
9
+ Base.metadata.create_all(bind=engine)
10
+
11
+ updated_tables = inspector.get_table_names()
12
+ new_tables = set(updated_tables) - set(existing_tables)
13
+
14
+ if new_tables:
15
+ print(f"[INFO] Created new article tables: {', '.join(new_tables)}")
16
+ else:
17
+ print("[INFO] No new article tables created. All tables already exist.")
18
+
19
+ if __name__ == "__main__":
20
+ create_tables()
scripts/db/create_extensions.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import text
2
+ from backend.scripts.db.session import engine
3
+
4
+ def create_vector_extension():
5
+ with engine.connect() as conn:
6
+ conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector WITH SCHEMA extensions;"))
7
+ print("[INFO] 'vector' extension created if not present.")
8
+
9
+ if __name__ == "__main__":
10
+ create_vector_extension()
scripts/db/create_user_tables.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from backend.scripts.migration_schemas.user_models import Base
2
+ from backend.scripts.db.session import engine
3
+ from sqlalchemy import inspect
4
+
5
+ def create_tables():
6
+ inspector = inspect(engine)
7
+ existing_tables = inspector.get_table_names()
8
+
9
+ # This will create all tables defined on Base.metadata that don't yet exist
10
+ Base.metadata.create_all(bind=engine)
11
+
12
+ updated_tables = inspector.get_table_names()
13
+ new_tables = set(updated_tables) - set(existing_tables)
14
+
15
+ if new_tables:
16
+ print(f"[INFO] Created new tables: {', '.join(new_tables)}")
17
+ else:
18
+ print("[INFO] No new tables created. All tables already exist.")
19
+
20
+ if __name__ == "__main__":
21
+ create_tables()
scripts/db/encrypt_passwords.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import psycopg2
3
+ import bcrypt
4
+ from psycopg2.extras import RealDictCursor
5
+ from dotenv import load_dotenv
6
+ from backend.scripts.db.session import DATABASE_URL
7
+ import traceback
8
+
9
+
10
+ def get_db_connection():
11
+ return psycopg2.connect(DATABASE_URL, cursor_factory=RealDictCursor)
12
+
13
+ def hash_unencrypted_passwords():
14
+ conn = cursor = None
15
+ try:
16
+ conn = get_db_connection()
17
+ cursor = conn.cursor()
18
+
19
+ # Find rows with non-bcrypt passwords (e.g. not starting with $2)
20
+ cursor.execute("""
21
+ SELECT id, user_password
22
+ FROM user_profiles
23
+ WHERE user_password NOT LIKE '$2%';
24
+ """)
25
+ users = cursor.fetchall()
26
+
27
+ print(f"Found {len(users)} users with unencrypted passwords.")
28
+
29
+ for user in users:
30
+ user_id = user['id']
31
+ raw_password = user['user_password']
32
+
33
+ # Hash the plaintext password
34
+ hashed_pw = bcrypt.hashpw(raw_password.encode(), bcrypt.gensalt()).decode()
35
+
36
+ # Update the row with the hashed password
37
+ cursor.execute("""
38
+ UPDATE user_profiles
39
+ SET user_password = %s
40
+ WHERE id = %s
41
+ """, (hashed_pw, user_id))
42
+
43
+ conn.commit()
44
+ print("Password hashing complete.")
45
+
46
+ except Exception as e:
47
+ print("[ERROR]", e)
48
+ traceback.print_exc()
49
+ if conn:
50
+ conn.rollback()
51
+ finally:
52
+ if cursor:
53
+ cursor.close()
54
+ if conn:
55
+ conn.close()
56
+
57
+ if __name__ == "__main__":
58
+ hash_unencrypted_passwords()
scripts/db/seed_data_helplines_organizations.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uuid
2
+ import numpy as np
3
+ from sqlalchemy.exc import IntegrityError, SQLAlchemyError
4
+
5
+ from backend.scripts.db.session import SessionLocal
6
+ from backend.scripts.migration_schemas.resources_models import Resource
7
+
8
+ def seed_resources():
9
+ session = SessionLocal()
10
+
11
+ resources = [
12
+ Resource(
13
+ id=str(uuid.uuid4()),
14
+ name="Primary Crisis Hotline",
15
+ phone="1010",
16
+ operation_hours="24/7",
17
+ description="Operated by the Bhutan Youth Development Fund (YDF) and the Ministry of Health, this helpline offers support for mental health issues and suicide prevention.",
18
+ category="mental health",
19
+ type="helpline",
20
+ source="bhutanyouth.org",
21
+ website="https://bhutanyouth.org"
22
+ ),
23
+ Resource(
24
+ id=str(uuid.uuid4()),
25
+ name="Emergency Line",
26
+ phone="112",
27
+ operation_hours="24/7",
28
+ description="The national emergency number is for immediate assistance and is accessible via mobile and landline.",
29
+ category="emergency",
30
+ type="helpline",
31
+ source="National Emergency Services",
32
+ website="moh.gov.bt"
33
+ ),
34
+ Resource(
35
+ id=str(uuid.uuid4()),
36
+ name="Mental Health Support Line",
37
+ phone="1098",
38
+ operation_hours="24/7",
39
+ description="National helpline for children and vulnerable groups. Provides mental health support.",
40
+ category="mental health, children",
41
+ type="helpline",
42
+ source="National Helpline Directory",
43
+ ),
44
+
45
+ Resource(
46
+ id=str(uuid.uuid4()),
47
+ name="Sherig Counselling Services (MoE)",
48
+ phone="17861294",
49
+ operation_hours="Weekdays 9am–5pm",
50
+ description="Counselling helpline for students and youth, staffed by trained school counselors.",
51
+ category="youth, education, counseling",
52
+ source="moe.gov.bt",
53
+ website="https://sites.google.com/moe.gov.bt/sherigcounsellingservices",
54
+ type = "helpline"
55
+ ),
56
+
57
+ Resource(
58
+ id=str(uuid.uuid4()),
59
+ name="PEMA (Psychosocial Education and Mental Health Awareness)",
60
+ phone="1010",
61
+ website="https://thepema.gov.bt/",
62
+ description="PEMA is the national nodal agency for mental health promotion and services, offering counselling, crisis intervention, and rehabilitation. They also have a helpline and offer walk-in services.",
63
+ type="organization"
64
+ ),
65
+ Resource(
66
+ id=str(uuid.uuid4()),
67
+ name="RENEW (Respect, Educate, Nurture, and Empower Women)",
68
+ phone="+975 2 332 159",
69
+ website="https://renew.org.bt/",
70
+ description="Founded by Her Majesty Gyalyum Sangay Choden Wangchuck in 2004, RENEW is a non-profit organization supporting women.",
71
+ type="organization"
72
+ ),
73
+ Resource(
74
+ id=str(uuid.uuid4()),
75
+ name="Jigme Dorji Wangchuck National Referral Hospital",
76
+ phone="+975 17 32 24 96",
77
+ website="https://jdwnrh.gov.bt/",
78
+ description="This hospital has a psychiatric ward, providing specialized mental health services.",
79
+ type="organization"
80
+ ),
81
+
82
+ Resource(
83
+ id=str(uuid.uuid4()),
84
+ name="Bhutan Board for Certified Counselors (BBCC)",
85
+ description="Accredits and supports professional counselors in Bhutan. Promotes ethical and culturally sensitive counseling.",
86
+ phone=None,
87
+ website="https://www.counselingbhutan.com",
88
+ address="Thimphu",
89
+ type="organization"
90
+ ),
91
+
92
+ Resource(
93
+ id=str(uuid.uuid4()),
94
+ name="Institute of Traditional Medicine Services",
95
+ description="Provides traditional Bhutanese medical treatments, including mental and spiritual healing.",
96
+ phone=None,
97
+ website=None,
98
+ address="Langjophakha, Thimphu",
99
+ type="organization"
100
+ )
101
+ ]
102
+
103
+ try:
104
+ for resource in resources:
105
+ session.add(resource)
106
+ session.commit()
107
+ print(f"✅ Inserted {len(resources)} resources into DB.")
108
+ except IntegrityError as e:
109
+ session.rollback()
110
+ print(f"⚠️ Duplicate detected, skipping existing entries: {str(e)}")
111
+ except SQLAlchemyError as e:
112
+ session.rollback()
113
+ print(f"❌ Failed to seed: {str(e)}")
114
+ finally:
115
+ session.close()
116
+
117
+
118
+ def main():
119
+ seed_resources()
120
+
121
+
122
+ if __name__ == "__main__":
123
+ main()
scripts/db/session.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from sqlalchemy import create_engine
3
+ from sqlalchemy.orm import sessionmaker
4
+ from dotenv import load_dotenv
5
+
6
+ load_dotenv()
7
+
8
+ DATABASE_URL = (
9
+ f"postgresql://{os.getenv('DATABASE_USER')}:{os.getenv('DATABASE_PASSWORD')}"
10
+ f"@{os.getenv('DATABASE_HOST')}:{os.getenv('DATABASE_PORT')}/{os.getenv('DATABASE_NAME')}"
11
+ )
12
+
13
+ print("Connecting to:", DATABASE_URL)
14
+
15
+ engine = create_engine(DATABASE_URL, connect_args={"sslmode": "require"})
16
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
scripts/ingest/upload_articles_from_bucket.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import uuid
4
+ import requests
5
+ import tempfile
6
+
7
+ from dotenv import load_dotenv
8
+ import boto3
9
+ from sqlalchemy.exc import SQLAlchemyError
10
+
11
+ from backend.app.core.deps import get_config_value, get_embedding_model
12
+ from backend.rag.pdf_parser import extract_text
13
+ from backend.rag.embeddings import generate_embeddings
14
+ from backend.rag.chunker import smart_chunk_text, create_chunk_objects
15
+ from backend.scripts.db.session import SessionLocal
16
+ from backend.scripts.migration_schemas.resources_models import Article, ArticleChunk
17
+
18
+ load_dotenv()
19
+
20
+ # === Load ENV ===
21
+ ACCESS_KEY = os.getenv("AWS_ACCESS_KEY_ID")
22
+ SECRET_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
23
+ REGION = os.getenv("AWS_REGION")
24
+ ENDPOINT_URL = os.getenv("SUPABASE_STORAGE_ENDPOINT")
25
+ BUCKET_NAME = os.getenv("SUPABASE_BUCKET")
26
+ SUPABASE_STORAGE_URL = os.getenv("SUPABASE_STORAGE_URL")
27
+
28
+ class SyncUpload:
29
+ def __init__(self):
30
+ self.model = get_embedding_model()
31
+ self.embedding_dim = get_config_value("model.embedding_dim", 384)
32
+ self.file_list = self.get_articles_supabase()
33
+ self.current_articles = self.get_current_articles_psql()
34
+
35
+ def get_articles_supabase(self):
36
+ s3 = boto3.client(
37
+ 's3',
38
+ region_name=REGION,
39
+ endpoint_url=ENDPOINT_URL,
40
+ aws_access_key_id=ACCESS_KEY,
41
+ aws_secret_access_key=SECRET_KEY
42
+ )
43
+ response = s3.list_objects_v2(Bucket=BUCKET_NAME)
44
+ return [obj['Key'] for obj in response.get('Contents', []) if obj['Key'].endswith('.pdf')]
45
+
46
+ def get_current_articles_psql(self):
47
+ session = SessionLocal()
48
+ try:
49
+ return [a.title for a in session.query(Article.title).all()]
50
+ finally:
51
+ session.close()
52
+
53
+ def extract_text_from_bytes(self, pdf_bytesio):
54
+ with tempfile.NamedTemporaryFile(suffix=".pdf", delete=True) as tmp:
55
+ tmp.write(pdf_bytesio.read())
56
+ tmp.flush()
57
+ return extract_text(tmp.name)
58
+
59
+ def create_article_object(self, id, title):
60
+ return Article(id=id, title=title)
61
+
62
+ def file_to_chunks(self, article_filename, doc_id):
63
+ article_url = f"{SUPABASE_STORAGE_URL}/v1/object/public/pdfs//{article_filename}"
64
+ print(f"[INFO] Downloading: {article_url}")
65
+ response = requests.get(article_url)
66
+ if response.status_code != 200:
67
+ print(f"[ERROR] Failed to download {article_url}")
68
+ return None
69
+
70
+ try:
71
+ text = self.extract_text_from_bytes(io.BytesIO(response.content))
72
+ print(f"[SUCCESS] Extracted {len(text)} characters from '{article_filename}'")
73
+ raw_chunks = smart_chunk_text(text)
74
+ chunk_objs = create_chunk_objects(doc_id=doc_id, chunks=raw_chunks)
75
+ embedded_chunks = generate_embeddings(chunk_objs)
76
+ return embedded_chunks
77
+ except Exception as e:
78
+ print(f"[ERROR] Processing failed for {article_filename}: {e}")
79
+ return None
80
+
81
+ def articles_to_rag(self):
82
+ session = SessionLocal()
83
+ for article_file in self.file_list:
84
+ article_title = article_file.replace(".pdf", "")
85
+ if article_title in self.current_articles:
86
+ print(f"[SKIP] Already processed: {article_title}")
87
+ continue
88
+
89
+ doc_id = str(uuid.uuid4())
90
+ article = self.create_article_object(id=doc_id, title=article_title)
91
+ chunk_data = self.file_to_chunks(article_file, doc_id)
92
+
93
+ if not chunk_data:
94
+ continue
95
+
96
+ try:
97
+ chunks = [
98
+ ArticleChunk(
99
+ chunk_id=c["chunk_id"],
100
+ doc_id=c["doc_id"],
101
+ chunk_text=c["chunk_text"],
102
+ embedding=c["embedding"],
103
+ keywords=c["keywords"]
104
+ ) for c in chunk_data
105
+ ]
106
+
107
+ session.add(article)
108
+ session.add_all(chunks)
109
+ session.commit()
110
+ print(f"[SUCCESS] Uploaded: {article_title} ({len(chunks)} chunks)")
111
+ except SQLAlchemyError as e:
112
+ session.rollback()
113
+ print(f"[ERROR] DB insert failed for {article_title}: {e}")
114
+ finally:
115
+ session.close()
116
+
117
+ if __name__ == "__main__":
118
+ SyncUpload().articles_to_rag()
scripts/ingest/upload_files_to_bucket.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import boto3
3
+ from pathlib import Path
4
+ from botocore.exceptions import ClientError
5
+ from tqdm import tqdm
6
+ import sys
7
+
8
+ AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
9
+ AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
10
+ ENDPOINT_URL = os.getenv("SUPABASE_STORAGE_ENDPOINT")
11
+ BUCKET_NAME = os.getenv("SUPABASE_BUCKET")
12
+ REGION = os.getenv("AWS_REGION")
13
+
14
+ s3 = boto3.client(
15
+ "s3",
16
+ aws_access_key_id=AWS_ACCESS_KEY_ID,
17
+ aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
18
+ endpoint_url=ENDPOINT_URL,
19
+ region_name=REGION
20
+ )
21
+
22
+ def upload_pdfs(folder_path: str):
23
+
24
+ response = s3.list_objects_v2(Bucket=BUCKET_NAME)
25
+ file_list = [obj['Key'] for obj in response.get('Contents', []) if obj['Key'].endswith('.pdf')]
26
+
27
+ folder = Path(folder_path)
28
+
29
+ if not folder.exists() or not folder.is_dir():
30
+ print("❌ Invalid folder path.")
31
+ return
32
+
33
+ pdf_files = list(folder.glob("*.pdf"))
34
+
35
+ if not pdf_files:
36
+ print("Folder exists, but no PDF files were found.")
37
+ return
38
+
39
+ for file_path in tqdm(pdf_files):
40
+ key = file_path.name
41
+ print(f"📄 Uploading: {key}")
42
+
43
+ if key in file_list:
44
+ print(f"✅ {key} already exists in the bucket, skipping.")
45
+ continue
46
+ else:
47
+ try:
48
+ s3.upload_file(
49
+ Filename=str(file_path),
50
+ Bucket=BUCKET_NAME,
51
+ Key=key,
52
+ ExtraArgs={"ContentType": "application/pdf"},
53
+ )
54
+ except ClientError as e:
55
+ print(f"❌ Error uploading {key}: {e}")
56
+
57
+ print("✅ Upload complete. Run `make sync-bucket` to process the files.")
58
+
59
+
60
+
61
+ def main():
62
+ if len(sys.argv) > 1:
63
+ folder = sys.argv[1]
64
+ else:
65
+ print("No folder path provided. Using default: backend/data/rag_articles")
66
+ folder = input("📂 Enter path to folder with PDFs (normally backend/data/rag_articles)): ").strip()
67
+
68
+ print(f"Using folder: {folder}")
69
+ upload_pdfs(folder)
70
+ # Your existing logic here, using `folder`
71
+
72
+ if __name__ == "__main__":
73
+ main()
scripts/migration_schemas/__pycache__/resources_models.cpython-310.pyc ADDED
Binary file (2 kB). View file
 
scripts/migration_schemas/resources_models.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import yaml
2
+ from sqlalchemy import (
3
+ Column,
4
+ String,
5
+ Text,
6
+ ForeignKey,
7
+ Date,
8
+ )
9
+ from sqlalchemy.dialects.postgresql import ARRAY
10
+ from sqlalchemy.ext.declarative import declarative_base
11
+ from pgvector.sqlalchemy import Vector
12
+ from sqlalchemy.orm import relationship
13
+ import os
14
+ from backend.app.core.deps import EMBEDDING_DIM as embedding_dim
15
+ from sqlalchemy import UniqueConstraint
16
+
17
+ Base = declarative_base()
18
+
19
+
20
+ class Resource(Base):
21
+ __tablename__ = "resources"
22
+
23
+ id = Column(String, primary_key=True)
24
+ name = Column(String, nullable=False)
25
+ description = Column(Text)
26
+ phone = Column(String)
27
+ website = Column(String)
28
+ address = Column(String)
29
+ operation_hours = Column(String)
30
+ category = Column(String) # e.g., "mental_health", "addiction", etc.
31
+ type = Column(String, nullable=False) # e.g., "helpline", "organization"
32
+ source = Column(String)
33
+
34
+ __table_args__ = (
35
+ UniqueConstraint("name", name="uq_resource_name"),
36
+ )
37
+
38
+ class Article(Base):
39
+ __tablename__ = "articles"
40
+
41
+ id = Column(String, primary_key=True, unique=True)
42
+ title = Column(String, nullable=False, unique=True)
43
+ author = Column(String)
44
+ source = Column(String)
45
+ published_date = Column(Date)
46
+ topic = Column(String)
47
+
48
+ chunks = relationship("ArticleChunk", back_populates="article")
49
+
50
+ class ArticleChunk(Base):
51
+ __tablename__ = "article_chunks"
52
+
53
+ chunk_id = Column(String, primary_key=True, unique=True)
54
+ doc_id = Column(String, ForeignKey("articles.id"), nullable=False)
55
+ chunk_text = Column(Text, nullable=False)
56
+ embedding = Column(Vector(embedding_dim))
57
+ keywords = Column(Text)
58
+
59
+ article = relationship("Article", back_populates="chunks")
60
+
61
+
62
+
scripts/migration_schemas/user_models.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import (
2
+ Column,
3
+ String,
4
+ Integer,
5
+ Text,
6
+ TIMESTAMP,
7
+ CheckConstraint,
8
+ ForeignKey,
9
+ func,
10
+ )
11
+ from sqlalchemy.dialects.postgresql import UUID
12
+ from sqlalchemy.ext.declarative import declarative_base
13
+ import uuid
14
+
15
+ Base = declarative_base()
16
+
17
+ class UserProfile(Base):
18
+ __tablename__ = "user_profiles"
19
+
20
+ id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
21
+
22
+ name = Column(String(100), nullable=False)
23
+ age = Column(Integer, CheckConstraint("age > 0 AND age <= 150"))
24
+
25
+ gender = Column(String(20), CheckConstraint(
26
+ "gender IN ('Male', 'Female', 'Non-binary', 'Other', 'Prefer not to say')"
27
+ ))
28
+
29
+ city_region = Column(String(100))
30
+ profession = Column(String(100))
31
+
32
+ marital_status = Column(String(30), CheckConstraint(
33
+ "marital_status IN ('Single', 'In relationship', 'Married', 'Divorced', 'Widowed', 'Other', 'Prefer not to say')"
34
+ ))
35
+
36
+ previous_mental_diagnosis = Column(Text, default="NA")
37
+ ethnicity = Column(String(50))
38
+
39
+ created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
40
+ updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now(), onupdate=func.now())
41
+
42
+
43
+ class ConversationHistory(Base):
44
+ __tablename__ = "conversation_history"
45
+
46
+ id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
47
+
48
+ user_id = Column(UUID(as_uuid=True), ForeignKey("user_profiles.id", ondelete="CASCADE"), nullable=False)
49
+
50
+ message = Column(Text, nullable=False)
51
+ response = Column(Text, nullable=False)
52
+
53
+ timestamp = Column(TIMESTAMP(timezone=True), server_default=func.now())
54
+
static/mediaabout.css ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @media screen and (max-width: 1100px){
3
+
4
+
5
+
6
+
7
+ .burger{
8
+ position: absolute;
9
+ cursor: pointer;
10
+ right: 5%;
11
+ top: 50%;
12
+ transform: translate(-5% , -50%);
13
+ z-index: 2;
14
+ }
15
+
16
+ .line{
17
+ width: 30px;
18
+ height: 3px;
19
+ background: #4b5b39;
20
+ margin: 5px;
21
+ }
22
+
23
+ .burger:hover .line{
24
+ transform-origin: 50% 50%;
25
+ animation: line-grow ease-out 400ms ;
26
+ }
27
+ .burger:focus .line{
28
+ transform-origin: 50% 50%;
29
+ animation: line-grow ease-out 400ms ;
30
+ }
31
+
32
+ @keyframes line-grow{
33
+ 0%{transform: scaleX(1);}
34
+ 50%{transform: scaleX(1.5);}
35
+ 100%{transform: scaleX(1);}
36
+ }
37
+ .logo{
38
+ width: 40%;
39
+ display: flex;
40
+ justify-content: center;
41
+ align-items: center;
42
+ }
43
+
44
+ .navbar{
45
+ position: relative;
46
+
47
+
48
+
49
+ }
50
+
51
+
52
+ .nav-Links{
53
+ position: sticky;
54
+ height: 100vh;
55
+ width: 100%;
56
+ background:turquoise;
57
+ flex-direction: column;
58
+
59
+ align-items: center;
60
+ clip-path: circle(100px at 90% -10%);
61
+ -webkit-clip-path: circle(100px at 90% -10%);
62
+ transition: all 1s ease-out;
63
+ pointer-events: none;
64
+ }
65
+
66
+ .nav-Links.open{
67
+ clip-path: circle(1000px at 90% -10%);
68
+ -webkit-clip-path: circle(1000px at 90% -10%);
69
+ pointer-events: all;
70
+ justify-content: space-evenly;
71
+ }
72
+
73
+ .nav-Links li{
74
+ opacity: 0;
75
+ justify-content: center;
76
+ display: flex;
77
+ }
78
+
79
+ .nav-Links li a{
80
+
81
+ font-size: 25px;
82
+ }
83
+
84
+ .nav-Links li:nth-child(1){
85
+ transition: all 0.5s ease 0.2s;
86
+ }
87
+ .nav-Links li:nth-child(2){
88
+ transition: all 0.5s ease 0.4s;
89
+ }
90
+ .nav-Links li:nth-child(3){
91
+ transition: all 0.5s ease 0.6s;
92
+ }
93
+ .nav-Links li:nth-child(4){
94
+ transition: all 0.5s ease 0.8s;
95
+ }
96
+ .nav-Links li:nth-child(5){
97
+ transition: all 0.5s ease 0.8s;
98
+ }
99
+
100
+ li.fade{
101
+ opacity: 1;
102
+ }
103
+
104
+
105
+
106
+ #search{
107
+ width: 100%;
108
+ }
109
+
110
+ /*
111
+ .firstsection{
112
+ height: 100vh;
113
+
114
+ } */
115
+
116
+
117
+
118
+ .box {
119
+
120
+ width: 700px;
121
+ height: 850px;
122
+ border-radius: 10vw 10vw;
123
+ margin: auto;
124
+ }
125
+
126
+
127
+ .first{
128
+ margin-top: auto;
129
+ }
130
+
131
+ .first h1{
132
+ font-size: 1.7rem
133
+
134
+ }
135
+
136
+ .first p{
137
+ font-size: 17px;
138
+ margin-top: 2rem;
139
+ line-height: 1.5em;
140
+ }
141
+
142
+ .first p::before{
143
+ content: open-quote ;
144
+ color: #4b5b39;
145
+ font-size: 2rem;
146
+ }
147
+
148
+ .first p::after{
149
+ content: close-quote ;
150
+ color: #4b5b39;
151
+ font-size: 2rem;
152
+ }
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+ .container{
163
+ display: flex;
164
+ flex-direction: column;
165
+ justify-content: center;
166
+ align-items: center;
167
+ padding: 5px;
168
+ }
169
+
170
+ .sec1{
171
+ display: flex;
172
+ flex-direction: row;
173
+ justify-content:center;
174
+ align-items: center;
175
+
176
+ }
177
+
178
+ .logo-footer{
179
+ width: 20%;
180
+ display: flex;
181
+ align-items: center;
182
+
183
+ }
184
+
185
+ .logo-footer img{
186
+ width: 90%;
187
+ border: 3px solid white;
188
+ border-radius: 10px
189
+ }
190
+
191
+ .useless-text{
192
+ font-size: 11px;
193
+ padding-left: 10px;
194
+ }
195
+
196
+
197
+ .site-name {
198
+ width: 51%;
199
+ font-size: 10px;
200
+ }
201
+
202
+
203
+
204
+ .social-links{
205
+ display: flex;
206
+ flex-direction: row;
207
+ justify-content: center;
208
+ align-items: center;
209
+ width: 80%;
210
+
211
+ }
212
+
213
+ .log1{
214
+ padding-left: 4px;
215
+ padding-right: 4px;
216
+ border-radius: 50%;
217
+ }
218
+ .log2{
219
+ border-radius: 50%;
220
+ padding-left: 4px;
221
+ padding-right: 4px;
222
+ }
223
+ .log3{
224
+ border-radius: 50%;
225
+ padding-left: 4px;
226
+ padding-right: 4px;
227
+ }
228
+ .log4{
229
+ border-radius: 50%;
230
+ padding-left: 4px;
231
+ padding-right: 4px;
232
+ }
233
+
234
+ .log1 img , .log2 img ,.log3 img,.log4 img {
235
+ border-radius: 50%;
236
+ }
237
+
238
+
239
+
240
+ }
static/mediahome.css ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @media screen and (max-width: 1100px){
3
+
4
+ .burger{
5
+ position: absolute;
6
+ cursor: pointer;
7
+ right: 5%;
8
+ top: 50%;
9
+ transform: translate(-5% , -50%);
10
+ z-index: 2;
11
+ }
12
+
13
+ .line{
14
+ width: 30px;
15
+ height: 3px;
16
+ background: #4b5b39;
17
+ margin: 5px;
18
+ }
19
+
20
+ .burger:hover .line{
21
+ transform-origin: 50% 50%;
22
+ animation: line-grow ease-out 400ms ;
23
+ }
24
+ .burger:focus .line{
25
+ transform-origin: 50% 50%;
26
+ animation: line-grow ease-out 400ms ;
27
+ }
28
+
29
+ @keyframes line-grow{
30
+ 0%{transform: scaleX(1);}
31
+ 50%{transform: scaleX(1.5);}
32
+ 100%{transform: scaleX(1);}
33
+ }
34
+ .logo{
35
+ width: 40%;
36
+ display: flex;
37
+ justify-content: center;
38
+ align-items: center;
39
+ }
40
+
41
+ .navbar{
42
+ position: relative;
43
+
44
+
45
+
46
+ }
47
+
48
+
49
+ .nav-Links{
50
+ position: sticky;
51
+ height: 100vh;
52
+ width: 100%;
53
+ background:#abee53;
54
+ flex-direction: column;
55
+
56
+ align-items: center;
57
+ clip-path: circle(100px at 90% -10%);
58
+ -webkit-clip-path: circle(100px at 90% -10%);
59
+ transition: all 1s ease-out;
60
+ pointer-events: none;
61
+ }
62
+
63
+ .nav-Links.open{
64
+ clip-path: circle(1000px at 90% -10%);
65
+ -webkit-clip-path: circle(1000px at 90% -10%);
66
+ pointer-events: all;
67
+ justify-content: space-evenly;
68
+ }
69
+
70
+ .nav-Links li{
71
+ opacity: 0;
72
+ justify-content: center;
73
+ display: flex;
74
+ }
75
+
76
+ .nav-Links li a{
77
+
78
+ font-size: 24px;
79
+ }
80
+
81
+ .nav-Links li:nth-child(1){
82
+ transition: all 0.5s ease 0.2s;
83
+ }
84
+ .nav-Links li:nth-child(2){
85
+ transition: all 0.5s ease 0.4s;
86
+ }
87
+ .nav-Links li:nth-child(3){
88
+ transition: all 0.5s ease 0.6s;
89
+ }
90
+ .nav-Links li:nth-child(4){
91
+ transition: all 0.5s ease 0.8s;
92
+ }
93
+ .nav-Links li:nth-child(5){
94
+ transition: all 0.5s ease 0.8s;
95
+ }
96
+
97
+ li.fade{
98
+ opacity: 1;
99
+ }
100
+
101
+ /* .v-class-resp{
102
+ position: fixed;
103
+ height: 80vh;
104
+ width: 100%;
105
+ background-color: #5b78c7;
106
+ flex-direction: column;
107
+ align-items: center;
108
+ clip-path: circle(100px at 90% -10%);
109
+ -webkit-clip-path: circle(100px at 90% -10%);
110
+ transition: all 1s ease-out;
111
+ pointer-events: none;
112
+
113
+ } */
114
+
115
+
116
+ /*
117
+ .v-class-resp.open{
118
+ clip-path: circle(1000px at 90% -10%);
119
+ -webkit-clip-path: circle(1000px at 90% -10%);
120
+ pointer-events: all;
121
+ }
122
+
123
+ .v-class-resp li{
124
+ opacity: 0;
125
+ }
126
+ .v-class-resp div{
127
+ opacity: 0;
128
+ }
129
+
130
+ .v-class-resp li a{
131
+
132
+ font-size: 25px;
133
+ }
134
+ */
135
+
136
+ /* }
137
+ .nav-list1 div:nth-child(1){
138
+ transition: all 0.5s ease 0.2s;
139
+ }
140
+ .nav-list1 div:nth-child(2){
141
+ transition: all 0.5s ease 0.2s;
142
+ }
143
+ .nav-list1 div:nth-child(3){
144
+ transition: all 0.5s ease 0.2s;
145
+ }
146
+ .nav-list li:nth-child(1){
147
+ transition: all 0.5s ease 0.2s;
148
+ }
149
+ .nav-list li:nth-child(2){
150
+ transition: all 0.5s ease 0.3s;
151
+ }
152
+ .nav-list li:nth-child(3){
153
+ transition: all 0.5s ease 0.4s;
154
+ }
155
+ .nav-list li:nth-child(4){
156
+ transition: all 0.5s ease 0.5s;
157
+ }
158
+
159
+ div.fade
160
+ li.fade{
161
+ opacity: 1;
162
+ } */
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+ .firstsection{
171
+ height: 100vh;
172
+
173
+ }
174
+
175
+ .box-main{
176
+ flex-direction:column-reverse;
177
+ max-width: 100%;
178
+ justify-content: space-evenly;
179
+ height: 100%;
180
+ }
181
+
182
+ .secondhalf{
183
+ width: 100%;
184
+ margin: 0% 0%;
185
+ padding: 0% 0%;
186
+ justify-content: center;
187
+ }
188
+
189
+ .secondhalf img{
190
+ align-items: center;
191
+ width: 180px;
192
+ border: 2px solid white;
193
+ border-radius: 50px;
194
+ display: block;
195
+ justify-content: center;
196
+ }
197
+
198
+ #search{
199
+ width: 100%;
200
+ }
201
+
202
+ .burger{
203
+ display: block;
204
+ }
205
+
206
+ .h-nav-resp{
207
+ height: 60px;
208
+
209
+ }
210
+
211
+ .v-class-resp{
212
+ opacity: 0;
213
+
214
+ }
215
+
216
+
217
+
218
+
219
+
220
+ .text-big-section{
221
+
222
+
223
+ font-size: 23px;
224
+
225
+
226
+
227
+ }
228
+
229
+ .text-small-section{
230
+
231
+
232
+ font-size: 16px;
233
+
234
+ }
235
+
236
+ .section-mid{
237
+ height: 250vh;
238
+ }
239
+
240
+ .section1{
241
+ margin-left: 10%;
242
+ margin-right: 10%;
243
+ margin-top: 5%;
244
+ margin-bottom: 5%;
245
+ }
246
+ .section2{
247
+ margin-left: 10%;
248
+ margin-right: 10%;
249
+ margin-top: 5%;
250
+ margin-bottom: 5%;
251
+ }
252
+ .section3{
253
+ margin-left: 10%;
254
+ margin-right: 10%;
255
+ margin-top: 5%;
256
+ margin-bottom: 5%;
257
+ }
258
+
259
+
260
+
261
+ .text-big{
262
+ text-align: center;
263
+ font-size: 30px;
264
+ }
265
+
266
+ .text-small{
267
+ text-align: center;
268
+ font-size: 18px;
269
+ }
270
+
271
+ .buttons{
272
+ text-align: center;
273
+
274
+ }
275
+
276
+ .btn{
277
+ margin: 0;
278
+ }
279
+
280
+
281
+
282
+
283
+ .container{
284
+ display: flex;
285
+ flex-direction: column;
286
+ justify-content: center;
287
+ align-items: center;
288
+ padding: 5px;
289
+ }
290
+
291
+ .sec1{
292
+ display: flex;
293
+ flex-direction: row;
294
+ justify-content:center;
295
+ align-items: center;
296
+
297
+ }
298
+
299
+ .logo-footer{
300
+ width: 20%;
301
+ display: flex;
302
+ align-items: center;
303
+
304
+ }
305
+
306
+ .logo-footer img{
307
+ width: 90%;
308
+ border: 3px solid white;
309
+ border-radius: 10px
310
+ }
311
+
312
+ .useless-text{
313
+ font-size: 11px;
314
+ padding-left: 10px;
315
+ }
316
+
317
+
318
+ .site-name {
319
+ width: 51%;
320
+ font-size: 10px;
321
+ }
322
+
323
+
324
+
325
+ .social-links{
326
+ display: flex;
327
+ flex-direction: row;
328
+ justify-content: center;
329
+ align-items: center;
330
+ width: 80%;
331
+
332
+ }
333
+
334
+
335
+
336
+ .log1{
337
+ padding-left: 4px;
338
+ padding-right: 4px;
339
+ border-radius: 50%;
340
+ }
341
+ .log2{
342
+ border-radius: 50%;
343
+ padding-left: 4px;
344
+ padding-right: 4px;
345
+ }
346
+ .log3{
347
+ border-radius: 50%;
348
+ padding-left: 4px;
349
+ padding-right: 4px;
350
+ }
351
+ .log4{
352
+ border-radius: 50%;
353
+ padding-left: 4px;
354
+ padding-right: 4px;
355
+ }
356
+
357
+
358
+
359
+ .a-1 .log1 img{
360
+ height: 40px;
361
+ width: 40px;
362
+
363
+ }
364
+
365
+
366
+ .a-2 .log2 img{
367
+ height: 40px;
368
+ width: 40px;
369
+
370
+ }
371
+
372
+ .a-3 .log3 img{
373
+ height: 40px;
374
+ width: 40px;
375
+
376
+ }
377
+
378
+ .a-4 .log4 img{
379
+ height: 40px;
380
+ width: 40px;
381
+
382
+ }
383
+
384
+
385
+
386
+ .log1 img , .log2 img ,.log3 img,.log4 img {
387
+ border-radius: 50%;
388
+ }
389
+
390
+
391
+ }
392
+
393
+
394
+
395
+
396
+
397
+
398
+
399
+
400
+
401
+
402
+
403
+
404
+
405
+
406
+
407
+
408
+ /*
409
+
410
+
411
+ @media screen and (max-width: 480px){
412
+ .container{
413
+ margin: 10$ 0;
414
+ }
415
+ form{
416
+ width: 268px
417
+ }
418
+ header{
419
+ width: 268px;
420
+ }
421
+ #title{
422
+ font-size: 1.35em;
423
+ padding: 5px;
424
+ }
425
+
426
+ #description{
427
+ padding-bottom: 5%;
428
+ }
429
+ } */
static/mental-health_12560579.png ADDED
static/styleChatBotUI.css ADDED
@@ -0,0 +1,868 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Chatbot UI Stylesheet */
2
+ /* This stylesheet is designed to create a modern and user-friendly chatbot interface. */
3
+ body {
4
+ /* background-color: #f5f5f5; */
5
+ /* background-image: url(/vecteezy_modern-simple-abstract-pattern_.jpg); */
6
+ background-color: hsl(47.1, 69%, 90%);
7
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
8
+ }
9
+ .chat-container {
10
+ max-width: 1200px;
11
+ margin: 0 auto;
12
+ background: linear-gradient(to right top, #dfc665, #6ceb8c);
13
+ border-radius: 15px;
14
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
15
+ height: 90vh;
16
+ display: flex;
17
+ flex-direction: column;
18
+ }
19
+ .chat-header {
20
+ padding: 15px 20px;
21
+ border-bottom: 1px solid #eaeaea;
22
+ background: linear-gradient(to bottom top, #6ceb8c,#dfc665);
23
+ border-top-left-radius: 15px;
24
+ border-top-right-radius: 15px;
25
+ }
26
+ .chat-body {
27
+ flex: 1;
28
+ overflow-y: auto;
29
+ padding: 20px;
30
+ display: flex;
31
+ flex-direction: column;
32
+ }
33
+ .chat-footer {
34
+ padding: 15px;
35
+ border-top: 1px solid #eaeaea;
36
+ background: linear-gradient(to top bottom ,#dfc665,#6ceb8c);
37
+ border-bottom-left-radius: 15px;
38
+ border-bottom-right-radius: 15px;
39
+ }
40
+ .message {
41
+ max-width: 80%;
42
+ margin-bottom: 15px;
43
+ padding: 10px 15px;
44
+ border-radius: 15px;
45
+ position: relative;
46
+ }
47
+ .user-message {
48
+ background-color: #e3f2fd;
49
+ color: #000;
50
+ align-self: flex-end;
51
+ border-bottom-right-radius: 0;
52
+ }
53
+ .assistant-message {
54
+ background-color: #f5f5f5;
55
+ color: #000;
56
+ align-self: flex-start;
57
+ border-bottom-left-radius: 0;
58
+ }
59
+ .agent-tag {
60
+ display: inline-block;
61
+ background-color: #ebf5ff;
62
+ color: #0d6efd;
63
+ padding: 2px 8px;
64
+ border-radius: 10px;
65
+ font-size: 0.8em;
66
+ font-weight: bold;
67
+ margin-bottom: 5px;
68
+ }
69
+ .message-input {
70
+ border-radius: 20px;
71
+ padding: 10px 15px;
72
+ resize: none;
73
+ }
74
+ .file-upload-container {
75
+ position: relative;
76
+ overflow: hidden;
77
+ display: inline-block;
78
+ }
79
+ .file-upload-btn {
80
+ border: none;
81
+ color: white;
82
+ border-radius: 50%;
83
+ width: 40px;
84
+ height: 40px;
85
+ cursor: pointer;
86
+ }
87
+ .file-upload-input {
88
+ position: absolute;
89
+ top: 0;
90
+ right: 0;
91
+ margin: 0;
92
+ padding: 0;
93
+ font-size: 20px;
94
+ cursor: pointer;
95
+ opacity: 0;
96
+ filter: alpha(opacity=0);
97
+ }
98
+ .preview-container {
99
+ margin-top: 10px;
100
+ display: none;
101
+ }
102
+ .preview-voice {
103
+ max-width: 100px;
104
+ max-height: 100px;
105
+ border-radius: 5px;
106
+ }
107
+ .result-image {
108
+ max-width: 300px;
109
+ max-height: 300px;
110
+ border-radius: 5px;
111
+ margin-top: 10px;
112
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
113
+ }
114
+ .image-side-by-side {
115
+ display: flex;
116
+ flex-wrap: wrap;
117
+ gap: 10px;
118
+ margin-top: 10px;
119
+ }
120
+ .image-container {
121
+ flex: 1;
122
+ min-width: 200px;
123
+ }
124
+ .image-caption {
125
+ font-size: 0.85em;
126
+ text-align: center;
127
+ margin-top: 5px;
128
+ color: #666;
129
+ }
130
+ .thinking {
131
+ display: flex;
132
+ align-items: center;
133
+ padding: 10px;
134
+ }
135
+ .dot {
136
+ height: 8px;
137
+ width: 8px;
138
+ margin-right: 5px;
139
+ background-color: #0d6efd;
140
+ border-radius: 50%;
141
+ display: inline-block;
142
+ animation: pulse 1.5s infinite ease-in-out;
143
+ }
144
+ .dot:nth-child(2) {
145
+ animation-delay: 0.3s;
146
+ }
147
+ .dot:nth-child(3) {
148
+ animation-delay: 0.6s;
149
+ }
150
+ @keyframes pulse {
151
+ 0% { transform: scale(0.8); opacity: 0.5; }
152
+ 50% { transform: scale(1.2); opacity: 1; }
153
+ 100% { transform: scale(0.8); opacity: 0.5; }
154
+ }
155
+ .sidebar {
156
+ background: linear-gradient(to right top, #dfc665, #6ceb8c);
157
+ padding: 20px;
158
+ border-radius: 15px;
159
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
160
+ height: 90vh;
161
+ overflow-y: auto;
162
+ }
163
+ .sidebar h5 {
164
+ margin-bottom: 15px;
165
+ border-bottom: 1px solid #eaeaea;
166
+ padding-bottom: 10px;
167
+ }
168
+ .agent-info {
169
+ margin-bottom: 15px;
170
+ }
171
+ .agent-info h6 {
172
+ color: #0d6efd;
173
+ }
174
+
175
+ .welcome{
176
+ font-size: x-large;
177
+ }
178
+ .list-group{
179
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
180
+ --bs-list-group-border-color: none;
181
+ }
182
+ .list-group-item {
183
+ background-color: transparent;
184
+
185
+ }
186
+ .card-btn{
187
+ background-color:#646e3a;
188
+ border-color:#646e3a;
189
+ border-radius: 4px;
190
+ color: aliceblue;
191
+
192
+
193
+ }
194
+ .card-btn:hover {
195
+ color: var(--bs-btn-hover-color);
196
+ background-color: #242427;
197
+ border-color:
198
+ #242427;
199
+ }
200
+
201
+
202
+
203
+
204
+ .structured-response {
205
+ line-height: 1.6;
206
+ }
207
+
208
+ .structured-response .empathy-section {
209
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
210
+ color: white;
211
+ padding: 15px;
212
+ border-radius: 8px;
213
+ margin-bottom: 15px;
214
+ border-left: 4px solid #4a69bd;
215
+ }
216
+
217
+ .structured-response .solution-section {
218
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
219
+ color: white;
220
+ padding: 15px;
221
+ border-radius: 8px;
222
+ margin-bottom: 15px;
223
+ border-left: 4px solid #eb4d4b;
224
+ }
225
+
226
+ .structured-response .recommendations-section {
227
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
228
+ color: white;
229
+ padding: 15px;
230
+ border-radius: 8px;
231
+ margin-bottom: 15px;
232
+ border-left: 4px solid #0abde3;
233
+ }
234
+
235
+ .structured-response .section-title {
236
+ font-weight: bold;
237
+ font-size: 1.1em;
238
+ margin-bottom: 8px;
239
+ text-transform: uppercase;
240
+ letter-spacing: 1px;
241
+ }
242
+
243
+ .message-content ul {
244
+ padding-left: 20px;
245
+ }
246
+
247
+ .message-content li {
248
+ margin-bottom: 5px;
249
+ }
250
+
251
+ /* Add these styles to styleChatBotUI.css */
252
+
253
+ /* Assessment Summary Styles */
254
+ .assessment-summary {
255
+ background: #f8f9fa;
256
+ border-radius: 10px;
257
+ padding: 15px;
258
+ margin: 15px 0;
259
+ border: 1px solid #e9ecef;
260
+ }
261
+
262
+ .assessment-summary h4 {
263
+ color: #495057;
264
+ margin-bottom: 15px;
265
+ font-size: 16px;
266
+ border-bottom: 2px solid #667eea;
267
+ padding-bottom: 5px;
268
+ }
269
+
270
+ .assessment-summary h5 {
271
+ color: #6c757d;
272
+ font-size: 14px;
273
+ margin: 10px 0 8px 0;
274
+ font-weight: 600;
275
+ }
276
+
277
+ .basic-info ul {
278
+ list-style: none;
279
+ padding: 0;
280
+ margin: 0;
281
+ }
282
+
283
+ .basic-info li {
284
+ padding: 4px 0;
285
+ font-size: 13px;
286
+ border-bottom: 1px solid #f1f3f4;
287
+ }
288
+
289
+ .basic-info li:last-child {
290
+ border-bottom: none;
291
+ }
292
+
293
+ .score-summary {
294
+ display: flex;
295
+ flex-direction: column;
296
+ gap: 8px;
297
+ }
298
+
299
+ .score-item {
300
+ display: flex;
301
+ flex-direction: column;
302
+ background: white;
303
+ padding: 8px;
304
+ border-radius: 6px;
305
+ border: 1px solid #e9ecef;
306
+ }
307
+
308
+ .test-name {
309
+ font-weight: 600;
310
+ font-size: 12px;
311
+ color: #495057;
312
+ }
313
+
314
+ .score {
315
+ font-size: 11px;
316
+ color: #6c757d;
317
+ }
318
+
319
+ .level {
320
+ font-size: 11px;
321
+ padding: 2px 6px;
322
+ border-radius: 4px;
323
+ margin-top: 4px;
324
+ font-weight: 500;
325
+ }
326
+
327
+ .level.normal {
328
+ background: #d4edda;
329
+ color: #155724;
330
+ }
331
+
332
+ .level.concern {
333
+ background: #fff3cd;
334
+ color: #856404;
335
+ }
336
+
337
+ .overall-status {
338
+ margin-top: 15px;
339
+ }
340
+
341
+ .status {
342
+ padding: 8px;
343
+ border-radius: 6px;
344
+ font-size: 13px;
345
+ font-weight: 500;
346
+ text-align: center;
347
+ }
348
+
349
+ .status.normal {
350
+ background: #d4edda;
351
+ color: #155724;
352
+ border: 1px solid #c3e6cb;
353
+ }
354
+
355
+ .status.alert {
356
+ background: #fff3cd;
357
+ color: #856404;
358
+ border: 1px solid #ffeaa7;
359
+ }
360
+
361
+ .emergency-alert {
362
+ background: #f8d7da;
363
+ border: 1px solid #f5c6cb;
364
+ border-radius: 6px;
365
+ padding: 10px;
366
+ margin-top: 15px;
367
+ }
368
+
369
+ .emergency-alert h5 {
370
+ color: #721c24;
371
+ margin-bottom: 8px;
372
+ }
373
+
374
+ .emergency-alert p {
375
+ color: #721c24;
376
+ font-size: 12px;
377
+ margin-bottom: 8px;
378
+ }
379
+
380
+ .emergency-alert ul {
381
+ list-style: none;
382
+ padding: 0;
383
+ margin: 0;
384
+ }
385
+
386
+ .emergency-alert li {
387
+ color: #721c24;
388
+ font-size: 11px;
389
+ padding: 2px 0;
390
+ }
391
+
392
+ .no-assessment {
393
+ text-align: center;
394
+ padding: 20px;
395
+ color: #6c757d;
396
+ }
397
+
398
+ .no-assessment p {
399
+ margin-bottom: 15px;
400
+ font-size: 14px;
401
+ }
402
+
403
+ .guest-info {
404
+ text-align: center;
405
+ padding: 20px;
406
+ color: #6c757d;
407
+ }
408
+
409
+ .guest-info h3 {
410
+ color: #495057;
411
+ margin-bottom: 10px;
412
+ }
413
+
414
+ .guest-info p {
415
+ margin-bottom: 15px;
416
+ font-size: 14px;
417
+ }
418
+
419
+ /* Add these styles to static/styleChatBotUI.css */
420
+
421
+ /* Assessment Summary Styles */
422
+ .assessment-summary {
423
+ background: #f8f9fa;
424
+ border-radius: 10px;
425
+ padding: 15px;
426
+ margin: 15px 0;
427
+ border: 1px solid #e9ecef;
428
+ }
429
+
430
+ .assessment-summary h4 {
431
+ color: #495057;
432
+ margin-bottom: 15px;
433
+ font-size: 16px;
434
+ border-bottom: 2px solid #667eea;
435
+ padding-bottom: 5px;
436
+ }
437
+
438
+ .assessment-summary h5 {
439
+ color: #6c757d;
440
+ font-size: 14px;
441
+ margin: 10px 0 8px 0;
442
+ font-weight: 600;
443
+ }
444
+
445
+ .basic-info ul {
446
+ list-style: none;
447
+ padding: 0;
448
+ margin: 0;
449
+ }
450
+
451
+ .basic-info li {
452
+ padding: 4px 0;
453
+ font-size: 13px;
454
+ border-bottom: 1px solid #f1f3f4;
455
+ }
456
+
457
+ .basic-info li:last-child {
458
+ border-bottom: none;
459
+ }
460
+
461
+ .score-summary {
462
+ display: flex;
463
+ flex-direction: column;
464
+ gap: 8px;
465
+ }
466
+
467
+ .score-item {
468
+ display: flex;
469
+ flex-direction: column;
470
+ background: white;
471
+ padding: 8px;
472
+ border-radius: 6px;
473
+ border: 1px solid #e9ecef;
474
+ }
475
+
476
+ .test-name {
477
+ font-weight: 600;
478
+ font-size: 12px;
479
+ color: #495057;
480
+ }
481
+
482
+ .score {
483
+ font-size: 11px;
484
+ color: #6c757d;
485
+ }
486
+
487
+ .level {
488
+ font-size: 11px;
489
+ padding: 2px 6px;
490
+ border-radius: 4px;
491
+ margin-top: 4px;
492
+ font-weight: 500;
493
+ }
494
+
495
+ .level.normal {
496
+ background: #d4edda;
497
+ color: #155724;
498
+ }
499
+
500
+ .level.concern {
501
+ background: #fff3cd;
502
+ color: #856404;
503
+ }
504
+
505
+ .overall-status .status.normal {
506
+ background: #d4edda;
507
+ color: #155724;
508
+ border: 1px solid #c3e6cb;
509
+ }
510
+
511
+ .overall-status .status.alert {
512
+ background: #fff3cd;
513
+ color: #856404;
514
+ border: 1px solid #ffeaa7;
515
+ }
516
+
517
+ .emergency-alert {
518
+ background: #f8d7da;
519
+ border: 1px solid #f5c6cb;
520
+ border-radius: 6px;
521
+ padding: 10px;
522
+ margin-top: 15px;
523
+ }
524
+
525
+ .emergency-alert h5 {
526
+ color: #721c24;
527
+ margin-bottom: 8px;
528
+ }
529
+
530
+ .emergency-alert p {
531
+ color: #721c24;
532
+ font-size: 12px;
533
+ margin-bottom: 8px;
534
+ }
535
+
536
+ .emergency-alert ul {
537
+ list-style: none;
538
+ padding: 0;
539
+ margin: 0;
540
+ }
541
+
542
+ .emergency-alert li {
543
+ color: #721c24;
544
+ font-size: 11px;
545
+ padding: 2px 0;
546
+ }
547
+
548
+ .no-assessment {
549
+ text-align: center;
550
+ padding: 20px;
551
+ color: #6c757d;
552
+ }
553
+
554
+ .guest-info {
555
+ text-align: center;
556
+ padding: 20px;
557
+ color: #6c757d;
558
+ }
559
+
560
+ /* Responsive adjustments */
561
+ @media (max-width: 768px) {
562
+ .assessment-summary {
563
+ padding: 10px;
564
+ margin: 10px 0;
565
+ }
566
+
567
+ .assessment-summary h4 {
568
+ font-size: 14px;
569
+ }
570
+
571
+ .basic-info li {
572
+ font-size: 12px;
573
+ }
574
+ }
575
+
576
+ /* Add to static/styleChatBotUI.css */
577
+
578
+ .user-status {
579
+ background: #f8f9fa;
580
+ padding: 12px;
581
+ border-radius: 8px;
582
+ margin: 15px 0;
583
+ border: 1px solid #e9ecef;
584
+ }
585
+
586
+ .user-status .badge {
587
+ font-size: 0.85em;
588
+ padding: 4px 8px;
589
+ }
590
+
591
+ .badge.bg-success {
592
+ background-color: #28a745 !important;
593
+ color: white;
594
+ }
595
+
596
+ .badge.bg-warning {
597
+ background-color: #ffc107 !important;
598
+ color: #212529 !important;
599
+ }
600
+
601
+ .assessment-summary {
602
+ background: #ffffff;
603
+ border: 1px solid #e3f2fd;
604
+ border-radius: 10px;
605
+ padding: 15px;
606
+ margin: 15px 0;
607
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
608
+ }
609
+
610
+ .assessment-summary h4 {
611
+ color: #1976d2;
612
+ margin-bottom: 15px;
613
+ font-size: 1.1em;
614
+ }
615
+
616
+ .assessment-summary h5 {
617
+ color: #424242;
618
+ margin: 10px 0 5px 0;
619
+ font-size: 0.95em;
620
+ }
621
+
622
+ .basic-info ul {
623
+ list-style: none;
624
+ padding: 0;
625
+ margin: 0;
626
+ }
627
+
628
+ .basic-info li {
629
+ padding: 4px 0;
630
+ border-bottom: 1px solid #f0f0f0;
631
+ font-size: 0.9em;
632
+ }
633
+
634
+ .basic-info li:last-child {
635
+ border-bottom: none;
636
+ }
637
+
638
+ .score-item {
639
+ display: flex;
640
+ justify-content: space-between;
641
+ align-items: center;
642
+ padding: 8px 12px;
643
+ background: #f8f9fa;
644
+ border-radius: 6px;
645
+ margin: 5px 0;
646
+ border-left: 3px solid #17a2b8;
647
+ }
648
+
649
+ .test-name {
650
+ font-weight: 600;
651
+ color: #495057;
652
+ font-size: 0.85em;
653
+ }
654
+
655
+ .score {
656
+ font-weight: bold;
657
+ color: #007bff;
658
+ font-size: 0.9em;
659
+ }
660
+
661
+ .level {
662
+ padding: 2px 8px;
663
+ border-radius: 12px;
664
+ font-size: 0.75em;
665
+ font-weight: 600;
666
+ text-transform: uppercase;
667
+ }
668
+
669
+ .level.normal {
670
+ background: #d4edda;
671
+ color: #155724;
672
+ }
673
+
674
+ .level.concern {
675
+ background: #f8d7da;
676
+ color: #721c24;
677
+ }
678
+
679
+ .overall-status {
680
+ margin: 15px 0;
681
+ text-align: center;
682
+ }
683
+
684
+ .status {
685
+ padding: 10px;
686
+ border-radius: 8px;
687
+ font-weight: 600;
688
+ font-size: 0.9em;
689
+ }
690
+
691
+ .status.normal {
692
+ background: #d4edda;
693
+ color: #155724;
694
+ border: 1px solid #c3e6cb;
695
+ }
696
+
697
+ .status.alert {
698
+ background: #f8d7da;
699
+ color: #721c24;
700
+ border: 1px solid #f5c6cb;
701
+ }
702
+
703
+ .emergency-alert {
704
+ background: #fff3cd;
705
+ border: 1px solid #ffeaa7;
706
+ border-radius: 8px;
707
+ padding: 12px;
708
+ margin: 15px 0;
709
+ }
710
+
711
+ .emergency-alert h5 {
712
+ color: #856404;
713
+ margin-bottom: 8px;
714
+ }
715
+
716
+ .emergency-alert ul {
717
+ margin: 8px 0 0 20px;
718
+ font-size: 0.85em;
719
+ }
720
+
721
+ .assessment-actions {
722
+ text-align: center;
723
+ margin-top: 15px;
724
+ padding-top: 15px;
725
+ border-top: 1px solid #e9ecef;
726
+ }
727
+
728
+ .assessment-actions .btn {
729
+ font-size: 0.85em;
730
+ padding: 6px 12px;
731
+ }
732
+
733
+ .no-assessment {
734
+ background: #f8f9fa;
735
+ padding: 20px;
736
+ border-radius: 8px;
737
+ text-align: center;
738
+ margin: 15px 0;
739
+ border: 1px dashed #dee2e6;
740
+ }
741
+
742
+ .no-assessment p {
743
+ color: #6c757d;
744
+ margin-bottom: 15px;
745
+ font-size: 0.9em;
746
+ }
747
+
748
+ .guest-info {
749
+ background: #e3f2fd;
750
+ padding: 20px;
751
+ border-radius: 8px;
752
+ text-align: center;
753
+ margin: 15px 0;
754
+ border: 1px solid #bbdefb;
755
+ }
756
+
757
+ .guest-info h3 {
758
+ color: #1976d2;
759
+ margin-bottom: 10px;
760
+ }
761
+
762
+ .guest-info p {
763
+ color: #424242;
764
+ margin-bottom: 15px;
765
+ font-size: 0.9em;
766
+ }
767
+
768
+ .sidebar-actions {
769
+ border-top: 2px solid #e9ecef;
770
+ padding-top: 15px;
771
+ }
772
+
773
+ .sidebar-actions .btn {
774
+ font-size: 0.9em;
775
+ font-weight: 500;
776
+ border: 2px solid;
777
+ transition: all 0.3s ease;
778
+ }
779
+
780
+ .sidebar-actions .btn:hover {
781
+ transform: translateY(-1px);
782
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
783
+ }
784
+
785
+
786
+ #delete-account {
787
+ transition: all 0.3s ease;
788
+ border: 2px solid #dc3545 !important;
789
+ color: #dc3545 !important;
790
+ background-color: transparent;
791
+ }
792
+
793
+ #delete-account:hover {
794
+ background-color: #dc3545 !important;
795
+ color: white !important;
796
+ transform: translateY(-1px);
797
+ box-shadow: 0 4px 8px rgba(220, 53, 69, 0.3);
798
+ }
799
+
800
+ #delete-account:disabled {
801
+ opacity: 0.6;
802
+ cursor: not-allowed;
803
+ transform: none;
804
+ box-shadow: none;
805
+ }
806
+
807
+ /* Warning styling for delete confirmation */
808
+ .delete-warning {
809
+ border: 2px solid #dc3545;
810
+ background-color: #f8d7da;
811
+ color: #721c24;
812
+ padding: 15px;
813
+ border-radius: 8px;
814
+ margin: 10px 0;
815
+ }
816
+
817
+ /* Responsive adjustments */
818
+ @media (max-width: 768px) {
819
+ .assessment-summary {
820
+ padding: 10px;
821
+ margin: 10px 0;
822
+ }
823
+
824
+ .assessment-summary h4 {
825
+ font-size: 1em;
826
+ }
827
+
828
+ .basic-info li {
829
+ font-size: 0.85em;
830
+ }
831
+
832
+ .score-item {
833
+ padding: 6px 8px;
834
+ }
835
+
836
+ .test-name, .score {
837
+ font-size: 0.8em;
838
+ }
839
+
840
+ .level {
841
+ font-size: 0.7em;
842
+ padding: 1px 6px;
843
+ }
844
+ }
845
+
846
+ /* Responsive adjustments */
847
+ @media (max-width: 768px) {
848
+ .assessment-summary {
849
+ padding: 10px;
850
+ margin: 10px 0;
851
+ }
852
+
853
+ .assessment-summary h4 {
854
+ font-size: 14px;
855
+ }
856
+
857
+ .basic-info li {
858
+ font-size: 12px;
859
+ }
860
+ }
861
+
862
+
863
+ @media (max-width: 768px) {
864
+ .sidebar {
865
+ height: auto;
866
+ margin-bottom: 15px;
867
+ }
868
+ }
static/styleabout.css ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @import url('https://fonts.googleapis.com/css2?family=Ubuntu&display=swap');
3
+
4
+ *{
5
+
6
+ margin: 0;
7
+ padding: 0;
8
+ }
9
+
10
+ /*
11
+ scroller for crome AND INTERNET explorer */
12
+
13
+
14
+ ::-webkit-scrollbar{
15
+ width: 2em;
16
+ }
17
+
18
+
19
+ ::-webkit-scrollbar-track{
20
+ background: hsl(174 72% 56% / 1);
21
+ border-radius: 100vw;
22
+ margin-block: .1em;
23
+ }
24
+ ::-webkit-scrollbar-thumb{
25
+ background: hsl(120 20% 30% / 1);
26
+ border-radius: 100vw;
27
+ border: .25em solid hsl(174 72% 56% / 1);
28
+ }
29
+ ::-webkit-scrollbar-thumb:hover{
30
+ background: hsl(120 20% 10% / 1);
31
+ }
32
+
33
+
34
+
35
+
36
+ /* scroller for firefox */
37
+
38
+ @supports(scrollbar-color:rgb(11, 29, 15) rgb(51, 235, 171) ){
39
+
40
+ *{
41
+ scrollbar-color: rgb(11, 29, 15) rgb(51, 235, 171) ;
42
+ scrollbar-width: auto;
43
+ scrollbar-arrow-color: #4b5b39;
44
+
45
+
46
+ }
47
+
48
+ }
49
+
50
+
51
+
52
+
53
+
54
+
55
+ html{
56
+ scroll-behavior: smooth;
57
+ }
58
+
59
+
60
+ .logo{
61
+ width: 30%;
62
+ display: flex;
63
+ justify-content: left;
64
+ align-items: center;
65
+ }
66
+ .logo img{
67
+ width: 40%;
68
+
69
+
70
+ }
71
+
72
+
73
+ nav{
74
+ padding: 1.5rem;
75
+ box-sizing: border-box;
76
+ font-family: sans-serif;
77
+
78
+ }
79
+
80
+
81
+ .navbar{
82
+ width: 100%;
83
+ height: 10vh;
84
+ background:hsl(86, 82%, 63%);
85
+ position: sticky;
86
+ z-index: 3;
87
+
88
+
89
+
90
+ }
91
+
92
+
93
+ .nav-Links{
94
+ display: flex;
95
+ list-style: none;
96
+ gap: 5rem;
97
+ font-size: 1.2rem;
98
+
99
+ width: 100%;
100
+ display: flex;
101
+ list-style: none;
102
+ height: 100%;
103
+ justify-content: center;
104
+ align-items: center;
105
+ }
106
+
107
+ .nav-Links a{
108
+ text-decoration: none;
109
+ color:rgb(14, 20, 6); ;
110
+ /* #be00ff99;color: #ca10fa; */
111
+
112
+ font-size: 18px;
113
+ font-weight: bold;
114
+ font-family: sans-serif;
115
+ position: relative;
116
+ }
117
+
118
+ .nav-item{
119
+
120
+ position: relative;
121
+ }
122
+
123
+ .nav-Links li a::before{
124
+ content: '';
125
+ display: block;
126
+ height: 3.5px;
127
+ background:rgb(14, 20, 6);;
128
+ position: absolute;
129
+ /* top: -.75em; */
130
+ bottom: -.75em;
131
+ left: 0;
132
+ right: 0;
133
+ transform: scale(0,1);
134
+ /* transform-origin: right; */
135
+ /* transform-origin: left; */
136
+ transition: transform ease-in-out 250ms;
137
+
138
+ }
139
+
140
+ .nav-Links li a:hover:before{
141
+ transform: scale(1,1);
142
+
143
+ }
144
+
145
+
146
+
147
+
148
+
149
+ .background1{
150
+ /* background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/308367/halftone-yellow.png); */
151
+ background: linear-gradient(to right top, #65dfc9, #6cdbeb);
152
+
153
+
154
+ }
155
+
156
+
157
+
158
+
159
+ .text-big{
160
+
161
+ padding: 1rem;
162
+ border-radius: 10px;
163
+ text-align: center;
164
+ font-size: 41px;
165
+ font-family: 'Ubuntu', sans-serif;
166
+ margin: 1%
167
+
168
+
169
+ }
170
+
171
+ .text-small{
172
+ font-size: 18px;
173
+ margin: 5%;
174
+ text-align: center;
175
+ background: #b2dcb1;
176
+ border-radius: 10px;
177
+ }
178
+
179
+
180
+
181
+
182
+ /* body or section starts from here */
183
+
184
+
185
+ .firstsection{
186
+ height: 120vh;
187
+ display: flex;
188
+ flex-direction: row;
189
+ justify-content: center;
190
+
191
+ /* background: linear-gradient(to right top, #65dfc9, #6cdbeb); */
192
+ background: linear-gradient(to right top, #dfc665, #6ceb8c);
193
+ }
194
+
195
+
196
+ .box{
197
+ margin:auto;
198
+ width: 1200px;
199
+ height: 600px;
200
+ /*background:linear-gradient(to right top, #83ebd887, #83c0e9f0);*/
201
+ background: linear-gradient(to right bottom,
202
+ rgba(255,225,225,0.7),
203
+ rgba(255,225,225,0.3));
204
+ z-index: 2;
205
+ position: relative;
206
+ border-radius: 75px;
207
+ box-shadow: 0 0.25em 2em -2em black,
208
+ 0 40px 0 -20px rgba(255,225,225,0.8) ;
209
+
210
+ display: flex;
211
+ flex-direction: row;
212
+ justify-content: center;
213
+ align-items: center;
214
+ }
215
+
216
+
217
+
218
+ .first{
219
+ width: 80%;
220
+ height: 75%;
221
+ /* text-align: center; */
222
+
223
+
224
+
225
+
226
+ }
227
+
228
+ .first h1{
229
+ font-size: 2.7rem;
230
+ font-weight: 50;
231
+ margin: 2rem;
232
+ font-family: 'Ubuntu', sans-serif;
233
+ color: #4b5b39;
234
+ text-align: center;
235
+ }
236
+
237
+ .first p{
238
+ font-family: 'Ubuntu', sans-serif;
239
+ font-size: 1.4rem;
240
+ margin-top: 2rem;
241
+ color: rgb(84, 80, 80);
242
+ line-height: 1.6em;
243
+
244
+ }
245
+
static/styleassessment.css ADDED
@@ -0,0 +1,470 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @import url('https://fonts.googleapis.com/css2?family=Ubuntu&display=swap');
3
+
4
+ *{
5
+
6
+ margin: 0;
7
+ padding: 0;
8
+
9
+ }
10
+
11
+ /*
12
+ scroller for crome AND INTERNET explorer */
13
+
14
+
15
+ ::-webkit-scrollbar{
16
+ width: 2em;
17
+ }
18
+
19
+
20
+ ::-webkit-scrollbar-track{
21
+ background: hsl(174 72% 56% / 1);
22
+ border-radius: 100vw;
23
+ margin-block: .1em;
24
+ }
25
+ ::-webkit-scrollbar-thumb{
26
+ background: hsl(120 20% 30% / 1);
27
+ border-radius: 100vw;
28
+ border: .25em solid hsl(174 72% 56% / 1);
29
+ }
30
+ ::-webkit-scrollbar-thumb:hover{
31
+ background: hsl(120 20% 10% / 1);
32
+ }
33
+
34
+
35
+
36
+
37
+ /* scroller for firefox */
38
+
39
+ @supports(scrollbar-color:rgb(11, 29, 15) rgb(51, 235, 171) ){
40
+
41
+ *{
42
+ scrollbar-color: rgb(11, 29, 15) rgb(51, 235, 171) ;
43
+ scrollbar-width: auto;
44
+ scrollbar-arrow-color: #4b5b39;
45
+
46
+
47
+ }
48
+
49
+ }
50
+
51
+
52
+
53
+ html{
54
+ scroll-behavior: smooth;
55
+
56
+ }
57
+
58
+ /* CSS of Navbar start */
59
+
60
+
61
+ .logo{
62
+ width: 30%;
63
+ display: flex;
64
+ justify-content: left;
65
+ align-items: center;
66
+ }
67
+ .logo img{
68
+ width: 40%;
69
+
70
+
71
+ }
72
+
73
+
74
+ nav{
75
+ padding: 1.5rem;
76
+ box-sizing: border-box;
77
+ font-family: sans-serif;
78
+
79
+ }
80
+
81
+
82
+ .navbar{
83
+ width: 100%;
84
+ height: 10vh;
85
+ background:hsl(86, 82%, 63%);
86
+ position: sticky;
87
+ z-index: 3;
88
+
89
+
90
+
91
+ }
92
+
93
+
94
+ .nav-Links{
95
+ display: flex;
96
+ list-style: none;
97
+ gap: 5rem;
98
+ font-size: 1.2rem;
99
+
100
+ width: 100%;
101
+ display: flex;
102
+ list-style: none;
103
+ height: 100%;
104
+ justify-content: center;
105
+ align-items: center;
106
+ }
107
+
108
+ .nav-Links a{
109
+ text-decoration: none;
110
+ color:rgb(14, 20, 6); ;
111
+ /* #be00ff99;color: #ca10fa; */
112
+
113
+ font-size: 18px;
114
+ font-weight: bold;
115
+ font-family: sans-serif;
116
+ position: relative;
117
+ }
118
+
119
+ .nav-item{
120
+
121
+ position: relative;
122
+ }
123
+
124
+ .nav-Links li a::before{
125
+ content: '';
126
+ display: block;
127
+ height: 3.5px;
128
+ background:rgb(14, 20, 6);;
129
+ position: absolute;
130
+ /* top: -.75em; */
131
+ bottom: -.75em;
132
+ left: 0;
133
+ right: 0;
134
+ transform: scale(0,1);
135
+ /* transform-origin: right; */
136
+ /* transform-origin: left; */
137
+ transition: transform ease-in-out 250ms;
138
+
139
+ }
140
+
141
+ .nav-Links li a:hover:before{
142
+ transform: scale(1,1);
143
+
144
+ }
145
+
146
+ /* CSS of Navbar end */
147
+
148
+
149
+
150
+
151
+ /* CSS of form section starts */
152
+ .form-container {
153
+ display: flex;
154
+ justify-content: space-between;
155
+ align-items: center;
156
+ }
157
+
158
+ .left-section, .right-section {
159
+ width: 50%;
160
+ }
161
+ .image {
162
+ display: flex;
163
+ justify-content: center;
164
+ align-items: center;
165
+ }
166
+
167
+ .left-section .image img {
168
+ width: 70%;
169
+ height: auto;
170
+ }
171
+
172
+ .right-section {
173
+ padding: 20px;
174
+ }
175
+
176
+ .form-box {
177
+ border: 1px solid #ccc;
178
+ border-radius: 10px;
179
+ padding: 20px;
180
+ background-color: transparent;
181
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
182
+ width: 80%;
183
+ }
184
+ #sub-title {
185
+ font-size: 24px;
186
+ margin-bottom: 20px;
187
+ font-weight: bolder;
188
+ }
189
+
190
+
191
+ .form-input {
192
+ width: 92%;
193
+ padding: 10px;
194
+ margin-top: 5px;
195
+ border: 1px solid #ccc;
196
+ border-radius: 5px;
197
+ font-size: 15px;
198
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
199
+ background: #fff1f0;
200
+ text-align: center;
201
+ }
202
+
203
+ .gender-placeholder {
204
+ width: 100%;
205
+ }
206
+
207
+ .btn{
208
+ display: block;
209
+ margin: 50px auto;
210
+ width: fit-content;
211
+ border: 1px solid #242427;
212
+ color: aliceblue;
213
+ padding: 6px 10px;
214
+ border-radius: 6px;
215
+ font-family: 'Ubuntu', sans-serif;
216
+ text-decoration: none;
217
+ color: #242427;
218
+ cursor: pointer;
219
+
220
+ /* We need this to position
221
+ span inside button */
222
+ position: relative;
223
+ overflow: hidden;
224
+ box-shadow: 6px 7px 40px -4px
225
+ rgba(0, 0, 0, 0.2);
226
+
227
+ }
228
+ .btn-primary {
229
+ background-color:#646e3a;
230
+ color: white;
231
+ border: none;
232
+ font-size: medium;
233
+ padding: 10px 15px;
234
+ border-radius: 5px;
235
+ cursor: pointer;
236
+ }
237
+
238
+ .btn-primary:hover {
239
+ background-color: #242427;
240
+ color: white;
241
+ }
242
+ /* CSS of form section starts */
243
+
244
+ .firstsection{
245
+ height: 90vh;
246
+ display: flex;
247
+ flex-direction: row;
248
+ justify-content: center;
249
+ padding: 4rem 4rem;
250
+ align-items: center;
251
+ font-family: 'Ubuntu', sans-serif;
252
+ background: linear-gradient(to right top, #dfc665, #6ceb8c);
253
+ }
254
+
255
+
256
+ .box{
257
+ margin:auto;
258
+ width: 1200px;
259
+ height: fit-content;
260
+ /*background:linear-gradient(to right top, #83ebd887, #83c0e9f0);*/
261
+ background: linear-gradient(to right bottom,
262
+ rgba(255,225,225,0.7),
263
+ rgba(255,225,225,0.3));
264
+ z-index: 2;
265
+ position: relative;
266
+ border-radius: 75px;
267
+ box-shadow: 0 0.25em 2em -2em black,
268
+ 0 40px 0 -20px rgba(255,225,225,0.8) ;
269
+
270
+ display: flex;
271
+ flex-direction: row;
272
+ justify-content: center;
273
+ align-items: center;
274
+ }
275
+
276
+
277
+
278
+ .first{
279
+ width: 80%;
280
+ height: 75%;
281
+
282
+ }
283
+
284
+
285
+ .container{
286
+ width: 100%;
287
+ align-items: center;
288
+ /* margin: 3.5em auto 0 0.8em; */
289
+ }
290
+
291
+ form{
292
+ display: flex;
293
+ flex-direction: column;
294
+ justify-content: left;
295
+ align-items: start;
296
+ line-height: 1 rem;
297
+
298
+
299
+
300
+
301
+ }
302
+
303
+ #title{
304
+ font-size: 2em;
305
+ font-family: 'Ubuntu', sans-serif;
306
+ font-weight: 50;
307
+ }
308
+
309
+
310
+ header{
311
+
312
+ margin: 2rem;
313
+ color: #4b5b39;
314
+ text-align: center;
315
+
316
+ }
317
+
318
+
319
+
320
+ #survey-form{
321
+ color: #4b5b39;
322
+ font-family: 'Ubuntu', sans-serif;
323
+ font-size: 1.1em;
324
+ font-weight: 50;
325
+ align-items: center;
326
+
327
+ }
328
+
329
+
330
+
331
+ /* Scrollable question area for each section */
332
+ .row {
333
+ max-height: 350px; /* Adjust height as needed */
334
+ overflow-y: auto;
335
+ padding-right: 10px; /* For scrollbar space */
336
+ margin-bottom: 18px;
337
+ /* Optional: smooth scrolling */
338
+ scroll-behavior: smooth;
339
+ }
340
+
341
+ /* Optional: Custom scrollbar styling for Chrome/Edge */
342
+ .row::-webkit-scrollbar {
343
+ width: 8px;
344
+ }
345
+ .row::-webkit-scrollbar-thumb {
346
+ background: #b5fffc;
347
+ border-radius: 4px;
348
+ }
349
+ .row::-webkit-scrollbar-track {
350
+ background: #f0f0f0;
351
+ border-radius: 4px;
352
+ }
353
+
354
+ /* Optional: Custom scrollbar for Firefox */
355
+ .row {
356
+ scrollbar-width: thin;
357
+ scrollbar-color: #b5fffc #f0f0f0;
358
+ align-items: center;
359
+ }
360
+
361
+ .section-title {
362
+
363
+ font-size: 18px;
364
+ font-family: 'Ubuntu', sans-serif;
365
+ background: #c1d06f;
366
+ width: inherit;
367
+ font-weight: bold;
368
+ margin-bottom: 6px;
369
+ text-align: center;
370
+ padding: 2px;
371
+ border-radius: 6px;
372
+ }
373
+
374
+
375
+
376
+ .basic-info{
377
+ display: flex;
378
+ flex-direction: row;
379
+ }
380
+
381
+ .gender{
382
+ display: flex;
383
+ flex-direction: row;
384
+ }
385
+ .gender-placeholder{
386
+ text-align: center;
387
+ color: #4b5b39;;
388
+ }
389
+
390
+
391
+ .question-section{
392
+
393
+ display: flex;
394
+ width: 50%;
395
+ flex-direction: column;
396
+ align-items: left;
397
+ }
398
+
399
+ /* .question{
400
+ padding-bottom: 0.5em;
401
+ } */
402
+
403
+ .rating{
404
+ display: flex;
405
+ flex-direction: column;
406
+ }
407
+
408
+ .bascic-info{
409
+ padding: 2px;
410
+ }
411
+
412
+ .form-control {
413
+ /* height: 5vh; */
414
+ width: fit-content;
415
+ font-size: 15px;
416
+ border: 2px solid gray;
417
+ border-radius: 6px;
418
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
419
+ background: #fff1f0;
420
+ text-align: center;
421
+ margin-left: 6px;
422
+ padding: 6px;
423
+ box-sizing: border-box;
424
+ transition: border-color 0.3s ease;
425
+ }
426
+
427
+
428
+ /* .btn:hover{
429
+ background:#4b5b39;
430
+ } */
431
+
432
+
433
+
434
+ .btn span {
435
+ position: absolute;
436
+ border-radius: 50%;
437
+ /* To make it round */
438
+ background-color: rgba(0, 0, 0, 0.3);
439
+ width: 100px;
440
+ height: 100px;
441
+ margin-top: -50px;
442
+ /* for positioning */
443
+ margin-left: -50px;
444
+ animation: ripple 1s;
445
+ opacity: 0;
446
+ }
447
+ /* Add animation */
448
+ @keyframes ripple {
449
+ from {
450
+ opacity: 1;
451
+ transform: scale(0);
452
+ }
453
+ to {
454
+ opacity: 0;
455
+ transform: scale(10);
456
+ }
457
+ }
458
+
459
+
460
+
461
+
462
+
463
+
464
+ /* CSS of form section end */
465
+
466
+
467
+
468
+
469
+
470
+
static/stylehome.css ADDED
@@ -0,0 +1,470 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @import url('https://fonts.googleapis.com/css2?family=Ubuntu&display=swap');
3
+
4
+ *{
5
+
6
+ margin: 0;
7
+ padding: 0;
8
+
9
+ }
10
+
11
+ /*
12
+ scroller for crome AND INTERNET explorer */
13
+
14
+
15
+ ::-webkit-scrollbar{
16
+ width: 2em;
17
+ }
18
+
19
+
20
+ ::-webkit-scrollbar-track{
21
+ background: hsl(174 72% 56% / 1);
22
+ border-radius: 100vw;
23
+ margin-block: .1em;
24
+ }
25
+ ::-webkit-scrollbar-thumb{
26
+ background: hsl(120 20% 30% / 1);
27
+ border-radius: 100vw;
28
+ border: .25em solid hsl(174 72% 56% / 1);
29
+ }
30
+ ::-webkit-scrollbar-thumb:hover{
31
+ background: hsl(120 20% 10% / 1);
32
+ }
33
+
34
+
35
+
36
+
37
+ /* scroller for firefox */
38
+
39
+ @supports(scrollbar-color:rgb(11, 29, 15) rgb(51, 235, 171) ){
40
+
41
+ *{
42
+ scrollbar-color: rgb(11, 29, 15) rgb(51, 235, 171) ;
43
+ scrollbar-width: auto;
44
+ scrollbar-arrow-color: #4b5b39;
45
+
46
+
47
+ }
48
+
49
+ }
50
+
51
+
52
+
53
+ html{
54
+ scroll-behavior: smooth;
55
+
56
+ }
57
+
58
+ /* CSS of Navbar start */
59
+
60
+
61
+ .logo{
62
+ width: 30%;
63
+ display: flex;
64
+ justify-content: left;
65
+ align-items: center;
66
+ }
67
+ .logo img{
68
+ width: 40%;
69
+
70
+
71
+ }
72
+
73
+
74
+ nav{
75
+ padding: 1.5rem;
76
+ box-sizing: border-box;
77
+ font-family: sans-serif;
78
+
79
+ }
80
+
81
+
82
+ .navbar{
83
+ width: 100%;
84
+ height: 10vh;
85
+ background:hsl(86, 82%, 63%);
86
+ position: sticky;
87
+ z-index: 3;
88
+
89
+
90
+
91
+ }
92
+
93
+
94
+ .nav-Links{
95
+ display: flex;
96
+ list-style: none;
97
+ gap: 5rem;
98
+ font-size: 1.2rem;
99
+
100
+ width: 100%;
101
+ display: flex;
102
+ list-style: none;
103
+ height: 100%;
104
+ justify-content: center;
105
+ align-items: center;
106
+ }
107
+
108
+ .nav-Links a{
109
+ text-decoration: none;
110
+ color:rgb(14, 20, 6); ;
111
+ /* #be00ff99;color: #ca10fa; */
112
+
113
+ font-size: 18px;
114
+ font-weight: bold;
115
+ font-family: sans-serif;
116
+ position: relative;
117
+ }
118
+
119
+ .nav-item{
120
+
121
+ position: relative;
122
+ }
123
+
124
+ .nav-Links li a::before{
125
+ content: '';
126
+ display: block;
127
+ height: 3.5px;
128
+ background:rgb(14, 20, 6);;
129
+ position: absolute;
130
+ /* top: -.75em; */
131
+ bottom: -.75em;
132
+ left: 0;
133
+ right: 0;
134
+ transform: scale(0,1);
135
+ /* transform-origin: right; */
136
+ /* transform-origin: left; */
137
+ transition: transform ease-in-out 250ms;
138
+
139
+ }
140
+
141
+ .nav-Links li a:hover:before{
142
+ transform: scale(1,1);
143
+
144
+ }
145
+
146
+ /* CSS of Navbar end */
147
+
148
+
149
+
150
+
151
+ /* CSS of form section starts */
152
+ .form-container {
153
+ display: flex;
154
+ justify-content: space-between;
155
+ align-items: center;
156
+ }
157
+
158
+ .left-section, .right-section {
159
+ width: 50%;
160
+ }
161
+ .image {
162
+ display: flex;
163
+ justify-content: center;
164
+ align-items: center;
165
+ }
166
+
167
+ .left-section .image img {
168
+ width: 70%;
169
+ height: auto;
170
+ }
171
+
172
+ .right-section {
173
+ padding: 20px;
174
+ }
175
+
176
+ .form-box {
177
+ border: 1px solid #ccc;
178
+ border-radius: 10px;
179
+ padding: 20px;
180
+ background-color: transparent;
181
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
182
+ width: 80%;
183
+ }
184
+ #sub-title {
185
+ font-size: 24px;
186
+ margin-bottom: 20px;
187
+ font-weight: bolder;
188
+ }
189
+
190
+
191
+ .form-input {
192
+ width: 92%;
193
+ padding: 10px;
194
+ margin-top: 5px;
195
+ border: 1px solid #ccc;
196
+ border-radius: 5px;
197
+ font-size: 15px;
198
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
199
+ background: #fff1f0;
200
+ text-align: center;
201
+ }
202
+
203
+ .gender-placeholder {
204
+ width: 100%;
205
+ }
206
+
207
+ .btn{
208
+ display: block;
209
+ margin: 50px auto;
210
+ width: fit-content;
211
+ border: 1px solid #242427;
212
+ color: aliceblue;
213
+ padding: 6px 10px;
214
+ border-radius: 6px;
215
+ font-family: 'Ubuntu', sans-serif;
216
+ text-decoration: none;
217
+ color: #242427;
218
+ cursor: pointer;
219
+
220
+ /* We need this to position
221
+ span inside button */
222
+ position: relative;
223
+ overflow: hidden;
224
+ box-shadow: 6px 7px 40px -4px
225
+ rgba(0, 0, 0, 0.2);
226
+
227
+ }
228
+ .btn-primary {
229
+ background-color:#646e3a;
230
+ color: white;
231
+ border: none;
232
+ font-size: medium;
233
+ padding: 10px 15px;
234
+ border-radius: 5px;
235
+ cursor: pointer;
236
+ }
237
+
238
+ .btn-primary:hover {
239
+ background-color: #242427;
240
+ color: white;
241
+ }
242
+ /* CSS of form section starts */
243
+
244
+ .firstsection{
245
+ height: fit-content;
246
+ display: flex;
247
+ flex-direction: row;
248
+ justify-content: center;
249
+ padding: 2rem 2rem;
250
+ align-items: center;
251
+ font-family: 'Ubuntu', sans-serif;
252
+ background: linear-gradient(to right top, #dfc665, #6ceb8c);
253
+ }
254
+
255
+
256
+ .box{
257
+ margin:auto;
258
+ width: 1200px;
259
+ height: fit-content;
260
+ /*background:linear-gradient(to right top, #83ebd887, #83c0e9f0);*/
261
+ background: linear-gradient(to right bottom,
262
+ rgba(255,225,225,0.7),
263
+ rgba(255,225,225,0.3));
264
+ z-index: 2;
265
+ position: relative;
266
+ border-radius: 75px;
267
+ box-shadow: 0 0.25em 2em -2em black,
268
+ 0 40px 0 -20px rgba(255,225,225,0.8) ;
269
+
270
+ display: flex;
271
+ flex-direction: row;
272
+ justify-content: center;
273
+ align-items: center;
274
+ }
275
+
276
+
277
+
278
+ .first{
279
+ width: 80%;
280
+ height: 75%;
281
+
282
+ }
283
+
284
+
285
+ .container{
286
+ width: 100%;
287
+ align-items: center;
288
+ /* margin: 3.5em auto 0 0.8em; */
289
+ }
290
+
291
+ form{
292
+ display: flex;
293
+ flex-direction: column;
294
+ justify-content: left;
295
+ align-items: start;
296
+ line-height: 1 rem;
297
+
298
+
299
+
300
+
301
+ }
302
+
303
+ #title{
304
+ font-size: 2em;
305
+ font-family: 'Ubuntu', sans-serif;
306
+ font-weight: 50;
307
+ }
308
+
309
+
310
+ header{
311
+
312
+ margin: 2rem;
313
+ color: #4b5b39;
314
+ text-align: center;
315
+
316
+ }
317
+
318
+
319
+
320
+ #survey-form{
321
+ color: #4b5b39;
322
+ font-family: 'Ubuntu', sans-serif;
323
+ font-size: 1.1em;
324
+ font-weight: 50;
325
+ align-items: center;
326
+
327
+ }
328
+
329
+
330
+
331
+ /* Scrollable question area for each section */
332
+ .row {
333
+ max-height: 350px; /* Adjust height as needed */
334
+ overflow-y: auto;
335
+ padding-right: 10px; /* For scrollbar space */
336
+ margin-bottom: 18px;
337
+ /* Optional: smooth scrolling */
338
+ scroll-behavior: smooth;
339
+ }
340
+
341
+ /* Optional: Custom scrollbar styling for Chrome/Edge */
342
+ .row::-webkit-scrollbar {
343
+ width: 8px;
344
+ }
345
+ .row::-webkit-scrollbar-thumb {
346
+ background: #b5fffc;
347
+ border-radius: 4px;
348
+ }
349
+ .row::-webkit-scrollbar-track {
350
+ background: #f0f0f0;
351
+ border-radius: 4px;
352
+ }
353
+
354
+ /* Optional: Custom scrollbar for Firefox */
355
+ .row {
356
+ scrollbar-width: thin;
357
+ scrollbar-color: #b5fffc #f0f0f0;
358
+ align-items: center;
359
+ }
360
+
361
+ .section-title {
362
+
363
+ font-size: 18px;
364
+ font-family: 'Ubuntu', sans-serif;
365
+ background: #c1d06f;
366
+ width: inherit;
367
+ font-weight: bold;
368
+ margin-bottom: 6px;
369
+ text-align: center;
370
+ padding: 2px;
371
+ border-radius: 6px;
372
+ }
373
+
374
+
375
+
376
+ .basic-info{
377
+ display: flex;
378
+ flex-direction: row;
379
+ }
380
+
381
+ .gender{
382
+ display: flex;
383
+ flex-direction: row;
384
+ }
385
+ .gender-placeholder{
386
+ text-align: center;
387
+ color: #4b5b39;;
388
+ }
389
+
390
+
391
+ .question-section{
392
+
393
+ display: flex;
394
+ width: 50%;
395
+ flex-direction: column;
396
+ align-items: left;
397
+ }
398
+
399
+ /* .question{
400
+ padding-bottom: 0.5em;
401
+ } */
402
+
403
+ .rating{
404
+ display: flex;
405
+ flex-direction: column;
406
+ }
407
+
408
+ .bascic-info{
409
+ padding: 2px;
410
+ }
411
+
412
+ .form-control {
413
+ /* height: 5vh; */
414
+ width: fit-content;
415
+ font-size: 15px;
416
+ border: 2px solid gray;
417
+ border-radius: 6px;
418
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
419
+ background: #fff1f0;
420
+ text-align: center;
421
+ margin-left: 6px;
422
+ padding: 6px;
423
+ box-sizing: border-box;
424
+ transition: border-color 0.3s ease;
425
+ }
426
+
427
+
428
+ /* .btn:hover{
429
+ background:#4b5b39;
430
+ } */
431
+
432
+
433
+
434
+ .btn span {
435
+ position: absolute;
436
+ border-radius: 50%;
437
+ /* To make it round */
438
+ background-color: rgba(0, 0, 0, 0.3);
439
+ width: 100px;
440
+ height: 100px;
441
+ margin-top: -50px;
442
+ /* for positioning */
443
+ margin-left: -50px;
444
+ animation: ripple 1s;
445
+ opacity: 0;
446
+ }
447
+ /* Add animation */
448
+ @keyframes ripple {
449
+ from {
450
+ opacity: 1;
451
+ transform: scale(0);
452
+ }
453
+ to {
454
+ opacity: 0;
455
+ transform: scale(10);
456
+ }
457
+ }
458
+
459
+
460
+
461
+
462
+
463
+
464
+ /* CSS of form section end */
465
+
466
+
467
+
468
+
469
+
470
+
static/treeman.png ADDED

Git LFS Details

  • SHA256: bc77a2bd016d7e4189952368bb499708c429607a486b64dafdb4a59e832dd973
  • Pointer size: 131 Bytes
  • Size of remote file: 931 kB
survey_data/survey_20250626_143630_Harsh_Narayan.json ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "timestamp": "2025-06-26T14:36:30.957480",
3
+ "name": "Harsh Narayan",
4
+ "age": 25,
5
+ "sex": "Male",
6
+ "location": "Urban",
7
+ "emotion": "anger",
8
+ "prediction": "Mild",
9
+ "score": 3.1785573959350586,
10
+ "averages": {
11
+ "Self_Distraction": 2.0,
12
+ "Denial": 2.5,
13
+ "Venting": 3.0,
14
+ "Self_Blame": 3.0,
15
+ "Behavioural_Disengagement": 3.5,
16
+ "Acceptance": 3.0,
17
+ "Active_Coping": 4.0,
18
+ "Shyness": 2.888888888888889,
19
+ "Loneliness": 3.25,
20
+ "Self_Esteem": 2.6,
21
+ "Life_Satisfaction": 2.4
22
+ },
23
+ "raw_responses": {
24
+ "self_distraction": [
25
+ 2.0,
26
+ 2.0
27
+ ],
28
+ "denial": [
29
+ 2.0,
30
+ 3.0
31
+ ],
32
+ "venting": [
33
+ 3.0,
34
+ 3.0
35
+ ],
36
+ "self_blame": [
37
+ 2.0,
38
+ 4.0
39
+ ],
40
+ "behavioural_disengagement": [
41
+ 3.0,
42
+ 4.0
43
+ ],
44
+ "acceptance": [
45
+ 4.0,
46
+ 2.0
47
+ ],
48
+ "active_coping": [
49
+ 5.0,
50
+ 3.0
51
+ ],
52
+ "shyness": [
53
+ 1.0,
54
+ 3.0,
55
+ 2.0,
56
+ 3.0,
57
+ 2.0,
58
+ 5.0,
59
+ 4.0,
60
+ 3.0,
61
+ 3.0
62
+ ],
63
+ "loneliness": [
64
+ 4.0,
65
+ 2.0,
66
+ 3.0,
67
+ 4.0
68
+ ],
69
+ "self_esteem": [
70
+ 2.0,
71
+ 2.0,
72
+ 4.0,
73
+ 3.0,
74
+ 2.0
75
+ ],
76
+ "life_satisfaction": [
77
+ 2.0,
78
+ 2.0,
79
+ 3.0,
80
+ 3.0,
81
+ 2.0
82
+ ]
83
+ }
84
+ }
survey_data/survey_20250707_185716_Harsh_Narayan.json ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "timestamp": "2025-07-07T18:57:16.698853",
3
+ "name": "Harsh Narayan",
4
+ "age": 24,
5
+ "sex": "Female",
6
+ "location": "Rural",
7
+ "emotion": "confused",
8
+ "prediction": "Mild",
9
+ "score": 2.6052439212799072,
10
+ "averages": {
11
+ "Self_Distraction": 3.0,
12
+ "Denial": 2.5,
13
+ "Venting": 2.5,
14
+ "Self_Blame": 3.0,
15
+ "Behavioural_Disengagement": 3.0,
16
+ "Acceptance": 3.0,
17
+ "Active_Coping": 2.5,
18
+ "Shyness": 2.5555555555555554,
19
+ "Loneliness": 1.75,
20
+ "Self_Esteem": 2.2,
21
+ "Life_Satisfaction": 2.8
22
+ },
23
+ "raw_responses": {
24
+ "self_distraction": [
25
+ 4.0,
26
+ 2.0
27
+ ],
28
+ "denial": [
29
+ 2.0,
30
+ 3.0
31
+ ],
32
+ "venting": [
33
+ 2.0,
34
+ 3.0
35
+ ],
36
+ "self_blame": [
37
+ 3.0,
38
+ 3.0
39
+ ],
40
+ "behavioural_disengagement": [
41
+ 2.0,
42
+ 4.0
43
+ ],
44
+ "acceptance": [
45
+ 3.0,
46
+ 3.0
47
+ ],
48
+ "active_coping": [
49
+ 3.0,
50
+ 2.0
51
+ ],
52
+ "shyness": [
53
+ 3.0,
54
+ 2.0,
55
+ 3.0,
56
+ 2.0,
57
+ 2.0,
58
+ 4.0,
59
+ 2.0,
60
+ 3.0,
61
+ 2.0
62
+ ],
63
+ "loneliness": [
64
+ 2.0,
65
+ 2.0,
66
+ 1.0,
67
+ 2.0
68
+ ],
69
+ "self_esteem": [
70
+ 2.0,
71
+ 2.0,
72
+ 2.0,
73
+ 3.0,
74
+ 2.0
75
+ ],
76
+ "life_satisfaction": [
77
+ 4.0,
78
+ 1.0,
79
+ 4.0,
80
+ 2.0,
81
+ 3.0
82
+ ]
83
+ }
84
+ }
survey_data/survey_20250730_173819_Harsh_Narayan.json ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "timestamp": "2025-07-30T17:38:19.239336",
3
+ "name": "Harsh Narayan",
4
+ "age": 25,
5
+ "sex": "Male",
6
+ "location": "Urban",
7
+ "emotion": "anger",
8
+ "prediction": "Healthy",
9
+ "score": 1.6321943998336792,
10
+ "averages": {
11
+ "Self_Distraction": 1.5,
12
+ "Denial": 1.5,
13
+ "Venting": 1.5,
14
+ "Self_Blame": 2.0,
15
+ "Behavioural_Disengagement": 2.0,
16
+ "Acceptance": 3.0,
17
+ "Active_Coping": 3.0,
18
+ "Shyness": 2.4444444444444446,
19
+ "Loneliness": 2.25,
20
+ "Self_Esteem": 2.6,
21
+ "Life_Satisfaction": 2.8
22
+ },
23
+ "raw_responses": {
24
+ "self_distraction": [
25
+ 1.0,
26
+ 2.0
27
+ ],
28
+ "denial": [
29
+ 1.0,
30
+ 2.0
31
+ ],
32
+ "venting": [
33
+ 1.0,
34
+ 2.0
35
+ ],
36
+ "self_blame": [
37
+ 1.0,
38
+ 3.0
39
+ ],
40
+ "behavioural_disengagement": [
41
+ 2.0,
42
+ 2.0
43
+ ],
44
+ "acceptance": [
45
+ 2.0,
46
+ 4.0
47
+ ],
48
+ "active_coping": [
49
+ 2.0,
50
+ 4.0
51
+ ],
52
+ "shyness": [
53
+ 2.0,
54
+ 2.0,
55
+ 3.0,
56
+ 2.0,
57
+ 2.0,
58
+ 2.0,
59
+ 3.0,
60
+ 3.0,
61
+ 3.0
62
+ ],
63
+ "loneliness": [
64
+ 2.0,
65
+ 2.0,
66
+ 3.0,
67
+ 2.0
68
+ ],
69
+ "self_esteem": [
70
+ 4.0,
71
+ 2.0,
72
+ 3.0,
73
+ 2.0,
74
+ 2.0
75
+ ],
76
+ "life_satisfaction": [
77
+ 3.0,
78
+ 2.0,
79
+ 3.0,
80
+ 2.0,
81
+ 4.0
82
+ ]
83
+ }
84
+ }
survey_data/survey_20250731_141528_Rohit_Kumar.json ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "timestamp": "2025-07-31T14:15:28.643684",
3
+ "name": "Rohit Kumar",
4
+ "age": 26,
5
+ "sex": "Male",
6
+ "location": "Urban",
7
+ "emotion": "neutral/unsure",
8
+ "prediction": "Mild",
9
+ "score": 2.72636079788208,
10
+ "averages": {
11
+ "Self_Distraction": 3.5,
12
+ "Denial": 2.5,
13
+ "Venting": 3.5,
14
+ "Self_Blame": 3.0,
15
+ "Behavioural_Disengagement": 3.0,
16
+ "Acceptance": 4.0,
17
+ "Active_Coping": 3.5,
18
+ "Shyness": 2.7777777777777777,
19
+ "Loneliness": 1.75,
20
+ "Self_Esteem": 3.6,
21
+ "Life_Satisfaction": 2.6
22
+ },
23
+ "raw_responses": {
24
+ "self_distraction": [
25
+ 3.0,
26
+ 4.0
27
+ ],
28
+ "denial": [
29
+ 2.0,
30
+ 3.0
31
+ ],
32
+ "venting": [
33
+ 3.0,
34
+ 4.0
35
+ ],
36
+ "self_blame": [
37
+ 3.0,
38
+ 3.0
39
+ ],
40
+ "behavioural_disengagement": [
41
+ 3.0,
42
+ 3.0
43
+ ],
44
+ "acceptance": [
45
+ 4.0,
46
+ 4.0
47
+ ],
48
+ "active_coping": [
49
+ 3.0,
50
+ 4.0
51
+ ],
52
+ "shyness": [
53
+ 3.0,
54
+ 4.0,
55
+ 2.0,
56
+ 2.0,
57
+ 2.0,
58
+ 4.0,
59
+ 3.0,
60
+ 3.0,
61
+ 2.0
62
+ ],
63
+ "loneliness": [
64
+ 2.0,
65
+ 1.0,
66
+ 3.0,
67
+ 1.0
68
+ ],
69
+ "self_esteem": [
70
+ 2.0,
71
+ 4.0,
72
+ 4.0,
73
+ 4.0,
74
+ 4.0
75
+ ],
76
+ "life_satisfaction": [
77
+ 2.0,
78
+ 2.0,
79
+ 3.0,
80
+ 4.0,
81
+ 2.0
82
+ ]
83
+ }
84
+ }
templates/ChatbotUI.html ADDED
@@ -0,0 +1,1700 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Mental Health Assistant</title>
7
+ <link rel="icon" type="image/png" href="https://img.icons8.com/fluency/48/chromatography.png">
8
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <link rel="stylesheet" href="../static/styleChatBotUI.css">
11
+ </head>
12
+ <body>
13
+ <div class="container-fluid py-4">
14
+ <div class="row">
15
+ <!-- Sidebar -->
16
+ <div class="col-md-3 mb-3">
17
+
18
+
19
+ <div class="sidebar">
20
+ <div class="user-info">
21
+ {% if session.user_data and session.user_data.name != 'Guest' %}
22
+ <div class="user-profile">
23
+ <h3>👤 Welcome, {{ session.user_data.name }}!</h3>
24
+
25
+ <!-- User Status -->
26
+ <div class="user-status">
27
+ <p><strong>Account Status:</strong>
28
+ {% if session.user_data.has_completed_survey %}
29
+ <span class="badge bg-success">Assessment Complete</span>
30
+ {% else %}
31
+ <span class="badge bg-warning">No Assessment</span>
32
+ {% endif %}
33
+ </p>
34
+ {% if session.user_data.assessment_date %}
35
+ <p><strong>Last Assessment:</strong> {{ session.user_data.assessment_date }}</p>
36
+ {% endif %}
37
+ </div>
38
+
39
+ <!-- Assessment Information Section -->
40
+ {% if session.assessment_data %}
41
+ <div class="assessment-summary">
42
+ <h4>📋 Assessment Summary</h4>
43
+ <div class="basic-info">
44
+ <h5>Basic Information:</h5>
45
+ <ul>
46
+ <li><strong>Age:</strong> {{ session.assessment_data.basic_info.age }}</li>
47
+ <li><strong>Gender:</strong> {{ session.assessment_data.basic_info.gender }}</li>
48
+ <li><strong>Location:</strong> {{ session.assessment_data.basic_info.location }}</li>
49
+ <li><strong>Current Mood:</strong> {{ session.assessment_data.basic_info.emotion }}</li>
50
+ {% if session.assessment_data.basic_info.days_indoors %}
51
+ <li><strong>Days Indoors:</strong> {{ session.assessment_data.basic_info.days_indoors }}</li>
52
+ {% endif %}
53
+ {% if session.assessment_data.basic_info.history_of_mental_illness %}
54
+ <li><strong>Mental Health History:</strong> {{ session.assessment_data.basic_info.history_of_mental_illness }}</li>
55
+ {% endif %}
56
+ {% if session.assessment_data.basic_info.treatment %}
57
+ <li><strong>Current Treatment:</strong> {{ session.assessment_data.basic_info.treatment }}</li>
58
+ {% endif %}
59
+ </ul>
60
+ </div>
61
+
62
+ {% if session.assessment_data.assessment_result and session.assessment_data.assessment_result.detailed_scores %}
63
+ <div class="assessment-scores">
64
+ <h5>Assessment Results:</h5>
65
+ <div class="score-summary">
66
+ {% for test_name, scores in session.assessment_data.assessment_result.detailed_scores.items() %}
67
+ <div class="score-item">
68
+ <span class="test-name">{{ test_name }}:</span>
69
+ <span class="score">{{ scores.score }}/{{ scores.max_score }}</span>
70
+ <div class="level {{ 'concern' if 'severe' in scores.level.lower() or 'moderate' in scores.level.lower() else 'normal' }}">
71
+ {{ scores.level }}
72
+ </div>
73
+ </div>
74
+ {% endfor %}
75
+ </div>
76
+ </div>
77
+
78
+ <div class="overall-status">
79
+ <h5>Overall Status:</h5>
80
+ <div class="status {{ 'alert' if 'concern' in session.assessment_data.assessment_result.overall_status.lower() else 'normal' }}">
81
+ {{ session.assessment_data.assessment_result.overall_status }}
82
+ </div>
83
+ </div>
84
+ {% endif %}
85
+
86
+ {% if session.assessment_data.assessment_result and session.assessment_data.assessment_result.emergency_info %}
87
+ <div class="emergency-alert">
88
+ <h5>⚠️ Important:</h5>
89
+ <p>{{ session.assessment_data.assessment_result.emergency_info.message }}</p>
90
+ <ul>
91
+ {% for resource in session.assessment_data.assessment_result.emergency_info.resources %}
92
+ <li>{{ resource }}</li>
93
+ {% endfor %}
94
+ </ul>
95
+ </div>
96
+ {% endif %}
97
+
98
+ <div class="assessment-actions">
99
+ <a href="{{ url_for('assessment') }}" class="btn btn-sm btn-outline-primary">
100
+ 🔄 Retake Assessment
101
+ </a>
102
+ </div>
103
+ </div>
104
+ {% else %}
105
+ <div class="no-assessment">
106
+ <p>No assessment completed yet.</p>
107
+ <a href="{{ url_for('assessment') }}" class="btn btn-sm btn-outline-primary">Take Assessment</a>
108
+ </div>
109
+ {% endif %}
110
+ </div>
111
+ {% else %}
112
+ <div class="guest-info">
113
+ <h3>👋 Hello, Guest!</h3>
114
+ <p>You're using the chatbot as a guest. Sign up to save your assessment and chat history.</p>
115
+ <a href="{{ url_for('home') }}" class="btn btn-sm btn-outline-primary">Sign Up for Full Features</a>
116
+ </div>
117
+ {% endif %}
118
+ </div>
119
+
120
+ <!-- Action Buttons Section - ONLY ONE SET -->
121
+ <div class="sidebar-actions mt-4">
122
+ <button id="clear-chat" class="btn btn-outline-danger w-100 mb-2">
123
+ <i class="fas fa-trash-alt me-2"></i> Clear Chat
124
+ </button>
125
+
126
+ {% if session.user_data and session.user_data.name != 'Guest' %}
127
+ <button id="clear-history" class="btn btn-outline-warning w-100 mb-2">
128
+ <i class="fas fa-history me-2"></i> Clear History
129
+ </button>
130
+
131
+ <!-- ✅ NEW: Delete Account Button -->
132
+ <button id="delete-account" class="btn btn-outline-danger w-100 mb-2" style="border-color: #dc3545; color: #dc3545;">
133
+ <i class="fas fa-user-times me-2"></i> Delete Account
134
+ </button>
135
+ {% endif %}
136
+
137
+ <button id="end-session" class="btn btn-outline-secondary w-100">
138
+ <i class="fas fa-sign-out-alt me-2"></i> End Session
139
+ </button>
140
+ </div>
141
+ </div>
142
+ </div>
143
+
144
+ <!-- Chat Container -->
145
+ <div class="col-md-9">
146
+ <div class="chat-container">
147
+ <div class="chat-header">
148
+ <h5 class="mb-0">
149
+ <i class="fas fa-stethoscope me-2"></i>
150
+ Multi-Agent Mental Health Assistant Chatbot
151
+ </h5>
152
+ <small class="text-muted">Ask mental health questions via text or voice</small>
153
+ </div>
154
+
155
+
156
+ <div id="chat-body" class="chat-body">
157
+ <div class="message assistant-message">
158
+ <div class="agent-tag">System</div>
159
+ <div class="message-content">
160
+ <p id="welcome-text">
161
+ {% if user_data.name == 'Guest' %}
162
+ Welcome! I'm your mental health support assistant. You can ask me questions about mental health, share your feelings, or discuss any concerns you may have. How can I help you today?
163
+ {% elif user_data.emotion and user_data.emotion != 'neutral/unsure' %}
164
+ Hi {{ user_data.name }}! I understand you're feeling {{ user_data.emotion }}.
165
+ {% if user_data.result == 'Severe' %}
166
+ Given what you're experiencing, I want you to know that immediate support is available. How can I help you today?
167
+ {% elif user_data.result == 'Mild' %}
168
+ I'm here to provide support and guidance. What's on your mind?
169
+ {% else %}
170
+ I'm here to help you navigate through this. What would you like to talk about?
171
+ {% endif %}
172
+ {% else %}
173
+ Welcome {{ user_data.name }}! I'm your mental health support assistant. How are you feeling today?
174
+ {% endif %}
175
+ </p>
176
+ </div>
177
+ <div class="audio-controls mt-2">
178
+ <button class="btn btn-sm btn-outline-primary play-tts-btn"
179
+ data-message-id="welcome-msg"
180
+ data-text="">
181
+ <i class="fas fa-play"></i> Play Voice Response
182
+ </button>
183
+ <span class="audio-status ms-2"></span>
184
+ </div>
185
+ </div>
186
+ </div>
187
+
188
+
189
+
190
+ <div class="chat-footer">
191
+
192
+ <form id="chat-form" class="d-flex align-items-end" onsubmit="return false;" action="javascript:void(0);">
193
+ <!-- Voice recording button -->
194
+ <button type="button" class="btn btn-warning rounded-circle me-2" id="voice-record-btn" style="width: 40px; height: 40px;">
195
+ <i class="fas fa-microphone"></i>
196
+ </button>
197
+
198
+ <div class="flex-grow-1">
199
+ <textarea id="message-input" class="form-control message-input" rows="1" placeholder="Type your message or use voice recording..."></textarea>
200
+ </div>
201
+
202
+ <button type="button" class="btn btn-primary rounded-circle ms-2" id="send-btn" style="width: 40px; height: 40px;">
203
+ <i class="fas fa-paper-plane"></i>
204
+ </button>
205
+ </form>
206
+ </div>
207
+ </div>
208
+ </div>
209
+ </div>
210
+ </div>
211
+
212
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
213
+ <!-- Update the message display section -->
214
+ <script>
215
+ function displayMessage(message, isUser = false, agent = null, confidence = null) {
216
+ const chatMessages = document.getElementById('chat-messages');
217
+ const messageDiv = document.createElement('div');
218
+ messageDiv.className = `message ${isUser ? 'user-message' : 'bot-message'}`;
219
+
220
+ if (isUser) {
221
+ messageDiv.innerHTML = `
222
+ <div class="message-content">
223
+ <strong>You:</strong> ${message}
224
+ </div>
225
+ `;
226
+ } else {
227
+ // Check if this is an enhanced response with exercises and questions
228
+ const hasExercises = message.includes('Mental Health Exercises') || message.includes('**Mental Health Exercises:**');
229
+ const hasQuestions = message.includes('Follow-up Questions') || message.includes('Questions to Consider');
230
+
231
+ // Format the enhanced response
232
+ let formattedMessage = formatEnhancedResponse(message);
233
+
234
+ messageDiv.innerHTML = `
235
+ <div class="message-content bot-response">
236
+ ${formattedMessage}
237
+ ${agent ? `<div class="agent-info">Response by: ${agent}</div>` : ''}
238
+ ${confidence ? `<div class="confidence-score">Confidence: ${(confidence * 100).toFixed(1)}%</div>` : ''}
239
+ ${hasExercises ? '<div class="feature-tag">✨ Includes Mental Health Exercises</div>' : ''}
240
+ ${hasQuestions ? '<div class="feature-tag">❓ Includes Follow-up Questions</div>' : ''}
241
+ </div>
242
+ `;
243
+ }
244
+
245
+ chatMessages.appendChild(messageDiv);
246
+ chatMessages.scrollTop = chatMessages.scrollHeight;
247
+ }
248
+
249
+ function formatEnhancedResponse(message) {
250
+ // Enhanced formatting for better readability
251
+ let formatted = message
252
+ // Format section headers
253
+ .replace(/\*\*(EMPATHY\/ACKNOWLEDGMENT|SOLUTION\/INFORMATION|RECOMMENDATIONS):\*\*/g,
254
+ '<h3 class="section-header">$1</h3>')
255
+
256
+ // Format subsection headers
257
+ .replace(/\*\*(Mental Health Exercises|Follow-up Questions[^:]*|Next Steps):\*\*/g,
258
+ '<h4 class="subsection-header">$1</h4>')
259
+
260
+ // Format exercise items
261
+ .replace(/• \*\*([^:]+):\*\* ([^\n]+)/g,
262
+ '<div class="exercise-item"><strong>$1:</strong> <span class="exercise-description">$2</span></div>')
263
+
264
+ // Format regular bullet points
265
+ .replace(/• ([^\n]+)/g, '<li class="recommendation-item">$1</li>')
266
+
267
+ // Format bold text
268
+ .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
269
+
270
+ // Format line breaks
271
+ .replace(/\n/g, '<br>');
272
+
273
+ return formatted;
274
+ }
275
+
276
+ // Add CSS for enhanced formatting
277
+ const enhancedStyles = `
278
+ <style>
279
+ .section-header {
280
+ color: #2c5530;
281
+ border-bottom: 2px solid #4a7c59;
282
+ padding-bottom: 5px;
283
+ margin: 15px 0 10px 0;
284
+ font-size: 1.1em;
285
+ }
286
+
287
+ .subsection-header {
288
+ color: #4a7c59;
289
+ margin: 10px 0 5px 0;
290
+ font-size: 1em;
291
+ }
292
+
293
+ .exercise-item {
294
+ background: #f0f8f0;
295
+ padding: 8px 12px;
296
+ margin: 5px 0;
297
+ border-left: 3px solid #4a7c59;
298
+ border-radius: 0 5px 5px 0;
299
+ }
300
+
301
+ .exercise-description {
302
+ color: #2c5530;
303
+ font-style: italic;
304
+ }
305
+
306
+ .recommendation-item {
307
+ margin: 5px 0;
308
+ padding: 3px 0;
309
+ list-style-type: disc;
310
+ margin-left: 20px;
311
+ }
312
+
313
+ .feature-tag {
314
+ display: inline-block;
315
+ background: #e8f5e8;
316
+ color: #2c5530;
317
+ padding: 2px 8px;
318
+ border-radius: 12px;
319
+ font-size: 0.8em;
320
+ margin: 2px;
321
+ border: 1px solid #4a7c59;
322
+ }
323
+
324
+ .agent-info {
325
+ font-size: 0.8em;
326
+ color: #666;
327
+ margin-top: 10px;
328
+ font-style: italic;
329
+ }
330
+
331
+ .confidence-score {
332
+ font-size: 0.8em;
333
+ color: #4a7c59;
334
+ margin-top: 5px;
335
+ font-weight: bold;
336
+ }
337
+
338
+ .bot-response {
339
+ line-height: 1.6;
340
+ }
341
+
342
+ .empathy-section, .solution-section, .recommendations-section {
343
+ margin: 15px 0;
344
+ padding: 12px;
345
+ border-radius: 8px;
346
+ border-left: 4px solid;
347
+ }
348
+
349
+ .empathy-section {
350
+ background-color: #e3f2fd;
351
+ border-left-color: #2196f3;
352
+ }
353
+
354
+ .solution-section {
355
+ background-color: #f3e5f5;
356
+ border-left-color: #9c27b0;
357
+ }
358
+
359
+ .recommendations-section {
360
+ background-color: #e8f5e8;
361
+ border-left-color: #4caf50;
362
+ }
363
+
364
+ .section-title {
365
+ font-weight: bold;
366
+ margin-bottom: 8px;
367
+ color: #333;
368
+ }
369
+
370
+ .structured-response {
371
+ line-height: 1.6;
372
+ }
373
+ </style>
374
+ `;
375
+
376
+ // Add the enhanced styles to the page
377
+ document.head.insertAdjacentHTML('beforeend', enhancedStyles);
378
+ </script>
379
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.2/marked.min.js"></script>
380
+
381
+ <script>
382
+
383
+
384
+
385
+ // Global variables
386
+ let mediaRecorder;
387
+ let audioChunks = [];
388
+ let isRecording = false;
389
+ let currentAudio = null;
390
+ let isVoiceQuery = false;
391
+ let globalAudioController = null;
392
+
393
+ // ✅ FIXED: Safe template variable handling
394
+ function getUserData() {
395
+ try {
396
+ return {
397
+ name: '{{ session.get("user_data", {}).get("name", "Guest") | e }}' || 'Guest',
398
+ emotion: '{{ session.get("user_data", {}).get("emotion", "neutral") | e }}' || 'neutral',
399
+ result: '{{ session.get("user_data", {}).get("result", "Unknown") | e }}' || 'Unknown'
400
+ };
401
+ } catch (e) {
402
+ console.warn('Template variable error:', e);
403
+ return {
404
+ name: 'Guest',
405
+ emotion: 'neutral',
406
+ result: 'Unknown'
407
+ };
408
+ }
409
+ }
410
+
411
+ // ✅ SINGLE DOMContentLoaded listener with PROPER event binding
412
+ document.addEventListener('DOMContentLoaded', function() {
413
+ console.log('🚀 DOM loaded, initializing chat...');
414
+
415
+ // Get elements with error checking
416
+ const chatBody = document.getElementById('chat-body');
417
+ const chatForm = document.getElementById('chat-form');
418
+ const messageInput = document.getElementById('message-input');
419
+ const sendBtn = document.getElementById('send-btn');
420
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
421
+ const clearChatBtn = document.getElementById('clear-chat');
422
+ const clearHistoryBtn = document.getElementById('clear-history');
423
+ const endSessionBtn = document.getElementById('end-session');
424
+ // Delete account - Clean binding
425
+ const deleteAccountBtn = document.getElementById('delete-account');
426
+ if (deleteAccountBtn) {
427
+ deleteAccountBtn.addEventListener('click', deleteAccountHandler);
428
+ }
429
+
430
+ // Debug: Check if critical elements exist
431
+ if (!chatBody) {
432
+ console.error('❌ chat-body element not found!');
433
+ return;
434
+ }
435
+ if (!chatForm) {
436
+ console.error('❌ chat-form element not found!');
437
+ return;
438
+ }
439
+ if (!messageInput) {
440
+ console.error('❌ message-input element not found!');
441
+ return;
442
+ }
443
+ if (!sendBtn) {
444
+ console.error('❌ send-btn element not found!');
445
+ return;
446
+ }
447
+
448
+ console.log('✅ All critical elements found');
449
+
450
+ // Add global audio controls
451
+ addGlobalAudioControls();
452
+
453
+ // Check backend connection
454
+ checkBackendConnection();
455
+
456
+ // Load conversation history
457
+ loadConversationHistory();
458
+
459
+ // ✅ CRITICAL FIX: Use button click instead of form submit
460
+ sendBtn.addEventListener('click', function(e) {
461
+ e.preventDefault();
462
+ e.stopPropagation();
463
+ console.log('📤 Send button clicked');
464
+ handleMessageSend();
465
+ });
466
+
467
+ // ✅ REMOVE form submit listener entirely
468
+ // chatForm.addEventListener('submit', handleFormSubmission); // REMOVE THIS
469
+
470
+ // ✅ Enter key handling
471
+ messageInput.addEventListener('keydown', function(e) {
472
+ if (e.key === 'Enter' && !e.shiftKey) {
473
+ e.preventDefault();
474
+ e.stopPropagation();
475
+ console.log('⌨️ Enter key pressed');
476
+ handleMessageSend();
477
+ }
478
+ });
479
+
480
+ // Voice recording - Clean binding
481
+ if (voiceRecordBtn) {
482
+ voiceRecordBtn.addEventListener('click', toggleRecording);
483
+ }
484
+
485
+ // Clear chat - Clean binding
486
+ if (clearChatBtn) {
487
+ clearChatBtn.addEventListener('click', clearChatHandler);
488
+ }
489
+
490
+ // Clear history - Clean binding
491
+ if (clearHistoryBtn) {
492
+ clearHistoryBtn.addEventListener('click', clearHistoryHandler);
493
+ }
494
+
495
+ // End session - Clean binding
496
+ if (endSessionBtn) {
497
+ endSessionBtn.addEventListener('click', endSessionHandler);
498
+ }
499
+
500
+ // Auto-resize textarea
501
+ messageInput.addEventListener('input', function() {
502
+ this.style.height = 'auto';
503
+ this.style.height = this.scrollHeight + 'px';
504
+ });
505
+
506
+ // Initialize TTS for welcome message
507
+ initializeTTSButtons();
508
+
509
+ console.log('✅ Chat initialization complete');
510
+ });
511
+
512
+ // ✅ NEW: Single message send handler
513
+ async function handleMessageSend() {
514
+ console.log('📝 Handling message send');
515
+
516
+ const messageInput = document.getElementById('message-input');
517
+ const sendBtn = document.getElementById('send-btn');
518
+ const message = messageInput.value.trim();
519
+
520
+ if (!message) {
521
+ console.log('⏭️ Empty message, skipping');
522
+ return;
523
+ }
524
+
525
+ // Prevent multiple sends
526
+ if (sendBtn.disabled) {
527
+ console.log('⏭️ Send already in progress, ignoring');
528
+ return;
529
+ }
530
+
531
+ sendBtn.disabled = true;
532
+ sendBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
533
+
534
+ console.log('💬 Processing message:', message);
535
+
536
+ try {
537
+ // Add user message immediately
538
+ addUserMessage(message);
539
+ console.log('✅ User message added successfully');
540
+
541
+ // Clear input
542
+ messageInput.value = '';
543
+ messageInput.style.height = 'auto';
544
+
545
+ // Show typing indicator
546
+ const typingIndicator = addTypingIndicator();
547
+
548
+ console.log('🚀 Sending request to /chat_message');
549
+
550
+ const userData = getUserData();
551
+ console.log('👤 User data:', userData);
552
+
553
+ const requestBody = {
554
+ message: message,
555
+ user_data: userData
556
+ };
557
+ console.log('📦 Request body:', JSON.stringify(requestBody, null, 2));
558
+
559
+ console.log('🌐 Making fetch request...');
560
+
561
+ const response = await fetch('/chat_message', {
562
+ method: 'POST',
563
+ headers: {
564
+ 'Content-Type': 'application/json',
565
+ },
566
+ credentials: 'include',
567
+ body: JSON.stringify(requestBody)
568
+ });
569
+
570
+ console.log('📡 Response received - Status:', response.status);
571
+
572
+ if (!response.ok) {
573
+ const errorText = await response.text();
574
+ console.error('❌ Response not OK:', response.status, errorText);
575
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
576
+ }
577
+
578
+ console.log('📖 Reading response JSON...');
579
+ const data = await response.json();
580
+ console.log('✅ Parsed response data:', JSON.stringify(data, null, 2));
581
+
582
+ // Remove typing indicator
583
+ removeTypingIndicator(typingIndicator);
584
+
585
+ if (data && data.response) {
586
+ console.log('📝 Response text length:', data.response.length);
587
+ console.log('📝 Agent:', data.agent);
588
+ console.log('📝 Adding assistant message...');
589
+
590
+ addAssistantMessage(data.response, data.agent || 'Assistant');
591
+ console.log('✅ Assistant message added successfully');
592
+
593
+ // Auto-play for voice queries
594
+ if (isVoiceQuery) {
595
+ setTimeout(() => {
596
+ const lastMessage = document.querySelector('#chat-body .message:last-child');
597
+ const playButton = lastMessage?.querySelector('.play-tts-btn');
598
+ if (playButton) {
599
+ playButton.click();
600
+ }
601
+ }, 800);
602
+ isVoiceQuery = false;
603
+ }
604
+ } else {
605
+ console.error('❌ No response in data:', data);
606
+ addAssistantMessage('Sorry, I received an empty response. Please try again.', 'System');
607
+ }
608
+
609
+ } catch (error) {
610
+ console.error('❌ Error details:', error);
611
+ removeTypingIndicator(typingIndicator);
612
+ addAssistantMessage('Sorry, there was a network error. Please check your connection and try again.', 'System');
613
+ } finally {
614
+ // Re-enable send button
615
+ sendBtn.disabled = false;
616
+ sendBtn.innerHTML = '<i class="fas fa-paper-plane"></i>';
617
+ }
618
+
619
+ scrollToBottom();
620
+ }
621
+
622
+
623
+ // ✅ ADD: Backend connection check with user feedback
624
+ async function checkBackendConnection() {
625
+ try {
626
+ console.log('🔗 Checking FastAPI backend connection...');
627
+
628
+ const response = await fetch('/test_backend_connection', {
629
+ method: 'GET',
630
+ timeout: 5000
631
+ });
632
+
633
+ if (response.ok) {
634
+ console.log('✅ FastAPI backend is connected and ready');
635
+ return true;
636
+ } else {
637
+ console.log('⚠️ FastAPI backend responded with error:', response.status);
638
+ showBackendWarning();
639
+ return false;
640
+ }
641
+ } catch (error) {
642
+ console.log('❌ FastAPI backend is not available:', error.message);
643
+ showBackendWarning();
644
+ return false;
645
+ }
646
+ }
647
+
648
+ // ✅ ADD: Delete account event handler
649
+ function deleteAccountHandler() {
650
+ // Multi-step confirmation for safety
651
+ const userName = getUserData().name;
652
+
653
+ // First confirmation
654
+ if (!confirm(`⚠️ WARNING: Are you sure you want to permanently delete your account?`)) {
655
+ return;
656
+ }
657
+
658
+ // Second confirmation with username
659
+ const confirmText = prompt(
660
+ `🚨 FINAL WARNING: This action cannot be undone!\n\n` +
661
+ `Your account "${userName}" and ALL associated data will be permanently deleted, including:\n` +
662
+ `• Your profile information\n` +
663
+ `• All assessment results\n` +
664
+ `• Complete conversation history\n` +
665
+ `• All saved data\n\n` +
666
+ `Type "DELETE MY ACCOUNT" (exactly) to confirm:`
667
+ );
668
+
669
+ if (confirmText !== "DELETE MY ACCOUNT") {
670
+ alert("Account deletion cancelled. The text must match exactly.");
671
+ return;
672
+ }
673
+
674
+ // Show loading state
675
+ const deleteBtn = document.getElementById('delete-account');
676
+ if (deleteBtn) {
677
+ deleteBtn.disabled = true;
678
+ deleteBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i> Deleting...';
679
+ }
680
+
681
+ // Make delete request
682
+ fetch('/delete_account', {
683
+ method: 'POST',
684
+ headers: {
685
+ 'Content-Type': 'application/json',
686
+ },
687
+ credentials: 'include'
688
+ })
689
+ .then(response => response.json())
690
+ .then(data => {
691
+ if (data.status === 'success') {
692
+ alert('Your account has been permanently deleted. You will now be redirected to the home page.');
693
+ window.location.href = '/';
694
+ } else {
695
+ alert('Error deleting account: ' + (data.message || 'Unknown error'));
696
+ // Reset button
697
+ if (deleteBtn) {
698
+ deleteBtn.disabled = false;
699
+ deleteBtn.innerHTML = '<i class="fas fa-user-times me-2"></i> Delete Account';
700
+ }
701
+ }
702
+ })
703
+ .catch(error => {
704
+ console.error('Error:', error);
705
+ alert('Network error occurred while deleting account. Please try again.');
706
+ // Reset button
707
+ if (deleteBtn) {
708
+ deleteBtn.disabled = false;
709
+ deleteBtn.innerHTML = '<i class="fas fa-user-times me-2"></i> Delete Account';
710
+ }
711
+ });
712
+ }
713
+
714
+
715
+
716
+ function showBackendWarning() {
717
+ const chatBody = document.getElementById('chat-body');
718
+ if (chatBody) {
719
+ const warningElement = document.createElement('div');
720
+ warningElement.className = 'message assistant-message bg-warning-subtle';
721
+ warningElement.innerHTML = `
722
+ <div class="agent-tag">System Notice</div>
723
+ <div class="message-content">
724
+ <p>⚠️ <strong>Backend Notice:</strong> The AI assistant backend is not fully available. You'll receive basic responses while we work to restore full functionality.</p>
725
+ <p><small>Please ensure FastAPI is running on port 8000, then refresh the page.</small></p>
726
+ </div>
727
+ `;
728
+ chatBody.appendChild(warningElement);
729
+ scrollToBottom();
730
+ }
731
+ }
732
+
733
+
734
+
735
+ // ✅ FIXED: Robust message display functions
736
+ function addUserMessage(message) {
737
+ const chatBody = document.getElementById('chat-body');
738
+
739
+ if (!chatBody) {
740
+ console.error('❌ Chat body not found for user message!');
741
+ return;
742
+ }
743
+
744
+ console.log('✅ Adding user message:', message);
745
+
746
+ const userMessageElement = document.createElement('div');
747
+ userMessageElement.className = 'message user-message';
748
+ userMessageElement.innerHTML = `<p>${escapeHtml(message)}</p>`;
749
+
750
+ chatBody.appendChild(userMessageElement);
751
+ scrollToBottom();
752
+
753
+ console.log('✅ User message element added to DOM');
754
+ }
755
+
756
+ function addTypingIndicator() {
757
+ const chatBody = document.getElementById('chat-body');
758
+
759
+ if (!chatBody) {
760
+ console.error('❌ Chat body not found for typing indicator!');
761
+ return null;
762
+ }
763
+
764
+ const thinkingElement = document.createElement('div');
765
+ thinkingElement.className = 'message assistant-message typing-indicator';
766
+ thinkingElement.innerHTML = `
767
+ <div class="agent-tag">Assistant</div>
768
+ <div class="message-content">
769
+ <p>Thinking...</p>
770
+ </div>
771
+ `;
772
+
773
+ chatBody.appendChild(thinkingElement);
774
+ scrollToBottom();
775
+
776
+ console.log('✅ Typing indicator added');
777
+ return thinkingElement;
778
+ }
779
+
780
+ function removeTypingIndicator(typingIndicator) {
781
+ if (typingIndicator && typingIndicator.parentNode) {
782
+ typingIndicator.remove();
783
+ console.log('✅ Typing indicator removed');
784
+ }
785
+ }
786
+
787
+ function addAssistantMessage(message, agent = 'Assistant') {
788
+ const chatBody = document.getElementById('chat-body');
789
+
790
+ if (!chatBody) {
791
+ console.error('❌ Chat body not found for assistant message!');
792
+ return;
793
+ }
794
+
795
+ console.log('✅ Adding assistant message from:', agent);
796
+
797
+ const messageId = 'msg-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
798
+
799
+ // ✅ FIXED: Simplified message formatting
800
+ let formattedMessage = formatMessage(message);
801
+
802
+ const assistantMessageElement = document.createElement('div');
803
+ assistantMessageElement.className = 'message assistant-message';
804
+
805
+ assistantMessageElement.innerHTML = `
806
+ <div class="agent-tag">${escapeHtml(agent)}</div>
807
+ <div class="message-content">${formattedMessage}</div>
808
+ <div class="audio-controls mt-2">
809
+ <button class="btn btn-sm btn-outline-primary play-tts-btn"
810
+ data-message-id="${messageId}"
811
+ data-text="${encodeURIComponent(message)}">
812
+ <i class="fas fa-play"></i> Play Voice
813
+ </button>
814
+ <span class="audio-status ms-2"></span>
815
+ </div>
816
+ `;
817
+
818
+ chatBody.appendChild(assistantMessageElement);
819
+
820
+ // ✅ FIXED: Add event listener to the new play button
821
+ const playButton = assistantMessageElement.querySelector('.play-tts-btn');
822
+ const audioStatus = assistantMessageElement.querySelector('.audio-status');
823
+
824
+ if (playButton && audioStatus) {
825
+ playButton.addEventListener('click', function() {
826
+ const text = decodeURIComponent(this.getAttribute('data-text'));
827
+ playMessageTTS(this, text, audioStatus);
828
+ });
829
+ }
830
+
831
+ scrollToBottom();
832
+ console.log('✅ Assistant message fully added with event listeners!');
833
+ }
834
+
835
+ // ✅ FIXED: Simplified message formatting
836
+ function formatMessage(message) {
837
+ if (!message) return '';
838
+
839
+ // Use marked.js if available, otherwise simple formatting
840
+ if (typeof marked !== 'undefined') {
841
+ try {
842
+ return marked.parse(message);
843
+ } catch (e) {
844
+ console.warn('Marked.js parsing failed, using simple formatting');
845
+ }
846
+ }
847
+
848
+ // Simple fallback formatting
849
+ let formatted = escapeHtml(message);
850
+
851
+ // Convert **bold** to <strong>
852
+ formatted = formatted.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
853
+
854
+ // Convert *italic* to <em>
855
+ formatted = formatted.replace(/\*([^*]+)\*/g, '<em>$1</em>');
856
+
857
+ // Convert line breaks
858
+ formatted = formatted.replace(/\n/g, '<br>');
859
+
860
+ // Convert bullet points
861
+ formatted = formatted.replace(/• ([^\n]+)/g, '<li>$1</li>');
862
+
863
+ return formatted;
864
+ }
865
+
866
+ function escapeHtml(text) {
867
+ const div = document.createElement('div');
868
+ div.textContent = text;
869
+ return div.innerHTML;
870
+ }
871
+
872
+ function scrollToBottom() {
873
+ const chatBody = document.getElementById('chat-body');
874
+ if (chatBody) {
875
+ chatBody.scrollTop = chatBody.scrollHeight;
876
+ }
877
+ }
878
+
879
+ // ✅ FIXED: Initialize TTS buttons
880
+ function initializeTTSButtons() {
881
+ document.querySelectorAll('.play-tts-btn').forEach(button => {
882
+ // Remove existing listeners to prevent duplicates
883
+ const newButton = button.cloneNode(true);
884
+ button.parentNode.replaceChild(newButton, button);
885
+
886
+ const text = newButton.getAttribute('data-text');
887
+ const audioStatus = newButton.parentElement.querySelector('.audio-status');
888
+
889
+ newButton.addEventListener('click', function() {
890
+ playMessageTTS(this, text, audioStatus);
891
+ });
892
+ });
893
+ }
894
+
895
+ // ✅ MISSING: Event handler functions
896
+ function clearChatHandler() {
897
+ if (confirm('Are you sure you want to clear the current chat?')) {
898
+ clearChatDisplay();
899
+ }
900
+ }
901
+
902
+ async function clearHistoryHandler() {
903
+ if (confirm('Are you sure you want to clear your conversation history permanently?')) {
904
+ await clearConversationHistory();
905
+ }
906
+ }
907
+
908
+ function endSessionHandler() {
909
+ if (confirm('Are you sure you want to end your session?')) {
910
+ endUserSession();
911
+ }
912
+ }
913
+
914
+ // ✅ MISSING: Clear chat display function
915
+ function clearChatDisplay() {
916
+ if (currentAudio) {
917
+ stopGlobalAudio();
918
+ }
919
+
920
+ const chatBody = document.getElementById('chat-body');
921
+ if (!chatBody) return;
922
+
923
+ // Clear all messages
924
+ chatBody.innerHTML = '';
925
+
926
+ // Add welcome message back
927
+ const welcomeMessage = document.createElement('div');
928
+ welcomeMessage.className = 'message assistant-message';
929
+ welcomeMessage.innerHTML = `
930
+ <div class="agent-tag">System</div>
931
+ <div class="message-content">
932
+ <p>Chat cleared. How can I help you today?</p>
933
+ </div>
934
+ <div class="audio-controls mt-2">
935
+ <button class="btn btn-sm btn-outline-primary play-tts-btn" data-text="Chat cleared. How can I help you today?">
936
+ <i class="fas fa-play"></i> Play Voice Response
937
+ </button>
938
+ <span class="audio-status ms-2"></span>
939
+ </div>
940
+ `;
941
+ chatBody.appendChild(welcomeMessage);
942
+
943
+ // Initialize TTS for welcome message
944
+ initializeTTSButtons();
945
+
946
+ console.log('✅ Chat display cleared');
947
+ }
948
+
949
+ // ✅ MISSING: Clear conversation history function
950
+ async function clearConversationHistory() {
951
+ try {
952
+ const response = await fetch('/delete_conversation_history', {
953
+ method: 'POST',
954
+ credentials: 'include'
955
+ });
956
+
957
+ if (response.ok) {
958
+ clearChatDisplay();
959
+ alert('Conversation history cleared successfully!');
960
+ } else {
961
+ alert('Failed to clear conversation history');
962
+ }
963
+ } catch (error) {
964
+ console.error('Error clearing history:', error);
965
+ alert('Error clearing conversation history');
966
+ }
967
+ }
968
+
969
+ // ✅ MISSING: End session function
970
+ function endUserSession() {
971
+ if (currentAudio) {
972
+ stopGlobalAudio();
973
+ }
974
+
975
+ fetch('/clear_session', {
976
+ method: 'POST',
977
+ credentials: 'include'
978
+ }).then(response => response.json())
979
+ .then(data => {
980
+ if (data.redirect) {
981
+ window.location.href = data.redirect;
982
+ }
983
+ }).catch(() => {
984
+ window.location.href = '/';
985
+ });
986
+ }
987
+
988
+ // ✅ MISSING: Load conversation history function
989
+ async function loadConversationHistory() {
990
+ try {
991
+ const response = await fetch('/load_conversation_history');
992
+ if (response.ok) {
993
+ const data = await response.json();
994
+ const messages = data.messages || [];
995
+
996
+ if (messages.length > 0) {
997
+ const chatBody = document.getElementById('chat-body');
998
+
999
+ // Clear default welcome messages
1000
+ const defaultMessages = chatBody.querySelectorAll('.message.assistant-message');
1001
+ defaultMessages.forEach(msg => {
1002
+ const content = msg.querySelector('.message-content p');
1003
+ if (content && content.textContent.includes('Welcome')) {
1004
+ msg.remove();
1005
+ }
1006
+ });
1007
+
1008
+ // Add history messages
1009
+ messages.forEach(msg => {
1010
+ if (msg.role === 'user') {
1011
+ addUserMessage(msg.content);
1012
+ } else if (msg.role === 'assistant') {
1013
+ addAssistantMessage(msg.content, 'Assistant');
1014
+ }
1015
+ });
1016
+
1017
+ scrollToBottom();
1018
+ }
1019
+ }
1020
+ } catch (error) {
1021
+ console.log('No conversation history available or user is guest');
1022
+ }
1023
+ }
1024
+
1025
+ // ✅ COMPLETE: Toggle recording function (was missing)
1026
+ function toggleRecording() {
1027
+ if (!isRecording) {
1028
+ startRecording();
1029
+ } else {
1030
+ stopRecording();
1031
+ }
1032
+ }
1033
+
1034
+ // ✅ COMPLETE: Start recording function
1035
+ function startRecording() {
1036
+ if (currentAudio) {
1037
+ stopGlobalAudio();
1038
+ }
1039
+
1040
+ navigator.mediaDevices.getUserMedia({
1041
+ audio: {
1042
+ echoCancellation: true,
1043
+ noiseSuppression: true,
1044
+ autoGainControl: true,
1045
+ sampleRate: 16000,
1046
+ channelCount: 1
1047
+ }
1048
+ })
1049
+ .then(stream => {
1050
+ const options = { mimeType: 'audio/webm;codecs=opus' };
1051
+ if (!MediaRecorder.isTypeSupported(options.mimeType)) {
1052
+ options.mimeType = 'audio/webm';
1053
+ }
1054
+
1055
+ mediaRecorder = new MediaRecorder(stream, options);
1056
+ audioChunks = [];
1057
+
1058
+ mediaRecorder.addEventListener('dataavailable', event => {
1059
+ if (event.data.size > 0) {
1060
+ audioChunks.push(event.data);
1061
+ }
1062
+ });
1063
+
1064
+ mediaRecorder.addEventListener('stop', () => {
1065
+ const audioBlob = new Blob(audioChunks, { type: mediaRecorder.mimeType });
1066
+
1067
+ if (audioBlob.size < 1000) {
1068
+ alert('Recording too short. Please speak for at least 2-3 seconds.');
1069
+ resetVoiceButton();
1070
+ return;
1071
+ }
1072
+
1073
+ isVoiceQuery = true;
1074
+ transcribeSpeech(audioBlob);
1075
+ stream.getTracks().forEach(track => track.stop());
1076
+ });
1077
+
1078
+ mediaRecorder.start(100);
1079
+ isRecording = true;
1080
+
1081
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
1082
+ voiceRecordBtn.innerHTML = '<i class="fas fa-stop"></i>';
1083
+ voiceRecordBtn.classList.remove('btn-warning');
1084
+ voiceRecordBtn.classList.add('btn-danger');
1085
+
1086
+ setTimeout(() => {
1087
+ if (isRecording) {
1088
+ stopRecording();
1089
+ }
1090
+ }, 10000);
1091
+ })
1092
+ .catch(error => {
1093
+ console.error('Microphone error:', error);
1094
+ alert('Could not access microphone. Please check permissions.');
1095
+ });
1096
+ }
1097
+
1098
+ // ✅ COMPLETE: Stop recording function
1099
+ function stopRecording() {
1100
+ if (mediaRecorder && isRecording) {
1101
+ mediaRecorder.stop();
1102
+ isRecording = false;
1103
+
1104
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
1105
+ voiceRecordBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
1106
+ voiceRecordBtn.disabled = true;
1107
+ }
1108
+ }
1109
+
1110
+ // ✅ COMPLETE: Transcribe speech function
1111
+ function transcribeSpeech(audioBlob) {
1112
+ const formData = new FormData();
1113
+ formData.append('audio', audioBlob, 'recording.webm');
1114
+
1115
+ fetch('/transcribe', {
1116
+ method: 'POST',
1117
+ body: formData
1118
+ })
1119
+ .then(response => response.json())
1120
+ .then(data => {
1121
+ if (data.transcript && data.transcript.trim()) {
1122
+ const messageInput = document.getElementById('message-input');
1123
+ messageInput.value = data.transcript;
1124
+ messageInput.focus();
1125
+
1126
+ isVoiceQuery = true;
1127
+
1128
+ setTimeout(() => {
1129
+ handleMessageSend(); // ✅ FIXED: Call handleMessageSend instead of form submit
1130
+ }, 500);
1131
+
1132
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
1133
+ voiceRecordBtn.innerHTML = '<i class="fas fa-check"></i>';
1134
+ voiceRecordBtn.classList.remove('btn-danger');
1135
+ voiceRecordBtn.classList.add('btn-success');
1136
+ setTimeout(resetVoiceButton, 1500);
1137
+ } else {
1138
+ alert(data.error || 'No speech detected. Please speak clearly and try again.');
1139
+ resetVoiceButton();
1140
+ }
1141
+ })
1142
+ .catch(error => {
1143
+ console.error('Transcription error:', error);
1144
+ alert('Transcription failed. Please try again.');
1145
+ resetVoiceButton();
1146
+ });
1147
+ }
1148
+
1149
+ // ✅ COMPLETE: Reset voice button function
1150
+ function resetVoiceButton() {
1151
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
1152
+ if (voiceRecordBtn) {
1153
+ voiceRecordBtn.disabled = false;
1154
+ voiceRecordBtn.innerHTML = '<i class="fas fa-microphone"></i>';
1155
+ voiceRecordBtn.classList.remove('btn-danger', 'btn-success');
1156
+ voiceRecordBtn.classList.add('btn-warning');
1157
+ }
1158
+ }
1159
+
1160
+ // ✅ MISSING: Show backend warning function
1161
+ function showBackendWarning() {
1162
+ const chatBody = document.getElementById('chat-body');
1163
+ if (chatBody) {
1164
+ const warningElement = document.createElement('div');
1165
+ warningElement.className = 'message assistant-message bg-warning-subtle';
1166
+ warningElement.innerHTML = `
1167
+ <div class="agent-tag">System Notice</div>
1168
+ <div class="message-content">
1169
+ <p>⚠️ <strong>Backend Notice:</strong> The AI assistant backend is not fully available. You'll receive basic responses while we work to restore full functionality.</p>
1170
+ <p><small>Please ensure FastAPI is running on port 8000, then refresh the page.</small></p>
1171
+ </div>
1172
+ `;
1173
+ chatBody.appendChild(warningElement);
1174
+ scrollToBottom();
1175
+ }
1176
+ }
1177
+
1178
+ // ✅ FIXED: Clear chat display
1179
+ function clearChatDisplay() {
1180
+ if (currentAudio) {
1181
+ stopGlobalAudio();
1182
+ }
1183
+
1184
+ const chatBody = document.getElementById('chat-body');
1185
+ if (!chatBody) return;
1186
+
1187
+ // Clear all messages
1188
+ chatBody.innerHTML = '';
1189
+
1190
+ // Add welcome message back
1191
+ const welcomeMessage = document.createElement('div');
1192
+ welcomeMessage.className = 'message assistant-message';
1193
+ welcomeMessage.innerHTML = `
1194
+ <div class="agent-tag">System</div>
1195
+ <div class="message-content">
1196
+ <p>Chat cleared. How can I help you today?</p>
1197
+ </div>
1198
+ <div class="audio-controls mt-2">
1199
+ <button class="btn btn-sm btn-outline-primary play-tts-btn" data-text="Chat cleared. How can I help you today?">
1200
+ <i class="fas fa-play"></i> Play Voice
1201
+ </button>
1202
+ <span class="audio-status ms-2"></span>
1203
+ </div>
1204
+ `;
1205
+ chatBody.appendChild(welcomeMessage);
1206
+
1207
+ // Initialize TTS for welcome message
1208
+ initializeTTSButtons();
1209
+
1210
+ console.log('✅ Chat display cleared');
1211
+ }
1212
+
1213
+ async function clearConversationHistory() {
1214
+ try {
1215
+ const response = await fetch('/delete_conversation_history', {
1216
+ method: 'POST',
1217
+ credentials: 'include'
1218
+ });
1219
+
1220
+ if (response.ok) {
1221
+ clearChatDisplay();
1222
+ alert('Conversation history cleared successfully!');
1223
+ } else {
1224
+ alert('Failed to clear conversation history');
1225
+ }
1226
+ } catch (error) {
1227
+ console.error('Error clearing history:', error);
1228
+ alert('Error clearing conversation history');
1229
+ }
1230
+ }
1231
+
1232
+ function endUserSession() {
1233
+ if (currentAudio) {
1234
+ stopGlobalAudio();
1235
+ }
1236
+
1237
+ fetch('/clear_session', {
1238
+ method: 'POST',
1239
+ credentials: 'include'
1240
+ }).then(response => response.json())
1241
+ .then(data => {
1242
+ if (data.redirect) {
1243
+ window.location.href = data.redirect;
1244
+ }
1245
+ }).catch(() => {
1246
+ window.location.href = '/';
1247
+ });
1248
+ }
1249
+
1250
+ // ===== AUDIO CONTROL FUNCTIONS =====
1251
+ function addGlobalAudioControls() {
1252
+ const globalControls = document.createElement('div');
1253
+ globalControls.id = 'global-audio-controls';
1254
+ globalControls.className = 'position-fixed top-0 end-0 m-3 p-2 bg-dark text-white rounded shadow';
1255
+ globalControls.style.zIndex = '1000';
1256
+ globalControls.style.display = 'none';
1257
+ globalControls.innerHTML = `
1258
+ <button id="global-pause-btn" class="btn btn-sm btn-light me-2">
1259
+ <i class="fas fa-pause"></i>
1260
+ </button>
1261
+ <button id="global-stop-btn" class="btn btn-sm btn-danger">
1262
+ <i class="fas fa-stop"></i>
1263
+ </button>
1264
+ <span id="global-audio-status" class="ms-2">Playing...</span>
1265
+ `;
1266
+ document.body.appendChild(globalControls);
1267
+
1268
+ document.getElementById('global-pause-btn').addEventListener('click', toggleGlobalAudio);
1269
+ document.getElementById('global-stop-btn').addEventListener('click', stopGlobalAudio);
1270
+ }
1271
+
1272
+ function showGlobalControls() {
1273
+ const controls = document.getElementById('global-audio-controls');
1274
+ if (controls) controls.style.display = 'block';
1275
+ }
1276
+
1277
+ function hideGlobalControls() {
1278
+ const controls = document.getElementById('global-audio-controls');
1279
+ if (controls) controls.style.display = 'none';
1280
+ }
1281
+
1282
+ function toggleGlobalAudio() {
1283
+ if (currentAudio) {
1284
+ const globalPauseBtn = document.getElementById('global-pause-btn');
1285
+ const globalStatus = document.getElementById('global-audio-status');
1286
+
1287
+ if (currentAudio.paused) {
1288
+ currentAudio.play();
1289
+ globalPauseBtn.innerHTML = '<i class="fas fa-pause"></i>';
1290
+ globalStatus.textContent = 'Playing...';
1291
+ } else {
1292
+ currentAudio.pause();
1293
+ globalPauseBtn.innerHTML = '<i class="fas fa-play"></i>';
1294
+ globalStatus.textContent = 'Paused';
1295
+ }
1296
+ }
1297
+ }
1298
+
1299
+ function stopGlobalAudio() {
1300
+ if (currentAudio) {
1301
+ currentAudio.pause();
1302
+ currentAudio.currentTime = 0;
1303
+ currentAudio = null;
1304
+ hideGlobalControls();
1305
+ resetAllPlayButtons();
1306
+ }
1307
+ }
1308
+
1309
+ async function playMessageTTS(button, text, statusElement) {
1310
+ const messageId = button.getAttribute('data-message-id');
1311
+ const cleanText = removeMarkdown(text);
1312
+
1313
+ // If this message is currently playing, toggle pause/play
1314
+ if (currentAudio && currentAudio.dataset && currentAudio.dataset.messageId === messageId) {
1315
+ if (!currentAudio.paused) {
1316
+ currentAudio.pause();
1317
+ button.innerHTML = '<i class="fas fa-play"></i> Resume';
1318
+ statusElement.textContent = 'Paused';
1319
+ return;
1320
+ } else {
1321
+ currentAudio.play();
1322
+ button.innerHTML = '<i class="fas fa-pause"></i> Pause';
1323
+ statusElement.textContent = 'Playing...';
1324
+ return;
1325
+ }
1326
+ }
1327
+
1328
+ // Stop any currently playing audio
1329
+ if (currentAudio) {
1330
+ stopGlobalAudio();
1331
+ }
1332
+
1333
+ // Show loading state
1334
+ button.disabled = true;
1335
+ button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Generating...';
1336
+ statusElement.textContent = 'Generating speech...';
1337
+
1338
+ try {
1339
+ const response = await fetch('/generate-speech', {
1340
+ method: 'POST',
1341
+ headers: {
1342
+ 'Content-Type': 'application/json'
1343
+ },
1344
+ body: JSON.stringify({ text: cleanText })
1345
+ });
1346
+
1347
+ if (!response.ok) {
1348
+ throw new Error(`HTTP error! status: ${response.status}`);
1349
+ }
1350
+
1351
+ const audioBlob = await response.blob();
1352
+ const audioUrl = URL.createObjectURL(audioBlob);
1353
+
1354
+ currentAudio = new Audio(audioUrl);
1355
+ currentAudio.dataset = { messageId: messageId };
1356
+
1357
+ currentAudio.oncanplay = () => {
1358
+ button.disabled = false;
1359
+ button.innerHTML = '<i class="fas fa-pause"></i> Pause';
1360
+ button.classList.remove('btn-outline-primary');
1361
+ button.classList.add('btn-primary');
1362
+ statusElement.textContent = 'Ready to play';
1363
+ };
1364
+
1365
+ currentAudio.onplay = () => {
1366
+ button.innerHTML = '<i class="fas fa-pause"></i> Pause';
1367
+ statusElement.textContent = 'Playing...';
1368
+ showGlobalControls();
1369
+ };
1370
+
1371
+ currentAudio.onpause = () => {
1372
+ button.innerHTML = '<i class="fas fa-play"></i> Resume';
1373
+ statusElement.textContent = 'Paused';
1374
+ };
1375
+
1376
+ currentAudio.onended = () => {
1377
+ button.innerHTML = '<i class="fas fa-play"></i> Play Again';
1378
+ button.classList.remove('btn-primary');
1379
+ button.classList.add('btn-outline-primary');
1380
+ statusElement.textContent = 'Finished';
1381
+ hideGlobalControls();
1382
+ URL.revokeObjectURL(audioUrl);
1383
+ currentAudio = null;
1384
+ };
1385
+
1386
+ currentAudio.onerror = (e) => {
1387
+ console.error('Audio playback error:', e);
1388
+ button.innerHTML = '<i class="fas fa-exclamation-triangle"></i> Error';
1389
+ button.disabled = false;
1390
+ statusElement.textContent = 'Playback error';
1391
+ hideGlobalControls();
1392
+ };
1393
+
1394
+ // Start playing
1395
+ currentAudio.play();
1396
+
1397
+ } catch (error) {
1398
+ console.error("TTS Error:", error);
1399
+ button.innerHTML = '<i class="fas fa-exclamation-triangle"></i> Failed';
1400
+ button.disabled = false;
1401
+ statusElement.textContent = 'Generation failed';
1402
+ hideGlobalControls();
1403
+ }
1404
+ }
1405
+
1406
+
1407
+ // ✅ NEW: Function to sync TTS text with actual displayed text
1408
+ function syncWelcomeMessageTTS() {
1409
+ const welcomeTextElement = document.getElementById('welcome-text');
1410
+ const welcomePlayButton = document.querySelector('[data-message-id="welcome-msg"]');
1411
+
1412
+ if (welcomeTextElement && welcomePlayButton) {
1413
+ const actualText = welcomeTextElement.textContent.trim();
1414
+ welcomePlayButton.setAttribute('data-text', encodeURIComponent(actualText));
1415
+
1416
+ // Add click handler
1417
+ welcomePlayButton.addEventListener('click', function() {
1418
+ const text = decodeURIComponent(this.getAttribute('data-text'));
1419
+ const audioStatus = this.parentElement.querySelector('.audio-status');
1420
+ playMessageTTS(this, text, audioStatus);
1421
+ });
1422
+
1423
+ console.log('✅ Welcome message TTS synchronized with display text');
1424
+ }
1425
+ }
1426
+
1427
+ // ✅ UPDATE: Call sync function after DOM loads
1428
+ document.addEventListener('DOMContentLoaded', function() {
1429
+ console.log('🚀 DOM loaded, initializing chat...');
1430
+
1431
+ // ... your existing DOMContentLoaded code ...
1432
+
1433
+ // Initialize TTS for welcome message
1434
+ initializeTTSButtons();
1435
+
1436
+ // ✅ ADD: Sync welcome message TTS
1437
+ syncWelcomeMessageTTS();
1438
+
1439
+ console.log('✅ Chat initialization complete');
1440
+ });
1441
+
1442
+ // ✅ UPDATE: Enhanced initializeTTSButtons function
1443
+ function initializeTTSButtons() {
1444
+ document.querySelectorAll('.play-tts-btn').forEach(button => {
1445
+ // Skip welcome message - handled separately
1446
+ if (button.getAttribute('data-message-id') === 'welcome-msg') {
1447
+ return;
1448
+ }
1449
+
1450
+ // Remove existing listeners to prevent duplicates
1451
+ const newButton = button.cloneNode(true);
1452
+ button.parentNode.replaceChild(newButton, button);
1453
+
1454
+ const text = newButton.getAttribute('data-text');
1455
+ const audioStatus = newButton.parentElement.querySelector('.audio-status');
1456
+
1457
+ newButton.addEventListener('click', function() {
1458
+ const decodedText = decodeURIComponent(text);
1459
+ playMessageTTS(this, decodedText, audioStatus);
1460
+ });
1461
+ });
1462
+ }
1463
+
1464
+ function resetAllPlayButtons() {
1465
+ document.querySelectorAll('.play-tts-btn').forEach(btn => {
1466
+ btn.innerHTML = '<i class="fas fa-play"></i> Play Voice';
1467
+ btn.classList.remove('btn-primary');
1468
+ btn.classList.add('btn-outline-primary');
1469
+ btn.disabled = false;
1470
+ });
1471
+ document.querySelectorAll('.audio-status').forEach(status => {
1472
+ status.textContent = '';
1473
+ });
1474
+ }
1475
+
1476
+ function removeMarkdown(text) {
1477
+ if (!text) return '';
1478
+
1479
+ let cleanText = text;
1480
+ cleanText = cleanText.replace(/```[\s\S]*?```/g, ' [Code example] ');
1481
+ cleanText = cleanText.replace(/`([^`]+)`/g, '$1');
1482
+ cleanText = cleanText.replace(/#{1,6}\s+/g, '');
1483
+ cleanText = cleanText.replace(/(\*\*|__)(.*?)\1/g, '$2');
1484
+ cleanText = cleanText.replace(/(\*|_)(.*?)\1/g, '$2');
1485
+ cleanText = cleanText.replace(/^\s*[\*\-+]\s+/gm, '. ');
1486
+ cleanText = cleanText.replace(/^\s*\d+\.\s+/gm, '. ');
1487
+ cleanText = cleanText.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1');
1488
+ cleanText = cleanText.replace(/!\[([^\]]*)\]\([^)]+\)/g, ' [Image] ');
1489
+ cleanText = cleanText.replace(/^\>\s+/gm, '');
1490
+ cleanText = cleanText.replace(/\n{2,}/g, '. ');
1491
+ cleanText = cleanText.replace(/\n/g, ' ');
1492
+ cleanText = cleanText.replace(/\s+/g, ' ');
1493
+ cleanText = cleanText.trim();
1494
+
1495
+ if (cleanText && !cleanText.endsWith('.') && !cleanText.endsWith('!') && !cleanText.endsWith('?')) {
1496
+ cleanText += '.';
1497
+ }
1498
+
1499
+ return cleanText;
1500
+ }
1501
+
1502
+ // ===== VOICE RECORDING FUNCTIONS =====
1503
+ function toggleRecording() {
1504
+ if (!isRecording) {
1505
+ startRecording();
1506
+ } else {
1507
+ stopRecording();
1508
+ }
1509
+ }
1510
+
1511
+ function startRecording() {
1512
+ if (currentAudio) {
1513
+ stopGlobalAudio();
1514
+ }
1515
+
1516
+ navigator.mediaDevices.getUserMedia({
1517
+ audio: {
1518
+ echoCancellation: true,
1519
+ noiseSuppression: true,
1520
+ autoGainControl: true,
1521
+ sampleRate: 16000,
1522
+ channelCount: 1
1523
+ }
1524
+ })
1525
+ .then(stream => {
1526
+ const options = { mimeType: 'audio/webm;codecs=opus' };
1527
+ if (!MediaRecorder.isTypeSupported(options.mimeType)) {
1528
+ options.mimeType = 'audio/webm';
1529
+ }
1530
+
1531
+ mediaRecorder = new MediaRecorder(stream, options);
1532
+ audioChunks = [];
1533
+
1534
+ mediaRecorder.addEventListener('dataavailable', event => {
1535
+ if (event.data.size > 0) {
1536
+ audioChunks.push(event.data);
1537
+ }
1538
+ });
1539
+
1540
+ mediaRecorder.addEventListener('stop', () => {
1541
+ const audioBlob = new Blob(audioChunks, { type: mediaRecorder.mimeType });
1542
+
1543
+ if (audioBlob.size < 1000) {
1544
+ alert('Recording too short. Please speak for at least 2-3 seconds.');
1545
+ resetVoiceButton();
1546
+ return;
1547
+ }
1548
+
1549
+ isVoiceQuery = true;
1550
+ transcribeSpeech(audioBlob);
1551
+ stream.getTracks().forEach(track => track.stop());
1552
+ });
1553
+
1554
+ mediaRecorder.start(100);
1555
+ isRecording = true;
1556
+
1557
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
1558
+ voiceRecordBtn.innerHTML = '<i class="fas fa-stop"></i>';
1559
+ voiceRecordBtn.classList.remove('btn-warning');
1560
+ voiceRecordBtn.classList.add('btn-danger');
1561
+
1562
+ setTimeout(() => {
1563
+ if (isRecording) {
1564
+ stopRecording();
1565
+ }
1566
+ }, 10000);
1567
+ })
1568
+ .catch(error => {
1569
+ console.error('Microphone error:', error);
1570
+ alert('Could not access microphone. Please check permissions.');
1571
+ });
1572
+ }
1573
+
1574
+ function stopRecording() {
1575
+ if (mediaRecorder && isRecording) {
1576
+ mediaRecorder.stop();
1577
+ isRecording = false;
1578
+
1579
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
1580
+ voiceRecordBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
1581
+ voiceRecordBtn.disabled = true;
1582
+ }
1583
+ }
1584
+
1585
+ function transcribeSpeech(audioBlob) {
1586
+ const formData = new FormData();
1587
+ formData.append('audio', audioBlob, 'recording.webm');
1588
+
1589
+ fetch('/transcribe', {
1590
+ method: 'POST',
1591
+ body: formData
1592
+ })
1593
+ .then(response => response.json())
1594
+ .then(data => {
1595
+ if (data.transcript && data.transcript.trim()) {
1596
+ const messageInput = document.getElementById('message-input');
1597
+ messageInput.value = data.transcript;
1598
+ messageInput.focus();
1599
+
1600
+ isVoiceQuery = true;
1601
+
1602
+ setTimeout(() => {
1603
+ const chatForm = document.getElementById('chat-form');
1604
+ chatForm.dispatchEvent(new Event('submit'));
1605
+ }, 500);
1606
+
1607
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
1608
+ voiceRecordBtn.innerHTML = '<i class="fas fa-check"></i>';
1609
+ voiceRecordBtn.classList.remove('btn-danger');
1610
+ voiceRecordBtn.classList.add('btn-success');
1611
+ setTimeout(resetVoiceButton, 1500);
1612
+ } else {
1613
+ alert(data.error || 'No speech detected. Please speak clearly and try again.');
1614
+ resetVoiceButton();
1615
+ }
1616
+ })
1617
+ .catch(error => {
1618
+ console.error('Transcription error:', error);
1619
+ alert('Transcription failed. Please try again.');
1620
+ resetVoiceButton();
1621
+ });
1622
+ }
1623
+
1624
+ function resetVoiceButton() {
1625
+ const voiceRecordBtn = document.getElementById('voice-record-btn');
1626
+ if (voiceRecordBtn) {
1627
+ voiceRecordBtn.disabled = false;
1628
+ voiceRecordBtn.innerHTML = '<i class="fas fa-microphone"></i>';
1629
+ voiceRecordBtn.classList.remove('btn-danger', 'btn-success');
1630
+ voiceRecordBtn.classList.add('btn-warning');
1631
+ }
1632
+ }
1633
+
1634
+ // ===== CONVERSATION HISTORY =====
1635
+ async function loadConversationHistory() {
1636
+ try {
1637
+ const response = await fetch('/load_conversation_history');
1638
+ if (response.ok) {
1639
+ const data = await response.json();
1640
+ const messages = data.messages || [];
1641
+
1642
+ if (messages.length > 0) {
1643
+ const chatBody = document.getElementById('chat-body');
1644
+
1645
+ // Clear default welcome messages
1646
+ const defaultMessages = chatBody.querySelectorAll('.message.assistant-message');
1647
+ defaultMessages.forEach(msg => {
1648
+ const content = msg.querySelector('.message-content p');
1649
+ if (content && content.textContent.includes('Welcome')) {
1650
+ msg.remove();
1651
+ }
1652
+ });
1653
+
1654
+ // Add history messages
1655
+ messages.forEach(msg => {
1656
+ if (msg.role === 'user') {
1657
+ addUserMessage(msg.content);
1658
+ } else if (msg.role === 'assistant') {
1659
+ addAssistantMessage(msg.content, 'Assistant');
1660
+ }
1661
+ });
1662
+
1663
+ scrollToBottom();
1664
+ }
1665
+ }
1666
+ } catch (error) {
1667
+ console.log('No conversation history available or user is guest');
1668
+ }
1669
+ }
1670
+
1671
+ async function checkBackendConnection() {
1672
+ try {
1673
+ console.log('🔗 Checking FastAPI backend connection...');
1674
+
1675
+ const response = await fetch('/test_backend_connection', {
1676
+ method: 'GET',
1677
+ timeout: 5000
1678
+ });
1679
+
1680
+ if (response.ok) {
1681
+ console.log('✅ FastAPI backend is connected and ready');
1682
+ return true;
1683
+ } else {
1684
+ console.log('⚠️ FastAPI backend responded with error:', response.status);
1685
+ return false;
1686
+ }
1687
+ } catch (error) {
1688
+ console.log('❌ FastAPI backend is not available:', error.message);
1689
+ return false;
1690
+ }
1691
+ }
1692
+
1693
+
1694
+ </script>
1695
+ </body>
1696
+ </html>
1697
+
1698
+
1699
+
1700
+
templates/aboutt.html ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <meta charset="UTF-8">
7
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
9
+ <meta name="description" content="">
10
+ <meta name="keywords" content="blogs, blog, universe ,world, personal blog, people, writer">
11
+ <meta name="robots" content="INDEX, FOLLOW">
12
+ <link rel="stylesheet" href="../static/styleabout.css">
13
+ <link rel="stylesheet" href="../static/mediaabout.css">
14
+
15
+
16
+
17
+ <title>ABOUT</title>
18
+
19
+ </head>
20
+
21
+ <body class="{% if session.user_id or session.is_guest %}authenticated{% endif %}"
22
+ data-signup-error="{{ signup_error|default('') }}"
23
+ data-login-error="{{ login_error|default('') }}"
24
+ data-show-signup="{{ show_signup_modal|default(false)|tojson }}"
25
+ data-show-login="{{ show_login_modal|default(false)|tojson }}">
26
+
27
+ <nav class="navbar">
28
+ <ul class="nav-Links">
29
+ <a href="{{ url_for('home') }}">
30
+ <div class="logo">
31
+ <img src="{{ url_for('static', filename='mental-health_12560579.png') }}" alt="logo">
32
+ </div>
33
+ </a>
34
+ <div class="nav-item"><li><a href="{{ url_for('home') }}">Home</a></li></div>
35
+ <div class="nav-item"><li><a href="{{ url_for('chatbot') }}">ChatBot</a></li></div>
36
+ <div class="nav-item"><li><a href="{{ url_for('about') }}">About Us</a></li></div>
37
+
38
+ </ul>
39
+ </nav>
40
+
41
+
42
+
43
+ <section class=" firstsection">
44
+
45
+ <div class="box">
46
+ <div class="first">
47
+ <h1>Mental Health Chatbot</h1>
48
+ <p> Mental health includes our emotional, psychological, and social well-being.
49
+ It affects how we think, feel, and act. It also helps determine how we handle stress,
50
+ relate to others, and make choices. Mental health is important at every stage of life,
51
+ from childhood and adolescence through adulthood.
52
+ <br>
53
+
54
+ Throughout your life, if you experience mental health problems, your thinking,
55
+ mood, and behavior could be affected. Many factors contribute to mental health problems,
56
+ and we aim to find those factors and give suggestions accordingly.
57
+ </p>
58
+
59
+
60
+ </div>
61
+
62
+ </div>
63
+
64
+
65
+
66
+
67
+ </section>
68
+
69
+
70
+
71
+ <script src="java/resp.js"></script>
72
+
73
+
74
+ </body>
75
+
76
+ </html>
templates/assessment.html ADDED
@@ -0,0 +1,1306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="description" content="">
8
+ <meta name="keywords" content="mental health, chatbot, wellness, self-assessment, coping strategies, shyness, loneliness, self esteem, life satisfaction">
9
+ <meta name="robots" content="INDEX, FOLLOW">
10
+ <link rel="stylesheet" href="{{ url_for('static', filename='styleassessment.css') }}">
11
+ <link rel="stylesheet" href="{{ url_for('static', filename='mediahome.css') }}">
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap" rel="stylesheet">
15
+ <title>Mental Health Chatbot</title>
16
+ <style>
17
+ /* Authentication modal styles */
18
+ .auth-overlay {
19
+ display: none;
20
+ position: fixed;
21
+ top: 0;
22
+ left: 0;
23
+ width: 100%;
24
+ height: 100%;
25
+ background: rgba(0, 0, 0, 0.7);
26
+ z-index: 1000;
27
+ justify-content: center;
28
+ align-items: center;
29
+ }
30
+
31
+ .auth-modal {
32
+ background: white;
33
+ padding: 40px;
34
+ border-radius: 15px;
35
+ max-width: 400px;
36
+ width: 90%;
37
+ position: relative;
38
+ max-height: 90vh;
39
+ overflow-y: auto;
40
+ }
41
+
42
+ .close-modal {
43
+ position: absolute;
44
+ top: 15px;
45
+ right: 15px;
46
+ font-size: 30px;
47
+ cursor: pointer;
48
+ color: #999;
49
+ }
50
+
51
+ .close-modal:hover {
52
+ color: #333;
53
+ }
54
+
55
+ .auth-tabs {
56
+ display: flex;
57
+ margin-bottom: 30px;
58
+ border-bottom: 2px solid #eee;
59
+ }
60
+
61
+ .auth-tab {
62
+ flex: 1;
63
+ padding: 10px;
64
+ text-align: center;
65
+ cursor: pointer;
66
+ border-bottom: 3px solid transparent;
67
+ transition: all 0.3s;
68
+ }
69
+
70
+ .auth-tab.active {
71
+ color: #667eea;
72
+ border-bottom-color: #667eea;
73
+ }
74
+
75
+ .auth-form {
76
+ display: none;
77
+ }
78
+
79
+ .auth-form.active {
80
+ display: block;
81
+ }
82
+
83
+ .form-group {
84
+ margin-bottom: 20px;
85
+ }
86
+
87
+ .form-group label {
88
+ display: block;
89
+ margin-bottom: 5px;
90
+ color: #333;
91
+ font-weight: 500;
92
+ }
93
+
94
+ .form-control {
95
+ width: 100%;
96
+ padding: 12px;
97
+ border: 1px solid #ddd;
98
+ border-radius: 8px;
99
+ font-size: 16px;
100
+ box-sizing: border-box;
101
+ }
102
+
103
+ .form-control:focus {
104
+ outline: none;
105
+ border-color: #667eea;
106
+ }
107
+
108
+ .btn-auth {
109
+ width: 100%;
110
+ padding: 12px;
111
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
112
+ color: white;
113
+ border: none;
114
+ border-radius: 8px;
115
+ font-size: 16px;
116
+ font-weight: 600;
117
+ cursor: pointer;
118
+ transition: transform 0.2s;
119
+ }
120
+
121
+ .btn-auth:hover {
122
+ transform: translateY(-2px);
123
+ }
124
+
125
+ .guest-access {
126
+ text-align: center;
127
+ margin-top: 20px;
128
+ padding-top: 20px;
129
+ border-top: 1px solid #eee;
130
+ }
131
+
132
+ .guest-link {
133
+ color: #667eea;
134
+ text-decoration: none;
135
+ }
136
+
137
+ .guest-link:hover {
138
+ text-decoration: underline;
139
+ }
140
+
141
+ /* Hide survey form initially */
142
+ #survey-section {
143
+ display: none;
144
+ }
145
+
146
+ /* Show survey when authenticated */
147
+ body.authenticated #survey-section {
148
+ display: block;
149
+ }
150
+
151
+ body.authenticated .auth-prompt {
152
+ display: none;
153
+ }
154
+
155
+ .error-message {
156
+ background: #fee;
157
+ color: #c33;
158
+ padding: 10px;
159
+ border-radius: 5px;
160
+ margin-bottom: 20px;
161
+ text-align: center;
162
+ }
163
+
164
+ .btn-primary,.btn-success{
165
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
166
+ color: white;
167
+ padding: 10px 20px;
168
+ border: none;
169
+ border-radius: 5px;
170
+ text-decoration: none;
171
+ display: inline-block;
172
+ cursor: pointer;
173
+ transition: all 0.3s;
174
+ font-size: 16px;
175
+ font-weight: 600;
176
+ }
177
+
178
+ .btn-primary.btn-success:hover {
179
+ transform: translateY(-2px);
180
+ box-shadow: 0 5px 15px rgba(0,0,0,0.2);
181
+ }
182
+
183
+ .btn-secondary {
184
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
185
+ color: white;
186
+ padding: 10px 20px;
187
+ border: none;
188
+ border-radius: 5px;
189
+ text-decoration: none;
190
+ display: inline-block;
191
+ cursor: pointer;
192
+ transition: all 0.3s;
193
+ font-size: 16px;
194
+ font-weight: 600;
195
+ }
196
+
197
+
198
+ .btn-secondary:hover {
199
+ transform: translateY(-2px);
200
+ box-shadow: 0 5px 15px rgba(0,0,0,0.2);
201
+ }
202
+
203
+ .step-navigation {
204
+ display: flex;
205
+ justify-content: space-between;
206
+ /* margin-top: 20px; */
207
+ }
208
+
209
+ /* Authentication specific styles */
210
+ .auth-prompt {
211
+ min-height: 60vh;
212
+ display: flex;
213
+ align-items: center;
214
+ justify-content: center;
215
+ }
216
+
217
+ /* Password strength indicator */
218
+ .password-strength {
219
+ font-size: 12px;
220
+ margin-top: 5px;
221
+ padding: 3px 8px;
222
+ border-radius: 3px;
223
+ display: inline-block;
224
+ }
225
+
226
+ .password-strength.weak {
227
+ color: #dc3545;
228
+ background-color: #f8d7da;
229
+ }
230
+
231
+ .password-strength.medium {
232
+ color: #856404;
233
+ background-color: #fff3cd;
234
+ }
235
+
236
+ .password-strength.strong {
237
+ color: #155724;
238
+ background-color: #d4edda;
239
+ }
240
+
241
+ /* Add confirm password field styling */
242
+ .password-match-error {
243
+ color: #dc3545;
244
+ font-size: 12px;
245
+ margin-top: 5px;
246
+ }
247
+
248
+
249
+ .error-message {
250
+ background: #f8d7da;
251
+ color: #721c24;
252
+ padding: 12px 20px;
253
+ border-radius: 5px;
254
+ margin-bottom: 20px;
255
+ text-align: center;
256
+ border: 1px solid #f5c6cb;
257
+ font-weight: 500;
258
+ animation: shake 0.5s ease-in-out;
259
+ }
260
+
261
+ @keyframes shake {
262
+ 0%, 100% { transform: translateX(0); }
263
+ 25% { transform: translateX(-10px); }
264
+ 75% { transform: translateX(10px); }
265
+ }
266
+
267
+ .success-message {
268
+ background: #d4edda;
269
+ color: #155724;
270
+ padding: 12px 20px;
271
+ border-radius: 5px;
272
+ margin-bottom: 20px;
273
+ text-align: center;
274
+ border: 1px solid #c3e6cb;
275
+ font-weight: 500;
276
+ }
277
+
278
+ /* Progress bar styles */
279
+ .progress-indicator {
280
+ /* margin: 20px 0; */
281
+ text-align: center;
282
+ }
283
+
284
+ .progress-bar {
285
+ background: #e9ecef;
286
+ border-radius: 10px;
287
+ height: 8px;
288
+ margin: 10px 0;
289
+ overflow: hidden;
290
+ }
291
+
292
+ .progress-fill {
293
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
294
+ height: 100%;
295
+ width: 16.66%; /* Default to step 1 */
296
+ transition: width 0.3s ease;
297
+ }
298
+
299
+ .step-counter {
300
+ color: #666;
301
+ font-size: 14px;
302
+ font-weight: 500;
303
+ }
304
+ </style>
305
+ </head>
306
+
307
+ <body class="authenticated">
308
+
309
+ <nav class="navbar">
310
+ <ul class="nav-Links">
311
+ <a href="{{ url_for('home') }}">
312
+ <div class="logo">
313
+ <img src="{{ url_for('static', filename='mental-health_12560579.png') }}" alt="logo">
314
+ </div>
315
+ </a>
316
+ <div class="nav-item"><li><a href="{{ url_for('home') }}">Home</a></li></div>
317
+ <div class="nav-item"><li><a href="{{ url_for('chatbot') }}">Chatbot</a></li></div>
318
+ <div class="nav-item"><li><a href="{{ url_for('about') }}">About Us</a></li></div>
319
+ <div class="nav-item"><li><a href="#">Welcome, {{ session.username }}</a></li></div>
320
+ <div class="nav-item"><li><a href="{{ url_for('logout') }}">Logout</a></li></div>
321
+ </ul>
322
+ </nav>
323
+
324
+
325
+
326
+ <!--
327
+ {% if session.user_id and session.user_data.name %}
328
+ <div class="bascic-info">
329
+ <label>Name:
330
+ <input type="text" name="Name" class="form-control" value="{{ session.user_data.name }}" readonly required>
331
+ </label>
332
+ </div>
333
+ {% else %}
334
+ <div class="bascic-info">
335
+ <label>Name:
336
+ <input type="text" name="Name" class="form-control" required placeholder="Enter your full name">
337
+ </label>
338
+ </div>
339
+ {% endif %} -->
340
+
341
+
342
+
343
+ <section class="firstsection" id="survey-section" style="display: block;">
344
+ <div class="box">
345
+ <div class="container">
346
+ <header>
347
+ <h1 id="title">Mental Health Assessment - Bhutan</h1>
348
+ {% if session.user_id %}
349
+ <p>Welcome, {{ session.user_data.name }}! Please complete this comprehensive mental health assessment.</p>
350
+ {% endif %}
351
+ <div class="assessment-info">
352
+ <h3>Professional Mental Health Screening</h3>
353
+ <p>This assessment includes clinically validated questionnaires: PHQ-9 (Depression), GAD-7 (Anxiety), and basic wellness screening.</p>
354
+ <p><strong>Important:</strong> This is a screening tool, not a diagnostic instrument. Results should be discussed with a healthcare professional.</p>
355
+ </div>
356
+ </header>
357
+ <div class="form-container">
358
+ <div class="left-section">
359
+ <div class="image">
360
+ <img src="/static/treeman.png" alt="Mental Health Assessment">
361
+ </div>
362
+
363
+ </div>
364
+ <div class="right-section">
365
+ <form id="survey-form" method="post" action="/assessment/step">
366
+ <input type="hidden" name="current_step" id="current-step" value="1">
367
+ <input type="hidden" name="total_steps" id="total-steps" value="6">
368
+ <div class="form-box">
369
+ <h2 id="sub-title">Mental Health Assessment</h2>
370
+
371
+ <!-- Step 1: Basic Information -->
372
+ <div class="assessment-step" id="step-1" data-step="1">
373
+ <div class="section-title">Step 1: Basic Information</div>
374
+ <div class="row">
375
+ {% if session.user_id and session.user_data.name %}
376
+ <div class="bascic-info">
377
+ <label>Name:
378
+ <input type="text" name="Name" class="form-control" value="{{ session.user_data.name }}" readonly required>
379
+ </label>
380
+ </div>
381
+ {% else %}
382
+ <div class="bascic-info">
383
+ <label>Name:
384
+ <input type="text" name="Name" class="form-control" required placeholder="Enter your full name">
385
+ </label>
386
+ </div>
387
+ {% endif %}
388
+ <div class="bascic-info">
389
+ <label>Age:
390
+ <input class="form-control" type="number" name="Age" min="10" max="100" required>
391
+ </label>
392
+ </div>
393
+ <div class="bascic-info">
394
+ <label>Gender:
395
+ <select class="form-control" name="Sex" required>
396
+ <option disabled selected value>Select One</option>
397
+ <option value="Male">Male</option>
398
+ <option value="Female">Female</option>
399
+ <option value="Other">Other</option>
400
+ <option value="Prefer not to say">Prefer not to say</option>
401
+ </select>
402
+ </label>
403
+ </div>
404
+ <div class="bascic-info">
405
+ <label>Location:
406
+ <select class="form-control" name="Location" required>
407
+ <option disabled selected value>Select One</option>
408
+ <option value="Thimphu">Thimphu</option>
409
+ <option value="Paro">Paro</option>
410
+ <option value="Punakha">Punakha</option>
411
+ <option value="Wangdue">Wangdue</option>
412
+ <option value="Other Urban">Other Urban</option>
413
+ <option value="Rural">Rural</option>
414
+ </select>
415
+ </label>
416
+ </div>
417
+ <div class="bascic-info">
418
+ <label>Days spent indoors in the last week:
419
+ <select class="form-control" name="days_indoors" required>
420
+ <option disabled selected value>Select One</option>
421
+ <option value="0">0 days</option>
422
+ <option value="1">1 day</option>
423
+ <option value="2">2 days</option>
424
+ <option value="3">3 days</option>
425
+ <option value="4">4 days</option>
426
+ <option value="5">5 days</option>
427
+ <option value="6">6 days</option>
428
+ <option value="7">7 days (all week)</option>
429
+ </select>
430
+ </label>
431
+ </div>
432
+
433
+ <div class="bascic-info">
434
+ <label>How would you describe your current emotion/mood?
435
+ <select class="form-control" name="Emotion" required>
436
+ <option disabled selected value>Select One</option>
437
+ <option value="Very Happy">Very Happy</option>
438
+ <option value="Happy">Happy</option>
439
+ <option value="Neutral">Neutral</option>
440
+ <option value="Sad">Sad</option>
441
+ <option value="Very Sad">Very Sad</option>
442
+ <option value="Anxious">Anxious</option>
443
+ <option value="Angry">Angry</option>
444
+ <option value="Stressed">Stressed</option>
445
+ <option value="Confused">Confused</option>
446
+ <option value="Other">Other</option>
447
+ </select>
448
+ </label>
449
+ </div>
450
+
451
+ <div class="bascic-info">
452
+ <label>Do you have a history of mental illness?
453
+ <select class="form-control" name="history_of_mental_illness" required>
454
+ <option disabled selected value>Select One</option>
455
+ <option value="Yes">Yes</option>
456
+ <option value="No">No</option>
457
+ <option value="Unsure">Unsure</option>
458
+ <option value="Prefer not to say">Prefer not to say</option>
459
+ </select>
460
+ </label>
461
+ </div>
462
+
463
+ <div class="bascic-info">
464
+ <label>Are you currently receiving any mental health treatment?
465
+ <select class="form-control" name="treatment" required>
466
+ <option disabled selected value>Select One</option>
467
+ <option value="Yes - Therapy/Counseling">Yes - Therapy/Counseling</option>
468
+ <option value="Yes - Medication">Yes - Medication</option>
469
+ <option value="Yes - Both therapy and medication">Yes - Both therapy and medication</option>
470
+ <option value="No">No</option>
471
+ <option value="Previously, but not currently">Previously, but not currently</option>
472
+ <option value="Prefer not to say">Prefer not to say</option>
473
+ </select>
474
+ </label>
475
+ </div>
476
+ </div>
477
+ <div class="step-navigation">
478
+ <button type="submit" name="action" value="next" class="btn btn-primary">Next Step</button>
479
+ </div>
480
+ </div>
481
+
482
+ <!-- Step 2: PHQ-9 Depression Screening -->
483
+ <div class="assessment-step" id="step-2" data-step="2" style="display: none;">
484
+ <div class="section-title">Step 2: PHQ-9 Depression Screening</div>
485
+ <div class="assessment-instructions">
486
+ <p><strong>Instructions:</strong> Over the last 2 weeks, how often have you been bothered by any of the following problems?</p>
487
+ <p><em>Scale: 0 = Not at all, 1 = Several days, 2 = More than half the days, 3 = Nearly every day</em></p>
488
+ </div>
489
+ <div class="row">
490
+ <div class="question-item">
491
+ <label>
492
+ <span class="question">1. Little interest or pleasure in doing things</span>
493
+ <select name="PHQ9_1" class="form-control" required>
494
+ <option disabled selected value>Select One</option>
495
+ <option value="0">Not at all</option>
496
+ <option value="1">Several days</option>
497
+ <option value="2">More than half the days</option>
498
+ <option value="3">Nearly every day</option>
499
+ </select>
500
+ </label>
501
+ </div>
502
+ <div class="question-item">
503
+ <label>
504
+ <span class="question">2. Feeling down, depressed, or hopeless</span>
505
+ <select name="PHQ9_2" class="form-control" required>
506
+ <option disabled selected value>Select One</option>
507
+ <option value="0">Not at all</option>
508
+ <option value="1">Several days</option>
509
+ <option value="2">More than half the days</option>
510
+ <option value="3">Nearly every day</option>
511
+ </select>
512
+ </label>
513
+ </div>
514
+ <div class="question-item">
515
+ <label>
516
+ <span class="question">3. Trouble falling asleep, staying asleep, or sleeping too much</span>
517
+ <select name="PHQ9_3" class="form-control" required>
518
+ <option disabled selected value>Select One</option>
519
+ <option value="0">Not at all</option>
520
+ <option value="1">Several days</option>
521
+ <option value="2">More than half the days</option>
522
+ <option value="3">Nearly every day</option>
523
+ </select>
524
+ </label>
525
+ </div>
526
+ <div class="question-item">
527
+ <label>
528
+ <span class="question">4. Feeling tired or having little energy</span>
529
+ <select name="PHQ9_4" class="form-control" required>
530
+ <option disabled selected value>Select One</option>
531
+ <option value="0">Not at all</option>
532
+ <option value="1">Several days</option>
533
+ <option value="2">More than half the days</option>
534
+ <option value="3">Nearly every day</option>
535
+ </select>
536
+ </label>
537
+ </div>
538
+ <div class="question-item">
539
+ <label>
540
+ <span class="question">5. Poor appetite or overeating</span>
541
+ <select name="PHQ9_5" class="form-control" required>
542
+ <option disabled selected value>Select One</option>
543
+ <option value="0">Not at all</option>
544
+ <option value="1">Several days</option>
545
+ <option value="2">More than half the days</option>
546
+ <option value="3">Nearly every day</option>
547
+ </select>
548
+ </label>
549
+ </div>
550
+ <div class="question-item">
551
+ <label>
552
+ <span class="question">6. Feeling bad about yourself or that you are a failure or have let yourself or your family down</span>
553
+ <select name="PHQ9_6" class="form-control" required>
554
+ <option disabled selected value>Select One</option>
555
+ <option value="0">Not at all</option>
556
+ <option value="1">Several days</option>
557
+ <option value="2">More than half the days</option>
558
+ <option value="3">Nearly every day</option>
559
+ </select>
560
+ </label>
561
+ </div>
562
+ <div class="question-item">
563
+ <label>
564
+ <span class="question">7. Trouble concentrating on things, such as reading the newspaper or watching television</span>
565
+ <select name="PHQ9_7" class="form-control" required>
566
+ <option disabled selected value>Select One</option>
567
+ <option value="0">Not at all</option>
568
+ <option value="1">Several days</option>
569
+ <option value="2">More than half the days</option>
570
+ <option value="3">Nearly every day</option>
571
+ </select>
572
+ </label>
573
+ </div>
574
+ <div class="question-item">
575
+ <label>
576
+ <span class="question">8. Moving or speaking so slowly that other people could have noticed, or being so fidgety or restless that you have been moving around a lot more than usual</span>
577
+ <select name="PHQ9_8" class="form-control" required>
578
+ <option disabled selected value>Select One</option>
579
+ <option value="0">Not at all</option>
580
+ <option value="1">Several days</option>
581
+ <option value="2">More than half the days</option>
582
+ <option value="3">Nearly every day</option>
583
+ </select>
584
+ </label>
585
+ </div>
586
+ <div class="question-item">
587
+ <label>
588
+ <span class="question">9. Thoughts that you would be better off dead or thoughts of hurting yourself in some way</span>
589
+ <select name="PHQ9_9" class="form-control" required>
590
+ <option disabled selected value>Select One</option>
591
+ <option value="0">Not at all</option>
592
+ <option value="1">Several days</option>
593
+ <option value="2">More than half the days</option>
594
+ <option value="3">Nearly every day</option>
595
+ </select>
596
+ </label>
597
+ </div>
598
+ </div>
599
+ <div class="step-navigation">
600
+ <button type="submit" name="action" value="previous" class="btn btn-secondary">Previous</button>
601
+ <button type="submit" name="action" value="next" class="btn btn-primary">Next Step</button>
602
+ </div>
603
+ </div>
604
+
605
+ <!-- Step 3: GAD-7 Anxiety Screening -->
606
+ <div class="assessment-step" id="step-3" data-step="3" style="display: none;">
607
+ <div class="section-title">Step 3: GAD-7 Anxiety Screening</div>
608
+ <div class="assessment-instructions">
609
+ <p><strong>Instructions:</strong> Over the last 2 weeks, how often have you been bothered by the following problems?</p>
610
+ <!-- <p><em>Scale: 0 = Not at all, 1 = Several days, 2 = More than half the days, 3 = Nearly every day</em></p> -->
611
+ </div>
612
+ <div class="row">
613
+ <div class="question-item">
614
+ <label>
615
+ <span class="question">1. Feeling nervous, anxious, or on edge</span>
616
+ <select name="GAD7_1" class="form-control" required>
617
+ <option disabled selected value>Select One</option>
618
+ <option value="0">Not at all</option>
619
+ <option value="1">Several days</option>
620
+ <option value="2">More than half the days</option>
621
+ <option value="3">Nearly every day</option>
622
+ </select>
623
+ </label>
624
+ </div>
625
+ <div class="question-item">
626
+ <label>
627
+ <span class="question">2. Not being able to stop or control worrying</span>
628
+ <select name="GAD7_2" class="form-control" required>
629
+ <option disabled selected value>Select One</option>
630
+ <option value="0">Not at all</option>
631
+ <option value="1">Several days</option>
632
+ <option value="2">More than half the days</option>
633
+ <option value="3">Nearly every day</option>
634
+ </select>
635
+ </label>
636
+ </div>
637
+ <div class="question-item">
638
+ <label>
639
+ <span class="question">3. Worrying too much about different things</span>
640
+ <select name="GAD7_3" class="form-control" required>
641
+ <option disabled selected value>Select One</option>
642
+ <option value="0">Not at all</option>
643
+ <option value="1">Several days</option>
644
+ <option value="2">More than half the days</option>
645
+ <option value="3">Nearly every day</option>
646
+ </select>
647
+ </label>
648
+ </div>
649
+ <div class="question-item">
650
+ <label>
651
+ <span class="question">4. Trouble relaxing</span>
652
+ <select name="GAD7_4" class="form-control" required>
653
+ <option disabled selected value>Select One</option>
654
+ <option value="0">Not at all</option>
655
+ <option value="1">Several days</option>
656
+ <option value="2">More than half the days</option>
657
+ <option value="3">Nearly every day</option>
658
+ </select>
659
+ </label>
660
+ </div>
661
+ <div class="question-item">
662
+ <label>
663
+ <span class="question">5. Being so restless that it's hard to sit still</span>
664
+ <select name="GAD7_5" class="form-control" required>
665
+ <option disabled selected value>Select One</option>
666
+ <option value="0">Not at all</option>
667
+ <option value="1">Several days</option>
668
+ <option value="2">More than half the days</option>
669
+ <option value="3">Nearly every day</option>
670
+ </select>
671
+ </label>
672
+ </div>
673
+ <div class="question-item">
674
+ <label>
675
+ <span class="question">6. Becoming easily annoyed or irritable</span>
676
+ <select name="GAD7_6" class="form-control" required>
677
+ <option disabled selected value>Select One</option>
678
+ <option value="0">Not at all</option>
679
+ <option value="1">Several days</option>
680
+ <option value="2">More than half the days</option>
681
+ <option value="3">Nearly every day</option>
682
+ </select>
683
+ </label>
684
+ </div>
685
+ <div class="question-item">
686
+ <label>
687
+ <span class="question">7. Feeling afraid as if something awful might happen</span>
688
+ <select name="GAD7_7" class="form-control" required>
689
+ <option disabled selected value>Select One</option>
690
+ <option value="0">Not at all</option>
691
+ <option value="1">Several days</option>
692
+ <option value="2">More than half the days</option>
693
+ <option value="3">Nearly every day</option>
694
+ </select>
695
+ </label>
696
+ </div>
697
+ </div>
698
+ <div class="step-navigation">
699
+ <button type="submit" name="action" value="previous" class="btn btn-secondary">Previous</button>
700
+ <button type="submit" name="action" value="next" class="btn btn-primary">Next Step</button>
701
+ </div>
702
+ </div>
703
+
704
+
705
+
706
+ <!-- Step 4: DAST-10 & AUDIT Screening -->
707
+ <div class="assessment-step" id="step-4" data-step="4" style="display: none;">
708
+ <div class="section-title">Step 4: DAST-10 Substance Use Screening</div>
709
+ <div class="assessment-instructions">
710
+ <p><strong>Instructions:</strong> The following questions concern information about your involvement with drugs (excluding alcohol and tobacco) during the past 12 months.</p>
711
+ <p><em>Please answer honestly with Yes or No.</em></p>
712
+ </div>
713
+ <div class="row">
714
+ <div class="question-item">
715
+ <label>
716
+ <span class="question">1. Have you used drugs other than those required for medical reasons?</span>
717
+ <select name="DAST_1" class="form-control" required>
718
+ <option disabled selected value>Select One</option>
719
+ <option value="No">No</option>
720
+ <option value="Yes">Yes</option>
721
+ </select>
722
+ </label>
723
+ </div>
724
+ <div class="question-item">
725
+ <label>
726
+ <span class="question">2. Have you abused more than one drug at a time?</span>
727
+ <select name="DAST_2" class="form-control" required>
728
+ <option disabled selected value>Select One</option>
729
+ <option value="No">No</option>
730
+ <option value="Yes">Yes</option>
731
+ </select>
732
+ </label>
733
+ </div>
734
+ <div class="question-item">
735
+ <label>
736
+ <span class="question">3. Are you able to stop using drugs when you want to?</span>
737
+ <select name="DAST_3" class="form-control" required>
738
+ <option disabled selected value>Select One</option>
739
+ <option value="Yes">Yes</option>
740
+ <option value="No">No</option>
741
+ </select>
742
+ </label>
743
+ </div>
744
+ <div class="question-item">
745
+ <label>
746
+ <span class="question">4. Have you had blackouts or flashbacks from drug use?</span>
747
+ <select name="DAST_4" class="form-control" required>
748
+ <option disabled selected value>Select One</option>
749
+ <option value="No">No</option>
750
+ <option value="Yes">Yes</option>
751
+ </select>
752
+ </label>
753
+ </div>
754
+ <div class="question-item">
755
+ <label>
756
+ <span class="question">5. Do you ever feel bad or guilty about your drug use?</span>
757
+ <select name="DAST_5" class="form-control" required>
758
+ <option disabled selected value>Select One</option>
759
+ <option value="No">No</option>
760
+ <option value="Yes">Yes</option>
761
+ </select>
762
+ </label>
763
+ </div>
764
+ <div class="question-item">
765
+ <label>
766
+ <span class="question">6. Does your spouse (or parents) ever complain about your involvement with drugs?</span>
767
+ <select name="DAST_6" class="form-control" required>
768
+ <option disabled selected value>Select One</option>
769
+ <option value="No">No</option>
770
+ <option value="Yes">Yes</option>
771
+ </select>
772
+ </label>
773
+ </div>
774
+ <div class="question-item">
775
+ <label>
776
+ <span class="question">7. Have you neglected your family because of your use of drugs?</span>
777
+ <select name="DAST_7" class="form-control" required>
778
+ <option disabled selected value>Select One</option>
779
+ <option value="No">No</option>
780
+ <option value="Yes">Yes</option>
781
+ </select>
782
+ </label>
783
+ </div>
784
+ <div class="question-item">
785
+ <label>
786
+ <span class="question">8. Have you engaged in illegal activities in order to obtain drugs?</span>
787
+ <select name="DAST_8" class="form-control" required>
788
+ <option disabled selected value>Select One</option>
789
+ <option value="No">No</option>
790
+ <option value="Yes">Yes</option>
791
+ </select>
792
+ </label>
793
+ </div>
794
+ <div class="question-item">
795
+ <label>
796
+ <span class="question">9. Have you ever experienced withdrawal symptoms (felt sick) when you stopped taking drugs?</span>
797
+ <select name="DAST_9" class="form-control" required>
798
+ <option disabled selected value>Select One</option>
799
+ <option value="No">No</option>
800
+ <option value="Yes">Yes</option>
801
+ </select>
802
+ </label>
803
+ </div>
804
+ <div class="question-item">
805
+ <label>
806
+ <span class="question">10. Have you had medical problems as a result of your drug use (e.g., memory loss, hepatitis, convulsions, bleeding)?</span>
807
+ <select name="DAST_10" class="form-control" required>
808
+ <option disabled selected value>Select One</option>
809
+ <option value="No">No</option>
810
+ <option value="Yes">Yes</option>
811
+ </select>
812
+ </label>
813
+ </div>
814
+ </div>
815
+ <div class="step-navigation">
816
+ <button type="button" name="action" value="previous" class="btn btn-secondary">Previous</button>
817
+ <button type="button" name="action" value="next" class="btn btn-primary">Next Step</button>
818
+ </div>
819
+ </div>
820
+
821
+
822
+ <!-- Step 5: AUDIT Alcohol Use Screening -->
823
+ <div class="assessment-step" id="step-5" data-step="5" style="display: none;">
824
+ <div class="section-title">Step 5: AUDIT Alcohol Use Screening</div>
825
+ <div class="assessment-instructions">
826
+ <p><strong>Instructions:</strong> Please answer the following questions based on your alcohol use over the past 12 months.</p>
827
+ <p><em>Select the most appropriate response for each question.</em></p>
828
+ </div>
829
+ <div class="row">
830
+ <div class="question-item">
831
+ <label>
832
+ <span class="question">1. How often do you have a drink containing alcohol?</span>
833
+ <select name="AUDIT_1" class="form-control" required>
834
+ <option disabled selected value>Select One</option>
835
+ <option value="Never">Never</option>
836
+ <option value="Monthly or less">Monthly or less</option>
837
+ <option value="2 to 4 times a month">2 to 4 times a month</option>
838
+ <option value="2 to 3 times a week">2 to 3 times a week</option>
839
+ <option value="4 or more times a week">4 or more times a week</option>
840
+ </select>
841
+ </label>
842
+ </div>
843
+ <div class="question-item">
844
+ <label>
845
+ <span class="question">2. How many drinks containing alcohol do you have on a typical day when you are drinking?</span>
846
+ <select name="AUDIT_2" class="form-control" required>
847
+ <option disabled selected value>Select One</option>
848
+ <option value="1 or 2">1 or 2</option>
849
+ <option value="3 or 4">3 or 4</option>
850
+ <option value="5 or 6">5 or 6</option>
851
+ <option value="7, 8, or 9">7, 8, or 9</option>
852
+ <option value="10 or more">10 or more</option>
853
+ </select>
854
+ </label>
855
+ </div>
856
+ <div class="question-item">
857
+ <label>
858
+ <span class="question">3. How often do you have six or more drinks on one occasion?</span>
859
+ <select name="AUDIT_3" class="form-control" required>
860
+ <option disabled selected value>Select One</option>
861
+ <option value="Never">Never</option>
862
+ <option value="Less than monthly">Less than monthly</option>
863
+ <option value="Monthly">Monthly</option>
864
+ <option value="Weekly">Weekly</option>
865
+ <option value="Daily or almost daily">Daily or almost daily</option>
866
+ </select>
867
+ </label>
868
+ </div>
869
+ <div class="question-item">
870
+ <label>
871
+ <span class="question">4. How often during the last year have you found that you were not able to stop drinking once you had started?</span>
872
+ <select name="AUDIT_4" class="form-control" required>
873
+ <option disabled selected value>Select One</option>
874
+ <option value="Never">Never</option>
875
+ <option value="Less than monthly">Less than monthly</option>
876
+ <option value="Monthly">Monthly</option>
877
+ <option value="Weekly">Weekly</option>
878
+ <option value="Daily or almost daily">Daily or almost daily</option>
879
+ </select>
880
+ </label>
881
+ </div>
882
+ <div class="question-item">
883
+ <label>
884
+ <span class="question">5. How often during the last year have you failed to do what was normally expected from you because of drinking?</span>
885
+ <select name="AUDIT_5" class="form-control" required>
886
+ <option disabled selected value>Select One</option>
887
+ <option value="Never">Never</option>
888
+ <option value="Less than monthly">Less than monthly</option>
889
+ <option value="Monthly">Monthly</option>
890
+ <option value="Weekly">Weekly</option>
891
+ <option value="Daily or almost daily">Daily or almost daily</option>
892
+ </select>
893
+ </label>
894
+ </div>
895
+ <div class="question-item">
896
+ <label>
897
+ <span class="question">6. How often during the last year have you needed a first drink in the morning to get yourself going after a heavy drinking session?</span>
898
+ <select name="AUDIT_6" class="form-control" required>
899
+ <option disabled selected value>Select One</option>
900
+ <option value="Never">Never</option>
901
+ <option value="Less than monthly">Less than monthly</option>
902
+ <option value="Monthly">Monthly</option>
903
+ <option value="Weekly">Weekly</option>
904
+ <option value="Daily or almost daily">Daily or almost daily</option>
905
+ </select>
906
+ </label>
907
+ </div>
908
+ <div class="question-item">
909
+ <label>
910
+ <span class="question">7. How often during the last year have you had a feeling of guilt or remorse after drinking?</span>
911
+ <select name="AUDIT_7" class="form-control" required>
912
+ <option disabled selected value>Select One</option>
913
+ <option value="Never">Never</option>
914
+ <option value="Less than monthly">Less than monthly</option>
915
+ <option value="Monthly">Monthly</option>
916
+ <option value="Weekly">Weekly</option>
917
+ <option value="Daily or almost daily">Daily or almost daily</option>
918
+ </select>
919
+ </label>
920
+ </div>
921
+ <div class="question-item">
922
+ <label>
923
+ <span class="question">8. How often during the last year have you been unable to remember what happened the night before because you had been drinking?</span>
924
+ <select name="AUDIT_8" class="form-control" required>
925
+ <option disabled selected value>Select One</option>
926
+ <option value="Never">Never</option>
927
+ <option value="Less than monthly">Less than monthly</option>
928
+ <option value="Monthly">Monthly</option>
929
+ <option value="Weekly">Weekly</option>
930
+ <option value="Daily or almost daily">Daily or almost daily</option>
931
+ </select>
932
+ </label>
933
+ </div>
934
+ <div class="question-item">
935
+ <label>
936
+ <span class="question">9. Have you or someone else been injured as a result of your drinking?</span>
937
+ <select name="AUDIT_9" class="form-control" required>
938
+ <option disabled selected value>Select One</option>
939
+ <option value="No">No</option>
940
+ <option value="Yes, but not in the last year">Yes, but not in the last year</option>
941
+ <option value="Yes, during the last year">Yes, during the last year</option>
942
+ </select>
943
+ </label>
944
+ </div>
945
+ <div class="question-item">
946
+ <label>
947
+ <span class="question">10. Has a relative or friend or a doctor or another health worker been concerned about your drinking or suggested you cut down?</span>
948
+ <select name="AUDIT_10" class="form-control" required>
949
+ <option disabled selected value>Select One</option>
950
+ <option value="No">No</option>
951
+ <option value="Yes, but not in the last year">Yes, but not in the last year</option>
952
+ <option value="Yes, during the last year">Yes, during the last year</option>
953
+ </select>
954
+ </label>
955
+ </div>
956
+ </div>
957
+ <div class="step-navigation">
958
+ <button type="submit" name="action" value="previous" class="btn btn-secondary">Previous</button>
959
+ <button type="submit" name="action" value="next" class="btn btn-primary">Next Step</button>
960
+ </div>
961
+ </div>
962
+
963
+
964
+
965
+ <!-- Step 6: Bipolar Screening -->
966
+ <div class="assessment-step" id="step-6" data-step="6" style="display: none;">
967
+ <div class="section-title">Step 6: Bipolar Screening</div>
968
+ <div class="assessment-instructions">
969
+ <p><strong>Instructions:</strong> Have there ever been times when you were not your usual self and...</p>
970
+ <p><em>Please answer Yes or No for each question.</em></p>
971
+ </div>
972
+ <div class="row">
973
+ <div class="question-item">
974
+ <label>
975
+ <span class="question">1. You felt so good or hyper that other people thought you were not your normal self or were so hyper that you got into trouble?</span>
976
+ <select name="BIPOLAR_1" class="form-control" required>
977
+ <option disabled selected value>Select One</option>
978
+ <option value="No">No</option>
979
+ <option value="Yes">Yes</option>
980
+ </select>
981
+ </label>
982
+ </div>
983
+ <div class="question-item">
984
+ <label>
985
+ <span class="question">2. You were so irritable that you shouted at people or started fights or arguments?</span>
986
+ <select name="BIPOLAR_2" class="form-control" required>
987
+ <option disabled selected value>Select One</option>
988
+ <option value="No">No</option>
989
+ <option value="Yes">Yes</option>
990
+ </select>
991
+ </label>
992
+ </div>
993
+ <div class="question-item">
994
+ <label>
995
+ <span class="question">3. You felt much more self-confident than usual?</span>
996
+ <select name="BIPOLAR_3" class="form-control" required>
997
+ <option disabled selected value>Select One</option>
998
+ <option value="No">No</option>
999
+ <option value="Yes">Yes</option>
1000
+ </select>
1001
+ </label>
1002
+ </div>
1003
+ <div class="question-item">
1004
+ <label>
1005
+ <span class="question">4. You got much less sleep than usual and found you didn't really miss it?</span>
1006
+ <select name="BIPOLAR_4" class="form-control" required>
1007
+ <option disabled selected value>Select One</option>
1008
+ <option value="No">No</option>
1009
+ <option value="Yes">Yes</option>
1010
+ </select>
1011
+ </label>
1012
+ </div>
1013
+ <div class="question-item">
1014
+ <label>
1015
+ <span class="question">5. You were much more talkative or spoke faster than usual?</span>
1016
+ <select name="BIPOLAR_5" class="form-control" required>
1017
+ <option disabled selected value>Select One</option>
1018
+ <option value="No">No</option>
1019
+ <option value="Yes">Yes</option>
1020
+ </select>
1021
+ </label>
1022
+ </div>
1023
+ <div class="question-item">
1024
+ <label>
1025
+ <span class="question">6. You had racing thoughts?</span>
1026
+ <select name="BIPOLAR_6" class="form-control" required>
1027
+ <option disabled selected value>Select One</option>
1028
+ <option value="No">No</option>
1029
+ <option value="Yes">Yes</option>
1030
+ </select>
1031
+ </label>
1032
+ </div>
1033
+ <div class="question-item">
1034
+ <label>
1035
+ <span class="question">7. You were so easily distracted that you had trouble concentrating?</span>
1036
+ <select name="BIPOLAR_7" class="form-control" required>
1037
+ <option disabled selected value>Select One</option>
1038
+ <option value="No">No</option>
1039
+ <option value="Yes">Yes</option>
1040
+ </select>
1041
+ </label>
1042
+ </div>
1043
+ <div class="question-item">
1044
+ <label>
1045
+ <span class="question">8. You were more active or did more things than usual?</span>
1046
+ <select name="BIPOLAR_8" class="form-control" required>
1047
+ <option disabled selected value>Select One</option>
1048
+ <option value="No">No</option>
1049
+ <option value="Yes">Yes</option>
1050
+ </select>
1051
+ </label>
1052
+ </div>
1053
+ <div class="question-item">
1054
+ <label>
1055
+ <span class="question">9. You were much more social or outgoing than usual?</span>
1056
+ <select name="BIPOLAR_9" class="form-control" required>
1057
+ <option disabled selected value>Select One</option>
1058
+ <option value="No">No</option>
1059
+ <option value="Yes">Yes</option>
1060
+ </select>
1061
+ </label>
1062
+ </div>
1063
+ <div class="question-item">
1064
+ <label>
1065
+ <span class="question">10. You did things that were unusual for you or that other people might have thought were excessive or risky?</span>
1066
+ <select name="BIPOLAR_10" class="form-control" required>
1067
+ <option disabled selected value>Select One</option>
1068
+ <option value="No">No</option>
1069
+ <option value="Yes">Yes</option>
1070
+ </select>
1071
+ </label>
1072
+ </div>
1073
+ <div class="question-item">
1074
+ <label>
1075
+ <span class="question">11. Spending money got you or your family into trouble?</span>
1076
+ <select name="BIPOLAR_11" class="form-control" required>
1077
+ <option disabled selected value>Select One</option>
1078
+ <option value="No">No</option>
1079
+ <option value="Yes">Yes</option>
1080
+ </select>
1081
+ </label>
1082
+ </div>
1083
+ </div>
1084
+ <div class="step-navigation">
1085
+ <button type="submit" name="action" value="previous" class="btn btn-secondary">Previous</button>
1086
+ <button type="submit" name="action" value="submit" class="btn btn-success">Complete Assessment</button>
1087
+ </div>
1088
+ </div>
1089
+
1090
+ <!-- Progress indicator -->
1091
+ <div class="progress-indicator">
1092
+ <div class="progress-bar">
1093
+ <div class="progress-fill" id="progress-fill"></div>
1094
+ </div>
1095
+ <div class="step-counter">
1096
+ Step <span id="current-step-number">{{ session.get('current_step', 1) }}</span> of <span id="total-step-number">6</span>
1097
+ </div>
1098
+ </div>
1099
+
1100
+ {% if prediction %}
1101
+ <div class="result" id="result-message" style="display:none;">
1102
+ <strong>Result:</strong> {{ prediction['prediction'] }}<br>
1103
+ <strong>Score:</strong> {{ prediction['score'] }}
1104
+ </div>
1105
+ {% endif %}
1106
+
1107
+ </div>
1108
+
1109
+ </div>
1110
+
1111
+ </form>
1112
+ </div>
1113
+ </div>
1114
+
1115
+ </div>
1116
+ </section>
1117
+ <script>
1118
+ document.addEventListener("DOMContentLoaded", function() {
1119
+ // Initialize variables
1120
+ var currentStep = 1;
1121
+ var totalSteps = 6;
1122
+ var assessmentData = {};
1123
+
1124
+ console.log('Initializing client-side step navigation');
1125
+
1126
+ // Show only the current step
1127
+ function showStep(stepNumber) {
1128
+ console.log('Showing step:', stepNumber);
1129
+
1130
+ const steps = document.querySelectorAll('.assessment-step');
1131
+ steps.forEach((step, index) => {
1132
+ const stepNum = index + 1;
1133
+ if (stepNum === stepNumber) {
1134
+ step.style.display = 'block';
1135
+ } else {
1136
+ step.style.display = 'none';
1137
+ }
1138
+ });
1139
+
1140
+ // Update progress indicator
1141
+ updateProgressIndicator(stepNumber);
1142
+
1143
+ // Update current step
1144
+ currentStep = stepNumber;
1145
+
1146
+ // Update hidden form field
1147
+ const currentStepInput = document.getElementById('current-step');
1148
+ if (currentStepInput) {
1149
+ currentStepInput.value = currentStep;
1150
+ }
1151
+ }
1152
+
1153
+ // Update progress indicator
1154
+ function updateProgressIndicator(stepNumber) {
1155
+ const progressFill = document.getElementById('progress-fill');
1156
+ const currentStepNumber = document.getElementById('current-step-number');
1157
+
1158
+ if (progressFill) {
1159
+ const progressPercent = (stepNumber / totalSteps) * 100;
1160
+ progressFill.style.width = progressPercent + '%';
1161
+ }
1162
+
1163
+ if (currentStepNumber) {
1164
+ currentStepNumber.textContent = stepNumber;
1165
+ }
1166
+ }
1167
+
1168
+ // Validate current step - IMPROVED VERSION
1169
+ function validateCurrentStep() {
1170
+ const currentStepDiv = document.querySelector('.assessment-step[style*="block"]');
1171
+ if (!currentStepDiv) return true;
1172
+
1173
+ const requiredFields = currentStepDiv.querySelectorAll('select[required], input[required]');
1174
+ let isValid = true;
1175
+ let invalidFields = [];
1176
+
1177
+ requiredFields.forEach(field => {
1178
+ if (!field.value || field.value === '' || field.value === 'Select One') {
1179
+ isValid = false;
1180
+ invalidFields.push(field);
1181
+ field.style.borderColor = '#dc3545';
1182
+ field.style.backgroundColor = '#fff5f5';
1183
+ field.style.boxShadow = '0 0 5px rgba(220, 53, 69, 0.5)';
1184
+ } else {
1185
+ field.style.borderColor = '#28a745';
1186
+ field.style.backgroundColor = '#f8fff8';
1187
+ field.style.boxShadow = '0 0 5px rgba(40, 167, 69, 0.3)';
1188
+ }
1189
+ });
1190
+
1191
+ if (!isValid) {
1192
+ // Scroll to first invalid field
1193
+ if (invalidFields.length > 0) {
1194
+ invalidFields[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
1195
+ invalidFields[0].focus();
1196
+ }
1197
+ alert(`Please fill in all required fields before proceeding. (${invalidFields.length} fields missing)`);
1198
+ }
1199
+
1200
+ return isValid;
1201
+ }
1202
+
1203
+ // Save current step data
1204
+ function saveCurrentStepData() {
1205
+ const currentStepDiv = document.querySelector('.assessment-step[style*="block"]');
1206
+ if (!currentStepDiv) return;
1207
+
1208
+ const formFields = currentStepDiv.querySelectorAll('input, select, textarea');
1209
+ formFields.forEach(field => {
1210
+ if (field.name && field.value && field.value !== 'Select One') {
1211
+ assessmentData[field.name] = field.value;
1212
+ }
1213
+ });
1214
+
1215
+ console.log('Saved step data:', assessmentData);
1216
+ }
1217
+
1218
+ // Load saved data for current step
1219
+ function loadSavedData() {
1220
+ Object.keys(assessmentData).forEach(key => {
1221
+ const field = document.querySelector(`[name="${key}"]`);
1222
+ if (field && assessmentData[key] && assessmentData[key] !== 'Select One') {
1223
+ field.value = assessmentData[key];
1224
+ }
1225
+ });
1226
+ }
1227
+
1228
+ // Handle navigation button clicks
1229
+ function handleNavigation(e) {
1230
+ e.preventDefault(); // Prevent form submission
1231
+
1232
+ const action = e.target.getAttribute('value') || e.target.getAttribute('data-action');
1233
+ console.log('Navigation action:', action);
1234
+
1235
+ // Save current step data first
1236
+ saveCurrentStepData();
1237
+
1238
+ if (action === 'next') {
1239
+ // Validate before going to next step
1240
+ if (!validateCurrentStep()) {
1241
+ return false;
1242
+ }
1243
+
1244
+ if (currentStep < totalSteps) {
1245
+ showStep(currentStep + 1);
1246
+ }
1247
+ } else if (action === 'previous') {
1248
+ if (currentStep > 1) {
1249
+ showStep(currentStep - 1);
1250
+ }
1251
+ } else if (action === 'submit') {
1252
+ // Validate before submitting
1253
+ if (!validateCurrentStep()) {
1254
+ return false;
1255
+ }
1256
+
1257
+ // Change form action to submission endpoint and submit
1258
+ const form = document.getElementById('survey-form');
1259
+ if (form) {
1260
+ // Add all saved data to form before submission
1261
+ Object.keys(assessmentData).forEach(key => {
1262
+ let existingField = form.querySelector(`[name="${key}"]`);
1263
+ if (!existingField) {
1264
+ const hiddenField = document.createElement('input');
1265
+ hiddenField.type = 'hidden';
1266
+ hiddenField.name = key;
1267
+ hiddenField.value = assessmentData[key];
1268
+ form.appendChild(hiddenField);
1269
+ }
1270
+ });
1271
+
1272
+ form.action = '/assessment/submit';
1273
+ form.submit();
1274
+ }
1275
+ }
1276
+
1277
+ return false; // Prevent any default action
1278
+ }
1279
+
1280
+ // Add event listeners to all navigation buttons
1281
+ const navButtons = document.querySelectorAll('.step-navigation button');
1282
+ navButtons.forEach(button => {
1283
+ button.addEventListener('click', handleNavigation);
1284
+ });
1285
+
1286
+ // Prevent default form submission
1287
+ const form = document.getElementById('survey-form');
1288
+ if (form) {
1289
+ form.addEventListener('submit', function(e) {
1290
+ // Only allow submission if it's the final submit
1291
+ if (!e.target.closest('button[value="submit"]')) {
1292
+ e.preventDefault();
1293
+ return false;
1294
+ }
1295
+ });
1296
+ }
1297
+
1298
+ // Initialize the first step
1299
+ showStep(1);
1300
+ loadSavedData();
1301
+
1302
+ console.log('Client-side navigation initialized');
1303
+ });
1304
+ </script>
1305
+ </body>
1306
+ </html>
templates/home.html ADDED
@@ -0,0 +1,566 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="description" content="Advanced Multi-Agent AI Mental Health Assistant with Voice Interaction, Crisis Detection, and Evidence-Based Assessments">
8
+ <meta name="keywords" content="mental health, AI chatbot, multi-agent system, voice interaction, crisis detection, PHQ-9, GAD-7, DAST-10, AUDIT, mental health assessment, CrewAI, RAG, Whisper AI, text-to-speech">
9
+ <meta name="robots" content="INDEX, FOLLOW">
10
+ <link rel="stylesheet" href="{{ url_for('static', filename='stylehome.css') }}">
11
+ <link rel="stylesheet" href="{{ url_for('static', filename='mediahome.css') }}">
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap" rel="stylesheet">
15
+ <title>Bhutanese Mental Health Assistant</title>
16
+ <style>
17
+ /* Authentication modal styles */
18
+ .auth-overlay {
19
+ display: none;
20
+ position: fixed;
21
+ top: 0;
22
+ left: 0;
23
+ width: 100%;
24
+ height: 100%;
25
+ background: rgba(0, 0, 0, 0.7);
26
+ z-index: 1000;
27
+ justify-content: center;
28
+ align-items: center;
29
+ }
30
+
31
+ .auth-modal {
32
+ background: white;
33
+ padding: 40px;
34
+ border-radius: 15px;
35
+ max-width: 400px;
36
+ width: 90%;
37
+ position: relative;
38
+ max-height: 90vh;
39
+ overflow-y: auto;
40
+ }
41
+
42
+ .close-modal {
43
+ position: absolute;
44
+ top: 15px;
45
+ right: 15px;
46
+ font-size: 30px;
47
+ cursor: pointer;
48
+ color: #999;
49
+ }
50
+
51
+ .close-modal:hover {
52
+ color: #333;
53
+ }
54
+
55
+ .auth-tabs {
56
+ display: flex;
57
+ margin-bottom: 30px;
58
+ border-bottom: 2px solid #eee;
59
+ }
60
+
61
+ .auth-tab {
62
+ flex: 1;
63
+ padding: 10px;
64
+ text-align: center;
65
+ cursor: pointer;
66
+ border-bottom: 3px solid transparent;
67
+ transition: all 0.3s;
68
+ }
69
+
70
+ .auth-tab.active {
71
+ color: #667eea;
72
+ border-bottom-color: #667eea;
73
+ }
74
+
75
+ .auth-form {
76
+ display: none;
77
+ font-family: 'Ubuntu', sans-serif;
78
+ }
79
+
80
+ .auth-form.active {
81
+ display: block;
82
+
83
+ }
84
+
85
+ .form-group {
86
+ margin-bottom: 20px;
87
+ }
88
+
89
+ .form-group label {
90
+ display: block;
91
+ margin-bottom: 5px;
92
+ color: #333;
93
+ font-weight: 500;
94
+ }
95
+
96
+ .form-control {
97
+ width: 100%;
98
+ padding: 12px;
99
+ border: 1px solid #ddd;
100
+ border-radius: 8px;
101
+ font-size: 16px;
102
+ box-sizing: border-box;
103
+ }
104
+
105
+ .form-control:focus {
106
+ outline: none;
107
+ border-color: #667eea;
108
+ }
109
+
110
+ .btn-auth {
111
+ width: 100%;
112
+ padding: 12px;
113
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
114
+ color: white;
115
+ border: none;
116
+ border-radius: 8px;
117
+ font-size: 16px;
118
+ font-weight: 600;
119
+ cursor: pointer;
120
+ transition: transform 0.2s;
121
+ }
122
+
123
+ .btn-auth:hover {
124
+ transform: translateY(-2px);
125
+ }
126
+
127
+ .guest-access {
128
+ text-align: center;
129
+ margin-top: 20px;
130
+ padding-top: 20px;
131
+ border-top: 1px solid #eee;
132
+ font-family: 'Ubuntu', sans-serif;
133
+ }
134
+
135
+ .guest-link {
136
+ color: #667eea;
137
+ text-decoration: none;
138
+ }
139
+
140
+ .guest-link:hover {
141
+ text-decoration: underline;
142
+ }
143
+
144
+ /* Survey section styles */
145
+ /* #survey-section {
146
+ display: none;
147
+ }
148
+
149
+ body.authenticated #survey-section {
150
+ display: block;
151
+ }
152
+
153
+ body.authenticated .auth-prompt {
154
+ display: none;
155
+ }
156
+ */
157
+ /* Button styles */
158
+ .btn-primary {
159
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
160
+ color: white;
161
+ padding: 10px 20px;
162
+ border: none;
163
+ border-radius: 5px;
164
+ text-decoration: none;
165
+ display: inline-block;
166
+ cursor: pointer;
167
+ transition: all 0.3s;
168
+ font-size: 16px;
169
+ font-weight: 600;
170
+ }
171
+
172
+ .btn-primary:hover {
173
+ transform: translateY(-2px);
174
+ box-shadow: 0 5px 15px rgba(0,0,0,0.2);
175
+ }
176
+
177
+ .btn-secondary {
178
+ background: #6c757d;
179
+ color: white;
180
+ padding: 10px 20px;
181
+ border: none;
182
+ border-radius: 5px;
183
+ text-decoration: none;
184
+ display: inline-block;
185
+ cursor: pointer;
186
+ transition: background 0.3s;
187
+ }
188
+
189
+ .btn-secondary:hover {
190
+ background: #5a6268;
191
+ }
192
+
193
+ /* Authentication prompt styles */
194
+ .auth-prompt {
195
+ min-height: 60vh;
196
+ display: flex;
197
+ align-items: center;
198
+ justify-content: center;
199
+ }
200
+
201
+ /* Password strength indicator */
202
+ .password-strength {
203
+ font-size: 12px;
204
+ margin-top: 5px;
205
+ padding: 3px 8px;
206
+ border-radius: 3px;
207
+ display: inline-block;
208
+ }
209
+
210
+ .password-strength.weak {
211
+ color: #dc3545;
212
+ background-color: #f8d7da;
213
+ }
214
+
215
+ .password-strength.medium {
216
+ color: #856404;
217
+ background-color: #fff3cd;
218
+ }
219
+
220
+ .password-strength.strong {
221
+ color: #155724;
222
+ background-color: #d4edda;
223
+ }
224
+
225
+ .password-match-error {
226
+ color: #dc3545;
227
+ font-size: 12px;
228
+ margin-top: 5px;
229
+ }
230
+
231
+ /* Error and success messages */
232
+ .error-message {
233
+ background: #f8d7da;
234
+ color: #721c24;
235
+ padding: 12px 20px;
236
+ border-radius: 5px;
237
+ margin-bottom: 20px;
238
+ text-align: center;
239
+ border: 1px solid #f5c6cb;
240
+ font-weight: 500;
241
+ animation: shake 0.5s ease-in-out;
242
+ }
243
+
244
+ @keyframes shake {
245
+ 0%, 100% { transform: translateX(0); }
246
+ 25% { transform: translateX(-10px); }
247
+ 75% { transform: translateX(10px); }
248
+ }
249
+
250
+ .success-message {
251
+ background: #d4edda;
252
+ color: #155724;
253
+ padding: 12px 20px;
254
+ border-radius: 5px;
255
+ margin-bottom: 20px;
256
+ text-align: center;
257
+ border: 1px solid #c3e6cb;
258
+ font-weight: 500;
259
+ }
260
+ </style>
261
+ </head>
262
+ <body class="{% if session.user_id or session.is_guest %}authenticated{% endif %}"
263
+ data-signup-error="{{ signup_error|default('') }}"
264
+ data-login-error="{{ login_error|default('') }}"
265
+ data-show-signup="{{ show_signup_modal|default(false)|tojson }}"
266
+ data-show-login="{{ show_login_modal|default(false)|tojson }}">
267
+
268
+ <nav class="navbar">
269
+ <ul class="nav-Links">
270
+ <a href="{{ url_for('home') }}">
271
+ <div class="logo">
272
+ <img src="{{ url_for('static', filename='mental-health_12560579.png') }}" alt="logo">
273
+ </div>
274
+ </a>
275
+ <div class="nav-item"><li><a href="{{ url_for('home') }}">Home</a></li></div>
276
+ <div class="nav-item"><li><a href="{{ url_for('chatbot') }}">ChatBot</a></li></div>
277
+ <div class="nav-item"><li><a href="{{ url_for('about') }}">About Us</a></li></div>
278
+
279
+ {% if session.user_id %}
280
+ <div class="nav-item"><li><a href="#">Welcome, {{ session.username }}</a></li></div>
281
+ <div class="nav-item"><li><a href="{{ url_for('logout') }}">Logout</a></li></div>
282
+ {% else %}
283
+ <div class="nav-item"><li><a href="#" onclick="showAuthModal()">Login/Sign Up</a></li></div>
284
+ {% endif %}
285
+ </ul>
286
+ </nav>
287
+
288
+ <!-- Authentication Modal -->
289
+ <div class="auth-overlay" id="authOverlay">
290
+ <div class="auth-modal">
291
+ <span class="close-modal" onclick="closeAuthModal()">&times;</span>
292
+
293
+ <div class="auth-tabs">
294
+ <div class="auth-tab active" onclick="switchTab('login')">Login</div>
295
+ <div class="auth-tab" onclick="switchTab('signup')">Sign Up</div>
296
+ </div>
297
+
298
+ <!-- Login Form -->
299
+ <form class="auth-form active" id="loginForm" method="POST" action="{{ url_for('login') }}">
300
+ {% if login_error %}
301
+ <div class="error-message">{{ login_error }}</div>
302
+ {% endif %}
303
+ <div class="form-group">
304
+ <label for="login-username">Username or Email</label>
305
+ <input type="text" class="form-control" id="login-username" name="username" required>
306
+ </div>
307
+ <div class="form-group">
308
+ <label for="login-password">Password</label>
309
+ <input type="password" class="form-control" id="login-password" name="password" required>
310
+ </div>
311
+ <div class="form-group">
312
+ <input type="checkbox" id="remember" name="remember">
313
+ <label for="remember" style="display: inline; margin-left: 5px;">Remember me</label>
314
+ </div>
315
+ <button type="submit" class="btn-auth">Login</button>
316
+ </form>
317
+
318
+ <!-- Signup Form -->
319
+ <form class="auth-form" id="signupForm" method="POST" action="{{ url_for('signup') }}">
320
+ {% if signup_error %}
321
+ <div class="error-message">{{ signup_error }}</div>
322
+ {% endif %}
323
+ <div class="form-group">
324
+ <label for="signup-fullname">Full Name</label>
325
+ <input type="text" class="form-control" id="signup-fullname" name="full_name" required>
326
+ </div>
327
+ <div class="form-group">
328
+ <label for="signup-username">Username</label>
329
+ <input type="text" class="form-control" id="signup-username" name="username"
330
+ pattern="[a-zA-Z0-9_]{3,20}" required>
331
+ </div>
332
+ <div class="form-group">
333
+ <label for="signup-email">Email</label>
334
+ <input type="email" class="form-control" id="signup-email" name="email" required>
335
+ </div>
336
+ <div class="form-group">
337
+ <label for="signup-password">Password</label>
338
+ <input type="password" class="form-control" id="signup-password" name="password"
339
+ minlength="8" required>
340
+ <div id="password-strength"></div>
341
+ </div>
342
+ <div class="form-group">
343
+ <label for="signup-confirm">Confirm Password</label>
344
+ <input type="password" class="form-control" id="signup-confirm" name="confirm_password" required>
345
+ <div id="password-match-error" class="password-match-error"></div>
346
+ </div>
347
+ <button type="submit" class="btn-auth">Sign Up</button>
348
+ </form>
349
+
350
+ <div class="guest-access">
351
+ <p>Just exploring? <a href="{{ url_for('guest_access') }}" class="guest-link">Continue as Guest</a></p>
352
+ </div>
353
+ </div>
354
+ </div>
355
+
356
+ <!-- Landing Page Content -->
357
+ {% if session.user_id %}
358
+ <section class="firstsection auth-prompt" style="height: 100vh;">
359
+ <div class="box" >
360
+ <div class="container" style="text-align: center; padding: 50px; ">
361
+ <h1>Welcome back, {{ session.user_data.name }}!</h1>
362
+ <p style="font-size: 20px; color: #667eea; margin: 20px 0;">Ready to continue your mental wellness journey?</p>
363
+
364
+ <div style="margin-top: 30px;">
365
+ <a href="{{ url_for('assessment') }}" class="btn btn-primary" style="margin: 10px; font-size: 18px; padding: 15px 30px;">Take Assessment</a>
366
+ <a href="{{ url_for('chatbot') }}" class="btn btn-secondary" style="margin: 10px; font-size: 18px; padding: 15px 30px;">Chat with Assistant</a>
367
+ </div>
368
+ </div>
369
+ </div>
370
+ </section>
371
+ {% elif not session.user_id and not session.is_guest %}
372
+ <section class="firstsection auth-prompt">
373
+ <div class="box">
374
+ <div class="container" style="text-align: center; padding: 50px;">
375
+ <h1>Welcome to Bhutanese Mental Health AI Assistant</h1>
376
+ <p style="font-size: 20px; color: #667eea; margin: 20px 0;">Advanced Multi-Agent AI System for Comprehensive Mental Wellness Support</p>
377
+
378
+ <div style="max-width: 800px; margin: 0 auto; text-align: left;">
379
+ <div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin: 30px 0;">
380
+ <h2 style="color: #333; margin-bottom: 20px;">Bhutanese Mental Health Support Features:</h2>
381
+
382
+ <div style="margin-bottom: 20px;">
383
+ <h3 style="color: #667eea;">� Multi-Agent AI System</h3>
384
+ <p>Experience our advanced AI chatbot powered by specialized agents including Crisis Detection, Mental Health Assessment, Knowledge Retrieval, and Personalized Recommendation systems using cutting-edge CrewAI technology.</p>
385
+ </div>
386
+
387
+ <div style="margin-bottom: 20px;">
388
+ <h3 style="color: #667eea;">🎯 Scientifically-Backed Assessments</h3>
389
+ <p>Take standardized mental health assessments including PHQ-9 (Depression), GAD-7 (Anxiety), DAST-10 (Substance Use), AUDIT (Alcohol Use), and Bipolar Disorder screening with immediate scoring and interpretation.</p>
390
+ </div>
391
+
392
+ <div style="margin-bottom: 20px;">
393
+ <h3 style="color: #667eea;">🎤 Voice & Speech Integration</h3>
394
+ <p>Interact naturally with voice recording capabilities, real-time speech-to-text transcription using Whisper AI, and text-to-speech responses for a more accessible and conversational experience.</p>
395
+ </div>
396
+
397
+ <div style="margin-bottom: 20px;">
398
+ <h3 style="color: #667eea;">� Knowledge-Enhanced Responses</h3>
399
+ <p>Get evidence-based guidance through our RAG (Retrieval-Augmented Generation) system that draws from comprehensive mental health knowledge bases and culturally sensitive resources for Bhutan.</p>
400
+ </div>
401
+
402
+ <div style="margin-bottom: 20px;">
403
+ <h3 style="color: #667eea;">🆘 Crisis Detection & Support</h3>
404
+ <p>Advanced AI monitors conversations for crisis indicators, providing immediate emergency resources and specialized support when needed, with direct access to Bhutanese mental health helplines.</p>
405
+ </div>
406
+
407
+ <div style="margin-bottom: 20px;">
408
+ <h3 style="color: #667eea;">🔐 Privacy & Security First</h3>
409
+ <p>Your data is protected with encryption, secure authentication, and the option to use our services anonymously as a guest. All conversations and assessments are stored securely.</p>
410
+ </div>
411
+ </div>
412
+
413
+ <div style="background: #e8f4fd; padding: 25px; border-radius: 15px; margin-bottom: 30px;">
414
+ <h3 style="color: #0c5460; margin-bottom: 15px;">How Our Advanced System Works:</h3>
415
+ <ol style="margin-left: 20px; line-height: 1.8;">
416
+ <li><strong>Smart Authentication</strong> - Create a secure account or explore anonymously with guest access</li>
417
+ <li><strong>AI-Powered Assessment</strong> - Complete standardized mental health screenings (PHQ-9, GAD-7, etc.) with instant scoring</li>
418
+ <li><strong>Multi-Agent Chat System</strong> - Interact with specialized AI agents for crisis detection, condition classification, and personalized recommendations</li>
419
+ <li><strong>Voice & Text Interaction</strong> - Chat via text or voice with real-time transcription and text-to-speech responses</li>
420
+ <li><strong>Knowledge-Enhanced Support</strong> - Receive evidence-based guidance from our comprehensive mental health knowledge base</li>
421
+ <li><strong>Progress Tracking</strong> - Monitor your mental wellness journey with saved assessments and chat history</li>
422
+ <li><strong>Emergency Support</strong> - Automatic crisis detection with immediate access to local Bhutanese mental health resources</li>
423
+ </ol>
424
+ </div>
425
+ </div>
426
+
427
+ <div style="margin-top: 30px; display: flex; justify-content: center; flex-direction: column; align-items: center;">
428
+ <button class="btn btn-primary" onclick="showAuthModal()" style="margin: 10px; font-size: 18px; padding: 15px 30px;">🚀 Start Your Journey</button>
429
+ <a href="{{ url_for('guest_access') }}" class="btn btn-secondary" style="margin: 10px; font-size: 18px; padding: 15px 30px;">👤 Try as Guest</a>
430
+ <p style="margin-top: 15px; font-size: 14px; color: #888;">
431
+ ✨ Featuring: Multi-Agent AI • Voice Interaction • Crisis Detection • Evidence-Based Assessments
432
+ </p>
433
+ </div>
434
+
435
+ <p style="margin-top: 20px; font-style: italic; color: #666;">
436
+ <strong>Powered by Advanced AI:</strong> Our system uses CrewAI multi-agent technology, Whisper speech recognition, RAG knowledge retrieval, and evidence-based assessment tools. This tool is for support and assessment only - for emergencies or serious concerns, please consult healthcare professionals or contact emergency services.
437
+ </p>
438
+ </div>
439
+ </div>
440
+ </section>
441
+ {% endif %}
442
+ <!-- JavaScript -->
443
+ <script>
444
+ // Auth modal functions
445
+ function showAuthModal() {
446
+ document.getElementById('authOverlay').style.display = 'flex';
447
+ }
448
+
449
+ function closeAuthModal() {
450
+ document.getElementById('authOverlay').style.display = 'none';
451
+ }
452
+
453
+ function switchTab(tab) {
454
+ document.querySelectorAll('.auth-tab').forEach(t => t.classList.remove('active'));
455
+ document.querySelectorAll('.auth-form').forEach(f => f.classList.remove('active'));
456
+ if (tab === 'login') {
457
+ document.querySelector('.auth-tab:nth-child(1)').classList.add('active');
458
+ document.getElementById('loginForm').classList.add('active');
459
+ } else {
460
+ document.querySelector('.auth-tab:nth-child(2)').classList.add('active');
461
+ document.getElementById('signupForm').classList.add('active');
462
+ }
463
+ }
464
+
465
+ // Close modal when clicking outside
466
+ document.getElementById('authOverlay').addEventListener('click', function(e) {
467
+ if (e.target === this) {
468
+ closeAuthModal();
469
+ }
470
+ });
471
+
472
+ document.addEventListener("DOMContentLoaded", function() {
473
+ // Auth modal error handling
474
+ const body = document.body;
475
+ const signupError = body.getAttribute('data-signup-error');
476
+ const loginError = body.getAttribute('data-login-error');
477
+ const showSignupModal = body.getAttribute('data-show-signup') === 'true';
478
+ const showLoginModal = body.getAttribute('data-show-login') === 'true';
479
+
480
+ // Handle signup errors and modal display
481
+ if (showSignupModal || signupError) {
482
+ setTimeout(() => {
483
+ showAuthModal();
484
+ switchTab('signup');
485
+ }, 100);
486
+ }
487
+
488
+ // Handle login errors and modal display
489
+ if (showLoginModal || loginError) {
490
+ setTimeout(() => {
491
+ showAuthModal();
492
+ switchTab('login');
493
+ }, 100);
494
+ }
495
+
496
+ // Password strength checker
497
+ const passwordInput = document.getElementById('signup-password');
498
+ if (passwordInput) {
499
+ passwordInput.addEventListener('input', function(e) {
500
+ const password = e.target.value;
501
+ const strengthDiv = document.getElementById('password-strength');
502
+ if (!password) {
503
+ strengthDiv.textContent = '';
504
+ strengthDiv.className = 'password-strength';
505
+ return;
506
+ }
507
+ if (password.length < 8) {
508
+ strengthDiv.textContent = 'Too short (min 8 characters)';
509
+ strengthDiv.className = 'password-strength weak';
510
+ } else if (password.match(/^[a-zA-Z]+$/) || password.match(/^[0-9]+$/)) {
511
+ strengthDiv.textContent = 'Weak - add numbers and symbols';
512
+ strengthDiv.className = 'password-strength weak';
513
+ } else if (password.match(/^[a-zA-Z0-9]+$/)) {
514
+ strengthDiv.textContent = 'Medium - add symbols';
515
+ strengthDiv.className = 'password-strength medium';
516
+ } else {
517
+ strengthDiv.textContent = 'Strong password';
518
+ strengthDiv.className = 'password-strength strong';
519
+ }
520
+ });
521
+ }
522
+
523
+ // Real-time password match validation
524
+ const confirmInput = document.getElementById('signup-confirm');
525
+ if (confirmInput) {
526
+ confirmInput.addEventListener('input', function(e) {
527
+ const password = document.getElementById('signup-password').value;
528
+ const confirmPassword = e.target.value;
529
+ const matchError = document.getElementById('password-match-error');
530
+ if (confirmPassword && password !== confirmPassword) {
531
+ matchError.textContent = 'Passwords do not match';
532
+ e.target.style.borderColor = '#dc3545';
533
+ } else if (confirmPassword && password === confirmPassword) {
534
+ matchError.textContent = '';
535
+ e.target.style.borderColor = '#28a745';
536
+ } else {
537
+ matchError.textContent = '';
538
+ e.target.style.borderColor = '';
539
+ }
540
+ });
541
+ }
542
+
543
+ // Signup form validation
544
+ const signupForm = document.getElementById('signupForm');
545
+ if (signupForm) {
546
+ signupForm.addEventListener('submit', function(e) {
547
+ const password = document.getElementById('signup-password').value;
548
+ const confirmPassword = document.getElementById('signup-confirm').value;
549
+ if (password !== confirmPassword) {
550
+ e.preventDefault();
551
+ alert('Passwords do not match!');
552
+ document.getElementById('signup-confirm').focus();
553
+ return false;
554
+ }
555
+ if (password.length < 8) {
556
+ e.preventDefault();
557
+ alert('Password must be at least 8 characters long');
558
+ document.getElementById('signup-password').focus();
559
+ return false;
560
+ }
561
+ });
562
+ }
563
+ });
564
+ </script>
565
+ </body>
566
+ </html>
templates/initial_survey.html ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Initial Assessment - Mental Health Assistant</title>
7
+ <link rel="stylesheet" href="{{ url_for('static', filename='stylehome.css') }}">
8
+ <style>
9
+ .survey-intro {
10
+ text-align: center;
11
+ max-width: 600px;
12
+ margin: 50px auto;
13
+ padding: 40px;
14
+ background: white;
15
+ border-radius: 15px;
16
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1);
17
+ }
18
+
19
+ .survey-intro h1 {
20
+ color: #667eea;
21
+ margin-bottom: 20px;
22
+ }
23
+
24
+ .survey-intro p {
25
+ color: #666;
26
+ line-height: 1.6;
27
+ margin-bottom: 30px;
28
+ }
29
+
30
+ .benefits {
31
+ text-align: left;
32
+ background: #f8f9fa;
33
+ padding: 20px;
34
+ border-radius: 10px;
35
+ margin: 20px 0;
36
+ }
37
+
38
+ .benefits li {
39
+ margin: 10px 0;
40
+ color: #333;
41
+ }
42
+
43
+ .btn-start-survey {
44
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
45
+ color: white;
46
+ padding: 15px 40px;
47
+ border: none;
48
+ border-radius: 8px;
49
+ font-size: 18px;
50
+ cursor: pointer;
51
+ transition: transform 0.2s;
52
+ }
53
+
54
+ .btn-start-survey:hover {
55
+ transform: translateY(-2px);
56
+ }
57
+
58
+ .skip-option {
59
+ margin-top: 20px;
60
+ color: #999;
61
+ }
62
+ </style>
63
+ </head>
64
+ <body>
65
+ <div class="survey-intro">
66
+ <h1>Welcome, {{ session.user_data.name }}!</h1>
67
+ <p>Before we begin, we'd like to understand your current mental health status better.
68
+ This initial assessment will help us provide personalized support.</p>
69
+
70
+ <div class="benefits">
71
+ <h3>Why take this assessment?</h3>
72
+ <ul>
73
+ <li>🎯 Get personalized mental health insights</li>
74
+ <li>📊 Track your progress over time</li>
75
+ <li>💡 Receive tailored recommendations</li>
76
+ <li>🔒 Your data is completely confidential</li>
77
+ </ul>
78
+ </div>
79
+
80
+ <p><strong>Time required:</strong> 5-7 minutes</p>
81
+
82
+ <form action="{{ url_for('home') }}" method="get">
83
+ <button type="submit" class="btn-start-survey">Start Assessment</button>
84
+ </form>
85
+
86
+ <!-- Optional: Allow skipping for now -->
87
+ <!-- <div class="skip-option">
88
+ <a href="{{ url_for('chatbot') }}">Skip for now</a>
89
+ </div> -->
90
+ </div>
91
+ </body>
92
+ </html>
templates/user_dashboard.html ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Welcome - Mental Health Assistant</title>
7
+ <link rel="stylesheet" href="{{ url_for('static', filename='stylehome.css') }}">
8
+ <style>
9
+ body {
10
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
11
+ min-height: 100vh;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ font-family: 'Roboto', sans-serif;
16
+ }
17
+
18
+ .dashboard-container {
19
+ max-width: 600px;
20
+ width: 90%;
21
+ padding: 40px;
22
+ background: white;
23
+ border-radius: 15px;
24
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1);
25
+ text-align: center;
26
+ }
27
+
28
+ .welcome-header {
29
+ margin-bottom: 40px;
30
+ }
31
+
32
+ .welcome-header h1 {
33
+ color: #333;
34
+ margin-bottom: 10px;
35
+ }
36
+
37
+ .welcome-header p {
38
+ color: #666;
39
+ font-size: 18px;
40
+ }
41
+
42
+ .new-user-message {
43
+ background: #e8f4fd;
44
+ border: 1px solid #bee5eb;
45
+ color: #0c5460;
46
+ padding: 15px;
47
+ border-radius: 8px;
48
+ margin-bottom: 30px;
49
+ }
50
+
51
+ .options-grid {
52
+ display: grid;
53
+ grid-template-columns: 1fr 1fr;
54
+ gap: 20px;
55
+ margin-top: 30px;
56
+ }
57
+
58
+ .option-card {
59
+ padding: 30px 20px;
60
+ border: 2px solid #eee;
61
+ border-radius: 10px;
62
+ cursor: pointer;
63
+ transition: all 0.3s;
64
+ text-decoration: none;
65
+ color: #333;
66
+ }
67
+
68
+ .option-card:hover {
69
+ border-color: #667eea;
70
+ transform: translateY(-5px);
71
+ box-shadow: 0 5px 20px rgba(102, 126, 234, 0.2);
72
+ }
73
+
74
+ .option-card.recommended {
75
+ border-color: #667eea;
76
+ background: #f6f8ff;
77
+ }
78
+
79
+ .option-icon {
80
+ font-size: 48px;
81
+ margin-bottom: 15px;
82
+ }
83
+
84
+ .option-title {
85
+ font-size: 20px;
86
+ font-weight: 600;
87
+ margin-bottom: 10px;
88
+ }
89
+
90
+ .option-desc {
91
+ color: #666;
92
+ font-size: 14px;
93
+ }
94
+
95
+ .recommended-badge {
96
+ background: #667eea;
97
+ color: white;
98
+ font-size: 12px;
99
+ padding: 4px 8px;
100
+ border-radius: 4px;
101
+ margin-top: 10px;
102
+ display: inline-block;
103
+ }
104
+
105
+ .last-assessment {
106
+ margin-top: 30px;
107
+ padding: 20px;
108
+ background: #f8f9fa;
109
+ border-radius: 10px;
110
+ }
111
+
112
+ .logout-link {
113
+ margin-top: 30px;
114
+ display: inline-block;
115
+ color: #666;
116
+ text-decoration: none;
117
+ font-size: 14px;
118
+ }
119
+
120
+ .logout-link:hover {
121
+ color: #333;
122
+ text-decoration: underline;
123
+ }
124
+
125
+ @media (max-width: 600px) {
126
+ .options-grid {
127
+ grid-template-columns: 1fr;
128
+ }
129
+ }
130
+ </style>
131
+ </head>
132
+ <body>
133
+ <div class="dashboard-container">
134
+ <div class="welcome-header">
135
+ <h1>Welcome{% if not session.user_data.has_completed_survey %} to GreenLife{% else %} back{% endif %}, {{ session.user_data.name }}!</h1>
136
+ <p>What would you like to do today?</p>
137
+ </div>
138
+
139
+ {% if not session.user_data.has_completed_survey %}
140
+ <div class="new-user-message">
141
+ <strong>Welcome aboard!</strong> We recommend starting with a mental health assessment
142
+ to help personalize your experience.
143
+ </div>
144
+ {% endif %}
145
+
146
+ <div class="options-grid">
147
+ <a href="{{ url_for('assessment') }}" class="option-card {% if not session.user_data.has_completed_survey %}recommended{% endif %}">
148
+ <div class="option-icon">📋</div>
149
+ <div class="option-title">Take Assessment</div>
150
+ <div class="option-desc">Complete a mental health assessment to track your progress</div>
151
+ {% if not session.user_data.has_completed_survey %}
152
+ <div class="recommended-badge">Recommended</div>
153
+ {% endif %}
154
+ </a>
155
+
156
+ <a href="{{ url_for('chatbot') }}" class="option-card">
157
+ <div class="option-icon">💬</div>
158
+ <div class="option-title">Chat with Assistant</div>
159
+ <div class="option-desc">Get support and guidance from our AI assistant</div>
160
+ </a>
161
+ </div>
162
+
163
+ {% if session.user_data.has_completed_survey %}
164
+ <div class="last-assessment">
165
+ <p><strong>Previous Assessment:</strong> You've completed an assessment before.</p>
166
+ <p>Taking regular assessments helps track your mental health journey.</p>
167
+ </div>
168
+ {% else %}
169
+ <div class="last-assessment">
170
+ <p><strong>Note:</strong> You haven't completed an assessment yet.</p>
171
+ <p>We recommend taking one to get personalized insights.</p>
172
+ </div>
173
+ {% endif %}
174
+
175
+ <a href="{{ url_for('logout') }}" class="logout-link">Logout</a>
176
+ </div>
177
+ </body>
178
+ </html>