diff --git a/src/components/bitcoinConnect/SubscriptionPaymentButton.js b/src/components/bitcoinConnect/SubscriptionPaymentButton.js index 505004c..3b4fd79 100644 --- a/src/components/bitcoinConnect/SubscriptionPaymentButton.js +++ b/src/components/bitcoinConnect/SubscriptionPaymentButton.js @@ -286,7 +286,7 @@ const SubscriptionPaymentButtons = ({ )} {(recurring || (!oneTime && !recurring)) && ( { setSubscriptionExpiredAt(expiredAt); } } - }, [user, subscriptionType]); + }, [user]); const handleSubscriptionSuccess = async response => { setIsProcessing(true); @@ -269,7 +269,12 @@ const SubscribeModal = ({ user }) => { setSubscriptionType(e.value)} + onChange={(e) => { + // Only update if the value actually changed + if (e.value !== subscriptionType) { + setSubscriptionType(e.value) + } + }} className="mb-3 w-full max-w-[300px] mx-auto" pt={{ button: { className: 'text-base px-8 py-2 text-white' }, diff --git a/src/components/profile/subscription/UserSubscription.js b/src/components/profile/subscription/UserSubscription.js index a49975f..afe4dd1 100644 --- a/src/components/profile/subscription/UserSubscription.js +++ b/src/components/profile/subscription/UserSubscription.js @@ -187,7 +187,11 @@ const UserSubscription = () => { setSubscriptionType(e.value)} + onChange={(e) => { + if (e.value !== subscriptionType) { + setSubscriptionType(e.value) + } + }} className="mb-3 w-full max-w-[300px] mx-auto" pt={{ button: { className: 'text-base px-8 py-2 text-white' }, diff --git a/src/pages/about.js b/src/pages/about.js index 2bc1dd1..6e62354 100644 --- a/src/pages/about.js +++ b/src/pages/about.js @@ -9,7 +9,6 @@ import useWindowWidth from '@/hooks/useWindowWidth'; import GenericButton from '@/components/buttons/GenericButton'; import InteractivePromotionalCarousel from '@/components/content/carousels/InteractivePromotionalCarousel'; import axios from 'axios'; -import { Menu } from 'primereact/menu'; import { ProgressSpinner } from 'primereact/progressspinner'; import SubscriptionPaymentButtons from '@/components/bitcoinConnect/SubscriptionPaymentButton'; import CalendlyEmbed from '@/components/profile/subscription/CalendlyEmbed'; @@ -18,7 +17,8 @@ import RenewSubscription from '@/components/profile/subscription/RenewSubscripti import Nip05Form from '@/components/profile/subscription/Nip05Form'; import LightningAddressForm from '@/components/profile/subscription/LightningAddressForm'; import MoreInfo from '@/components/MoreInfo'; -import { SUBSCRIPTION_PERIODS } from '@/constants/subscriptionPeriods'; +import { SUBSCRIPTION_PERIODS, calculateExpirationDate } from '@/constants/subscriptionPeriods'; +import { SelectButton } from 'primereact/selectbutton'; const AboutPage = () => { const { data: session, update } = useSession(); @@ -37,6 +37,12 @@ const AboutPage = () => { const [nip05Visible, setNip05Visible] = useState(false); const [cancelSubscriptionVisible, setCancelSubscriptionVisible] = useState(false); const [renewSubscriptionVisible, setRenewSubscriptionVisible] = useState(false); + const [subscriptionType, setSubscriptionType] = useState('monthly'); + + const subscriptionOptions = [ + { label: 'Monthly', value: 'monthly' }, + { label: 'Yearly', value: 'yearly' }, + ]; const isTabView = windowWidth <= 1160; const isMobile = windowWidth < 668; @@ -117,9 +123,16 @@ const AboutPage = () => { useEffect(() => { if (user && user.role) { setSubscribed(user.role.subscribed); - const subscribedAt = new Date(user.role.lastPaymentAt); - const subscribedUntil = new Date(subscribedAt.getTime() + SUBSCRIPTION_PERIODS.MONTHLY.DAYS * 24 * 60 * 60 * 1000); - setSubscribedUntil(subscribedUntil); + + if (user.role.lastPaymentAt) { + const subscribedAt = new Date(user.role.lastPaymentAt); + + // Use the shared helper to calculate expiration date + const subscribedUntil = calculateExpirationDate(subscribedAt, user.role.subscriptionType || 'monthly'); + + setSubscribedUntil(subscribedUntil); + } + if (user.role.subscriptionExpiredAt) { const expiredAt = new Date(user.role.subscriptionExpiredAt); setSubscriptionExpiredAt(expiredAt); @@ -133,6 +146,7 @@ const AboutPage = () => { const apiResponse = await axios.put('/api/users/subscription', { userId: session.user.id, isSubscribed: true, + subscriptionType: subscriptionType, }); if (apiResponse.data) { await update(); @@ -369,13 +383,48 @@ const AboutPage = () => { {/* Payment Buttons */} {(!session?.user || (session?.user && !subscribed)) && ( - + <> +
+
+

Select Your Plan

+ { + // Only update if the value actually changed + if (e.value !== subscriptionType) { + setSubscriptionType(e.value) + } + }} + className="mb-3 w-full max-w-[300px] mx-auto" + pt={{ + button: { className: 'text-base px-8 py-2 text-white' }, + root: { className: 'flex justify-center' } + }} + /> + {subscriptionType === 'yearly' && ( +
+ Save ~17% with yearly subscription! +
+ )} +
+ {subscriptionType === 'yearly' ? '500,000' : '50,000'} sats + + ({subscriptionType === 'yearly' ? 'yearly' : 'monthly'}) + +
+
+
+ + + )} ) : ( diff --git a/src/pages/api/users/subscription/cron.js b/src/pages/api/users/subscription/cron.js index 7bb8e87..ecdc27a 100644 --- a/src/pages/api/users/subscription/cron.js +++ b/src/pages/api/users/subscription/cron.js @@ -49,7 +49,7 @@ export default async function handler(req, res) { await ln.fetch(); const newInvoice = await ln.requestInvoice({ satoshi: amount, - comment: `${subscriptionType.charAt(0).toUpperCase() + subscriptionType.slice(1)} Subscription Renewal for User: ${userId}`, + comment: `${subscriptionType ? (subscriptionType.charAt(0).toUpperCase() + subscriptionType.slice(1)) : 'Monthly'} Subscription Renewal for User: ${userId}`, }); console.log(`Generated invoice for ${amount} sats for ${subscriptionType} subscription`);