Spaces:
Sleeping
Sleeping
| """ | |
| Profile management routes. | |
| Feature: 012-profile-contact-ui | |
| User Story 1: Profile Management | |
| """ | |
| import logging | |
| from flask import Blueprint, render_template, request, redirect, url_for, flash, session, jsonify | |
| from ..services.backend_client import backend_client, BackendAPIError | |
| from ..services.storage_service import ( | |
| get_user_profile, | |
| create_or_update_user, | |
| ) | |
| logger = logging.getLogger(__name__) | |
| bp = Blueprint("profile", __name__, url_prefix="/profile") | |
| def view_profile(): | |
| """Display user profile with facts.""" | |
| # Check authentication | |
| if "user_id" not in session: | |
| flash("Please log in to view your profile.", "warning") | |
| return redirect(url_for("auth.login")) | |
| user_id = session["user_id"] | |
| try: | |
| # Get user profile from SQLite | |
| user_profile = get_user_profile(user_id) | |
| if not user_profile: | |
| flash("Profile not found. Please log in again.", "error") | |
| return redirect(url_for("auth.logout")) | |
| # Get profile facts from backend (mode="memorize") | |
| facts = backend_client.get_messages(user_profile.session_id, user_id, mode="memorize") | |
| return render_template( | |
| "profile/view.html", | |
| user_profile=user_profile, | |
| facts=facts, | |
| ) | |
| except BackendAPIError as e: | |
| flash(f"Error loading profile: {str(e)}", "error") | |
| return render_template("profile/view.html", user_profile=None, facts=[]) | |
| def add_fact(): | |
| """Add a new fact to user profile.""" | |
| # Check authentication | |
| if "user_id" not in session: | |
| return {"error": "Unauthorized"}, 401 | |
| user_id = session["user_id"] | |
| fact_content = request.form.get("content", "").strip() | |
| # Validate input | |
| if not fact_content: | |
| flash("Fact content cannot be empty.", "error") | |
| return redirect(url_for("profile.view_profile")) | |
| if len(fact_content) > 500: | |
| flash("Fact content exceeds 500 characters.", "error") | |
| return redirect(url_for("profile.view_profile")) | |
| try: | |
| # Get user profile | |
| user_profile = get_user_profile(user_id) | |
| if not user_profile: | |
| flash("Profile not found.", "error") | |
| return redirect(url_for("auth.logout")) | |
| # Send fact to backend with proper attribution (Feature: 001-refine-memory-producer-logic) | |
| # Profile facts: producer=user_id, produced_for="prepmate" | |
| logger.info( | |
| f"Saving profile fact: user_id={user_id}, producer={user_id}, " | |
| f"produced_for=prepmate, content_length={len(fact_content)}" | |
| ) | |
| backend_client.send_message( | |
| session_id=user_profile.session_id, | |
| content=fact_content, | |
| user_id=user_id, | |
| mode="memorize", | |
| producer=user_id, # User is the producer | |
| produced_for="prepmate", # Produced for the prepmate system | |
| ) | |
| # Fetch updated facts to ensure immediate visibility (T010) | |
| facts = backend_client.get_messages(user_profile.session_id, user_id, mode="memorize") | |
| logger.info(f"Profile fact saved successfully for user {user_id}") | |
| # Feature: 012-realtime-message-display - Return JSON for AJAX requests | |
| if request.headers.get('X-Requested-With') == 'XMLHttpRequest': | |
| # Find the newly added fact (last fact in the list) | |
| new_fact = facts[-1] if facts else None | |
| return jsonify({ | |
| 'success': True, | |
| 'message': { | |
| 'id': new_fact.message_id if new_fact else None, | |
| 'content': fact_content, | |
| 'role': 'user', | |
| 'type': 'fact', | |
| 'created_at': new_fact.created_at if new_fact else None | |
| } | |
| }) | |
| # Re-render with updated facts instead of redirect | |
| return render_template( | |
| "profile/view.html", | |
| user_profile=user_profile, | |
| facts=facts, | |
| ) | |
| except BackendAPIError as e: | |
| flash(f"Error adding fact: {str(e)}", "error") | |
| # Preserve input on error by passing it to template | |
| user_profile = get_user_profile(user_id) | |
| facts = backend_client.get_messages(user_profile.session_id, user_id, mode="memorize") if user_profile else [] | |
| return render_template( | |
| "profile/view.html", | |
| user_profile=user_profile, | |
| facts=facts, | |
| preserved_content=fact_content, | |
| ) | |
| def delete_fact(message_id: str): | |
| """Delete a fact from user profile.""" | |
| # Check authentication | |
| if "user_id" not in session: | |
| return {"error": "Unauthorized"}, 401 | |
| # Note: Backend API does not support message deletion yet | |
| # This is a placeholder for future implementation | |
| flash("Fact deletion not yet implemented.", "warning") | |
| return redirect(url_for("profile.view_profile")) | |