diff --git a/__pycache__/app.cpython-313.pyc b/__pycache__/app.cpython-313.pyc index 7da0fcd..d7aab49 100644 Binary files a/__pycache__/app.cpython-313.pyc and b/__pycache__/app.cpython-313.pyc differ diff --git a/__pycache__/models.cpython-313.pyc b/__pycache__/models.cpython-313.pyc index c577fe6..da12aed 100644 Binary files a/__pycache__/models.cpython-313.pyc and b/__pycache__/models.cpython-313.pyc differ diff --git a/migrations/versions/add_stripe_payment_links_to_pricing_plans.py b/migrations/versions/add_stripe_payment_links_to_pricing_plans.py new file mode 100644 index 0000000..1ea20a9 --- /dev/null +++ b/migrations/versions/add_stripe_payment_links_to_pricing_plans.py @@ -0,0 +1,43 @@ +"""add stripe payment links to pricing plans + +Revision ID: add_stripe_payment_links +Revises: 9206bf87bb8e +Create Date: 2024-12-19 13:00:00.000000 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy import text + + +# revision identifiers, used by Alembic. +revision = 'add_stripe_payment_links' +down_revision = '9206bf87bb8e' +branch_labels = None +depends_on = None + + +def upgrade(): + conn = op.get_bind() + + # Check if columns already exist + result = conn.execute(text(""" + SELECT column_name + FROM information_schema.columns + WHERE table_name = 'pricing_plans' + AND column_name IN ('monthly_stripe_link', 'annual_stripe_link') + """)) + existing_columns = [row[0] for row in result.fetchall()] + + # Add Stripe payment link columns if they don't exist + if 'monthly_stripe_link' not in existing_columns: + op.add_column('pricing_plans', sa.Column('monthly_stripe_link', sa.String(length=500), nullable=True)) + + if 'annual_stripe_link' not in existing_columns: + op.add_column('pricing_plans', sa.Column('annual_stripe_link', sa.String(length=500), nullable=True)) + + +def downgrade(): + # Remove Stripe payment link columns + op.drop_column('pricing_plans', 'annual_stripe_link') + op.drop_column('pricing_plans', 'monthly_stripe_link') \ No newline at end of file diff --git a/models.py b/models.py index 3a96298..e9a236c 100644 --- a/models.py +++ b/models.py @@ -603,6 +603,9 @@ class PricingPlan(db.Model): is_custom = db.Column(db.Boolean, default=False) button_text = db.Column(db.String(50), default='Get Started') button_url = db.Column(db.String(200), default='#') + # Stripe payment links + monthly_stripe_link = db.Column(db.String(500), nullable=True) + annual_stripe_link = db.Column(db.String(500), nullable=True) order_index = db.Column(db.Integer, default=0) is_active = db.Column(db.Boolean, default=True) # Quota fields diff --git a/routes/__pycache__/admin.cpython-313.pyc b/routes/__pycache__/admin.cpython-313.pyc index d7c90a3..4ca6cc1 100644 Binary files a/routes/__pycache__/admin.cpython-313.pyc and b/routes/__pycache__/admin.cpython-313.pyc differ diff --git a/routes/admin.py b/routes/admin.py index b780b03..fbb43dc 100644 --- a/routes/admin.py +++ b/routes/admin.py @@ -469,7 +469,8 @@ def create_pricing_plan(): annual_price = float(request.form.get('annual_price')) features = json.loads(request.form.get('features', '[]')) button_text = request.form.get('button_text', 'Get Started') - button_url = request.form.get('button_url', '#') + monthly_stripe_link = request.form.get('monthly_stripe_link', '') + annual_stripe_link = request.form.get('annual_stripe_link', '') is_popular = request.form.get('is_popular') == 'true' is_custom = request.form.get('is_custom') == 'true' is_active = request.form.get('is_active') == 'true' @@ -496,7 +497,8 @@ def create_pricing_plan(): annual_price=annual_price, features=features, button_text=button_text, - button_url=button_url, + monthly_stripe_link=monthly_stripe_link, + annual_stripe_link=annual_stripe_link, is_popular=is_popular, is_custom=is_custom, is_active=is_active, @@ -582,7 +584,8 @@ def update_pricing_plan(plan_id): annual_price = float(request.form.get('annual_price')) features = json.loads(request.form.get('features', '[]')) button_text = request.form.get('button_text', 'Get Started') - button_url = request.form.get('button_url', '#') + monthly_stripe_link = request.form.get('monthly_stripe_link', '') + annual_stripe_link = request.form.get('annual_stripe_link', '') is_popular = request.form.get('is_popular') == 'true' is_custom = request.form.get('is_custom') == 'true' is_active = request.form.get('is_active') == 'true' @@ -605,7 +608,8 @@ def update_pricing_plan(plan_id): plan.annual_price = annual_price plan.features = features plan.button_text = button_text - plan.button_url = button_url + plan.monthly_stripe_link = monthly_stripe_link + plan.annual_stripe_link = annual_stripe_link plan.is_popular = is_popular plan.is_custom = is_custom plan.is_active = is_active diff --git a/static/js/settings/pricing.js b/static/js/settings/pricing.js index 653b2b6..909d20f 100644 --- a/static/js/settings/pricing.js +++ b/static/js/settings/pricing.js @@ -164,7 +164,8 @@ function loadPlanForEdit(planId) { document.getElementById('editMonthlyPrice').value = plan.monthly_price; document.getElementById('editAnnualPrice').value = plan.annual_price; document.getElementById('editButtonText').value = plan.button_text; - document.getElementById('editButtonUrl').value = plan.button_url; + document.getElementById('editMonthlyStripeLink').value = plan.monthly_stripe_link || ''; + document.getElementById('editAnnualStripeLink').value = plan.annual_stripe_link || ''; document.getElementById('editIsPopular').checked = plan.is_popular; document.getElementById('editIsCustom').checked = plan.is_custom; document.getElementById('editIsActive').checked = plan.is_active; diff --git a/templates/components/pricing_section.html b/templates/components/pricing_section.html index 2f63494..473e9a8 100644 --- a/templates/components/pricing_section.html +++ b/templates/components/pricing_section.html @@ -47,9 +47,27 @@ - - {{ plan.button_text }} - + + {% if plan.is_custom %} + + {{ plan.button_text }} + + {% else %} + {% if plan.monthly_stripe_link or plan.annual_stripe_link %} + + {{ plan.button_text }} + + {% else %} + + {{ plan.button_text }} + + {% endif %} + {% endif %} @@ -242,6 +260,14 @@ document.addEventListener('DOMContentLoaded', function() { // Simply animate the number change animateNumber(price, monthlyValue, annualValue); }); + + // Update payment links to annual + document.querySelectorAll('.payment-button').forEach(button => { + const annualLink = button.getAttribute('data-annual-link'); + if (annualLink) { + button.href = annualLink; + } + }); } else { // Switch to monthly prices with animation monthlyPrices.forEach((price, index) => { @@ -251,6 +277,14 @@ document.addEventListener('DOMContentLoaded', function() { // Simply animate the number change back to monthly animateNumber(price, currentValue, originalMonthlyValue); }); + + // Update payment links to monthly + document.querySelectorAll('.payment-button').forEach(button => { + const monthlyLink = button.getAttribute('data-monthly-link'); + if (monthlyLink) { + button.href = monthlyLink; + } + }); } }); }); diff --git a/templates/settings/tabs/pricing.html b/templates/settings/tabs/pricing.html index f5afabf..e26bed2 100644 --- a/templates/settings/tabs/pricing.html +++ b/templates/settings/tabs/pricing.html @@ -53,6 +53,35 @@ + + {% if plan.monthly_stripe_link or plan.annual_stripe_link %} +