mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-23 16:05:24 +00:00
Consistent widths accross pages aligning with navbar
This commit is contained in:
parent
d353e948f7
commit
d3092f56af
@ -27,6 +27,7 @@ export default function GenericCarousel({items, selectedTopic, title}) {
|
|||||||
return `${type}-${baseKey}-${index}`;
|
return `${type}-${baseKey}-${index}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// todo: max sizing for single peice of content being shown
|
||||||
const renderItem = (item, index) => {
|
const renderItem = (item, index) => {
|
||||||
if (!item) return <TemplateSkeleton key={generateUniqueTemplateKey(item, index, 'skeleton')} />;
|
if (!item) return <TemplateSkeleton key={generateUniqueTemplateKey(item, index, 'skeleton')} />;
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ export default function GenericCarousel({items, selectedTopic, title}) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full px-4 mb-4">
|
<div className="w-full mb-4">
|
||||||
<div className="grid grid-cols-2 gap-4 max-w-full max-tab:grid-cols-1 lg:grid-cols-3">
|
<div className="grid grid-cols-2 gap-4 max-w-full max-tab:grid-cols-1 lg:grid-cols-3">
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<div key={generateUniqueTemplateKey(item, index, 'container')} className="w-full min-w-0">
|
<div key={generateUniqueTemplateKey(item, index, 'container')} className="w-full min-w-0">
|
||||||
|
@ -15,7 +15,7 @@ const DiscordFeed = ({ searchQuery }) => {
|
|||||||
if (!data) return [];
|
if (!data) return [];
|
||||||
return data
|
return data
|
||||||
.filter(message =>
|
.filter(message =>
|
||||||
message.content.toLowerCase().includes(searchQuery.toLowerCase())
|
searchQuery ? message.content.toLowerCase().includes(searchQuery.toLowerCase()) : true
|
||||||
)
|
)
|
||||||
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
|
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
|
||||||
}, [data, searchQuery]);
|
}, [data, searchQuery]);
|
||||||
@ -33,8 +33,8 @@ const DiscordFeed = ({ searchQuery }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full min-bottom-bar:w-[86vw]">
|
<div className="h-full w-full">
|
||||||
<div className="mx-4">
|
<div className="mx-0">
|
||||||
{filteredData.length > 0 ? (
|
{filteredData.length > 0 ? (
|
||||||
filteredData.map(message => (
|
filteredData.map(message => (
|
||||||
<CommunityMessage
|
<CommunityMessage
|
||||||
|
@ -98,6 +98,7 @@ const GlobalFeed = ({searchQuery}) => {
|
|||||||
const dateB = b.type === 'nostr' ? b.created_at * 1000 : new Date(b.timestamp || b.createdAt);
|
const dateB = b.type === 'nostr' ? b.created_at * 1000 : new Date(b.timestamp || b.createdAt);
|
||||||
return dateB - dateA;
|
return dateB - dateA;
|
||||||
}).filter(item => {
|
}).filter(item => {
|
||||||
|
if (!searchQuery) return true;
|
||||||
const searchLower = searchQuery.toLowerCase();
|
const searchLower = searchQuery.toLowerCase();
|
||||||
if (item.type === 'discord' || item.type === 'nostr') {
|
if (item.type === 'discord' || item.type === 'nostr') {
|
||||||
return item.content.toLowerCase().includes(searchLower);
|
return item.content.toLowerCase().includes(searchLower);
|
||||||
@ -108,8 +109,8 @@ const GlobalFeed = ({searchQuery}) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full min-bottom-bar:w-[86vw]">
|
<div className="h-full w-full">
|
||||||
<div className="mx-4 mt-4">
|
<div className="mx-0 mt-4">
|
||||||
{combinedFeed.length > 0 ? (
|
{combinedFeed.length > 0 ? (
|
||||||
combinedFeed.map(item => (
|
combinedFeed.map(item => (
|
||||||
<CommunityMessage
|
<CommunityMessage
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import { InputTextarea } from 'primereact/inputtextarea';
|
import { InputTextarea } from 'primereact/inputtextarea';
|
||||||
import GenericButton from '@/components/buttons/GenericButton';
|
import GenericButton from '@/components/buttons/GenericButton';
|
||||||
import { Panel } from 'primereact/panel';
|
|
||||||
import { useNDKContext } from "@/context/NDKContext";
|
import { useNDKContext } from "@/context/NDKContext";
|
||||||
import { NDKEvent } from "@nostr-dev-kit/ndk";
|
import { NDKEvent } from "@nostr-dev-kit/ndk";
|
||||||
import { finalizeEvent, verifyEvent } from 'nostr-tools/pure'
|
import { finalizeEvent, verifyEvent } from 'nostr-tools/pure'
|
||||||
@ -12,21 +11,54 @@ import { useSession } from 'next-auth/react';
|
|||||||
|
|
||||||
const MessageInput = () => {
|
const MessageInput = () => {
|
||||||
const [message, setMessage] = useState('');
|
const [message, setMessage] = useState('');
|
||||||
const [collapsed, setCollapsed] = useState(true);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const { ndk, addSigner } = useNDKContext();
|
const { ndk, addSigner } = useNDKContext();
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
|
const pool = useRef(null);
|
||||||
|
|
||||||
|
// Initialize pool when needed
|
||||||
|
const getPool = async () => {
|
||||||
|
if (!pool.current) {
|
||||||
|
pool.current = new SimplePool();
|
||||||
|
}
|
||||||
|
return pool.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
const publishToRelay = async (relay, event, currentPool) => {
|
||||||
|
try {
|
||||||
|
// Wait for relay connection
|
||||||
|
await currentPool.ensureRelay(relay);
|
||||||
|
// Try to publish
|
||||||
|
await currentPool.publish([relay], event);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(`Failed to publish to ${relay}:`, err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (session && session?.user && session.user?.privkey) {
|
if (!message.trim()) return;
|
||||||
handleManualSubmit(session.user.privkey);
|
if (isSubmitting) return;
|
||||||
} else {
|
|
||||||
handleExtensionSubmit();
|
try {
|
||||||
|
setIsSubmitting(true);
|
||||||
|
if (session && session?.user && session.user?.privkey) {
|
||||||
|
await handleManualSubmit(session.user.privkey);
|
||||||
|
} else {
|
||||||
|
await handleExtensionSubmit();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error submitting message:", error);
|
||||||
|
showToast('error', 'Error', 'There was an error sending your message. Please try again.');
|
||||||
|
} finally {
|
||||||
|
setIsSubmitting(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleExtensionSubmit = async () => {
|
const handleExtensionSubmit = async () => {
|
||||||
if (!message.trim() || !ndk) return;
|
if (!ndk) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!ndk.signer) {
|
if (!ndk.signer) {
|
||||||
@ -39,10 +71,10 @@ const MessageInput = () => {
|
|||||||
|
|
||||||
await event.publish();
|
await event.publish();
|
||||||
showToast('success', 'Message Sent', 'Your message has been sent to the PlebDevs community.');
|
showToast('success', 'Message Sent', 'Your message has been sent to the PlebDevs community.');
|
||||||
setMessage(''); // Clear the input after successful publish
|
setMessage('');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error publishing message:", error);
|
console.error("Error publishing message:", error);
|
||||||
showToast('error', 'Error', 'There was an error sending your message. Please try again.');
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,66 +87,62 @@ const MessageInput = () => {
|
|||||||
['t', 'plebdevs']
|
['t', 'plebdevs']
|
||||||
],
|
],
|
||||||
content: message,
|
content: message,
|
||||||
}, privkey)
|
}, privkey);
|
||||||
|
|
||||||
let isGood = verifyEvent(event);
|
let isGood = verifyEvent(event);
|
||||||
|
if (!isGood) {
|
||||||
|
throw new Error('Event verification failed');
|
||||||
|
}
|
||||||
|
|
||||||
if (isGood) {
|
try {
|
||||||
const pool = new SimplePool();
|
const currentPool = await getPool();
|
||||||
const published = await pool.publish(appConfig.defaultRelayUrls, event);
|
let publishedToAny = false;
|
||||||
if (published) {
|
|
||||||
|
// Try to publish to each relay sequentially
|
||||||
|
for (const relay of appConfig.defaultRelayUrls) {
|
||||||
|
const success = await publishToRelay(relay, event, currentPool);
|
||||||
|
if (success) {
|
||||||
|
publishedToAny = true;
|
||||||
|
break; // Stop after first successful publish
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publishedToAny) {
|
||||||
showToast('success', 'Message Sent', 'Your message has been sent to the PlebDevs community.');
|
showToast('success', 'Message Sent', 'Your message has been sent to the PlebDevs community.');
|
||||||
setMessage('');
|
setMessage('');
|
||||||
} else {
|
} else {
|
||||||
showToast('error', 'Error', 'There was an error sending your message. Please try again.');
|
throw new Error('Failed to publish to any relay');
|
||||||
}
|
}
|
||||||
} else {
|
} catch (err) {
|
||||||
showToast('error', 'Error', 'There was an error sending your message. Please try again.');
|
console.error("Publishing error:", err);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error finalizing event:", error);
|
console.error("Error finalizing event:", error);
|
||||||
showToast('error', 'Error', 'There was an error sending your message. Please try again.');
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerTemplate = (options) => {
|
|
||||||
return (
|
|
||||||
<div className="flex align-items-center justify-content-between my-1 py-2">
|
|
||||||
<GenericButton outlined severity="primary" size="small" className="py-0" onClick={options.onTogglerClick} icon={options.collapsed ? 'pi pi-chevron-down' : 'pi pi-chevron-up'} />
|
|
||||||
<h2 className="m-0 ml-2">New Message</h2>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel
|
<div className="flex flex-row items-center gap-2">
|
||||||
headerTemplate={headerTemplate}
|
<InputTextarea
|
||||||
toggleable
|
value={message}
|
||||||
collapsed={collapsed}
|
onChange={(e) => setMessage(e.target.value)}
|
||||||
onToggle={(e) => setCollapsed(e.value)}
|
rows={1}
|
||||||
className="w-full"
|
autoResize
|
||||||
>
|
placeholder="Type your message here..."
|
||||||
<div className="w-full flex flex-col">
|
className="flex-1 bg-[#1e2732] border-[#2e3b4e] rounded-lg"
|
||||||
<InputTextarea
|
disabled={isSubmitting}
|
||||||
value={message}
|
/>
|
||||||
onChange={(e) => setMessage(e.target.value)}
|
<GenericButton
|
||||||
rows={2}
|
icon="pi pi-send"
|
||||||
cols={10}
|
outlined
|
||||||
autoResize
|
onClick={handleSubmit}
|
||||||
placeholder="Type your message here..."
|
className="h-full"
|
||||||
className="w-full"
|
disabled={isSubmitting || !message.trim()}
|
||||||
/>
|
loading={isSubmitting}
|
||||||
</div>
|
/>
|
||||||
<div className="w-full flex flex-row justify-end mt-4">
|
</div>
|
||||||
<GenericButton
|
|
||||||
label="Send"
|
|
||||||
icon="pi pi-send"
|
|
||||||
outlined
|
|
||||||
onClick={handleSubmit}
|
|
||||||
className="w-fit py-2"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Panel>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,13 +72,13 @@ const NostrFeed = ({ searchQuery }) => {
|
|||||||
|
|
||||||
const filteredNotes = communityNotes
|
const filteredNotes = communityNotes
|
||||||
.filter(message =>
|
.filter(message =>
|
||||||
message.content.toLowerCase().includes(searchQuery.toLowerCase())
|
searchQuery ? message.content.toLowerCase().includes(searchQuery.toLowerCase()) : true
|
||||||
)
|
)
|
||||||
.sort((a, b) => b.created_at - a.created_at);
|
.sort((a, b) => b.created_at - a.created_at);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full min-bottom-bar:w-[86vw]">
|
<div className="h-full w-full">
|
||||||
<div className="mx-4 mt-4">
|
<div className="mx-0 mt-4">
|
||||||
{filteredNotes.length > 0 ? (
|
{filteredNotes.length > 0 ? (
|
||||||
filteredNotes.map(message => (
|
filteredNotes.map(message => (
|
||||||
<CommunityMessage
|
<CommunityMessage
|
||||||
|
@ -36,13 +36,13 @@ const StackerNewsFeed = ({ searchQuery }) => {
|
|||||||
|
|
||||||
const filteredItems = items
|
const filteredItems = items
|
||||||
.filter(item =>
|
.filter(item =>
|
||||||
item.title.toLowerCase().includes(searchQuery.toLowerCase())
|
searchQuery ? item.title.toLowerCase().includes(searchQuery.toLowerCase()) : true
|
||||||
)
|
)
|
||||||
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full min-bottom-bar:w-[86vw]">
|
<div className="h-full w-full">
|
||||||
<div className="mx-4 mt-4">
|
<div className="mx-0 mt-4">
|
||||||
{filteredItems && filteredItems.length > 0 ? (
|
{filteredItems && filteredItems.length > 0 ? (
|
||||||
filteredItems.map(item => (
|
filteredItems.map(item => (
|
||||||
<CommunityMessage
|
<CommunityMessage
|
||||||
|
@ -144,7 +144,9 @@ const CommunityMessage = ({ message, searchQuery, windowWidth, platform }) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p className="m-0 text-lg text-gray-200 break-words">{highlightText(message.content, searchQuery)}</p>
|
<p className="m-0 text-lg text-gray-200 break-words">
|
||||||
|
{searchQuery ? highlightText(message.content, searchQuery) : message.content}
|
||||||
|
</p>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -52,9 +52,9 @@ const CommunityMenuTab = ({ selectedTopic, onTabChange }) => {
|
|||||||
activeIndex={allItems.indexOf(selectedTopic)}
|
activeIndex={allItems.indexOf(selectedTopic)}
|
||||||
onTabChange={(e) => onTabChange(allItems[e.index])}
|
onTabChange={(e) => onTabChange(allItems[e.index])}
|
||||||
pt={{
|
pt={{
|
||||||
menu: { className: 'bg-transparent border-none ml-2 my-4 py-1' },
|
menu: { className: 'bg-transparent border-none my-1 py-1' },
|
||||||
action: ({ context, parent }) => ({
|
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',
|
className: 'cursor-pointer select-none flex items-center relative no-underline overflow-hidden border-b-2 p-2 pl-[4px] font-bold rounded-t-lg',
|
||||||
style: { top: '2px' }
|
style: { top: '2px' }
|
||||||
}),
|
}),
|
||||||
menuitem: { className: 'mr-0' }
|
menuitem: { className: 'mr-0' }
|
||||||
|
@ -27,7 +27,7 @@ const Navbar = () => {
|
|||||||
{
|
{
|
||||||
label: 'Feeds',
|
label: 'Feeds',
|
||||||
icon: 'pi pi-comments',
|
icon: 'pi pi-comments',
|
||||||
command: () => router.push('/feeds?channel=global')
|
command: () => router.push('/feed?channel=global')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Subscribe',
|
label: 'Subscribe',
|
||||||
@ -49,9 +49,9 @@ const Navbar = () => {
|
|||||||
src="/images/plebdevs-icon.png"
|
src="/images/plebdevs-icon.png"
|
||||||
width={50}
|
width={50}
|
||||||
height={50}
|
height={50}
|
||||||
className="rounded-full mr-2 max-tab:hidden max-mob:hidden"
|
className="rounded-full max-tab:hidden max-mob:hidden"
|
||||||
/>
|
/>
|
||||||
<h1 className="text-white text-xl font-semibold max-tab:text-2xl max-mob:text-2xl pb-1">PlebDevs</h1>
|
<h1 className="text-white text-xl font-semibold max-tab:text-2xl max-mob:text-2xl pb-1 pl-2">PlebDevs</h1>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`ml-2 p-2 cursor-pointer transition-all duration-300 flex items-center justify-center ${isHovered ? 'bg-gray-700 rounded-full' : ''}`}
|
className={`ml-2 p-2 cursor-pointer transition-all duration-300 flex items-center justify-center ${isHovered ? 'bg-gray-700 rounded-full' : ''}`}
|
||||||
@ -83,7 +83,7 @@ const Navbar = () => {
|
|||||||
<Menubar
|
<Menubar
|
||||||
start={start}
|
start={start}
|
||||||
end={UserAvatar}
|
end={UserAvatar}
|
||||||
className='px-6 py-8 bg-gray-800 border-t-0 border-l-0 border-r-0 rounded-none fixed z-10 w-[100vw] max-tab:px-[5%] max-mob:px-[5%]'
|
className='px-10 py-8 bg-gray-800 border-t-0 border-l-0 border-r-0 rounded-none fixed z-10 w-[100vw] max-tab:px-[5%] max-mob:px-[5%]'
|
||||||
style={{ height: navbarHeight }}
|
style={{ height: navbarHeight }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-right: 8px;
|
|
||||||
height: 50px;
|
height: 50px;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import React, { useRef, useState, useEffect } from 'react';
|
import React, { useRef, useState, useEffect } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { Avatar } from 'primereact/avatar';
|
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useImageProxy } from '@/hooks/useImageProxy';
|
import { useImageProxy } from '@/hooks/useImageProxy';
|
||||||
import GenericButton from '@/components/buttons/GenericButton';
|
import GenericButton from '@/components/buttons/GenericButton';
|
||||||
import { Menu } from 'primereact/menu';
|
import { Menu } from 'primereact/menu';
|
||||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||||
import { useSession, signOut } from 'next-auth/react';
|
import { useSession, signOut } from 'next-auth/react';
|
||||||
import { ProgressSpinner } from 'primereact/progressspinner';
|
|
||||||
import { useIsAdmin } from '@/hooks/useIsAdmin';
|
import { useIsAdmin } from '@/hooks/useIsAdmin';
|
||||||
import 'primereact/resources/primereact.min.css';
|
import 'primereact/resources/primereact.min.css';
|
||||||
import 'primeicons/primeicons.css';
|
import 'primeicons/primeicons.css';
|
||||||
|
@ -113,7 +113,7 @@ const UserContent = () => {
|
|||||||
const isError = coursesError || documentsError || videosError || draftsError || contentIdsError || courseDraftsError;
|
const isError = coursesError || documentsError || videosError || draftsError || contentIdsError || courseDraftsError;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4">
|
<div className="py-4 px-1">
|
||||||
{
|
{
|
||||||
windowWidth < 768 && (
|
windowWidth < 768 && (
|
||||||
<h1 className="text-3xl font-bold mb-6">My Content</h1>
|
<h1 className="text-3xl font-bold mb-6">My Content</h1>
|
||||||
|
@ -32,7 +32,7 @@ const UserProfile = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
user && (
|
user && (
|
||||||
<div className="p-4">
|
<div className="py-4 px-1">
|
||||||
{
|
{
|
||||||
windowWidth < 768 && (
|
windowWidth < 768 && (
|
||||||
<h1 className="text-3xl font-bold mb-6">Profile</h1>
|
<h1 className="text-3xl font-bold mb-6">Profile</h1>
|
||||||
|
@ -19,7 +19,7 @@ const UserSettings = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
user && (
|
user && (
|
||||||
<div className="p-4">
|
<div className="py-4 px-1">
|
||||||
{windowWidth < 768 && (
|
{windowWidth < 768 && (
|
||||||
<h1 className="text-3xl font-bold mb-6">Settings</h1>
|
<h1 className="text-3xl font-bold mb-6">Settings</h1>
|
||||||
)}
|
)}
|
||||||
|
@ -93,7 +93,7 @@ const UserSubscription = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4">
|
<div className="py-4 px-1">
|
||||||
{windowWidth < 768 && (
|
{windowWidth < 768 && (
|
||||||
<h1 className="text-3xl font-bold mb-6">Subscription Management</h1>
|
<h1 className="text-3xl font-bold mb-6">Subscription Management</h1>
|
||||||
)}
|
)}
|
||||||
|
@ -66,7 +66,7 @@ const SearchBar = () => {
|
|||||||
|
|
||||||
const handleContentSelect = (content) => {
|
const handleContentSelect = (content) => {
|
||||||
if (content?.type === 'course') {
|
if (content?.type === 'course') {
|
||||||
router.push(`/course/${content.id}`);
|
router.push(`/course/${content?.d || content?.id}`);
|
||||||
} else {
|
} else {
|
||||||
router.push(`/details/${content.id}`);
|
router.push(`/details/${content.id}`);
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,8 @@ const AboutPage = () => {
|
|||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
const windowWidth = useWindowWidth();
|
const windowWidth = useWindowWidth();
|
||||||
|
|
||||||
const isTabView = windowWidth <= 1360;
|
const isTabView = windowWidth <= 1160;
|
||||||
const isMobile = windowWidth < 768;
|
const isMobile = windowWidth < 668;
|
||||||
|
|
||||||
const copyToClipboard = async (text) => {
|
const copyToClipboard = async (text) => {
|
||||||
try {
|
try {
|
||||||
@ -32,7 +32,7 @@ const AboutPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${isTabView ? 'w-full' : 'w-[83vw]'} ${isMobile ? 'p-0' : 'p-4'} mx-auto`}>
|
<div className={`${isTabView ? 'w-full' : 'w-full px-12'} ${isMobile ? 'p-0' : 'p-4'} mx-auto`}>
|
||||||
<InteractivePromotionalCarousel />
|
<InteractivePromotionalCarousel />
|
||||||
<Card title="Key Features" className={`mb-4 ${isMobile ? 'm-2' : null}`}>
|
<Card title="Key Features" className={`mb-4 ${isMobile ? 'm-2' : null}`}>
|
||||||
<div className="flex flex-col gap-4 max-w-[80%] max-mob:max-w-full">
|
<div className="flex flex-col gap-4 max-w-[80%] max-mob:max-w-full">
|
||||||
|
@ -58,9 +58,9 @@ const MenuTab = ({ items, selectedTopic, onTabChange }) => {
|
|||||||
activeIndex={allItems.indexOf(selectedTopic)}
|
activeIndex={allItems.indexOf(selectedTopic)}
|
||||||
onTabChange={(e) => onTabChange(allItems[e.index])}
|
onTabChange={(e) => onTabChange(allItems[e.index])}
|
||||||
pt={{
|
pt={{
|
||||||
menu: { className: 'bg-transparent border-none ml-2 my-4 py-1' },
|
menu: { className: 'bg-transparent border-none my-2 py-1' },
|
||||||
action: ({ context, parent }) => ({
|
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',
|
className: 'cursor-pointer select-none flex items-center relative no-underline overflow-hidden border-b-2 p-2 pl-1 font-bold rounded-t-lg',
|
||||||
style: { top: '2px' }
|
style: { top: '2px' }
|
||||||
}),
|
}),
|
||||||
menuitem: { className: 'mr-0' }
|
menuitem: { className: 'mr-0' }
|
||||||
@ -156,7 +156,7 @@ const ContentPage = () => {
|
|||||||
router.push(`/content${queryParam}`, undefined, { shallow: true });
|
router.push(`/content${queryParam}`, undefined, { shallow: true });
|
||||||
filterContent(newTopic, allContent);
|
filterContent(newTopic, allContent);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderCarousels = () => {
|
const renderCarousels = () => {
|
||||||
return (
|
return (
|
||||||
<GenericCarousel
|
<GenericCarousel
|
||||||
@ -170,15 +170,14 @@ const ContentPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full px-4">
|
<div className="w-full px-10 max-mob:px-1">
|
||||||
<div className="w-fit mx-4 mt-8 flex flex-col items-start">
|
<div className="w-fit mt-8 flex flex-col items-start">
|
||||||
<h1 className="text-3xl font-bold mb-4 ml-1">All Content</h1>
|
<h1 className="text-3xl font-bold mb-4 ml-2">All Content</h1>
|
||||||
</div>
|
</div>
|
||||||
<MenuTab
|
<MenuTab
|
||||||
items={allTopics}
|
items={allTopics}
|
||||||
selectedTopic={selectedTopic}
|
selectedTopic={selectedTopic}
|
||||||
onTabChange={handleTopicChange}
|
onTabChange={handleTopicChange}
|
||||||
className="max-w-[90%] mx-auto"
|
|
||||||
/>
|
/>
|
||||||
{renderCarousels()}
|
{renderCarousels()}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { InputText } from 'primereact/inputtext';
|
|
||||||
import CommunityMenuTab from '@/components/menutab/CommunityMenuTab';
|
import CommunityMenuTab from '@/components/menutab/CommunityMenuTab';
|
||||||
import NostrFeed from '@/components/feeds/NostrFeed';
|
import NostrFeed from '@/components/feeds/NostrFeed';
|
||||||
import DiscordFeed from '@/components/feeds/DiscordFeed';
|
import DiscordFeed from '@/components/feeds/DiscordFeed';
|
||||||
@ -17,7 +16,6 @@ const Feed = () => {
|
|||||||
const [selectedTopic, setSelectedTopic] = useState('global');
|
const [selectedTopic, setSelectedTopic] = useState('global');
|
||||||
const [title, setTitle] = useState('Community');
|
const [title, setTitle] = useState('Community');
|
||||||
const allTopics = ['global', 'nostr', 'discord', 'stackernews'];
|
const allTopics = ['global', 'nostr', 'discord', 'stackernews'];
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -50,38 +48,31 @@ const Feed = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-5xl mx-auto">
|
<div className="w-full mx-auto px-10">
|
||||||
<div className="mb-6">
|
<div className="mb-2">
|
||||||
<div className='mb-4 flex flex-row items-end'>
|
<div className='flex flex-col'>
|
||||||
<h1 className="font-bold mb-0">Feeds</h1>
|
<div className='my-4 flex flex-row items-end'>
|
||||||
<GenericButton
|
<h1 className="font-bold mb-0">Feeds</h1>
|
||||||
icon={getTagIcon(title)}
|
<GenericButton
|
||||||
className='ml-2 text-sm p-2 py-1 flex items-center cursor-default hover:bg-transparent'
|
icon={getTagIcon(title)}
|
||||||
outlined
|
className='ml-2 text-sm p-2 py-1 flex items-center cursor-default hover:bg-transparent'
|
||||||
severity={{
|
outlined
|
||||||
'global': 'success',
|
severity={{
|
||||||
'discord': 'primary',
|
'global': 'success',
|
||||||
'stackernews': 'warning',
|
'discord': 'primary',
|
||||||
'nostr': 'help'
|
'stackernews': 'warning',
|
||||||
}[title] || 'info'}
|
'nostr': 'help'
|
||||||
label={`${title}`}
|
}[title] || 'info'}
|
||||||
/>
|
label={`${title}`}
|
||||||
</div>
|
/>
|
||||||
<div className='w-full flex flex-row items-center justify-between mb-2'>
|
</div>
|
||||||
<InputText
|
{selectedTopic === 'nostr' && (
|
||||||
value={searchQuery}
|
<div className='w-full mt-2'>
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
<MessageInput />
|
||||||
placeholder="Search"
|
</div>
|
||||||
icon="pi pi-search"
|
)}
|
||||||
className="w-fit"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<Divider />
|
<Divider />
|
||||||
{selectedTopic === 'nostr' && (
|
|
||||||
<MessageInput
|
|
||||||
collapsed={false}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<CommunityMenuTab
|
<CommunityMenuTab
|
||||||
items={allTopics}
|
items={allTopics}
|
||||||
@ -90,10 +81,10 @@ const Feed = () => {
|
|||||||
className="mb-4"
|
className="mb-4"
|
||||||
/>
|
/>
|
||||||
<div className="feed-content">
|
<div className="feed-content">
|
||||||
{selectedTopic === 'global' && <GlobalFeed searchQuery={searchQuery} />}
|
{selectedTopic === 'global' && <GlobalFeed />}
|
||||||
{selectedTopic === 'nostr' && <NostrFeed searchQuery={searchQuery} />}
|
{selectedTopic === 'nostr' && <NostrFeed />}
|
||||||
{selectedTopic === 'discord' && <DiscordFeed searchQuery={searchQuery} />}
|
{selectedTopic === 'discord' && <DiscordFeed />}
|
||||||
{selectedTopic === 'stackernews' && <StackerNewsFeed searchQuery={searchQuery} />}
|
{selectedTopic === 'stackernews' && <StackerNewsFeed />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -53,7 +53,7 @@ const Profile = () => {
|
|||||||
if (!session) return null;
|
if (!session) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full min-h-full min-bottom-bar:w-[86vw] mx-auto">
|
<div className="w-full min-h-full mx-auto px-10">
|
||||||
<TabView
|
<TabView
|
||||||
pt={{
|
pt={{
|
||||||
root: {
|
root: {
|
||||||
|
@ -123,7 +123,7 @@ const Subscribe = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4">
|
<div className="w-full px-12 my-4">
|
||||||
{windowWidth < 768 && (
|
{windowWidth < 768 && (
|
||||||
<h1 className="text-3xl font-bold mb-6">Subscription Management</h1>
|
<h1 className="text-3xl font-bold mb-6">Subscription Management</h1>
|
||||||
)}
|
)}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user