import os import json from typing import Dict, List from flask import Blueprint, render_template, request from modules.projects.project_handler import ProjectHandler projects_bp = Blueprint('projects', __name__) _handler = ProjectHandler() def _project_root() -> str: # 3 niveaux au dessus de modules/projects/ = racine projet return os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) def _clients_dir() -> str: return os.path.join(_project_root(), 'Data', 'clients') def _load_clients_index() -> Dict[str, str]: """ Retourne un dict {client_id: client_name lisible} client_id = nom de fichier sans extension dans Data/clients """ idx: Dict[str, str] = {} cdir = _clients_dir() if not os.path.isdir(cdir): return idx for fname in os.listdir(cdir): if not fname.endswith('.json'): continue client_id = os.path.splitext(fname)[0] path = os.path.join(cdir, fname) try: with open(path, 'r', encoding='utf-8') as f: data = json.load(f) name = data.get('client_name') or client_id.replace('_', ' ').title() idx[client_id] = name except Exception: idx[client_id] = client_id.replace('_', ' ').title() return idx def _list_all_projects() -> List: """ Parcourt Data/projects/ et retourne la liste des objets Project. """ base = _handler.base_dir projects = [] if os.path.isdir(base): for client_id in os.listdir(base): client_path = os.path.join(base, client_id) if os.path.isdir(client_path): projects.extend(_handler.list_projects(client_id)) return projects @projects_bp.route('/projects', methods=['GET']) def projects_index(): clients_idx = _load_clients_index() selected_client = request.args.get('client_id', '').strip() query = request.args.get('q', '').strip().lower() # Charger tous les projets projects = _list_all_projects() # Filtre par client if selected_client: projects = [p for p in projects if p.client_id == selected_client] # Recherche plein texte basique if query: def match(p) -> bool: hay = ' '.join([ p.name or '', p.status or '', p.description or '' ]).lower() return query in hay projects = [p for p in projects if match(p)] # Tri par updated_at décroissante projects.sort(key=lambda p: p.updated_at or '', reverse=True) # Transformer pour la vue (nom client) def client_name_for(pid: str) -> str: return clients_idx.get(pid, pid.replace('_', ' ').title()) view_projects = [] for p in projects: view_projects.append({ 'id': p.id, 'client_id': p.client_id, 'client_name': client_name_for(p.client_id), 'name': p.name, 'status': p.status, 'start_date': p.start_date, 'end_date': p.end_date, 'budget': p.budget, 'updated_at': p.updated_at }) # Liste triée des clients pour le sélecteur clients_for_select = sorted( [{'id': cid, 'name': cname} for cid, cname in clients_idx.items()], key=lambda c: c['name'].lower() ) return render_template( 'projects/all_projects.html', projects=view_projects, clients=clients_for_select, selected_client=selected_client, q=request.args.get('q', '').strip() )