diff --git a/web/src/padelnomics/app.py b/web/src/padelnomics/app.py index 51a0a64..e54a817 100644 --- a/web/src/padelnomics/app.py +++ b/web/src/padelnomics/app.py @@ -1,6 +1,7 @@ """ Padelnomics - Application factory and entry point. """ +import time from pathlib import Path from quart import Quart, Response, abort, g, redirect, request, session, url_for @@ -9,6 +10,8 @@ from .analytics import close_analytics_db, open_analytics_db from .core import close_db, config, get_csrf_token, init_db, setup_request_id from .i18n import LANG_BLUEPRINTS, SUPPORTED_LANGS, get_translations +_ASSET_VERSION = str(int(time.time())) + def _detect_lang() -> str: """Detect preferred language from cookie then Accept-Language header.""" @@ -220,6 +223,7 @@ def create_app() -> Quart: "ab_tag": getattr(g, "ab_tag", None), "lang": effective_lang, "t": get_translations(effective_lang), + "v": _ASSET_VERSION, } # ------------------------------------------------------------------------- diff --git a/web/src/padelnomics/locales/de.json b/web/src/padelnomics/locales/de.json index eb5ca46..8a44bad 100644 --- a/web/src/padelnomics/locales/de.json +++ b/web/src/padelnomics/locales/de.json @@ -224,6 +224,7 @@ "planner_quote_cta_check_4": "Nur passende Anbieter sehen deine Anfrage", "planner_quote_cta_btn": "Angebote einholen →", "planner_quote_cta_hint": "Dauert ca. 2 Minuten", + "planner_export_inline": "Teile diese Analyse mit Partnern oder Investoren", "planner_export_btn": "Geschäftsplan exportieren (PDF) →", "planner_export_hint": "99 € einmalig · Bankfertig", "planner_signup_bar_msg": "Erstelle ein Konto, um Szenarien zu speichern und Pläne zu vergleichen.", @@ -802,12 +803,12 @@ "card_total_courts": "Plätze gesamt", "card_floor_area": "Grundfläche", "card_court_area": "Platzfläche", - "card_total_capex": "Gesamt-CAPEX", + "card_total_capex": "Gesamtinvestition", "card_per_court": "Pro Platz", "card_per_sqm": "Pro m²", "budget_over": "BUDGET ÜBERSCHRITTEN", "budget_under": "IM BUDGET", - "table_total_capex": "GESAMT-CAPEX", + "table_total_capex": "GESAMTINVESTITION", "th_item": "Position", "th_amount": "Betrag", "card_net_rev_mo": "Nettoumsatz/Monat", @@ -1109,14 +1110,14 @@ "planner_section_util": "Auslastung & Betrieb", "planner_step3_title": "Investition & Baukosten", "planner_step3_sub": "Konfiguriere Baukosten, Glas- und Beleuchtungsoptionen sowie Dein Budgetziel.", - "planner_section_capex": "Bau & CAPEX", + "planner_section_capex": "Investitionskosten (CAPEX)", "planner_hint_adjust": "Nach Szenario anpassen", "planner_step4_title": "Betrieb & Finanzierung", "planner_step4_sub": "Monatliche Betriebskosten, Kreditkonditionen und Exit-Annahmen.", "planner_section_opex": "Monatliche Betriebskosten", "planner_section_financing": "Finanzierung", "planner_section_exit": "Exit-Annahmen", - "planner_chart_capex": "CAPEX-Aufschlüsselung", + "planner_chart_capex": "Kostenaufschlüsselung", "planner_chart_cf": "Monatlicher Netto-Cashflow (60 Monate)", "planner_chart_cum": "Kumulierter Cashflow", "planner_section_annual": "Jahresübersicht", @@ -1151,7 +1152,7 @@ "about_meta_desc": "Padelnomics ist eine kostenlose Finanzplanungsplattform für Padel-Unternehmer. Modelliere deine Investition, finde Anbieter und plane dein Padel-Business mit professionellen Tools.", "about_og_desc": "Entwickelt für Padel-Unternehmer, die professionelle Finanztools ohne Beratungskosten benötigen. Kostenloser Planer, 60+ Variablen, Anbieterverzeichnis und mehr.", "about_h1": "Über Padelnomics", - "about_body_p1": "Padel ist der am schnellsten wachsende Sport in Europa, doch für die meisten Unternehmer ist die Eröffnung einer Paddelhalle immer noch ein Sprung ins Ungewisse. Die Finanzen sind komplex: Der CAPEX variiert stark je nach Anlagentyp, der Standort bestimmt die Auslastung, und der Unterschied zwischen 60 % und 75 % Belegung kann über Erfolg oder Misserfolg einer Investition entscheiden.", + "about_body_p1": "Padel ist eine der am schnellsten wachsenden Sportarten weltweit, doch für die meisten Unternehmer ist die Eröffnung einer Paddelhalle immer noch ein Sprung ins Ungewisse. Die Finanzen sind komplex: Der CAPEX variiert stark je nach Anlagentyp, der Standort bestimmt die Auslastung, und der Unterschied zwischen 60 % und 75 % Belegung kann über Erfolg oder Misserfolg einer Investition entscheiden.", "about_body_p2": "Wir haben Padelnomics gebaut, weil wir kein ausreichend gutes Finanzplanungstool gefunden haben. Vorhandene Rechner sind entweder zu simpel (5 Eingaben, ein Ergebnis) oder hinter teuren Beratungsmandaten verborgen. Wir wollten etwas mit der Tiefe eines professionellen Finanzmodells, aber der Zugänglichkeit einer Web-App.", "about_body_p3": "Das Ergebnis ist ein kostenloser Finanzplaner mit 60+ anpassbaren Variablen, 6 Analyse-Tabs, Sensitivitätsanalyse und den professionellen Kennzahlen, die Banken und Investoren sehen müssen. Jede Annahme ist transparent und anpassbar. Keine Blackboxen.", "about_why_p": "Der Planer ist kostenlos, weil wir glauben, dass bessere Planung zu besseren Padelanlagen führt — und das ist gut für die gesamte Branche. Wir verdienen Geld, indem wir Unternehmer mit Platz-Anbietern und Finanzierungspartnern verbinden, wenn sie bereit sind, von der Planung zum Bau überzugehen.", @@ -1191,8 +1192,8 @@ "landing_faq_a2": "Nein. Der Planer funktioniert sofort ohne Registrierung. Erstelle ein Konto, um Szenarien zu speichern, Konfigurationen zu vergleichen und PDF-Berichte zu exportieren.", "landing_faq_a3": "Wenn du über den Planer Angebote anforderst, teilen wir deine Projektdetails (Anlagentyp, Platzzahl, Glas, Beleuchtung, Land, Budget, Zeitplan) mit passenden Anbietern aus unserem Verzeichnis. Diese kontaktieren dich direkt mit ihren Angeboten.", "landing_faq_a4": "Das Durchsuchen des Verzeichnisses ist für alle kostenlos. Anbieter erhalten standardmäßig einen Basiseintrag. Kostenpflichtige Pläne (Basic ab 39 €/Monat, Growth ab 199 €/Monat, Pro ab 499 €/Monat) schalten Anfrageformulare, vollständige Beschreibungen, Logos, verifizierte Badges und Prioritätsplatzierung frei.", - "landing_faq_a5": "Das Modell verwendet reale Standardwerte auf Basis europäischer Marktdaten. Jede Annahme ist anpassbar, sodass du deine lokalen Gegebenheiten abbilden kannst. Die Sensitivitätsanalyse zeigt, wie sich die Ergebnisse in verschiedenen Szenarien verändern, und hilft dir, die Bandbreite möglicher Ergebnisse zu verstehen.", - "landing_seo_p1": "Padel ist der am schnellsten wachsende Sport in Europa — die Nachfrage nach Plätzen übersteigt das Angebot in Deutschland, Österreich, der Schweiz und darüber hinaus bei weitem. Eine Paddelhalle zu eröffnen kann eine attraktive Investition sein, aber die Zahlen müssen stimmen. Eine typische Indoorhalle mit 6–8 Plätzen erfordert zwischen 300.000 € (Anmietung eines Bestandsgebäudes) und 2–3 Mio. € (Neubau), mit Amortisationszeiten von 3–5 Jahren für gut gelegene Anlagen.", + "landing_faq_a5": "Das Modell verwendet reale Standardwerte auf Basis globaler Marktdaten. Jede Annahme ist anpassbar, sodass du deine lokalen Gegebenheiten abbilden kannst. Die Sensitivitätsanalyse zeigt, wie sich die Ergebnisse in verschiedenen Szenarien verändern, und hilft dir, die Bandbreite möglicher Ergebnisse zu verstehen.", + "landing_seo_p1": "Padel ist eine der am schnellsten wachsenden Racketsportarten weltweit — die Nachfrage nach Plätzen übersteigt das Angebot von Deutschland, Spanien und Schweden bis in die USA und den Nahen Osten. Eine Paddelhalle zu eröffnen kann eine attraktive Investition sein, aber die Zahlen müssen stimmen. Eine typische Indoorhalle mit 6–8 Plätzen erfordert zwischen 300.000 € (Anmietung eines Bestandsgebäudes) und 2–3 Mio. € (Neubau), mit Amortisationszeiten von 3–5 Jahren für gut gelegene Anlagen.", "landing_seo_p2": "Die entscheidenden Faktoren für den Erfolg sind Standort (treibt die Auslastung), Baukosten (CAPEX), Miet- oder Grundstückskosten sowie die Preisstrategie. Unser Finanzplaner ermöglicht es dir, alle diese Variablen interaktiv zu modellieren und die Auswirkungen auf IRR, MOIC, Cashflow und Schuldendienstdeckungsgrad in Echtzeit zu sehen. Ob du als Unternehmer deine erste Anlage prüfst, als Immobilienentwickler Padel in ein Mixed-Use-Projekt integrierst oder als Investor eine bestehende Paddelhalle bewertest — Padelnomics gibt dir die finanzielle Klarheit für fundierte Entscheidungen.", "landing_final_cta_sub": "Modelliere deine Investition und lass dich mit verifizierten Platz-Anbietern aus {total_countries} Ländern zusammenbringen.", "landing_jsonld_org_desc": "Professionelle Planungsplattform für Padelplatz-Investitionen. Finanzplaner, Anbieterverzeichnis und Marktinformationen für Padel-Unternehmer.", diff --git a/web/src/padelnomics/locales/en.json b/web/src/padelnomics/locales/en.json index 1aa318f..dbd6bc0 100644 --- a/web/src/padelnomics/locales/en.json +++ b/web/src/padelnomics/locales/en.json @@ -224,6 +224,7 @@ "planner_quote_cta_check_4": "Only matching suppliers see your request", "planner_quote_cta_btn": "Get Quotes →", "planner_quote_cta_hint": "Takes ~2 minutes", + "planner_export_inline": "Share this analysis with partners or investors", "planner_export_btn": "Export Business Plan (PDF) →", "planner_export_hint": "€99 one-time · Bank-ready", "planner_signup_bar_msg": "Create an account to save scenarios and compare plans.", @@ -1151,7 +1152,7 @@ "about_meta_desc": "Padelnomics is a free financial planning platform for padel entrepreneurs. Model your investment, find suppliers, and plan your padel court business with professional-grade tools.", "about_og_desc": "Built for padel entrepreneurs who need professional financial tools without consulting fees. Free planner, 60+ variables, supplier directory, and more.", "about_h1": "About Padelnomics", - "about_body_p1": "Padel is the fastest-growing sport in Europe, but opening a padel hall is still a leap of faith for most entrepreneurs. The financials are complex: CAPEX varies wildly depending on venue type, location drives utilization, and the difference between a 60% and 75% occupancy rate can mean the difference between a great investment and a money pit.", + "about_body_p1": "Padel is one of the fastest-growing sports worldwide, but opening a padel hall is still a leap of faith for most entrepreneurs. The financials are complex: CAPEX varies wildly depending on venue type, location drives utilization, and the difference between a 60% and 75% occupancy rate can mean the difference between a great investment and a money pit.", "about_body_p2": "We built Padelnomics because we couldn't find a financial planning tool that was good enough. Existing calculators are either too simplistic (5 inputs, one output) or locked behind expensive consulting engagements. We wanted something with the depth of a professional financial model but the accessibility of a web app.", "about_body_p3": "The result is a free financial planner with 60+ adjustable variables, 6 analysis tabs, sensitivity analysis, and the professional metrics that banks and investors need to see. Every assumption is transparent and adjustable. No black boxes.", "about_why_p": "The planner is free because we believe better planning leads to better padel venues, and that's good for the entire industry. We make money by connecting entrepreneurs with court suppliers and financing partners when they're ready to move from planning to building.", @@ -1191,8 +1192,8 @@ "landing_faq_a2": "No. The planner works instantly with no signup. Create an account to save scenarios, compare configurations, and export PDF reports.", "landing_faq_a3": "When you request quotes through the planner, we share your project details (venue type, court count, glass, lighting, country, budget, timeline) with relevant suppliers from our directory. They contact you directly with proposals.", "landing_faq_a4": "Browsing the directory is free for everyone. Suppliers have a basic listing by default. Paid plans (Basic at €39/mo, Growth at €199/mo, Pro at €499/mo) unlock enquiry forms, full descriptions, logos, verified badges, and priority placement.", - "landing_faq_a5": "The model uses real-world defaults based on European market data. Every assumption is adjustable so you can match your local conditions. The sensitivity analysis shows how results change across different scenarios, helping you understand the range of outcomes.", - "landing_seo_p1": "Padel is the fastest-growing sport in Europe, with demand for courts far outstripping supply in Germany, the UK, Scandinavia, and beyond. Opening a padel hall can be a lucrative investment, but the numbers need to work. A typical indoor padel venue with 6-8 courts requires between €300K (renting an existing building) and €2-3M (building new), with payback periods of 3-5 years for well-located venues.", + "landing_faq_a5": "The model uses real-world defaults based on global market data. Every assumption is adjustable so you can match your local conditions. The sensitivity analysis shows how results change across different scenarios, helping you understand the range of outcomes.", + "landing_seo_p1": "Padel is one of the fastest-growing racket sports globally, with demand for courts outstripping supply across markets from Germany, Spain, and Sweden to the US and Middle East. Opening a padel hall can be a lucrative investment, but the numbers need to work. A typical indoor padel venue with 6-8 courts requires between €300K (renting an existing building) and €2-3M (building new), with payback periods of 3-5 years for well-located venues.", "landing_seo_p2": "The key variables that determine success are location (driving utilization), construction costs (CAPEX), rent or land costs, and pricing strategy. Our financial planner lets you model all of these variables interactively, seeing the impact on your IRR, MOIC, cash flow, and debt service coverage ratio in real time. Whether you're an entrepreneur exploring your first venue, a real estate developer adding padel to a mixed-use project, or an investor evaluating a padel hall acquisition, Padelnomics gives you the financial clarity to make informed decisions.", "landing_final_cta_sub": "Model your investment, then get matched with verified court suppliers across {total_countries} countries.", "landing_jsonld_org_desc": "Professional padel court investment planning platform. Financial planner, supplier directory, and market intelligence for padel entrepreneurs.", diff --git a/web/src/padelnomics/planner/calculator.py b/web/src/padelnomics/planner/calculator.py index cf38776..96e75c2 100644 --- a/web/src/padelnomics/planner/calculator.py +++ b/web/src/padelnomics/planner/calculator.py @@ -20,11 +20,11 @@ DEFAULTS = { "venue": "indoor", "own": "rent", "dblCourts": 4, - "sglCourts": 2, - "sqmPerDblHall": 336, - "sqmPerSglHall": 240, - "sqmPerDblOutdoor": 312, - "sqmPerSglOutdoor": 216, + "sglCourts": 0, + "sqmPerDblHall": 250, + "sqmPerSglHall": 160, + "sqmPerDblOutdoor": 230, + "sqmPerSglOutdoor": 150, "ratePeak": 50, "rateOffPeak": 35, "rateSingle": 30, diff --git a/web/src/padelnomics/planner/routes.py b/web/src/padelnomics/planner/routes.py index ac64207..ce954af 100644 --- a/web/src/padelnomics/planner/routes.py +++ b/web/src/padelnomics/planner/routes.py @@ -99,7 +99,11 @@ def augment_d(d: dict, s: dict, lang: str) -> None: "#EC4899", "#06B6D4", "#84CC16", "#F97316", "#475569", "#0EA5E9", "#A78BFA", ] - _cap_items = [i for i in d["capexItems"] if i["amount"] > 0] + _cap_items = sorted( + [i for i in d["capexItems"] if i["amount"] > 0], + key=lambda i: i["amount"], + reverse=True, + ) d["capex_chart"] = { "type": "doughnut", "data": { @@ -114,7 +118,7 @@ def augment_d(d: dict, s: dict, lang: str) -> None: "responsive": True, "maintainAspectRatio": False, "cutout": "60%", - "plugins": {"legend": {"position": "right", "labels": {"boxWidth": 10, "font": {"size": 10}}}}, + "plugins": {"legend": {"position": "right", "labels": {"boxWidth": 10, "font": {"size": 12}, "padding": 8}}}, }, } @@ -380,18 +384,6 @@ async def calculate(): TOTAL_WIZARD_STEPS = 4 -@bp.route("/wizard-nav") -async def wizard_nav(): - """HTMX endpoint: render wizard Back/Next/Calculate buttons for a given step.""" - step = request.args.get("step", 1, type=int) - step = max(1, min(step, TOTAL_WIZARD_STEPS)) - lang = g.get("lang", "en") - t = get_translations(lang) - return await render_template( - "partials/wizard_nav.html", step=step, total_steps=TOTAL_WIZARD_STEPS, t=t, - ) - - @bp.route("/scenarios", methods=["GET"]) @login_required async def scenario_list(): diff --git a/web/src/padelnomics/planner/templates/partials/tab_capex.html b/web/src/padelnomics/planner/templates/partials/tab_capex.html index b910373..dfed10d 100644 --- a/web/src/padelnomics/planner/templates/partials/tab_capex.html +++ b/web/src/padelnomics/planner/templates/partials/tab_capex.html @@ -22,6 +22,8 @@ {% endif %} +
+

{{ t.planner_section_capex }}

@@ -39,6 +41,7 @@
{{ t.th_item }}{{ t.th_amount }}
+
{{ t.planner_chart_capex }}
diff --git a/web/src/padelnomics/planner/templates/partials/tab_returns.html b/web/src/padelnomics/planner/templates/partials/tab_returns.html index 2d046a7..409ca30 100644 --- a/web/src/padelnomics/planner/templates/partials/tab_returns.html +++ b/web/src/padelnomics/planner/templates/partials/tab_returns.html @@ -108,7 +108,7 @@
-
- {{ t.planner_export_inline|default('Share this analysis with partners or investors') }} - {{ t.planner_export_btn }} → -
+ + {{ t.planner_export_inline }} + {{ t.planner_export_btn }} + diff --git a/web/src/padelnomics/planner/templates/planner.html b/web/src/padelnomics/planner/templates/planner.html index 4e24800..88340a0 100644 --- a/web/src/padelnomics/planner/templates/planner.html +++ b/web/src/padelnomics/planner/templates/planner.html @@ -7,7 +7,7 @@ - + {% endblock %} @@ -345,7 +345,8 @@ + + + {% endblock %} {% block scripts %} @@ -431,5 +433,5 @@ window.__COUNTRY_PRESETS__ = {{ country_presets | tojson | safe }}; window.__QUOTE_URL__ = "{{ url_for('leads.quote_request') }}"; - + {% endblock %} diff --git a/web/src/padelnomics/static/css/planner.css b/web/src/padelnomics/static/css/planner.css index edf4bf8..141f93d 100644 --- a/web/src/padelnomics/static/css/planner.css +++ b/web/src/padelnomics/static/css/planner.css @@ -365,10 +365,10 @@ } .pill-options { display: flex; + flex-wrap: wrap; gap: 4px; } .pill-btn { - flex: 1; padding: 6px 10px; font-size: 11px; font-weight: 600; @@ -409,6 +409,8 @@ /* ── Data Tables ── */ .data-table { width: 100%; + max-width: 640px; + margin: 0 auto; border-collapse: collapse; font-size: 12px; } @@ -531,7 +533,7 @@ } /* ── Spacing helpers ── */ -.mb-section { margin-bottom: 28px; } +.mb-section { margin-bottom: 28px; max-width: 640px; margin-left: auto; margin-right: auto; overflow-x: auto; } .mb-4 { margin-bottom: 1rem; } .mt-4 { margin-top: 1rem; } @@ -627,14 +629,14 @@ display: block; position: fixed; right: max(1rem, calc((100vw - 72rem) / 2 - 280px)); - top: 80px; + top: calc(50px + 1.5rem); width: 240px; background: #EFF6FF; border: 2px solid #1D4ED8; border-radius: 20px; padding: 24px; box-shadow: 0 4px 24px rgba(29,78,216,0.1); - z-index: 40; + z-index: 60; } .quote-sidebar__label { font-size: 11px; @@ -1134,30 +1136,53 @@ .wizard-step { max-width: 100%; } .wizard-preview, .wizard-nav { max-width: 100%; } - .wizard-step { padding-bottom: 100px; } /* space for sticky footer */ + .wizard-step { padding-bottom: 140px; } /* space for fixed footer + bottom nav */ + .wizard-footer { + position: fixed; + bottom: 56px; /* sit directly above bottom nav */ + left: 0; + right: 0; + z-index: 55; + margin-top: 0; + padding: 0 1.5rem; + background: #FFFFFF; + border-top: 1px solid #E2E8F0; + } + .wizard-nav { + max-width: 560px; + margin: 0 auto; + border-radius: 0; + border: none; + background: transparent; + } } /* ── Export inline CTA (within Returns tab) ── */ .export-cta-inline { - margin-top: 1.5rem; - padding: 14px 16px; - background: var(--gn-bg); - border: 1px solid rgba(22,163,74,0.2); - border-radius: 12px; - font-size: 12px; - color: var(--txt-2); display: flex; align-items: center; justify-content: space-between; gap: 12px; -} -.export-cta-inline a { - color: var(--gn); - font-weight: 600; + margin-top: 1.5rem; + padding: 14px 20px; + background: var(--gn-bg); + border: 1px solid rgba(22,163,74,0.2); + border-radius: 12px; + font-size: 13px; + color: var(--txt-2); text-decoration: none; + cursor: pointer; + transition: background 0.15s, border-color 0.15s; +} +.export-cta-inline:hover { + background: rgba(22,163,74,0.1); + border-color: rgba(22,163,74,0.35); +} +.export-cta-inline__btn { + color: var(--gn); + font-weight: 700; white-space: nowrap; } -.export-cta-inline a:hover { text-decoration: underline; } /* ── Mobile Bottom Navigation ── */ .bottom-nav { @@ -1167,9 +1192,9 @@ left: 0; right: 0; z-index: 60; - background: var(--bg-2); - border-top: 1px solid var(--border); - padding: 4px 0; + background: #FFFFFF; + border-top: 1px solid #E2E8F0; + padding: 4px 1.5rem; padding-bottom: max(4px, env(safe-area-inset-bottom)); } .bottom-nav__btn { @@ -1180,18 +1205,20 @@ gap: 2px; padding: 6px 4px 4px; border: none; + border-top: 2px solid transparent; background: transparent; - color: var(--txt-3); + color: #94A3B8; font-size: 10px; font-weight: 600; font-family: 'DM Sans', sans-serif; cursor: pointer; - transition: color 0.15s; + transition: color 0.15s, border-color 0.15s; -webkit-tap-highlight-color: transparent; } .bottom-nav__btn svg { transition: color 0.15s; } .bottom-nav__btn--active { - color: var(--rd); + color: #1D4ED8; + border-top-color: #1D4ED8; } @media (max-width: 768px) { .bottom-nav { display: flex; } @@ -1206,7 +1233,6 @@ border: 1px solid var(--border); border-radius: 14px; background: var(--bg-2); - overflow: hidden; } .wizard-details__summary { display: flex; @@ -1252,9 +1278,8 @@ bottom: 56px; /* above bottom nav */ left: 0; right: 0; - z-index: 55; + z-index: 65; padding: 10px 16px; - padding-bottom: max(10px, env(safe-area-inset-bottom)); background: var(--cta-bg); border-top: 1px solid rgba(29,78,216,0.15); box-shadow: 0 -2px 12px rgba(29,78,216,0.08); @@ -1336,4 +1361,12 @@ /* Add padding below content for bottom nav + CTA bar */ .planner-app main { padding-bottom: 120px; } + + /* Hide feedback on planner mobile — too much competing for bottom space. + planner.css only loads on planner pages so this won't affect other pages. */ + #feedback-wrap { display: none !important; } + .feedback-label { display: none; } + + /* Hide live summary on mobile — wizard footer is just nav buttons */ + .wizard-preview { display: none !important; } } diff --git a/web/src/padelnomics/static/js/planner.js b/web/src/padelnomics/static/js/planner.js index 7b211bc..2db28d9 100644 --- a/web/src/padelnomics/static/js/planner.js +++ b/web/src/padelnomics/static/js/planner.js @@ -99,8 +99,16 @@ function showWizStep(n) { steps.forEach(s => s.classList.toggle('active', +s.dataset.wiz === n)); document.querySelectorAll('.wiz-dot').forEach(d => d.classList.toggle('wiz-dot--active', +d.dataset.wiz === n)); - // Fetch server-rendered nav buttons (moves i18n to templates) - htmx.ajax('GET', '/planner/wizard-nav?step=' + n, '#wizNav'); + const nav = document.getElementById('wizNav'); + const back = nav.dataset.back; + const next = nav.dataset.next; + const results = nav.dataset.results; + const isLast = n >= steps.length; + nav.innerHTML = + (n > 1 ? `` : '
') + + (isLast + ? `` + : ``); } // ─── Quote navigation ──────────────────────────────────────────────────────── diff --git a/web/src/padelnomics/templates/base.html b/web/src/padelnomics/templates/base.html index 1d74596..33b6de1 100644 --- a/web/src/padelnomics/templates/base.html +++ b/web/src/padelnomics/templates/base.html @@ -13,7 +13,7 @@ - + @@ -242,7 +242,7 @@ - {{ t.nav_feedback }} + {{ t.nav_feedback }}