This commit is contained in:
ct
2025-07-02 18:25:12 +08:00
parent 68a47ec916
commit 0aa0d9569f
20 changed files with 515 additions and 193 deletions

View File

@@ -1,4 +1,6 @@
// resources/js/Pages/User/Partials/upgrade-sheet.jsx
import { usePage } from '@inertiajs/react';
import { SparklesText } from '@/components/magicui/sparkles-text';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
import { Button } from '@/components/ui/button';
@@ -8,11 +10,17 @@ import { useMitt } from '@/plugins/MittContext';
import CartIcon from '@/reusables/cart-icon.jsx';
import CoinIcon from '@/reusables/coin-icon.jsx';
import usePricingStore from '@/stores/PricingStore.js';
import useUserStore from '@/stores/UserStore.js';
import { Download, ShieldIcon } from 'lucide-react';
import { useEffect, useState } from 'react';
import UpgradePlanCarousel from './partials/upgrade-plan-carousel.tsx';
const UpgradeSheet = () => {
const { subscription, one_times, isFetchingPricing, fetchPricing, isCheckingOut, checkoutSubscribe } = usePricingStore();
const { plan, billing, user_usage } = useUserStore();
const { auth } = usePage().props;
const [isRedirectingToBilling, setIsRedirectingToBilling] = useState(false);
// State to control sheet visibility
const [isOpen, setIsOpen] = useState(false);
@@ -104,36 +112,108 @@ const UpgradeSheet = () => {
</SheetHeader>
<div className="mx-auto w-full max-w-[600px] space-y-3 px-4">
{subscription ? (
<div id="plan-purchase" className="mx-auto space-y-6 rounded-lg border p-4 text-center sm:p-7">
<SparklesText className="text-xl font-bold sm:text-2xl">
Upgrade to {subscription?.name} Plan<br></br> at only {subscription?.symbol}
{subscription?.amount}
{subscription?.primary_interval === 'month' ? '/m' : '/y'}*
</SparklesText>
<UpgradePlanCarousel />
<div className="space-y-2">
<Button
disabled={isCheckingOut}
onClick={() => {
handleSubscribe(subscription);
}}
size="lg"
className="mx-auto w-[220px] text-sm sm:text-base"
>
{isCheckingOut ? (
<Spinner className="text-muted h-4 w-4" />
) : (
<span>
Subscribe at ({subscription?.symbol}
{subscription?.amount}
{subscription?.primary_interval === 'month' ? '/m' : '/y'})*
</span>
)}
</Button>
<div className="text-muted-foreground text-xs">* Launch pricing limited to first 1000 users</div>
{auth?.user ? (
<div id="stats">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
{/* Non-watermark Exports */}
{user_usage?.non_watermark_videos_left && (
<div className="bg-card relative overflow-hidden rounded-xl border p-6 shadow-sm">
<div className="relative z-10">
<div className="mb-2 flex items-center gap-2">
<Download className="text-primary h-5 w-5" />
<span className="text-muted-foreground text-xs font-medium">Non-watermark Exports</span>
</div>
<div className="text-foreground text-xl font-bold">{user_usage?.non_watermark_videos_left}</div>
<div className="text-muted-foreground text-sm">exports left</div>
</div>
<Download className="bg-muted absolute -top-2 -right-2 h-20 w-20 opacity-15" />
</div>
)}
{/* Credits */}
<div className="bg-card relative overflow-hidden rounded-xl border p-6 shadow-sm">
<div className="relative z-10">
<div className="mb-2 flex items-center gap-2">
<CoinIcon className="text-primary h-5 w-5" />
<span className="text-muted-foreground text-xs font-medium">Credits</span>
</div>
<div className="text-foreground text-xl font-bold">999</div>
<div className="text-muted-foreground text-sm">available</div>
</div>
<CoinIcon className="bg-muted absolute -top-2 -right-2 h-20 w-20 opacity-15" />
</div>
</div>
</div>
) : (
<div className="flex items-center justify-between rounded-lg border p-4">
<div className="text-xs">Have an account with us?</div>
<Button onClick={() => emitter.emit('login')} size="sm" variant="outline">
Login Now
</Button>
</div>
)}
{subscription ? (
<>
{auth.user && plan.tier != 'free' ? (
<div className="mx-auto space-y-6 rounded-lg border p-4 text-center sm:p-7">
<SparklesText className="text-xl font-bold sm:text-2xl">You're now in the {plan?.name} plan!</SparklesText>
{billing?.portal && (
<Button
variant="outline"
onClick={() => {
setIsRedirectingToBilling(true);
window.location.replace(billing?.portal);
}}
disabled={isRedirectingToBilling}
>
{isRedirectingToBilling ? <Spinner className="text-muted-foreground h-4 w-4" /> : 'Manage Subscription'}
</Button>
)}
<div className="text-muted-foreground block rounded border p-3 text-center text-xs">
<ShieldIcon className="mr-1 mb-1 inline h-4 w-4" />
All our payments are securely processed by Stripe.
</div>
</div>
) : (
<div id="plan-purchase" className="mx-auto space-y-6 rounded-lg border p-4 text-center sm:p-7">
<SparklesText className="text-xl font-bold sm:text-2xl">
Upgrade to {subscription?.name} Plan<br></br> at only {subscription?.symbol}
{subscription?.amount}
{subscription?.primary_interval === 'month' ? '/m' : '/y'}*
</SparklesText>
<UpgradePlanCarousel />
<div className="space-y-2">
<Button
disabled={isCheckingOut}
onClick={() => {
handleSubscribe(subscription);
}}
size="lg"
className="mx-auto w-[220px] text-sm sm:text-base"
>
{isCheckingOut ? (
<Spinner className="text-muted h-4 w-4" />
) : (
<span>
Subscribe at ({subscription?.symbol}
{subscription?.amount}
{subscription?.primary_interval === 'month' ? '/m' : '/y'})*
</span>
)}
</Button>
<div className="text-muted-foreground text-xs">* Launch pricing limited to first 1000 users</div>
<div className="text-muted-foreground block rounded border p-3 text-center text-xs">
<ShieldIcon className="mr-1 mb-1 inline h-4 w-4" />
All our payments are securely processed by Stripe.
</div>
</div>
</div>
)}
</>
) : (
isFetchingPricing && (
<div className="mx-auto w-full">