diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..e5d39a7e22ac3d0af7424a4896bb3c5f0b23fe77
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,7 @@
+.git
+__pycache__/
+*.pyc
+.vscode/
+migrations/
+*.db
+*.log
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..3cbc66ef54811ffebdfecb9907ae2328da1146c0
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,46 @@
+# Dockerfile
+
+# Use an official Python runtime as a parent image
+# Using slim-buster for a smaller image size
+FROM python:3.11-slim-buster
+
+# Set the working directory in the container
+WORKDIR /app
+
+# Prevent python from writing pyc files to disc (optional)
+ENV PYTHONDONTWRITEBYTECODE 1
+# Ensure python output is sent straight to terminal (useful for logs)
+ENV PYTHONUNBUFFERED 1
+
+# Install system dependencies first (cached if they don't change often)
+RUN apt-get update && apt-get install -y --no-install-recommends \
+    build-essential \
+    cmake \
+    pkg-config \
+    libcairo2-dev \
+    && rm -rf /var/lib/apt/lists/*
+
+# Copy only the requirements file first to leverage Docker cache
+COPY requirements.txt .
+
+# Install Python dependencies
+# This layer is cached and only re-run if requirements.txt changes
+RUN pip install --no-cache-dir -r requirements.txt
+
+# Now copy the rest of the application code
+# This needs to happen *after* pip install to leverage caching
+COPY . .
+
+# Make port 5000 available to the world outside this container
+# This is the port Gunicorn will listen on INSIDE the container
+EXPOSE 5000
+
+# Define environment variables (can be overridden at runtime)
+# Example: Setting Flask environment to production
+ENV FLASK_ENV production
+# You SHOULD set SECRET_KEY, DATABASE_URL etc. via docker run -e or docker-compose environment section
+
+# Run wsgi.py when the container launches using Gunicorn
+# Use 0.0.0.0 to allow connections from outside the container
+# Adjust the number of workers (-w) based on your EC2 instance resources
+CMD ["gunicorn", "--bind", "0.0.0.0:5000", "-w", "4", "wsgi:app"] 
\ No newline at end of file
diff --git a/README.md b/README.md
index 21b6e9bfa7bb2e0458d26d2a5810accc92518abb..7eb25f554531463caebde4db0a524bdf3650f761 100644
--- a/README.md
+++ b/README.md
@@ -162,7 +162,3 @@ Dự án được phát triển bởi nhóm sinh viên năm 2 tại Đại học
 3. Commit thay đổi của bạn (`git commit -m 'Add some amazing feature'`)
 4. Push lên nhánh (`git push origin feature/amazing-feature`)
 5. Tạo Pull Request
-
-## Giấy phép
-
-Phần mềm này được phân phối dưới giấy phép MIT. Xem tệp LICENSE để biết thêm thông tin.
diff --git a/app/__init__.py b/app/__init__.py
index b830505c688020d34ac68375ba07010c0c67a80a..9a46639c6b837ff32b797781e1fa86f3b46b58e8 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -69,13 +69,18 @@ def create_app(config_class=None): # Có thể bỏ config_class hoặc dùng ch
     # silent=True để không báo lỗi nếu file không tồn tại
     app.config.from_pyfile('config.py', silent=True)
 
-    # --- Quan trọng: Đảm bảo các cấu hình cần thiết được thiết lập --- 
-    # Nếu không có trong file config.py, cần có giá trị mặc định ở đây
-    app.config.setdefault('SECRET_KEY', 'a_default_secret_key_change_me_123') # Changed default key
-    app.config.setdefault('SQLALCHEMY_DATABASE_URI', 'mysql://root:MinhDZ3009@localhost/ccu') 
-    app.config.setdefault('SQLALCHEMY_TRACK_MODIFICATIONS', False)
-    app.config.setdefault('UPLOAD_FOLDER', os.path.join(app.instance_path, 'uploads'))
-    app.config.setdefault('WTF_CSRF_ENABLED', True)
+    # --- Quan trọng: Thiết lập cấu hình từ biến môi trường hoặc giá trị mặc định --- 
+    app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'replace_with_strong_key_in_production')
+    
+    # Ưu tiên đọc từ biến môi trường DATABASE_URL, nếu không có thì dùng giá trị mặc định
+    # Đảm bảo giá trị mặc định cũng dùng đúng driver 'mysql+mysqlconnector'
+    default_db_uri = 'mysql+mysqlconnector://ccuuser:MinhDZ3009@localhost/ccu' # Thay your_local_password nếu cần
+    app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL', default_db_uri)
+    
+    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
+    app.config['UPLOAD_FOLDER'] = os.environ.get('UPLOAD_FOLDER', os.path.join(app.instance_path, 'uploads'))
+    app.config['MAX_CONTENT_LENGTH'] = int(os.environ.get('MAX_CONTENT_LENGTH', 16 * 1024 * 1024)) # Default 16MB
+    app.config['WTF_CSRF_ENABLED'] = True # Nên luôn bật CSRF
     
     # Tạo thư mục UPLOAD_FOLDER nếu chưa có
     upload_folder = app.config['UPLOAD_FOLDER']
@@ -89,6 +94,9 @@ def create_app(config_class=None): # Có thể bỏ config_class hoặc dùng ch
             print(f"Error creating upload folder {upload_folder}: {e}") # Log lỗi nếu không tạo được
     # -----------------------------------------------------------------
     
+    # Print the final DB URI being used before initializing db
+    print(f"DEBUG: SQLALCHEMY_DATABASE_URI before db.init_app: {app.config.get('SQLALCHEMY_DATABASE_URI')}")
+
     # Liên kết các extensions với app
     db.init_app(app)
     login_manager.init_app(app)
diff --git a/app/forms/dietitian_forms.py b/app/forms/dietitian_forms.py
index c2fd31e77e232b2457afe06c27c6f2ad62da2204..685419b6e912c2c9627952a844d849b4488f965d 100644
--- a/app/forms/dietitian_forms.py
+++ b/app/forms/dietitian_forms.py
@@ -1,18 +1,34 @@
 from flask_wtf import FlaskForm
-from wtforms import StringField, PasswordField, TextAreaField, SubmitField, ValidationError
-from wtforms.validators import DataRequired, Email, Length, EqualTo
+from wtforms import StringField, PasswordField, TextAreaField, SubmitField, ValidationError, SelectField
+from wtforms.validators import DataRequired, Email, Length, EqualTo, Optional
 from app.models import User
+from app.models.dietitian import DietitianStatus
 
 class DietitianForm(FlaskForm):
-    firstName = StringField('Họ', validators=[DataRequired(), Length(max=50)])
-    lastName = StringField('Tên', validators=[DataRequired(), Length(max=50)])
+    firstName = StringField('First Name', validators=[DataRequired(), Length(max=50)])
+    lastName = StringField('Last Name', validators=[DataRequired(), Length(max=50)])
     email = StringField('Email', validators=[DataRequired(), Email(), Length(max=100)])
-    password = PasswordField('Mật khẩu', validators=[DataRequired(), Length(min=6)])
-    phone = StringField('Số điện thoại', validators=[Length(max=20)])
-    specialization = StringField('Chuyên môn', validators=[Length(max=100)])
-    notes = TextAreaField('Ghi chú')
-    submit = SubmitField('Tạo tài khoản')
+    password = PasswordField('Password', validators=[DataRequired(), Length(min=6)])
+    phone = StringField('Phone Number', validators=[Length(max=20)])
+    specialization = StringField('Specialization', validators=[Length(max=100)])
+    notes = TextAreaField('Notes')
+    submit = SubmitField('Create Account')
 
     def validate_email(self, field):
         if User.query.filter_by(email=field.data).first():
-            raise ValidationError('Email này đã được sử dụng.')
\ No newline at end of file
+            raise ValidationError('This email is already in use.')
+
+class EditDietitianForm(FlaskForm):
+    firstName = StringField('First Name', validators=[DataRequired(), Length(max=50)])
+    lastName = StringField('Last Name', validators=[DataRequired(), Length(max=50)])
+    email = StringField('Email', validators=[DataRequired(), Email(), Length(max=100)])
+    phone = StringField('Phone Number', validators=[Length(max=20)])
+    specialization = StringField('Specialization', validators=[Length(max=100)])
+    notes = TextAreaField('Notes')
+    submit = SubmitField('Update Information')
+
+    def validate_email(self, field):
+        # Kiểm tra email đã tồn tại nhưng bỏ qua email hiện tại của dietitian
+        user = User.query.filter_by(email=field.data).first()
+        if user and user.email != self.email.default:
+            raise ValidationError('This email is already in use by another user.')
\ No newline at end of file
diff --git a/app/routes/dietitians.py b/app/routes/dietitians.py
index f986117d27ae6bffd97fb27b9f54506da6479190..12cbd2615a0d545469679c7f83f97fa2cc5c4830 100644
--- a/app/routes/dietitians.py
+++ b/app/routes/dietitians.py
@@ -2,13 +2,14 @@ from flask import Blueprint, render_template, request, redirect, url_for, flash,
 from flask_login import login_required, current_user
 from app import db
 from app.models.dietitian import Dietitian, DietitianStatus
-from app.models.patient import Patient
+from app.models.patient import Patient, PatientStatus
 from app.models.encounter import Encounter
 from sqlalchemy import desc, or_, func, text
 from datetime import datetime
 from app.models.user import User
 from flask import current_app
-from app.forms.dietitian_forms import DietitianForm
+from app.forms.dietitian_forms import DietitianForm, EditDietitianForm
+from app.utils.decorators import permission_required
 
 dietitians_bp = Blueprint('dietitians', __name__, url_prefix='/dietitians')
 
@@ -113,7 +114,12 @@ def new():
                 email=form.email.data,
                 role='Dietitian' # Mặc định là Dietitian
             )
-            new_user.set_password(form.password.data) # Hash mật khẩu từ form
+            if hasattr(form, 'password') and form.password.data:
+                new_user.set_password(form.password.data)
+            else:
+                flash('Mật khẩu là bắt buộc khi tạo mới.', 'danger')
+                return render_template('dietitians/new.html', form=form)
+            
             db.session.add(new_user)
             db.session.flush() # Lấy userID sau khi add
 
@@ -123,11 +129,14 @@ def new():
                 firstName=form.firstName.data, # Đồng bộ tên
                 lastName=form.lastName.data,   # Đồng bộ họ
                 email=form.email.data,         # Đồng bộ email
-                phone=form.phone.data,
-                specialization=form.specialization.data,
-                notes=form.notes.data,
+                phone=form.phone.data if hasattr(form, 'phone') else None,
+                specialization=form.specialization.data if hasattr(form, 'specialization') else None,
+                notes=form.notes.data if hasattr(form, 'notes') else None,
                 status=DietitianStatus.AVAILABLE # Mặc định là AVAILABLE
             )
+            if hasattr(form, 'phone') and form.phone.data:
+                new_user.phone = form.phone.data
+            
             db.session.add(new_dietitian)
             db.session.commit()
             
@@ -136,85 +145,99 @@ def new():
         except Exception as e:
             db.session.rollback()
             current_app.logger.error(f"Lỗi khi tạo tài khoản dietitian: {e}")
-            flash(f'Lỗi khi tạo tài khoản: {str(e)}', 'error')
+            flash(f'Lỗi khi tạo tài khoản: {str(e)}', 'danger')
             
     # GET request hoặc form validation thất bại
-    return render_template('dietitians/new.html', form=form) # Truyền form vào template
+    return render_template('dietitians/new.html', form=form)
 
 @dietitians_bp.route('/<int:id>/edit', methods=['GET', 'POST'])
 @login_required
 def edit(id):
-    """Chỉnh sửa chuyên gia dinh dưỡng"""
+    """Edit a dietitian (Admin view)"""
     dietitian = Dietitian.query.filter_by(dietitianID=id).first_or_404()
-    
-    # Kiểm tra quyền: chỉ admin hoặc chính dietitian đó mới được sửa
-    if not current_user.is_admin and (not dietitian.user or dietitian.user_id != current_user.userID):
-        flash('Bạn không có quyền chỉnh sửa thông tin này.', 'danger')
-        return redirect(url_for('dietitians.index'))
-    
-    # Nếu user đang sửa profile của chính mình, chuyển hướng đến edit_profile
-    if dietitian.user and dietitian.user_id == current_user.userID:
-        return redirect(url_for('auth.edit_profile'))
-    
-    # Nếu là admin đang sửa thông tin dietitian khác
-    if request.method == 'POST':
-        # Lấy dữ liệu form
-        firstName = request.form.get('firstName', '').strip()
-        lastName = request.form.get('lastName', '').strip()
-        email = request.form.get('email', '').strip()
-        phone = request.form.get('phone', '').strip()
-        specialization = request.form.get('specialization', '').strip()
-        notes = request.form.get('notes', '').strip()
-        
-        # Kiểm tra dữ liệu
-        if not firstName or not lastName or not email:
-            flash('Họ, tên và email là bắt buộc.', 'danger')
-            return render_template('dietitians/edit_admin.html', dietitian=dietitian, status_options=DietitianStatus)
-        
+    user = dietitian.user # Get the associated user
+
+    # --- Permissions --- 
+    # Only Admin can access this route directly
+    if not current_user.is_admin:
+        # If a dietitian is trying to edit their own profile, redirect them
+        if user and user.userID == current_user.userID:
+             return redirect(url_for('auth.edit_profile'))
+        else:
+            flash('You do not have permission to access this page.', 'danger')
+            return redirect(url_for('dietitians.index'))
+    # -----------------
+
+    # Use EditDietitianForm (without password or status field)
+    form = EditDietitianForm(obj=dietitian)
+
+    if form.validate_on_submit():
         try:
-            # Cập nhật thông tin dietitian
-            dietitian.firstName = firstName
-            dietitian.lastName = lastName
-            dietitian.email = email
-            dietitian.phone = phone
-            dietitian.specialization = specialization
-            dietitian.notes = notes
-            # Trạng thái không cho sửa trực tiếp ở đây
+            # Update dietitian information from form
+            dietitian.firstName = form.firstName.data
+            dietitian.lastName = form.lastName.data
+            dietitian.email = form.email.data
+            dietitian.phone = form.phone.data
+            dietitian.specialization = form.specialization.data
+            dietitian.notes = form.notes.data
             
-            # Đồng bộ ngược lại User nếu có thay đổi email, phone (tùy chọn)
-            if dietitian.user:
-                dietitian.user.firstName = dietitian.firstName
-                dietitian.user.lastName = dietitian.lastName
-                dietitian.user.email = dietitian.email
-                dietitian.user.phone = dietitian.phone
+            # No more status update - status is managed elsewhere
             
+            # Synchronize changes to linked User (if exists)
+            if user:
+                user.firstName = form.firstName.data
+                user.lastName = form.lastName.data
+                user.email = form.email.data # Sync User email
+                user.phone = form.phone.data
+
             db.session.commit()
-            flash('Cập nhật thông tin thành công!', 'success')
+            flash('Information updated successfully!', 'success')
             return redirect(url_for('dietitians.show', id=dietitian.dietitianID))
+        
         except Exception as e:
             db.session.rollback()
-            flash(f'Có lỗi xảy ra: {str(e)}', 'danger')
-            # Render lại form với dietitian object
-            return render_template('dietitians/edit_admin.html', dietitian=dietitian, status_options=DietitianStatus)
+            current_app.logger.error(f"Error updating dietitian {id}: {e}")
+            flash(f'An error occurred during update: {str(e)}', 'danger')
 
-    # GET request: hiển thị form chỉnh sửa (dùng template riêng cho admin sửa)
-    # Lưu ý: Cần tạo template edit_admin.html hoặc điều chỉnh edit.html cũ
-    # Sử dụng một template riêng như edit_admin.html sẽ rõ ràng hơn
-    return render_template('dietitians/edit_admin.html', dietitian=dietitian, status_options=DietitianStatus)
+    # Render template, pass form to context
+    return render_template('dietitians/edit_admin.html', 
+                          dietitian=dietitian, 
+                          form=form)
 
 @dietitians_bp.route('/<int:id>/delete', methods=['POST'])
 @login_required
 def delete(id):
-    """Xóa chuyên gia dinh dưỡng"""
+    """Xóa chuyên gia dinh dưỡng và User liên kết"""
+    # --- Quyền hạn: Chỉ Admin --- 
+    if not current_user.is_admin:
+        flash('Bạn không có quyền thực hiện hành động này.', 'danger')
+        return redirect(url_for('dietitians.index'))
+    # --------------------------
+    
     dietitian = Dietitian.query.get_or_404(id)
+    user_to_delete = dietitian.user # Lấy user liên kết
     
+    # Kiểm tra xem dietitian có đang quản lý bệnh nhân không
+    assigned_patient_count = Patient.query.filter_by(assigned_dietitian_user_id=dietitian.user_id).count()
+    if assigned_patient_count > 0:
+        flash(f'Không thể xóa chuyên gia dinh dưỡng {dietitian.full_name} vì họ đang quản lý {assigned_patient_count} bệnh nhân. Vui lòng gán lại bệnh nhân trước.', 'warning')
+        return redirect(url_for('dietitians.show', id=id))
+
     try:
+        # Xóa Dietitian profile trước
         db.session.delete(dietitian)
+        db.session.flush() # Đảm bảo dietitian bị xóa trước khi xóa user (nếu có ràng buộc)
+        
+        # Xóa User liên kết (nếu có)
+        if user_to_delete:
+            db.session.delete(user_to_delete)
+            
         db.session.commit()
-        flash('Xóa chuyên gia dinh dưỡng thành công!', 'success')
+        flash(f'Đã xóa chuyên gia dinh dưỡng {dietitian.firstName} {dietitian.lastName} và tài khoản liên kết thành công!', 'success')
     except Exception as e:
         db.session.rollback()
-        flash(f'Lỗi: {str(e)}', 'error')
+        current_app.logger.error(f"Error deleting dietitian {id}: {e}")
+        flash(f'Lỗi khi xóa chuyên gia dinh dưỡng: {str(e)}', 'error')
     
     return redirect(url_for('dietitians.index'))
 
@@ -224,67 +247,104 @@ def assign_dietitian(patient_id):
     """Phân công chuyên gia dinh dưỡng cho bệnh nhân"""
     patient = Patient.query.filter_by(patient_id=patient_id).first_or_404()
     
-    # Tìm encounter hiện tại của bệnh nhân
-    encounter = Encounter.query.filter_by(
-        patient_id=patient.id,
-        dischargeDateTime=None
-    ).order_by(Encounter.admissionDateTime.desc()).first()
-    
-    if not encounter:
-        flash('Không tìm thấy thông tin nhập viện của bệnh nhân này.', 'error')
-        return redirect(url_for('patients.patient_detail', patient_id=patient.patient_id))
-    
-    dietitian_id = request.form.get('dietitian_id')
-    
-    if dietitian_id:
-        # Nếu có chỉ định cụ thể dietitian
-        dietitian = Dietitian.query.get_or_404(int(dietitian_id))
+    # Nên dùng ID dạng số của patient (thường là primary key) thay vì patient_id dạng string
+    # patient = Patient.query.get_or_404(patient_id_int) # Nếu có primary key là số
+
+    # Lấy dietitian_id từ form
+    dietitian_user_id = request.form.get('dietitian_user_id', type=int)
+
+    if dietitian_user_id:
+        # Tìm User của dietitian được chọn
+        dietitian_user = User.query.filter_by(userID=dietitian_user_id, role='Dietitian').first_or_404()
     else:
-        # Tự động phân công dietitian có ít bệnh nhân nhất
-        dietitian = Dietitian.get_least_busy_dietitian()
+        # Tự động phân công dietitian có ít bệnh nhân nhất (logic cần xem lại)
+        # Logic get_least_busy_dietitian() cần trả về User object
+        # dietitian_user = Dietitian.get_least_busy_dietitian_user() # Ví dụ
+        # if not dietitian_user:
+        #     flash('Không tìm thấy chuyên gia dinh dưỡng khả dụng.', 'error')
+        #     return redirect(url_for('patients.patient_detail', patient_id=patient.patient_id)) # Nên dùng patient_id dạng string
+        flash('Chức năng tự động phân công chưa được triển khai đầy đủ.', 'warning')
+        return redirect(url_for('patients.patient_detail', patient_id=patient.patient_id)) # Dùng patient_id dạng string
+
+    # Cập nhật trường assigned_dietitian_user_id của Patient
+    patient.assigned_dietitian_user_id = dietitian_user.userID
+    patient.assignment_date = datetime.utcnow() # Ghi nhận thời gian gán
+    # Cập nhật trạng thái bệnh nhân nếu cần (ví dụ: từ NEW -> NEEDS_ASSESSMENT)
+    if patient.status == PatientStatus.NEW:
+        patient.status = PatientStatus.NEEDS_ASSESSMENT
         
-        if not dietitian:
-            flash('Không tìm thấy chuyên gia dinh dưỡng khả dụng.', 'error')
-            return redirect(url_for('patients.patient_detail', patient_id=patient.patient_id))
-    
-    # Cập nhật encounter với dietitian mới
-    encounter.dietitian_id = dietitian.id
     db.session.commit()
     
-    flash(f'Đã phân công bệnh nhân {patient.full_name} cho chuyên gia dinh dưỡng {dietitian.full_name}.', 'success')
-    return redirect(url_for('patients.patient_detail', patient_id=patient.patient_id))
+    flash(f'Đã phân công bệnh nhân {patient.full_name} cho chuyên gia dinh dưỡng {dietitian_user.full_name}.', 'success')
+    return redirect(url_for('patients.patient_detail', patient_id=patient.patient_id)) # Dùng patient_id dạng string
 
 @dietitians_bp.route('/<int:id>/patients')
-def patients(id):
+@login_required # Chỉ cần login, không cần quyền cụ thể để xem profile
+def patients_list(id): # Đổi tên hàm để tránh trùng lặp
+    """Hiển thị danh sách bệnh nhân của một chuyên gia dinh dưỡng cụ thể (theo dietitianID)"""
     dietitian = Dietitian.query.get_or_404(id)
-    patients = Patient.query.filter(Patient.dietitian_id == id).all()
-    return render_template('dietitians/patients.html', dietitian=dietitian, patients=patients)
+    
+    # Lấy danh sách bệnh nhân được gán qua user_id
+    if dietitian.user_id:
+        assigned_patients = Patient.query.filter_by(assigned_dietitian_user_id=dietitian.user_id)\
+                                       .order_by(Patient.lastName, Patient.firstName).all()
+    else:
+        assigned_patients = [] # Nếu dietitian chưa có user liên kết thì không có BN nào
+        
+    # Render template khác hoặc phần riêng trong show.html
+    # Ví dụ: return render_template('dietitians/_assigned_patients.html', patients=assigned_patients)
+    # Hoặc nếu dùng trong show.html thì không cần route riêng này
+    flash('Route này có thể không cần thiết nếu danh sách bệnh nhân đã hiển thị trong trang show.', 'info')
+    return redirect(url_for('.show', id=id))
+
+@dietitians_bp.route('/<int:dietitian_id>/assign_patient/<string:patient_id>', methods=['POST'])
+@login_required
+@permission_required('ADMIN') # Chỉ Admin mới được gán BN tuỳ ý
+def assign_patient_manual(dietitian_id, patient_id):
+    """Gán một bệnh nhân cụ thể cho một chuyên gia dinh dưỡng (Admin)"""
+    patient = Patient.query.filter_by(patient_id=patient_id).first_or_404()
+    dietitian = Dietitian.query.get_or_404(dietitian_id)
+
+    if not dietitian.user_id:
+        flash('Chuyên gia dinh dưỡng này chưa có tài khoản người dùng liên kết.', 'error')
+        return redirect(url_for('dietitians.show', id=dietitian_id))
 
-@dietitians_bp.route('/<int:id>/assign_patient/<int:patient_id>', methods=['POST'])
-def assign_patient(id, patient_id):
     try:
-        patient = Patient.query.get_or_404(patient_id)
-        patient.dietitian_id = id
+        patient.assigned_dietitian_user_id = dietitian.user_id
+        patient.assignment_date = datetime.utcnow()
+        if patient.status == PatientStatus.NEW:
+             patient.status = PatientStatus.NEEDS_ASSESSMENT
         db.session.commit()
-        flash(f'Bệnh nhân {patient.fullName} đã được gán cho chuyên gia dinh dưỡng này!', 'success')
+        flash(f'Bệnh nhân {patient.full_name} đã được gán cho {dietitian.full_name}!', 'success')
     except Exception as e:
         db.session.rollback()
         flash(f'Đã xảy ra lỗi: {str(e)}', 'error')
-    return redirect(url_for('dietitians.show', id=id))
+    return redirect(url_for('dietitians.show', id=dietitian_id))
 
-@dietitians_bp.route('/<int:id>/unassign_patient/<int:patient_id>', methods=['POST'])
+@dietitians_bp.route('/<int:dietitian_id>/unassign_patient/<string:patient_id>', methods=['POST'])
 @login_required
-def unassign_patient(id, patient_id):
-    """Bỏ phân công bệnh nhân"""
+@permission_required('ADMIN') # Chỉ Admin mới được bỏ gán
+def unassign_patient_manual(dietitian_id, patient_id):
+    """Bỏ phân công bệnh nhân khỏi chuyên gia dinh dưỡng (Admin)"""
+    patient = Patient.query.filter_by(patient_id=patient_id).first_or_404()
+    dietitian = Dietitian.query.get_or_404(dietitian_id)
+
+    if not dietitian.user_id:
+         flash('Chuyên gia dinh dưỡng này không có tài khoản người dùng liên kết.', 'warning')
+         return redirect(url_for('dietitians.show', id=dietitian_id))
+
     try:
-        patient = Patient.query.get_or_404(patient_id)
-        if patient.dietitian_id == id:
-            patient.dietitian_id = None
+        if patient.assigned_dietitian_user_id == dietitian.user_id:
+            patient.assigned_dietitian_user_id = None
+            patient.assignment_date = None # Xóa ngày gán
+            # Cân nhắc chuyển trạng thái bệnh nhân về NEW hoặc giữ nguyên
+            # if patient.status == PatientStatus.NEEDS_ASSESSMENT:
+            #     patient.status = PatientStatus.NEW
             db.session.commit()
-            flash(f'Bệnh nhân {patient.fullName} đã được gỡ bỏ khỏi chuyên gia dinh dưỡng này!', 'success')
+            flash(f'Bệnh nhân {patient.full_name} đã được gỡ bỏ khỏi {dietitian.full_name}!', 'success')
         else:
-            flash('Bệnh nhân không được gán cho chuyên gia dinh dưỡng này!', 'error')
+            flash('Bệnh nhân này không được gán cho chuyên gia dinh dưỡng này!', 'error')
     except Exception as e:
         db.session.rollback()
         flash(f'Đã xảy ra lỗi: {str(e)}', 'error')
-    return redirect(url_for('dietitians.show', id=id)) 
\ No newline at end of file
+    return redirect(url_for('dietitians.show', id=dietitian_id)) 
\ No newline at end of file
diff --git a/app/templates/_macros.html b/app/templates/_macros.html
index 2102e42caf877b9227061f2b2f59d77059ef82d8..f60ab57ec52d723db58405444501a17476900a93 100644
--- a/app/templates/_macros.html
+++ b/app/templates/_macros.html
@@ -29,27 +29,27 @@
 {% endmacro %}
 
 {% macro status_badge(status_value) %}
-    {% set status_str = status_value | string | upper %}
-    {% set badge_class = 'bg-gray-100 text-gray-800' %} {# Default #}
-    {% set status_text = status_str.replace('_', ' ').title() %}
-
-    {% if status_str == 'AVAILABLE' or status_str == 'ACTIVE' or status_str == 'COMPLETED' or status_str == 'SUCCESS' %}
-        {% set badge_class = 'bg-green-100 text-green-800' %}
-    {% elif status_str == 'UNAVAILABLE' or status_str == 'INACTIVE' or status_str == 'FAILED' or status_str == 'ERROR' %}
-        {% set badge_class = 'bg-red-100 text-red-800' %}
-    {% elif status_str == 'PENDING' or status_str == 'NEEDS_ASSESSMENT' or status_str == 'IN_PROGRESS' %}
-        {% set badge_class = 'bg-yellow-100 text-yellow-800' %}
-    {% elif status_str == 'ON_LEAVE' %}
-        {% set badge_class = 'bg-blue-100 text-blue-800' %}
-        {% set status_text = 'On Leave' %}
-    {% elif status_str == 'DRAFT' %}
-        {% set badge_class = 'bg-purple-100 text-purple-800' %}
-    {% elif status_str == 'ASSESSMENT_IN_PROGRESS' %}
-        {% set badge_class = 'bg-indigo-100 text-indigo-800' %}
+    {% if status_value == "AVAILABLE" %}
+        <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
+            {{ status_value.replace("_", " ").title() }}
+        </span>
+    {% elif status_value == "BUSY" %}
+        <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">
+            {{ status_value.replace("_", " ").title() }}
+        </span>
+    {% elif status_value == "ON_LEAVE" %}
+        <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-orange-100 text-orange-800">
+            {{ status_value.replace("_", " ").title() }}
+        </span>
+    {% elif status_value == "UNAVAILABLE" %}
+        <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">
+            {{ status_value.replace("_", " ").title() }}
+        </span>
+    {% else %}
+        <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">
+            {{ status_value.replace("_", " ").title() }}
+        </span>
     {% endif %}
-    <span class="px-2.5 py-0.5 inline-flex text-xs leading-5 font-semibold rounded-full {{ badge_class }}">
-        {{ status_text }}
-    </span>
 {% endmacro %}
 
 {% macro patient_status_badge(status) %}
@@ -138,4 +138,44 @@
             </div>
         {% endif %}
     {% endwith %}
+{% endmacro %}
+
+{% macro render_form_field(field) %}
+    {% if field.type != 'CSRFTokenField' and field.type != 'SubmitField' %}
+        <div class="form-group mb-4">
+            {% if field.type == 'BooleanField' %}
+                <div class="flex items-center">
+                    {{ field(class="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded") }}
+                    {{ field.label(class="ml-2 block text-sm text-gray-900") }}
+                </div>
+            {% else %}
+                {{ field.label(class="block text-sm font-medium text-gray-700 mb-1") }}
+                {% if field.type == 'TextAreaField' %}
+                    {{ field(class="shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-300 rounded-md", rows=4) }}
+                {% elif field.type == 'SelectField' %}
+                    {{ field(class="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm") }}
+                {% else %}
+                    {{ field(class="shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-300 rounded-md") }}
+                {% endif %}
+            {% endif %}
+            
+            {% if field.errors %}
+                <div class="mt-1">
+                    {% for error in field.errors %}
+                        <p class="text-sm text-red-600">{{ error }}</p>
+                    {% endfor %}
+                </div>
+            {% endif %}
+            
+            {% if field.description %}
+                <p class="mt-1 text-sm text-gray-500">{{ field.description }}</p>
+            {% endif %}
+        </div>
+    {% elif field.type == 'CSRFTokenField' %}
+        {{ field }}
+    {% elif field.type == 'SubmitField' %}
+        <button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 transition duration-200">
+            {{ field.label.text }}
+        </button>
+    {% endif %} 
 {% endmacro %} 
\ No newline at end of file
diff --git a/app/templates/admin/edit_profile.html b/app/templates/admin/edit_profile.html
index cbe1e54d4fb45ca0815a2a0142b5732e4f739df6..754aa32e226b26d441e6979317af4affbb023a32 100644
--- a/app/templates/admin/edit_profile.html
+++ b/app/templates/admin/edit_profile.html
@@ -44,11 +44,11 @@
 
                 <div class="grid grid-cols-1 gap-y-6 gap-x-4 sm:grid-cols-6">
                     <div class="sm:col-span-3">
-                        {{ render_field(form.firstName, label_text="Tên") }}
+                        {{ render_field(form.firstName, label_text="First Name") }}
                     </div>
 
                     <div class="sm:col-span-3">
-                        {{ render_field(form.lastName, label_text="Họ") }}
+                        {{ render_field(form.lastName, label_text="Last Name") }}
                     </div>
 
                     <div class="sm:col-span-4">
diff --git a/app/templates/base.html b/app/templates/base.html
index ca9f8fc4b067caa41f147ca6ee334c5f56ad7e56..419abcf096ece45c59141755fcb4f7ad52a7582e 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -5,6 +5,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta name="csrf-token" content="{{ csrf_token }}">
     <title>{% block title %}CCU HTM{% endblock %}</title>
+    <link rel="icon" type="image/png" href="{{ url_for('static', filename='img/logo.png') }}">
     <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
     <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
     <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1/dist/chart.min.js"></script>
diff --git a/app/templates/dietitians/create.html b/app/templates/dietitians/create.html
deleted file mode 100644
index 45671da57daf9a2c26b6ef651bc89696077d2db9..0000000000000000000000000000000000000000
--- a/app/templates/dietitians/create.html
+++ /dev/null
@@ -1,97 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Thêm chuyên gia dinh dưỡng - CCU HTM{% endblock %}
-
-{% block header %}Thêm chuyên gia dinh dưỡng mới{% endblock %}
-
-{% block content %}
-<div class="container mx-auto px-4 py-6">
-    <!-- Breadcrumb -->
-    <div class="mb-6">
-        <nav class="flex" aria-label="Breadcrumb">
-            <ol class="inline-flex items-center space-x-1 md:space-x-3">
-                <li class="inline-flex items-center">
-                    <a href="{{ url_for('handle_root') }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 transition duration-200">
-                        <svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path></svg>
-                        Trang chủ
-                    </a>
-                </li>
-                <li>
-                    <div class="flex items-center">
-                        <svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
-                        <a href="{{ url_for('dietitians.index') }}" class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 transition duration-200">Chuyên gia dinh dưỡng</a>
-                    </div>
-                </li>
-                <li aria-current="page">
-                    <div class="flex items-center">
-                        <svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
-                        <span class="ml-1 text-sm font-medium text-gray-500 md:ml-2">Thêm mới</span>
-                    </div>
-                </li>
-            </ol>
-        </nav>
-    </div>
-
-    <div class="max-w-4xl mx-auto">
-        <div class="bg-white shadow overflow-hidden sm:rounded-lg">
-            <div class="px-4 py-5 sm:px-6 border-b border-gray-200">
-                <h3 class="text-lg leading-6 font-medium text-gray-900">Thông tin chuyên gia dinh dưỡng</h3>
-                <p class="mt-1 max-w-2xl text-sm text-gray-500">Nhập thông tin chi tiết cho chuyên gia dinh dưỡng mới.</p>
-            </div>
-
-            <form method="POST" action="{{ url_for('dietitians.store') }}" class="px-4 py-5 sm:p-6">
-                <div class="grid grid-cols-6 gap-6">
-                    <div class="col-span-6 sm:col-span-3">
-                        <label for="firstName" class="block text-sm font-medium text-gray-700">Tên</label>
-                        <input type="text" name="firstName" id="firstName" class="mt-1 focus:ring-primary-500 focus:border-primary-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" required>
-                    </div>
-
-                    <div class="col-span-6 sm:col-span-3">
-                        <label for="lastName" class="block text-sm font-medium text-gray-700">Họ</label>
-                        <input type="text" name="lastName" id="lastName" class="mt-1 focus:ring-primary-500 focus:border-primary-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" required>
-                    </div>
-
-                    <div class="col-span-6 sm:col-span-3">
-                        <label for="email" class="block text-sm font-medium text-gray-700">Email</label>
-                        <input type="email" name="email" id="email" class="mt-1 focus:ring-primary-500 focus:border-primary-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" required>
-                    </div>
-
-                    <div class="col-span-6 sm:col-span-3">
-                        <label for="phone" class="block text-sm font-medium text-gray-700">Số điện thoại</label>
-                        <input type="text" name="phone" id="phone" class="mt-1 focus:ring-primary-500 focus:border-primary-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
-                    </div>
-
-                    <div class="col-span-6">
-                        <label for="specialization" class="block text-sm font-medium text-gray-700">Chuyên môn</label>
-                        <input type="text" name="specialization" id="specialization" class="mt-1 focus:ring-primary-500 focus:border-primary-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
-                    </div>
-
-                    <div class="col-span-6">
-                        <label for="notes" class="block text-sm font-medium text-gray-700">Ghi chú</label>
-                        <textarea name="notes" id="notes" rows="3" class="mt-1 focus:ring-primary-500 focus:border-primary-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md"></textarea>
-                    </div>
-
-                    <div class="col-span-6">
-                        <label for="status" class="block text-sm font-medium text-gray-700">Trạng thái</label>
-                        <select id="status" name="status" class="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm">
-                            <option value="available" selected>Khả dụng</option>
-                            <option value="unavailable">Không khả dụng</option>
-                        </select>
-                    </div>
-                </div>
-
-                <div class="pt-5 mt-4 border-t border-gray-200">
-                    <div class="flex justify-end">
-                        <a href="{{ url_for('dietitians.index') }}" class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 transition duration-200">
-                            Hủy
-                        </a>
-                        <button type="submit" class="ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 transition duration-200">
-                            Thêm mới
-                        </button>
-                    </div>
-                </div>
-            </form>
-        </div>
-    </div>
-</div>
-{% endblock %}
\ No newline at end of file
diff --git a/app/templates/dietitians/edit_admin.html b/app/templates/dietitians/edit_admin.html
index c57cd1a9b607040d0845b58c6862c35e59cefaa1..450e4d824dab51eab9667a0071e7f63e437b18f7 100644
--- a/app/templates/dietitians/edit_admin.html
+++ b/app/templates/dietitians/edit_admin.html
@@ -1,6 +1,8 @@
 {% extends "base.html" %}
+{% from "_macros.html" import render_form_field, status_badge %}
 
-{% block title %}Chỉnh sửa chuyên gia dinh dưỡng - Admin{% endblock %}
+{% block title %}Edit Dietitian - Admin{% endblock %}
+{% block header %}Edit Dietitian Profile{% endblock %} 
 
 {% block content %}
 <div class="container mx-auto px-4 py-8 animate-fade-in">
@@ -16,84 +18,62 @@
                 <li>
                     <div class="flex items-center">
                         <i class="fas fa-chevron-right text-gray-400 mx-2"></i>
-                        <a href="{{ url_for('dietitians.index') }}" class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 transition duration-200">Chuyên gia dinh dưỡng</a>
+                        <a href="{{ url_for('dietitians.index') }}" class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 transition duration-200">Dietitians</a>
                     </div>
                 </li>
                 <li aria-current="page">
                     <div class="flex items-center">
                         <i class="fas fa-chevron-right text-gray-400 mx-2"></i>
-                        <span class="ml-1 text-sm font-medium text-gray-500 md:ml-2">Chỉnh sửa: {{ dietitian.full_name }}</span>
+                        <span class="ml-1 text-sm font-medium text-gray-500 md:ml-2">Editing: {{ dietitian.firstName }} {{ dietitian.lastName }}</span>
                     </div>
                 </li>
             </ol>
         </nav>
     </div>
 
-    <h1 class="text-2xl font-semibold text-gray-800 mb-6">Chỉnh sửa thông tin: {{ dietitian.full_name }} ({{ dietitian.formattedID }})</h1>
+    <h1 class="text-2xl font-bold leading-7 text-gray-900 sm:text-2xl sm:truncate">Editing {{ dietitian.firstName }} {{ dietitian.lastName }} ({{ dietitian.formattedID }})'s Information</h1>
 
     <form method="POST" action="{{ url_for('dietitians.edit', id=dietitian.dietitianID) }}" class="bg-white shadow-md rounded-lg px-8 pt-6 pb-8 mb-4">
-        {# Assume CSRF token is handled by Flask-WTF or you add it manually #}
-        {# <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> #}
+        {{ form.csrf_token }}
         
         <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
             <!-- First Name -->
             <div>
-                <label for="firstName" class="block text-sm font-medium text-gray-700 mb-1">Họ <span class="text-red-500">*</span></label>
-                <input type="text" id="firstName" name="firstName" value="{{ dietitian.firstName or '' }}" required 
-                       class="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md">
+                {{ render_form_field(form.firstName) }}
             </div>
 
             <!-- Last Name -->
             <div>
-                <label for="lastName" class="block text-sm font-medium text-gray-700 mb-1">Tên <span class="text-red-500">*</span></label>
-                <input type="text" id="lastName" name="lastName" value="{{ dietitian.lastName or '' }}" required 
-                       class="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md">
+                {{ render_form_field(form.lastName) }}
             </div>
 
             <!-- Email -->
             <div>
-                <label for="email" class="block text-sm font-medium text-gray-700 mb-1">Email <span class="text-red-500">*</span></label>
-                <input type="email" id="email" name="email" value="{{ dietitian.email or '' }}" required 
-                       class="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md">
+                {{ render_form_field(form.email) }}
             </div>
 
             <!-- Phone -->
             <div>
-                <label for="phone" class="block text-sm font-medium text-gray-700 mb-1">Số điện thoại</label>
-                <input type="tel" id="phone" name="phone" value="{{ dietitian.phone or '' }}" 
-                       class="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md">
+                {{ render_form_field(form.phone) }}
             </div>
 
             <!-- Specialization -->
             <div class="md:col-span-2">
-                <label for="specialization" class="block text-sm font-medium text-gray-700 mb-1">Chuyên môn</label>
-                <input type="text" id="specialization" name="specialization" value="{{ dietitian.specialization or '' }}" 
-                       class="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md">
-            </div>
-            
-             <!-- Status (Read-only for Admin in this form - maybe changed via separate action) -->
-            <div>
-                <label class="block text-sm font-medium text-gray-700 mb-1">Trạng thái</label>
-                <span class="inline-flex items-center px-3 py-1.5 rounded-full text-sm font-medium bg-{{ dietitian.get_status_badge_class() }}-100 text-{{ dietitian.get_status_badge_class() }}-800">
-                    {{ dietitian.status.value if dietitian.status else 'Không xác định' }}
-                </span>
-                <p class="text-xs text-gray-500 mt-1">Trạng thái hiện không thể thay đổi trực tiếp tại đây.</p>
+                {{ render_form_field(form.specialization) }}
             </div>
 
             <!-- Notes -->
             <div class="md:col-span-2">
-                <label for="notes" class="block text-sm font-medium text-gray-700 mb-1">Ghi chú</label>
-                <textarea id="notes" name="notes" rows="4" 
-                          class="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border border-gray-300 rounded-md">{{ dietitian.notes or '' }}</textarea>
+                {{ render_form_field(form.notes) }}
             </div>
         </div>
 
         <div class="flex items-center justify-end space-x-4">
             <a href="{{ url_for('dietitians.index') }}" class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded-md transition duration-300">
-                Hủy bỏ
+                Cancel
             </a>
             <button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md transition duration-300">
-                <i class="fas fa-save mr-2"></i> Lưu thay đổi
+                <i class="fas fa-save mr-2"></i> Save Changes
             </button>
         </div>
     </form>
diff --git a/app/templates/dietitians/index.html b/app/templates/dietitians/index.html
index ecb4fbf208d223deb9f2d3cbfd6e39bdfd5c6ab4..829a57734498018391cc3e8dc26f9a6f7c6db148 100644
--- a/app/templates/dietitians/index.html
+++ b/app/templates/dietitians/index.html
@@ -111,7 +111,8 @@
                                 <a href="{{ url_for('dietitians.show', id=current_dietitian.dietitianID) }}" class="text-blue-600 hover:text-blue-800 mr-3 transition duration-200">Detail</a>
                                 <a href="{{ url_for('auth.edit_profile') }}" class="text-indigo-600 hover:text-indigo-900 mr-3 transition duration-200">Edit</a>
                                 {% if current_user.is_admin %}
-                                <form action="{{ url_for('dietitians.delete', id=current_dietitian.dietitianID) }}" method="POST" class="inline-block" onsubmit="return confirm('Bạn có chắc chắn muốn xóa chuyên gia dinh dưỡng này?');">
+                                <form action="{{ url_for('dietitians.delete', id=current_dietitian.dietitianID) }}" method="POST" class="inline-block" onsubmit="return confirm('Are you sure that you want to delete this Dietitian account?');">
+                                    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
                                     <button type="submit" class="text-red-600 hover:text-red-900 transition duration-200">Xóa</button>
                                 </form>
                                 {% endif %}
@@ -170,7 +171,8 @@
                                     <a href="{{ url_for('dietitians.show', id=dietitian.dietitianID) }}" class="text-primary-600 hover:text-primary-900 mr-3 transition duration-200">Detail</a>
                                     {% if current_user.is_admin %}
                                     <a href="{{ url_for('dietitians.edit', id=dietitian.dietitianID) }}" class="text-indigo-600 hover:text-indigo-900 mr-3 transition duration-200">Edit</a>
-                                    <form action="{{ url_for('dietitians.delete', id=dietitian.dietitianID) }}" method="POST" class="inline-block" onsubmit="return confirm('Bạn có chắc chắn muốn xóa chuyên gia dinh dưỡng này?');">
+                                    <form action="{{ url_for('dietitians.delete', id=dietitian.dietitianID) }}" method="POST" class="inline-block" onsubmit="return confirm('Are you sure that you want to delete this Dietitian account?');">
+                                        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
                                         <button type="submit" class="text-red-600 hover:text-red-900 transition duration-200">Delete</button>
                                     </form>
                                     {% endif %}
diff --git a/app/templates/dietitians/new.html b/app/templates/dietitians/new.html
index 9613147ad0983349d59383d4cb779ed39d81596d..7bf31ffbb761cce18c1bdb5cbf97c76e0f6b2f75 100644
--- a/app/templates/dietitians/new.html
+++ b/app/templates/dietitians/new.html
@@ -1,7 +1,7 @@
 {% extends "base.html" %}
 {% from "_formhelpers.html" import render_field %}
 
-{% block title %}Thêm chuyên gia dinh dưỡng mới - Admin{% endblock %}
+{% block title %}Add New Dietitian - Admin{% endblock %}
 
 {% block content %}
 <div class="container mx-auto px-4 py-8 animate-fade-in">
@@ -17,56 +17,56 @@
                 <li>
                     <div class="flex items-center">
                         <i class="fas fa-chevron-right text-gray-400 mx-2"></i>
-                        <a href="{{ url_for('dietitians.index') }}" class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 transition duration-200">Chuyên gia dinh dưỡng</a>
+                        <a href="{{ url_for('dietitians.index') }}" class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 transition duration-200">Dietitians</a>
                     </div>
                 </li>
                 <li aria-current="page">
                     <div class="flex items-center">
                         <i class="fas fa-chevron-right text-gray-400 mx-2"></i>
-                        <span class="ml-1 text-sm font-medium text-gray-500 md:ml-2">Thêm mới</span>
+                        <span class="ml-1 text-sm font-medium text-gray-500 md:ml-2">Add New</span>
                     </div>
                 </li>
             </ol>
         </nav>
     </div>
 
-    <h1 class="text-2xl font-semibold text-gray-800 mb-6">Tạo tài khoản chuyên gia dinh dưỡng mới</h1>
+    <h1 class="text-2xl font-semibold text-gray-800 mb-6">Create New Dietitian Account</h1>
 
     <form method="POST" action="{{ url_for('dietitians.new') }}" class="bg-white shadow-md rounded-lg px-8 pt-6 pb-8 mb-4">
         {{ form.csrf_token }}
 
-        <h3 class="text-lg font-medium text-gray-900 mb-4 border-b pb-2">Thông tin tài khoản (User)</h3>
+        <h3 class="text-lg font-medium text-gray-900 mb-4 border-b pb-2">Account Information (User)</h3>
         <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
             <!-- First Name -->
-            {{ render_field(form.firstName, label_text="Họ") }}
+            {{ render_field(form.firstName) }}
             <!-- Last Name -->
-            {{ render_field(form.lastName, label_text="Tên") }}
+            {{ render_field(form.lastName) }}
             <!-- Email -->
-            {{ render_field(form.email, label_text="Email") }}
+            {{ render_field(form.email) }}
             <!-- Password -->
-            {{ render_field(form.password, label_text="Mật khẩu") }}
-            <div class="md:col-span-2"><p class="text-xs text-gray-500 -mt-4">Mật khẩu tạm thời cho người dùng mới.</p></div>
+            {{ render_field(form.password) }}
+            <div class="md:col-span-2"><p class="text-xs text-gray-500 -mt-4">Temporary password for the new user.</p></div>
         </div>
 
-        <h3 class="text-lg font-medium text-gray-900 mb-4 border-b pb-2">Thông tin hồ sơ (Dietitian Profile)</h3>
+        <h3 class="text-lg font-medium text-gray-900 mb-4 border-b pb-2">Profile Information (Dietitian Profile)</h3>
         <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
              <!-- Phone -->
-            {{ render_field(form.phone, label_text="Số điện thoại") }}
+            {{ render_field(form.phone) }}
             <!-- Specialization -->
-            {{ render_field(form.specialization, label_text="Chuyên môn") }}
+            {{ render_field(form.specialization) }}
              <!-- Notes -->
             <div class="md:col-span-2">
-                 <label for="notes" class="block text-sm font-medium text-gray-700 mb-1">Ghi chú</label>
+                 <label for="notes" class="block text-sm font-medium text-gray-700 mb-1">Notes</label>
                  {{ form.notes(rows="3", class="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border border-gray-300 rounded-md") }}
             </div>
         </div>
 
         <div class="flex items-center justify-end space-x-4">
             <a href="{{ url_for('dietitians.index') }}" class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded-md transition duration-300">
-                Hủy bỏ
+                Cancel
             </a>
             <button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md transition duration-300">
-                <i class="fas fa-user-plus mr-2"></i> Tạo tài khoản
+                <i class="fas fa-user-plus mr-2"></i> Create Account
             </button>
         </div>
     </form>
diff --git a/app/templates/dietitians/show.html b/app/templates/dietitians/show.html
index 01cf33bb65c3d233db70409c1dcb7e9dcf6c3cbf..1b22033c30026415a4bed438cdd9746ff2210c6e 100644
--- a/app/templates/dietitians/show.html
+++ b/app/templates/dietitians/show.html
@@ -51,6 +51,7 @@
                     {% endif %}
                     {% if current_user.is_admin %}
                     <form action="{{ url_for('dietitians.delete', id=dietitian.dietitianID) }}" method="POST" onsubmit="return confirm('Are you sure you want to delete this dietitian?');" class="inline-block">
+                        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
                         <button type="submit" class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition duration-200">
                             <svg class="mr-2 -ml-1 h-4 w-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
diff --git a/ccu_htm_db_schema.png b/ccu_htm_db_schema.png
new file mode 100644
index 0000000000000000000000000000000000000000..81067858690cbc90f6a1bab913aa0545cd050e3c
Binary files /dev/null and b/ccu_htm_db_schema.png differ
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..359ebb09785cac28c3d346e726763da48dec324c
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,80 @@
+version: '3.8'
+
+services:
+  app:
+    build: .
+    container_name: ccu_htm_app
+    restart: always
+    depends_on:
+      db:
+        condition: service_healthy # Wait for DB healthcheck
+    ports:
+      - "${PORT:-5000}:5000" # Use PORT from .env or default to 5000
+    volumes:
+      - ./uploads:/app/uploads # Mount uploads folder
+      - ./instance:/app/instance # Mount instance folder (if needed for config/db)
+      # Migrations folder is part of the image, not usually mounted
+    env_file:
+      - .env
+    environment:
+      # Override DATABASE_URL to use the service name 'db' and correct driver
+      - DATABASE_URL=mysql+mysqlconnector://${MYSQL_USER}:${MYSQL_PASSWORD}@db:3306/${MYSQL_DATABASE}
+      - FLASK_APP=${FLASK_APP}
+      - FLASK_ENV=${FLASK_ENV}
+      - SECRET_KEY=${SECRET_KEY}
+      - PORT=5000 # Internal port Gunicorn listens on
+    networks:
+      - app-network
+    # Removed healthcheck for app as it might depend on readiness
+
+  db:
+    image: mysql:8.0
+    container_name: ccu_htm_db
+    restart: always
+    # Removed port mapping for DB - not needed if only app connects
+    volumes:
+      - mysql_data:/var/lib/mysql
+      # Uncomment if you have init scripts
+      # - ./sql:/docker-entrypoint-initdb.d
+    env_file:
+      - .env
+    environment:
+      # Pass variables directly from .env
+      - MYSQL_DATABASE=${MYSQL_DATABASE}
+      - MYSQL_USER=${MYSQL_USER}
+      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
+      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
+    networks:
+      - app-network
+    command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
+    healthcheck:
+      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-u$${MYSQL_USER}", "-p$${MYSQL_PASSWORD}"] # Use user/pass for ping
+      interval: 10s
+      timeout: 5s
+      retries: 10 # Increased retries
+      start_period: 30s
+
+  nginx:
+    image: nginx:alpine # Use alpine for smaller size
+    container_name: ccu_htm_nginx
+    restart: always
+    ports:
+      - "80:80"
+      - "443:443"
+    volumes:
+      - ./nginx/conf.d:/etc/nginx/conf.d:ro # Mount config read-only
+      - ./nginx/ssl:/etc/nginx/ssl:ro # Mount ssl certs read-only
+      # Static files should ideally be served by Nginx if collected
+      # - ./staticfiles:/app/static # Example if static files are collected here
+    depends_on:
+      - app
+    networks:
+      - app-network
+
+networks:
+  app-network:
+    driver: bridge
+
+volumes:
+  mysql_data:
+    # driver: local # Default is local 
\ No newline at end of file
diff --git a/generate_architecture_diagram.py b/generate_architecture_diagram.py
new file mode 100644
index 0000000000000000000000000000000000000000..4380a643a00e70464ecfc7552cf9aada5d0a1efc
--- /dev/null
+++ b/generate_architecture_diagram.py
@@ -0,0 +1,78 @@
+from diagrams import Diagram, Cluster, Edge
+from diagrams.programming.framework import Flask
+from diagrams.programming.language import Python
+from diagrams.onprem.database import MySQL  # Sử dụng MySQL vì cấu hình của bạn là MySQL
+from diagrams.onprem.network import Nginx # Hoặc một web server khác nếu bạn dùng
+from diagrams.onprem.client import User, Client # User và Browser
+from diagrams.onprem.compute import Server # Server tổng quát
+from diagrams.generic.storage import Storage # Cho static/templates
+from diagrams.generic.device import Mobile # Ví dụ client khác
+
+# Đặt tên file output không có phần mở rộng
+diagram_filename = "ccu_htm_architecture"
+
+# Hướng của biểu đồ: TB (Top to Bottom), LR (Left to Right)
+diagram_direction = "TB"
+
+with Diagram(f"{diagram_filename}", show=False, direction=diagram_direction, filename=diagram_filename) as diag:
+    # --- Clients --- 
+    user = User("End User")
+    browser = Client("Web Browser")
+    # mobile_app = Mobile("Mobile App (Future?)") # Ví dụ nếu có app di động
+
+    # --- Infrastructure / Deployment --- 
+    # Giả sử dùng Nginx làm reverse proxy và Gunicorn làm WSGI server
+    # Nếu chỉ chạy Flask dev server, bạn có thể bỏ qua Nginx/Gunicorn
+    # nginx = Nginx("Nginx\n(Reverse Proxy)") 
+    # gunicorn = Server("Gunicorn\n(WSGI Server)") 
+    
+    # --- Backend Application --- 
+    with Cluster("Flask Application (Python Backend)"):
+        flask_app = Flask("Flask App Core")
+        # Các thành phần chính trong app/
+        with Cluster("Application Logic"):
+            routes = Python("Routes\n(Blueprints)")
+            forms = Python("Forms\n(Flask-WTF)")
+            models = Python("Models\n(SQLAlchemy)")
+            utils = Python("Utilities / Decorators")
+        
+        # Template và Static files
+        with Cluster("Presentation"):
+            templates = Storage("Jinja2 Templates")
+            static_files = Storage("Static Files\n(CSS, JS, Images)")
+            macros = Storage("Macros")
+
+        # Liên kết nội bộ trong Flask App
+        flask_app >> routes
+        routes >> models
+        routes >> forms
+        routes >> templates 
+        routes >> utils
+        templates >> macros # Templates import macros
+        templates >> static_files # Templates link tới static
+
+    # --- Database --- 
+    database = MySQL("MySQL Database\n(ccu)")
+    
+    # --- Configuration --- 
+    config = Storage("Configuration\n(instance/config.py, .env)")
+
+    # --- Connections --- 
+    user >> browser
+    
+    # Nếu dùng Nginx/Gunicorn:
+    # browser >> nginx >> gunicorn >> flask_app
+    
+    # Nếu chỉ dùng Flask dev server:
+    browser >> Edge(label="HTTP Requests") >> flask_app
+    
+    # Backend connections
+    flask_app >> Edge(label="Reads config") >> config
+    models >> Edge(label="CRUD Operations") >> database
+    
+    # Frontend response
+    flask_app >> Edge(label="HTML Response") >> browser
+
+diag # Hiển thị biểu đồ (nếu show=True) hoặc chỉ tạo file
+
+print(f"Diagram generated: {diagram_filename}.png")
diff --git a/generate_db_schema_diagram.py b/generate_db_schema_diagram.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d5dcc023c29697fb4d940712e080d4f76c8e410
--- /dev/null
+++ b/generate_db_schema_diagram.py
@@ -0,0 +1,86 @@
+from diagrams import Diagram, Cluster, Edge, Node
+from diagrams.onprem.database import MySQL # Chỉ cần MySQL icon
+
+# Đặt tên file output không có phần mở rộng
+diagram_filename = "ccu_htm_db_schema"
+
+# Hướng của biểu đồ: TB (Top to Bottom), LR (Left to Right)
+diagram_direction = "LR" 
+
+with Diagram(f"{diagram_filename}", show=False, direction=diagram_direction, filename=diagram_filename) as diag:
+    # Định nghĩa database cluster
+    with Cluster("CCU HTM Database Schema (MySQL: ccu)") as db_cluster:
+        # Định nghĩa các bảng chính
+        user_table = Node("User\n(users)\nPK: userID")
+        dietitian_table = Node("Dietitian\n(dietitians)\nPK: dietitianID")
+        patient_table = Node("Patient\n(patients)\nPK: patientID")
+        encounter_table = Node("Encounter\n(encounters)\nPK: encounterID")
+        measurement_table = Node("PhysiologicalMeasurement\n(physiologicalmeasurements)\nPK: measurementID")
+        procedure_table = Node("Procedure\n(procedures)\nPK: procedureID")
+        referral_table = Node("Referral\n(referrals)\nPK: referralID")
+        report_table = Node("Report\n(reports)\nPK: reportID")
+        support_msg_table = Node("SupportMessage\n(support_messages)\nPK: messageID")
+        activity_log_table = Node("ActivityLog\n(activity_logs)\nPK: logID")
+
+        # Định nghĩa các mối quan hệ từ models
+        
+        # 1. User <-> Dietitian (One-to-One)
+        user_table << Edge(label="1..1 (user_id)") >> dietitian_table
+        
+        # 2. User (Dietitian) <-> Patient (One-to-Many)
+        user_table << Edge(label="1..N (assigned_dietitian_user_id)") << patient_table
+        
+        # 3. Patient <-> Encounter (One-to-Many)
+        patient_table >> Edge(label="1..N (patient_id)") >> encounter_table
+
+        # 4. Patient <-> PhysiologicalMeasurement (One-to-Many)
+        patient_table >> Edge(label="1..N (patient_id)") >> measurement_table
+        
+        # 5. Patient <-> Procedure (One-to-Many)
+        patient_table >> Edge(label="1..N (patient_id)") >> procedure_table
+        
+        # 6. Patient <-> Referral (One-to-Many)
+        patient_table >> Edge(label="1..N (patient_id)") >> referral_table
+        
+        # 7. Patient <-> Report (One-to-Many)
+        patient_table >> Edge(label="1..N (patient_id)") >> report_table
+        
+        # 8. Encounter <-> PhysiologicalMeasurement (One-to-Many)
+        encounter_table >> Edge(label="1..N (encounter_id)") >> measurement_table
+        
+        # 9. Encounter <-> Procedure (One-to-Many)
+        encounter_table >> Edge(label="1..N (encounter_id)") >> procedure_table
+        
+        # 10. Encounter <-> Referral (One-to-Many)
+        encounter_table >> Edge(label="1..N (encounter_id)") >> referral_table
+        
+        # 11. Encounter <-> Report (One-to-Many)
+        encounter_table >> Edge(label="1..N (encounter_id)") >> report_table
+        
+        # 12. User <-> Report (One-to-Many) - author relationship
+        user_table >> Edge(label="1..N (author_id)") >> report_table
+        
+        # 13. User <-> Report (One-to-Many) - dietitian assignment
+        user_table >> Edge(label="1..N (dietitian_id)", style="dashed") >> report_table
+        
+        # 14. User <-> Referral (One-to-Many) - dietitian assignment
+        user_table >> Edge(label="1..N (assigned_dietitian_user_id)", style="dashed") >> referral_table
+        
+        # 15. User <-> Encounter (One-to-Many) - dietitian assignment
+        user_table >> Edge(label="1..N (dietitian_id)", style="dashed") >> encounter_table
+        
+        # 16. User <-> SupportMessage (One-to-Many)
+        user_table >> Edge(label="1..N (sender)") >> support_msg_table
+        
+        # 17. User <-> ActivityLog (One-to-Many)
+        user_table >> Edge(label="1..N (user_id)") >> activity_log_table
+        
+        # 18. Procedure <-> Report (One-to-Many)
+        procedure_table >> Edge(label="1..N (related_procedure_id)") >> report_table
+        
+        # 19. Referral <-> Report (One-to-One)
+        referral_table >> Edge(label="1..1 (referral_id)") >> report_table
+
+diag
+
+print(f"Comprehensive database schema diagram generated: {diagram_filename}.png") 
\ No newline at end of file
diff --git a/nginx/conf.d/default.conf b/nginx/conf.d/default.conf
new file mode 100644
index 0000000000000000000000000000000000000000..090adba5e786b9edd706bccbd4e8ae432ed8ca0f
--- /dev/null
+++ b/nginx/conf.d/default.conf
@@ -0,0 +1,46 @@
+server {
+    listen 80;
+    # Replace with your actual domain name
+    server_name demoblog.ccuhuantrungminh.site www.demoblog.ccuhuantrungminh.site; 
+
+    # Optional: Redirect www to non-www (or vice-versa)
+    # if ($host = www.demoblog.ccuhuantrungminh.site) {
+    #     return 301 https://demoblog.ccuhuantrungminh.site$request_uri;
+    # }
+
+    # Serve static files directly if they exist (adjust path if needed)
+    # location /static/ {
+    #     alias /app/static/;
+    #     expires 1d; # Add caching headers for static files
+    # }
+
+    # Pass all other requests to the Flask/Gunicorn app service
+    location / {
+        proxy_pass http://app:5000; # Match the internal port Gunicorn listens on
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        
+        # Optional: Increase timeouts for long-running requests
+        # proxy_connect_timeout 600;
+        # proxy_send_timeout 600;
+        # proxy_read_timeout 600;
+        # send_timeout 600;
+    }
+
+    # Optional: Add location block for handling uploads if needed directly via Nginx
+    # location /uploads/ {
+    #     alias /app/uploads/;
+    # }
+
+    # Add HTTPS configuration later using certbot/Let's Encrypt
+    # For now, only HTTP is configured
+}
+
+# Optional: Add another server block for www redirection if not handled above
+# server {
+#    listen 80;
+#    server_name www.demoblog.ccuhuantrungminh.site;
+#    return 301 https://demoblog.ccuhuantrungminh.site$request_uri;
+# } 
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 43852f9a197652224e64a4d6b7d93be7d0f44d64..33bd4990110db41df8e3738b6219b14e0dafc7f3 100644
Binary files a/requirements.txt and b/requirements.txt differ
diff --git a/run.py b/run.py
index 4d4dcaaf801b07d855119bc4c342916e5b85bc45..947c5f4d713198f6cda4a0fb05474bf47290d3a9 100644
--- a/run.py
+++ b/run.py
@@ -11,6 +11,7 @@ from flask import Flask
 from datetime import datetime
 from flask_migrate import Migrate, init, migrate, upgrade, stamp
 import json # Import json
+from urllib.parse import urlparse # Import urlparse
 
 # Import models and status needed for reset
 from app.models.user import User
@@ -34,27 +35,50 @@ def clear_cache():
 def create_mysql_database(app):
     """Create MySQL database if it doesn't exist"""
     try:
-        uri = app.config['SQLALCHEMY_DATABASE_URI']
-        if not uri.startswith('mysql'):
+        uri_str = app.config['SQLALCHEMY_DATABASE_URI']
+        
+        # Parse the URI using urllib.parse
+        parsed_uri = urlparse(uri_str)
+        
+        # Ensure it's a MySQL URI (can handle mysql+mysqlconnector, etc.)
+        if not parsed_uri.scheme.startswith('mysql'):
             print("[Skip] Not a MySQL URI.")
             return True
 
-        creds, path = uri.replace('mysql://', '').split('@')
-        user, pwd = creds.split(':')
-        host, db = path.split('/')
+        # Extract connection details safely
+        db_user = parsed_uri.username
+        db_password = parsed_uri.password
+        db_host = parsed_uri.hostname
+        db_port = parsed_uri.port or 3306 # Default MySQL port if not specified
+        db_name = parsed_uri.path.lstrip('/') # Remove leading slash from path
 
-        connection = mysql.connector.connect(host=host, user=user, password=pwd)
+        if not all([db_user, db_password, db_host, db_name]):
+             print("[DB Error] Could not parse all required components from the URI.")
+             print(f"  User: {db_user}, Pass: {'******' if db_password else None}, Host: {db_host}, DB: {db_name}")
+             return False
+
+        print(f"[DB] Attempting to connect to host: {db_host}:{db_port} as user: {db_user}")
+        connection = mysql.connector.connect(
+            host=db_host,
+            port=db_port,
+            user=db_user,
+            password=db_password
+        )
         cursor = connection.cursor()
         
         # Create database with UTF-8 support
-        cursor.execute(f"CREATE DATABASE IF NOT EXISTS {db} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci")
+        print(f"[DB] Creating/verifying database '{db_name}'...")
+        cursor.execute(f"CREATE DATABASE IF NOT EXISTS `{db_name}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci")
         cursor.close()
         connection.close()
         
-        print(f"[DB] Database '{db}' created/verified.")
+        print(f"[DB] Database '{db_name}' created/verified.")
         return True
+    except mysql.connector.Error as err:
+        print(f"[DB Error] MySQL connection/creation error: {err}")
+        return False
     except Exception as e:
-        print(f"[DB Error] {e}")
+        print(f"[DB Error] Unexpected error during DB creation: {e}")
         return False
 
 def init_tables_and_admin(app, db):
@@ -103,20 +127,29 @@ def perform_database_reset(app, db, bcrypt):
             return False
 
         # Get database connection information
-        uri = app.config['SQLALCHEMY_DATABASE_URI']
-        if not uri.startswith('mysql'):
+        uri_str = app.config['SQLALCHEMY_DATABASE_URI']
+        parsed_uri = urlparse(uri_str)
+
+        if not parsed_uri.scheme.startswith('mysql'):
             print("[Error] Only MySQL databases are supported for reset.")
             return False
             
-        # Parse connection string
-        creds, path = uri.replace('mysql://', '').split('@')
-        user_db, pwd = creds.split(':') # Renamed user to user_db to avoid conflict
-        host, database = path.split('/')
+        # Extract connection details safely
+        user_db = parsed_uri.username
+        pwd = parsed_uri.password
+        host = parsed_uri.hostname
+        port = parsed_uri.port or 3306
+        database = parsed_uri.path.lstrip('/')
+
+        if not all([user_db, pwd, host, database]):
+             print("[DB Error] Could not parse all required components from the URI for reset.")
+             return False
         
         # Connect directly to database
-        print(f"[DB] Connecting to MySQL database '{database}'...")
+        print(f"[DB] Connecting to MySQL database '{database}' on {host}:{port} for reset...")
         connection = mysql.connector.connect(
             host=host,
+            port=port,
             user=user_db, # Use renamed variable
             password=pwd,
             database=database
diff --git a/wsgi.py b/wsgi.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0cc3777ea261492aee49e5223edf6b539bed659
--- /dev/null
+++ b/wsgi.py
@@ -0,0 +1,19 @@
+# wsgi.py
+import os
+from dotenv import load_dotenv
+
+# Load environment variables from .env file if it exists
+# This is useful for local development but might not be needed in production
+# if environment variables are set directly.
+dotenv_path = os.path.join(os.path.dirname(__file__), '.env')
+if os.path.exists(dotenv_path):
+    load_dotenv(dotenv_path)
+
+from app import create_app
+
+# Create the Flask app instance
+# The create_app function should handle reading configuration 
+# (e.g., from environment variables)
+app = create_app()
+
+# Gunicorn (or other WSGI servers) will look for this 'app' variable 
\ No newline at end of file