""" Utilitaires pour charger et manipuler les données projets depuis le JSON. Modifier uniquement data/projects.json pour mettre à jour le portfolio. """ import json import re from pathlib import Path from typing import Optional, List, Dict from django.conf import settings def load_config() -> Dict: """ Charge la configuration globale du site depuis data/config.json. Contient : profil, navbar, compétences, expériences, contact, footer, SEO. Pour modifier les infos du site, éditez uniquement data/config.json. """ config_path: Path = settings.CONFIG_JSON_PATH if not config_path.exists(): return {} with open(config_path, 'r', encoding='utf-8') as f: return json.load(f) def load_projects() -> List[Dict]: """ Charge tous les projets depuis le fichier JSON. Retourne une liste de dictionnaires projets. """ json_path: Path = settings.PROJECTS_JSON_PATH if not json_path.exists(): return [] with open(json_path, 'r', encoding='utf-8') as f: data = json.load(f) projects = data.get('projects', []) # Générer un slug unique pour chaque projet (utilisé dans les URLs) for i, project in enumerate(projects): project['slug'] = _slugify(project.get('title', f'projet-{i}')) project['id'] = i # Index pour retrouver le projet facilement return projects def get_project_by_slug(slug: str) -> Optional[Dict]: """ Retourne un projet spécifique par son slug. """ projects = load_projects() for project in projects: if project.get('slug') == slug: return project return None def get_all_categories(projects: List[Dict]) -> List[str]: """ Retourne la liste unique de toutes les catégories disponibles. """ categories = set() for project in projects: cat = project.get('category', '').strip() if cat: categories.add(cat) return sorted(list(categories)) def get_all_technologies(projects: List[Dict]) -> List[str]: """ Retourne la liste unique de toutes les technologies utilisées, triées par fréquence décroissante (les plus utilisées en premier). """ freq: Dict[str, int] = {} for project in projects: for tech in project.get('technologies', []): t = tech.strip() freq[t] = freq.get(t, 0) + 1 return sorted(freq.keys(), key=lambda t: (-freq[t], t)) def filter_projects(projects: List[Dict], category: str = '', tech: str = '') -> List[Dict]: """ Filtre les projets par catégorie et/ou technologie. """ filtered = projects if category: filtered = [p for p in filtered if p.get('category', '').lower() == category.lower()] if tech: filtered = [ p for p in filtered if any(t.lower() == tech.lower() for t in p.get('technologies', [])) ] return filtered def _slugify(text: str) -> str: """ Convertit un titre en slug URL-safe. Ex: "Mon Super Projet" → "mon-super-projet" """ text = text.lower().strip() # Remplacer les caractères accentués replacements = { 'à': 'a', 'â': 'a', 'ä': 'a', 'é': 'e', 'è': 'e', 'ê': 'e', 'ë': 'e', 'î': 'i', 'ï': 'i', 'ô': 'o', 'ö': 'o', 'ù': 'u', 'û': 'u', 'ü': 'u', 'ç': 'c', 'ñ': 'n', } for char, replacement in replacements.items(): text = text.replace(char, replacement) # Remplacer tout caractère non alphanumérique par un tiret text = re.sub(r'[^a-z0-9]+', '-', text) text = text.strip('-') return text