mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-04-19 19:01:19 +00:00
Subscription modal now has functioning buttons, just need to add custom nip05 and lnaddress forms
This commit is contained in:
parent
023e9d5525
commit
a5a35f90fc
42
src/components/profile/subscription/CalendlyEmbed.js
Normal file
42
src/components/profile/subscription/CalendlyEmbed.js
Normal file
@ -0,0 +1,42 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Button } from 'primereact/button';
|
||||
|
||||
const CalendlyEmbed = ({ visible, onHide }) => {
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://assets.calendly.com/assets/external/widget.js';
|
||||
script.async = true;
|
||||
document.body.appendChild(script);
|
||||
|
||||
return () => {
|
||||
document.body.removeChild(script);
|
||||
};
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
const dialogFooter = (
|
||||
<div>
|
||||
<Button label="Close" icon="pi pi-times" onClick={onHide} className="p-button-text" />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
header="Schedule a Meeting"
|
||||
visible={visible}
|
||||
style={{ width: '50vw' }}
|
||||
footer={dialogFooter}
|
||||
onHide={onHide}
|
||||
>
|
||||
<div
|
||||
className="calendly-inline-widget"
|
||||
data-url="https://calendly.com/plebdevs/30min?hide_event_type_details=1&hide_gdpr_banner=1"
|
||||
style={{ minWidth: '320px', height: '700px' }}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default CalendlyEmbed;
|
43
src/components/profile/subscription/CancelSubscription.js
Normal file
43
src/components/profile/subscription/CancelSubscription.js
Normal file
@ -0,0 +1,43 @@
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import {Dialog} from 'primereact/dialog';
|
||||
import axios from 'axios';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { ProgressSpinner } from 'primereact/progressspinner';
|
||||
import GenericButton from '@/components/buttons/GenericButton';
|
||||
|
||||
const CancelSubscription = ({visible, onHide}) => {
|
||||
const { data: session, update } = useSession();
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const { showToast } = useToast();
|
||||
const handleCancelSubscription = async () => {
|
||||
setIsProcessing(true);
|
||||
try {
|
||||
const response = await axios.put('/api/users/subscription', {
|
||||
userId: session.user.id,
|
||||
isSubscribed: false,
|
||||
nwc: null
|
||||
});
|
||||
if (response.status === 200) {
|
||||
showToast('success', 'Subscription canceled', 'Subscription canceled successfully');
|
||||
update();
|
||||
onHide();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error canceling subscription:', error);
|
||||
showToast('error', 'Error canceling subscription', error.message);
|
||||
setIsProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog header="Cancel Subscription" visible={visible} onHide={onHide}>
|
||||
<p>Are you sure you want to cancel your subscription?</p>
|
||||
<div className="flex flex-row justify-center mt-6">
|
||||
{isProcessing ? <ProgressSpinner /> : <GenericButton severity="danger" outlined className="mx-auto" label="Cancel Subscription" onClick={handleCancelSubscription} />}
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default CancelSubscription;
|
79
src/components/profile/subscription/RenewSubscription.js
Normal file
79
src/components/profile/subscription/RenewSubscription.js
Normal file
@ -0,0 +1,79 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Card } from 'primereact/card';
|
||||
import { ProgressSpinner } from 'primereact/progressspinner';
|
||||
import SubscriptionPaymentButtons from '@/components/bitcoinConnect/SubscriptionPaymentButton';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import axios from 'axios';
|
||||
|
||||
const RenewSubscription = ({ visible, onHide, subscribedUntil }) => {
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const { data: session, update } = useSession();
|
||||
const { showToast } = useToast();
|
||||
|
||||
const handleSubscriptionSuccess = async (response) => {
|
||||
setIsProcessing(true);
|
||||
try {
|
||||
const apiResponse = await axios.put('/api/users/subscription', {
|
||||
userId: session.user.id,
|
||||
isSubscribed: true,
|
||||
});
|
||||
if (apiResponse.data) {
|
||||
await update();
|
||||
showToast('success', 'Subscription Renewed', 'Your subscription has been renewed successfully.');
|
||||
onHide();
|
||||
} else {
|
||||
throw new Error('Failed to update subscription status');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Subscription renewal error:', error);
|
||||
showToast('error', 'Subscription Renewal Failed', `Error: ${error.message}`);
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubscriptionError = (error) => {
|
||||
console.error('Subscription error:', error);
|
||||
showToast('error', 'Subscription Renewal Failed', `An error occurred: ${error.message}`);
|
||||
setIsProcessing(false);
|
||||
};
|
||||
|
||||
const formatDate = (date) => {
|
||||
if (!date) return 'N/A';
|
||||
return new Date(date).toLocaleDateString();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
header="Renew Your PlebDevs Subscription"
|
||||
visible={visible}
|
||||
onHide={onHide}
|
||||
className="p-fluid pb-0 w-fit"
|
||||
>
|
||||
{isProcessing ? (
|
||||
<div className="w-full flex flex-col mx-auto justify-center items-center mt-4">
|
||||
<div className='w-full h-full flex items-center justify-center'><ProgressSpinner /></div>
|
||||
<span className="ml-2">Processing renewal...</span>
|
||||
</div>
|
||||
) : (
|
||||
<Card className="shadow-lg">
|
||||
<div className="text-center mb-4">
|
||||
<h2 className="text-2xl font-bold text-primary">Renew Your Subscription</h2>
|
||||
<p className="text-gray-400">Your current subscription is valid until {formatDate(subscribedUntil)}</p>
|
||||
<p className="text-gray-400">Renew now to extend your access to premium benefits!</p>
|
||||
</div>
|
||||
<SubscriptionPaymentButtons
|
||||
onSuccess={handleSubscriptionSuccess}
|
||||
onRecurringSubscriptionSuccess={handleSubscriptionSuccess}
|
||||
onError={handleSubscriptionError}
|
||||
setIsProcessing={setIsProcessing}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default RenewSubscription;
|
@ -11,6 +11,11 @@ import { Badge } from 'primereact/badge';
|
||||
import GenericButton from '@/components/buttons/GenericButton';
|
||||
import { Menu } from "primereact/menu";
|
||||
import { Message } from "primereact/message";
|
||||
import CancelSubscription from '@/components/profile/subscription/CancelSubscription';
|
||||
import CalendlyEmbed from '@/components/profile/subscription/CalendlyEmbed';
|
||||
import NostrIcon from '../../../../public/images/nostr.png';
|
||||
import Image from 'next/image';
|
||||
import RenewSubscription from '@/components/profile/subscription/RenewSubscription';
|
||||
|
||||
const SubscribeModal = ({ user }) => {
|
||||
const { data: session, update } = useSession();
|
||||
@ -21,7 +26,10 @@ const SubscribeModal = ({ user }) => {
|
||||
const [subscribed, setSubscribed] = useState(false);
|
||||
const [subscribedUntil, setSubscribedUntil] = useState(null);
|
||||
const [subscriptionExpiredAt, setSubscriptionExpiredAt] = useState(null);
|
||||
const [calendlyVisible, setCalendlyVisible] = useState(false);
|
||||
const menu = useRef(null);
|
||||
const [cancelSubscriptionVisible, setCancelSubscriptionVisible] = useState(false);
|
||||
const [renewSubscriptionVisible, setRenewSubscriptionVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (user && user.role) {
|
||||
@ -88,21 +96,21 @@ const SubscribeModal = ({ user }) => {
|
||||
label: "Renew Subscription",
|
||||
icon: "pi pi-bolt",
|
||||
command: () => {
|
||||
// Add your renew functionality here
|
||||
setRenewSubscriptionVisible(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Schedule 1:1",
|
||||
icon: "pi pi-calendar",
|
||||
command: () => {
|
||||
// Add your schedule functionality here
|
||||
setCalendlyVisible(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Cancel Subscription",
|
||||
icon: "pi pi-trash",
|
||||
command: () => {
|
||||
// Add your cancel functionality here
|
||||
setCancelSubscriptionVisible(true);
|
||||
},
|
||||
},
|
||||
];
|
||||
@ -110,21 +118,23 @@ const SubscribeModal = ({ user }) => {
|
||||
const subscriptionCardTitle = (
|
||||
<div className="w-full flex flex-row justify-between items-center">
|
||||
<span className="text-xl text-900 font-bold text-white">Plebdevs Subscription</span>
|
||||
<i
|
||||
className="pi pi-ellipsis-h text-2xl cursor-pointer hover:opacity-75"
|
||||
{subscribed && (
|
||||
<i
|
||||
className="pi pi-ellipsis-h text-2xl cursor-pointer hover:opacity-75"
|
||||
onClick={(e) => menu.current.toggle(e)}
|
||||
></i>
|
||||
></i>
|
||||
)}
|
||||
<Menu model={menuItems} popup ref={menu} />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card title={subscriptionCardTitle} className="w-fit m-8 mx-auto">
|
||||
<Card title={subscriptionCardTitle} className="w-fit m-4 mx-auto">
|
||||
{subscribed && (
|
||||
<div className="flex flex-col">
|
||||
<Message className="w-fit" severity="success" text="Subscribed!" />
|
||||
<p className="mt-8">Thank you for your support 🎉</p>
|
||||
<p className="mt-4">Thank you for your support 🎉</p>
|
||||
<p className="text-sm text-gray-400">Pay-as-you-go subscription will renew on {subscribedUntil.toLocaleDateString()}</p>
|
||||
</div>
|
||||
)}
|
||||
@ -133,7 +143,7 @@ const SubscribeModal = ({ user }) => {
|
||||
<Message className="w-fit" severity="info" text="You currently have no active subscription" />
|
||||
<GenericButton
|
||||
label="Subscribe"
|
||||
className="w-auto mt-8 text-[#f8f8ff]"
|
||||
className="w-auto mt-4 text-[#f8f8ff]"
|
||||
onClick={() => setVisible(true)}
|
||||
/>
|
||||
</div>
|
||||
@ -143,7 +153,7 @@ const SubscribeModal = ({ user }) => {
|
||||
<Message className="w-fit" severity="warn" text={`Your subscription expired on ${subscriptionExpiredAt.toLocaleDateString()}`} />
|
||||
<GenericButton
|
||||
label="Subscribe"
|
||||
className="w-auto mt-8 text-[#f8f8ff]"
|
||||
className="w-auto mt-4 text-[#f8f8ff]"
|
||||
onClick={() => setVisible(true)}
|
||||
/>
|
||||
</div>
|
||||
@ -166,26 +176,26 @@ const SubscribeModal = ({ user }) => {
|
||||
<h2 className="text-2xl font-bold text-primary">Unlock Premium Benefits</h2>
|
||||
<p className="text-gray-400">Subscribe now and elevate your development journey!</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
||||
<div className="flex flex-col gap-4 mb-4 w-[60%] mx-auto">
|
||||
<div className="flex items-center">
|
||||
<i className="pi pi-book text-2xl text-primary mr-2"></i>
|
||||
<span>Access ALL current and future content</span>
|
||||
<i className="pi pi-book text-2xl text-primary mr-2 text-blue-400"></i>
|
||||
<span>Access ALL current and future PlebDevs content</span>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<i className="pi pi-users text-2xl text-primary mr-2"></i>
|
||||
<span>Join PlebLab Bitcoin Hackerspace Slack</span>
|
||||
<i className="pi pi-calendar text-2xl text-primary mr-2 text-red-400"></i>
|
||||
<span>Personal mentorship & guidance and access to exclusive 1:1 booking calendar</span>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<i className="pi pi-calendar text-2xl text-primary mr-2"></i>
|
||||
<span>Exclusive 1:1 booking calendar</span>
|
||||
<i className="pi pi-bolt text-2xl text-primary mr-2 text-yellow-500"></i>
|
||||
<span>Claim your own personal plebdevs.com Lightning Address</span>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<i className="pi pi-star text-2xl text-primary mr-2"></i>
|
||||
<span>Personal mentorship & guidance</span>
|
||||
<Image src={NostrIcon} alt="Nostr" width={26 } height={26} className='mr-2' />
|
||||
<span>Claim your own personal plebdevs.com Nostr NIP-05 identity</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center mb-4 flex flex-row justify-center">
|
||||
<Badge value="BONUS" severity="success" className="mr-2"></Badge>
|
||||
<Badge value="BONUS" severity="success" className="mr-2 text-[#f8f8ff] font-bold"></Badge>
|
||||
<span className="text-center font-bold">I WILL MAKE SURE YOU WIN HARD AND LEVEL UP AS A DEV!</span>
|
||||
</div>
|
||||
<SubscriptionPaymentButtons
|
||||
@ -197,6 +207,21 @@ const SubscribeModal = ({ user }) => {
|
||||
</Card>
|
||||
)}
|
||||
</Dialog>
|
||||
{calendlyVisible && (
|
||||
<CalendlyEmbed
|
||||
visible={calendlyVisible}
|
||||
onHide={() => setCalendlyVisible(false)}
|
||||
/>
|
||||
)}
|
||||
<CancelSubscription
|
||||
visible={cancelSubscriptionVisible}
|
||||
onHide={() => setCancelSubscriptionVisible(false)}
|
||||
/>
|
||||
<RenewSubscription
|
||||
visible={renewSubscriptionVisible}
|
||||
onHide={() => setRenewSubscriptionVisible(false)}
|
||||
subscribedUntil={subscribedUntil}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user