diff --git a/src/components/content/carousels/InteractivePromotionalCarousel.js b/src/components/content/carousels/InteractivePromotionalCarousel.js
new file mode 100644
index 0000000..584edb1
--- /dev/null
+++ b/src/components/content/carousels/InteractivePromotionalCarousel.js
@@ -0,0 +1,211 @@
+import Image from "next/image"
+import { useState } from "react"
+import { useImageProxy } from "@/hooks/useImageProxy"
+import GenericButton from "@/components/buttons/GenericButton"
+import { useRouter } from "next/router"
+import useWindowWidth from "@/hooks/useWindowWidth"
+
+// With current spacing the title can only be 1 line
+const promotions = [
+ {
+ id: 1,
+ category: "PLEBDEVS",
+ title: "Developer education & community platform",
+ description: "PlebDevs is your gateway to mastering Bitcoin, Lightning, and Nostr technologies. Join our community of aspiring developers and start your journey today!",
+ icon: "pi pi-code",
+ image: "https://media.istockphoto.com/id/537331500/photo/programming-code-abstract-technology-background-of-software-deve.jpg?s=612x612&w=0&k=20&c=jlYes8ZfnCmD0lLn-vKvzQoKXrWaEcVypHnB5MuO-g8=",
+ },
+ {
+ id: 2,
+ category: "COURSES",
+ title: "Structured learning paths for new devs",
+ description: "Dive into our comprehensive courses covering Bitcoin protocol, Lightning Network, and Nostr. From basics to advanced topics, we've got you covered.",
+ icon: "pi pi-book",
+ image: "https://media.istockphoto.com/id/1224500457/photo/programming-code-abstract-technology-background-of-software-developer-and-computer-script.jpg?s=612x612&w=0&k=20&c=nHMypkMTU1HUUW85Zt0Ff7MDbq17n0eVeXaoM9Knt4Q=",
+ },
+ {
+ id: 3,
+ category: "WORKSHOPS",
+ title: "Hands-on Video Workshops",
+ description: "Watch and learn with our interactive video workshops. Get practical experience building real Bitcoin and Lightning applications.",
+ icon: "pi pi-video",
+ image: "https://newsroom.siliconslopes.com/content/images/2018/10/code.jpg",
+ },
+ {
+ id: 4,
+ category: "RESOURCES",
+ title: "In-depth Resources and Documentation",
+ description: "Access our extensive library of resources, including guides, documentation, and best practices for Bitcoin development.",
+ icon: "pi pi-file",
+ image: "https://img.freepik.com/free-photo/programming-background-with-person-working-with-codes-computer_23-2150010125.jpg",
+ },
+ {
+ id: 5,
+ category: "COMMUNITY",
+ title: "Join Our Community",
+ description: "Connect with other developers, share your projects, and get support from our community of Bitcoin enthusiasts.",
+ icon: "pi pi-users",
+ image: "https://pikwizard.com/pw/medium/50238b1cad4ff412fdafc1325efa1c9f.jpg",
+ },
+ {
+ id: 6,
+ category: "LIGHTNING / NOSTR",
+ title: "Lightning and Nostr integrated",
+ description: "This platform is the first of its kind to integrate Lightning Network and Nostr protocols, allowing users to send and receive payments and interact with the Nostr network.",
+ icon: "pi pi-bolt",
+ image: "https://www.financemagnates.com/wp-content/uploads/2016/05/Bicoin-lightning.jpg",
+ },
+]
+
+const InteractivePromotionalCarousel = () => {
+ const [selectedPromotion, setSelectedPromotion] = useState(promotions[0])
+ const { returnImageProxy } = useImageProxy();
+ const windowWidth = useWindowWidth();
+ const isMobileView = windowWidth <= 1360;
+ const router = useRouter();
+
+ return (
+
+
+
+ {isMobileView ? (
+
+
{selectedPromotion.category}
+
+ {selectedPromotion.title}
+
+
{selectedPromotion.description}
+
+ {
+ (() => {
+ switch (selectedPromotion.category) {
+ case "PLEBDEVS":
+ return (
+ <>
+ router.push('/about')} severity="success" icon={} label="Learn More" className="py-2 font-semibold" size="small" outlined />
+ router.push('/subscribe')} severity="warning" icon={} label="Subscribe" className="py-2 font-semibold" size="small" outlined />
+ router.push('/content?tag=all')} severity="primary" icon={} label="View all content" className="py-2 font-semibold" size="small" outlined />
+ >
+ );
+ case "COURSES":
+ return (
+ router.push('/content?tag=courses')} icon={} label="View All Courses" className="py-2 font-semibold" size="small" outlined />
+ );
+ case "WORKSHOPS":
+ return (
+ router.push('/content?tag=workshops')} icon={} label="View All Workshops" className="py-2 font-semibold" size="small" outlined />
+ );
+ case "RESOURCES":
+ return (
+ router.push('/content?tag=resources')} icon={} label="View All Resources" className="py-2 font-semibold" size="small" outlined />
+ );
+ case "COMMUNITY":
+ return (
+ router.push('/feed?channel=global')} icon={} label="Open Community Feed" className="py-2 font-semibold" size="small" outlined />
+ );
+ case "LIGHTNING / NOSTR":
+ return (
+ router.push('/subscribe')} severity="warning" icon={} label="Subscribe" className="py-2 font-semibold" size="small" outlined />
+ );
+ default:
+ return null;
+ }
+ })()
+ }
+
+
+ ) : (
+ <>
+
+
+
{selectedPromotion.category}
+
+ {selectedPromotion.title}
+
+
{selectedPromotion.description}
+
+ {
+ (() => {
+ switch (selectedPromotion.category) {
+ case "PLEBDEVS":
+ return (
+ <>
+ router.push('/about')} severity="success" icon={} label="Learn More" className="py-2 font-semibold" size="small" outlined />
+ router.push('/subscribe')} severity="warning" icon={} label="Subscribe" className="py-2 font-semibold" size="small" outlined />
+ router.push('/content?tag=all')} severity="primary" icon={} label="View all content" className="py-2 font-semibold" size="small" outlined />
+ >
+ );
+ case "COURSES":
+ return (
+ router.push('/content?tag=courses')} icon={} label="View All Courses" className="py-2 font-semibold" size="small" outlined />
+ );
+ case "WORKSHOPS":
+ return (
+ router.push('/content?tag=workshops')} icon={} label="View All Workshops" className="py-2 font-semibold" size="small" outlined />
+ );
+ case "RESOURCES":
+ return (
+ router.push('/content?tag=resources')} icon={} label="View All Resources" className="py-2 font-semibold" size="small" outlined />
+ );
+ case "COMMUNITY":
+ return (
+ router.push('/feed?channel=global')} icon={} label="Open Community Feed" className="py-2 font-semibold" size="small" outlined />
+ );
+ case "LIGHTNING / NOSTR":
+ return (
+ router.push('/subscribe')} severity="warning" icon={} label="Subscribe" className="py-2 font-semibold" size="small" outlined />
+ );
+ default:
+ return null;
+ }
+ })()
+ }
+
+
+ >
+ )}
+
+
+ {isMobileView ? (
+
+ {promotions.map((promo) => (
+
setSelectedPromotion(promo)}>
+
+
{promo.title}
+
+ ))}
+
+ ) : (
+ promotions.map((promo) => (
+
setSelectedPromotion(promo)}>
+
+
{promo.title}
+
+ ))
+ )}
+
+
+ );
+}
+
+export default InteractivePromotionalCarousel;
\ No newline at end of file
diff --git a/src/components/content/courses/CourseDetails.js b/src/components/content/courses/CourseDetails.js
index 6b8581b..3cd96a5 100644
--- a/src/components/content/courses/CourseDetails.js
+++ b/src/components/content/courses/CourseDetails.js
@@ -179,7 +179,7 @@ export default function CourseDetails({ processedEvent, paidCourse, lessons, dec
anchor={nAddress}
user={user?.pubkey || null}
relays="wss://nos.lol/, wss://relay.damus.io/, wss://relay.snort.social/, wss://relay.nostr.band/, wss://relay.mutinywallet.com/, wss://relay.primal.net/"
- disable=""
+ disable="zaps"
/>
)}
diff --git a/src/components/feeds/messages/CommunityMessage.js b/src/components/feeds/messages/CommunityMessage.js
index 7aee020..169c669 100644
--- a/src/components/feeds/messages/CommunityMessage.js
+++ b/src/components/feeds/messages/CommunityMessage.js
@@ -85,7 +85,7 @@ const CommunityMessage = ({ message, searchQuery, windowWidth, platform }) => {
anchor={nip19.noteEncode(message.id)}
user={npub || null}
relays="wss://nos.lol/, wss://relay.damus.io/, wss://relay.snort.social/, wss://relay.nostr.band/, wss://relay.mutinywallet.com/, wss://relay.primal.net/"
- disable=""
+ disable="zaps"
/>
diff --git a/src/components/interactive-news-carousel.jsx b/src/components/interactive-news-carousel.jsx
deleted file mode 100644
index a78034b..0000000
--- a/src/components/interactive-news-carousel.jsx
+++ /dev/null
@@ -1,137 +0,0 @@
-import Image from "next/image"
-import { useState } from "react"
-import { useImageProxy } from "@/hooks/useImageProxy"
-import GenericButton from "@/components/buttons/GenericButton"
-import { useRouter } from "next/router"
-const promotions = [
- {
- id: 1,
- category: "PLEBDEVS",
- title: "Learn how to code, build Bitcoin, Lightning, and Nostr apps, become a developer.",
- description: "PlebDevs is your gateway to mastering Bitcoin, Lightning, and Nostr technologies. Join our community of aspiring developers and start your journey today!",
- icon: "pi pi-code",
- image: "https://media.istockphoto.com/id/537331500/photo/programming-code-abstract-technology-background-of-software-deve.jpg?s=612x612&w=0&k=20&c=jlYes8ZfnCmD0lLn-vKvzQoKXrWaEcVypHnB5MuO-g8=",
- },
- {
- id: 2,
- category: "COURSES",
- title: "Structured Learning Paths for Bitcoin Developers",
- description: "Dive into our comprehensive courses covering Bitcoin protocol, Lightning Network, and Nostr. From basics to advanced topics, we've got you covered.",
- icon: "pi pi-book",
- image: "https://media.istockphoto.com/id/1224500457/photo/programming-code-abstract-technology-background-of-software-developer-and-computer-script.jpg?s=612x612&w=0&k=20&c=nHMypkMTU1HUUW85Zt0Ff7MDbq17n0eVeXaoM9Knt4Q=",
- },
- {
- id: 3,
- category: "WORKSHOPS",
- title: "Hands-on Video Workshops",
- description: "Watch and learn with our interactive video workshops. Get practical experience building real Bitcoin and Lightning applications.",
- icon: "pi pi-video",
- image: "https://newsroom.siliconslopes.com/content/images/2018/10/code.jpg",
- },
- {
- id: 4,
- category: "RESOURCES",
- title: "In-depth Resources and Documentation",
- description: "Access our extensive library of resources, including guides, documentation, and best practices for Bitcoin development.",
- icon: "pi pi-file",
- image: "https://img.freepik.com/free-photo/programming-background-with-person-working-with-codes-computer_23-2150010125.jpg",
- },
- {
- id: 5,
- category: "COMMUNITY",
- title: "Join Our Community",
- description: "Connect with other developers, share your projects, and get support from our community of Bitcoin enthusiasts.",
- icon: "pi pi-users",
- image: "https://pikwizard.com/pw/medium/50238b1cad4ff412fdafc1325efa1c9f.jpg",
- },
- {
- id: 6,
- category: "LIGHTNING / NOSTR",
- title: "Lightning and Nostr integrated",
- description: "This platform is the first of its kind to integrate Lightning Network and Nostr protocols, allowing users to send and receive payments and interact with the Nostr network.",
- icon: "pi pi-bolt",
- image: "https://www.financemagnates.com/wp-content/uploads/2016/05/Bicoin-lightning.jpg",
- },
-]
-
-export function InteractivePromotionalCarousel() {
- const [selectedPromotion, setSelectedPromotion] = useState(promotions[0])
- const { returnImageProxy } = useImageProxy();
- const router = useRouter();
-
- return (
-
-
-
-
{/* Modified gradient */}
-
-
{selectedPromotion.category}
{/* Changed color */}
-
- {selectedPromotion.title}
-
-
{selectedPromotion.description}
-
- {
- (() => {
- switch (selectedPromotion.category) {
- case "PLEBDEVS":
- return (
- <>
- router.push('/about')} severity="success" icon={} label="Learn More" className="py-2 font-semibold" size="small" outlined />
- router.push('/subscribe')} severity="warning" icon={} label="Subscribe" className="py-2 font-semibold" size="small" outlined />
- router.push('/content?tag=all')} severity="primary" icon={} label="View all content" className="py-2 font-semibold" size="small" outlined />
- >
- );
- case "COURSES":
- return (
- router.push('/content?tag=courses')} icon={} label="View All Courses" className="py-2 font-semibold" size="small" outlined />
- );
- case "WORKSHOPS":
- return (
- router.push('/content?tag=workshops')} icon={} label="View All Workshops" className="py-2 font-semibold" size="small" outlined />
- );
- case "RESOURCES":
- return (
- router.push('/content?tag=resources')} icon={} label="View All Resources" className="py-2 font-semibold" size="small" outlined />
- );
- case "COMMUNITY":
- return (
- router.push('/feed?channel=global')} icon={} label="Open Community Feed" className="py-2 font-semibold" size="small" outlined />
- );
- case "LIGHTNING / NOSTR":
- return (
- router.push('/subscribe')} severity="warning" icon={} label="Subscribe" className="py-2 font-semibold" size="small" outlined />
- );
- default:
- return null;
- }
- })()
- }
-
-
-
-
{/* Reduced space-y */}
- {promotions.map((promo) => (
-
setSelectedPromotion(promo)}>
-
-
{/* Changed icon color */}
-
{promo.category}
{/* Changed text style */}
-
-
{promo.title}
{/* Changed text style */}
-
- ))}
-
-
- );
-}
\ No newline at end of file
diff --git a/src/components/navbar/Navbar.js b/src/components/navbar/Navbar.js
index 09a5944..b7c65a9 100644
--- a/src/components/navbar/Navbar.js
+++ b/src/components/navbar/Navbar.js
@@ -7,9 +7,11 @@ import SearchBar from '../search/SearchBar';
import 'primereact/resources/primereact.min.css';
import 'primeicons/primeicons.css';
import { useNDKContext } from '@/context/NDKContext';
+import useWindowWidth from '@/hooks/useWindowWidth';
const Navbar = () => {
const router = useRouter();
+ const windowWidth = useWindowWidth();
const navbarHeight = '60px';
const {ndk} = useNDKContext();
@@ -25,7 +27,7 @@ const Navbar = () => {
/>
PlebDevs
- {ndk && }
+ {ndk && windowWidth > 600 && }
);
diff --git a/src/components/search/SearchBar.js b/src/components/search/SearchBar.js
index 709c575..7408ea2 100644
--- a/src/components/search/SearchBar.js
+++ b/src/components/search/SearchBar.js
@@ -9,12 +9,14 @@ import MessageDropdownItem from '@/components/content/dropdowns/MessageDropdownI
import { useContentSearch } from '@/hooks/useContentSearch';
import { useCommunitySearch } from '@/hooks/useCommunitySearch';
import { useRouter } from 'next/router';
+import useWindowWidth from '@/hooks/useWindowWidth';
import styles from './searchbar.module.css';
const SearchBar = () => {
const { searchContent, searchResults: contentResults } = useContentSearch();
const { searchCommunity, searchResults: communityResults } = useCommunitySearch();
const router = useRouter();
+ const windowWidth = useWindowWidth();
const [selectedSearchOption, setSelectedSearchOption] = useState({ name: 'Content', code: 'content', icon: 'pi pi-video' });
const searchOptions = [
{ name: 'Content', code: 'content', icon: 'pi pi-video' },
@@ -71,11 +73,11 @@ const SearchBar = () => {
}
return (
-
+
845 ? 'w-[300px]' : 'w-[160px]'}`}
value={searchTerm}
onChange={handleSearch}
placeholder={`Search ${selectedSearchOption.name.toLowerCase()}`}
diff --git a/src/pages/content/index.js b/src/pages/content/index.js
index 570d670..9e49d42 100644
--- a/src/pages/content/index.js
+++ b/src/pages/content/index.js
@@ -76,7 +76,6 @@ const ContentPage = () => {
const [processedCourses, setProcessedCourses] = useState([]);
const [allContent, setAllContent] = useState([]);
const [allTopics, setAllTopics] = useState([]);
- const [searchQuery, setSearchQuery] = useState('');
const [selectedTopic, setSelectedTopic] = useState('All')
const [filteredContent, setFilteredContent] = useState([]);
@@ -165,13 +164,6 @@ const ContentPage = () => {
All Content
- setSearchQuery(e.target.value)}
- placeholder="Search"
- icon="pi pi-search"
- className="w-full"
- />
!['Courses', 'Workshops', 'Resources'].includes(topic))]}
diff --git a/src/pages/course/[slug]/draft/edit.js b/src/pages/course/[slug]/draft/edit.js
index 10c99a6..97e0edc 100644
--- a/src/pages/course/[slug]/draft/edit.js
+++ b/src/pages/course/[slug]/draft/edit.js
@@ -4,12 +4,21 @@ import { useRouter } from "next/router";
import CourseForm from "@/components/forms/course/CourseForm";
import { useNDKContext } from "@/context/NDKContext";
import { useToast } from "@/hooks/useToast";
+import { useIsAdmin } from "@/hooks/useIsAdmin";
export default function Edit() {
const [draft, setDraft] = useState(null);
const { ndk } = useNDKContext();
const router = useRouter();
const { showToast } = useToast();
+ const { isAdmin, isLoading } = useIsAdmin();
+ useEffect(() => {
+ if (isLoading) return;
+
+ if (!isAdmin) {
+ router.push('/');
+ }
+ }, [isAdmin, router, isLoading]);
useEffect(() => {
if (router.isReady) {
diff --git a/src/pages/course/[slug]/draft/index.js b/src/pages/course/[slug]/draft/index.js
index 42513fd..5ea358b 100644
--- a/src/pages/course/[slug]/draft/index.js
+++ b/src/pages/course/[slug]/draft/index.js
@@ -6,17 +6,26 @@ import DraftCourseDetails from "@/components/content/courses/DraftCourseDetails"
import DraftCourseLesson from "@/components/content/courses/DraftCourseLesson";
import { useNDKContext } from "@/context/NDKContext";
import { useSession } from "next-auth/react";
-
+import { useIsAdmin } from "@/hooks/useIsAdmin";
const DraftCourse = () => {
const { data: session, status } = useSession();
const [course, setCourse] = useState(null);
const [lessons, setLessons] = useState([]);
const [lessonsWithAuthors, setLessonsWithAuthors] = useState([]);
+ const { isAdmin, isLoading } = useIsAdmin();
const router = useRouter();
const {ndk, addSigner} = useNDKContext();
const { slug } = router.query;
+ useEffect(() => {
+ if (isLoading) return;
+
+ if (!isAdmin) {
+ router.push('/');
+ }
+ }, [isAdmin, router, isLoading]);
+
const fetchAuthor = useCallback(async (pubkey) => {
if (!pubkey) return;
const author = await ndk.getUser({ pubkey });
diff --git a/src/pages/draft/[slug]/edit.js b/src/pages/draft/[slug]/edit.js
index 7267d6e..179026f 100644
--- a/src/pages/draft/[slug]/edit.js
+++ b/src/pages/draft/[slug]/edit.js
@@ -4,10 +4,19 @@ import axios from "axios";
import ResourceForm from "@/components/forms/ResourceForm";
import WorkshopForm from "@/components/forms/WorkshopForm";
import CourseForm from "@/components/forms/course/CourseForm";
+import { useIsAdmin } from "@/hooks/useIsAdmin";
const Edit = () => {
const [draft, setDraft] = useState(null);
const router = useRouter();
+ const { isAdmin, isLoading } = useIsAdmin();
+ useEffect(() => {
+ if (isLoading) return;
+
+ if (!isAdmin) {
+ router.push('/');
+ }
+ }, [isAdmin, router, isLoading]);
useEffect(() => {
if (router.isReady) {
diff --git a/src/pages/draft/[slug]/index.js b/src/pages/draft/[slug]/index.js
index b7fab53..0fa9485 100644
--- a/src/pages/draft/[slug]/index.js
+++ b/src/pages/draft/[slug]/index.js
@@ -18,6 +18,7 @@ import 'primeicons/primeicons.css';
import dynamic from 'next/dynamic';
import { validateEvent } from '@/utils/nostr';
import { defaultRelayUrls } from '@/context/NDKContext';
+import { useIsAdmin } from "@/hooks/useIsAdmin";
const MDDisplay = dynamic(
() => import("@uiw/react-markdown-preview"),
@@ -36,6 +37,15 @@ export default function Draft() {
const router = useRouter();
const { showToast } = useToast();
const { ndk, addSigner } = useNDKContext();
+ const { isAdmin, isLoading } = useIsAdmin();
+
+ useEffect(() => {
+ if (isLoading) return;
+
+ if (!isAdmin) {
+ router.push('/');
+ }
+ }, [isAdmin, router, isLoading]);
useEffect(() => {
if (session) {
diff --git a/src/pages/index.js b/src/pages/index.js
index 12338ac..e2898eb 100644
--- a/src/pages/index.js
+++ b/src/pages/index.js
@@ -2,12 +2,9 @@ import Head from 'next/head';
import React from 'react';
import CoursesCarousel from '@/components/content/carousels/CoursesCarousel';
import WorkshopsCarousel from '@/components/content/carousels/WorkshopsCarousel';
-import HeroBanner from '@/components/banner/HeroBanner';
import ResourcesCarousel from '@/components/content/carousels/ResourcesCarousel';
-import { InteractivePromotionalCarousel } from '@/components/interactive-news-carousel';
+import InteractivePromotionalCarousel from '@/components/content/carousels/InteractivePromotionalCarousel';
-// todo append link to plebdevs item in each published course or resource description
-// todo perhaps need to update slug on details on course pages to be d tag instead of db id
export default function Home() {
return (
<>
@@ -18,7 +15,6 @@ export default function Home() {
- {/* */}
diff --git a/src/utils/text.js b/src/utils/text.js
index 60caaa3..cd85ba6 100644
--- a/src/utils/text.js
+++ b/src/utils/text.js
@@ -3,7 +3,7 @@ export const highlightText = (text, query) => {
const parts = text.split(new RegExp(`(${query})`, 'gi'));
return parts.map((part, index) =>
part.toLowerCase() === query.toLowerCase()
- ? {part}
+ ? {part}
: part
);
};
\ No newline at end of file