leothesouthafrican commited on
Commit
0082b84
·
1 Parent(s): 9bb8090

initial commit

Browse files
Files changed (49) hide show
  1. Dockerfile +21 -18
  2. Dockerfile.test +0 -28
  3. README +0 -1
  4. README.md +1 -3
  5. build_scripts/build.sh +28 -0
  6. docker-compose.dev.yml +1 -9
  7. docker-compose.prod.yml +1 -1
  8. nginx.conf +13 -17
  9. requirements.txt +182 -3
  10. web_app/backend/app/__init__.py +2 -8
  11. web_app/backend/app/answers_model.py +73 -8
  12. web_app/backend/app/{chatbot.py → chatbot_routes.py} +69 -19
  13. web_app/backend/app/data/.gitkeep +0 -0
  14. web_app/backend/app/data/{BER_Small.csv → BER/BER_Small.csv} +0 -0
  15. web_app/backend/app/data/chain.json +57 -0
  16. web_app/backend/app/data/dropped_features.txt +15 -0
  17. web_app/backend/app/data/energy_modelling.ipynb +0 -0
  18. web_app/backend/app/data/pinecone_tut.ipynb +0 -370
  19. web_app/backend/app/models.py +6 -6
  20. web_app/backend/app/pinecone_q.ipynb +0 -133
  21. web_app/backend/app/question_model.py +21 -4
  22. web_app/backend/requirements.txt +0 -102
  23. web_app/backend/run.py +1 -1
  24. web_app/frontend/package-lock.json +0 -0
  25. web_app/frontend/package.json +14 -4
  26. web_app/frontend/public/map1.json +0 -0
  27. web_app/frontend/src/App.jsx +2 -2
  28. web_app/frontend/src/AppRouter.jsx +7 -3
  29. web_app/frontend/src/components/ChatHistory.jsx +3 -3
  30. web_app/frontend/src/components/ChatInput.jsx +7 -5
  31. web_app/frontend/src/components/Map3D-old.jsx +137 -0
  32. web_app/frontend/src/components/Map3D.jsx +155 -0
  33. web_app/frontend/src/components/Navbar.jsx +15 -20
  34. web_app/frontend/src/components/StartCard.jsx +16 -13
  35. web_app/frontend/src/components/emailService.jsx +26 -0
  36. web_app/frontend/src/hooks/useChat.js +7 -9
  37. web_app/frontend/src/pages/AboutPage.jsx +13 -11
  38. web_app/frontend/src/pages/ChatBot.jsx +0 -76
  39. web_app/frontend/src/pages/ChatPage.jsx +169 -46
  40. web_app/frontend/src/pages/CityPage.jsx +112 -0
  41. web_app/frontend/src/pages/ContactPage.jsx +13 -11
  42. web_app/frontend/src/pages/DashboardPage-new.jsx +104 -0
  43. web_app/frontend/src/pages/DashboardPage-old.jsx +125 -0
  44. web_app/frontend/src/pages/DashboardPage.css +164 -0
  45. web_app/frontend/src/pages/LandingPage.jsx +3 -1
  46. web_app/frontend/src/pages/{DashboardPage.jsx → ReportsPage.jsx} +37 -36
  47. web_app/frontend/src/pages/ResourcesPage.jsx +105 -0
  48. web_app/frontend/src/pages/scrollbar.css +20 -0
  49. web_app/frontend/vite.config.js +11 -7
Dockerfile CHANGED
@@ -1,37 +1,40 @@
1
- # ----------------------
2
  # STAGE 1: Backend build
3
- # ----------------------
4
-
5
  FROM python:3.9-slim-buster as backend
6
-
7
  WORKDIR /app/backend
8
 
9
- COPY web_app/backend/requirements.txt .
 
 
10
 
11
- RUN apt-get update && apt-get install -y --no-install-recommends gcc g++
12
- RUN pip install --no-cache-dir -r requirements.txt
13
- RUN pip install pandas
 
 
14
 
 
15
  COPY web_app/backend/ .
16
 
17
  CMD ["python", "run.py"]
18
 
19
- # -------------------------
20
  # STAGE 2: Frontend build
21
- # -------------------------
22
-
23
  FROM node:14-alpine as frontend
24
-
25
  WORKDIR /app/frontend
26
 
27
- COPY web_app/frontend/package*.json ./
28
-
29
- RUN npm install
30
-
31
  COPY web_app/frontend/ .
 
 
 
 
32
 
33
- RUN npm run build
34
 
35
  EXPOSE 3000
 
36
 
37
- CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
1
+ #------------------------
2
  # STAGE 1: Backend build
3
+ #------------------------
 
4
  FROM python:3.9-slim-buster as backend
 
5
  WORKDIR /app/backend
6
 
7
+ # Copy necessary files
8
+ COPY requirements.txt .
9
+ COPY build_scripts/build.sh .
10
 
11
+ # Set environment variable, make the script executable and run it
12
+ ENV STAGE=backend
13
+ RUN chmod +x ./build.sh && \
14
+ ./build.sh backend && \
15
+ rm -rf /var/lib/apt/lists/*
16
 
17
+ # Copy the rest of the backend app
18
  COPY web_app/backend/ .
19
 
20
  CMD ["python", "run.py"]
21
 
22
+ #-------------------------
23
  # STAGE 2: Frontend build
24
+ #-------------------------
 
25
  FROM node:14-alpine as frontend
 
26
  WORKDIR /app/frontend
27
 
28
+ # Grouped copy for package-related files and the frontend app
29
+ COPY web_app/frontend/package*.json .
 
 
30
  COPY web_app/frontend/ .
31
+ COPY build_scripts/build.sh .
32
+
33
+ # Set environment variables, make the script executable and run it
34
+ ENV STAGE=frontend
35
 
36
+ RUN chmod +x ./build.sh && ./build.sh frontend
37
 
38
  EXPOSE 3000
39
+ CMD ["serve", "-s", "dist", "-l", "3000"]
40
 
 
Dockerfile.test DELETED
@@ -1,28 +0,0 @@
1
- # Use the official Python 3.9 image
2
- FROM python:3.9
3
-
4
- # Set the working directory to /code
5
- WORKDIR /code
6
-
7
- # Copy the current directory contents into the container at /code
8
- COPY ./requirements.txt /code/requirements.txt
9
-
10
- # Install requirements.txt
11
- RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
12
-
13
- # Set up a new user named "user" with user ID 1000
14
- RUN useradd -m -u 1000 user
15
- # Switch to the "user" user
16
- USER user
17
- # Set home to the user's home directory
18
- ENV HOME=/home/user \
19
- PATH=/home/user/.local/bin:$PATH
20
-
21
- # Set the working directory to the user's home directory
22
- WORKDIR $HOME/app
23
-
24
- # Copy the current directory contents into the container at $HOME/app setting the owner to the user
25
- COPY --chown=user . $HOME/app
26
-
27
- # Start the FastAPI app on port 7860, the default port expected by Spaces
28
- CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README DELETED
@@ -1 +0,0 @@
1
- # Hello
 
 
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Luminlab-web-app
3
  emoji: ⚡
4
  colorFrom: yellow
5
  colorTo: gray
@@ -8,5 +8,3 @@ pinned: false
8
  license: cc-by-nc-2.0
9
  app_port: 3000
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: web-app-temp
3
  emoji: ⚡
4
  colorFrom: yellow
5
  colorTo: gray
 
8
  license: cc-by-nc-2.0
9
  app_port: 3000
10
  ---
 
 
build_scripts/build.sh ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ # Check the STAGE environment variable
5
+ if [ "$STAGE" = "backend" ]; then
6
+
7
+ # Update and install dependencies
8
+ apt-get update && apt-get install -y --no-install-recommends gcc g++
9
+
10
+ # Install python dependencies
11
+ pip install --no-cache-dir -r requirements.txt
12
+
13
+ elif [ "$STAGE" = "frontend" ]; then
14
+
15
+ # Install dependencies
16
+ npm install
17
+
18
+ # Adjust permissions and build in a single command
19
+ chown -R node:node /app/frontend
20
+ npm run build
21
+
22
+ # Install serve
23
+ npm install -g serve
24
+
25
+ else
26
+ echo "Error: Invalid or no STAGE specified"
27
+ exit 1
28
+ fi
docker-compose.dev.yml CHANGED
@@ -5,7 +5,7 @@ services:
5
  context: .
6
  target: backend
7
  ports:
8
- - 5001:5000
9
 
10
  frontend:
11
  image: node:alpine
@@ -23,14 +23,6 @@ services:
23
  depends_on:
24
  - backend
25
 
26
- dl:
27
- build:
28
- context: .
29
- dockerfile: Dockerfile
30
- image: pytorch/pytorch:1.13.0-cuda11.6-cudnn8-runtime
31
- tty: true
32
- stdin_open: true
33
-
34
  volumes:
35
  postgres_data:
36
 
 
5
  context: .
6
  target: backend
7
  ports:
8
+ - 5000:5000
9
 
10
  frontend:
11
  image: node:alpine
 
23
  depends_on:
24
  - backend
25
 
 
 
 
 
 
 
 
 
26
  volumes:
27
  postgres_data:
28
 
docker-compose.prod.yml CHANGED
@@ -5,7 +5,7 @@ services:
5
  context: .
6
  target: backend
7
  ports:
8
- - 5001:5000
9
  environment:
10
  - DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}
11
  depends_on:
 
5
  context: .
6
  target: backend
7
  ports:
8
+ - 5000:5000
9
  environment:
10
  - DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}
11
  depends_on:
nginx.conf CHANGED
@@ -1,30 +1,26 @@
1
- # The events block configures the connection handling capabilities of Nginx.
2
- events {
3
- # The worker_connections directive specifies the maximum number of simultaneous connections
4
- # that a single worker process can handle.
5
- worker_connections 1024;
6
- }
7
 
8
- # The http block is where you define directives for handling HTTP requests.
9
  http {
10
- upstream frontend {
11
- server frontend:3000;
12
- }
13
-
14
  upstream backend {
15
  server backend:5000;
16
  }
 
 
 
17
 
18
  server {
19
- listen 80;
20
-
21
- location / {
22
- proxy_pass http://frontend;
23
- }
24
 
25
  location /api/ {
26
  proxy_pass http://backend;
 
 
 
 
 
 
 
 
27
  }
28
  }
29
  }
30
-
 
1
+ events {}
 
 
 
 
 
2
 
 
3
  http {
 
 
 
 
4
  upstream backend {
5
  server backend:5000;
6
  }
7
+ upstream frontend {
8
+ server frontend:3000;
9
+ }
10
 
11
  server {
12
+ listen 8081;
 
 
 
 
13
 
14
  location /api/ {
15
  proxy_pass http://backend;
16
+ proxy_set_header Host $host;
17
+ proxy_set_header X-Real-IP $remote_addr;
18
+ }
19
+
20
+ location / {
21
+ proxy_pass http://frontend;
22
+ proxy_set_header Host $host;
23
+ proxy_set_header X-Real-IP $remote_addr;
24
  }
25
  }
26
  }
 
requirements.txt CHANGED
@@ -1,3 +1,182 @@
1
- fastapi==0.74.*
2
- requests==2.27.*
3
- uvicorn[standard]==0.17.*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiohttp==3.8.5
2
+ aiosignal==1.3.1
3
+ anyio==3.7.1
4
+ appnope==0.1.3
5
+ argon2-cffi==21.3.0
6
+ argon2-cffi-bindings==21.2.0
7
+ arrow==1.2.3
8
+ astor==0.8.1
9
+ asttokens==2.2.1
10
+ async-lru==2.0.4
11
+ async-timeout==4.0.2
12
+ attrs==23.1.0
13
+ Babel==2.12.1
14
+ backcall==0.2.0
15
+ backoff==2.2.1
16
+ beautifulsoup4==4.12.2
17
+ bleach==6.0.0
18
+ blinker==1.6.2
19
+ cachetools==5.3.1
20
+ certifi==2023.7.22
21
+ cffi==1.15.1
22
+ charset-normalizer==3.2.0
23
+ chroma-hnswlib==0.7.1
24
+ chromadb==0.4.3
25
+ click==8.1.4
26
+ coloredlogs==15.0.1
27
+ comm==0.1.4
28
+ contourpy==1.1.0
29
+ cssselect==1.2.0
30
+ cssutils==2.7.1
31
+ cycler==0.11.0
32
+ dataclasses-json==0.5.13
33
+ debugpy==1.6.7
34
+ decorator==5.1.1
35
+ defusedxml==0.7.1
36
+ dnspython==2.4.1
37
+ docopt==0.6.2
38
+ executing==1.2.0
39
+ faiss-cpu==1.7.4
40
+ fastapi==0.99.1
41
+ fastjsonschema==2.18.0
42
+ Flask==2.3.2
43
+ Flask-Cors==4.0.0
44
+ Flask-SQLAlchemy==3.0.5
45
+ flatbuffers==23.5.26
46
+ fonttools==4.41.1
47
+ fpdf==1.7.2
48
+ fqdn==1.5.1
49
+ frozenlist==1.4.0
50
+ h11==0.14.0
51
+ httptools==0.6.0
52
+ humanfriendly==10.0
53
+ idna==3.4
54
+ importlib-resources==6.0.0
55
+ ipykernel==6.25.0
56
+ ipython==8.14.0
57
+ ipython-genutils==0.2.0
58
+ ipywidgets==8.1.0
59
+ isoduration==20.11.0
60
+ itsdangerous==2.1.2
61
+ jedi==0.18.2
62
+ Jinja2==3.1.2
63
+ joblib==1.3.1
64
+ json5==0.9.14
65
+ jsonpointer==2.4
66
+ jsonschema==4.18.6
67
+ jsonschema-specifications==2023.7.1
68
+ jupyter==1.0.0
69
+ jupyter-console==6.6.3
70
+ jupyter-events==0.7.0
71
+ jupyter-lsp==2.2.0
72
+ jupyter_client==8.3.0
73
+ jupyter_core==5.3.1
74
+ jupyter_server==2.7.0
75
+ jupyter_server_terminals==0.4.4
76
+ jupyterlab==4.0.4
77
+ jupyterlab-pygments==0.2.2
78
+ jupyterlab-widgets==3.0.8
79
+ jupyterlab_server==2.24.0
80
+ kiwisolver==1.4.4
81
+ langchain==0.0.247
82
+ langsmith==0.0.15
83
+ loguru==0.7.0
84
+ lxml==4.9.3
85
+ MarkupSafe==2.1.3
86
+ marshmallow==3.20.1
87
+ matplotlib==3.7.2
88
+ matplotlib-inline==0.1.6
89
+ mistune==3.0.1
90
+ monotonic==1.6
91
+ mpmath==1.3.0
92
+ multidict==6.0.4
93
+ mypy-extensions==1.0.0
94
+ nbclient==0.8.0
95
+ nbconvert==7.7.3
96
+ nbformat==5.9.2
97
+ nest-asyncio==1.5.7
98
+ notebook==7.0.2
99
+ notebook_shim==0.2.3
100
+ numexpr==2.8.4
101
+ numpy==1.25.1
102
+ onnxruntime==1.15.1
103
+ openai==0.27.8
104
+ openapi-schema-pydantic==1.2.4
105
+ overrides==7.3.1
106
+ packaging==23.1
107
+ pandas==1.5.3
108
+ pandasai==0.7.2
109
+ pandocfilters==1.5.0
110
+ parso==0.8.3
111
+ pexpect==4.8.0
112
+ pickleshare==0.7.5
113
+ Pillow==10.0.0
114
+ pinecone-client==2.2.2
115
+ pipreqs==0.4.13
116
+ platformdirs==3.10.0
117
+ plotly==5.15.0
118
+ posthog==3.0.1
119
+ premailer==3.10.0
120
+ prometheus-client==0.17.1
121
+ prompt-toolkit==3.0.39
122
+ protobuf==4.23.4
123
+ psutil==5.9.5
124
+ #psycopg2-binary==2.9.1
125
+ ptyprocess==0.7.0
126
+ pulsar-client==3.2.0
127
+ pure-eval==0.2.2
128
+ pycparser==2.21
129
+ pydantic==1.10.12
130
+ Pygments==2.15.1
131
+ pyparsing==3.0.9
132
+ PyPika==0.48.9
133
+ python-dateutil==2.8.2
134
+ python-dotenv==1.0.0
135
+ python-json-logger==2.0.7
136
+ pytz==2023.3
137
+ PyYAML==6.0.1
138
+ pyzmq==25.1.0
139
+ qtconsole==5.4.3
140
+ QtPy==2.3.1
141
+ referencing==0.30.2
142
+ regex==2023.6.3
143
+ requests==2.31.0
144
+ rfc3339-validator==0.1.4
145
+ rfc3986-validator==0.1.1
146
+ rpds-py==0.9.2
147
+ scikit-learn==1.3.0
148
+ scipy==1.11.1
149
+ Send2Trash==1.8.2
150
+ six==1.16.0
151
+ sniffio==1.3.0
152
+ soupsieve==2.4.1
153
+ SQLAlchemy==2.0.18
154
+ stack-data==0.6.2
155
+ starlette==0.27.0
156
+ sympy==1.12
157
+ tenacity==8.2.2
158
+ terminado==0.17.1
159
+ threadpoolctl==3.2.0
160
+ tiktoken==0.4.0
161
+ tinycss2==1.2.1
162
+ tokenizers==0.13.3
163
+ tornado==6.3.2
164
+ tqdm==4.65.0
165
+ traitlets==5.9.0
166
+ typing-inspect==0.9.0
167
+ typing_extensions==4.7.1
168
+ uri-template==1.3.0
169
+ urllib3==2.0.4
170
+ uvicorn==0.23.1
171
+ uvloop==0.17.0
172
+ watchfiles==0.19.0
173
+ wcwidth==0.2.6
174
+ webcolors==1.13
175
+ webencodings==0.5.1
176
+ websocket-client==1.6.1
177
+ websockets==11.0.3
178
+ Werkzeug==2.3.6
179
+ widgetsnbextension==4.0.8
180
+ yagmail==0.15.293
181
+ yarg==0.1.9
182
+ yarl==1.9.2
web_app/backend/app/__init__.py CHANGED
@@ -2,11 +2,5 @@ from flask import Flask # Import the Flask module
2
  from flask_cors import CORS # Import the CORS module
3
 
4
  app = Flask(__name__) # Initialize a Flask web app
5
- CORS(app) # Implement Cross-Origin Resource Sharing (CORS) on the Flask app
6
-
7
- from app import chatbot, home, models # Import modules from the "app" package (assuming it's in the same directory)
8
-
9
- # Use the app's context to perform actions related to the app
10
- with app.app_context():
11
- models.db.drop_all()
12
- models.db.create_all()
 
2
  from flask_cors import CORS # Import the CORS module
3
 
4
  app = Flask(__name__) # Initialize a Flask web app
5
+ cors = CORS(app)
6
+ from app import chatbot_routes, home, models # Import modules from the "app" package (assuming it's in the same directory)
 
 
 
 
 
 
web_app/backend/app/answers_model.py CHANGED
@@ -1,10 +1,75 @@
1
- from pandasai import PandasAI
2
- from pandasai.llm.openai import OpenAI
3
- from dotenv import load_dotenv
 
 
 
 
 
4
 
5
- # Load the environment variables
6
- load_dotenv()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
- # Initialize the OpenAI and PandasAI
9
- llm = OpenAI(model = "gpt-3.5-turbo-16k", temperature = 0.0)
10
- pandas_ai = PandasAI(llm, conversational = True)
 
1
+ import pinecone
2
+ from dotenv import load_dotenv, find_dotenv
3
+ from langchain.embeddings.openai import OpenAIEmbeddings
4
+ from langchain.memory import ConversationBufferMemory
5
+ from langchain.vectorstores import Pinecone
6
+ from langchain.chat_models import ChatOpenAI
7
+ from langchain.chains import RetrievalQA
8
+ from langchain import PromptTemplate
9
 
10
+ # Load environment variables
11
+ load_dotenv(find_dotenv())
12
+
13
+ # Setting up embeddings
14
+ embedder = OpenAIEmbeddings()
15
+
16
+ # Setting up the vectorstore
17
+ pinecone.init(environment="us-west4-gcp")
18
+ index = pinecone.Index('seai-website')
19
+
20
+ #Set up the retriever
21
+ vectorstore = Pinecone(index, embedder.embed_query, 'text')
22
+
23
+ # Setting up the llm
24
+ llm = ChatOpenAI(temperature=0.0)
25
+
26
+ # Setting up the prompt template
27
+ template = """
28
+ Use the following context (delimited by <ctx></ctx>) and the chat history (delimited by <hs></hs>) to answer the question:
29
+ ------
30
+ <ctx>
31
+ {context}
32
+ </ctx>
33
+ ------
34
+ <hs>
35
+ {history}
36
+ </hs>
37
+ ------
38
+ {question}
39
+ Answer:
40
+ """
41
+ prompt = PromptTemplate(
42
+ input_variables=["history", "context", "question"],
43
+ template=template,
44
+ )
45
+
46
+ # Setting up the memory
47
+ memory = ConversationBufferMemory(memory_key="history", input_key="question")
48
+
49
+ # Setting up the QA chain
50
+ qa = RetrievalQA.from_chain_type(
51
+ llm=ChatOpenAI(),
52
+ chain_type='stuff',
53
+ retriever=vectorstore.as_retriever(),
54
+ verbose=True,
55
+ chain_type_kwargs={
56
+ "verbose": True,
57
+ "prompt": prompt,
58
+ "memory": memory
59
+ }
60
+ )
61
+
62
+ def generate_question_response(query: str) -> str:
63
+ return qa.run(query)
64
+
65
+ if __name__ == "__main__":
66
+ # Sample query
67
+ test_query = "What is the capital of France?"
68
+
69
+ # Generate a response using the model
70
+ response = generate_question_response(test_query)
71
+
72
+ # Print the query and its response
73
+ print(f"Query: {test_query}")
74
+ print(f"Response: {response}")
75
 
 
 
 
web_app/backend/app/{chatbot.py → chatbot_routes.py} RENAMED
@@ -1,40 +1,38 @@
1
  from app import app
2
  from flask import send_from_directory, jsonify, request
3
- import pandas as pd
4
- from pandasai import PandasAI
5
- from pandasai.llm.openai import OpenAI
6
- from os import environ
7
  import os
8
- from dotenv import load_dotenv
9
  from app.question_model import generate_response
10
- from app.answers_model import pandas_ai
11
-
12
- print(os.getcwd())
13
 
14
  # Load the environment variables
15
- load_dotenv()
16
 
17
- CURRENT_DIRECTORY = os.path.dirname(__file__)
18
- DATA_PATH = os.path.join(CURRENT_DIRECTORY, 'data', 'BER_Small.csv')
19
 
20
- df = pd.read_csv(DATA_PATH, encoding='ISO-8859-1', low_memory=False)
 
 
 
 
21
 
22
  # Route to handle user prompt questions
23
  @app.route('/sendText', methods=['POST'])
24
  def handle_text():
25
  try:
26
  data = request.get_json()
27
- print(data)
28
  print(f'Received text: {data["text"]}')
29
 
30
- # Process the dataframe
31
- output = pandas_ai(df, prompt = data["text"])
32
  print(f'Output: {output}')
33
 
34
  return jsonify(message='Received!', output=output), 200
35
  except Exception as e:
36
- print(f'Error occurred: {e}')
37
- return jsonify(message='Error occurred', error=str(e), type=str(type(e))), 500
38
 
39
  # Route to handle suggested questions
40
  @app.route('/sendQuestions', methods=['POST'])
@@ -58,5 +56,57 @@ def handle_questions():
58
 
59
  return jsonify(message='Received!', output=output), 200
60
  except Exception as e:
61
- print(f'Error occurred: {e}')
62
- return jsonify(message='Error occurred', error=str(e), type=str(type(e))), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from app import app
2
  from flask import send_from_directory, jsonify, request
 
 
 
 
3
  import os
4
+ from dotenv import load_dotenv, find_dotenv
5
  from app.question_model import generate_response
6
+ from app.answers_model import generate_question_response
7
+ from fpdf import FPDF
8
+ import yagmail
9
 
10
  # Load the environment variables
11
+ load_dotenv(find_dotenv())
12
 
13
+ print(f"Loading .env from: {find_dotenv()}")
 
14
 
15
+ # Add a route to help with error handling
16
+ @app.errorhandler(500)
17
+ def internal_error(error):
18
+ app.logger.error("Server Error: %s", error)
19
+ return jsonify(message="Internal Server Error"), 500
20
 
21
  # Route to handle user prompt questions
22
  @app.route('/sendText', methods=['POST'])
23
  def handle_text():
24
  try:
25
  data = request.get_json()
 
26
  print(f'Received text: {data["text"]}')
27
 
28
+ # Use the new model to get the output
29
+ output = generate_question_response(data["text"])
30
  print(f'Output: {output}')
31
 
32
  return jsonify(message='Received!', output=output), 200
33
  except Exception as e:
34
+ app.logger.error(f"Error occurred during sendText: {e}")
35
+ return jsonify(message='Error occurred during sendText', error=str(e), type=str(type(e))), 500
36
 
37
  # Route to handle suggested questions
38
  @app.route('/sendQuestions', methods=['POST'])
 
56
 
57
  return jsonify(message='Received!', output=output), 200
58
  except Exception as e:
59
+ app.logger.error(f"Error occurred during sendText: {e}")
60
+ return jsonify(message='Error occurred during sendText', error=str(e), type=str(type(e))), 500
61
+
62
+ @app.route('/exportChat', methods=['POST'])
63
+ def export_chat():
64
+ email = request.json.get('email')
65
+ chat_history = request.json.get('chatHistory')
66
+
67
+ # Convert chatHistory to PDF
68
+ pdf_file = create_pdf_from_chat_history(chat_history)
69
+
70
+ # Send the PDF to the email
71
+ send_pdf_to_email(email, pdf_file)
72
+
73
+ return jsonify({"message": f"Email sent to: {email}"}), 200
74
+
75
+ def create_pdf_from_chat_history(chat_history):
76
+ # Initialize the Python PDF library, FPDF
77
+ pdf = FPDF()
78
+
79
+ # Add a new page to the PDF
80
+ pdf.add_page()
81
+
82
+ # Set the font for the page (Arial, size 12)
83
+ pdf.set_font("Arial", size = 12)
84
+
85
+ # Loop through the chat history
86
+ for chat in chat_history:
87
+ # Add each question and answer to the PDF as a multiline text box
88
+ pdf.multi_cell(190, 10, f"Q: {chat['question']}\nA: {chat['response']}")
89
+
90
+ # Define the name of the generated PDF file
91
+ filename = "chat_history.pdf"
92
+
93
+ # Generate the PDF and save it to a file
94
+ pdf.output(name=filename, dest='F').encode("latin1")
95
+
96
+ # Return the filename for later usage
97
+ return filename
98
+
99
+ def send_pdf_to_email(email, pdf_file):
100
+ # Initialize yagmail client with email and password
101
+ yag = yagmail.SMTP(user="leo.defig", password="dummyPASSWORD123")
102
+
103
+ # Use yagmail to send an email with the PDF file as an attachment
104
+ yag.send(
105
+ to=email,
106
+ subject="Your Chat History",
107
+ contents="Please find attached the chat history.",
108
+ attachments=pdf_file,
109
+ )
110
+
111
+ # After sending the email, delete the PDF file from local storage
112
+ os.remove(pdf_file)
web_app/backend/app/data/.gitkeep ADDED
File without changes
web_app/backend/app/data/{BER_Small.csv → BER/BER_Small.csv} RENAMED
File without changes
web_app/backend/app/data/chain.json ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "memory": null,
3
+ "verbose": false,
4
+ "tags": null,
5
+ "metadata": null,
6
+ "prompt": {
7
+ "input_variables": [
8
+ "input"
9
+ ],
10
+ "output_parser": null,
11
+ "partial_variables": {},
12
+ "messages": [
13
+ {
14
+ "content": "You are a world class algorithm for extracting information in structured formats.",
15
+ "additional_kwargs": {}
16
+ },
17
+ {
18
+ "content": "Use the given format to extract information from the following input:",
19
+ "additional_kwargs": {},
20
+ "example": false
21
+ },
22
+ {
23
+ "prompt": {
24
+ "input_variables": [
25
+ "input"
26
+ ],
27
+ "output_parser": null,
28
+ "partial_variables": {},
29
+ "template": "{input}",
30
+ "template_format": "f-string",
31
+ "validate_template": true,
32
+ "_type": "prompt"
33
+ },
34
+ "additional_kwargs": {}
35
+ },
36
+ {
37
+ "content": "Tips: Make sure to answer in the correct format",
38
+ "additional_kwargs": {},
39
+ "example": false
40
+ }
41
+ ],
42
+ "_type": "chat"
43
+ },
44
+ "llm": {
45
+ "model_name": "gpt-3.5-turbo",
46
+ "model": "gpt-3.5-turbo",
47
+ "request_timeout": null,
48
+ "max_tokens": null,
49
+ "stream": false,
50
+ "n": 1,
51
+ "temperature": 0.0,
52
+ "_type": "openai-chat"
53
+ },
54
+ "output_key": "function",
55
+ "output_parser": {
56
+ "args_only": true,
57
+ "pydantic_schema":
web_app/backend/app/data/dropped_features.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "ThirdEnerProdDelivered","UvalueDoor","DeliveredEnergyPumpsFans","SecondFloorHeight",
2
+ "gsdHSSupplSystemEff","SecondPartLTotalContribution","FirstEnerProdC02EmissionFactor","FirstEnerProdDeliveredLow",
3
+ "LowEnergyLightingPercent","C02SupplementaryWater","FirstFloorArea","ZeroLossCollectorEff",
4
+ "FirstEnerConsumedDelivered","ThirdFloorHeight","InsulationThickness","ThirdWallUValue",
5
+ "SecondFloorArea","FanPowerManuDeclaredValue","CHPHeatEff","GroundFloorUValue",
6
+ "CollectorHeatLossCoEff","UValueFloor","WHMainSystemEff","PrimaryEnergySupplementaryWater",
7
+ "ThirdFloorArea","WHEffAdjFactor","UValueRoof","PermeabilityTestResult",
8
+ "TotalC02Emissions","FirstHeatGenPlantEff","ThirdPercentageHeat","prob_smarea_error_0corr",
9
+ "PercentageDraughtStripped","CHPUnitHeatFraction","SecondPercentageHeat","FirstFloorHeight",
10
+ "TotalPrimaryEnergyFact","DoorArea","HSSupplSystemEff","TempFactorUnadj",
11
+ "RenewEPren","SecondHeatGenPlantEff","CombiBoilerAddLoss","SolarStorageVolume",
12
+ "ThirdHeatGenPlantEff","HSEffAdjFactor","FirstWallUValue","HeatExchangerEff",
13
+ "ThirdPartLTotalContribution","DeliveredEnergySecondarySpace","AnnualSolarRadiation","FirstPercentageHeat",
14
+ "DeclaredLossFactor","WaterStorageVolume","RoomInRoofArea","FirstPartLTotalContribution",
15
+ "SecondWallUValue","SecondEnerProdDelivered","RER","ThermalBridgingFactor"
web_app/backend/app/data/energy_modelling.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
web_app/backend/app/data/pinecone_tut.ipynb DELETED
@@ -1,370 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": 13,
6
- "metadata": {},
7
- "outputs": [],
8
- "source": [
9
- "import pinecone \n",
10
- "import pandas as pd\n",
11
- "\n",
12
- "api_key = \"22e9da2e-64bc-47c6-b4a2-d0d220210aff\"\n",
13
- "pinecone.init(api_key=api_key, environment='us-west4-gcp')"
14
- ]
15
- },
16
- {
17
- "cell_type": "code",
18
- "execution_count": 10,
19
- "metadata": {},
20
- "outputs": [],
21
- "source": [
22
- "#Giving our index a name\n",
23
- "index_name = \"lumin-question-data\"\n",
24
- "\n",
25
- "#Delete index if it already exists\n",
26
- "if index_name in pinecone.list_indexes():\n",
27
- " pinecone.delete_index(index_name)"
28
- ]
29
- },
30
- {
31
- "cell_type": "code",
32
- "execution_count": 11,
33
- "metadata": {},
34
- "outputs": [],
35
- "source": [
36
- "# Create Pinecone index\n",
37
- "dimensions = 3\n",
38
- "pinecone.create_index(name = index_name, dimension = dimensions, metric = 'cosine', shards = 1)"
39
- ]
40
- },
41
- {
42
- "cell_type": "code",
43
- "execution_count": 12,
44
- "metadata": {},
45
- "outputs": [],
46
- "source": [
47
- "index = pinecone.Index(index_name=index_name)"
48
- ]
49
- },
50
- {
51
- "cell_type": "code",
52
- "execution_count": 16,
53
- "metadata": {},
54
- "outputs": [
55
- {
56
- "data": {
57
- "text/html": [
58
- "<div>\n",
59
- "<style scoped>\n",
60
- " .dataframe tbody tr th:only-of-type {\n",
61
- " vertical-align: middle;\n",
62
- " }\n",
63
- "\n",
64
- " .dataframe tbody tr th {\n",
65
- " vertical-align: top;\n",
66
- " }\n",
67
- "\n",
68
- " .dataframe thead th {\n",
69
- " text-align: right;\n",
70
- " }\n",
71
- "</style>\n",
72
- "<table border=\"1\" class=\"dataframe\">\n",
73
- " <thead>\n",
74
- " <tr style=\"text-align: right;\">\n",
75
- " <th></th>\n",
76
- " <th>id</th>\n",
77
- " <th>vector</th>\n",
78
- " </tr>\n",
79
- " </thead>\n",
80
- " <tbody>\n",
81
- " <tr>\n",
82
- " <th>0</th>\n",
83
- " <td>A</td>\n",
84
- " <td>[0.1, 0.2, 0.3]</td>\n",
85
- " </tr>\n",
86
- " <tr>\n",
87
- " <th>1</th>\n",
88
- " <td>B</td>\n",
89
- " <td>[0.2, 0.3, 0.4]</td>\n",
90
- " </tr>\n",
91
- " <tr>\n",
92
- " <th>2</th>\n",
93
- " <td>C</td>\n",
94
- " <td>[0.3, 0.4, 0.5]</td>\n",
95
- " </tr>\n",
96
- " <tr>\n",
97
- " <th>3</th>\n",
98
- " <td>D</td>\n",
99
- " <td>[0.4, 0.5, 0.6]</td>\n",
100
- " </tr>\n",
101
- " <tr>\n",
102
- " <th>4</th>\n",
103
- " <td>E</td>\n",
104
- " <td>[0.5, 0.6, 0.7]</td>\n",
105
- " </tr>\n",
106
- " </tbody>\n",
107
- "</table>\n",
108
- "</div>"
109
- ],
110
- "text/plain": [
111
- " id vector\n",
112
- "0 A [0.1, 0.2, 0.3]\n",
113
- "1 B [0.2, 0.3, 0.4]\n",
114
- "2 C [0.3, 0.4, 0.5]\n",
115
- "3 D [0.4, 0.5, 0.6]\n",
116
- "4 E [0.5, 0.6, 0.7]"
117
- ]
118
- },
119
- "execution_count": 16,
120
- "metadata": {},
121
- "output_type": "execute_result"
122
- }
123
- ],
124
- "source": [
125
- "#Load the dataframe\n",
126
- "df = pd.DataFrame(\n",
127
- " data={\n",
128
- " \"id\": [\"A\", \"B\", \"C\", \"D\", \"E\"],\n",
129
- " \"vector\": [\n",
130
- " [0.1, 0.2, 0.3],\n",
131
- " [0.2, 0.3, 0.4],\n",
132
- " [0.3, 0.4, 0.5],\n",
133
- " [0.4, 0.5, 0.6],\n",
134
- " [0.5, 0.6, 0.7]]\n",
135
- " }\n",
136
- ")\n",
137
- " \n",
138
- "df"
139
- ]
140
- },
141
- {
142
- "cell_type": "code",
143
- "execution_count": 17,
144
- "metadata": {},
145
- "outputs": [
146
- {
147
- "data": {
148
- "text/plain": [
149
- "{'upserted_count': 5}"
150
- ]
151
- },
152
- "execution_count": 17,
153
- "metadata": {},
154
- "output_type": "execute_result"
155
- }
156
- ],
157
- "source": [
158
- "index.upsert(vectors=zip(df['id'], df['vector']))"
159
- ]
160
- },
161
- {
162
- "cell_type": "code",
163
- "execution_count": 18,
164
- "metadata": {},
165
- "outputs": [
166
- {
167
- "data": {
168
- "text/plain": [
169
- "{'dimension': 3,\n",
170
- " 'index_fullness': 0.0,\n",
171
- " 'namespaces': {'': {'vector_count': 5}},\n",
172
- " 'total_vector_count': 5}"
173
- ]
174
- },
175
- "execution_count": 18,
176
- "metadata": {},
177
- "output_type": "execute_result"
178
- }
179
- ],
180
- "source": [
181
- "index.describe_index_stats()"
182
- ]
183
- },
184
- {
185
- "cell_type": "code",
186
- "execution_count": 19,
187
- "metadata": {},
188
- "outputs": [
189
- {
190
- "data": {
191
- "text/plain": [
192
- "{'results': [{'matches': [{'id': 'E',\n",
193
- " 'score': 0.990867436,\n",
194
- " 'values': [0.5, 0.6, 0.7]},\n",
195
- " {'id': 'D',\n",
196
- " 'score': 0.986927509,\n",
197
- " 'values': [0.4, 0.5, 0.6]}],\n",
198
- " 'namespace': ''}]}"
199
- ]
200
- },
201
- "execution_count": 19,
202
- "metadata": {},
203
- "output_type": "execute_result"
204
- }
205
- ],
206
- "source": [
207
- "index.query(\n",
208
- " queries=[[2,2,2]],\n",
209
- " top_k=2,\n",
210
- " include_values=True\n",
211
- ")"
212
- ]
213
- },
214
- {
215
- "cell_type": "code",
216
- "execution_count": 20,
217
- "metadata": {},
218
- "outputs": [
219
- {
220
- "data": {
221
- "text/plain": [
222
- "['lumin-question-data']"
223
- ]
224
- },
225
- "execution_count": 20,
226
- "metadata": {},
227
- "output_type": "execute_result"
228
- }
229
- ],
230
- "source": [
231
- "pinecone.list_indexes()"
232
- ]
233
- },
234
- {
235
- "cell_type": "code",
236
- "execution_count": 22,
237
- "metadata": {},
238
- "outputs": [
239
- {
240
- "data": {
241
- "text/plain": [
242
- "IndexDescription(name='lumin-question-data', metric='cosine', replicas=1, dimension=3.0, shards=1, pods=1, pod_type='p1.x1', status={'ready': True, 'state': 'Ready'}, metadata_config=None, source_collection='')"
243
- ]
244
- },
245
- "execution_count": 22,
246
- "metadata": {},
247
- "output_type": "execute_result"
248
- }
249
- ],
250
- "source": [
251
- "pinecone.describe_index(\"lumin-question-data\")"
252
- ]
253
- },
254
- {
255
- "cell_type": "code",
256
- "execution_count": 30,
257
- "metadata": {},
258
- "outputs": [],
259
- "source": [
260
- "import random \n",
261
- "\n",
262
- "ids = [\"a\", \"b\", \"c\", \"d\", \"e\"]\n",
263
- "vecs = [[random.random() for _ in range(3)] for _ in range(len(ids))]"
264
- ]
265
- },
266
- {
267
- "cell_type": "code",
268
- "execution_count": 31,
269
- "metadata": {},
270
- "outputs": [
271
- {
272
- "data": {
273
- "text/plain": [
274
- "[[0.5582998198744755, 0.01804592916533032, 0.06927366246378208],\n",
275
- " [0.19606955177481333, 0.9497032707066528, 0.08713643524214854],\n",
276
- " [0.06740320859564719, 0.5796438198602569, 0.2521688997698266],\n",
277
- " [0.08410319865807259, 0.0442919355259529, 0.6309807322716778],\n",
278
- " [0.7629393424814093, 0.02832065828346908, 0.6747540161958138]]"
279
- ]
280
- },
281
- "execution_count": 31,
282
- "metadata": {},
283
- "output_type": "execute_result"
284
- }
285
- ],
286
- "source": [
287
- "vecs"
288
- ]
289
- },
290
- {
291
- "cell_type": "code",
292
- "execution_count": 32,
293
- "metadata": {},
294
- "outputs": [],
295
- "source": [
296
- "index = pinecone.Index(\"lumin-question-data\")"
297
- ]
298
- },
299
- {
300
- "cell_type": "code",
301
- "execution_count": 33,
302
- "metadata": {},
303
- "outputs": [
304
- {
305
- "data": {
306
- "text/plain": [
307
- "{'upserted_count': 5}"
308
- ]
309
- },
310
- "execution_count": 33,
311
- "metadata": {},
312
- "output_type": "execute_result"
313
- }
314
- ],
315
- "source": [
316
- "index.upsert(vectors=zip(ids, vecs))"
317
- ]
318
- },
319
- {
320
- "cell_type": "code",
321
- "execution_count": 36,
322
- "metadata": {},
323
- "outputs": [
324
- {
325
- "ename": "AttributeError",
326
- "evalue": "'Index' object has no attribute 'delete_index'",
327
- "output_type": "error",
328
- "traceback": [
329
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
330
- "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
331
- "Cell \u001b[0;32mIn[36], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m index\u001b[39m.\u001b[39;49mdelete_index(\u001b[39m\"\u001b[39m\u001b[39mlumin-question-data\u001b[39m\u001b[39m\"\u001b[39m)\n",
332
- "\u001b[0;31mAttributeError\u001b[0m: 'Index' object has no attribute 'delete_index'"
333
- ]
334
- }
335
- ],
336
- "source": [
337
- "index.delete_index(\"lumin-question-data\")"
338
- ]
339
- },
340
- {
341
- "cell_type": "code",
342
- "execution_count": null,
343
- "metadata": {},
344
- "outputs": [],
345
- "source": []
346
- }
347
- ],
348
- "metadata": {
349
- "kernelspec": {
350
- "display_name": "Python 3",
351
- "language": "python",
352
- "name": "python3"
353
- },
354
- "language_info": {
355
- "codemirror_mode": {
356
- "name": "ipython",
357
- "version": 3
358
- },
359
- "file_extension": ".py",
360
- "mimetype": "text/x-python",
361
- "name": "python",
362
- "nbconvert_exporter": "python",
363
- "pygments_lexer": "ipython3",
364
- "version": "3.11.4"
365
- },
366
- "orig_nbformat": 4
367
- },
368
- "nbformat": 4,
369
- "nbformat_minor": 2
370
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
web_app/backend/app/models.py CHANGED
@@ -1,12 +1,12 @@
1
- from flask_sqlalchemy import SQLAlchemy
2
- from app import app
3
 
4
  #Connect to the database
5
- app.config["SQLALCHEMY_DATABASE_URI"] = ("postgresql://luminlab:Lumin#adapt2023@194.29.101.181:5433/luminlab_db")
6
 
7
- db = SQLAlchemy(app)
8
 
9
- class User(db.Model):
10
  __tablename__ = 'user'
11
  id = db.Column(db.Integer, primary_key=True, autoincrement=True)
12
  first_name = db.Column(db.String(50), nullable=False)
@@ -29,4 +29,4 @@ class User(db.Model):
29
 
30
  # create an application context
31
  with app.app_context():
32
- db.create_all()
 
1
+ #from flask_sqlalchemy import SQLAlchemy
2
+ #from app import app
3
 
4
  #Connect to the database
5
+ #app.config["SQLALCHEMY_DATABASE_URI"] = ("postgresql://luminlab:Lumin#adapt2023@194.29.101.181:5433/luminlab_db")
6
 
7
+ #db = SQLAlchemy(app)
8
 
9
+ """class User(db.Model):
10
  __tablename__ = 'user'
11
  id = db.Column(db.Integer, primary_key=True, autoincrement=True)
12
  first_name = db.Column(db.String(50), nullable=False)
 
29
 
30
  # create an application context
31
  with app.app_context():
32
+ db.create_all()"""
web_app/backend/app/pinecone_q.ipynb DELETED
@@ -1,133 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": 1,
6
- "metadata": {},
7
- "outputs": [
8
- {
9
- "name": "stderr",
10
- "output_type": "stream",
11
- "text": [
12
- "/opt/homebrew/lib/python3.11/site-packages/pinecone/index.py:4: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
13
- " from tqdm.autonotebook import tqdm\n"
14
- ]
15
- },
16
- {
17
- "data": {
18
- "text/plain": [
19
- "True"
20
- ]
21
- },
22
- "execution_count": 1,
23
- "metadata": {},
24
- "output_type": "execute_result"
25
- }
26
- ],
27
- "source": [
28
- "from langchain.document_loaders.csv_loader import CSVLoader\n",
29
- "from langchain.vectorstores import FAISS\n",
30
- "from langchain.embeddings.openai import OpenAIEmbeddings\n",
31
- "from langchain.prompts import PromptTemplate\n",
32
- "from langchain.chat_models import ChatOpenAI\n",
33
- "from langchain.chains import LLMChain\n",
34
- "from dotenv import load_dotenv\n",
35
- "import pandas as pd\n",
36
- "\n",
37
- "import pinecone\n",
38
- "\n",
39
- "\n",
40
- "\n",
41
- "load_dotenv()"
42
- ]
43
- },
44
- {
45
- "cell_type": "code",
46
- "execution_count": 4,
47
- "metadata": {},
48
- "outputs": [],
49
- "source": [
50
- "#set the file path\n",
51
- "file_path = \"/Users/leo/Programming/luminlab/web_app/backend/app/data/BER_Small.csv\"\n",
52
- "df = pd.read_csv(file_path, encoding='ISO-8859-1', low_memory=False)\n",
53
- "\n",
54
- "#load the data\n",
55
- "loader = CSVLoader(file_path=file_path)\n",
56
- "documents = loader.load()\n",
57
- "embeddings = OpenAIEmbeddings()\n",
58
- "\n",
59
- "#set up pinecone\n",
60
- "api_key = \"22e9da2e-64bc-47c6-b4a2-d0d220210aff\"\n",
61
- "pinecone.init(api_key=api_key, environment='us-west4-gcp')\n",
62
- "index_name = \"lumin-answers\"\n",
63
- "\n",
64
- "\n",
65
- "# Create Pinecone index\n",
66
- "dimensions = df.shape[1]\n",
67
- "\n",
68
- "#Delete index if it already exists\n",
69
- "if index_name in pinecone.list_indexes():\n",
70
- " pinecone.delete_index(index_name)\n",
71
- " \n",
72
- "pinecone.create_index(name = index_name, dimension = dimensions, metric = 'cosine', shards = 1)\n",
73
- "\n",
74
- "#Init the index so that we can interact with it\n",
75
- "index = pinecone.Index(index_name)"
76
- ]
77
- },
78
- {
79
- "cell_type": "code",
80
- "execution_count": 5,
81
- "metadata": {},
82
- "outputs": [
83
- {
84
- "data": {
85
- "text/plain": [
86
- "{'dimension': 212,\n",
87
- " 'index_fullness': 0.0,\n",
88
- " 'namespaces': {},\n",
89
- " 'total_vector_count': 0}"
90
- ]
91
- },
92
- "execution_count": 5,
93
- "metadata": {},
94
- "output_type": "execute_result"
95
- }
96
- ],
97
- "source": [
98
- "index.describe_index_stats()"
99
- ]
100
- },
101
- {
102
- "cell_type": "code",
103
- "execution_count": null,
104
- "metadata": {},
105
- "outputs": [],
106
- "source": [
107
- "index = "
108
- ]
109
- }
110
- ],
111
- "metadata": {
112
- "kernelspec": {
113
- "display_name": "Python 3",
114
- "language": "python",
115
- "name": "python3"
116
- },
117
- "language_info": {
118
- "codemirror_mode": {
119
- "name": "ipython",
120
- "version": 3
121
- },
122
- "file_extension": ".py",
123
- "mimetype": "text/x-python",
124
- "name": "python",
125
- "nbconvert_exporter": "python",
126
- "pygments_lexer": "ipython3",
127
- "version": "3.11.4"
128
- },
129
- "orig_nbformat": 4
130
- },
131
- "nbformat": 4,
132
- "nbformat_minor": 2
133
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
web_app/backend/app/question_model.py CHANGED
@@ -4,10 +4,12 @@ from langchain.embeddings.openai import OpenAIEmbeddings
4
  from langchain.prompts import PromptTemplate
5
  from langchain.chat_models import ChatOpenAI
6
  from langchain.chains import LLMChain
7
- from dotenv import load_dotenv
8
  import os
9
 
10
- load_dotenv()
 
 
11
 
12
  # Load the data
13
  # Get the directory of the current file
@@ -49,7 +51,22 @@ llm = ChatOpenAI(temperature=0, model = "gpt-3.5-turbo-16k")
49
 
50
  # Define a template for the prompts to the language model
51
  template = """
52
- ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  """
54
 
55
  # Define the template for the prompt with the input variables and template
@@ -89,4 +106,4 @@ def generate_response(message):
89
  # Convert follow-up questions into a string response
90
  response = '\n'.join(follow_ups)
91
 
92
- return response
 
4
  from langchain.prompts import PromptTemplate
5
  from langchain.chat_models import ChatOpenAI
6
  from langchain.chains import LLMChain
7
+ from dotenv import load_dotenv, find_dotenv
8
  import os
9
 
10
+ # Load the environment variables
11
+ load_dotenv(find_dotenv())
12
+
13
 
14
  # Load the data
15
  # Get the directory of the current file
 
51
 
52
  # Define a template for the prompts to the language model
53
  template = """
54
+ You are a extremely intelligent online assistant who's goal is to act as a
55
+ reccomendation system for the user. The user will ask you questions about the
56
+ retrofitting of their home in Ireland and you will provide them with the next two most
57
+ logical questions for them to ask. Your suggested questions should be similar to the
58
+ best practice examples that I will provide you with. The examples are structured as RootQuestion
59
+ being the original question asked by the user and FollowUp1 and FollowUp2 being the next two
60
+ questions that the user should ask.
61
+
62
+ Below is the question that you have received from the user:
63
+ {question}
64
+
65
+ Here is a list of the best practice examples that you should try to emulate:
66
+ {examples}
67
+
68
+ Please return the most logical next two questions for the user to ask.
69
+ Ensure that you only send back exactly two follow-up questions.
70
  """
71
 
72
  # Define the template for the prompt with the input variables and template
 
106
  # Convert follow-up questions into a string response
107
  response = '\n'.join(follow_ups)
108
 
109
+ return response
web_app/backend/requirements.txt DELETED
@@ -1,102 +0,0 @@
1
- aiohttp==3.8.5
2
- aiosignal==1.3.1
3
- anyio==3.7.1
4
- appnope==0.1.3
5
- astor==0.8.1
6
- asttokens==2.2.1
7
- async-timeout==4.0.2
8
- attrs==23.1.0
9
- backcall==0.2.0
10
- backoff==2.2.1
11
- blinker==1.6.2
12
- certifi==2023.7.22
13
- charset-normalizer==3.2.0
14
- chroma-hnswlib==0.7.1
15
- chromadb==0.4.3
16
- click==8.1.4
17
- coloredlogs==15.0.1
18
- contourpy==1.1.0
19
- cycler==0.11.0
20
- dataclasses-json==0.5.13
21
- decorator==5.1.1
22
- executing==1.2.0
23
- faiss-cpu==1.7.4
24
- fastapi==0.99.1
25
- Flask==2.3.2
26
- Flask-Cors==4.0.0
27
- Flask-SQLAlchemy==3.0.5
28
- flatbuffers==23.5.26
29
- fonttools==4.41.1
30
- frozenlist==1.4.0
31
- h11==0.14.0
32
- httptools==0.6.0
33
- humanfriendly==10.0
34
- idna==3.4
35
- importlib-resources==6.0.0
36
- ipython==8.14.0
37
- itsdangerous==2.1.2
38
- jedi==0.18.2
39
- Jinja2==3.1.2
40
- kiwisolver==1.4.4
41
- langchain==0.0.247
42
- langsmith==0.0.15
43
- MarkupSafe==2.1.3
44
- marshmallow==3.20.1
45
- matplotlib==3.7.2
46
- matplotlib-inline==0.1.6
47
- monotonic==1.6
48
- mpmath==1.3.0
49
- multidict==6.0.4
50
- mypy-extensions==1.0.0
51
- numexpr==2.8.4
52
- numpy==1.25.1
53
- onnxruntime==1.15.1
54
- openai==0.27.8
55
- openapi-schema-pydantic==1.2.4
56
- overrides==7.3.1
57
- packaging==23.1
58
- pandas==1.5.3
59
- pandasai==0.7.2
60
- parso==0.8.3
61
- pexpect==4.8.0
62
- pickleshare==0.7.5
63
- Pillow==10.0.0
64
- plotly==5.15.0
65
- posthog==3.0.1
66
- prompt-toolkit==3.0.39
67
- protobuf==4.23.4
68
- psycopg2-binary==2.9.1
69
- ptyprocess==0.7.0
70
- pulsar-client==3.2.0
71
- pure-eval==0.2.2
72
- pydantic==1.10.12
73
- Pygments==2.15.1
74
- pyparsing==3.0.9
75
- PyPika==0.48.9
76
- python-dateutil==2.8.2
77
- python-dotenv==1.0.0
78
- pytz==2023.3
79
- PyYAML==6.0.1
80
- regex==2023.6.3
81
- requests==2.31.0
82
- six==1.16.0
83
- sniffio==1.3.0
84
- SQLAlchemy==2.0.18
85
- stack-data==0.6.2
86
- starlette==0.27.0
87
- sympy==1.12
88
- tenacity==8.2.2
89
- tiktoken==0.4.0
90
- tokenizers==0.13.3
91
- tqdm==4.65.0
92
- traitlets==5.9.0
93
- typing-inspect==0.9.0
94
- typing_extensions==4.7.1
95
- urllib3==2.0.4
96
- uvicorn==0.23.1
97
- uvloop==0.17.0
98
- watchfiles==0.19.0
99
- wcwidth==0.2.6
100
- websockets==11.0.3
101
- Werkzeug==2.3.6
102
- yarl==1.9.2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
web_app/backend/run.py CHANGED
@@ -1,4 +1,4 @@
1
  from app import app
2
 
3
  if __name__ == "__main__":
4
- app.run(host="0.0.0.0")
 
1
  from app import app
2
 
3
  if __name__ == "__main__":
4
+ app.run(host="0.0.0.0", port=5000, debug=True)
web_app/frontend/package-lock.json CHANGED
The diff for this file is too large to render. See raw diff
 
web_app/frontend/package.json CHANGED
@@ -7,17 +7,27 @@
7
  "dev": "vite",
8
  "build": "vite build",
9
  "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10
- "preview": "vite preview"
 
11
  },
12
  "dependencies": {
 
 
 
 
 
 
13
  "@emotion/react": "^11.11.1",
14
  "@emotion/styled": "^11.11.0",
15
  "@mui/icons-material": "^5.14.1",
16
  "@mui/material": "^5.14.1",
17
  "axios": "^1.4.0",
18
- "esbuild": "^0.18.17",
 
 
19
  "react": "^18.2.0",
20
  "react-dom": "^18.2.0",
 
21
  "react-router-dom": "^6.14.2",
22
  "react-transition-group": "^4.4.5",
23
  "react-use": "^17.4.0"
@@ -25,11 +35,11 @@
25
  "devDependencies": {
26
  "@types/react": "^18.2.15",
27
  "@types/react-dom": "^18.2.7",
28
- "@vitejs/plugin-react": "^4.0.3",
29
  "eslint": "^8.45.0",
30
  "eslint-plugin-react": "^7.32.2",
31
  "eslint-plugin-react-hooks": "^4.6.0",
32
  "eslint-plugin-react-refresh": "^0.4.3",
33
- "vite": "^4.4.7"
34
  }
35
  }
 
7
  "dev": "vite",
8
  "build": "vite build",
9
  "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10
+ "preview": "vite preview",
11
+ "start": "npm run dev"
12
  },
13
  "dependencies": {
14
+ "@deck.gl/core": "^8.9.23",
15
+ "@deck.gl/extensions": "^8.9.23",
16
+ "@deck.gl/geo-layers": "^8.9.23",
17
+ "@deck.gl/layers": "^8.9.23",
18
+ "@deck.gl/mesh-layers": "^8.9.23",
19
+ "@deck.gl/react": "^8.9.23",
20
  "@emotion/react": "^11.11.1",
21
  "@emotion/styled": "^11.11.0",
22
  "@mui/icons-material": "^5.14.1",
23
  "@mui/material": "^5.14.1",
24
  "axios": "^1.4.0",
25
+ "esbuild": "^0.18.18",
26
+ "mapbox-gl": "^2.15.0",
27
+ "maplibre-gl": "^3.2.1",
28
  "react": "^18.2.0",
29
  "react-dom": "^18.2.0",
30
+ "react-map-gl": "^7.1.3",
31
  "react-router-dom": "^6.14.2",
32
  "react-transition-group": "^4.4.5",
33
  "react-use": "^17.4.0"
 
35
  "devDependencies": {
36
  "@types/react": "^18.2.15",
37
  "@types/react-dom": "^18.2.7",
38
+ "@vitejs/plugin-react": "^4.0.4",
39
  "eslint": "^8.45.0",
40
  "eslint-plugin-react": "^7.32.2",
41
  "eslint-plugin-react-hooks": "^4.6.0",
42
  "eslint-plugin-react-refresh": "^0.4.3",
43
+ "vite": "^4.4.8"
44
  }
45
  }
web_app/frontend/public/map1.json ADDED
The diff for this file is too large to render. See raw diff
 
web_app/frontend/src/App.jsx CHANGED
@@ -1,12 +1,12 @@
1
  import React from 'react';
2
- import Navbar from './components/Navbar';
3
  // import Footer from './components/Footer';
4
  import { Box } from '@mui/system';
5
 
6
  const App = ({ children }) => {
7
  return (
8
  <>
9
- <Navbar />
10
  <Box flexGrow={1}>
11
  {children}
12
  </Box>
 
1
  import React from 'react';
2
+ // import Navbar from './components/Navbar';
3
  // import Footer from './components/Footer';
4
  import { Box } from '@mui/system';
5
 
6
  const App = ({ children }) => {
7
  return (
8
  <>
9
+ {/* <Navbar /> */}
10
  <Box flexGrow={1}>
11
  {children}
12
  </Box>
web_app/frontend/src/AppRouter.jsx CHANGED
@@ -2,22 +2,26 @@ import React from 'react';
2
  import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
3
  import App from './App';
4
  import LandingPage from './pages/LandingPage';
5
- import ChatBot from './pages/ChatBot';
6
  import AboutPage from './pages/AboutPage';
7
  import ContactPage from './pages/ContactPage';
8
- import DashboardPage from './pages/DashboardPage';
9
  import ChatPage from './pages/ChatPage';
 
 
 
10
 
11
  const AppRouter = () => (
12
  <Router>
13
  <App>
14
  <Routes>
15
  <Route path="/" element={<LandingPage />} />
16
- <Route path="/chatbot" element={<ChatBot />} />
17
  <Route path="/about" element={<AboutPage />} />
18
  <Route path="/contact" element={<ContactPage />} />
19
  <Route path="/dashboard" element={<DashboardPage />} />
20
  <Route path="/dashboard/chat" element={<ChatPage />}/>
 
 
 
21
  </Routes>
22
  </App>
23
  </Router>
 
2
  import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
3
  import App from './App';
4
  import LandingPage from './pages/LandingPage';
 
5
  import AboutPage from './pages/AboutPage';
6
  import ContactPage from './pages/ContactPage';
7
+ import DashboardPage from './pages/DashboardPage-old';
8
  import ChatPage from './pages/ChatPage';
9
+ import ReportsPage from './pages/ReportsPage';
10
+ import CityPage from './pages/CityPage';
11
+ import ResourcesPage from './pages/ResourcesPage';
12
 
13
  const AppRouter = () => (
14
  <Router>
15
  <App>
16
  <Routes>
17
  <Route path="/" element={<LandingPage />} />
 
18
  <Route path="/about" element={<AboutPage />} />
19
  <Route path="/contact" element={<ContactPage />} />
20
  <Route path="/dashboard" element={<DashboardPage />} />
21
  <Route path="/dashboard/chat" element={<ChatPage />}/>
22
+ <Route path="/dashboard/reports" element={<ReportsPage />}/>
23
+ <Route path="/dashboard/city" element={<CityPage />}/>
24
+ <Route path="/dashboard/resources" element={<ResourcesPage />}/>
25
  </Routes>
26
  </App>
27
  </Router>
web_app/frontend/src/components/ChatHistory.jsx CHANGED
@@ -27,10 +27,10 @@ const ChatHistory = ({ chatHistory, handleFollowUp }) => {
27
  <Card
28
  sx={{
29
  my: 0,
30
- mt: index === 0 ? 6 : 2, // Conditional margin-top depending on the index
31
  mx: 2,
32
- width: '100%',
33
- maxWidth: 'calc(100% - 48px)', // Calculated max-width to provide spacing on larger screens
34
  }}
35
  >
36
  <CardContent>
 
27
  <Card
28
  sx={{
29
  my: 0,
30
+ mt: index === 0 ? 1 : 2, // Conditional margin-top depending on the index
31
  mx: 2,
32
+ // width: '100%',
33
+ // maxWidth: 'calc(100% - 48px)', // Calculated max-width to provide spacing on larger screens
34
  }}
35
  >
36
  <CardContent>
web_app/frontend/src/components/ChatInput.jsx CHANGED
@@ -17,17 +17,18 @@ const ChatInput = ({
17
  component="form"
18
  onSubmit={handleFormSubmit}
19
  sx={{
20
- position: 'fixed',
21
  bottom: 0,
22
  left: 0,
23
  right: 0,
24
- backgroundColor: '#404040',
25
  borderTop: '1px solid #DDD',
26
  py: 1,
27
  px: 2,
28
  display: 'flex',
29
  justifyContent: 'space-between',
30
  minHeight: 80,
 
31
  }}
32
  >
33
  <TextField
@@ -40,11 +41,12 @@ const ChatInput = ({
40
  rowsmax={2}
41
  variant="outlined"
42
  disabled={loading}
43
- sx={{ flexGrow: 1, maxHeight: '80%', mr: 1, ml: -1, backgroundColor: '#606060' }}
 
44
  />
45
 
46
  <Box sx={{ display: 'flex', alignItems: 'center' }}>
47
- <Button type="submit" color="primary" variant="contained" disabled={loading} sx={{ height: '100%', mr: 1 }}>
48
  {loading ? <CircularProgress size={24} /> : <PaperPlaneIcon />}
49
  </Button>
50
 
@@ -56,7 +58,7 @@ const ChatInput = ({
56
  height: '100%',
57
  width: 50,
58
  backgroundColor: grey[300],
59
- borderRadius: '4px',
60
  }}
61
  >
62
  <RefreshIcon />
 
17
  component="form"
18
  onSubmit={handleFormSubmit}
19
  sx={{
20
+ position: 'flex',
21
  bottom: 0,
22
  left: 0,
23
  right: 0,
24
+ backgroundColor: '#1D5B79',
25
  borderTop: '1px solid #DDD',
26
  py: 1,
27
  px: 2,
28
  display: 'flex',
29
  justifyContent: 'space-between',
30
  minHeight: 80,
31
+ borderRadius:'15px'
32
  }}
33
  >
34
  <TextField
 
41
  rowsmax={2}
42
  variant="outlined"
43
  disabled={loading}
44
+ sx={{ flexGrow: 1, maxHeight: '80%', mr: 1, ml: -1, backgroundColor: 'rgba(255, 255, 255, 0.8)',
45
+ borderRadius:'15px'}}
46
  />
47
 
48
  <Box sx={{ display: 'flex', alignItems: 'center' }}>
49
+ <Button type="submit" color="primary" variant="contained" disabled={loading} sx={{ backgroundColor:'#5499de' , height: '100%', mr: 1, borderRadius:'15px'}}>
50
  {loading ? <CircularProgress size={24} /> : <PaperPlaneIcon />}
51
  </Button>
52
 
 
58
  height: '100%',
59
  width: 50,
60
  backgroundColor: grey[300],
61
+ borderRadius:'15px'
62
  }}
63
  >
64
  <RefreshIcon />
web_app/frontend/src/components/Map3D-old.jsx ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, {useState, useEffect} from 'react';
2
+ import {createRoot} from 'react-dom/client';
3
+ import {Map} from 'react-map-gl';
4
+ import maplibregl from 'maplibre-gl';
5
+ import {AmbientLight, PointLight, LightingEffect} from '@deck.gl/core';
6
+ import DeckGL from '@deck.gl/react';
7
+ import {PolygonLayer} from '@deck.gl/layers';
8
+ import {TripsLayer} from '@deck.gl/geo-layers';
9
+ import { Box } from '@mui/system';
10
+
11
+
12
+ // Source data CSV, Attribution to CARTO, OpenStreetMap contributors to deck.gl trips-layer example
13
+ const DATA_URL = {
14
+ BUILDINGS:'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/buildings.json', // eslint-disable-line
15
+ TRIPS: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/trips-v7.json' // eslint-disable-line
16
+ };
17
+
18
+ const ambientLight = new AmbientLight({
19
+ color: [255, 255, 255],
20
+ intensity: 1.0
21
+ });
22
+
23
+ const pointLight = new PointLight({
24
+ color: [255, 255, 255],
25
+ intensity: 2.0,
26
+ position: [-74.05, 40.7, 8000]
27
+ });
28
+
29
+ const lightingEffect = new LightingEffect({ambientLight, pointLight});
30
+
31
+ const material = {
32
+ ambient: 0.1,
33
+ diffuse: 0.6,
34
+ shininess: 32,
35
+ specularColor: [60, 64, 70]
36
+ };
37
+
38
+ const DEFAULT_THEME = {
39
+ buildingColor: [74, 80, 87],
40
+ trailColor0: [253, 128, 93],
41
+ trailColor1: [23, 184, 190],
42
+ material,
43
+ effects: [lightingEffect]
44
+ };
45
+
46
+ const INITIAL_VIEW_STATE = {
47
+ longitude: -6.2760296,
48
+ latitude: 53.362321,
49
+ zoom: 13,
50
+ pitch: 45,
51
+ bearing: 0
52
+ };
53
+
54
+ const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json';
55
+
56
+ const landCover = [
57
+ [
58
+ [-74.0, 40.7],
59
+ [-74.02, 40.7],
60
+ [-74.02, 40.72],
61
+ [-74.0, 40.72]
62
+ ]
63
+ ];
64
+
65
+ export default function Map3D({
66
+ buildings = DATA_URL.BUILDINGS,
67
+ trips = DATA_URL.TRIPS,
68
+ trailLength = 180,
69
+ initialViewState = INITIAL_VIEW_STATE,
70
+ mapStyle = MAP_STYLE,
71
+ theme = DEFAULT_THEME,
72
+ loopLength = 1800,
73
+ animationSpeed = 1
74
+ }) {
75
+ const [time, setTime] = useState(0);
76
+ const [animation] = useState({});
77
+
78
+ const animate = () => {
79
+ setTime(t => (t + animationSpeed) % loopLength);
80
+ animation.id = window.requestAnimationFrame(animate);
81
+ };
82
+
83
+ useEffect(() => {
84
+ animation.id = window.requestAnimationFrame(animate);
85
+ return () => window.cancelAnimationFrame(animation.id);
86
+ }, [animation]);
87
+
88
+ const layers = [
89
+ new PolygonLayer({
90
+ id: 'ground',
91
+ data: landCover,
92
+ getPolygon: f => f,
93
+ stroked: false,
94
+ getFillColor: [0, 0, 0, 0]
95
+ }),
96
+ new TripsLayer({
97
+ id: 'trips',
98
+ data: trips,
99
+ getPath: d => d.path,
100
+ getTimestamps: d => d.timestamps,
101
+ getColor: d => (d.vendor === 0 ? theme.trailColor0 : theme.trailColor1),
102
+ opacity: 0.3,
103
+ widthMinPixels: 2,
104
+ rounded: true,
105
+ trailLength,
106
+ currentTime: time,
107
+
108
+ shadowEnabled: false
109
+ }),
110
+ new PolygonLayer({
111
+ id: 'buildings',
112
+ data: buildings,
113
+ extruded: true,
114
+ wireframe: false,
115
+ opacity: 0.5,
116
+ getPolygon: f => f.polygon,
117
+ getElevation: f => f.height,
118
+ getFillColor: theme.buildingColor,
119
+ material: theme.material
120
+ })
121
+ ];
122
+
123
+ return (
124
+ <Box sx={{ width: '100%', height: '100%', position: 'relative', borderRadius: '15px', overflow: 'hidden'}}>
125
+ <DeckGL
126
+ style={{ width: '100%', height: '100%', position: 'absolute'}}
127
+ layers={layers}
128
+ effects={theme.effects}
129
+ initialViewState={initialViewState}
130
+ controller={true}
131
+ >
132
+ <Map reuseMaps mapLib={maplibregl} mapStyle={mapStyle} preventStyleDiffing={true} attributionControl={false} />
133
+ </DeckGL>
134
+ </Box>
135
+ );
136
+ }
137
+
web_app/frontend/src/components/Map3D.jsx ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, {useState, useEffect} from 'react';
2
+ import {createRoot} from 'react-dom/client';
3
+ import {Map} from 'react-map-gl';
4
+ import maplibregl from 'maplibre-gl';
5
+ import {AmbientLight, PointLight, LightingEffect} from '@deck.gl/core';
6
+ import DeckGL from '@deck.gl/react';
7
+ import {PolygonLayer} from '@deck.gl/layers';
8
+ import {TripsLayer} from '@deck.gl/geo-layers';
9
+ import { Box } from '@mui/system';
10
+
11
+
12
+ // Source data CSV, Attribution to CARTO, OpenStreetMap contributors to deck.gl trips-layer example
13
+ const DATA_URL = {
14
+ // BUILDINGS:'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/buildings.json', // eslint-disable-line
15
+ BUILDINGS: '/map1.json'
16
+ };
17
+
18
+ const ambientLight = new AmbientLight({
19
+ color: [255, 255, 255],
20
+ intensity: 6.0
21
+ });
22
+
23
+ const pointLight = new PointLight({
24
+ color: [255, 255, 255],
25
+ intensity: 1.0,
26
+ position: [-6.4741164,
27
+ 53.4622087, 8000]
28
+ });
29
+
30
+ // const lightingEffect = new LightingEffect({ambientLight, pointLight});
31
+ const lightingEffect = new LightingEffect({ambientLight, pointLight});
32
+
33
+
34
+ const material = {
35
+ ambient: 0.1,
36
+ diffuse: 0.6,
37
+ shininess: 32,
38
+ specularColor: [60, 64, 70]
39
+ };
40
+
41
+ const DEFAULT_THEME = {
42
+ buildingColor: [51, 204, 255],
43
+ trailColor0: [253, 128, 93],
44
+ trailColor1: [23, 184, 190],
45
+ material,
46
+ effects: [lightingEffect]
47
+ };
48
+
49
+ const INITIAL_VIEW_STATE = {
50
+ longitude: -6.269218,
51
+ latitude: 53.342505,
52
+ zoom: 14.64,
53
+ pitch: 59.31,
54
+ bearing: 0
55
+ };
56
+
57
+ const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json';
58
+
59
+ const landCover = [
60
+ [
61
+ [-74.0, 40.7],
62
+ [-74.02, 40.7],
63
+ [-74.02, 40.72],
64
+ [-74.0, 40.72]
65
+ ]
66
+ ];
67
+
68
+ export default function Map3D({
69
+ buildings = DATA_URL.BUILDINGS,
70
+ initialViewState = INITIAL_VIEW_STATE,
71
+ mapStyle = MAP_STYLE,
72
+ theme = DEFAULT_THEME,
73
+ }) {
74
+ const [buildingData, setBuildingData] = useState(null);
75
+ const [viewState, setViewState] = useState(initialViewState); // Add this line to manage view state
76
+
77
+ useEffect(() => {
78
+ fetch(buildings)
79
+ .then((response) => response.json())
80
+ .then((json) => {
81
+ const allData = json.datasets[0].data.allData.map(([feature]) => feature);
82
+ setBuildingData(allData);
83
+ })
84
+ .catch((error) => {
85
+ console.error('Error fetching buildings data:', error);
86
+ });
87
+ }, [buildings]);
88
+
89
+ if (!buildingData) {
90
+ return <div>Loading...</div>;
91
+ }
92
+
93
+ const layers = [
94
+ new PolygonLayer({
95
+ id: 'ground',
96
+ data: landCover,
97
+ getPolygon: f => f,
98
+ stroked: false,
99
+ getFillColor: [0, 0, 0, 0]
100
+ }),
101
+ new PolygonLayer({
102
+ id: 'buildings',
103
+ data: buildingData,
104
+ extruded: true,
105
+ wireframe: false,
106
+ opacity: 0.5,
107
+ getPolygon: (f) => f.geometry.coordinates[0][0],
108
+ getElevation: (f) => f.properties.Height_Met,
109
+ getFillColor: theme.buildingColor,
110
+ material: theme.material,
111
+ })
112
+ ];
113
+
114
+ const onViewStateChange = ({ viewState }) => {
115
+ setViewState(viewState);
116
+ };
117
+
118
+ return (
119
+ <Box sx={{ width: '100%', height: '100%', position: 'relative', borderRadius: '15px', overflow: 'hidden'}}>
120
+ <DeckGL
121
+ style={{ width: '100%', height: '100%', position: 'absolute'}}
122
+ layers={layers}
123
+ effects={theme.effects}
124
+ initialViewState={initialViewState}
125
+ controller={true}
126
+ viewState={viewState}
127
+ onViewStateChange={onViewStateChange}
128
+ >
129
+ <Map reuseMaps mapLib={maplibregl} mapStyle={mapStyle} preventStyleDiffing={true} attributionControl={false} />
130
+ </DeckGL>
131
+ <div
132
+ style={{
133
+ position: 'absolute',
134
+ bottom: '10px',
135
+ right: '10px',
136
+ color: 'white',
137
+ background: 'rgba(0, 0, 0, 0.5)',
138
+ padding: '5px',
139
+ borderRadius: '5px',
140
+ }}
141
+ >
142
+ Longitude: {viewState.longitude.toFixed(6)}
143
+ <br />
144
+ Latitude: {viewState.latitude.toFixed(6)}
145
+ <br />
146
+ Zoom: {viewState.zoom.toFixed(2)}
147
+ <br />
148
+ Pitch: {viewState.pitch.toFixed(2)}
149
+ <br />
150
+ Bearing: {viewState.bearing.toFixed(2)}
151
+ </div>
152
+ </Box>
153
+ );
154
+ }
155
+
web_app/frontend/src/components/Navbar.jsx CHANGED
@@ -5,8 +5,7 @@ import { Menu, Close } from '@mui/icons-material';
5
  import { Link, useLocation } from 'react-router-dom';
6
  import './Navbar.css'
7
 
8
- // Define the Navbar component
9
- const Navbar = () => {
10
  const [open, setOpen] = useState(false);
11
  const location = useLocation();
12
  const [currentPage, setCurrentPage] = useState('');
@@ -22,24 +21,21 @@ const Navbar = () => {
22
  };
23
 
24
  return (
25
- // AppBar component to create the top navigation bar
26
- <AppBar position="absolute" style={{ backgroundColor: 'transparent', boxShadow: 'none' }}>
27
- {/* Toolbar component to contain the navigation content */}
28
- <Toolbar style={{ display: 'flex', justifyContent: 'space-between', margin: '10px', borderRadius: '15px', backgroundColor: 'rgba(255, 255, 255, 0.1)' }}>
29
- {/* Link to the home page with a logo and text */}
30
  <Link className="logo" to="/" style={{ textDecoration: 'none', padding: '10px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
31
- <Typography style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold' }}>
32
  LuminLab
33
  </Typography>
34
- <Divider orientation="vertical" flexItem sx={{ bgcolor: 'white', width: '1px', mx: 2 }}/>
35
- <Typography style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold' }}>
36
  {currentPage}
37
  </Typography>
38
  </Link>
39
 
40
  <Box display={{ xs: 'block', sm: 'none' }}>
41
  <IconButton
42
- color="inherit"
43
  onClick={handleToggle}
44
  >
45
  {open ? <Close /> : <Menu />}
@@ -58,29 +54,29 @@ const Navbar = () => {
58
  marginTop: '76px',
59
  marginRight: '10px',
60
  marginLeft: '10px',
61
- backgroundColor: '#F6FDFF',
62
  boxShadow: '1',
63
- color:'#4568dc'
64
  }
65
  }}
66
  transitionDuration={200}
67
  TransitionComponent={Fade}
68
  >
69
- <MenuItem onClick={() => setOpen(false)} component={Link} to="/about" style={{ fontWeight: 'bold' }}>About</MenuItem>
70
- <MenuItem onClick={() => setOpen(false)} component={Link} to="/contact" style={{ fontWeight: 'bold' }}>Contact</MenuItem>
71
  <MenuItem onClick={() => setOpen(false)} component={Link} to="/dashboard" style={{ fontWeight: 'bold' }}>Dashboard</MenuItem>
72
  {/* <MenuItem onClick={() => setOpen(false)} component={Link} to="/team" style={{ fontWeight: 'bold' }}>Team</MenuItem> */}
73
  </Drawer>
74
  </Box>
75
 
76
  <Box display={{ sm: 'flex', xs: 'none' }}>
77
- <Button className="nav-link" color="inherit" component={Link} to="/about" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px'}}>
78
  About
79
  </Button>
80
- <Button className="nav-link" color="inherit" component={Link} to="/contact" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px'}}>
81
- Contact
82
  </Button>
83
- <Button className="nav-link" color="inherit" component={Link} to="/dashboard" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px'}}>
84
  Dashboard
85
  </Button>
86
  {/* <Button className="nav-link" color="inherit" component={Link} to="/team" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold'}}>
@@ -92,6 +88,5 @@ const Navbar = () => {
92
  );
93
  };
94
 
95
- // Export the Navbar component as default
96
  export default Navbar;
97
 
 
5
  import { Link, useLocation } from 'react-router-dom';
6
  import './Navbar.css'
7
 
8
+ const Navbar = ({bgColor = 'rgba(255, 255, 255, 0.1)', fontColor = 'white'}) => {
 
9
  const [open, setOpen] = useState(false);
10
  const location = useLocation();
11
  const [currentPage, setCurrentPage] = useState('');
 
21
  };
22
 
23
  return (
24
+ <AppBar position="absolute" style={{ backgroundColor:'transparent', boxShadow: 'none' }}>
25
+ <Toolbar style={{ display: 'flex', justifyContent: 'space-between', margin: '10px', borderRadius: '15px', backgroundColor:bgColor }}>
 
 
 
26
  <Link className="logo" to="/" style={{ textDecoration: 'none', padding: '10px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
27
+ <Typography style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', color: fontColor}}>
28
  LuminLab
29
  </Typography>
30
+ <Divider orientation="vertical" flexItem sx={{ bgcolor: fontColor, width: '1px', mx: 2 }}/>
31
+ <Typography style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', color: fontColor}}>
32
  {currentPage}
33
  </Typography>
34
  </Link>
35
 
36
  <Box display={{ xs: 'block', sm: 'none' }}>
37
  <IconButton
38
+ color={fontColor}
39
  onClick={handleToggle}
40
  >
41
  {open ? <Close /> : <Menu />}
 
54
  marginTop: '76px',
55
  marginRight: '10px',
56
  marginLeft: '10px',
57
+ backgroundColor: bgColor,
58
  boxShadow: '1',
59
+ color: fontColor
60
  }
61
  }}
62
  transitionDuration={200}
63
  TransitionComponent={Fade}
64
  >
65
+ <MenuItem onClick={() => setOpen(false)} component={Link} to="/about" style={{ fontWeight: 'bold'}}>About</MenuItem>
66
+ <MenuItem onClick={() => setOpen(false)} component={Link} to="/contact" style={{ fontWeight: 'bold' }}>Client Communications</MenuItem>
67
  <MenuItem onClick={() => setOpen(false)} component={Link} to="/dashboard" style={{ fontWeight: 'bold' }}>Dashboard</MenuItem>
68
  {/* <MenuItem onClick={() => setOpen(false)} component={Link} to="/team" style={{ fontWeight: 'bold' }}>Team</MenuItem> */}
69
  </Drawer>
70
  </Box>
71
 
72
  <Box display={{ sm: 'flex', xs: 'none' }}>
73
+ <Button className="nav-link" color="inherit" component={Link} to="/about" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px', color: fontColor}}>
74
  About
75
  </Button>
76
+ <Button className="nav-link" color="inherit" component={Link} to="/contact" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px', color: fontColor}}>
77
+ Client Communications
78
  </Button>
79
+ <Button className="nav-link" color="inherit" component={Link} to="/dashboard" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px', color: fontColor}}>
80
  Dashboard
81
  </Button>
82
  {/* <Button className="nav-link" color="inherit" component={Link} to="/team" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold'}}>
 
88
  );
89
  };
90
 
 
91
  export default Navbar;
92
 
web_app/frontend/src/components/StartCard.jsx CHANGED
@@ -30,21 +30,24 @@ const StartCard = ({ inputText }) => {
30
  <CardContent>
31
  {/* Typography for the title */}
32
  <Typography
33
- variant="h6"
34
- sx={{
35
- textAlign: 'center',
36
- WebkitBackgroundClip: 'text',
37
- WebkitTextFillColor: 'transparent',
38
- backgroundImage:
39
- 'linear-gradient(90deg, #F46737 0%, #FFA53C 30%, #FBFF3C 60%, #49C628 100%)', // Gradient text effect
40
- pb: 0, // Remove bottom padding
41
- mb: 0, // Remove bottom margin
42
- mr: -10, // Adjust right margin
43
- }}
 
 
 
44
  >
45
- Unsure Where to Start?
46
  </Typography>
47
- </CardContent>
48
  </Card>
49
  </Grid>
50
  {/* Render the ButtonGrid component */}
 
30
  <CardContent>
31
  {/* Typography for the title */}
32
  <Typography
33
+ variant="h6"
34
+ sx={{
35
+ textAlign: 'center',
36
+ // You can add or adjust font-related styles if necessary, for example:
37
+ // fontFamily: 'Your preferred font-family here',
38
+ // fontWeight: 'normal',
39
+ // fontSize: '1rem',
40
+ // color: 'black', // or any other color you prefer
41
+ pl: -100,
42
+ pr: 12,
43
+ pb: 0, // Remove bottom padding
44
+ mb: 0, // Remove bottom margin
45
+ mr: -10, // Adjust right margin
46
+ }}
47
  >
48
+ Unsure Where to Start?
49
  </Typography>
50
+ </CardContent>
51
  </Card>
52
  </Grid>
53
  {/* Render the ButtonGrid component */}
web_app/frontend/src/components/emailService.jsx ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import axios from 'axios';
2
+
3
+ const handleSendEmail = async (email) => {
4
+ try {
5
+ // Fetch chatHistory from localStorage
6
+ const storedChatHistory = localStorage.getItem('chatHistory');
7
+
8
+ // If it doesn't exist or is empty, return
9
+ if (!storedChatHistory || storedChatHistory.length === 0) {
10
+ console.error("Chat history is empty.");
11
+ return;
12
+ }
13
+
14
+ const response = await axios.post('http://localhost:5000/exportChat', {
15
+ email: email,
16
+ chatHistory: JSON.parse(storedChatHistory) // Convert the stringified JSON to an object
17
+ });
18
+
19
+ console.log(response.data);
20
+
21
+ } catch (error) {
22
+ console.error("Error sending email:", error);
23
+ }
24
+ };
25
+
26
+ export default handleSendEmail;
web_app/frontend/src/hooks/useChat.js CHANGED
@@ -1,6 +1,5 @@
1
  import { useState } from 'react';
2
  import axios from 'axios';
3
-
4
  /**
5
  * Custom hook for managing chat-related state and functionality.
6
  * It handles input text, chat history, loading state, history navigation, and form submission.
@@ -24,8 +23,8 @@ export default function useChatHandler() {
24
  setLoading(true);
25
  let success = false;
26
  try {
27
- const sendTextResponse = await axios.post('http://localhost:5001/sendText', { text });
28
- const sendQuestionsResponse = await axios.post('http://localhost:5001/sendQuestions', { text });
29
 
30
  const newChatItem = {
31
  question: text,
@@ -60,18 +59,18 @@ export default function useChatHandler() {
60
  setChatHistory([...chatHistory]);
61
 
62
  try {
63
- const response = await axios.post('http://localhost:5001/sendText', {
64
  text: chatHistory[chatItemIndex].followUps[followUpIndex].text
65
  });
66
 
67
- // update the response and loading state
68
  chatHistory[chatItemIndex].followUps[followUpIndex].response = response.data.output;
69
  chatHistory[chatItemIndex].followUps[followUpIndex].loading = false;
70
 
71
- // Here, you might also want to get new follow-up questions based on the follow-up response.
72
- const sendQuestionsResponse = await axios.post('http://localhost:5001/sendQuestions', { text: response.data.output });
73
 
74
- // You can then add these to your followUp array.
75
  const newFollowUps = sendQuestionsResponse.data.output.followUps.map(followUp => ({
76
  text: followUp,
77
  response: null,
@@ -152,4 +151,3 @@ export default function useChatHandler() {
152
  };
153
 
154
  }
155
-
 
1
  import { useState } from 'react';
2
  import axios from 'axios';
 
3
  /**
4
  * Custom hook for managing chat-related state and functionality.
5
  * It handles input text, chat history, loading state, history navigation, and form submission.
 
23
  setLoading(true);
24
  let success = false;
25
  try {
26
+ const sendTextResponse = await axios.post('http://127.0.0.1:5000/sendText', { text });
27
+ const sendQuestionsResponse = await axios.post('http://127.0.0.1:5000/sendQuestions', { text });
28
 
29
  const newChatItem = {
30
  question: text,
 
59
  setChatHistory([...chatHistory]);
60
 
61
  try {
62
+ const response = await axios.post('http://127.0.0.1:5000/sendText', {
63
  text: chatHistory[chatItemIndex].followUps[followUpIndex].text
64
  });
65
 
66
+ // Update the response and loading state
67
  chatHistory[chatItemIndex].followUps[followUpIndex].response = response.data.output;
68
  chatHistory[chatItemIndex].followUps[followUpIndex].loading = false;
69
 
70
+ // Get new follow-up questions based on the follow-up response.
71
+ const sendQuestionsResponse = await axios.post('http://127.0.0.1:5000/sendQuestions', { text: response.data.output });
72
 
73
+ // Add to FollowUp array
74
  const newFollowUps = sendQuestionsResponse.data.output.followUps.map(followUp => ({
75
  text: followUp,
76
  response: null,
 
151
  };
152
 
153
  }
 
web_app/frontend/src/pages/AboutPage.jsx CHANGED
@@ -2,23 +2,25 @@ import React from 'react';
2
  import { Container, Typography, Button, Grid, styled, Paper} from '@mui/material';
3
  import { Link } from 'react-router-dom';
4
  import { Box } from '@mui/system';
 
5
  import Footer from '../components/Footer';
6
 
7
  const AboutPage = () => {
8
  return (
9
  <>
 
10
  <Box
11
- sx={{
12
- position: 'absolute',
13
- top: 0,
14
- left: 0,
15
- minHeight: '100vh',
16
- width: '100%',
17
- backgroundImage: 'linear-gradient(to bottom, #4568dc, #b06ab3)',
18
- backgroundRepeat: 'no-repeat',
19
- backgroundSize: 'cover',
20
- zIndex: -1
21
- }}
22
  />
23
  <Box sx={{
24
  position: 'absolute',
 
2
  import { Container, Typography, Button, Grid, styled, Paper} from '@mui/material';
3
  import { Link } from 'react-router-dom';
4
  import { Box } from '@mui/system';
5
+ import Navbar from '../components/Navbar';
6
  import Footer from '../components/Footer';
7
 
8
  const AboutPage = () => {
9
  return (
10
  <>
11
+ <Navbar />
12
  <Box
13
+ sx={{
14
+ position: 'absolute',
15
+ top: 0,
16
+ left: 0,
17
+ minHeight: '100vh',
18
+ width: '100%',
19
+ backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
20
+ backgroundRepeat: 'no-repeat',
21
+ backgroundSize: 'cover',
22
+ zIndex: -1
23
+ }}
24
  />
25
  <Box sx={{
26
  position: 'absolute',
web_app/frontend/src/pages/ChatBot.jsx DELETED
@@ -1,76 +0,0 @@
1
- // Import required dependencies and components
2
- import React, { useState} from 'react';
3
- import { Box } from '@mui/material';
4
- import useChatHandler from '../hooks/useChat.js';
5
- import ChatHistory from '../components/ChatHistory.jsx';
6
- import ChatInput from '../components/ChatInput.jsx';
7
- import StartCard from '../components/StartCard.jsx';
8
-
9
- // The ChatBot component which manages and displays the chat feature
10
- function ChatBot() {
11
- // State to hold the current index in chat history navigation, initialized to -1
12
- const [historyIndex, setHistoryIndex] = useState(-1);
13
- // State to hold whether we are currently navigating through history, initialized to false
14
- const [isHistoryNavigation, setIsHistoryNavigation] = useState(false);
15
-
16
- // Hook to handle chat logic, returns various state and handler functions
17
- const {
18
- inputText,
19
- handleInputChange,
20
- chatHistory,
21
- loading,
22
- handleSubmit,
23
- handleKeyDown,
24
- clearChatHistory,
25
- handleFollowUp, // include handleFollowUp here
26
- } = useChatHandler();
27
-
28
-
29
- // Function to submit a message, takes an event and prevents the page from refreshing
30
- const handleFormSubmit = (e) => {
31
- e.preventDefault();
32
- handleSubmit(inputText); // Pass the current input text to the handleSubmit function
33
- };
34
-
35
- return (
36
- <>
37
- {/* Container for the gradient background */}
38
- <Box
39
- sx={{
40
- position: 'absolute',
41
- top: 0,
42
- left: 0,
43
- minHeight: '100vh',
44
- width: '100%',
45
- backgroundImage: 'linear-gradient(to bottom, #4568dc, #b06ab3)',
46
- backgroundRepeat: 'no-repeat',
47
- backgroundSize: 'cover',
48
- zIndex: -1
49
- }}
50
- />
51
-
52
- {/* Container for the chat history */}
53
- <Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '100vh', mt: 6 }}>
54
- {/* Display the StartCard component only when the chat history is empty and the chat is not loading */}
55
- {chatHistory.length === 0 && !loading && <StartCard inputText={inputText} />}
56
-
57
- {/* Chat history component, displays past messages */}
58
- <ChatHistory chatHistory={chatHistory} handleFollowUp={handleFollowUp} />
59
- </Box>
60
-
61
- {/* Chat input component, where users type and submit their messages */}
62
- <ChatInput
63
- inputText={inputText}
64
- handleInputChange={handleInputChange}
65
- handleKeyDown={handleKeyDown}
66
- handleFormSubmit={handleFormSubmit}
67
- loading={loading}
68
- clearChatHistory={clearChatHistory}
69
- />
70
- </>
71
- );
72
- }
73
-
74
- // Export the ChatBot component
75
- export default ChatBot;
76
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
web_app/frontend/src/pages/ChatPage.jsx CHANGED
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText } from '@mui/material';
3
  import { Box } from '@mui/system';
4
  import { Link, Outlet } from 'react-router-dom';
5
  import ChatIcon from '@mui/icons-material/Chat';
@@ -7,6 +7,27 @@ import PieChartIcon from '@mui/icons-material/PieChart';
7
  import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
8
  import BookIcon from '@mui/icons-material/Book';
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  const ChatPage = () => {
11
 
12
  const services = [
@@ -16,74 +37,176 @@ const ChatPage = () => {
16
  { title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
17
  ];
18
 
19
- const menuOptions = ["Settings", "Profile", "Sign out"];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  return (
22
  <>
23
- <Box
24
- sx={{
25
- position: 'absolute',
26
- top: 0,
27
- left: 0,
28
- minHeight: '100vh',
29
- width: '100%',
30
- backgroundImage: 'linear-gradient(to bottom, #4568dc, #b06ab3)',
31
- backgroundRepeat: 'no-repeat',
32
- backgroundSize: 'cover',
33
- zIndex: -1
34
- }}
35
- />
36
- <Box
37
- sx={{
38
- position: 'absolute',
39
- top: '84px',
40
- left: '10px',
41
- right: '10px',
42
- height: '85vh',
43
- backgroundColor:'transparent',
44
- borderRadius:'15px',
45
- }}
46
- >
 
47
  <Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
48
  <Grid item xs={3}>
49
- <Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
50
- <List sx={{backgroundColor:"white", borderRadius:"15px"}}>
 
 
 
 
 
 
 
 
 
 
 
 
51
  {menuOptions.map((option, index) => (
52
- <ListItem button key={index}>
53
- <ListItemText primary={option} />
 
 
 
54
  </ListItem>
55
  ))}
56
  </List>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  <List
58
- sx={{
59
  textAlign: 'center',
60
  backgroundColor:"white",
61
  borderRadius:"15px",
62
  }}
63
  >
64
  <ListItem button>
65
- <ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
66
  </ListItem>
67
  </List>
68
-
69
-
70
  </Box>
71
  </Grid>
72
- <Grid container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
73
- <Box sx={{
74
- borderRadius: '15px',
75
- p: 2,
76
- flexGrow: 1,
77
- backgroundColor: 'rgba(255, 255, 255, 0.8)',
78
- boxSizing: 'border-box'
79
- }}>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  </Box>
81
  </Grid>
82
  </Grid>
83
  </Box>
84
- <Outlet />
85
- </>
86
- );
87
  };
88
 
89
  export default ChatPage;
 
1
+ import React, { useState } from 'react';
2
+ import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
3
  import { Box } from '@mui/system';
4
  import { Link, Outlet } from 'react-router-dom';
5
  import ChatIcon from '@mui/icons-material/Chat';
 
7
  import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
8
  import BookIcon from '@mui/icons-material/Book';
9
 
10
+ import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
11
+ import SettingsIcon from '@mui/icons-material/Settings';
12
+ import PersonIcon from '@mui/icons-material/Person';
13
+ import ExitToAppIcon from '@mui/icons-material/ExitToApp';
14
+ import SendIcon from '@mui/icons-material/Send';
15
+
16
+
17
+ import Navbar from '../components/Navbar';
18
+
19
+ import useChatHandler from '../hooks/useChat.js';
20
+
21
+ import ChatHistory from '../components/ChatHistory';
22
+ import ChatInput from '../components/ChatInput';
23
+ import StartCard from '../components/StartCard';
24
+ import handleSendEmail from '../components/emailService';
25
+
26
+ import './scrollbar.css';
27
+
28
+ import axios from 'axios';
29
+
30
+
31
  const ChatPage = () => {
32
 
33
  const services = [
 
37
  { title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
38
  ];
39
 
40
+ const handleSendEmail = async (email) => {
41
+ try {
42
+ const response = await axios.post('http://localhost:5000/exportChat', {
43
+ email: email
44
+ });
45
+
46
+ // You can handle the response here if needed.
47
+ console.log(response.data);
48
+
49
+ } catch (error) {
50
+ console.error("Error sending email:", error);
51
+ }
52
+ };
53
+
54
+ const menuOptions = [
55
+ { title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
56
+ { title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
57
+ { title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
58
+ { title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
59
+ ];
60
+
61
+ const [historyIndex, setHistoryIndex] = useState(-1);
62
+ const [isHistoryNavigation, setIsHistoryNavigation] = useState(false);
63
 
64
+ const {
65
+ inputText,
66
+ handleInputChange,
67
+ chatHistory,
68
+ loading,
69
+ handleSubmit,
70
+ handleKeyDown,
71
+ clearChatHistory,
72
+ handleFollowUp,
73
+ } = useChatHandler();
74
+
75
+ const handleFormSubmit = (e) => {
76
+ e.preventDefault();
77
+ handleSubmit(inputText);
78
+ };
79
+
80
  return (
81
  <>
82
+ <Navbar />
83
+ <Box
84
+ sx={{
85
+ position: 'absolute',
86
+ top: 0,
87
+ left: 0,
88
+ minHeight: '100vh',
89
+ width: '100%',
90
+ backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
91
+ backgroundRepeat: 'no-repeat',
92
+ backgroundSize: 'cover',
93
+ zIndex: -1
94
+ }}
95
+ />
96
+ <Box
97
+ sx={{
98
+ position: 'absolute',
99
+ top: '84px',
100
+ left: '10px',
101
+ right: '10px',
102
+ height: '85vh',
103
+ backgroundColor:'transparent',
104
+ borderRadius:'15px',
105
+ }}
106
+ >
107
  <Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
108
  <Grid item xs={3}>
109
+ <Box
110
+ sx={{
111
+ borderRadius: '15px',
112
+ p:2,
113
+ marginRight:'10px',
114
+ height:'calc(100%)',
115
+ backgroundColor: 'rgba(255, 255, 255, 0.7)',
116
+ boxSizing: 'border-box',
117
+ display: 'flex',
118
+ flexDirection: 'column',
119
+ justifyContent: 'space-between'
120
+ }}
121
+ >
122
+ <List sx={{backgroundColor:"white", borderRadius:"15px", mb: 2}}>
123
  {menuOptions.map((option, index) => (
124
+ <ListItem button key={index} component={Link} to={option.link}>
125
+ <ListItemIcon>
126
+ {option.icon}
127
+ </ListItemIcon>
128
+ <ListItemText primary={option.title} />
129
  </ListItem>
130
  ))}
131
  </List>
132
+ <Box
133
+ sx={{
134
+ display: 'flex',
135
+ flexDirection: 'column',
136
+ alignItems: 'flex-start',
137
+ p:1,
138
+ backgroundColor:'white',
139
+ borderRadius: '15px',
140
+ marginBottom: 'auto' // Pushes items below it to the bottom
141
+ }}
142
+ >
143
+ <Typography variant="body2" sx={{fontWeight: 'bold', mb: 1, paddingLeft: '3px'}}>
144
+ Export chat as PDF
145
+ </Typography>
146
+ <Box sx={{width: '100%', display: 'flex', alignItems: 'center'}}>
147
+ <input
148
+ type="email"
149
+ placeholder="Enter your email"
150
+ style={{
151
+ flexGrow: 1,
152
+ padding: '8px 12px',
153
+ border: '1px solid #ccc',
154
+ borderRadius: '5px',
155
+ marginRight: '10px'
156
+ }}
157
+ />
158
+ <IconButton color="primary" onClick={() => handleSendEmail(document.querySelector('input[type="email"]').value)}>
159
+ <SendIcon />
160
+ </IconButton>
161
+ </Box>
162
+ </Box>
163
  <List
164
+ sx={{
165
  textAlign: 'center',
166
  backgroundColor:"white",
167
  borderRadius:"15px",
168
  }}
169
  >
170
  <ListItem button>
171
+ <ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
172
  </ListItem>
173
  </List>
 
 
174
  </Box>
175
  </Grid>
176
+
177
+
178
+ <Grid item container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
179
+ <Box sx={{
180
+ borderRadius: '15px',
181
+ p: 2,
182
+ marginLeft: '10px',
183
+ flexGrow: 1,
184
+ backgroundColor: 'rgba(255, 255, 255, 0.8)',
185
+ boxSizing: 'border-box',
186
+ display: 'flex', // Make this a flex container
187
+ flexDirection: 'column' // Column direction
188
+ }}>
189
+ <Box sx={{ flexGrow: 1, overflow: 'auto' }} className="custom-scrollbar">
190
+ {chatHistory.length === 0 && !loading && <StartCard inputText={inputText} />}
191
+ <ChatHistory chatHistory={chatHistory} handleFollowUp={handleFollowUp} />
192
+ </Box>
193
+ <Box sx={{ mt:'10px' }}>
194
+ <ChatInput
195
+ inputText={inputText}
196
+ handleInputChange={handleInputChange}
197
+ handleKeyDown={handleKeyDown}
198
+ handleFormSubmit={handleFormSubmit}
199
+ loading={loading}
200
+ clearChatHistory={clearChatHistory}
201
+ />
202
+ </Box>
203
  </Box>
204
  </Grid>
205
  </Grid>
206
  </Box>
207
+ <Outlet />
208
+ </>
209
+ );
210
  };
211
 
212
  export default ChatPage;
web_app/frontend/src/pages/CityPage.jsx ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useEffect, useState } from 'react';
2
+ import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
3
+ import { Box } from '@mui/system';
4
+ import { Link, Outlet } from 'react-router-dom';
5
+ import ChatIcon from '@mui/icons-material/Chat';
6
+ import PieChartIcon from '@mui/icons-material/PieChart';
7
+ import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
8
+ import MapIcon from '@mui/icons-material/Map';
9
+ import BookIcon from '@mui/icons-material/Book';
10
+
11
+ import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
12
+ import SettingsIcon from '@mui/icons-material/Settings';
13
+ import PersonIcon from '@mui/icons-material/Person';
14
+ import ExitToAppIcon from '@mui/icons-material/ExitToApp';
15
+
16
+ import Navbar from '../components/Navbar';
17
+ import Map3D from '../components/Map3D';
18
+
19
+
20
+ const CityPage = () => {
21
+
22
+ const services = [
23
+ { title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
24
+ { title: 'Statistics and Charts', link: '/dashboard/stats', icon: <PieChartIcon style={{ fontSize: 60 }} /> },
25
+ { title: '3D Models', link: '/dashboard/3dmodels', icon: <ThreeDRotationIcon style={{ fontSize: 60 }} /> },
26
+ { title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
27
+ ];
28
+
29
+ const menuOptions = [
30
+ { title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
31
+ { title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
32
+ { title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
33
+ { title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
34
+ ];
35
+
36
+ return (
37
+ <>
38
+ <Navbar />
39
+ <Box
40
+ sx={{
41
+ position: 'absolute',
42
+ top: 0,
43
+ left: 0,
44
+ minHeight: '100vh',
45
+ width: '100%',
46
+ backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
47
+ backgroundRepeat: 'no-repeat',
48
+ backgroundSize: 'cover',
49
+ zIndex: -1
50
+ }}
51
+ />
52
+ <Box
53
+ sx={{
54
+ position: 'absolute',
55
+ top: '84px',
56
+ left: '10px',
57
+ right: '10px',
58
+ height: '85vh',
59
+ backgroundColor:'transparent',
60
+ borderRadius:'15px',
61
+ }}
62
+ >
63
+ <Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
64
+ <Grid item xs={3}>
65
+ <Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
66
+ <List sx={{backgroundColor:"white", borderRadius:"15px"}}>
67
+ {menuOptions.map((option, index) => (
68
+ <ListItem button key={index} component={Link} to={option.link}>
69
+ <ListItemIcon>
70
+ {option.icon}
71
+ </ListItemIcon>
72
+ <ListItemText primary={option.title} />
73
+ </ListItem>
74
+ ))}
75
+ </List>
76
+ <List
77
+ sx={{
78
+ textAlign: 'center',
79
+ backgroundColor:"white",
80
+ borderRadius:"15px",
81
+ }}
82
+ >
83
+ <ListItem button>
84
+ <ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
85
+ </ListItem>
86
+ </List>
87
+ </Box>
88
+ </Grid>
89
+ <Grid item container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
90
+ <Box sx={{
91
+ borderRadius: '15px',
92
+ p: 2,
93
+ marginLeft: '10px',
94
+ flexGrow: 1,
95
+ backgroundColor: 'rgba(255, 255, 255, 0.8)',
96
+ boxSizing: 'border-box',
97
+ display: 'flex',
98
+ width: '100%',
99
+ height: '100%',
100
+ }}>
101
+ <Map3D />
102
+ </Box>
103
+ </Grid>
104
+ </Grid>
105
+ </Box>
106
+ <Outlet />
107
+ </>
108
+ );
109
+
110
+ }
111
+ export default CityPage;
112
+
web_app/frontend/src/pages/ContactPage.jsx CHANGED
@@ -2,23 +2,25 @@ import React from 'react';
2
  import { Container, Typography, Button } from '@mui/material';
3
  import { Link } from 'react-router-dom';
4
  import { Box } from '@mui/system';
 
5
  import Footer from '../components/Footer';
6
 
7
  const ContactPage = () => {
8
  return (
9
  <>
 
10
  <Box
11
- sx={{
12
- position: 'absolute',
13
- top: 0,
14
- left: 0,
15
- minHeight: '100vh',
16
- width: '100%',
17
- backgroundImage: 'linear-gradient(to bottom, #4568dc, #b06ab3)',
18
- backgroundRepeat: 'no-repeat',
19
- backgroundSize: 'cover',
20
- zIndex: -1
21
- }}
22
  />
23
  <Box sx={{
24
  position: 'absolute',
 
2
  import { Container, Typography, Button } from '@mui/material';
3
  import { Link } from 'react-router-dom';
4
  import { Box } from '@mui/system';
5
+ import Navbar from '../components/Navbar';
6
  import Footer from '../components/Footer';
7
 
8
  const ContactPage = () => {
9
  return (
10
  <>
11
+ <Navbar />
12
  <Box
13
+ sx={{
14
+ position: 'absolute',
15
+ top: 0,
16
+ left: 0,
17
+ minHeight: '100vh',
18
+ width: '100%',
19
+ backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
20
+ backgroundRepeat: 'no-repeat',
21
+ backgroundSize: 'cover',
22
+ zIndex: -1
23
+ }}
24
  />
25
  <Box sx={{
26
  position: 'absolute',
web_app/frontend/src/pages/DashboardPage-new.jsx ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useEffect, useState } from 'react';
2
+ import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText } from '@mui/material';
3
+ import { Box } from '@mui/system';
4
+ import { Link } from 'react-router-dom';
5
+ import ChatIcon from '@mui/icons-material/Chat';
6
+ import PieChartIcon from '@mui/icons-material/PieChart';
7
+ import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
8
+ import BookIcon from '@mui/icons-material/Book';
9
+ import './DashboardPage.css';
10
+ import Navbar from '../components/Navbar';
11
+
12
+ const DashboardPage = () => {
13
+
14
+ const services = [
15
+ { title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon className="services-card-icon" /> },
16
+ { title: 'Statistics and Charts', link: '/dashboard/stats', icon: <PieChartIcon className="services-card-icon" /> },
17
+ { title: '3D Models', link: '/dashboard/3dmodels', icon: <ThreeDRotationIcon className="services-card-icon" /> },
18
+ { title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon className="services-card-icon" /> },
19
+ ];
20
+
21
+ const menuOptions = ["Settings", "Profile", "Sign out"];
22
+
23
+ const [colors, setColors] = useState({
24
+ bgColor: '',
25
+ fontColor: '',
26
+ });
27
+
28
+ useEffect(() => {
29
+ document.documentElement.classList.add('light-theme');
30
+
31
+ const updateColors = () => {
32
+ const computedStyle = getComputedStyle(document.documentElement);
33
+ const bgColor = computedStyle.getPropertyValue('--primary').trim();
34
+ const fontColor = computedStyle.getPropertyValue('--text').trim();
35
+
36
+ setColors({ bgColor, fontColor });
37
+ };
38
+
39
+ const toggleTheme = (event) => {
40
+ if (event.ctrlKey && event.key === 'q') {
41
+ document.documentElement.classList.toggle('light-theme');
42
+ document.documentElement.classList.toggle('dark-theme');
43
+
44
+ updateColors();
45
+ }
46
+ };
47
+
48
+ window.addEventListener('keydown', toggleTheme);
49
+ updateColors();
50
+ return () => {
51
+ window.removeEventListener('keydown', toggleTheme);
52
+ };
53
+ }, []);
54
+
55
+
56
+ return (
57
+ <>
58
+ <Navbar bgColor={colors.bgColor} fontColor={"#102317"}/>
59
+ <Box className="dashboard-background" />
60
+ <Box className="main-container">
61
+ <Grid container className="main-grid">
62
+
63
+ {/* Menu Grid */}
64
+ <Grid item xs={3} className="menu-grid">
65
+ <Box className="menu-box">
66
+ <List className="menu-list-1">
67
+ {menuOptions.map((option, index) => (
68
+ <ListItem button key={index}>
69
+ <ListItemText primary={option} />
70
+ </ListItem>
71
+ ))}
72
+ </List>
73
+ <List className="menu-list-2">
74
+ <ListItem button>
75
+ <ListItemText primary={<Typography className="menu-list-item">Terms and Conditions</Typography>} />
76
+ </ListItem>
77
+ </List>
78
+ </Box>
79
+ </Grid>
80
+
81
+ <Grid item container spacing={0} className="services-grid" xs={9}>
82
+ {services.map((service, index) => (
83
+ <Grid item xs={6} className={"services-grid-item"} key={index}>
84
+ <Box className={`services-box services-box-${index}`}>
85
+ <Card className={"services-card"}>
86
+ <CardActionArea component={Link} to={service.link} className={"services-card-action-area"}>
87
+ <CardContent className="services-card-content">
88
+ {service.icon}
89
+ <Typography variant="body1" className="services-card-typography">{service.title}</Typography>
90
+ </CardContent>
91
+ </CardActionArea>
92
+ </Card>
93
+ </Box>
94
+ </Grid>
95
+ ))}
96
+ </Grid>
97
+ </Grid>
98
+ </Box>
99
+ </>
100
+ );
101
+
102
+ };
103
+ export default DashboardPage;
104
+
web_app/frontend/src/pages/DashboardPage-old.jsx ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
3
+ import { Box } from '@mui/system';
4
+ import { Link } from 'react-router-dom';
5
+ import ChatIcon from '@mui/icons-material/Chat';
6
+ import PieChartIcon from '@mui/icons-material/PieChart';
7
+ import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
8
+ import MapIcon from '@mui/icons-material/Map';
9
+ import BookIcon from '@mui/icons-material/Book';
10
+
11
+ import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
12
+ import SettingsIcon from '@mui/icons-material/Settings';
13
+ import PersonIcon from '@mui/icons-material/Person';
14
+ import ExitToAppIcon from '@mui/icons-material/ExitToApp';
15
+
16
+ import Navbar from '../components/Navbar';
17
+ // import './DashboardPage.css';
18
+
19
+
20
+ const DashboardPage = () => {
21
+
22
+ const services = [
23
+ { title: 'Chat Assistant', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
24
+ { title: 'Reports and plans', link: '/dashboard/reports', icon: <PieChartIcon style={{ fontSize: 60 }} /> },
25
+ { title: 'My city in 3D', link: '/dashboard/city', icon: <MapIcon style={{ fontSize: 60 }} /> },
26
+ { title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
27
+ ];
28
+
29
+ const menuOptions = [
30
+ { title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
31
+ { title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
32
+ { title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
33
+ { title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
34
+ ];
35
+
36
+ return (
37
+ <>
38
+ <Navbar />
39
+ <Box
40
+ sx={{
41
+ position: 'absolute',
42
+ top: 0,
43
+ left: 0,
44
+ minHeight: '100vh',
45
+ width: '100%',
46
+ backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
47
+ backgroundRepeat: 'no-repeat',
48
+ backgroundSize: 'cover',
49
+ zIndex: -1
50
+ }}
51
+ />
52
+ <Box
53
+ sx={{
54
+ position: 'absolute',
55
+ top: '84px',
56
+ left: '10px',
57
+ right: '10px',
58
+ height: '85vh',
59
+ backgroundColor:'transparent',
60
+ borderRadius:'15px',
61
+ }}
62
+ >
63
+ <Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
64
+ {/* Menu Grid */}
65
+ <Grid item xs={3}>
66
+ <Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
67
+ <List sx={{backgroundColor:"white", borderRadius:"15px"}}>
68
+ {menuOptions.map((option, index) => (
69
+ <ListItem button key={index} component={Link} to={option.link}>
70
+ <ListItemIcon>
71
+ {option.icon}
72
+ </ListItemIcon>
73
+ <ListItemText primary={option.title} />
74
+ </ListItem>
75
+ ))}
76
+ </List>
77
+ <List
78
+ sx={{
79
+ textAlign: 'center',
80
+ backgroundColor:"white",
81
+ borderRadius:"15px",
82
+ }}
83
+ >
84
+ <ListItem button>
85
+ <ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
86
+ </ListItem>
87
+ </List>
88
+ </Box>
89
+ </Grid>
90
+
91
+ {/* Services Grid */}
92
+ <Grid item container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
93
+ {services.map((service, index) => (
94
+ <Grid item xs={6} sx={{display:'flex', flexDirection:'column'}} key={index}>
95
+ <Box sx={{
96
+ borderRadius: '15px',
97
+ p: 2,
98
+ marginLeft: '10px',
99
+ marginRight: (index % 2 !== 0) ? '0px' : '10px',
100
+ marginBottom: (index < 2) ? '10px' : '0px',
101
+ marginTop: (index >= 2) ? '10px' : '0px',
102
+ flexGrow: 1,
103
+ backgroundColor: 'rgba(255, 255, 255, 0.8)',
104
+ boxSizing: 'border-box'
105
+ }}>
106
+ <Card sx={{height: '100%', borderRadius: '15px'}}>
107
+ <CardActionArea component={Link} to={service.link} sx={{height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column'}}>
108
+ <CardContent sx={{textAlign: 'center'}}>
109
+ {service.icon}
110
+ <Typography variant="body1" sx={{mt: 1}}>{service.title}</Typography>
111
+ </CardContent>
112
+ </CardActionArea>
113
+ </Card>
114
+ </Box>
115
+ </Grid>
116
+ ))}
117
+ </Grid>
118
+ </Grid>
119
+ </Box>
120
+ </>
121
+ );
122
+ };
123
+
124
+ export default DashboardPage;
125
+
web_app/frontend/src/pages/DashboardPage.css ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root.dark-theme {
2
+ --text: #f4faf7;
3
+ --background: #102317;
4
+ --primary: #aae4c7;
5
+ --secondary: #060b0e;
6
+ --accent: #a1c2d7;
7
+ }
8
+
9
+ :root.light-theme {
10
+ --text: #102317;
11
+ --background: #f4faf7;
12
+ --primary: #aae4c7;
13
+ --secondary: #c6dae6;
14
+ --accent: #437a9c;
15
+ }
16
+
17
+ /* MAIN CONTAINER*/
18
+
19
+ .dashboard-background {
20
+ position: absolute;
21
+ top: 0;
22
+ left: 0;
23
+ min-height: 100vh;
24
+ width: 100%;
25
+ background-color: var(--background);
26
+ background-repeat: no-repeat;
27
+ background-size: cover;
28
+ z-index: -1;
29
+ }
30
+
31
+ .main-container {
32
+ position: absolute;
33
+ top: 84px;
34
+ left: 10px;
35
+ right: 10px;
36
+ height: 85vh;
37
+ background-color: transparent;
38
+ border-radius: 15px;
39
+ }
40
+
41
+ .main-grid {
42
+ background-color: transparent;
43
+ flex-grow: 1;
44
+ height: 100%;
45
+ border-radius: 15px;
46
+ }
47
+
48
+
49
+ /* MENU */
50
+
51
+ /* .menu-grid {
52
+ } */
53
+
54
+ .menu-box {
55
+ border-radius: 15px;
56
+ padding: 10px;
57
+ margin-right: 10px;
58
+ height: calc(100%);
59
+ background-color: var(--accent);
60
+ box-sizing: border-box;
61
+ display: flex;
62
+ flex-direction: column;
63
+ justify-content: space-between;
64
+ }
65
+
66
+ .menu-list-1 {
67
+ background-color: var(--secondary);
68
+ color: var(--text);
69
+ border-radius: 15px;
70
+ }
71
+
72
+ .menu-list-2 {
73
+ text-align: center;
74
+ background-color: var(--secondary);
75
+ color: var(--text);
76
+ border-radius: 15px;
77
+ }
78
+
79
+ .menu-list-item {
80
+ font-size: 14px;
81
+ }
82
+
83
+ /* SERVICE DASHBOARD */
84
+
85
+ .services-grid {
86
+ height: 100%;
87
+ box-sizing: border-box;
88
+ }
89
+
90
+ .services-grid-item {
91
+ display: flex;
92
+ flex-direction: column;
93
+ }
94
+
95
+ .services-box {
96
+ border-radius: 15px;
97
+ padding: 10px;
98
+ margin-left: 10px;
99
+ flex-grow: 1;
100
+ background-color: var(--accent);
101
+ box-sizing: border-box;
102
+ color: var(--secondary)
103
+ }
104
+
105
+ .services-card {
106
+ height: 100%;
107
+ border-radius: 15px !important;
108
+ background-color: var(--secondary) !important;
109
+ }
110
+
111
+ .services-card-action-area {
112
+ height: 100%;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ flex-direction: column;
117
+ background-color: 'blue' !important;
118
+
119
+ }
120
+
121
+ .services-card-content {
122
+ display: flex;
123
+ justify-content: center;
124
+ align-items: center;
125
+ flex-direction: column;
126
+ height: 90%;
127
+ background-color: 'blue' !important;
128
+
129
+ }
130
+
131
+ .services-card-typography {
132
+ margin-top: 1;
133
+ color: var(--text);
134
+ }
135
+
136
+ .services-card-icon {
137
+ font-size: 60px !important;
138
+ color: var(--text);
139
+ }
140
+
141
+ /* SERVICES GRID ITEMS */
142
+ .services-box-0 {
143
+ margin-right: 10px;
144
+ margin-bottom: 10px;
145
+ margin-top: 0px;
146
+ }
147
+
148
+ .services-box-1 {
149
+ margin-right: 0px;
150
+ margin-bottom: 10px;
151
+ margin-top: 0px;
152
+ }
153
+
154
+ .services-box-2 {
155
+ margin-right: 10px;
156
+ margin-bottom: 0px;
157
+ margin-top: 10px;
158
+ }
159
+
160
+ .services-box-3 {
161
+ margin-right: 0px;
162
+ margin-bottom: 0px;
163
+ margin-top: 10px;
164
+ }
web_app/frontend/src/pages/LandingPage.jsx CHANGED
@@ -3,10 +3,12 @@ import { Container, Typography, Button } from '@mui/material';
3
  import { Link } from 'react-router-dom';
4
  import { Box } from '@mui/system';
5
  import Footer from '../components/Footer';
 
6
 
7
  const LandingPage = () => {
8
  return (
9
  <>
 
10
  <Box
11
  sx={{
12
  position: 'absolute',
@@ -31,7 +33,7 @@ const LandingPage = () => {
31
  <Typography variant="h2" align="center" color="white" gutterBottom>
32
  Building a sustainable Dublin
33
  </Typography>
34
- <Button variant="contained" color="primary" component={Link} to="/chatbot" style={{ margin: '10px', borderRadius: '8px', backgroundColor: 'rgba(255, 255, 255, 0.2)' }}>
35
  <Typography style={{ textTransform: 'none', fontSize: '16px'}}>
36
  Try it out
37
  </Typography>
 
3
  import { Link } from 'react-router-dom';
4
  import { Box } from '@mui/system';
5
  import Footer from '../components/Footer';
6
+ import Navbar from '../components/Navbar';
7
 
8
  const LandingPage = () => {
9
  return (
10
  <>
11
+ <Navbar />
12
  <Box
13
  sx={{
14
  position: 'absolute',
 
33
  <Typography variant="h2" align="center" color="white" gutterBottom>
34
  Building a sustainable Dublin
35
  </Typography>
36
+ <Button variant="contained" color="primary" component={Link} to="/dashboard/chat" style={{ margin: '10px', borderRadius: '8px', backgroundColor: 'rgba(255, 255, 255, 0.2)' }}>
37
  <Typography style={{ textTransform: 'none', fontSize: '16px'}}>
38
  Try it out
39
  </Typography>
web_app/frontend/src/pages/{DashboardPage.jsx → ReportsPage.jsx} RENAMED
@@ -1,13 +1,21 @@
1
  import React from 'react';
2
- import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText } from '@mui/material';
3
  import { Box } from '@mui/system';
4
- import { Link } from 'react-router-dom';
5
  import ChatIcon from '@mui/icons-material/Chat';
6
  import PieChartIcon from '@mui/icons-material/PieChart';
7
  import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
 
8
  import BookIcon from '@mui/icons-material/Book';
9
 
10
- const DashboardPage = () => {
 
 
 
 
 
 
 
11
 
12
  const services = [
13
  { title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
@@ -16,10 +24,16 @@ const DashboardPage = () => {
16
  { title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
17
  ];
18
 
19
- const menuOptions = ["Settings", "Profile", "Sign out"];
 
 
 
 
 
20
 
21
  return (
22
  <>
 
23
  <Box
24
  sx={{
25
  position: 'absolute',
@@ -27,7 +41,7 @@ const DashboardPage = () => {
27
  left: 0,
28
  minHeight: '100vh',
29
  width: '100%',
30
- backgroundImage: 'linear-gradient(to bottom, #4568dc, #b06ab3)',
31
  backgroundRepeat: 'no-repeat',
32
  backgroundSize: 'cover',
33
  zIndex: -1
@@ -45,17 +59,20 @@ const DashboardPage = () => {
45
  }}
46
  >
47
  <Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
48
- <Grid item xs={3}>
49
  <Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
50
  <List sx={{backgroundColor:"white", borderRadius:"15px"}}>
51
  {menuOptions.map((option, index) => (
52
- <ListItem button key={index}>
53
- <ListItemText primary={option} />
 
 
 
54
  </ListItem>
55
  ))}
56
  </List>
57
  <List
58
- sx={{
59
  textAlign: 'center',
60
  backgroundColor:"white",
61
  borderRadius:"15px",
@@ -65,40 +82,24 @@ const DashboardPage = () => {
65
  <ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
66
  </ListItem>
67
  </List>
68
-
69
-
70
  </Box>
71
  </Grid>
72
  <Grid container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
73
- {services.map((service, index) => (
74
- <Grid item xs={6} sx={{display:'flex', flexDirection:'column'}} key={index}>
75
- <Box sx={{
76
- borderRadius: '15px',
77
- p: 2,
78
- marginLeft: '10px',
79
- marginRight: (index % 2 !== 0) ? '0px' : '10px',
80
- marginBottom: (index < 2) ? '10px' : '0px',
81
- marginTop: (index >= 2) ? '10px' : '0px',
82
- flexGrow: 1,
83
- backgroundColor: 'rgba(255, 255, 255, 0.8)',
84
- boxSizing: 'border-box'
85
- }}>
86
- <Card sx={{height: '100%', borderRadius: '15px'}}>
87
- <CardActionArea component={Link} to={service.link} sx={{height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column'}}>
88
- <CardContent sx={{textAlign: 'center'}}>
89
- {service.icon}
90
- <Typography variant="body1" sx={{mt: 1}}>{service.title}</Typography>
91
- </CardContent>
92
- </CardActionArea>
93
- </Card>
94
- </Box>
95
- </Grid>
96
- ))}
97
  </Grid>
98
  </Grid>
99
  </Box>
 
100
  </>
101
  );
102
  };
103
 
104
- export default DashboardPage;
 
1
  import React from 'react';
2
+ import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
3
  import { Box } from '@mui/system';
4
+ import { Link, Outlet } from 'react-router-dom';
5
  import ChatIcon from '@mui/icons-material/Chat';
6
  import PieChartIcon from '@mui/icons-material/PieChart';
7
  import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
8
+ import MapIcon from '@mui/icons-material/Map';
9
  import BookIcon from '@mui/icons-material/Book';
10
 
11
+ import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
12
+ import SettingsIcon from '@mui/icons-material/Settings';
13
+ import PersonIcon from '@mui/icons-material/Person';
14
+ import ExitToAppIcon from '@mui/icons-material/ExitToApp';
15
+
16
+ import Navbar from '../components/Navbar';
17
+
18
+ const ReportsPage = () => {
19
 
20
  const services = [
21
  { title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
 
24
  { title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
25
  ];
26
 
27
+ const menuOptions = [
28
+ { title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
29
+ { title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
30
+ { title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
31
+ { title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
32
+ ];
33
 
34
  return (
35
  <>
36
+ <Navbar />
37
  <Box
38
  sx={{
39
  position: 'absolute',
 
41
  left: 0,
42
  minHeight: '100vh',
43
  width: '100%',
44
+ backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
45
  backgroundRepeat: 'no-repeat',
46
  backgroundSize: 'cover',
47
  zIndex: -1
 
59
  }}
60
  >
61
  <Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
62
+ <Grid item xs={3}>
63
  <Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
64
  <List sx={{backgroundColor:"white", borderRadius:"15px"}}>
65
  {menuOptions.map((option, index) => (
66
+ <ListItem button key={index} component={Link} to={option.link}>
67
+ <ListItemIcon>
68
+ {option.icon}
69
+ </ListItemIcon>
70
+ <ListItemText primary={option.title} />
71
  </ListItem>
72
  ))}
73
  </List>
74
  <List
75
+ sx={{
76
  textAlign: 'center',
77
  backgroundColor:"white",
78
  borderRadius:"15px",
 
82
  <ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
83
  </ListItem>
84
  </List>
 
 
85
  </Box>
86
  </Grid>
87
  <Grid container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
88
+ <Box sx={{
89
+ borderRadius: '15px',
90
+ p: 2,
91
+ marginLeft: '10px',
92
+ flexGrow: 1,
93
+ backgroundColor: 'rgba(255, 255, 255, 0.8)',
94
+ boxSizing: 'border-box'
95
+ }}>
96
+ </Box>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  </Grid>
98
  </Grid>
99
  </Box>
100
+ <Outlet />
101
  </>
102
  );
103
  };
104
 
105
+ export default ReportsPage;
web_app/frontend/src/pages/ResourcesPage.jsx ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
3
+ import { Box } from '@mui/system';
4
+ import { Link, Outlet } from 'react-router-dom';
5
+ import ChatIcon from '@mui/icons-material/Chat';
6
+ import PieChartIcon from '@mui/icons-material/PieChart';
7
+ import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
8
+ import MapIcon from '@mui/icons-material/Map';
9
+ import BookIcon from '@mui/icons-material/Book';
10
+
11
+ import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
12
+ import SettingsIcon from '@mui/icons-material/Settings';
13
+ import PersonIcon from '@mui/icons-material/Person';
14
+ import ExitToAppIcon from '@mui/icons-material/ExitToApp';
15
+
16
+ import Navbar from '../components/Navbar';
17
+
18
+ const ResourcesPage = () => {
19
+
20
+ const services = [
21
+ { title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
22
+ { title: 'Statistics and Charts', link: '/dashboard/stats', icon: <PieChartIcon style={{ fontSize: 60 }} /> },
23
+ { title: '3D Models', link: '/dashboard/3dmodels', icon: <ThreeDRotationIcon style={{ fontSize: 60 }} /> },
24
+ { title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
25
+ ];
26
+
27
+ const menuOptions = [
28
+ { title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
29
+ { title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
30
+ { title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
31
+ { title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
32
+ ];
33
+
34
+ return (
35
+ <>
36
+ <Navbar />
37
+ <Box
38
+ sx={{
39
+ position: 'absolute',
40
+ top: 0,
41
+ left: 0,
42
+ minHeight: '100vh',
43
+ width: '100%',
44
+ backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
45
+ backgroundRepeat: 'no-repeat',
46
+ backgroundSize: 'cover',
47
+ zIndex: -1
48
+ }}
49
+ />
50
+ <Box
51
+ sx={{
52
+ position: 'absolute',
53
+ top: '84px',
54
+ left: '10px',
55
+ right: '10px',
56
+ height: '85vh',
57
+ backgroundColor:'transparent',
58
+ borderRadius:'15px',
59
+ }}
60
+ >
61
+ <Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
62
+ <Grid item xs={3}>
63
+ <Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
64
+ <List sx={{backgroundColor:"white", borderRadius:"15px"}}>
65
+ {menuOptions.map((option, index) => (
66
+ <ListItem button key={index} component={Link} to={option.link}>
67
+ <ListItemIcon>
68
+ {option.icon}
69
+ </ListItemIcon>
70
+ <ListItemText primary={option.title} />
71
+ </ListItem>
72
+ ))}
73
+ </List>
74
+ <List
75
+ sx={{
76
+ textAlign: 'center',
77
+ backgroundColor:"white",
78
+ borderRadius:"15px",
79
+ }}
80
+ >
81
+ <ListItem button>
82
+ <ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
83
+ </ListItem>
84
+ </List>
85
+ </Box>
86
+ </Grid>
87
+ <Grid container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
88
+ <Box sx={{
89
+ borderRadius: '15px',
90
+ p: 2,
91
+ marginLeft: '10px',
92
+ flexGrow: 1,
93
+ backgroundColor: 'rgba(255, 255, 255, 0.8)',
94
+ boxSizing: 'border-box'
95
+ }}>
96
+ </Box>
97
+ </Grid>
98
+ </Grid>
99
+ </Box>
100
+ <Outlet />
101
+ </>
102
+ );
103
+ };
104
+
105
+ export default ResourcesPage;
web_app/frontend/src/pages/scrollbar.css ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .custom-scrollbar {
2
+ height: 500px; /* Set your desired height */
3
+ overflow: auto;
4
+ }
5
+
6
+ .custom-scrollbar::-webkit-scrollbar {
7
+ width: 10px;
8
+ }
9
+
10
+ .custom-scrollbar::-webkit-scrollbar-track {
11
+ background: #f1f1f1;
12
+ }
13
+
14
+ .custom-scrollbar::-webkit-scrollbar-thumb {
15
+ background: #1D5B79;
16
+ }
17
+
18
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
19
+ background: #1D5B79;
20
+ }
web_app/frontend/vite.config.js CHANGED
@@ -1,14 +1,18 @@
1
- import { defineConfig } from 'vite'
2
- import react from '@vitejs/plugin-react'
3
 
4
- // https://vitejs.dev/config/
5
  export default defineConfig({
6
  plugins: [react()],
 
 
 
 
 
7
  server: {
8
  host: true,
9
  port: 3000,
10
- watch: {
11
- usePolling: true
12
- }
13
  }
14
- })
 
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
 
 
4
  export default defineConfig({
5
  plugins: [react()],
6
+ build: {
7
+ rollupOptions: {
8
+ external: ['@deck.gl/extensions']
9
+ }
10
+ },
11
  server: {
12
  host: true,
13
  port: 3000,
14
+ watch: {
15
+ usePolling: true
16
+ }
17
  }
18
+ });