Subscription plan UI updates, subscription plan in subscription buttons

This commit is contained in:
austinkelsay 2025-01-22 16:59:07 -06:00
parent ddb16c9401
commit 40eacbe722
6 changed files with 95 additions and 44 deletions

View File

@ -18,7 +18,7 @@ const PaymentModal = dynamic(
{ ssr: false } { ssr: false }
); );
const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptionSuccess, setIsProcessing, oneTime = false, recurring = false, layout = "row" }) => { const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptionSuccess, setIsProcessing, oneTime = false, recurring = false, layout = "row", selectedPlan = 'monthly' }) => {
const [invoice, setInvoice] = useState(null); const [invoice, setInvoice] = useState(null);
const [showRecurringOptions, setShowRecurringOptions] = useState(false); const [showRecurringOptions, setShowRecurringOptions] = useState(false);
const [nwcInput, setNwcInput] = useState(''); const [nwcInput, setNwcInput] = useState('');
@ -27,7 +27,7 @@ const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptio
const router = useRouter(); const router = useRouter();
const lnAddress = process.env.NEXT_PUBLIC_LIGHTNING_ADDRESS; const lnAddress = process.env.NEXT_PUBLIC_LIGHTNING_ADDRESS;
const amount = 50000; const amount = selectedPlan === 'yearly' ? 500000 : 50000;
useEffect(() => { useEffect(() => {
initializeBitcoinConnect(); initializeBitcoinConnect();
@ -92,9 +92,9 @@ const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptio
const initNwcOptions = { const initNwcOptions = {
name: "plebdevs.com", name: "plebdevs.com",
requestMethods: ['pay_invoice'], requestMethods: ['pay_invoice'],
maxAmount: 50000, maxAmount: selectedPlan === 'yearly' ? 500000 : 50000,
editable: false, editable: false,
budgetRenewal: 'monthly', budgetRenewal: selectedPlan === 'yearly' ? 'yearly' : 'monthly',
expiresAt: yearFromNow, expiresAt: yearFromNow,
}; };
await newNwc.initNWC(initNwcOptions); await newNwc.initNWC(initNwcOptions);
@ -257,7 +257,10 @@ const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptio
<AlbyButton handleSubmit={handleRecurringSubscription} /> <AlbyButton handleSubmit={handleRecurringSubscription} />
<span className='my-4 text-lg font-bold'>or</span> <span className='my-4 text-lg font-bold'>or</span>
<p className='text-lg font-bold'>Manually enter NWC URL</p> <p className='text-lg font-bold'>Manually enter NWC URL</p>
<span className='text-sm text-gray-500'>*make sure you set a budget of at least 50000 sats and set budget renewal to monthly</span> <span className='text-sm text-gray-500'>
*make sure you set a budget of at least {selectedPlan === 'yearly' ? '500,000' : '50,000'} sats
and set budget renewal to {selectedPlan === 'yearly' ? 'yearly' : 'monthly'}
</span>
<input <input
type="text" type="text"
value={nwcInput} value={nwcInput}

View File

@ -7,7 +7,7 @@ import { useSession } from 'next-auth/react';
import { useToast } from '@/hooks/useToast'; import { useToast } from '@/hooks/useToast';
import axios from 'axios'; import axios from 'axios';
const RenewSubscription = ({ visible, onHide, subscribedUntil }) => { const RenewSubscription = ({ visible, onHide, subscribedUntil, selectedPlan }) => {
const [isProcessing, setIsProcessing] = useState(false); const [isProcessing, setIsProcessing] = useState(false);
const { data: session, update } = useSession(); const { data: session, update } = useSession();
const { showToast } = useToast(); const { showToast } = useToast();
@ -70,6 +70,7 @@ const RenewSubscription = ({ visible, onHide, subscribedUntil }) => {
onError={handleSubscriptionError} onError={handleSubscriptionError}
setIsProcessing={setIsProcessing} setIsProcessing={setIsProcessing}
layout="col" layout="col"
selectedPlan={selectedPlan}
/> />
</Card> </Card>
)} )}

View File

@ -235,9 +235,9 @@ const SubscribeModal = ({ user }) => {
<span className="text-center font-bold">I WILL MAKE SURE YOU WIN HARD AND LEVEL UP AS A DEV!</span> <span className="text-center font-bold">I WILL MAKE SURE YOU WIN HARD AND LEVEL UP AS A DEV!</span>
</div> </div>
<div className="flex justify-center gap-4 mb-4"> <div className="flex justify-center gap-8 mb-4">
<div <div
className={`p-4 border rounded-lg cursor-pointer transition-all duration-200 hover:border-blue-400 className={`p-4 px-12 border rounded-lg cursor-pointer transition-all duration-200 hover:border-blue-400
${selectedPlan === 'monthly' ? 'border-blue-400 bg-blue-900/20' : 'border-gray-600'}`} ${selectedPlan === 'monthly' ? 'border-blue-400 bg-blue-900/20' : 'border-gray-600'}`}
onClick={() => setSelectedPlan('monthly')} onClick={() => setSelectedPlan('monthly')}
> >
@ -252,7 +252,7 @@ const SubscribeModal = ({ user }) => {
</div> </div>
<div <div
className={`p-4 border rounded-lg cursor-pointer transition-all duration-200 hover:border-blue-400 className={`p-4 px-12 border rounded-lg cursor-pointer transition-all duration-200 hover:border-blue-400
${selectedPlan === 'yearly' ? 'border-blue-400 bg-blue-900/20' : 'border-gray-600'}`} ${selectedPlan === 'yearly' ? 'border-blue-400 bg-blue-900/20' : 'border-gray-600'}`}
onClick={() => setSelectedPlan('yearly')} onClick={() => setSelectedPlan('yearly')}
> >
@ -272,6 +272,7 @@ const SubscribeModal = ({ user }) => {
onRecurringSubscriptionSuccess={handleRecurringSubscriptionSuccess} onRecurringSubscriptionSuccess={handleRecurringSubscriptionSuccess}
onError={handleSubscriptionError} onError={handleSubscriptionError}
setIsProcessing={setIsProcessing} setIsProcessing={setIsProcessing}
selectedPlan={selectedPlan}
/> />
</Card> </Card>
)} )}
@ -291,6 +292,7 @@ const SubscribeModal = ({ user }) => {
visible={renewSubscriptionVisible} visible={renewSubscriptionVisible}
onHide={() => setRenewSubscriptionVisible(false)} onHide={() => setRenewSubscriptionVisible(false)}
subscribedUntil={subscribedUntil} subscribedUntil={subscribedUntil}
selectedPlan={selectedPlan}
/> />
<Nip05Form <Nip05Form
visible={nip05Visible} visible={nip05Visible}

View File

@ -21,9 +21,7 @@ import RenewSubscription from '@/components/profile/subscription/RenewSubscripti
const UserSubscription = () => { const UserSubscription = () => {
const { data: session, update } = useSession(); const { data: session, update } = useSession();
const { showToast } = useToast(); const { showToast } = useToast();
const router = useRouter();
const windowWidth = useWindowWidth(); const windowWidth = useWindowWidth();
const menu = useRef(null);
const [user, setUser] = useState(null); const [user, setUser] = useState(null);
const [isProcessing, setIsProcessing] = useState(false); const [isProcessing, setIsProcessing] = useState(false);
const [subscribed, setSubscribed] = useState(false); const [subscribed, setSubscribed] = useState(false);
@ -34,6 +32,7 @@ const UserSubscription = () => {
const [nip05Visible, setNip05Visible] = useState(false); const [nip05Visible, setNip05Visible] = useState(false);
const [cancelSubscriptionVisible, setCancelSubscriptionVisible] = useState(false); const [cancelSubscriptionVisible, setCancelSubscriptionVisible] = useState(false);
const [renewSubscriptionVisible, setRenewSubscriptionVisible] = useState(false); const [renewSubscriptionVisible, setRenewSubscriptionVisible] = useState(false);
const [selectedPlan, setSelectedPlan] = useState('monthly');
useEffect(() => { useEffect(() => {
if (session && session?.user) { if (session && session?.user) {
@ -109,9 +108,10 @@ const UserSubscription = () => {
</div> </div>
{/* Right Column - 78% */} {/* Right Column - 78% */}
<div className="w-[78%] flex flex-col justify-center mx-auto max-lap:w-full"> <div className="w-[78%] flex flex-col justify-center mx-auto max-lap:w-full max-lap:mt-4">
<div className="border border-gray-600 rounded-lg mb-4">
{!subscribed && ( {!subscribed && (
<Card title="Subscribe to PlebDevs" className="mb-4"> <Card title="Subscribe to PlebDevs">
{isProcessing ? ( {isProcessing ? (
<div className="w-full flex flex-col mx-auto justify-center items-center mt-4"> <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> <div className='w-full h-full flex items-center justify-center'><ProgressSpinner /></div>
@ -145,17 +145,53 @@ const UserSubscription = () => {
<span>I WILL MAKE SURE YOU WIN HARD AND LEVEL UP AS A DEV!</span> <span>I WILL MAKE SURE YOU WIN HARD AND LEVEL UP AS A DEV!</span>
</div> </div>
</div> </div>
{/* Add new subscription option containers */}
<div className="flex justify-start gap-8 mb-4">
<div
className={`p-4 px-12 border rounded-lg cursor-pointer transition-all duration-200 hover:border-blue-400
${selectedPlan === 'monthly' ? 'border-blue-400 bg-blue-900/20' : 'border-gray-600'}`}
onClick={() => setSelectedPlan('monthly')}
>
<div className="flex items-center gap-2 mb-2">
<div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center
${selectedPlan === 'monthly' ? 'border-blue-400' : 'border-gray-400'}`}>
{selectedPlan === 'monthly' && <div className="w-2 h-2 rounded-full bg-blue-400"></div>}
</div>
<span className="font-semibold">Monthly</span>
</div>
<div className="text-lg font-bold">50,000 sats</div>
</div>
<div
className={`p-4 px-12 border rounded-lg cursor-pointer transition-all duration-200 hover:border-blue-400
${selectedPlan === 'yearly' ? 'border-blue-400 bg-blue-900/20' : 'border-gray-600'}`}
onClick={() => setSelectedPlan('yearly')}
>
<div className="flex items-center gap-2 mb-2">
<div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center
${selectedPlan === 'yearly' ? 'border-blue-400' : 'border-gray-400'}`}>
{selectedPlan === 'yearly' && <div className="w-2 h-2 rounded-full bg-blue-400"></div>}
</div>
<span className="font-semibold">Yearly</span>
</div>
<div className="text-lg font-bold">500,000 sats</div>
</div>
</div>
<SubscriptionPaymentButtons <SubscriptionPaymentButtons
onSuccess={handleSubscriptionSuccess} onSuccess={handleSubscriptionSuccess}
onRecurringSubscriptionSuccess={handleRecurringSubscriptionSuccess} onRecurringSubscriptionSuccess={handleRecurringSubscriptionSuccess}
onError={handleSubscriptionError} onError={handleSubscriptionError}
setIsProcessing={setIsProcessing} setIsProcessing={setIsProcessing}
layout={windowWidth < 768 ? "col" : "row"} layout={windowWidth < 768 ? "col" : "row"}
selectedPlan={selectedPlan}
/> />
</div> </div>
)} )}
</Card> </Card>
)} )}
</div>
{subscribed && ( {subscribed && (
<> <>
@ -184,7 +220,7 @@ const UserSubscription = () => {
</> </>
)} )}
<Card title="Frequently Asked Questions" className="mb-6"> <Card title="Frequently Asked Questions" className="mb-6 border border-gray-600 rounded-lg">
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
<div> <div>
<h3 className="text-lg font-semibold">How does the subscription work?</h3> <h3 className="text-lg font-semibold">How does the subscription work?</h3>
@ -227,6 +263,7 @@ const UserSubscription = () => {
visible={renewSubscriptionVisible} visible={renewSubscriptionVisible}
onHide={() => setRenewSubscriptionVisible(false)} onHide={() => setRenewSubscriptionVisible(false)}
subscribedUntil={subscribedUntil} subscribedUntil={subscribedUntil}
selectedPlan={selectedPlan}
/> />
<Nip05Form <Nip05Form
visible={nip05Visible} visible={nip05Visible}

View File

@ -11,7 +11,7 @@ const appConfig = {
"wss://purplerelay.com/", "wss://purplerelay.com/",
"wss://relay.devs.tools/" "wss://relay.devs.tools/"
], ],
authorPubkeys: ["f33c8a9617cb15f705fc70cd461cfd6eaf22f9e24c33eabad981648e5ec6f741", "c67cd3e1a83daa56cff16f635db2fdb9ed9619300298d4701a58e68e84098345"], authorPubkeys: ["f33c8a9617cb15f705fc70cd461cfd6eaf22f9e24c33eabad981648e5ec6f741", "c67cd3e1a83daa56cff16f635db2fdb9ed9619300298d4701a58e68e84098345", "468f729dd409053dac5e7470622c3996aad88db6ed1de9165cb1921b5ab4fd5e"],
customLightningAddresses: [ customLightningAddresses: [
{ {
// todo remove need for lowercase // todo remove need for lowercase

View File

@ -21,11 +21,11 @@ const Subscribe = () => {
const { data: session, update } = useSession(); const { data: session, update } = useSession();
const { showToast } = useToast(); const { showToast } = useToast();
const router = useRouter(); const router = useRouter();
const menu = useRef(null);
const windowWidth = useWindowWidth(); const windowWidth = useWindowWidth();
const [user, setUser] = useState(null); const [user, setUser] = useState(null);
const [isProcessing, setIsProcessing] = useState(false); const [isProcessing, setIsProcessing] = useState(false);
const [subscribed, setSubscribed] = useState(false); const [subscribed, setSubscribed] = useState(false);
const [selectedPlan, setSelectedPlan] = useState('monthly');
const [subscribedUntil, setSubscribedUntil] = useState(null); const [subscribedUntil, setSubscribedUntil] = useState(null);
const [subscriptionExpiredAt, setSubscriptionExpiredAt] = useState(null); const [subscriptionExpiredAt, setSubscriptionExpiredAt] = useState(null);
const [calendlyVisible, setCalendlyVisible] = useState(false); const [calendlyVisible, setCalendlyVisible] = useState(false);
@ -59,6 +59,7 @@ const Subscribe = () => {
const apiResponse = await axios.put('/api/users/subscription', { const apiResponse = await axios.put('/api/users/subscription', {
userId: session.user.id, userId: session.user.id,
isSubscribed: true, isSubscribed: true,
selectedPlan: selectedPlan,
}); });
if (apiResponse.data) { if (apiResponse.data) {
await update(); await update();
@ -93,34 +94,6 @@ const Subscribe = () => {
} }
}; };
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),
},
];
return ( return (
<div className="p-4"> <div className="p-4">
{windowWidth < 768 && ( {windowWidth < 768 && (
@ -181,11 +154,45 @@ const Subscribe = () => {
<span>I WILL MAKE SURE YOU WIN HARD AND LEVEL UP AS A DEV!</span> <span>I WILL MAKE SURE YOU WIN HARD AND LEVEL UP AS A DEV!</span>
</div> </div>
</div> </div>
<div className="flex justify-start gap-8 mb-4">
<div
className={`p-4 px-12 border rounded-lg cursor-pointer transition-all duration-200 hover:border-blue-400
${selectedPlan === 'monthly' ? 'border-blue-400 bg-blue-900/20' : 'border-gray-600'}`}
onClick={() => setSelectedPlan('monthly')}
>
<div className="flex items-center gap-2 mb-2">
<div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center
${selectedPlan === 'monthly' ? 'border-blue-400' : 'border-gray-400'}`}>
{selectedPlan === 'monthly' && <div className="w-2 h-2 rounded-full bg-blue-400"></div>}
</div>
<span className="font-semibold">Monthly</span>
</div>
<div className="text-lg font-bold">50,000 sats</div>
</div>
<div
className={`p-4 px-12 border rounded-lg cursor-pointer transition-all duration-200 hover:border-blue-400
${selectedPlan === 'yearly' ? 'border-blue-400 bg-blue-900/20' : 'border-gray-600'}`}
onClick={() => setSelectedPlan('yearly')}
>
<div className="flex items-center gap-2 mb-2">
<div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center
${selectedPlan === 'yearly' ? 'border-blue-400' : 'border-gray-400'}`}>
{selectedPlan === 'yearly' && <div className="w-2 h-2 rounded-full bg-blue-400"></div>}
</div>
<span className="font-semibold">Yearly</span>
</div>
<div className="text-lg font-bold">500,000 sats</div>
</div>
</div>
<SubscriptionPaymentButtons <SubscriptionPaymentButtons
onSuccess={handleSubscriptionSuccess} onSuccess={handleSubscriptionSuccess}
onRecurringSubscriptionSuccess={handleRecurringSubscriptionSuccess} onRecurringSubscriptionSuccess={handleRecurringSubscriptionSuccess}
onError={handleSubscriptionError} onError={handleSubscriptionError}
setIsProcessing={setIsProcessing} setIsProcessing={setIsProcessing}
selectedPlan={selectedPlan}
layout={windowWidth < 768 ? "col" : "row"} layout={windowWidth < 768 ? "col" : "row"}
/> />
</div> </div>
@ -262,6 +269,7 @@ const Subscribe = () => {
visible={renewSubscriptionVisible} visible={renewSubscriptionVisible}
onHide={() => setRenewSubscriptionVisible(false)} onHide={() => setRenewSubscriptionVisible(false)}
subscribedUntil={subscribedUntil} subscribedUntil={subscribedUntil}
selectedPlan={selectedPlan}
/> />
<Nip05Form <Nip05Form
visible={nip05Visible} visible={nip05Visible}