139 lines
4.5 KiB
JavaScript
139 lines
4.5 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import axios from "axios";
|
|
import { Link } from "react-router-dom";
|
|
import PlanCardSkeleton from "./PlanCardSkeleton";
|
|
import { useSubscription } from "../../hooks/useAuth";
|
|
import { frequencyLabel } from "../../utils/appUtils";
|
|
|
|
const SubscriptionPlans = () => {
|
|
const [plans, setPlans] = useState([]);
|
|
const [frequency, setFrequency] = useState(1);
|
|
const { data, isLoading, isError, error } = useSubscription(frequency);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
|
|
|
|
|
return (
|
|
<div className="container py-5">
|
|
{/* Frequency Switcher */}
|
|
<div className="text-center mb-4">
|
|
<div className="btn-group" role="group" aria-label="Plan frequency">
|
|
{["Monthly", "Quarterly", "Half-Yearly", "Yearly"].map(
|
|
(label, idx) => (
|
|
<button
|
|
key={idx}
|
|
type="button"
|
|
className={`btn btn-${
|
|
frequency === idx ? "primary" : "outline-secondary"
|
|
}`}
|
|
onClick={() => setFrequency(idx)}
|
|
>
|
|
{label}
|
|
</button>
|
|
)
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Cards */}
|
|
<div className="row g-4 mt-10">
|
|
{isLoading ? (
|
|
// Show 3 skeletons
|
|
<>
|
|
<PlanCardSkeleton />
|
|
<PlanCardSkeleton />
|
|
<PlanCardSkeleton />
|
|
</>
|
|
) : data.length === 0 ? (
|
|
<div className="text-center">No plans found</div>
|
|
) : isError ? (
|
|
<div className="text-start bg-light">
|
|
<p>{error.message}</p>
|
|
<p>{error.name}</p>
|
|
</div>
|
|
) : (
|
|
data.map((plan) => (
|
|
<div key={plan.id} className="col-xl-4 col-lg-6 col-md-6">
|
|
<div className="card h-100 shadow-lg border-0 p-3 text-center p-10">
|
|
{/* Header */}
|
|
<div className="mb-3">
|
|
<i className="bx bxs-package text-primary fs-1 mb-2"></i>
|
|
<p className="card-title fs-3 fw-bold mb-1">
|
|
{plan.planName}
|
|
</p>
|
|
<p className="text-muted mb-0 fs-5">{plan.description}</p>
|
|
</div>
|
|
|
|
{/* Price */}
|
|
<div className="mb-3">
|
|
<h4 className="fw-semibold mt-auto mb-0 fs-3">
|
|
{plan.currency?.symbol} {plan.price}
|
|
<small className="text-muted ms-1">
|
|
/ {frequencyLabel(frequency)}
|
|
</small>
|
|
</h4>
|
|
</div>
|
|
|
|
{/* Storage & Trial */}
|
|
<div className="text-muted mb-5 d-flex justify-content-center gap-4">
|
|
<div>
|
|
<i className="fa-solid fa-hdd me-2"></i>
|
|
Storage {plan.maxStorage} MB
|
|
</div>
|
|
<div>
|
|
<i className="fa-regular fa-calendar-check text-success me-2"></i>
|
|
Trial Days {plan.trialDays}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Features */}
|
|
<h6 className="fw-bold text-uppercase border-top pt-3 mb-3 text-center">
|
|
Features
|
|
</h6>
|
|
<ul className="list-unstyled text-start mb-4 ms-7 fs-5">
|
|
{plan.features?.modules &&
|
|
Object.values(plan.features.modules).map((mod) =>
|
|
mod && mod.name ? (
|
|
<li
|
|
key={mod.id}
|
|
className="d-flex align-items-center mb-4"
|
|
>
|
|
{mod.enabled ? (
|
|
<i className="fa-regular fa-circle-check text-success me-2"></i>
|
|
) : (
|
|
<i className="fa-regular fa-circle-xmark text-danger me-2"></i>
|
|
)}
|
|
{mod.name}
|
|
</li>
|
|
) : null
|
|
)}
|
|
</ul>
|
|
|
|
{/* Button */}
|
|
<div className="mt-auto">
|
|
<Link
|
|
to={`/auth/subscripe/${frequency}/${plan.id}`}
|
|
className="btn btn-outline-primary w-100 fw-bold mb-2"
|
|
>
|
|
Subscribe
|
|
</Link>
|
|
<Link
|
|
to="/auth/reqest/demo"
|
|
className="btn btn-outline-primary w-100 fw-bold"
|
|
>
|
|
Request a Demo
|
|
</Link>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SubscriptionPlans;
|