hugging-c-ai / src /app /pricing /page.js
NeoPy's picture
feat: Hugging-c-ai v2 — HF OAuth + multi-provider AI + HF bucket storage + Gradio
60faa09
Raw History Blame Contribute Delete
5.73 kB
"use client";
import { useSession } from "next-auth/react";
import { useState } from "react";
import Navbar from "@/components/Navbar";
import Footer from "@/components/Footer";
import { FaCheck, FaInfoCircle } from "react-icons/fa";
import axios from "axios";
import toast, { Toaster } from "react-hot-toast";
const PLANS = [
{ id: "basic", name: "Basic Pack", price: "$5", credits: 100, description: "Perfect for testing custom prompts and exploring styles." },
{ id: "standard", name: "Standard Pack", price: "$10", credits: 250, description: "Ideal for regular creators wanting high resolution outputs." },
{ id: "pro", name: "Professional Pack", price: "$20", credits: 600, description: "Designed for power users demanding batch exports and high speed.", popular: true },
{ id: "business", name: "Business Pack", price: "$50", credits: 2000, description: "Maximum value pack for agency workflows and large volume generations." }
];
export default function Pricing() {
const { data: session, status } = useSession();
const [loadingPlan, setLoadingPlan] = useState(null);
const handleCheckout = async (planId) => {
if (status !== "authenticated") {
toast.error("You must sign in with Google to purchase credit packages.");
return;
}
setLoadingPlan(planId);
try {
const { data } = await axios.post("/api/checkout", { planId });
if (data.url) {
window.location.href = data.url;
} else {
throw new Error("No redirection URL returned");
}
} catch (err) {
console.error(err);
toast.error(err.response?.data?.error || "Failed to trigger Stripe checkout session.");
} finally {
setLoadingPlan(null);
}
};
return (
<div className="flex min-h-dvh flex-col bg-bg-page select-none text-primary-text overflow-hidden">
<Toaster position="top-right" />
<Navbar />
<main className="flex-1 max-w-7xl w-full mx-auto px-4 py-12 sm:px-6 lg:px-8 flex flex-col gap-10 overflow-y-auto scrollbar-subtle items-center">
<div className="text-center space-y-4">
<div className="inline-flex items-center gap-2 px-3 py-1 bg-primary/10 border border-primary/20 rounded-full mb-1">
<FaInfoCircle className="text-primary text-xs" />
<span className="text-[10px] font-black text-primary uppercase tracking-widest">Pricing Plans</span>
</div>
<h1 className="text-3xl sm:text-4xl font-black tracking-tight uppercase">Buy Credits Packs</h1>
<p className="text-xs sm:text-sm text-secondary-text max-w-lg leading-relaxed">
Purchase flexible credit packages to perform high-resolution predictions. Keep all profits — we handle AI infrastructure.
</p>
</div>
{/* Pricing Cards Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 w-full max-w-5xl">
{PLANS.map((plan) => (
<div
key={plan.id}
className={`relative bg-bg-card border rounded-lg p-6 flex flex-col justify-between gap-6 transition-all duration-300 hover:shadow-2xl hover:-translate-y-1 ${
plan.popular ? "border-primary shadow-xl shadow-primary/5 scale-105" : "border-divider/50 shadow-md"
}`}
>
{plan.popular && (
<span className="absolute -top-3 left-1/2 -translate-x-1/2 bg-primary text-white text-[9px] font-black uppercase px-3 py-1 rounded-full tracking-wider shadow">
Most Popular
</span>
)}
<div className="space-y-4">
<div className="space-y-1">
<h3 className="text-sm font-extrabold uppercase tracking-wide text-primary-text">{plan.name}</h3>
<p className="text-2xl font-black tracking-tight text-white">{plan.price}</p>
</div>
<div className="text-xs bg-bg-page/50 border border-divider/30 p-3 rounded text-center font-extrabold text-primary">
{plan.credits} Art Credits
</div>
<p className="text-xs text-secondary-text leading-relaxed font-medium min-h-[3rem]">{plan.description}</p>
<ul className="space-y-2 border-t border-divider/30 pt-4 text-xs font-semibold text-secondary-text">
<li className="flex items-center gap-2">
<FaCheck className="text-primary text-[10px]" />
<span>Dynamic aspect ratios</span>
</li>
<li className="flex items-center gap-2">
<FaCheck className="text-primary text-[10px]" />
<span>HD image downloads</span>
</li>
<li className="flex items-center gap-2">
<FaCheck className="text-primary text-[10px]" />
<span>No subscription required</span>
</li>
</ul>
</div>
<button
onClick={() => handleCheckout(plan.id)}
disabled={loadingPlan !== null}
className={`w-full py-3 rounded-full text-xs font-bold transition-all shadow-md cursor-pointer select-none active:scale-[0.98] ${
plan.popular ? "bg-primary text-white hover:bg-primary-hover shadow-primary/15" : "bg-bg-page hover:bg-bg-card text-primary-text border border-divider"
}`}
>
{loadingPlan === plan.id ? "Loading checkout..." : "Purchase Credits"}
</button>
</div>
))}
</div>
</main>
<Footer />
</div>
);
}