/* eslint-disable react-hooks/exhaustive-deps, react-hooks/set-state-in-effect, react-hooks/immutability */ import React, { useState, useEffect } from 'react'; import { useAuth } from './AuthContext'; import { useNavigate } from 'react-router-dom'; import { Shield, Zap, Check, Target, ArrowRight, Briefcase } from 'lucide-react'; export default function PricingSection({ embedded = false, hideCurrentPlan = false }) { const { user, token, refreshAccessToken } = useAuth(); const navigate = useNavigate(); const [loadingPlan, setLoadingPlan] = useState(null); const [paymentSuccess, setPaymentSuccess] = useState(false); const [paymentError, setPaymentError] = useState(null); const [dynamicPrices, setDynamicPrices] = useState({}); useEffect(() => { // Fetch dynamic prices from backend fetch('/api/billing/tiers') .then(res => res.json()) .then(data => { const prices = {}; data.forEach(t => { prices[t.id] = (t.monthly_price / 100).toFixed(2); }); setDynamicPrices(prices); }) .catch(err => console.error("Failed to load dynamic prices", err)); const urlParams = new URLSearchParams(window.location.search); const sessionId = urlParams.get('session_id'); const canceled = urlParams.get('canceled'); const tierId = urlParams.get('tier_id'); if (sessionId && token) { verifyStripePayment(sessionId, tierId); } else if (canceled) { setPaymentError("Payment was canceled."); window.history.replaceState({}, document.title, window.location.pathname); } }, [token]); const verifyStripePayment = async (sessionId, tierId) => { try { let res = await fetch('/api/billing/verify-payment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ session_id: sessionId, tier_id: tierId }) }); if (res.status === 401) { // Token likely expired while user was on Stripe checkout const newToken = await refreshAccessToken(); if (newToken) { res = await fetch('/api/billing/verify-payment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${newToken}` }, body: JSON.stringify({ session_id: sessionId, tier_id: tierId }) }); } } const data = await res.json(); if (data.status === 'success') { setPaymentSuccess(true); setTimeout(() => { window.history.replaceState({}, document.title, window.location.pathname); window.location.reload(); }, 4000); } else { setPaymentError("Payment verification failed: " + (data.message || 'Unknown Error') + ". Please contact our support team at support@larshield.com for assistance."); window.history.replaceState({}, document.title, window.location.pathname); } } catch (err) { console.error(err); setPaymentError("Error verifying payment. Please reach out to our technical team at support@larshield.com."); } }; const handleSubscribe = async (priceId) => { if (priceId === 'enterprise') { window.location.href = "#booking"; return; } if (!user) { navigate('/login'); return; } setLoadingPlan(priceId); try { const res = await fetch('/api/billing/create-checkout-session', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ price_id: priceId, billing_cycle: 'monthly' }) }); const orderData = await res.json(); if (!orderData.checkout_url) { setPaymentError("Failed to create order: " + (orderData.message || 'Unknown error') + ". Please contact our support team at support@larshield.com."); setLoadingPlan(null); return; } window.location.href = orderData.checkout_url; } catch (err) { console.error(err); setPaymentError("An error occurred during checkout initialization. Please reach out to our technical team at support@larshield.com."); setLoadingPlan(null); } }; const plans = [ { id: 'quick', name: "Quick Scan", icon: , price: dynamicPrices['quick'] || 4.99, description: "Essential reconnaissance & basic security health checks.", scanners: "13 Security Modules", features: [ "3 Scans for 1 Target Website", "Fast Recon (Headers, Nmap Quick, WHOIS, WAF)", "DNS Security & SSL/TLS Audit", "Cookies, CSP & Clickjacking Checks", "Git Repository Exposure Detection", "Instant PDF Report Export" ], popular: false }, { id: 'advanced', name: "Advanced Scan", icon: , price: dynamicPrices['advanced'] || 44.99, description: "Core vulnerability auditing & deep path analysis.", scanners: "36 Security Modules", popular: false, features: [ "3 Scans for 1 Target Website", "Everything in Quick Scan", "Subdomain Discovery (Subfinder, Amass, crt.sh)", "XSS, SQL Injection & Path Traversal Fuzzing", "REST API, Cloud Bucket & Secrets Leak Scan", "CVE Database & Nikto Web Server Engine", "AI Remediation & Strategy Generator" ] }, { id: 'deep', name: "Deep Scan", icon: , price: dynamicPrices['deep'] || 99.99, description: "Exhaustive threat inspection & active DAST attack simulation.", scanners: "89 Security Modules", popular: true, features: [ "3 Scans for 1 Target Website", "Everything in Advanced Scan", "Full 65535-Port Nmap with NSE Vulnerability Scripts", "Nuclei Scanner Engine (Critical/High/Med/Low)", "OWASP ZAP DAST Engine (Active Attack Mode)", "XXE, SSTI, IDOR, GraphQL & Business Logic Flaws", "HTTP/2 Desync, JS Supply Chain & SAML/OAuth Bypasses" ] }, { id: 'enterprise', name: "Custom Solutions", icon: , price: "Custom", description: "Tailored VAPT services and dedicated security infrastructure.", scanners: "Expert Manual VAPT", popular: false, features: [ "Everything in Deep Scan", "Quarterly Manual VAPT", "Dedicated Security Architect", "Custom Compliance Reporting", "On-Premise Deployment Options", "1-Hour SLA" ] } ]; return (
{paymentError && (
error {paymentError}
)} {paymentSuccess && (
check_circle

Upgrade Successful!

Your payment was verified. We are unlocking your scan package...

)} {/* Background Soft Gradients (Adapted to Light Theme) */}
LarShield Target Scan Packages

Single Domain Scan Packages

Purchase a plan once and perform up to 3 complete scans on the same target website.

verified 1 Plan Purchase = 3 Scans Allowed for 1 Target Website
{/* Pricing Cards */}
{plans.map((plan) => { const isCurrentPlan = hideCurrentPlan ? false : user?.subscription_tier === plan.id; return (
{plan.popular && (
Recommended
)}
{React.cloneElement(plan.icon, { className: "w-5 h-5 text-primary" })}

{plan.name}

{plan.description}

{plan.price === 'Custom' ? 'Custom' : `$${plan.price}`} {/* Removed / month per user request */}
{plan.scanners}
    {plan.features.map((feature, idx) => (
  • {feature}
  • ))}
); })}
); }