diff --git a/financial-tracker/api-gateway/app/app.py b/financial-tracker/api-gateway/app/app.py
index c3961c4e73dc3dc6d3f76873775ab59aded6259c..f259d78c5a8f22e1545bd005f4da4e708fcad194 100644
--- a/financial-tracker/api-gateway/app/app.py
+++ b/financial-tracker/api-gateway/app/app.py
@@ -94,9 +94,102 @@ def me():
     except requests.exceptions.RequestException as e:
         app.logger.error(f"Error contacting user-service: {e}")
         return jsonify({"error": "User service unavailable"}), 503
+    
+
+@app.route('/auth/update', methods=["PUT"])
+def update_profile():
+    """
+    Forward request to update user profile to the user-service.
+    """
+    token = request.headers.get("Authorization")  # Get token from headers
+
+    if not token:
+        app.logger.error("Authorization token is missing.")
+        return jsonify({"error": "Authorization token is missing"}), 400
+
+    if not token.startswith("Bearer "):
+        app.logger.error("Invalid token format received.")
+        return jsonify({"error": "Invalid token format. Expected 'Bearer <token>'"}), 400
+
+    try:
+        app.logger.info("Forwarding user update request to user-service.")
+        headers = {"Authorization": token}
+        
+        # Forward the PUT request body to user-service
+        response = requests.put(f"{USER_SERVICE_URL}/auth/update", json=request.json, headers=headers)
+        
+        return jsonify(response.json()), response.status_code
+
+    except requests.exceptions.RequestException as e:
+        app.logger.error(f"Error contacting user-service: {e}")
+        return jsonify({"error": "User service unavailable"}), 503
+ 
+    
+@app.route('/auth/password', methods=["PUT"])
+def update_password():
+    """
+    Forward request to update user password to the user-service.
+    """
+    token = request.headers.get("Authorization")  # Get token from headers
 
-# Configure transaction service URL
-TRANSACTION_SERVICE_URL = os.getenv('TRANSACTION_SERVICE_URL', 'http://transaction-service:5002')
+    if not token:
+        app.logger.error("Authorization token is missing.")
+        return jsonify({"error": "Authorization token is missing"}), 400
+
+    if not token.startswith("Bearer "):
+        app.logger.error("Invalid token format received.")
+        return jsonify({"error": "Invalid token format. Expected 'Bearer <token>'"}), 400
+
+    try:
+        app.logger.info("Forwarding password update request to user-service.")
+        headers = {"Authorization": token}
+        
+        # Forward the PUT request body to user-service
+        response = requests.put(f"{USER_SERVICE_URL}/auth/password", json=request.json, headers=headers)
+        
+        return jsonify(response.json()), response.status_code
+
+    except requests.exceptions.RequestException as e:
+        app.logger.error(f"Error contacting user-service: {e}")
+        return jsonify({"error": "User service unavailable"}), 503
+
+
+@app.route('/currencies', methods=["GET"])
+@jwt_required()
+def fetch_currencies():
+    token = request.headers.get("Authorization")  # Get token from headers
+
+    if not token:
+        return jsonify({"error": "Authorization token is missing"}), 400
+
+    try:
+        user_id = get_jwt_identity()  # Extract user_id from JWT token
+        headers = {"Authorization": token}
+        response = requests.get(f"{USER_SERVICE_URL}/currencies", headers=headers)
+        response_data = jsonify(response.json())
+        
+        return response_data, response.status_code
+    except requests.exceptions.RequestException as e:
+        return jsonify({"error": "User service unavailable"}), 503
+    
+@app.route('/timezones', methods=["GET"])
+@jwt_required()
+def fetch_timezones():
+    token = request.headers.get("Authorization")  # Get token from headers
+
+    if not token:
+        return jsonify({"error": "Authorization token is missing"}), 400
+
+    try:
+        user_id = get_jwt_identity()  # Extract user_id from JWT token
+        headers = {"Authorization": token}
+        response = requests.get(f"{USER_SERVICE_URL}/timezones", headers=headers)
+        response_data = jsonify(response.json())
+        
+        return response_data, response.status_code
+    except requests.exceptions.RequestException as e:
+        return jsonify({"error": "User service unavailable"}), 503
+    
 
 @app.route('/transactions', methods=["GET", "POST"])
 def handle_transactions():
@@ -283,7 +376,7 @@ def add_income():
 
         response = requests.post(f"{TRANSACTION_SERVICE_URL}/income", headers=headers, json=request.get_json())
         return jsonify(response.json()), response.status_code
-    except requests.exceptions.RequestException:
+    except requests.exceptions.RequestException as e:
         app.logger.error(f"Error contacting transaction-service: {e}")
         return jsonify({"error": "Transaction service unavailable"}), 503
 
@@ -324,7 +417,7 @@ def update_income(income_id):
 
         response = requests.put(f"{TRANSACTION_SERVICE_URL}/income/{income_id}", headers=headers, json=request.get_json())
         return jsonify(response.json()), response.status_code
-    except requests.exceptions.RequestException:
+    except requests.exceptions.RequestException as e:
         app.logger.error(f"Error contacting transaction-service: {e}")
         return jsonify({"error": "Transaction service unavailable"}), 503
     
@@ -348,7 +441,7 @@ def delete_income(income_id):
                 app.logger.error(f"Failed to delete income with ID {income_id}.")
                 return jsonify({"error": "Failed to delete income"}), response.status_code
 
-    except requests.exceptions.RequestException:
+    except requests.exceptions.RequestException as e:
         app.logger.error(f"Error contacting transaction-service: {e}")
         return jsonify({"error": "Transaction service unavailable"}), 503
 
diff --git a/financial-tracker/docker-compose.yml b/financial-tracker/docker-compose.yml
index 66cca04e3a3dec9920d14bbf7260eb7a602de0b3..170cac38c54564887212b06d74fc241d9fede4ad 100644
--- a/financial-tracker/docker-compose.yml
+++ b/financial-tracker/docker-compose.yml
@@ -28,7 +28,8 @@ services:
       - DATABASE_URL=postgresql://user:password@user-db:5432/user_db
       - JWT_SECRET_KEY=3b5e41af18179f530c5881a5191e15f0ab35eed2fefdc068fda254eed3fb1ecb
     depends_on:
-      - user-db
+      user-db:
+        condition: service_healthy
     networks:
       - app-network
     healthcheck:
@@ -85,16 +86,23 @@ services:
 
   notification-service:
     build:
-      context: .
-      dockerfile: notification-service/Dockerfile
+      context: ./notification-service
     ports:
-      - "5005:5005"
+      - "5005:5005"  # Combined HTTP and WebSocket port
     environment:
       - DATABASE_URL=postgresql://user:password@notification-db:5432/notification_db
+      - JWT_SECRET_KEY=3b5e41af18179f530c5881a5191e15f0ab35eed2fefdc068fda254eed3fb1ecb
+      - EMAIL_USER=your_email_user
+      - EMAIL_PASS=your_email_password
     depends_on:
-      - notification-db
+      notification-db:
+        condition: service_healthy
     networks:
       - app-network
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:5005/health"]
+      interval: 30s
+      retries: 3
 
   frontend:
     build:
@@ -120,6 +128,11 @@ services:
       - user_db_data:/var/lib/postgresql/data
     networks:
       - app-network
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U user -d user_db"]
+      interval: 5s
+      timeout: 5s
+      retries: 5
 
   transaction-db:
     image: postgres:16
@@ -176,6 +189,11 @@ services:
       - notification_db_data:/var/lib/postgresql/data
     networks:
       - app-network
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U user -d notification_db"]
+      interval: 5s
+      timeout: 5s
+      retries: 5
 
 volumes:
   user_db_data:
diff --git a/financial-tracker/frontend/.env b/financial-tracker/frontend/.env
new file mode 100644
index 0000000000000000000000000000000000000000..0519ecba6ea913e21689ec692e81e9e4973fbf73
--- /dev/null
+++ b/financial-tracker/frontend/.env
@@ -0,0 +1 @@
+ 
\ No newline at end of file
diff --git a/financial-tracker/frontend/package.json b/financial-tracker/frontend/package.json
index ffb0bc3b18555309b54a760b824218b8097ef72c..cec9ed04094662c6dee0d68ef3009c791bd815df 100644
--- a/financial-tracker/frontend/package.json
+++ b/financial-tracker/frontend/package.json
@@ -9,10 +9,13 @@
     "@testing-library/user-event": "^13.5.0",
     "axios": "^1.8.4",
     "chart.js": "^4.4.8",
+    "bootstrap": "^5.3.2",
     "formik": "^2.4.6",
     "jwt-decode": "^4.0.0",
     "react": "^19.0.0",
     "react-chartjs-2": "^5.3.0",
+    "react-bootstrap": "^2.9.0",
+    "react-bootstrap-icons": "^1.11.3",
     "react-dom": "^19.0.0",
     "react-icons": "^5.5.0",
     "react-paginate": "^8.3.0",
diff --git a/financial-tracker/frontend/src/App.js b/financial-tracker/frontend/src/App.js
index 6dbc470864737ab6f2a9049b2928793c09670f6c..81be08f0daf3901256220c9c9b140b6979d57454 100644
--- a/financial-tracker/frontend/src/App.js
+++ b/financial-tracker/frontend/src/App.js
@@ -6,11 +6,9 @@ import Register from "./pages/Register";
 import Login from "./pages/Login";
 import Dashboard from "./pages/Dashboard";
 import Income from "./pages/Income";
-
-
-
 import Expenses from "./pages/Expenses";
 import Budget from "./pages/Budget";
+import Profile from "./pages/Profile";
 
 function App() {
   const [token, setToken] = useState(localStorage.getItem("token"));
@@ -18,6 +16,7 @@ function App() {
   useEffect(() => {
     const handleStorageChange = () => {
       setToken(localStorage.getItem("token"));
+      setToken(localStorage.getItem("token"));
     };
 
     window.addEventListener("storage", handleStorageChange);
@@ -26,6 +25,11 @@ function App() {
     };
   }, []);
 
+  const handleLogout = () => {
+    localStorage.removeItem("token");
+    setToken(null);
+  };
+
   return (
     <Router>
       <div className="App">
@@ -38,9 +42,10 @@ function App() {
             {token ? (
               <>
                 <li><Link to="/dashboard">Dashboard</Link></li>
-                <li><Link to="/income">Income</Link></li> {/* 👈 Add this line */}
+                <li><Link to="/income">Income</Link></li>
                 <li><Link to="/expenses">Expenses</Link></li>
-                <li><Link to="/budget">Budget</Link></li> 
+                <li><Link to="/budget">Budget</Link></li>
+                <li><Link to="/profile">Profile</Link></li>
                 <li>
                   <Link to="/" onClick={() => { localStorage.removeItem("token"); setToken(null); }}>
                     Logout
@@ -49,8 +54,8 @@ function App() {
               </>
             ) : (
               <>
-                <li><Link to="/login">Login</Link></li>
-                <li><Link to="/register">Register</Link></li>
+                <li><Link as={Link} to="/login">Login</Link></li>
+                <li><Link as={Link} to="/register">Register</Link></li>
               </>
             )}
           </ul>
@@ -63,7 +68,8 @@ function App() {
           <Route path="/dashboard" element={<Dashboard setToken={setToken} />} />
           <Route path="/income" element={<Income />} />
           <Route path="/expenses" element={<Expenses />} />
-          <Route path="/budget" element={<Budget />} /> 
+          <Route path="/budget" element={<Budget />} />
+          <Route path="/profile" element={<Profile setToken={setToken} />} />
         </Routes>
       </div>
     </Router>
diff --git a/financial-tracker/frontend/src/pages/Login.js b/financial-tracker/frontend/src/pages/Login.js
index 070f63fd480bafa04a80383eaa39391a742fe95b..fc591c89c6c5dfe97eb76367ef5ca50a8efb6529 100644
--- a/financial-tracker/frontend/src/pages/Login.js
+++ b/financial-tracker/frontend/src/pages/Login.js
@@ -19,6 +19,9 @@ const Login = ({ setToken }) => {
       });
 
       localStorage.setItem("token", response.data.access_token);
+      // Decode the JWT token to get the user ID
+      const tokenPayload = JSON.parse(atob(response.data.access_token.split('.')[1]));
+      localStorage.setItem("userId", tokenPayload.sub);
       setToken(response.data.access_token); // Update state immediately
       navigate("/dashboard");
     } catch (err) {
diff --git a/financial-tracker/frontend/src/pages/Profile.js b/financial-tracker/frontend/src/pages/Profile.js
new file mode 100644
index 0000000000000000000000000000000000000000..274018211a38c4ffc45bc18492a25ff3d570d352
--- /dev/null
+++ b/financial-tracker/frontend/src/pages/Profile.js
@@ -0,0 +1,329 @@
+import React, { useState, useEffect } from 'react';
+import axios from "axios";
+import { jwtDecode } from 'jwt-decode';
+import { Formik, Form, Field, ErrorMessage } from "formik";
+import * as Yup from "yup";
+import '../styles/Profile.css';
+
+
+const Profile = () => {
+  const [profile, setProfile] = useState({
+    first_name: '',
+    last_name: '',
+    email: '',
+    preferences: {
+      currency: '',
+      timezone: ''
+    }
+  });
+  const [currencies, setCurrencies] = useState([]);
+  const [timezones, setTimezones] = useState([]);
+  const [successMessage, setSuccessMessage] = useState('');
+  const [loading, setLoading] = useState(false);
+  const [isSessionValid, setIsSessionValid] = useState(true);
+
+  // Define validation schema using Yup
+  const profileValidationSchema = Yup.object().shape({
+    first_name: Yup.string()
+      .min(2, "First name must be at least 2 characters")
+      .max(50, "First name is too long")
+      .required("First name is required"),
+    last_name: Yup.string()
+      .min(2, "Last name must be at least 2 characters")
+      .max(50, "Last name is too long")
+      .required("Last name is required"),
+    email: Yup.string()
+      .email("Invalid email format")
+      .required("Email is required"),
+    currency: Yup.string()
+      .required("Currency selection is required"),
+    timezone: Yup.string()
+      .required("Timezone selection is required")
+  });
+  const passwordValidationSchema = Yup.object().shape({
+    currentPassword: Yup.string()
+      .required("Current password is required"),
+    newPassword: Yup.string()
+      .min(8, "New password must be at least 8 characters")
+      .matches(/[A-Z]/, "New password must contain at least one uppercase letter")
+      .matches(/[a-z]/, "New password must contain at least one lowercase letter")
+      .matches(/\d/, "New password must contain at least one number")
+      .matches(/[@$!%*?&_]/, "New password must contain at least one special character (@$!%*?&_)")
+      .required("New password is required"),
+    confirmPassword: Yup.string()
+      .oneOf([Yup.ref('newPassword'), null], "Passwords must match")
+      .required("Please confirm your new password")
+  });
+
+  // Check if token exists in localStorage to determine if session is valid
+  useEffect(() => {
+    const token = localStorage.getItem("token");
+
+    if (token) {
+      setIsSessionValid(true); // Token exists, session is valid
+    } else {
+      setIsSessionValid(false); // No token, session invalid
+      alert("Your session has expired. Please log in again.");
+      window.location.href = "/login"; // Redirect to login page
+    }
+  }, []);
+
+  // Only fetch data if session is valid
+  useEffect(() => {
+    if (isSessionValid) {
+      fetchProfile();
+      fetchCurrencies();
+      fetchTimezones();
+    }
+  }, [isSessionValid]);
+
+  const fetchProfile = async () => {
+    try {
+      const token = localStorage.getItem("token");
+
+      if (!token) {
+        console.error("No token found, user might not be logged in.");
+        return;
+      }
+
+      const decoded = jwtDecode(token);
+      console.log("Decoded JWT:", decoded);
+
+      // Use 'sub' as user_id
+      const user_id = decoded.sub;
+      if (!user_id) {
+        console.error("User ID is undefined. Check JWT structure.");
+        return;
+      }
+
+      const response = await axios.get("http://localhost:8000/auth/me", {
+        headers: { Authorization: `Bearer ${token}` },
+      })
+
+      const userData = response.data;
+      console.log("Fetched profile info:", userData);
+      console.log(userData.last_name);
+
+      setProfile({
+        first_name: userData.first_name || '',
+        last_name: userData.last_name || '',
+        email: userData.email || '',
+        preferences: {
+          currency: userData.preferences.currency || 'GBP',
+          timezone: userData.preferences.timezone || 'BST'
+        }
+      });
+    } catch (error) {
+      console.error('Error fetching profile:', error);
+      alert(`Error fetching profile: ${error.response}`);
+    }
+  };
+
+  const fetchCurrencies = async () => {
+    try {
+      const response = await axios.get('http://localhost:8000/currencies', {
+        headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
+      });
+      setCurrencies(response.data.currencies);
+    } catch (error) {
+      console.error('Error fetching currencies:', error);
+    }
+  };
+
+  const fetchTimezones = async () => {
+    try {
+      const response = await axios.get('http://localhost:8000/timezones', {
+        headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
+      });
+      setTimezones(response.data.timezones);
+    } catch (error) {
+      console.error('Error fetching timezones:', error);
+    }
+  };
+
+
+  const handleProfileUpdate = async (values, { setSubmitting }) => {
+    setLoading(true);
+
+    try {
+      const response = await axios.put("http://localhost:8000/auth/update", {
+        first_name: values.first_name,
+        last_name: values.last_name,
+        email: values.email,
+        preferences: {
+          currency: values.currency,
+          timezone: values.timezone
+        },
+      }, {
+        headers: {
+          Authorization: `Bearer ${localStorage.getItem('token')}`
+        }
+      });
+
+      setSuccessMessage("Profile updated successfully. Refreshing profile page...");
+      // Wait 1.5 seconds before refreshing
+      setTimeout(() => {
+        window.location.reload();
+      }, 1500);
+    } catch (error) {
+      console.error('Error updating profile:', error);
+      alert(`Error updating profile: ${error.response ? error.response.data.error || error.response.data.message : error.message}`);
+    } finally {
+      setLoading(false);
+      setSubmitting(false);
+    }
+  };
+
+  const handlePasswordUpdate = async (values, { setSubmitting }) => {
+    setLoading(true);
+
+    try {
+      const response = await axios.put("http://localhost:8000/auth/password", {
+        current_password: values.currentPassword,
+        new_password: values.newPassword
+      }, {
+        headers: {
+          Authorization: `Bearer ${localStorage.getItem('token')}`
+        }
+      });
+
+      setSuccessMessage("Password updated successfully. Refreshing profile page...");
+      setTimeout(() => {
+        window.location.reload();
+      }, 1500);
+    } catch (error) {
+      console.error('Error updating password:', error);
+      console.log(error.response)
+      if (error.response) {
+        const { status, data } = error.response;
+        console.log(status)
+        if (status === 401) {
+          alert(data.error || "Current password is incorrect.");
+        } else {
+          alert(data.error || data.message || "An unexpected error occurred.");
+        }
+      } else {
+        alert("Network error or server did not respond.");
+      }
+
+    } finally {
+      setLoading(false);
+      setSubmitting(false);
+    }
+  };
+
+
+  return (
+    <div className="profile-container">
+      <h1 className="page-title">Profile</h1>
+
+      {/* Display the success message */}
+      {successMessage && <div className="success-message">{successMessage}</div>}
+
+      <div className="profile-layout">
+        <div className="profile-card">
+          <h2 className="card-title">Profile Information</h2>
+          <Formik
+            enableReinitialize={true}
+            initialValues={{
+              first_name: profile.first_name,
+              last_name: profile.last_name,
+              email: profile.email,
+              currency: profile.preferences.currency,
+              timezone: profile.preferences.timezone,
+            }}
+            validationSchema={profileValidationSchema}
+            onSubmit={handleProfileUpdate}
+          >
+            {({ isSubmitting }) => (
+              <Form>
+                <div className="form-group">
+                  <label>First Name</label>
+                  <Field type="text" name="first_name" className="form-control" />
+                  <ErrorMessage name="first_name" component="div" className="error" />
+                </div>
+
+                <div className="form-group">
+                  <label>Last Name</label>
+                  <Field type="text" name="last_name" className="form-control" />
+                  <ErrorMessage name="last_name" component="div" className="error" />
+                </div>
+
+                <div className="form-group">
+                  <label>Email</label>
+                  <Field type="email" name="email" className="form-control" />
+                  <ErrorMessage name="email" component="div" className="error" />
+                </div>
+
+                <div className="form-group">
+                  <label>Currency</label>
+                  <Field as="select" name="currency" className="form-control">
+                    {currencies.map(currency => (
+                      <option key={currency} value={currency}>{currency}</option>
+                    ))}
+                  </Field>
+                  <ErrorMessage name="currency" component="div" className="error" />
+                </div>
+
+                <div className="form-group">
+                  <label>Timezone</label>
+                  <Field as="select" name="timezone" className="form-control">
+                    {timezones.map(timezone => (
+                      <option key={timezone} value={timezone}>{timezone}</option>
+                    ))}
+                  </Field>
+                  <ErrorMessage name="timezone" component="div" className="error" />
+                </div>
+
+                <button type="submit" className="btn btn-primary w-100" disabled={isSubmitting || loading}>
+                  {loading ? 'Updating...' : 'Update Profile'}
+                </button>
+              </Form>
+            )}
+          </Formik>
+        </div>
+
+        <div className="profile-card">
+          <h2 className="card-title">Change Password</h2>
+          <Formik
+            initialValues={{
+              currentPassword: '',
+              newPassword: '',
+              confirmPassword: ''
+            }}
+            validationSchema={passwordValidationSchema}
+            onSubmit={handlePasswordUpdate}
+          >
+            {({ isSubmitting }) => (
+              <Form>
+                <div className="form-group">
+                  <label>Current Password</label>
+                  <Field type="password" name="currentPassword" className="form-control" />
+                  <ErrorMessage name="currentPassword" component="div" className="error" />
+                </div>
+
+                <div className="form-group">
+                  <label>New Password</label>
+                  <Field type="password" name="newPassword" className="form-control" />
+                  <ErrorMessage name="newPassword" component="div" className="error" />
+                </div>
+
+                <div className="form-group">
+                  <label>Confirm New Password</label>
+                  <Field type="password" name="confirmPassword" className="form-control" />
+                  <ErrorMessage name="confirmPassword" component="div" className="error" />
+                </div>
+
+                <button type="submit" className="btn btn-primary w-100" disabled={isSubmitting || loading}>
+                  {loading ? 'Updating...' : 'Update Password'}
+                </button>
+              </Form>
+            )}
+          </Formik>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default Profile;
\ No newline at end of file
diff --git a/financial-tracker/frontend/src/pages/Register.js b/financial-tracker/frontend/src/pages/Register.js
index 9c46a58e966eada3295331b2f481b930a32fe16f..21d1d49aa0956b04cf624a909639ab3e9f3da0fe 100644
--- a/financial-tracker/frontend/src/pages/Register.js
+++ b/financial-tracker/frontend/src/pages/Register.js
@@ -12,8 +12,6 @@ const Register = () => {
   const [password, setPassword] = useState("");
   const [showPassword, setShowPassword] = useState(false);
 
-
-
   // Define validation schema using Yup
   const validationSchema = Yup.object().shape({
     firstName: Yup.string()
@@ -41,7 +39,7 @@ const Register = () => {
       {/* Register Form */}
       <div className="register-container">
         <h2>Register</h2>
-        
+
         <Formik
           initialValues={{ firstName: "", lastName: "", email: "", password: "" }}
           validationSchema={validationSchema}
@@ -66,89 +64,89 @@ const Register = () => {
               {status?.error && <p className="error-message">{status.error}</p>}
               {status?.success && <p className="success-message">{status.success}</p>}
 
-              
+
               <div className="form-group">
-              <label htmlFor="firstName">
-                First Name <span className="required-asterisk">*</span>
-              </label>
+                <label htmlFor="firstName">
+                  First Name <span className="required-asterisk">*</span>
+                </label>
                 <Field type="text" name="firstName" className="form-control" />
                 <ErrorMessage name="firstName" component="div" className="error" />
               </div>
 
               <div className="form-group">
-              <label htmlFor="lastName">
-                Last Name <span className="required-asterisk">*</span>
-              </label>
+                <label htmlFor="lastName">
+                  Last Name <span className="required-asterisk">*</span>
+                </label>
                 <Field type="text" name="lastName" className="form-control" />
                 <ErrorMessage name="lastName" component="div" className="error" />
               </div>
 
               <div className="form-group">
-              <label htmlFor="email">
-                Email <span className="required-asterisk">*</span>
-              </label>
+                <label htmlFor="email">
+                  Email <span className="required-asterisk">*</span>
+                </label>
                 <Field type="email" name="email" className="form-control" />
                 <ErrorMessage name="email" component="div" className="error" />
               </div>
-              
+
               <div className="form-group">
                 <label htmlFor="password">
                   Password <span className="required-asterisk">*</span>
                 </label>
-              <Field name="password">
-                {({ field, form }) => {
-                  // Update local password state every time the field changes
-                  const handlePasswordChange = (e) => {
-                    setPassword(e.target.value);
-                    form.setFieldValue("password", e.target.value); // Keep Formik in sync
-                  };
-
-                  return (
-                    <>
-                      <div className="password-wrapper">
-                        <input
-                          {...field}
-                          type={showPassword ? "text" : "password"}
-                          className="form-control"
-                          onChange={handlePasswordChange}
-                          placeholder="Enter your password"
-                        />
-                        <span
-                          className="toggle-password"
-                          onClick={() => setShowPassword((prev) => !prev)}
-                          title={showPassword ? "Hide password" : "Show password"}
-                        >
-                          {showPassword ? <FaEyeSlash /> : <FaEye />}
-                        </span>
-                        
-
-                      </div>
-
-                      {/* Dynamic password feedback */}
-                      <ul className="password-rules">
-                        <li className={password.length >= 8 ? "valid" : "invalid"}>
-                          {password.length >= 8 ? "✔" : "✖"} At least 8 characters
-                        </li>
-                        <li className={/[A-Z]/.test(password) ? "valid" : "invalid"}>
-                          {/[A-Z]/.test(password) ? "✔" : "✖"} One uppercase letter
-                        </li>
-                        <li className={/[a-z]/.test(password) ? "valid" : "invalid"}>
-                          {/[a-z]/.test(password) ? "✔" : "✖"} One lowercase letter
-                        </li>
-                        <li className={/\d/.test(password) ? "valid" : "invalid"}>
-                          {/\d/.test(password) ? "✔" : "✖"} One number
-                        </li>
-                        <li className={/[@$!%*?&_]/.test(password) ? "valid" : "invalid"}>
-                          {/[@$!%*?&_]/.test(password) ? "✔" : "✖"} One special character
-                        </li>
-                      </ul>
-                    </>
-                  );
-                }}
-              </Field>
-            </div>
-
-              
+                <Field name="password">
+                  {({ field, form }) => {
+                    // Update local password state every time the field changes
+                    const handlePasswordChange = (e) => {
+                      setPassword(e.target.value);
+                      form.setFieldValue("password", e.target.value); // Keep Formik in sync
+                    };
+
+                    return (
+                      <>
+                        <div className="password-wrapper">
+                          <input
+                            {...field}
+                            type={showPassword ? "text" : "password"}
+                            className="form-control"
+                            onChange={handlePasswordChange}
+                            placeholder="Enter your password"
+                          />
+                          <span
+                            className="toggle-password"
+                            onClick={() => setShowPassword((prev) => !prev)}
+                            title={showPassword ? "Hide password" : "Show password"}
+                          >
+                            {showPassword ? <FaEyeSlash /> : <FaEye />}
+                          </span>
+
+
+                        </div>
+
+                        {/* Dynamic password feedback */}
+                        <ul className="password-rules">
+                          <li className={password.length >= 8 ? "valid" : "invalid"}>
+                            {password.length >= 8 ? "✔" : "✖"} At least 8 characters
+                          </li>
+                          <li className={/[A-Z]/.test(password) ? "valid" : "invalid"}>
+                            {/[A-Z]/.test(password) ? "✔" : "✖"} One uppercase letter
+                          </li>
+                          <li className={/[a-z]/.test(password) ? "valid" : "invalid"}>
+                            {/[a-z]/.test(password) ? "✔" : "✖"} One lowercase letter
+                          </li>
+                          <li className={/\d/.test(password) ? "valid" : "invalid"}>
+                            {/\d/.test(password) ? "✔" : "✖"} One number
+                          </li>
+                          <li className={/[@$!%*?&_]/.test(password) ? "valid" : "invalid"}>
+                            {/[@$!%*?&_]/.test(password) ? "✔" : "✖"} One special character
+                          </li>
+                        </ul>
+                      </>
+                    );
+                  }}
+                </Field>
+              </div>
+
+
               <button type="submit" className="btn" disabled={isSubmitting}>
                 {isSubmitting ? "Registering..." : "Register"}
               </button>
diff --git a/financial-tracker/frontend/src/styles/App.css b/financial-tracker/frontend/src/styles/App.css
index 74b5e053450a48a6bdb4d71aad648e7af821975c..2a048894af5de192ea133c2d4aa0299191b0a2db 100644
--- a/financial-tracker/frontend/src/styles/App.css
+++ b/financial-tracker/frontend/src/styles/App.css
@@ -1,18 +1,15 @@
 .App {
   text-align: center;
 }
-
 .App-logo {
   height: 40vmin;
   pointer-events: none;
 }
-
 @media (prefers-reduced-motion: no-preference) {
   .App-logo {
     animation: App-logo-spin infinite 20s linear;
   }
 }
-
 .App-header {
   background-color: #282c34;
   min-height: 100vh;
@@ -23,11 +20,9 @@
   font-size: calc(10px + 2vmin);
   color: white;
 }
-
 .App-link {
   color: #61dafb;
 }
-
 @keyframes App-logo-spin {
   from {
     transform: rotate(0deg);
@@ -35,4 +30,4 @@
   to {
     transform: rotate(360deg);
   }
-}
+}
\ No newline at end of file
diff --git a/financial-tracker/frontend/src/styles/Profile.css b/financial-tracker/frontend/src/styles/Profile.css
new file mode 100644
index 0000000000000000000000000000000000000000..ccac474c93c9aae5c419202e58cc8274e50755a8
--- /dev/null
+++ b/financial-tracker/frontend/src/styles/Profile.css
@@ -0,0 +1,102 @@
+/* Profile.css */
+h1 {
+  font-size: 2.5em;
+  text-align: center;
+}
+
+.profile-container {
+  margin: 0 auto; 
+  border-radius: 8px;
+}
+
+.profile-layout {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  gap: 2rem;
+}
+
+.profile-card {
+  background-color: #f7f7f7;
+  padding: 2rem;
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  width: 100%;
+  max-width: 500px;
+}
+
+.profile-info, .change-password {
+  flex: 1;
+  min-width: 300px; 
+}
+
+.form-group {
+  margin-bottom: 15px;
+}
+
+.profile-container h2 {
+  text-align: center; 
+}
+
+.card-title label {
+  display: block;
+}
+
+label {
+  margin-bottom: 5px;
+  font-weight: bold;
+}
+
+.profile-card input,
+.profile-card select {
+  width: 100%;
+  padding: 8px;
+  margin-top: 5px;
+  border-radius: 5px;
+  border: 1px solid #ddd;
+}
+
+.profile-card input[type="text"],
+.profile-card input[type="email"],
+.profile-card input[type="password"],
+.profile-card select {
+  font-size: 16px;
+}
+
+button {
+  width: 100%;
+  padding: 10px;
+  background-color: #007bff;
+  color: white;
+  font-size: 16px;
+  border: none;
+  border-radius: 5px;
+}
+
+button:hover {
+  background-color: #0056b3; 
+  cursor: pointer;
+}
+
+/* Success Message */
+.success-message {
+  background-color: #4CAF50;
+  border-radius: 5px;
+  color: white;
+  margin: 10px auto;
+  margin-top: 10px;
+  padding: 10px;
+  width: 80%;
+}
+
+/* Responsive adjustments */
+@media (max-width: 600px) {
+  .profile-container {
+    width: 90%;
+  }
+
+  .profile-layout {
+    flex-direction: column;
+    gap: 20px;
+  }
+}
diff --git a/financial-tracker/notification-service/.DS_Store b/financial-tracker/notification-service/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..65dd82e3eb29c204fa0bcd2edece958c325989b8
Binary files /dev/null and b/financial-tracker/notification-service/.DS_Store differ
diff --git a/financial-tracker/notification-service/.env b/financial-tracker/notification-service/.env
new file mode 100644
index 0000000000000000000000000000000000000000..9361d60bd3551bb35d6ba377df05f41379363512
--- /dev/null
+++ b/financial-tracker/notification-service/.env
@@ -0,0 +1,2 @@
+MONGO_URI=mongodb://mongo:27017/notifications
+JWT_SECRET=your_jwt_secret
diff --git a/financial-tracker/notification-service/Dockerfile b/financial-tracker/notification-service/Dockerfile
index 1dd6cfae18c3c41e3c824d26b25492894b552a69..cece852b7a973bc2c6055207f9c70c29f5e79088 100644
--- a/financial-tracker/notification-service/Dockerfile
+++ b/financial-tracker/notification-service/Dockerfile
@@ -1,18 +1,14 @@
-FROM python:3.12
+FROM node:20-alpine
 
 WORKDIR /app
 
-# Set default database URL
-ENV DATABASE_URL=postgresql://user:password@notification-db:5432/notification_db
+COPY package*.json ./
 
-# Copy requirements.txt from root and install dependencies
-COPY requirements.txt .
-RUN pip install --no-cache-dir -r requirements.txt
+RUN npm install
 
-# Copy only the current service's code
-COPY ./notification-service/app /app
+COPY . .
 
-# Expose the service port
 EXPOSE 5005
+EXPOSE 8080
 
-CMD ["python", "app.py"]
+CMD ["npm", "start"]
diff --git a/financial-tracker/notification-service/app/controllers/notificationController.js b/financial-tracker/notification-service/app/controllers/notificationController.js
new file mode 100644
index 0000000000000000000000000000000000000000..8ef39d141a8a1133e55e27c0f9fc59b2a9960534
--- /dev/null
+++ b/financial-tracker/notification-service/app/controllers/notificationController.js
@@ -0,0 +1,38 @@
+const Notification = require("../models/Notification");
+
+exports.createNotification = async (req, res) => {
+  try {
+    const notification = new Notification(req.body);
+    await notification.save();
+    res.status(201).json(notification);
+  } catch (err) {
+    res.status(500).json({ error: err.message });
+  }
+};
+
+exports.getNotifications = async (req, res) => {
+  try {
+    const notifications = await Notification.find({ userId: req.params.userId });
+    res.json(notifications);
+  } catch (err) {
+    res.status(500).json({ error: err.message });
+  }
+};
+
+exports.markAsRead = async (req, res) => {
+  try {
+    await Notification.findByIdAndUpdate(req.params.id, { read: true });
+    res.status(200).json({ message: "Notification marked as read" });
+  } catch (err) {
+    res.status(500).json({ error: err.message });
+  }
+};
+
+exports.deleteNotification = async (req, res) => {
+  try {
+    await Notification.findByIdAndDelete(req.params.id);
+    res.status(200).json({ message: "Notification deleted" });
+  } catch (err) {
+    res.status(500).json({ error: err.message });
+  }
+};
diff --git a/financial-tracker/notification-service/app/middleware/auth.js b/financial-tracker/notification-service/app/middleware/auth.js
new file mode 100644
index 0000000000000000000000000000000000000000..4687a20f2dad73ae0a3404cd67cdc311490a41bf
--- /dev/null
+++ b/financial-tracker/notification-service/app/middleware/auth.js
@@ -0,0 +1,14 @@
+const jwt = require("jsonwebtoken");
+
+module.exports = (req, res, next) => {
+  const token = req.header("Authorization")?.replace("Bearer ", "");
+  if (!token) return res.status(401).json({ error: "Access denied. No token provided." });
+
+  try {
+    const decoded = jwt.verify(token, process.env.JWT_SECRET);
+    req.user = decoded;
+    next();
+  } catch (err) {
+    res.status(400).json({ error: "Invalid token." });
+  }
+};
\ No newline at end of file
diff --git a/financial-tracker/notification-service/app/models/Notification.js b/financial-tracker/notification-service/app/models/Notification.js
new file mode 100644
index 0000000000000000000000000000000000000000..59bf51ad33e849bd7f565d7545110f4af00ac092
--- /dev/null
+++ b/financial-tracker/notification-service/app/models/Notification.js
@@ -0,0 +1,11 @@
+const mongoose = require("mongoose");
+
+const NotificationSchema = new mongoose.Schema({
+  userId: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
+  message: { type: String, required: true },
+  type: { type: String, enum: ["budget", "transaction", "bill", "general"], default: "general" },
+  date: { type: Date, default: Date.now },
+  read: { type: Boolean, default: false },
+});
+
+module.exports = mongoose.model("Notification", NotificationSchema);
\ No newline at end of file
diff --git a/financial-tracker/notification-service/app/routes/notifications.js b/financial-tracker/notification-service/app/routes/notifications.js
new file mode 100644
index 0000000000000000000000000000000000000000..cf13216926ced3d57ba1889bbef8a45c9924be85
--- /dev/null
+++ b/financial-tracker/notification-service/app/routes/notifications.js
@@ -0,0 +1,11 @@
+const express = require("express");
+const router = express.Router();
+const controller = require("../controllers/notificationController");
+const auth = require("../middleware/auth");
+
+router.post("/", auth, controller.createNotification);
+router.get("/:userId", auth, controller.getNotifications);
+router.patch("/read/:id", auth, controller.markAsRead);
+router.delete("/:id", auth, controller.deleteNotification);
+
+module.exports = router;
diff --git a/financial-tracker/notification-service/package.json b/financial-tracker/notification-service/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8f5539a03b6c9ee50bfe8ba05487407bc76daf03
--- /dev/null
+++ b/financial-tracker/notification-service/package.json
@@ -0,0 +1,22 @@
+{
+  "name": "notification-service",
+  "version": "1.0.0",
+  "description": "Notification service for Financial Tracker",
+  "main": "app.js",
+  "scripts": {
+    "start": "node app.js",
+    "dev": "nodemon app.js"
+  },
+  "dependencies": {
+    "cors": "^2.8.5",
+    "express": "^4.18.2",
+    "jsonwebtoken": "^9.0.2",
+    "nodemailer": "^6.9.7",
+    "pg": "^8.11.3",
+    "ws": "^8.14.2",
+    "dotenv": "^16.3.1"
+  },
+  "devDependencies": {
+    "nodemon": "^3.0.1"
+  }
+} 
\ No newline at end of file
diff --git a/financial-tracker/notification-service/routes/notifications.js b/financial-tracker/notification-service/routes/notifications.js
new file mode 100644
index 0000000000000000000000000000000000000000..f376597018ae012baa982bb3a789fd90fff815ce
--- /dev/null
+++ b/financial-tracker/notification-service/routes/notifications.js
@@ -0,0 +1,199 @@
+const express = require('express');
+const router = express.Router();
+const { Pool } = require('pg');
+const jwt = require('jsonwebtoken');
+
+// PostgreSQL connection
+const pool = new Pool({
+    user: "user",
+    host: "notification-db",
+    database: "notification_db",
+    password: "password",
+    port: 5432,
+});
+
+// Get all notifications
+router.get('/', async (req, res) => {
+    try {
+        const result = await pool.query('SELECT * FROM notifications ORDER BY created_at DESC');
+        res.json(result.rows);
+    } catch (error) {
+        console.error('Get all notifications error:', error);
+        res.status(500).json({ error: 'Failed to fetch notifications' });
+    }
+});
+
+// Create notification
+router.post('/', async (req, res) => {
+    try {
+        const { user_id, title, message, type, priority = 'normal', metadata = {} } = req.body;
+
+        // Check user's notification preferences
+        const prefsResult = await pool.query(
+            'SELECT * FROM notification_preferences WHERE user_id = $1',
+            [user_id]
+        );
+        
+        const prefs = prefsResult.rows[0] || {
+            budget_alerts: true,
+            transaction_alerts: true,
+            bill_reminders: true,
+            email_notifications: true,
+            push_notifications: true
+        };
+
+        // Create notification in database
+        const result = await pool.query(
+            `INSERT INTO notifications 
+            (user_id, title, message, type, priority, metadata) 
+            VALUES ($1, $2, $3, $4, $5, $6) 
+            RETURNING *`,
+            [user_id, title, message, type, priority, metadata]
+        );
+
+        const notification = result.rows[0];
+        res.status(201).json(notification);
+    } catch (error) {
+        console.error('Create notification error:', error);
+        res.status(500).json({ error: 'Failed to create notification' });
+    }
+});
+
+// Get user's notifications
+router.get('/:userId', async (req, res) => {
+    try {
+        const { userId } = req.params;
+        const { unread_only } = req.query;
+
+        let query = 'SELECT * FROM notifications WHERE user_id = $1';
+        if (unread_only === 'true') {
+            query += ' AND read = FALSE';
+        }
+        query += ' ORDER BY created_at DESC';
+
+        const result = await pool.query(query, [userId]);
+        res.json(result.rows);
+    } catch (error) {
+        console.error('Get notifications error:', error);
+        res.status(500).json({ error: 'Failed to fetch notifications' });
+    }
+});
+
+// Mark notification as read
+router.put('/:id/read', async (req, res) => {
+    try {
+        const { id } = req.params;
+        const result = await pool.query(
+            'UPDATE notifications SET read = TRUE WHERE id = $1 RETURNING *',
+            [id]
+        );
+        
+        if (result.rows.length === 0) {
+            return res.status(404).json({ error: 'Notification not found' });
+        }
+        
+        res.json(result.rows[0]);
+    } catch (error) {
+        console.error('Mark as read error:', error);
+        res.status(500).json({ error: 'Failed to update notification' });
+    }
+});
+
+// Delete notification
+router.delete('/:id', async (req, res) => {
+    try {
+        const { id } = req.params;
+        const result = await pool.query(
+            'DELETE FROM notifications WHERE id = $1 RETURNING *',
+            [id]
+        );
+        
+        if (result.rows.length === 0) {
+            return res.status(404).json({ error: 'Notification not found' });
+        }
+        
+        res.json({ message: 'Notification deleted successfully' });
+    } catch (error) {
+        console.error('Delete notification error:', error);
+        res.status(500).json({ error: 'Failed to delete notification' });
+    }
+});
+
+// Get notification preferences
+router.get('/preferences/:userId', async (req, res) => {
+    try {
+        const { userId } = req.params;
+        const result = await pool.query(
+            'SELECT * FROM notification_preferences WHERE user_id = $1',
+            [userId]
+        );
+        
+        if (result.rows.length === 0) {
+            // Return default preferences if none set
+            return res.json({
+                user_id: userId,
+                budget_alerts: true,
+                transaction_alerts: true,
+                bill_reminders: true,
+                email_notifications: true,
+                push_notifications: true
+            });
+        }
+        
+        res.json(result.rows[0]);
+    } catch (error) {
+        console.error('Get preferences error:', error);
+        res.status(500).json({ error: 'Failed to fetch notification preferences' });
+    }
+});
+
+// Update notification preferences
+router.put('/preferences/:userId', async (req, res) => {
+    try {
+        const { userId } = req.params;
+        const {
+            budget_alerts,
+            transaction_alerts,
+            bill_reminders,
+            email_notifications,
+            push_notifications
+        } = req.body;
+
+        const result = await pool.query(
+            `INSERT INTO notification_preferences 
+            (user_id, budget_alerts, transaction_alerts, bill_reminders, email_notifications, push_notifications)
+            VALUES ($1, $2, $3, $4, $5, $6)
+            ON CONFLICT (user_id) 
+            DO UPDATE SET 
+                budget_alerts = $2,
+                transaction_alerts = $3,
+                bill_reminders = $4,
+                email_notifications = $5,
+                push_notifications = $6
+            RETURNING *`,
+            [userId, budget_alerts, transaction_alerts, bill_reminders, email_notifications, push_notifications]
+        );
+
+        res.json(result.rows[0]);
+    } catch (error) {
+        console.error('Update preferences error:', error);
+        res.status(500).json({ error: 'Failed to update notification preferences' });
+    }
+});
+
+// Mark all notifications as read
+router.put('/read-all/:userId', async (req, res) => {
+    try {
+        const { userId } = req.params;
+        await pool.query(
+            'UPDATE notifications SET read = TRUE WHERE user_id = $1',
+            [userId]
+        );
+        res.json({ message: 'All notifications marked as read' });
+    } catch (error) {
+        console.error('Mark all as read error:', error);
+        res.status(500).json({ error: 'Failed to update notifications' });
+    }
+});
+
+module.exports = router; 
\ No newline at end of file
diff --git a/financial-tracker/package-lock.json b/financial-tracker/package-lock.json
deleted file mode 100644
index bc227805b354553200e0a7bc37123691ce8c2f08..0000000000000000000000000000000000000000
--- a/financial-tracker/package-lock.json
+++ /dev/null
@@ -1,378 +0,0 @@
-{
-  "name": "financial-tracker",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "dependencies": {
-        "bootstrap": "^5.3.5",
-        "react-bootstrap": "^2.10.9"
-      }
-    },
-    "node_modules/@babel/runtime": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
-      "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "regenerator-runtime": "^0.14.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@popperjs/core": {
-      "version": "2.11.8",
-      "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
-      "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
-      "license": "MIT",
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/popperjs"
-      }
-    },
-    "node_modules/@react-aria/ssr": {
-      "version": "3.9.7",
-      "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.7.tgz",
-      "integrity": "sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@swc/helpers": "^0.5.0"
-      },
-      "engines": {
-        "node": ">= 12"
-      },
-      "peerDependencies": {
-        "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
-      }
-    },
-    "node_modules/@restart/hooks": {
-      "version": "0.4.16",
-      "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz",
-      "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==",
-      "license": "MIT",
-      "dependencies": {
-        "dequal": "^2.0.3"
-      },
-      "peerDependencies": {
-        "react": ">=16.8.0"
-      }
-    },
-    "node_modules/@restart/ui": {
-      "version": "1.9.4",
-      "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.4.tgz",
-      "integrity": "sha512-N4C7haUc3vn4LTwVUPlkJN8Ach/+yIMvRuTVIhjilNHqegY60SGLrzud6errOMNJwSnmYFnt1J0H/k8FE3A4KA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/runtime": "^7.26.0",
-        "@popperjs/core": "^2.11.8",
-        "@react-aria/ssr": "^3.5.0",
-        "@restart/hooks": "^0.5.0",
-        "@types/warning": "^3.0.3",
-        "dequal": "^2.0.3",
-        "dom-helpers": "^5.2.0",
-        "uncontrollable": "^8.0.4",
-        "warning": "^4.0.3"
-      },
-      "peerDependencies": {
-        "react": ">=16.14.0",
-        "react-dom": ">=16.14.0"
-      }
-    },
-    "node_modules/@restart/ui/node_modules/@restart/hooks": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.5.1.tgz",
-      "integrity": "sha512-EMoH04NHS1pbn07iLTjIjgttuqb7qu4+/EyhAx27MHpoENcB2ZdSsLTNxmKD+WEPnZigo62Qc8zjGnNxoSE/5Q==",
-      "license": "MIT",
-      "dependencies": {
-        "dequal": "^2.0.3"
-      },
-      "peerDependencies": {
-        "react": ">=16.8.0"
-      }
-    },
-    "node_modules/@restart/ui/node_modules/uncontrollable": {
-      "version": "8.0.4",
-      "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz",
-      "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==",
-      "license": "MIT",
-      "peerDependencies": {
-        "react": ">=16.14.0"
-      }
-    },
-    "node_modules/@swc/helpers": {
-      "version": "0.5.15",
-      "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
-      "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.8.0"
-      }
-    },
-    "node_modules/@types/prop-types": {
-      "version": "15.7.14",
-      "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
-      "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==",
-      "license": "MIT"
-    },
-    "node_modules/@types/react": {
-      "version": "19.1.0",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.0.tgz",
-      "integrity": "sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w==",
-      "license": "MIT",
-      "dependencies": {
-        "csstype": "^3.0.2"
-      }
-    },
-    "node_modules/@types/react-transition-group": {
-      "version": "4.4.12",
-      "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
-      "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
-      "license": "MIT",
-      "peerDependencies": {
-        "@types/react": "*"
-      }
-    },
-    "node_modules/@types/warning": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
-      "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==",
-      "license": "MIT"
-    },
-    "node_modules/bootstrap": {
-      "version": "5.3.5",
-      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.5.tgz",
-      "integrity": "sha512-ct1CHKtiobRimyGzmsSldEtM03E8fcEX4Tb3dGXz1V8faRwM50+vfHwTzOxB3IlKO7m+9vTH3s/3C6T2EAPeTA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/twbs"
-        },
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/bootstrap"
-        }
-      ],
-      "license": "MIT",
-      "peerDependencies": {
-        "@popperjs/core": "^2.11.8"
-      }
-    },
-    "node_modules/classnames": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
-      "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
-      "license": "MIT"
-    },
-    "node_modules/csstype": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
-      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
-      "license": "MIT"
-    },
-    "node_modules/dequal": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
-      "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/dom-helpers": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
-      "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/runtime": "^7.8.7",
-        "csstype": "^3.0.2"
-      }
-    },
-    "node_modules/invariant": {
-      "version": "2.2.4",
-      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
-      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
-      "license": "MIT",
-      "dependencies": {
-        "loose-envify": "^1.0.0"
-      }
-    },
-    "node_modules/js-tokens": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-      "license": "MIT"
-    },
-    "node_modules/loose-envify": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
-      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
-      "license": "MIT",
-      "dependencies": {
-        "js-tokens": "^3.0.0 || ^4.0.0"
-      },
-      "bin": {
-        "loose-envify": "cli.js"
-      }
-    },
-    "node_modules/object-assign": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/prop-types": {
-      "version": "15.8.1",
-      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
-      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
-      "license": "MIT",
-      "dependencies": {
-        "loose-envify": "^1.4.0",
-        "object-assign": "^4.1.1",
-        "react-is": "^16.13.1"
-      }
-    },
-    "node_modules/prop-types-extra": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
-      "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
-      "license": "MIT",
-      "dependencies": {
-        "react-is": "^16.3.2",
-        "warning": "^4.0.0"
-      },
-      "peerDependencies": {
-        "react": ">=0.14.0"
-      }
-    },
-    "node_modules/react": {
-      "version": "19.1.0",
-      "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
-      "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
-      "license": "MIT",
-      "peer": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/react-bootstrap": {
-      "version": "2.10.9",
-      "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.9.tgz",
-      "integrity": "sha512-TJUCuHcxdgYpOqeWmRApM/Dy0+hVsxNRFvq2aRFQuxhNi/+ivOxC5OdWIeHS3agxvzJ4Ev4nDw2ZdBl9ymd/JQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/runtime": "^7.24.7",
-        "@restart/hooks": "^0.4.9",
-        "@restart/ui": "^1.9.4",
-        "@types/prop-types": "^15.7.12",
-        "@types/react-transition-group": "^4.4.6",
-        "classnames": "^2.3.2",
-        "dom-helpers": "^5.2.1",
-        "invariant": "^2.2.4",
-        "prop-types": "^15.8.1",
-        "prop-types-extra": "^1.1.0",
-        "react-transition-group": "^4.4.5",
-        "uncontrollable": "^7.2.1",
-        "warning": "^4.0.3"
-      },
-      "peerDependencies": {
-        "@types/react": ">=16.14.8",
-        "react": ">=16.14.0",
-        "react-dom": ">=16.14.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/react-dom": {
-      "version": "19.1.0",
-      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
-      "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "scheduler": "^0.26.0"
-      },
-      "peerDependencies": {
-        "react": "^19.1.0"
-      }
-    },
-    "node_modules/react-is": {
-      "version": "16.13.1",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
-      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
-      "license": "MIT"
-    },
-    "node_modules/react-lifecycles-compat": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
-      "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==",
-      "license": "MIT"
-    },
-    "node_modules/react-transition-group": {
-      "version": "4.4.5",
-      "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
-      "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "@babel/runtime": "^7.5.5",
-        "dom-helpers": "^5.0.1",
-        "loose-envify": "^1.4.0",
-        "prop-types": "^15.6.2"
-      },
-      "peerDependencies": {
-        "react": ">=16.6.0",
-        "react-dom": ">=16.6.0"
-      }
-    },
-    "node_modules/regenerator-runtime": {
-      "version": "0.14.1",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
-      "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
-      "license": "MIT"
-    },
-    "node_modules/scheduler": {
-      "version": "0.26.0",
-      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
-      "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
-      "license": "MIT",
-      "peer": true
-    },
-    "node_modules/tslib": {
-      "version": "2.8.1",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
-      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
-      "license": "0BSD"
-    },
-    "node_modules/uncontrollable": {
-      "version": "7.2.1",
-      "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
-      "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/runtime": "^7.6.3",
-        "@types/react": ">=16.9.11",
-        "invariant": "^2.2.4",
-        "react-lifecycles-compat": "^3.0.4"
-      },
-      "peerDependencies": {
-        "react": ">=15.0.0"
-      }
-    },
-    "node_modules/warning": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
-      "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
-      "license": "MIT",
-      "dependencies": {
-        "loose-envify": "^1.0.0"
-      }
-    }
-  }
-}
diff --git a/financial-tracker/package.json b/financial-tracker/package.json
deleted file mode 100644
index 72a87f2d71eefe128a39a311e2e4f714ecdd9faa..0000000000000000000000000000000000000000
--- a/financial-tracker/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "dependencies": {
-    "bootstrap": "^5.3.5",
-    "react-bootstrap": "^2.10.9"
-  }
-}
diff --git a/financial-tracker/transaction-service/requirements.txt b/financial-tracker/transaction-service/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5f1fd100f7cb7cccbefae104a4436fd8d80d1a93
--- /dev/null
+++ b/financial-tracker/transaction-service/requirements.txt
@@ -0,0 +1,15 @@
+Flask==3.0.0
+Flask-SQLAlchemy==3.1.1
+Flask-JWT-Extended==4.6.0
+Flask-CORS==4.0.0
+psycopg2-binary==2.9.9
+python-dotenv==1.0.0
+requests==2.31.0
+SQLAlchemy==2.0.23
+Werkzeug==3.0.1
+python-dateutil==2.8.2
+pytest==7.4.3
+pytest-cov==4.1.0
+black==23.11.0
+flake8==6.1.0
+mypy==1.7.1 
\ No newline at end of file
diff --git a/financial-tracker/user-service/app/app.py b/financial-tracker/user-service/app/app.py
index 09c055f4f5f7736c1da89f93569e6d6bc0016076..a257f52d8d06b939ef1883af9696887ecf41c1ac 100644
--- a/financial-tracker/user-service/app/app.py
+++ b/financial-tracker/user-service/app/app.py
@@ -6,10 +6,10 @@ from flask_jwt_extended import (
 )
 from flask_sqlalchemy import SQLAlchemy
 from werkzeug.security import generate_password_hash, check_password_hash
+import enum
 import logging
 import os
 
-
 # Initialise Flask app
 app = Flask(__name__)
 app.debug = True
@@ -33,6 +33,92 @@ app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(hours=1)
 jwt = JWTManager(app)
 db = SQLAlchemy(app)
 
+# Define Enums for User model
+class CurrencyEnum(enum.Enum):
+    USD = "USD"
+    EUR = "EUR"
+    GBP = "GBP"
+    JPY = "JPY"
+    AUD = "AUD"
+    CAD = "CAD"
+    CHF = "CHF"
+    CNY = "CNY"
+    INR = "INR"
+    NZD = "NZD"
+    MXN = "MXN"
+    SGD = "SGD"
+    HKD = "HKD"
+    SEK = "SEK"
+    NOK = "NOK"
+    DKK = "DKK"
+    KRW = "KRW"
+    BRL = "BRL"
+    BWP = "BWP"
+    BDT = "BDT"
+    BGN = "BGN"
+    BHD = "BHD"
+    BIF = "BIF"
+    BOB = "BOB"
+    CVE = "CVE"
+    CZK = "CZK"
+    DOP = "DOP"
+    EGP = "EGP"
+    ETB = "ETB"
+    FJD = "FJD"
+    GHS = "GHS"
+    GIP = "GIP"
+    GMD = "GMD"
+    GNF = "GNF"
+    GTQ = "GTQ"
+    HUF = "HUF"
+    IDR = "IDR"
+    ISK = "ISK"
+    JOD = "JOD"
+    KES = "KES"
+    KWD = "KWD"
+    LAK = "LAK"
+    LKR = "LKR"
+    MAD = "MAD"
+    MGA = "MGA"
+    MWK = "MWK"
+    MYR = "MYR"
+    MZN = "MZN"
+    NGN = "NGN"
+    NPR = "NPR"
+    OMR = "OMR"
+    PEN = "PEN"
+    PHP = "PHP"
+    PKR = "PKR"
+    PLN = "PLN"
+    PYG = "PYG"
+    QAR = "QAR"
+    RON = "RON"
+    RWF = "RWF"
+    SAR = "SAR"
+    SLE = "SLE"
+    SRD = "SRD"
+    THB = "THB"
+    TND = "TND"
+    TRY = "TRY"
+    TWD = "TWD"
+    TZS = "TZS"
+    UGX = "UGX"
+    VND = "VND"
+    XAF = "XAF"
+    XCD = "XCD"
+    XOF = "XOF"
+    ZAR = "ZAR"
+    ZMW = "ZMW"
+
+class TimezoneEnum(enum.Enum):
+    UTC = "UTC"
+    GMT = "GMT"
+    BST = "BST"
+    EST = "Eastern Standard Time (EST)"
+    EDT = "Eastern Daylight Time (EDT)"
+    CST = "Central Standard Time (CST)"
+    CDT = "Central Daylight Time (CDT)"
+
 # DATABASE MODELS
 class User(db.Model):
     """User model for storing user information."""
@@ -41,6 +127,8 @@ class User(db.Model):
     last_name = db.Column(db.String(50), nullable=False)
     email = db.Column(db.String(120), unique=True, nullable=False)
     password_hash = db.Column(db.String(256), nullable=False)
+    currency = db.Column(db.Enum(CurrencyEnum), nullable=False, default='GBP')
+    timezone = db.Column(db.Enum(TimezoneEnum), nullable=False, default='GMT')
 
     def set_password(self, password):
         """Hash and store the user's password."""
@@ -127,14 +215,12 @@ def get_user():
         user_id = get_jwt_identity()
         app.logger.info(f"Extracted user_id from JWT: {user_id}")
 
-        # Convert user_id to integer
         try:
             user_id = int(user_id)
         except ValueError:
             app.logger.error("Invalid token payload: user_id is not an integer")
             return jsonify({"error": "Invalid token payload"}), 401
 
-        # Fetch user from DB
         user = User.query.get(user_id)
         app.logger.info(f"Fetched user from DB: {user}")
 
@@ -146,7 +232,11 @@ def get_user():
             "id": user.id,
             "first_name": user.first_name,
             "last_name": user.last_name,
-            "email": user.email
+            "email": user.email,
+            "preferences": {
+                "currency": user.currency.value,
+                "timezone": user.timezone.value
+            }
         }), 200
 
     except Exception as e:
@@ -165,6 +255,117 @@ def logout():
     return jsonify({"message": "Successfully logged out!"}), 200
 
 
+@app.route('/auth/password', methods=['PUT', 'OPTIONS'])
+@jwt_required()
+def update_password():
+    """Update user password."""
+    if request.method == 'OPTIONS':
+        return '', 204
+        
+    try:
+        data = request.get_json()
+        current_password = data.get('current_password')
+        new_password = data.get('new_password')
+
+        if not current_password or not new_password:
+            return jsonify({"error": "Current password and new password are required"}), 400
+
+        user_id = get_jwt_identity()
+        user = User.query.get(int(user_id))
+
+        if not user:
+            return jsonify({"error": "User not found"}), 404
+
+        if not user.check_password(current_password):
+            return jsonify({"error": "Invalid credentials"}), 401
+
+        user.set_password(new_password)
+        db.session.commit()
+
+        return jsonify({"message": "Password updated successfully"}), 200
+
+    except Exception as e:
+        app.logger.error(f"Error updating password: {str(e)}")
+        return jsonify({"error": "Failed to update password"}), 500
+
+
+@app.route('/auth/update', methods=['PUT', 'OPTIONS'])
+@jwt_required()
+def update_profile():
+    """Update user profile."""
+    if request.method == 'OPTIONS':
+        return '', 204
+        
+    try:
+        data = request.get_json()
+        user_id = get_jwt_identity()
+        user = User.query.get(int(user_id))
+
+        if not user:
+            return jsonify({"error": "User not found"}), 404
+
+        # Update basic fields if provided
+        if 'first_name' in data:
+            user.first_name = data['first_name']
+        if 'last_name' in data:
+            user.last_name = data['last_name']
+        if 'email' in data:
+            # Check if email is already taken by another user
+            existing_user = User.query.filter_by(email=data['email']).first()
+            if existing_user and existing_user.id != user.id:
+                return jsonify({"error": "Email already exists"}), 400
+            user.email = data['email']
+
+        # Update preferences if provided
+        if 'preferences' in data:
+            preferences = data['preferences']
+            if 'currency' in preferences:
+                user.currency = preferences['currency']
+            if 'timezone' in preferences:
+                user.timezone = preferences['timezone']
+
+        db.session.commit()
+
+        return jsonify({
+            "id": user.id,
+            "first_name": user.first_name,
+            "last_name": user.last_name,
+            "email": user.email,
+            "preferences": {
+                "currency": user.currency.value,
+                "timezone": user.timezone.value
+            }
+        }), 200
+
+    except Exception as e:
+        app.logger.error(f"Error updating profile: {str(e)}")
+        return jsonify({"error": "Failed to update profile"}), 500
+
+
+@app.route('/currencies', methods=['GET'])
+@jwt_required()
+def get_currencies():
+    """Retrieve supported currencies."""
+    try:
+        currencies = [currency.value for currency in CurrencyEnum]
+        return jsonify({"currencies": currencies}), 200
+    except Exception as e:
+        app.logger.error(f"Error retrieving currencies: {e}", exc_info=True)
+        return jsonify({"error": "An error occurred while fetching currencies"}), 500
+
+
+@app.route('/timezones', methods=['GET'])
+@jwt_required()
+def get_timezones():
+    """Retrieve supported timezones."""
+    try:
+        timezones = [timezone.value for timezone in TimezoneEnum]
+        return jsonify({"timezones": timezones}), 200
+    except Exception as e:
+        app.logger.error(f"Error retrieving timezones: {e}", exc_info=True)
+        return jsonify({"error": "An error occurred while fetching timezones"}), 500
+    
+    
 # HEALTH CHECK ROUTE
 @app.route('/health')
 def health():
@@ -173,8 +374,8 @@ def health():
     return jsonify({"status": "User service is running"}), 200
 
 
-# INITIALIZATION & RUNNING APP
-if __name__ == "__main__":
+# INITIALISATION & RUNNING APP
+if __name__ == "__main__":  
     # Create all tables in the database (if they don't exist)
     with app.app_context():
         db.create_all()  # Creates the tables for all models
diff --git a/financial-tracker/user-service/requirements.txt b/financial-tracker/user-service/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5d623d49e3224c9a7b1f6cee6d0ff8596b82beee
--- /dev/null
+++ b/financial-tracker/user-service/requirements.txt
@@ -0,0 +1,8 @@
+Flask==3.1.0
+Flask-JWT-Extended==4.7.1
+Flask-SQLAlchemy==3.1.1
+Flask-CORS==5.0.1
+psycopg2-binary==2.9.9
+python-dotenv==1.0.1
+pytz==2024.1
+Werkzeug>=3.1.0 
\ No newline at end of file