mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-04-19 10:51:20 +00:00
Updated carousels layout with menutab of tags on home page
This commit is contained in:
parent
3d8ba067e7
commit
79a0559995
@ -2,7 +2,6 @@ import React, { useEffect, useState, useRef } from 'react';
|
||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||
import Image from 'next/image';
|
||||
import { getSession, signIn, useSession } from 'next-auth/react';
|
||||
import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Avatar } from 'primereact/avatar';
|
||||
import { AvatarGroup } from 'primereact/avatargroup';
|
||||
@ -15,7 +14,6 @@ const HeroBanner = () => {
|
||||
const techs = ['Bitcoin', 'Lightning', 'Nostr'];
|
||||
const windowWidth = useWindowWidth();
|
||||
const router = useRouter();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
const { data: session } = useSession();
|
||||
|
||||
const isTabView = windowWidth <= 1360;
|
||||
@ -48,10 +46,10 @@ const HeroBanner = () => {
|
||||
};
|
||||
|
||||
const getHeroHeight = () => {
|
||||
if (isSuperWideScreen) return 'h-[900px]';
|
||||
if (isWideScreen) return 'h-[700px]';
|
||||
if (isMobile) return 'h-[450px]';
|
||||
return 'h-[600px]';
|
||||
if (isSuperWideScreen) return 'h-[700px]';
|
||||
if (isWideScreen) return 'h-[550px]';
|
||||
if (isMobile) return 'h-[400px]';
|
||||
return 'h-[500px]';
|
||||
};
|
||||
|
||||
const handleLearnToCode = async () => {
|
||||
@ -105,7 +103,7 @@ const HeroBanner = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${getHeroHeight()} ${isTabView ? 'mx-0' : 'm-14'} relative flex justify-center items-center overflow-hidden drop-shadow-2xl`}>
|
||||
<div className={`${getHeroHeight()} ${isTabView ? 'mx-0 w-full' : 'm-4'} relative flex justify-center items-center overflow-hidden drop-shadow-2xl rounded-lg`}>
|
||||
<Image
|
||||
src={HeroImage}
|
||||
alt="Banner"
|
||||
@ -117,7 +115,7 @@ const HeroBanner = () => {
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-black via-black/20 to-transparent rounded-lg" />
|
||||
|
||||
{!isTabView && (
|
||||
<div className="absolute right-0 top-24 bottom-0 w-1/2 overflow-hidden rounded-l-lg opacity-100 p-2 rounded-lg shadow-lg mr-2">
|
||||
<div className="absolute right-0 top-auto bottom-auto w-1/2 overflow-hidden opacity-100 p-4 shadow-lg">
|
||||
<video
|
||||
className="w-full object-cover rounded-lg shadow-lg"
|
||||
autoPlay
|
||||
@ -132,8 +130,8 @@ const HeroBanner = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={`absolute inset-0 flex flex-col justify-center ${isTabView ? 'items-center text-center' : 'items-start pl-8'}`}>
|
||||
<h1 className={`text-4xl sm:text-4xl lg:text-6xl font-bold leading-tight mb-6 ${isTabView ? 'px-4' : 'max-w-[50%]'}`}>
|
||||
<div className={`absolute inset-0 flex flex-col justify-center ${isTabView ? 'items-center text-center px-4' : 'items-start pl-8'}`}>
|
||||
<h1 className={`text-4xl sm:text-4xl lg:text-6xl font-bold leading-tight mb-4 ${isTabView ? 'px-4' : 'max-w-[50%]'}`}>
|
||||
<span className="block">Learn to code</span>
|
||||
<span className={`block ${isTabView ? `transition-opacity duration-500 ${isAnimating ? 'opacity-0' : 'opacity-100'}` : ''}`}>
|
||||
Build on{' '}
|
||||
@ -144,16 +142,16 @@ const HeroBanner = () => {
|
||||
<span className="block">Become a dev</span>
|
||||
</h1>
|
||||
{isMobile ? (
|
||||
<h3 className="text-[#f8f8ff] mb-8 font-semibold">
|
||||
<h3 className="text-[#f8f8ff] mb-6 font-semibold">
|
||||
A one of a kind developer education, content, and community platform built on Nostr and fully Lightning integrated.
|
||||
</h3>
|
||||
) : (
|
||||
<h2 className="text-[#f8f8ff] mb-8 font-semibold max-w-[42%]">
|
||||
<h2 className="text-[#f8f8ff] mb-6 font-semibold max-w-[42%]">
|
||||
A one of a kind developer education, content, and community platform built on Nostr and fully Lightning integrated.
|
||||
</h2>
|
||||
)}
|
||||
<div
|
||||
className="mb-8 flex flex-row hover:opacity-70 cursor-pointer"
|
||||
className="mb-6 flex flex-row hover:opacity-70 cursor-pointer"
|
||||
onClick={() => !isMobile && window.open('https://www.udemy.com/user/austin-james-kelsay/', '_blank')}
|
||||
style={{ cursor: isMobile ? 'default' : 'pointer' }}
|
||||
>
|
||||
@ -180,21 +178,10 @@ const HeroBanner = () => {
|
||||
label="Learn To Code"
|
||||
icon={<i className="pi pi-book pr-2 text-2xl" />}
|
||||
rounded
|
||||
severity="info"
|
||||
className="border-2"
|
||||
size={isMobile ? null : "large"}
|
||||
outlined
|
||||
onClick={handleLearnToCode}
|
||||
/>
|
||||
<GenericButton
|
||||
label="Level Up"
|
||||
icon={<i className="pi pi-video pr-2 text-2xl" />}
|
||||
rounded
|
||||
size={isMobile ? null : "large"}
|
||||
severity="success"
|
||||
className="border-2"
|
||||
outlined
|
||||
onClick={() => router.push('/content?tag=all')}
|
||||
onClick={handleLearnToCode}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -56,18 +56,18 @@ export default function CoursesCarousel() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<h3 className={`ml-[6%] mt-4 max-mob:text-3xl max-mob:ml-10`}>Courses</h3>
|
||||
<Divider className={`${isMobileView ? '' : 'hidden'}`} />
|
||||
<h3 className={`ml-[3%] mt-4 max-mob:text-2xl max-tab:ml-10 max-mob:ml-5`}>Courses</h3>
|
||||
<Divider className='w-[95%] mx-auto max-tab:hidden max-mob:w-[100%]' />
|
||||
<div className={"min-h-[384px]"}>
|
||||
<Carousel
|
||||
value={coursesLoading || !processedCourses.length ? [{}, {}, {}] : [...processedCourses]}
|
||||
numVisible={2}
|
||||
pt={{
|
||||
previousButton: {
|
||||
className: isMobileView ? 'm-0' : ''
|
||||
className: 'm-0'
|
||||
},
|
||||
nextButton: {
|
||||
className: isMobileView ? 'm-0' : ''
|
||||
className: 'm-0'
|
||||
}
|
||||
}}
|
||||
itemTemplate={(item) =>
|
||||
|
@ -82,17 +82,17 @@ export default function DocumentsCarousel() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<h3 className={`ml-[6%] mt-4 max-mob:text-3xl max-mob:ml-10`}>Documents</h3>
|
||||
<Divider className={`${isMobileView ? '' : 'hidden'}`} />
|
||||
<h3 className={`ml-[3%] mt-4 max-mob:text-2xl max-tab:ml-10 max-mob:ml-5`}>Documents</h3>
|
||||
<Divider className='w-[95%] mx-auto max-tab:hidden max-mob:w-[100%]' />
|
||||
<Carousel
|
||||
value={documentsLoading || !processedDocuments.length ? [{}, {}, {}] : [...processedDocuments]}
|
||||
numVisible={2}
|
||||
pt={{
|
||||
previousButton: {
|
||||
className: isMobileView ? 'm-0' : ''
|
||||
className: 'm-0'
|
||||
},
|
||||
nextButton: {
|
||||
className: isMobileView ? 'm-0' : ''
|
||||
className: 'm-0'
|
||||
}
|
||||
}}
|
||||
itemTemplate={(item) =>
|
||||
|
@ -83,17 +83,17 @@ export default function VideosCarousel() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<h3 className={`ml-[6%] mt-4 max-mob:text-3xl max-mob:ml-10`}>Videos</h3>
|
||||
<Divider className={`${isMobileView ? '' : 'hidden'}`} />
|
||||
<h3 className={`ml-[3%] mt-4 max-mob:text-2xl max-tab:ml-10 max-mob:ml-5`}>Videos</h3>
|
||||
<Divider className='w-[95%] mx-auto max-tab:hidden max-mob:w-[100%]' />
|
||||
<Carousel
|
||||
value={videosLoading || !processedVideos.length ? [{}, {}, {}] : [...processedVideos]}
|
||||
numVisible={2}
|
||||
pt={{
|
||||
previousButton: {
|
||||
className: isMobileView ? 'm-0' : ''
|
||||
className: 'm-0'
|
||||
},
|
||||
nextButton: {
|
||||
className: isMobileView ? 'm-0' : ''
|
||||
className: 'm-0'
|
||||
}
|
||||
}}
|
||||
itemTemplate={(item) =>
|
||||
|
@ -9,7 +9,7 @@ const appConfig = {
|
||||
"wss://purplerelay.com/",
|
||||
"wss://relay.devs.tools/"
|
||||
],
|
||||
authorPubkeys: ["f33c8a9617cb15f705fc70cd461cfd6eaf22f9e24c33eabad981648e5ec6f741", "c67cd3e1a83daa56cff16f635db2fdb9ed9619300298d4701a58e68e84098345"],
|
||||
authorPubkeys: ["f33c8a9617cb15f705fc70cd461cfd6eaf22f9e24c33eabad981648e5ec6f741", "c67cd3e1a83daa56cff16f635db2fdb9ed9619300298d4701a58e68e84098345", "6260f29fa75c91aaa292f082e5e87b438d2ab4fdf96af398567b01802ee2fcd4"],
|
||||
customLightningAddresses: [
|
||||
{
|
||||
// todo remove need for lowercase
|
||||
|
@ -11,6 +11,7 @@ export function useCourses() {
|
||||
const [coursesError, setCoursesError] = useState(null);
|
||||
|
||||
const { contentIds } = useContentIdsQuery()
|
||||
// const contentIds = ["f6825391-831c-44da-904a-9ac3d149b7be","f73c37f4-df2e-4f7d-a838-dce568c76136","f538f5c5-1a72-4804-8eb1-3f05cea64874","e58a42c0-c7c6-4b0e-8206-ace7df59a2b8","751ba534-e13a-4ed6-8f8b-452bf482f944","711924b4-3efe-4603-8a23-0ed42c88a63c","42f19d87-3a40-46bb-96b9-e7d31ded89bb","d084d45e-05fa-48fc-afa7-b54499f9e21e","ef588bcb-79a3-4ce9-a370-28c1dc7b604e","5bb34e83-599b-4494-9790-db2ac087baed","67d24075-7cda-4d38-93ad-cd0ef32f13f1","91c15fc0-bb11-43b4-83e6-4b8fd3a826ac","e25f3d3b-f28b-4edd-a325-380564e6db7d","558f88a6-fd1e-4482-9ae7-0f52d7fb82f0","181ed1a5-1f6b-4f68-bb5f-3c2f993f3c72","a0a7d5d2-d416-4bff-9a7f-836b51891fed","38180242-dd5c-4bae-ace4-d46b854d5b7d","5aeb5c26-0d6e-48d7-9436-11ff490a2adc","8b08d474-2ee9-4468-9976-19284c562e13","7d1c7b9b-0ad4-4199-a462-eeb936ea30c9","d607625a-81e1-4098-ba17-068ed29b05ed","e0b93cb8-ba23-4a6b-b7c9-efda9c886b7c","26fb6c60-3655-4193-998d-6e920caead68","4372a797-3565-44ab-a801-042ed5087873","18fd6bfd-fec1-4496-9871-2630b4f3d3b0","f3a61a3e-7523-43ff-9df3-7581c1436c36","b4deaa04-0c78-4526-80ec-362944fe35b6","dbc8672a-d09e-413b-a076-7b86bcc75ca6","5bba9ee9-a37b-496d-b524-e70ebd7140cc","c14bbbde-63b1-4341-a848-f67e07ee8618","e3d7ccfc-0374-46b9-98ff-5526247e13e5","164a7d28-3677-4f68-9fbb-ce2ff5cc4684","89da8522-f8dd-44e2-a49d-7be58328c9ff","03586c4c-5c4a-4bd6-b5e9-bfad02bb22c5","2c79dca4-334b-4805-9e97-fb1a27351580","93f52ce2-ebeb-445b-b698-757815ddb450","ee31bfb2-a2cd-4a31-87e1-da4f3e3c70fa","8cb1d556-df1b-4fef-a625-69c1fe1c397c","1f889e07-0fe2-4944-976d-7e602d3c1fb7","2553ed1a-d8ab-4fa5-a160-4a668a672a5e","80aac9d4-8bef-4a92-9ee9-dea1c2d66c3a","6fe3cb4b-2571-4e3b-9159-db78325ee5cc","a3083ab5-0187-4b77-83d1-29ae1f644559","e5399c72-9b95-46d6-a594-498e673b6c58","f93827ed-68ad-4b5e-af33-f7424b37f0d6","16a65e26-e5d9-450f-9b98-79d539b8acb0","8ce74cf3-bc67-4e95-83b6-a01983a1b586","6d8260b3-c902-46ec-8aed-f3b8c8f1229b"]
|
||||
const {ndk, addSigner} = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -11,6 +11,7 @@ export function useDocuments() {
|
||||
const [documentsError, setDocumentsError] = useState(null);
|
||||
|
||||
const { contentIds } = useContentIdsQuery()
|
||||
// const contentIds = ["f6825391-831c-44da-904a-9ac3d149b7be","f73c37f4-df2e-4f7d-a838-dce568c76136","f538f5c5-1a72-4804-8eb1-3f05cea64874","e58a42c0-c7c6-4b0e-8206-ace7df59a2b8","751ba534-e13a-4ed6-8f8b-452bf482f944","711924b4-3efe-4603-8a23-0ed42c88a63c","42f19d87-3a40-46bb-96b9-e7d31ded89bb","d084d45e-05fa-48fc-afa7-b54499f9e21e","ef588bcb-79a3-4ce9-a370-28c1dc7b604e","5bb34e83-599b-4494-9790-db2ac087baed","67d24075-7cda-4d38-93ad-cd0ef32f13f1","91c15fc0-bb11-43b4-83e6-4b8fd3a826ac","e25f3d3b-f28b-4edd-a325-380564e6db7d","558f88a6-fd1e-4482-9ae7-0f52d7fb82f0","181ed1a5-1f6b-4f68-bb5f-3c2f993f3c72","a0a7d5d2-d416-4bff-9a7f-836b51891fed","38180242-dd5c-4bae-ace4-d46b854d5b7d","5aeb5c26-0d6e-48d7-9436-11ff490a2adc","8b08d474-2ee9-4468-9976-19284c562e13","7d1c7b9b-0ad4-4199-a462-eeb936ea30c9","d607625a-81e1-4098-ba17-068ed29b05ed","e0b93cb8-ba23-4a6b-b7c9-efda9c886b7c","26fb6c60-3655-4193-998d-6e920caead68","4372a797-3565-44ab-a801-042ed5087873","18fd6bfd-fec1-4496-9871-2630b4f3d3b0","f3a61a3e-7523-43ff-9df3-7581c1436c36","b4deaa04-0c78-4526-80ec-362944fe35b6","dbc8672a-d09e-413b-a076-7b86bcc75ca6","5bba9ee9-a37b-496d-b524-e70ebd7140cc","c14bbbde-63b1-4341-a848-f67e07ee8618","e3d7ccfc-0374-46b9-98ff-5526247e13e5","164a7d28-3677-4f68-9fbb-ce2ff5cc4684","89da8522-f8dd-44e2-a49d-7be58328c9ff","03586c4c-5c4a-4bd6-b5e9-bfad02bb22c5","2c79dca4-334b-4805-9e97-fb1a27351580","93f52ce2-ebeb-445b-b698-757815ddb450","ee31bfb2-a2cd-4a31-87e1-da4f3e3c70fa","8cb1d556-df1b-4fef-a625-69c1fe1c397c","1f889e07-0fe2-4944-976d-7e602d3c1fb7","2553ed1a-d8ab-4fa5-a160-4a668a672a5e","80aac9d4-8bef-4a92-9ee9-dea1c2d66c3a","6fe3cb4b-2571-4e3b-9159-db78325ee5cc","a3083ab5-0187-4b77-83d1-29ae1f644559","e5399c72-9b95-46d6-a594-498e673b6c58","f93827ed-68ad-4b5e-af33-f7424b37f0d6","16a65e26-e5d9-450f-9b98-79d539b8acb0","8ce74cf3-bc67-4e95-83b6-a01983a1b586","6d8260b3-c902-46ec-8aed-f3b8c8f1229b"]
|
||||
const {ndk, addSigner} = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -11,6 +11,7 @@ export function useVideos() {
|
||||
const [videosError, setVideosError] = useState(null);
|
||||
|
||||
const { contentIds } = useContentIdsQuery()
|
||||
// const contentIds = ["f6825391-831c-44da-904a-9ac3d149b7be","f73c37f4-df2e-4f7d-a838-dce568c76136","f538f5c5-1a72-4804-8eb1-3f05cea64874","e58a42c0-c7c6-4b0e-8206-ace7df59a2b8","751ba534-e13a-4ed6-8f8b-452bf482f944","711924b4-3efe-4603-8a23-0ed42c88a63c","42f19d87-3a40-46bb-96b9-e7d31ded89bb","d084d45e-05fa-48fc-afa7-b54499f9e21e","ef588bcb-79a3-4ce9-a370-28c1dc7b604e","5bb34e83-599b-4494-9790-db2ac087baed","67d24075-7cda-4d38-93ad-cd0ef32f13f1","91c15fc0-bb11-43b4-83e6-4b8fd3a826ac","e25f3d3b-f28b-4edd-a325-380564e6db7d","558f88a6-fd1e-4482-9ae7-0f52d7fb82f0","181ed1a5-1f6b-4f68-bb5f-3c2f993f3c72","a0a7d5d2-d416-4bff-9a7f-836b51891fed","38180242-dd5c-4bae-ace4-d46b854d5b7d","5aeb5c26-0d6e-48d7-9436-11ff490a2adc","8b08d474-2ee9-4468-9976-19284c562e13","7d1c7b9b-0ad4-4199-a462-eeb936ea30c9","d607625a-81e1-4098-ba17-068ed29b05ed","e0b93cb8-ba23-4a6b-b7c9-efda9c886b7c","26fb6c60-3655-4193-998d-6e920caead68","4372a797-3565-44ab-a801-042ed5087873","18fd6bfd-fec1-4496-9871-2630b4f3d3b0","f3a61a3e-7523-43ff-9df3-7581c1436c36","b4deaa04-0c78-4526-80ec-362944fe35b6","dbc8672a-d09e-413b-a076-7b86bcc75ca6","5bba9ee9-a37b-496d-b524-e70ebd7140cc","c14bbbde-63b1-4341-a848-f67e07ee8618","e3d7ccfc-0374-46b9-98ff-5526247e13e5","164a7d28-3677-4f68-9fbb-ce2ff5cc4684","89da8522-f8dd-44e2-a49d-7be58328c9ff","03586c4c-5c4a-4bd6-b5e9-bfad02bb22c5","2c79dca4-334b-4805-9e97-fb1a27351580","93f52ce2-ebeb-445b-b698-757815ddb450","ee31bfb2-a2cd-4a31-87e1-da4f3e3c70fa","8cb1d556-df1b-4fef-a625-69c1fe1c397c","1f889e07-0fe2-4944-976d-7e602d3c1fb7","2553ed1a-d8ab-4fa5-a160-4a668a672a5e","80aac9d4-8bef-4a92-9ee9-dea1c2d66c3a","6fe3cb4b-2571-4e3b-9159-db78325ee5cc","a3083ab5-0187-4b77-83d1-29ae1f644559","e5399c72-9b95-46d6-a594-498e673b6c58","f93827ed-68ad-4b5e-af33-f7424b37f0d6","16a65e26-e5d9-450f-9b98-79d539b8acb0","8ce74cf3-bc67-4e95-83b6-a01983a1b586","6d8260b3-c902-46ec-8aed-f3b8c8f1229b"]
|
||||
const {ndk, addSigner} = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -36,7 +36,7 @@ export default function MyApp({
|
||||
<Layout>
|
||||
<div className="flex flex-col min-h-screen">
|
||||
<Navbar />
|
||||
<main className="flex-1 container mx-auto px-4 py-4">
|
||||
<main>
|
||||
<Component {...pageProps} />
|
||||
<Analytics />
|
||||
</main>
|
||||
|
@ -1,25 +1,218 @@
|
||||
import Head from 'next/head';
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState, useMemo } from 'react';
|
||||
// import GenericCarousel from '@/components/content/carousels/GenericCarousel';
|
||||
import CoursesCarousel from '@/components/content/carousels/CoursesCarousel';
|
||||
import VideosCarousel from '@/components/content/carousels/VideosCarousel';
|
||||
import DocumentsCarousel from '@/components/content/carousels/DocumentsCarousel';
|
||||
import { parseEvent, parseCourseEvent } from '@/utils/nostr';
|
||||
import { useDocuments } from '@/hooks/nostr/useDocuments';
|
||||
import { useVideos } from '@/hooks/nostr/useVideos';
|
||||
import { useCourses } from '@/hooks/nostr/useCourses';
|
||||
import { TabMenu } from 'primereact/tabmenu';
|
||||
import 'primeicons/primeicons.css';
|
||||
import GenericButton from '@/components/buttons/GenericButton';
|
||||
import { useRouter } from 'next/router';
|
||||
import HeroBanner from '@/components/banner/HeroBanner';
|
||||
|
||||
const TOP_CONTENT_IDS = [
|
||||
"72aa9f48-a0d1-4e0e-ba6b-de3e8ef8e9ad",
|
||||
"d493fc22-20ab-47fc-ab55-b017b92bb0fe",
|
||||
"936a024a-719c-455c-8c9d-2657ebd8a5f0",
|
||||
"dfa1e4ed-1387-418d-a166-84dbdb9701df",
|
||||
"f806c5c6-7b88-4be6-911e-0f7e08a0dac2",
|
||||
"ad217a77-7422-45eb-979e-fe8cefd89a1f",
|
||||
"3dcc434a-7b65-4cf4-883a-db117fe97b77",
|
||||
"e0495afa-d879-47d8-a8be-843785e47611",
|
||||
"8670318e-91d0-443f-9ceb-8324cd1bdabc",
|
||||
"5d67444d-0b91-423b-b927-3def8535adc8"
|
||||
];
|
||||
|
||||
const MenuTab = ({ selectedTopic, onTabChange, allTopics }) => {
|
||||
const router = useRouter();
|
||||
|
||||
// Define the hardcoded priority items that always appear first
|
||||
const priorityItems = ['Top', 'Courses', 'Videos', 'Documents', 'Free', 'Paid'];
|
||||
// Items that should be filtered out from topics
|
||||
const blacklistedItems = ['document', 'video', 'course'];
|
||||
|
||||
// Get dynamic topics, excluding hardcoded and blacklisted items
|
||||
const otherItems = allTopics.filter(item =>
|
||||
!priorityItems.includes(item) &&
|
||||
!blacklistedItems.includes(item)
|
||||
);
|
||||
|
||||
// Only take the first 4 dynamic topics to keep the menu clean
|
||||
// Additional topics will be accessible through the "More" page
|
||||
const limitedOtherItems = otherItems.slice(0, 8);
|
||||
|
||||
// Combine all menu items: priority items + up to 4 dynamic topics + More
|
||||
const allItems = [...priorityItems, ...limitedOtherItems, 'More'];
|
||||
|
||||
const menuItems = allItems.map((item) => {
|
||||
let icon = 'pi pi-tag';
|
||||
if (item === 'Top') icon = 'pi pi-star';
|
||||
else if (item === 'Documents') icon = 'pi pi-file';
|
||||
else if (item === 'Videos') icon = 'pi pi-video';
|
||||
else if (item === 'Courses') icon = 'pi pi-desktop';
|
||||
else if (item === 'Free') icon = 'pi pi-lock-open';
|
||||
else if (item === 'Paid') icon = 'pi pi-lock';
|
||||
else if (item === 'More') icon = 'pi pi-ellipsis-h';
|
||||
|
||||
const isMore = item === 'More';
|
||||
const path = isMore ? '/content?tag=all' : item === 'Top' ? '/' : `/content?tag=${item.toLowerCase()}`;
|
||||
|
||||
return {
|
||||
label: (
|
||||
<GenericButton
|
||||
className={`${selectedTopic === item ? 'bg-primary text-white' : ''}`}
|
||||
onClick={() => {
|
||||
onTabChange(item);
|
||||
router.push(path);
|
||||
}}
|
||||
outlined={selectedTopic !== item}
|
||||
rounded
|
||||
size='small'
|
||||
label={item}
|
||||
icon={icon}
|
||||
/>
|
||||
),
|
||||
command: () => {
|
||||
onTabChange(item);
|
||||
router.push(path);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<TabMenu
|
||||
model={menuItems}
|
||||
activeIndex={allItems.indexOf(selectedTopic)}
|
||||
onTabChange={(e) => onTabChange(allItems[e.index])}
|
||||
pt={{
|
||||
menu: { className: 'bg-transparent border-none my-2 mb-4' },
|
||||
action: ({ context, parent }) => ({
|
||||
className: 'cursor-pointer select-none flex items-center relative no-underline overflow-hidden border-b-2 p-2 font-bold rounded-t-lg',
|
||||
style: { top: '2px' }
|
||||
}),
|
||||
menuitem: { className: 'mr-0' }
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>PlebDevs</title>
|
||||
<meta name="description" content="Build on Bitcoin" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<main>
|
||||
<HeroBanner />
|
||||
<CoursesCarousel />
|
||||
<VideosCarousel />
|
||||
<DocumentsCarousel />
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
const router = useRouter();
|
||||
const { documents, documentsLoading } = useDocuments();
|
||||
const { videos, videosLoading } = useVideos();
|
||||
const { courses, coursesLoading } = useCourses();
|
||||
|
||||
const [processedDocuments, setProcessedDocuments] = useState([]);
|
||||
const [processedVideos, setProcessedVideos] = useState([]);
|
||||
const [processedCourses, setProcessedCourses] = useState([]);
|
||||
const [allContent, setAllContent] = useState([]);
|
||||
const [allTopics, setAllTopics] = useState([]);
|
||||
const [selectedTopic, setSelectedTopic] = useState('Top');
|
||||
const [filteredContent, setFilteredContent] = useState([]);
|
||||
|
||||
const memoizedFilteredContent = useMemo(() => filteredContent, [filteredContent]);
|
||||
|
||||
useEffect(() => {
|
||||
if (documents && !documentsLoading) {
|
||||
const processedDocuments = documents.map(document => ({...parseEvent(document), type: 'document'}));
|
||||
setProcessedDocuments(processedDocuments);
|
||||
}
|
||||
}, [documents, documentsLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
if (videos && !videosLoading) {
|
||||
const processedVideos = videos.map(video => ({...parseEvent(video), type: 'video'}));
|
||||
setProcessedVideos(processedVideos);
|
||||
}
|
||||
}, [videos, videosLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
if (courses && !coursesLoading) {
|
||||
const processedCourses = courses.map(course => ({...parseCourseEvent(course), type: 'course'}));
|
||||
setProcessedCourses(processedCourses);
|
||||
}
|
||||
}, [courses, coursesLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
const allContent = [...processedDocuments, ...processedVideos, ...processedCourses];
|
||||
setAllContent(allContent);
|
||||
|
||||
const uniqueTopics = new Set(allContent.map(item => item.topics).flat());
|
||||
const otherTopics = Array.from(uniqueTopics).filter(topic =>
|
||||
!['Top', 'Courses', 'Videos', 'Documents', 'Free', 'Paid', 'More'].includes(topic) &&
|
||||
!['document', 'video', 'course'].includes(topic)
|
||||
);
|
||||
setAllTopics(otherTopics);
|
||||
|
||||
if (selectedTopic === 'Top') {
|
||||
const topContent = allContent.filter(item => TOP_CONTENT_IDS.includes(item.d));
|
||||
setFilteredContent(topContent);
|
||||
} else {
|
||||
filterContent(selectedTopic, allContent);
|
||||
}
|
||||
}, [processedDocuments, processedVideos, processedCourses, selectedTopic]);
|
||||
|
||||
const filterContent = (topic, content) => {
|
||||
let filtered = content;
|
||||
if (topic !== 'Top' && topic !== 'More') {
|
||||
const topicLower = topic.toLowerCase();
|
||||
if (['courses', 'videos', 'documents'].includes(topicLower)) {
|
||||
filtered = content.filter(item => item.type === topicLower.slice(0, -1));
|
||||
} else if (topicLower === 'free') {
|
||||
filtered = content.filter(item => !item.price || Number(item.price) === 0);
|
||||
} else if (topicLower === 'paid') {
|
||||
filtered = content.filter(item => item.price && Number(item.price) > 0);
|
||||
} else {
|
||||
filtered = content.filter(item => item.topics && item.topics.includes(topicLower));
|
||||
}
|
||||
}
|
||||
setFilteredContent(filtered);
|
||||
};
|
||||
|
||||
const handleTopicChange = (newTopic) => {
|
||||
setSelectedTopic(newTopic);
|
||||
if (newTopic === 'Top') {
|
||||
const topContent = allContent.filter(item => TOP_CONTENT_IDS.includes(item.d));
|
||||
setFilteredContent(topContent);
|
||||
router.push('/');
|
||||
} else if (newTopic === 'More') {
|
||||
router.push('/content?tag=all');
|
||||
} else {
|
||||
filterContent(newTopic, allContent);
|
||||
router.push(`/content?tag=${newTopic.toLowerCase()}`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>PlebDevs</title>
|
||||
<meta name="description" content="Build on Bitcoin" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<main>
|
||||
<HeroBanner />
|
||||
<div className="w-full px-12">
|
||||
<MenuTab
|
||||
selectedTopic={selectedTopic}
|
||||
onTabChange={handleTopicChange}
|
||||
allTopics={allTopics}
|
||||
className="max-w-[90%] mx-auto"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full px-4">
|
||||
<CoursesCarousel />
|
||||
<VideosCarousel />
|
||||
<DocumentsCarousel />
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user