134 lines
4.4 KiB
JavaScript
134 lines
4.4 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import axios from "axios";
|
|
|
|
const SubscriptionPlans = () => {
|
|
const [plans, setPlans] = useState([]);
|
|
const [frequency, setFrequency] = useState(1);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const fetchPlans = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const res = await axios.get(
|
|
`http://localhost:5032/api/market/list/subscription-plan?frequency=${frequency}`,
|
|
{ headers: { "Content-Type": "application/json" } }
|
|
);
|
|
setPlans(res.data?.data || []);
|
|
} catch (err) {
|
|
console.error("Error fetching plans:", err);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
fetchPlans();
|
|
}, [frequency]);
|
|
|
|
const frequencyLabel = (freq) => {
|
|
switch (freq) {
|
|
case 0: return "mo";
|
|
case 1: return "3mo";
|
|
case 2: return "6mo";
|
|
case 3: return "yr";
|
|
default: return "mo";
|
|
}
|
|
};
|
|
|
|
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">
|
|
{loading ? (
|
|
<div className="text-center">Loading...</div>
|
|
) : plans.length === 0 ? (
|
|
<div className="text-center">No plans found</div>
|
|
) : (
|
|
plans.map((plan) => (
|
|
<div key={plan.id} className="col-xl-4 col-lg-6 col-md-6">
|
|
<div className="card h-100 shadow-sm border-0 p-3">
|
|
{/* Header */}
|
|
<div className="d-flex align-items-center gap-3 mb-3">
|
|
<i className="bx bxs-package text-primary fs-1"></i>
|
|
<div>
|
|
<p className="card-title fs-4 fw-bold mb-1 me-6">
|
|
{plan.planName}
|
|
</p>
|
|
<p className="text-muted mb-0">{plan.description}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Price */}
|
|
<div className="text-start mb-3">
|
|
<h4 className="fw-semibold mt-auto mb-3">
|
|
{plan.currency?.symbol} {plan.price}
|
|
</h4>
|
|
</div>
|
|
|
|
{/* Storage & Trial */}
|
|
<div className="text-start text-muted mb-3">
|
|
<div className="mb-1">
|
|
<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-start">
|
|
Features
|
|
</h6>
|
|
<ul className="list-unstyled text-start mb-4">
|
|
{plan.features?.modules &&
|
|
Object.values(plan.features.modules).map((mod) =>
|
|
mod && mod.name ? (
|
|
<li
|
|
key={mod.id}
|
|
className="d-flex align-items-center mb-2"
|
|
>
|
|
{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">
|
|
<button className="btn btn-outline-primary w-100 fw-bold">
|
|
Select Plan
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SubscriptionPlans;
|