diff --git a/src/components/profile/subscription/UserSubscription.js b/src/components/profile/subscription/UserSubscription.js index 496f349..1d43ddd 100644 --- a/src/components/profile/subscription/UserSubscription.js +++ b/src/components/profile/subscription/UserSubscription.js @@ -95,48 +95,6 @@ const UserSubscription = () => { } }; - const menuItems = [ - { - label: "Schedule 1:1", - icon: "pi pi-calendar", - command: () => { - setCalendlyVisible(true); - }, - }, - { - label: session?.user?.lightningAddress ? "Update PlebDevs Lightning Address" : "Claim PlebDevs Lightning Address", - icon: "pi pi-bolt", - command: () => { - setLightningAddressVisible(true); - }, - }, - { - label: session?.user?.nip05 ? "Update PlebDevs Nostr NIP-05" : "Claim PlebDevs Nostr NIP-05", - icon: "pi pi-at", - command: () => { - setNip05Visible(true); - }, - }, - { - label: "Renew Subscription", - icon: "pi pi-sync", - command: () => { - setRenewSubscriptionVisible(true); - }, - }, - { - label: "Cancel Subscription", - icon: "pi pi-trash", - command: () => { - setCancelSubscriptionVisible(true); - }, - }, - ]; - - useEffect(() => { - console.log(subscribed) - }, [subscribed]) - return (
{windowWidth < 768 && ( diff --git a/src/components/sidebar/Sidebar.js b/src/components/sidebar/Sidebar.js index 5c23025..0687d25 100644 --- a/src/components/sidebar/Sidebar.js +++ b/src/components/sidebar/Sidebar.js @@ -150,7 +150,7 @@ const Sidebar = ({ course = false }) => {

Create

)} -
session ? router.push('/profile?tab=subscribe') : router.push('/auth/signin')} className={`w-full flex flex-row items-center cursor-pointer py-2 my-2 hover:bg-gray-700 rounded-lg ${isActive('/profile?tab=subscribe') ? 'bg-gray-700' : ''}`}> +
session ? router.push('/profile?tab=subscribe') : router.push('/auth/signin')} className={`w-full flex flex-row items-center cursor-pointer py-2 my-2 hover:bg-gray-700 rounded-lg ${isActive('/profile?tab=subscribe') || isActive('/subscribe') ? 'bg-gray-700' : ''}`}>

Subscribe

diff --git a/src/pages/about.js b/src/pages/about.js index 9e9de5d..95c5094 100644 --- a/src/pages/about.js +++ b/src/pages/about.js @@ -34,7 +34,7 @@ const AboutPage = () => { )} -
+
{
  • Documents: Markdown documents posted as NIP-23 long-form events on Nostr.
  • Videos: Enhanced markdown files with rich media support, including embedded videos, also saved as NIP-23 events.
  • -
  • Courses: Nostr lists that combine multiple documents and videos into a structured learning path.
  • +
  • Courses: Nostr lists (NIP-51) that combines multiple documents and videos into a structured learning path.
diff --git a/src/pages/subscribe.js b/src/pages/subscribe.js index 9f32915..b611171 100644 --- a/src/pages/subscribe.js +++ b/src/pages/subscribe.js @@ -10,47 +10,66 @@ import { Menu } from "primereact/menu"; import GenericButton from '@/components/buttons/GenericButton'; import { ProgressSpinner } from 'primereact/progressspinner'; import SubscriptionPaymentButtons from '@/components/bitcoinConnect/SubscriptionPaymentButton'; +import Image from 'next/image'; +import NostrIcon from '../../public/images/nostr.png'; +import CalendlyEmbed from '@/components/profile/subscription/CalendlyEmbed'; +import CancelSubscription from '@/components/profile/subscription/CancelSubscription'; +import RenewSubscription from '@/components/profile/subscription/RenewSubscription'; +import Nip05Form from '@/components/profile/subscription/Nip05Form'; +import LightningAddressForm from '@/components/profile/subscription/LightningAddressForm'; const Subscribe = () => { const { data: session, update } = useSession(); const { showToast } = useToast(); const router = useRouter(); + const menu = useRef(null); const windowWidth = useWindowWidth(); + const [user, setUser] = useState(null); const [isProcessing, setIsProcessing] = useState(false); const [subscribed, setSubscribed] = useState(false); const [subscribedUntil, setSubscribedUntil] = useState(null); const [subscriptionExpiredAt, setSubscriptionExpiredAt] = useState(null); - const menu = useRef(null); + const [calendlyVisible, setCalendlyVisible] = useState(false); + const [lightningAddressVisible, setLightningAddressVisible] = useState(false); + const [nip05Visible, setNip05Visible] = useState(false); + const [cancelSubscriptionVisible, setCancelSubscriptionVisible] = useState(false); + const [renewSubscriptionVisible, setRenewSubscriptionVisible] = useState(false); useEffect(() => { if (session && session?.user) { - setSubscribed(session?.user.role.subscribed); - const subscribedAt = new Date(session?.user.role.lastPaymentAt); + setUser(session.user); + } + }, [session]) + + useEffect(() => { + if (user && user.role) { + setSubscribed(user.role.subscribed); + const subscribedAt = new Date(user.role.lastPaymentAt); const subscribedUntil = new Date(subscribedAt.getTime() + 31 * 24 * 60 * 60 * 1000); setSubscribedUntil(subscribedUntil); - if (session?.user.role.subscriptionExpiredAt) { - const expiredAt = new Date(session?.user.role.subscriptionExpiredAt) + if (user.role.subscriptionExpiredAt) { + const expiredAt = new Date(user.role.subscriptionExpiredAt) setSubscriptionExpiredAt(expiredAt); } } - }, [session, session?.user]); + }, [user]); - const handleSubscriptionSuccess = async (paymentResponse) => { + const handleSubscriptionSuccess = async (response) => { setIsProcessing(true); try { - const response = await axios.post('/api/subscription/create', { - paymentResponse, + const apiResponse = await axios.put('/api/users/subscription', { + userId: session.user.id, + isSubscribed: true, }); - if (response.data.success) { - showToast('success', 'Subscription successful!'); + if (apiResponse.data) { await update(); - router.push('/dashboard'); + showToast('success', 'Subscription Successful', 'Your subscription has been activated.'); } else { - showToast('error', 'Subscription failed. Please try again.'); + throw new Error('Failed to update subscription status'); } } catch (error) { - console.error('Subscription error:', error); - showToast('error', 'An error occurred. Please try again.'); + console.error('Subscription update error:', error); + showToast('error', 'Subscription Update Failed', `Error: ${error.message}`); } finally { setIsProcessing(false); } @@ -58,51 +77,48 @@ const Subscribe = () => { const handleSubscriptionError = (error) => { console.error('Subscription error:', error); - showToast('error', 'An error occurred during subscription. Please try again.'); + showToast('error', 'Subscription Failed', `An error occurred: ${error.message}`); + setIsProcessing(false); }; - const handleRecurringSubscriptionSuccess = async (paymentResponse) => { + const handleRecurringSubscriptionSuccess = async () => { setIsProcessing(true); try { - const response = await axios.post('/api/subscription/recurring', { - paymentResponse, - }); - if (response.data.success) { - showToast('success', 'Recurring subscription set up successfully!'); - await update(); - router.push('/dashboard'); - } else { - showToast('error', 'Failed to set up recurring subscription. Please try again.'); - } + await update(); + showToast('success', 'Recurring Subscription Activated', 'Your recurring subscription has been set up successfully.'); } catch (error) { - console.error('Recurring subscription error:', error); - showToast('error', 'An error occurred. Please try again.'); + console.error('Session update error:', error); + showToast('error', 'Session Update Failed', `Error: ${error.message}`); } finally { setIsProcessing(false); } }; const menuItems = [ - { - label: "Renew Subscription", - icon: "pi pi-bolt", - command: () => { - // Add your renew functionality here - }, - }, { label: "Schedule 1:1", icon: "pi pi-calendar", - command: () => { - // Add your schedule functionality here - }, + command: () => setCalendlyVisible(true), + }, + { + label: session?.user?.lightningAddress ? "Update PlebDevs Lightning Address" : "Claim PlebDevs Lightning Address", + icon: "pi pi-bolt", + command: () => setLightningAddressVisible(true), + }, + { + label: session?.user?.nip05 ? "Update PlebDevs Nostr NIP-05" : "Claim PlebDevs Nostr NIP-05", + icon: "pi pi-at", + command: () => setNip05Visible(true), + }, + { + label: "Renew Subscription", + icon: "pi pi-sync", + command: () => setRenewSubscriptionVisible(true), }, { label: "Cancel Subscription", icon: "pi pi-trash", - command: () => { - // Add your cancel functionality here - }, + command: () => setCancelSubscriptionVisible(true), }, ]; @@ -125,49 +141,55 @@ const Subscribe = () => { return (
- { - windowWidth < 768 && ( -

Subscription Management

- ) - } - {session && session?.user ? ( - - {subscribed && ( -
- -

Thank you for your support 🎉

-

Pay-as-you-go subscription will renew on {subscribedUntil.toLocaleDateString()}

-
- )} - {(!subscribed && !subscriptionExpiredAt) && ( -
- -
- )} - {subscriptionExpiredAt && ( -
- -
- )} -
- ) : ( - -

- The plebdevs subscription is a monthly subscription that unlocks all of the paid content, grants you access to the plebdevs 1:1 calendar for tutoring, support, and mentorship, and gives you an exclusive invite to the pleblab bitcoin hackerspace community. -

- -

- The plebdevs subscription is Lightning only and you can subscribe a month at a time with the pay as you go option or easily setup an auto recurring monthly subscription using Nostr Wallet Connect. -

- -
-

Login to start your subscription

- router.push('/auth/signin')} className='text-[#f8f8ff] w-fit' size="small" rounded icon="pi pi-user" /> + {windowWidth < 768 && ( +

Subscription Management

+ )} +
+ {session && session?.user ? ( + <> + {subscribed && ( +
+ +

Thank you for your support 🎉

+

Pay-as-you-go subscription will renew on {subscribedUntil.toLocaleDateString()}

+
+ )} + {(!subscribed && !subscriptionExpiredAt) && ( +
+ +
+ )} + {subscriptionExpiredAt && ( +
+ +
+ )} + + ) : ( +
+
- + )} +
+ + {!session?.user && ( + <> + +

+ The PlebDevs subscription unlocks all paid content, grants access to our 1:1 calendar for tutoring, support, and mentorship, and grants you your own personal plebdevs.com Lightning Address and Nostr NIP-05 identity. +

+

+ Subscribe monthly with a pay-as-you-go option or set up an auto-recurring subscription using Nostr Wallet Connect. +

+
+ +

Login to start your subscription!

+ router.push('/auth/signin')} className='text-[#f8f8ff] w-fit' rounded icon="pi pi-user" /> +
+ )} - + {isProcessing ? (
@@ -175,59 +197,107 @@ const Subscribe = () => {
) : (
-

Choose your subscription plan:

-
- -

Monthly Subscription

-

Get access to all PlebDevs features / content one month at a time.

- -
- -

Recurring Monthly Subscription

-

Setup auto recurring monthly payments for uninterrupted access.

- -
+
+

Unlock Premium Benefits

+

Subscribe now and elevate your development journey!

+
+
+ + Access ALL current and future PlebDevs content +
+
+ + Personal mentorship & guidance and access to exclusive 1:1 booking calendar +
+
+ + Claim your own personal plebdevs.com Lightning Address +
+
+ Nostr + Claim your own personal plebdevs.com Nostr NIP-05 identity +
+
+ + I WILL MAKE SURE YOU WIN HARD AND LEVEL UP AS A DEV! +
+
+
)} - -
    -
  • Access to exclusive content
  • -
  • Priority support
  • -
  • Early access to new features
  • -
  • Community forums
  • -
-
+ {session?.user && subscribed && ( + <> + +
+ setCalendlyVisible(true)} /> + setNip05Visible(true)} /> + } onClick={() => setLightningAddressVisible(true)} /> +
+ + +
+ setRenewSubscriptionVisible(true)} /> + setCancelSubscriptionVisible(true)} /> +
+
+ + )}

How does the subscription work?

-

Our subscription provides monthly access to all PlebDevs features. You can choose between a one-time payment or a recurring subscription.

+

Think of the subscriptions as a Patreon-type model. You pay a monthly fee and in return you get access to premium features and all of the paid content. You can cancel at any time.

+
+
+

How do I Subscribe? (Pay as you go)

+

The pay as you go subscription is a one-time payment that gives you access to all of the premium features for one month. You will need to manually renew your subscription every month.

+
+
+

How do I Subscribe? (Recurring)

+

The recurring subscription option allows you to submit a Nostr Wallet Connect URI that will be used to automatically send the subscription fee every month. You can cancel at any time.

Can I cancel my subscription?

Yes, you can cancel your subscription at any time. Your access will remain active until the end of the current billing period.

- {/* Add more FAQ items as needed */} +
+

What happens if I don't renew my subscription?

+

If you don't renew your subscription, your access to 1:1 calendar and paid content will be removed. However, you will still have access to your PlebDevs Lightning Address, NIP-05, and any content that you paid for.

+
+ + setCalendlyVisible(false)} + /> + setCancelSubscriptionVisible(false)} + /> + setRenewSubscriptionVisible(false)} + subscribedUntil={subscribedUntil} + /> + setNip05Visible(false)} + /> + setLightningAddressVisible(false)} + />
); };