feat: private accounts, explore/people merge, meal-plan fixes, i18n and theme cleanup

- Private accounts: users.isPrivate hides a user from search and their
  recipes from search/trending/for-you discovery surfaces (follow-aware
  where the route already has session context, blanket exclusion where it
  doesn't); existing followers and direct links are unaffected, no
  follow-request approval flow was built (explicit scope limit)
- Merged /people into the Explore tab (tab=people query param); the old
  standalone route now redirects there
- "Get Ideas" vs "Surprise Me" were doing the same empty-prompt call;
  Surprise Me now injects a real random constraint (5-ingredient, one-pot,
  etc.), matching the existing pattern in the AI recipe-generate dialog
- Meal-plan day cells now link to their recipe (was dead text) and gained
  a one-click "mark as cooked" action
- Theme toggle is now a real three-way light/dark/system control instead
  of a binary flip
- Nutrition goals form had zero i18n wiring; fully localized now

New migration 0027 (users.is_private) generated, left unapplied like the
others. Verified with typecheck, lint, and a clean --no-cache docker build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Arnaud
2026-07-10 09:26:03 +02:00
parent 36e7698096
commit 9c545a5bb3
20 changed files with 4804 additions and 82 deletions
+24 -4
View File
@@ -19,7 +19,8 @@
"notifications": "Notifications",
"viewProfile": "Voir le profil",
"lightMode": "Mode clair",
"darkMode": "Mode sombre"
"darkMode": "Mode sombre",
"systemMode": "Système"
},
"notifications": {
"title": "Notifications",
@@ -305,7 +306,19 @@
"nutritionGoals": {
"title": "Objectifs nutritionnels quotidiens",
"description": "Définissez vos objectifs quotidiens. Ils apparaissent sous forme de barres de progression dans votre planning repas.",
"viewDiaryCta": "Voir le journal nutritionnel"
"viewDiaryCta": "Voir le journal nutritionnel",
"caloriesLabel": "Calories (kcal/jour)",
"proteinLabel": "Protéines (g/jour)",
"carbsLabel": "Glucides (g/jour)",
"fatLabel": "Lipides (g/jour)",
"caloriesPlaceholder": "ex. 2000",
"proteinPlaceholder": "ex. 50",
"carbsPlaceholder": "ex. 250",
"fatPlaceholder": "ex. 70",
"saveButton": "Enregistrer les objectifs",
"saving": "Enregistrement...",
"saveSuccess": "Objectifs nutritionnels enregistrés",
"saveError": "Impossible d'enregistrer les objectifs nutritionnels"
},
"webhooksPage": {
"title": "Webhooks",
@@ -423,6 +436,8 @@
},
"explore": {
"title": "Explorer",
"tabRecipes": "Recettes",
"tabPeople": "Personnes",
"searchPlaceholder": "Rechercher des recettes publiques…",
"maxMinutes": "Minutes max",
"aiSearchPlaceholder": "ex. dîners rapides en semaine, cuisine réconfortante italienne…",
@@ -677,7 +692,10 @@
"listCreate": "Créer",
"pickRecipe": "Choisir une recette",
"addEntry": "+ Ajouter",
"removeEntry": "Retirer le repas"
"removeEntry": "Retirer le repas",
"markCooked": "Marquer comme cuisiné",
"markCookedSuccess": "Marqué comme cuisiné",
"markCookedFailed": "Échec du marquage comme cuisiné"
},
"pantry": {
"title": "Garde-manger",
@@ -1014,7 +1032,9 @@
"publicBioPlaceholder": "Parlez de vous aux autres cuisiniers…",
"privateBio": "Contexte IA (privé)",
"privateBioDescription": "Jamais visible publiquement. Injecté dans les prompts IA pour personnaliser les suggestions — ajoutez vos préférences alimentaires, équipements, niveau de cuisine, allergies, etc.",
"privateBioPlaceholder": "ex. Je suis végétarien, j'ai un robot pâtissier et une friteuse à air, niveau intermédiaire, allergique aux fruits à coque, je préfère les saveurs méditerranéennes…"
"privateBioPlaceholder": "ex. Je suis végétarien, j'ai un robot pâtissier et une friteuse à air, niveau intermédiaire, allergique aux fruits à coque, je préfère les saveurs méditerranéennes…",
"privateAccount": "Compte privé",
"privateAccountDescription": "Une fois activé, votre profil et vos recettes n'apparaîtront plus dans la recherche ni dans les découvertes (Explorer, Tendances, Pour vous). Les personnes qui vous suivent déjà continueront de voir vos recettes."
},
"profilePage": {
"tabRecipes": "Recettes",