New cockpit
This commit is contained in:
93
app.py
93
app.py
@@ -46,6 +46,46 @@ _DOMAIN_LABELS = {
|
||||
'other': ('Autre', '📌'),
|
||||
}
|
||||
|
||||
_CONDITION_LABELS = {
|
||||
'hypertension': 'Hypertension',
|
||||
'diabetes_risk': 'Risque diabète',
|
||||
'cardiovascular_risk': 'Risque cardio-vasculaire',
|
||||
'anxiety': 'Anxiété',
|
||||
'digestive_issues': 'Troubles digestifs',
|
||||
'back_pain': 'Douleurs dorsales',
|
||||
'osteoporosis_risk': 'Risque ostéoporose',
|
||||
'metabolic_syndrome': 'Syndrome métabolique',
|
||||
'thyroid': 'Thyroïde',
|
||||
'sleep_apnea': 'Apnée du sommeil',
|
||||
}
|
||||
_GOAL_LABELS = {
|
||||
'weight_loss': 'Perte de poids',
|
||||
'muscle_gain': 'Prise de muscle',
|
||||
'longevity': 'Longévité',
|
||||
'energy': 'Énergie',
|
||||
'better_sleep': 'Améliorer le sommeil',
|
||||
'stress_reduction': 'Réduction du stress',
|
||||
'metabolic_health': 'Santé métabolique',
|
||||
'cardiovascular_health': 'Santé cardio-vasculaire',
|
||||
'cognitive_health': 'Santé cognitive',
|
||||
}
|
||||
_DIET_LABELS = {
|
||||
'omnivore': 'Omnivore',
|
||||
'flexitarian': 'Flexitarien',
|
||||
'vegetarian': 'Végétarien',
|
||||
'vegan': 'Végétalien',
|
||||
'paleo': 'Paléo',
|
||||
'keto': 'Kéto',
|
||||
'other': 'Autre',
|
||||
}
|
||||
_ACTIVITY_LABELS = {
|
||||
'sedentary': 'Sédentaire',
|
||||
'light': 'Légère activité',
|
||||
'moderate': 'Activité modérée',
|
||||
'intense': 'Activité intense',
|
||||
'athlete': 'Athlète',
|
||||
}
|
||||
|
||||
|
||||
# ── Models ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -796,9 +836,37 @@ def admin_review_update(rid):
|
||||
@login_required
|
||||
@admin_required
|
||||
def admin_library():
|
||||
from pipeline import _CONDITIONS, _HEALTH_GOALS, _DIET_TYPES, _ACTIVITY_LEVELS
|
||||
|
||||
recs = PendingRecommendation.query.filter_by(status='approved') \
|
||||
.order_by(PendingRecommendation.domain, PendingRecommendation.priority.desc()).all()
|
||||
return render_template('admin/library.html', recs=recs, domain_labels=_DOMAIN_LABELS)
|
||||
|
||||
tree = {}
|
||||
ev_total = {'A': 0, 'B': 0, 'C': 0}
|
||||
for rec in recs:
|
||||
d = rec.domain
|
||||
ev = rec.evidence_level if rec.evidence_level in ('A', 'B', 'C') else 'C'
|
||||
ev_total[ev] += 1
|
||||
if d not in tree:
|
||||
tree[d] = {'recs': [], 'tags': {}, 'ev': {'A': 0, 'B': 0, 'C': 0}}
|
||||
tree[d]['recs'].append(rec)
|
||||
tree[d]['ev'][ev] += 1
|
||||
for tag in (rec.tags or []):
|
||||
tag = tag.strip().lower()
|
||||
if not tag:
|
||||
continue
|
||||
if tag not in tree[d]['tags']:
|
||||
tree[d]['tags'][tag] = {'recs': [], 'ev': {'A': 0, 'B': 0, 'C': 0}}
|
||||
tree[d]['tags'][tag]['recs'].append(rec)
|
||||
tree[d]['tags'][tag]['ev'][ev] += 1
|
||||
|
||||
return render_template('admin/library.html',
|
||||
recs=recs, tree=tree,
|
||||
domain_labels=_DOMAIN_LABELS, ev_total=ev_total,
|
||||
conditions=_CONDITIONS, health_goals=_HEALTH_GOALS,
|
||||
diet_types=_DIET_TYPES, activity_levels=_ACTIVITY_LEVELS,
|
||||
condition_labels=_CONDITION_LABELS, goal_labels=_GOAL_LABELS,
|
||||
diet_labels=_DIET_LABELS, activity_labels=_ACTIVITY_LABELS)
|
||||
|
||||
|
||||
@app.route('/admin/library/<int:rid>/delete', methods=['POST'])
|
||||
@@ -814,6 +882,29 @@ def admin_library_delete(rid):
|
||||
return redirect(url_for('admin_library'))
|
||||
|
||||
|
||||
@app.route('/admin/library/<int:rid>/update', methods=['POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def admin_library_update(rid):
|
||||
rec = db.get_or_404(PendingRecommendation, rid)
|
||||
f = request.form
|
||||
rec.target_sex = f.get('target_sex', 'all')
|
||||
rec.target_age_min = int(f['target_age_min']) if f.get('target_age_min') else None
|
||||
rec.target_age_max = int(f['target_age_max']) if f.get('target_age_max') else None
|
||||
rec.not_for_under_18 = 'not_for_under_18' in f
|
||||
rec.not_for_pregnant = 'not_for_pregnant' in f
|
||||
rec.required_conditions = f.getlist('required_conditions')
|
||||
rec.excluded_conditions = f.getlist('excluded_conditions')
|
||||
rec.required_health_goals = f.getlist('required_health_goals')
|
||||
rec.required_diet_types = f.getlist('required_diet_types')
|
||||
rec.required_activity_levels = f.getlist('required_activity_levels')
|
||||
rec.priority = int(f.get('priority', rec.priority))
|
||||
rec.admin_notes = f.get('admin_notes', '').strip()
|
||||
db.session.commit()
|
||||
flash(f'Ciblage de « {rec.title} » mis à jour.', 'success')
|
||||
return redirect(url_for('admin_library'))
|
||||
|
||||
|
||||
@app.route('/admin/config', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
|
||||
Reference in New Issue
Block a user