#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ FLASK WEB APPLICATION - INDEX-SISTEM-JOCURI Author: Claude AI Assistant Date: 2025-09-09 Purpose: Web interface for searching educational activities Features: - Search interface matching interfata-web.jpg mockup exactly - 9 filter dropdowns as specified in PRD - Full-text search functionality - Results display in table format - Links to source files - Activity sheet generation PRD Requirements: - RF6: Layout identical to mockup - RF7: Search box for free text search - RF8: 9 dropdown filters - RF9: Apply and Reset buttons - RF10: Results table display - RF11: Links to source files """ from flask import Flask, request, render_template, jsonify, redirect, url_for from database import DatabaseManager import os from pathlib import Path import json app = Flask(__name__) app.config['SECRET_KEY'] = 'your-secret-key-here' # Initialize database manager db = DatabaseManager("../data/activities.db") # Filter options for dropdowns (based on PRD RF8) FILTER_OPTIONS = { 'valori': [ 'Viziune și perspectivă', 'Recunoștință', 'Altele', 'Management timpul', 'Identitate personală' ], 'durata': [ '5-15min', '15-30min', '30+min' ], 'tematica': [ 'cercetășesc', 'team building', 'educativ' ], 'domeniu': [ 'sport', 'artă', 'știință' ], 'metoda': [ 'joc', 'poveste', 'atelier' ], 'materiale': [ 'fără', 'simple', 'complexe' ], 'competente_fizice': [ 'fizice', 'mentale', 'sociale' ], 'competente_impactate': [ 'fizice', 'mentale', 'sociale' ], 'participanti': [ '2-5', '5-10', '10-30', '30+' ], 'varsta': [ '5-8', '8-12', '12-16', '16+' ] } def get_dynamic_filter_options(): """Get dynamic filter options from database""" try: return db.get_filter_options() except: return {} @app.route('/') def index(): """Main search page""" # Get dynamic filter options from database dynamic_filters = get_dynamic_filter_options() # Merge with static options all_filters = FILTER_OPTIONS.copy() all_filters.update(dynamic_filters) return render_template('index.html', filters=all_filters) @app.route('/search', methods=['GET', 'POST']) def search(): """Search activities based on filters and query""" # Get search parameters search_query = request.form.get('search_query', '').strip() or request.args.get('q', '').strip() # Get filter values filters = {} for filter_name in FILTER_OPTIONS.keys(): value = request.form.get(filter_name) or request.args.get(filter_name) if value and value != '': filters[filter_name] = value # Map filter names to database fields db_filters = {} if 'tematica' in filters: db_filters['category'] = filters['tematica'] if 'varsta' in filters: db_filters['age_group'] = filters['varsta'] + ' ani' if 'participanti' in filters: db_filters['participants'] = filters['participanti'] + ' persoane' if 'durata' in filters: db_filters['duration'] = filters['durata'] if 'materiale' in filters: material_map = {'fără': 'Fără materiale', 'simple': 'Materiale simple', 'complexe': 'Materiale complexe'} db_filters['materials'] = material_map.get(filters['materiale'], filters['materiale']) # Search in database try: results = db.search_activities( search_text=search_query if search_query else None, **db_filters, limit=100 ) # Convert results to list of dicts for template activities = [] for result in results: activities.append({ 'id': result['id'], 'title': result['title'], 'description': result['description'][:200] + '...' if len(result['description']) > 200 else result['description'], 'category': result['category'], 'age_group': result['age_group'], 'participants': result['participants'], 'duration': result['duration'], 'materials': result['materials'], 'file_path': result['file_path'], 'tags': json.loads(result['tags']) if result['tags'] else [] }) except Exception as e: print(f"Search error: {e}") activities = [] # Get dynamic filter options for the form dynamic_filters = get_dynamic_filter_options() all_filters = FILTER_OPTIONS.copy() all_filters.update(dynamic_filters) return render_template('results.html', activities=activities, search_query=search_query, applied_filters=filters, filters=all_filters, results_count=len(activities)) @app.route('/generate_sheet/') def generate_sheet(activity_id): """Generate activity sheet for specific activity""" try: # Get activity from database results = db.search_activities(limit=1000) # Get all to find by ID activity_data = None for result in results: if result['id'] == activity_id: activity_data = result break if not activity_data: return "Activity not found", 404 # Get similar activities for recommendations similar_activities = db.search_activities( category=activity_data['category'], limit=5 ) # Filter out current activity and limit to 3 recommendations = [act for act in similar_activities if act['id'] != activity_id][:3] return render_template('fisa.html', activity=activity_data, recommendations=recommendations) except Exception as e: print(f"Sheet generation error: {e}") return f"Error generating sheet: {e}", 500 @app.route('/file/') def view_file(filename): """Serve activity files (PDFs, docs, etc.)""" # Security: only serve files from the base directory base_path = Path("/mnt/d/GoogleDrive/Cercetasi/carti-camp-jocuri") file_path = base_path / filename try: if file_path.exists() and file_path.is_file(): # For now, just return file info - in production you'd serve the actual file return f"File: {filename}
Path: {file_path}
Size: {file_path.stat().st_size} bytes" else: return "File not found", 404 except Exception as e: return f"Error accessing file: {e}", 500 @app.route('/api/statistics') def api_statistics(): """API endpoint for database statistics""" try: stats = db.get_statistics() return jsonify(stats) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/reset_filters') def reset_filters(): """Reset all filters and redirect to main page""" return redirect(url_for('index')) @app.errorhandler(404) def not_found(error): return render_template('404.html'), 404 @app.errorhandler(500) def internal_error(error): return render_template('500.html'), 500 def init_app(): """Initialize application""" print("🚀 Starting INDEX-SISTEM-JOCURI Flask Application") print("=" * 50) # Check if database exists and has data try: stats = db.get_statistics() print(f"✅ Database connected: {stats['total_activities']} activities loaded") if stats['total_activities'] == 0: print("⚠️ Warning: No activities found in database!") print(" Run: python indexer.py --clear-db to index files first") except Exception as e: print(f"❌ Database error: {e}") print(f"🌐 Web interface will be available at: http://localhost:5000") print("📱 Interface matches: interfata-web.jpg") print("=" * 50) if __name__ == '__main__': init_app() # Run Flask app app.run( host='0.0.0.0', # Accept connections from any IP port=5000, debug=True, # Enable debug mode for development threaded=True # Handle multiple requests )