mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-05-16 03:05:51 +00:00
Update subscribe and about page, a bunch of styling and mobile styling fixes
This commit is contained in:
parent
bcf6c9bf9a
commit
ace772f32c
@ -34,23 +34,6 @@ const UserProfile = () => {
|
|||||||
}
|
}
|
||||||
}, [session]);
|
}, [session]);
|
||||||
|
|
||||||
const menuItems = [
|
|
||||||
{
|
|
||||||
label: "Edit",
|
|
||||||
icon: "pi pi-pencil",
|
|
||||||
command: () => {
|
|
||||||
showToast("warn", "Alert", "This feature is not yet implemented");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Delete",
|
|
||||||
icon: "pi pi-trash",
|
|
||||||
command: () => {
|
|
||||||
showToast("warn", "Alert", "This feature is not yet implemented");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const header = (
|
const header = (
|
||||||
<div className="flex flex-wrap align-items-center justify-content-between gap-2">
|
<div className="flex flex-wrap align-items-center justify-content-between gap-2">
|
||||||
<span className="text-xl text-900 font-bold text-[#f8f8ff]">Progress</span>
|
<span className="text-xl text-900 font-bold text-[#f8f8ff]">Progress</span>
|
||||||
@ -80,11 +63,6 @@ const UserProfile = () => {
|
|||||||
height={100}
|
height={100}
|
||||||
className="rounded-full my-4"
|
className="rounded-full my-4"
|
||||||
/>
|
/>
|
||||||
<i
|
|
||||||
className="pi pi-ellipsis-h absolute right-24 text-2xl my-4 cursor-pointer hover:opacity-75"
|
|
||||||
onClick={(e) => menu.current.toggle(e)}
|
|
||||||
></i>
|
|
||||||
<Menu model={menuItems} popup ref={menu} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-center text-2xl my-2">
|
<h1 className="text-center text-2xl my-2">
|
||||||
|
@ -191,7 +191,7 @@ const UserSettings = () => {
|
|||||||
<span className="font-bold">NIP-05:</span> {user.nip05.name}@plebdevs.com
|
<span className="font-bold">NIP-05:</span> {user.nip05.name}@plebdevs.com
|
||||||
</h3>
|
</h3>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-col w-1/2 mx-auto justify-between items-center">
|
<div className="flex flex-col w-1/2 mx-auto justify-between items-center max-mob:w-full max-tab:w-full">
|
||||||
<h2 className="text-xl my-2 max-mob:text-base max-tab:text-base">Connect Your Lightning Wallet</h2>
|
<h2 className="text-xl my-2 max-mob:text-base max-tab:text-base">Connect Your Lightning Wallet</h2>
|
||||||
<BitcoinConnectButton />
|
<BitcoinConnectButton />
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,7 +6,7 @@ import { useSession } from 'next-auth/react';
|
|||||||
const allTasks = [
|
const allTasks = [
|
||||||
{ status: 'Create Account', completed: true, tier: 'Pleb', courseId: null },
|
{ status: 'Create Account', completed: true, tier: 'Pleb', courseId: null },
|
||||||
{
|
{
|
||||||
status: 'PlebDevs Starter (Coming Soon)',
|
status: 'PlebDevs Starter',
|
||||||
completed: false,
|
completed: false,
|
||||||
tier: 'New Dev',
|
tier: 'New Dev',
|
||||||
courseId: null,
|
courseId: null,
|
||||||
@ -16,8 +16,26 @@ const allTasks = [
|
|||||||
{ status: 'Push Commit', completed: false }
|
{ status: 'Push Commit', completed: false }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ status: 'PlebDevs Course 1', completed: false, tier: 'Junior Dev', courseId: 'd20e2e9b-5123-4a91-b27f-d75ea1d5811e' },
|
{
|
||||||
{ status: 'PlebDevs Course 2', completed: false, tier: 'Plebdev', courseId: 'aa3b1641-ad2b-4ef4-9f0f-38951ae307b7' },
|
status: 'PlebDevs Course 1',
|
||||||
|
completed: false,
|
||||||
|
tier: 'Junior Dev',
|
||||||
|
courseId: 'd20e2e9b-5123-4a91-b27f-d75ea1d5811e',
|
||||||
|
subTasks: [
|
||||||
|
{ status: 'Complete the course', completed: false },
|
||||||
|
{ status: 'Submit Link to completed project', completed: false },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 'PlebDevs Course 2',
|
||||||
|
completed: false,
|
||||||
|
tier: 'Plebdev',
|
||||||
|
courseId: 'aa3b1641-ad2b-4ef4-9f0f-38951ae307b7',
|
||||||
|
subTasks: [
|
||||||
|
{status: 'Complete the course', completed: false},
|
||||||
|
{ status: 'Submit Link to completed project', completed: false },
|
||||||
|
]
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const UserProgress = () => {
|
const UserProgress = () => {
|
||||||
@ -74,7 +92,7 @@ const UserProgress = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-gray-800 rounded-3xl p-6 w-[500px] mx-auto my-8">
|
<div className="bg-gray-800 rounded-3xl p-6 w-[500px] max-mob:w-full max-tab:w-full mx-auto my-8">
|
||||||
<h1 className="text-3xl font-bold text-white mb-2">Dev Journey (Coming Soon)</h1>
|
<h1 className="text-3xl font-bold text-white mb-2">Dev Journey (Coming Soon)</h1>
|
||||||
<p className="text-gray-400 mb-4">Track your progress from Pleb to Plebdev</p>
|
<p className="text-gray-400 mb-4">Track your progress from Pleb to Plebdev</p>
|
||||||
|
|
||||||
@ -122,7 +140,8 @@ const UserProgress = () => {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ul className="space-y-2 mt-2 ml-9">
|
<ul className="space-y-2 mt-2 ml-9 max-mob:mt-0 max-tab:mt-0">
|
||||||
|
<span className="text-gray-400 text-xs">(Coming Soon)</span>
|
||||||
{task.subTasks.map((subTask, subIndex) => (
|
{task.subTasks.map((subTask, subIndex) => (
|
||||||
<li key={subIndex} className="flex items-center">
|
<li key={subIndex} className="flex items-center">
|
||||||
{subTask.completed ? (
|
{subTask.completed ? (
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Dialog } from 'primereact/dialog';
|
import { Dialog } from 'primereact/dialog';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
|
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||||
|
|
||||||
const CalendlyEmbed = ({ visible, onHide }) => {
|
const CalendlyEmbed = ({ visible, onHide }) => {
|
||||||
|
const windowWidth = useWindowWidth();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
@ -26,7 +28,7 @@ const CalendlyEmbed = ({ visible, onHide }) => {
|
|||||||
<Dialog
|
<Dialog
|
||||||
header="Schedule a Meeting"
|
header="Schedule a Meeting"
|
||||||
visible={visible}
|
visible={visible}
|
||||||
style={{ width: '50vw' }}
|
style={{ width: windowWidth < 768 ? '100vw' : '50vw' }}
|
||||||
footer={dialogFooter}
|
footer={dialogFooter}
|
||||||
onHide={onHide}
|
onHide={onHide}
|
||||||
>
|
>
|
||||||
|
@ -7,6 +7,7 @@ import { InputText } from 'primereact/inputtext';
|
|||||||
import { ProgressSpinner } from 'primereact/progressspinner';
|
import { ProgressSpinner } from 'primereact/progressspinner';
|
||||||
import { InputNumber } from 'primereact/inputnumber';
|
import { InputNumber } from 'primereact/inputnumber';
|
||||||
import GenericButton from '@/components/buttons/GenericButton';
|
import GenericButton from '@/components/buttons/GenericButton';
|
||||||
|
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||||
|
|
||||||
const LightningAddressForm = ({ visible, onHide }) => {
|
const LightningAddressForm = ({ visible, onHide }) => {
|
||||||
const [isProcessing, setIsProcessing] = useState(false);
|
const [isProcessing, setIsProcessing] = useState(false);
|
||||||
@ -20,6 +21,7 @@ const LightningAddressForm = ({ visible, onHide }) => {
|
|||||||
const [lndHost, setLndHost] = useState('');
|
const [lndHost, setLndHost] = useState('');
|
||||||
const [lndPort, setLndPort] = useState('8080');
|
const [lndPort, setLndPort] = useState('8080');
|
||||||
|
|
||||||
|
const windowWidth = useWindowWidth();
|
||||||
const { data: session, update } = useSession();
|
const { data: session, update } = useSession();
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
|
|
||||||
@ -86,7 +88,7 @@ const LightningAddressForm = ({ visible, onHide }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog header="Lightning Address" visible={visible} onHide={onHide}>
|
<Dialog header="Lightning Address" visible={visible} onHide={onHide} style={{ width: windowWidth < 768 ? '100vw' : '60vw' }}>
|
||||||
{existingLightningAddress ? (
|
{existingLightningAddress ? (
|
||||||
<p>Update your Lightning Address details</p>
|
<p>Update your Lightning Address details</p>
|
||||||
) : (
|
) : (
|
||||||
|
@ -6,6 +6,7 @@ import { useToast } from '@/hooks/useToast';
|
|||||||
import { InputText } from 'primereact/inputtext';
|
import { InputText } from 'primereact/inputtext';
|
||||||
import { ProgressSpinner } from 'primereact/progressspinner';
|
import { ProgressSpinner } from 'primereact/progressspinner';
|
||||||
import GenericButton from '@/components/buttons/GenericButton';
|
import GenericButton from '@/components/buttons/GenericButton';
|
||||||
|
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||||
|
|
||||||
const Nip05Form = ({ visible, onHide }) => {
|
const Nip05Form = ({ visible, onHide }) => {
|
||||||
const [isProcessing, setIsProcessing] = useState(false);
|
const [isProcessing, setIsProcessing] = useState(false);
|
||||||
@ -13,6 +14,7 @@ const Nip05Form = ({ visible, onHide }) => {
|
|||||||
const [pubkey, setPubkey] = useState('');
|
const [pubkey, setPubkey] = useState('');
|
||||||
const [name, setName] = useState('');
|
const [name, setName] = useState('');
|
||||||
|
|
||||||
|
const windowWidth = useWindowWidth();
|
||||||
const { data: session, update } = useSession();
|
const { data: session, update } = useSession();
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
|
|
||||||
@ -74,7 +76,7 @@ const Nip05Form = ({ visible, onHide }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog header="NIP-05" visible={visible} onHide={onHide}>
|
<Dialog header="NIP-05" visible={visible} onHide={onHide} style={{ width: windowWidth < 768 ? '100vw' : '60vw' }}>
|
||||||
{existingNip05 ? (
|
{existingNip05 ? (
|
||||||
<p>Update your Pubkey and Name</p>
|
<p>Update your Pubkey and Name</p>
|
||||||
) : (
|
) : (
|
||||||
|
@ -23,6 +23,7 @@ const SubscribeModal = ({ user }) => {
|
|||||||
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 [isProcessing, setIsProcessing] = useState(false);
|
const [isProcessing, setIsProcessing] = useState(false);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [subscribed, setSubscribed] = useState(false);
|
const [subscribed, setSubscribed] = useState(false);
|
||||||
@ -31,7 +32,6 @@ const SubscribeModal = ({ user }) => {
|
|||||||
const [calendlyVisible, setCalendlyVisible] = useState(false);
|
const [calendlyVisible, setCalendlyVisible] = useState(false);
|
||||||
const [lightningAddressVisible, setLightningAddressVisible] = useState(false);
|
const [lightningAddressVisible, setLightningAddressVisible] = useState(false);
|
||||||
const [nip05Visible, setNip05Visible] = useState(false);
|
const [nip05Visible, setNip05Visible] = useState(false);
|
||||||
const menu = useRef(null);
|
|
||||||
const [cancelSubscriptionVisible, setCancelSubscriptionVisible] = useState(false);
|
const [cancelSubscriptionVisible, setCancelSubscriptionVisible] = useState(false);
|
||||||
const [renewSubscriptionVisible, setRenewSubscriptionVisible] = useState(false);
|
const [renewSubscriptionVisible, setRenewSubscriptionVisible] = useState(false);
|
||||||
|
|
||||||
|
@ -219,8 +219,8 @@ const UserSubscription = () => {
|
|||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<GenericButton severity="info" outlined className="w-fit text-start" label="Schedule 1:1" icon="pi pi-calendar" onClick={() => setCalendlyVisible(true)} />
|
<GenericButton severity="info" outlined className="w-fit text-start" label="Schedule 1:1" icon="pi pi-calendar" onClick={() => setCalendlyVisible(true)} />
|
||||||
<GenericButton severity="help" outlined className="w-fit text-start" label="Update Nostr NIP-05" icon="pi pi-at" onClick={() => setNip05Visible(true)} />
|
<GenericButton severity="help" outlined className="w-fit text-start" label={user?.nip05 ? "Update Nostr NIP-05" : "Claim PlebDevs Nostr NIP-05"} icon="pi pi-at" onClick={() => setNip05Visible(true)} />
|
||||||
<GenericButton severity="warning" outlined className="w-fit text-start" label="Update Lightning Address" icon={<i style={{ color: "orange" }} className="pi pi-bolt mr-2"></i>} onClick={() => setLightningAddressVisible(true)} />
|
<GenericButton severity="warning" outlined className="w-fit text-start" label={user?.lightningAddress ? "Update Lightning Address" : "Claim PlebDevs Lightning Address"} icon={<i style={{ color: "orange" }} className="pi pi-bolt mr-2"></i>} onClick={() => setLightningAddressVisible(true)} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -228,7 +228,7 @@ const UserSubscription = () => {
|
|||||||
<Card title="Manage Subscription" className="mb-4">
|
<Card title="Manage Subscription" className="mb-4">
|
||||||
<div className='flex flex-col gap-4'>
|
<div className='flex flex-col gap-4'>
|
||||||
<GenericButton outlined className="w-fit" label="Renew Subscription" icon="pi pi-sync" onClick={() => setRenewSubscriptionVisible(true)} />
|
<GenericButton outlined className="w-fit" label="Renew Subscription" icon="pi pi-sync" onClick={() => setRenewSubscriptionVisible(true)} />
|
||||||
<GenericButton outlined className="w-fit" label="Cancel Subscription" icon="pi pi-trash" onClick={() => setCancelSubscriptionVisible(true)} />
|
<GenericButton severity="danger" outlined className="w-fit" label="Cancel Subscription" icon="pi pi-trash" onClick={() => setCancelSubscriptionVisible(true)} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</>
|
</>
|
||||||
@ -238,12 +238,24 @@ const UserSubscription = () => {
|
|||||||
<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>
|
||||||
<p>Our subscription provides monthly access to all PlebDevs features. You can choose between a one-time payment or a recurring subscription.</p>
|
<p>Think of the subscriptions as a paetreon 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.</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold">How do I Subscribe? (Pay as you go)</h3>
|
||||||
|
<p>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.</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold">How do I Subscribe? (Recurring)</h3>
|
||||||
|
<p>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.</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-semibold">Can I cancel my subscription?</h3>
|
<h3 className="text-lg font-semibold">Can I cancel my subscription?</h3>
|
||||||
<p>Yes, you can cancel your subscription at any time. Your access will remain active until the end of the current billing period.</p>
|
<p>Yes, you can cancel your subscription at any time. Your access will remain active until the end of the current billing period.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold">What happens if I don't renew my subscription?</h3>
|
||||||
|
<p>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.</p>
|
||||||
|
</div>
|
||||||
{/* Add more FAQ items as needed */}
|
{/* Add more FAQ items as needed */}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -1,24 +1,25 @@
|
|||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import NostrIcon from '../../public/images/nostr.png';
|
import NostrIcon from '../../public/images/nostr.png';
|
||||||
import { Tooltip } from 'primereact/tooltip';
|
import { Card } from 'primereact/card';
|
||||||
import { useToast } from "@/hooks/useToast"
|
import { Message } from 'primereact/message';
|
||||||
|
import { useToast } from "@/hooks/useToast";
|
||||||
import useWindowWidth from "@/hooks/useWindowWidth";
|
import useWindowWidth from "@/hooks/useWindowWidth";
|
||||||
|
import GenericButton from '@/components/buttons/GenericButton';
|
||||||
|
|
||||||
const AboutPage = () => {
|
const AboutPage = () => {
|
||||||
const {showToast} = useToast()
|
const { showToast } = useToast();
|
||||||
const windowWidth = useWindowWidth();
|
const windowWidth = useWindowWidth();
|
||||||
const isMobileView = windowWidth <= 768;
|
|
||||||
|
|
||||||
const copyToClipboard = async (text) => {
|
const copyToClipboard = async (text) => {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(text);
|
await navigator.clipboard.writeText(text);
|
||||||
showToast("success", "Copied", "Copied Lightning Address to clipboard")
|
showToast("success", "Copied", "Copied Lightning Address to clipboard");
|
||||||
if (window && window?.webln && window?.webln?.lnurl) {
|
if (window && window?.webln && window?.webln?.lnurl) {
|
||||||
await window.webln.enable();
|
await window.webln.enable();
|
||||||
const result = await window.webln.lnurl("austin@bitcoinpleb.dev");
|
const result = await window.webln.lnurl("austin@bitcoinpleb.dev");
|
||||||
if (result && result?.preimage) {
|
if (result && result?.preimage) {
|
||||||
showToast("success", "Copied", "Copied Lightning Address to clipboard")
|
showToast("success", "Payment Sent", "Thank you for your donation!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -27,93 +28,104 @@ const AboutPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl mx-auto py-8 px-4">
|
<div className="p-4 max-w-4xl mx-auto">
|
||||||
|
{windowWidth < 768 && (
|
||||||
<h1 className="text-3xl font-bold mb-6">About PlebDevs</h1>
|
<h1 className="text-3xl font-bold mb-6">About PlebDevs</h1>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="bg-gray-700 rounded-lg p-6 mb-8">
|
<Card className="mb-4">
|
||||||
<p className="text-lg flex items-center">
|
<div className='flex flex-row gap-4'>
|
||||||
<i className="pi pi-info-circle text-blue-500 mr-3 text-2xl"></i>
|
<Message pt={{
|
||||||
PlebDevs is a custom-built education platform designed to help new and aspiring developers, with a special focus on Bitcoin Lightning and Nostr technologies.
|
icon: {
|
||||||
</p>
|
className: 'hidden'
|
||||||
{/* <p className='text-lg font-semibold px-9 mt-4'> */}
|
|
||||||
<p className='font-normal text-lg px-9 mt-4 mb-2'>The pitch is simple:</p>
|
|
||||||
<ul className='list-disc list-inside ml-16 space-y-2'>
|
|
||||||
<li>Learn how to code 💻</li>
|
|
||||||
<li>Build Bitcoin / Lightning / Nostr apps ⚡</li>
|
|
||||||
<li>Become a developer 🚀</li>
|
|
||||||
</ul>
|
|
||||||
{/* </p> */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-8">
|
|
||||||
<h2 className="text-2xl font-bold flex items-center">
|
|
||||||
<i className="pi pi-star text-yellow-500 mr-3 text-2xl"></i>
|
|
||||||
Key Features
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{/* Feature sections */}
|
|
||||||
<FeatureSection
|
|
||||||
icon="pi-cloud"
|
|
||||||
title="Content Distribution"
|
|
||||||
description="All educational content is published to Nostr and actively pulled from Nostr relays, ensuring decentralized and up-to-date information."
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FeatureSection
|
|
||||||
icon="pi-file-edit"
|
|
||||||
title="Content Types"
|
|
||||||
description={
|
|
||||||
<ul className="list-disc list-inside ml-6 space-y-2">
|
|
||||||
<li><span className="font-bold">Documents:</span> Markdown documents posted as NIP-23 long-form events on Nostr.</li>
|
|
||||||
<li><span className="font-bold">Videos:</span> Enhanced markdown files with rich media support, including embedded videos, also saved as NIP-23 events.</li>
|
|
||||||
<li><span className="font-bold">Courses:</span> Nostr lists that combine multiple documents and videos into a structured learning path.</li>
|
|
||||||
</ul>
|
|
||||||
}
|
}
|
||||||
|
}} severity="info" text="PlebDevs is a fully Lightning and Nostr integrated education, content, and community platform designed to help new and aspiring developers, with a focus on Bitcoin / Lightning / Nostr technologies." />
|
||||||
|
<Message pt={{
|
||||||
|
icon: {
|
||||||
|
className: 'hidden'
|
||||||
|
}
|
||||||
|
}} severity="success" text="PlebDevs offers a personal yet distributed learning experience, combining videos, courses, documents, and community channels through Nostr, monetizing with Lightning, and integrating them into a single platform" />
|
||||||
|
</div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<h3 className='font-bold mb-2'>The pitch is simple:</h3>
|
||||||
|
<ul className='list-disc list-inside ml-6 space-y-2'>
|
||||||
|
<li className='text-lg'>Learn how to code 💻</li>
|
||||||
|
<li className='text-lg'>Build Bitcoin / Lightning / Nostr apps ⚡</li>
|
||||||
|
<li className='text-lg'>Become a developer 🚀</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card title="Key Features" className="mb-4">
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col items-start justify-center">
|
||||||
|
<div className='flex flex-row items-start justify-center'>
|
||||||
|
<i className="pi pi-cloud text-2xl text-primary mr-2 text-blue-400"></i>
|
||||||
|
<h3 className='text-lg font-semibold'>Content Distribution:</h3>
|
||||||
|
</div>
|
||||||
|
<p className='text-lg'>All educational content is published to Nostr and actively pulled from Nostr relays, ensuring distributed and up-to-date information.</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-start">
|
||||||
|
<i className="pi pi-file-edit text-2xl text-primary mr-2 text-green-400 mt-1"></i>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold">Content Types:</h3>
|
||||||
|
<p className='text-lg'>high signal, Bitcoin, Lightning, Nostr educational content.</p>
|
||||||
|
<ul className="list-disc list-inside ml-2 mt-2 space-y-2">
|
||||||
|
<li><span className="text-lg font-semibold">Documents:</span> Markdown documents posted as NIP-23 long-form events on Nostr.</li>
|
||||||
|
<li><span className="text-lg font-semibold">Videos:</span> Enhanced markdown files with rich media support, including embedded videos, also saved as NIP-23 events.</li>
|
||||||
|
<li><span className="text-lg font-semibold">Courses:</span> Nostr lists that combine multiple documents and videos into a structured learning path.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-start">
|
||||||
|
<i className="pi pi-users text-2xl text-primary mr-2 text-purple-400 mt-1"></i>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold">Community:</h3>
|
||||||
|
<p className='text-lg'>All of the current PlebDevs Community channels.</p>
|
||||||
|
<ul className="list-disc list-inside ml-2 mt-2 space-y-2">
|
||||||
|
<li><span className="text-lg font-semibold">Nostr:</span> Public plebdevs nostr chat</li>
|
||||||
|
<li><span className="text-lg font-semibold">Discord:</span> PlebDevs Discord server</li>
|
||||||
|
<li><span className="text-lg font-semibold">StackerNews:</span> StackerNews ~devs territory</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card title="Connect with Us" className="mb-4">
|
||||||
|
<div className="flex flex-wrap gap-4 justify-center">
|
||||||
|
<GenericButton
|
||||||
|
severity="secondary"
|
||||||
|
outlined
|
||||||
|
icon="pi pi-github"
|
||||||
|
label="GitHub"
|
||||||
|
onClick={() => window.open('https://github.com/pleb-devs', '_blank')}
|
||||||
|
/>
|
||||||
|
<GenericButton
|
||||||
|
severity="info"
|
||||||
|
outlined
|
||||||
|
icon="pi pi-twitter"
|
||||||
|
label="X.com"
|
||||||
|
onClick={() => window.open('https://x.com/pleb_devs', '_blank')}
|
||||||
|
/>
|
||||||
|
<GenericButton
|
||||||
|
severity="help"
|
||||||
|
outlined
|
||||||
|
icon={<Image src={NostrIcon} alt="Nostr" width={20} height={20} className="mr-2" />}
|
||||||
|
label="Nostr"
|
||||||
|
onClick={() => window.open('https://nostr.com/plebdevs@plebdevs.com', '_blank')}
|
||||||
|
/>
|
||||||
|
<GenericButton
|
||||||
|
severity="warning"
|
||||||
|
outlined
|
||||||
|
icon="pi pi-bolt"
|
||||||
|
label="Donate"
|
||||||
|
onClick={() => copyToClipboard("austin@bitcoinpleb.dev")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</Card>
|
||||||
<div className="mt-12 bg-gray-700 rounded-lg p-6">
|
|
||||||
<p className="italic text-lg flex items-center">
|
|
||||||
<i className="pi pi-flag text-blue-500 mr-3 text-2xl"></i>
|
|
||||||
PlebDevs aims to provide a comprehensive, decentralized learning experience for aspiring developers, with a strong emphasis on emerging technologies in the Bitcoin ecosystem.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-12 bg-gray-700 rounded-lg p-6">
|
|
||||||
<div className="flex items-center justify-center space-x-16">
|
|
||||||
<Tooltip target=".pi-github" content={isMobileView ? null : "GitHub"} position="bottom" />
|
|
||||||
<a href="https://github.com/pleb-devs" target="_blank" rel="noopener noreferrer">
|
|
||||||
<i className="pi pi-github text-white text-5xl"></i>
|
|
||||||
</a>
|
|
||||||
<Tooltip target=".pi-twitter" content={isMobileView ? null : "X.com"} position="bottom" />
|
|
||||||
<a href="https://x.com/pleb_devs" target="_blank" rel="noopener noreferrer">
|
|
||||||
<i className="pi pi-twitter text-black text-5xl"></i>
|
|
||||||
</a>
|
|
||||||
<Tooltip target=".nostr-icon" content={isMobileView ? null : "Nostr"} position="bottom" />
|
|
||||||
<a href="https://nostr.com/plebdevs@plebdevs.com" target="_blank" rel="noopener noreferrer">
|
|
||||||
<Image src={NostrIcon} alt="Nostr" width={44} height={44} className='nostr-icon' />
|
|
||||||
</a>
|
|
||||||
<Tooltip target=".pi-bolt" content={isMobileView ? null : "Donate"} position="bottom" />
|
|
||||||
<p onClick={() => copyToClipboard("austin@bitcoinpleb.dev")} className='cursor-pointer'>
|
|
||||||
<i className="pi pi-bolt text-yellow-500 text-5xl"></i>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const FeatureSection = ({ icon, title, description }) => (
|
|
||||||
<div className="bg-gray-700 shadow-md rounded-lg p-6">
|
|
||||||
<h3 className="text-xl font-bold mb-4 flex items-center">
|
|
||||||
<i className={`pi ${icon} text-blue-500 mr-3 text-2xl`}></i>
|
|
||||||
{title}
|
|
||||||
</h3>
|
|
||||||
{typeof description === 'string' ? (
|
|
||||||
<p>{description}</p>
|
|
||||||
) : (
|
|
||||||
description
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default AboutPage;
|
export default AboutPage;
|
Loading…
x
Reference in New Issue
Block a user