working on list page
This commit is contained in:
parent
5a09b0be77
commit
c1cbd5f794
@ -40,7 +40,7 @@ export default function ProfilePage({
|
||||
];
|
||||
return (
|
||||
<div className="relative mx-auto max-w-5xl space-y-6">
|
||||
<div className="relative -mx-5 @container ">
|
||||
<div className="relative @container">
|
||||
<div className="absolute top-0 h-[8rem] w-full" />
|
||||
<div className="mx-auto max-w-5xl p-0">
|
||||
<div className="m-0 @5xl:px-5 @5xl:pt-8">
|
||||
|
@ -16,7 +16,7 @@ export default function AppLayout({ children }: { children: React.ReactNode }) {
|
||||
{/* Sidebar */}
|
||||
<Sidebar />
|
||||
<div className="relative flex flex-1 shrink-0 grow justify-center overflow-x-hidden">
|
||||
<div className="flex-1 overflow-x-hidden px-5 pb-5">{children}</div>
|
||||
<div className="flex-1 overflow-x-hidden pb-5">{children}</div>
|
||||
</div>
|
||||
{/* Mobile Banner */}
|
||||
<MobileBanner />
|
||||
|
@ -19,7 +19,7 @@ const FeaturedListsSection = dynamic(
|
||||
);
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="relative space-y-6 pt-5 sm:pt-7">
|
||||
<div className="relative space-y-6 px-5 pt-5 sm:pt-7">
|
||||
<ExploreCreators />
|
||||
<LongFormContentSection />
|
||||
<BecomeACreator />
|
||||
|
44
app/(app)/list/[naddr]/_components/ProfileInfo.tsx
Normal file
44
app/(app)/list/[naddr]/_components/ProfileInfo.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import Link from "next/link";
|
||||
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
||||
import useProfile from "@/lib/hooks/useProfile";
|
||||
import { nip19 } from "nostr-tools";
|
||||
import { getTwoLetters, getNameToShow } from "@/lib/utils";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { HiMiniChevronRight, HiCheckBadge } from "react-icons/hi2";
|
||||
|
||||
type ProfileInfoProps = {
|
||||
pubkey: string;
|
||||
};
|
||||
export default function ProfileInfo({ pubkey }: ProfileInfoProps) {
|
||||
const { profile } = useProfile(pubkey);
|
||||
const npub = nip19.npubEncode(pubkey);
|
||||
return (
|
||||
<Link
|
||||
href={`/${npub}`}
|
||||
className="center group gap-x-2 rounded-sm rounded-r-full border bg-background/50 pl-0.5 pr-1 text-muted-foreground hover:shadow"
|
||||
>
|
||||
<Avatar className="center h-[16px] w-[16px] overflow-hidden rounded-[.25rem] bg-muted @sm:h-[18px] @sm:w-[18px]">
|
||||
<AvatarImage src={profile?.image} alt={profile?.displayName} />
|
||||
<AvatarFallback className="text-[8px]">
|
||||
{getTwoLetters({ npub, profile })}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-[14px] ">{getNameToShow({ npub, profile })}</span>
|
||||
{!!profile?.nip05 && <HiCheckBadge className="h-3 w-3 text-primary" />}
|
||||
</div>
|
||||
<HiMiniChevronRight className="h-4 w-4" />
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export function LoadingProfileInfo() {
|
||||
return (
|
||||
<div className="center group gap-x-1">
|
||||
<Avatar className="center h-[16px] w-[16px] overflow-hidden rounded-[.25rem] bg-muted @sm:h-[18px] @sm:w-[18px]"></Avatar>
|
||||
<div className="space-y-1">
|
||||
<Skeleton className="h-2 w-[70px] bg-muted" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -10,7 +10,9 @@ import { getTwoLetters, truncateText } from "@/lib/utils";
|
||||
import { nip19 } from "nostr-tools";
|
||||
import useEvents from "@/lib/hooks/useEvents";
|
||||
import Spinner from "@/components/spinner";
|
||||
import { getTagValues } from "@/lib/nostr/utils";
|
||||
import { getTagValues, getTagsValues } from "@/lib/nostr/utils";
|
||||
import ProfileInfo from "./_components/ProfileInfo";
|
||||
import Feed from "@/containers/Feed";
|
||||
|
||||
const demo = [
|
||||
{
|
||||
@ -51,11 +53,13 @@ export default function ListPage({
|
||||
|
||||
if (!event) {
|
||||
return (
|
||||
<div className="center ">
|
||||
<div className="center pt-20 text-primary">
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const noteIds = getTagsValues("e", event.tags).filter(Boolean);
|
||||
|
||||
const title =
|
||||
getTagValues("title", event.tags) ??
|
||||
getTagValues("name", event.tags) ??
|
||||
@ -63,100 +67,55 @@ export default function ListPage({
|
||||
const image =
|
||||
getTagValues("image", event.tags) ??
|
||||
getTagValues("picture", event.tags) ??
|
||||
getTagValues("benner", event.tags);
|
||||
getTagValues("banner", event.tags) ??
|
||||
profile?.banner;
|
||||
|
||||
const description = getTagValues("description", event.tags);
|
||||
return (
|
||||
<div className="relative mx-auto max-w-5xl space-y-6">
|
||||
<div className="relative bg-muted @container">
|
||||
<div className="absolute top-0 h-[8rem] w-full" />
|
||||
<div className="mx-auto max-w-5xl p-0">
|
||||
<div className="m-0 @5xl:px-5 @5xl:pt-8">
|
||||
<div className="relative w-full overflow-hidden bg-gradient-to-b from-primary pb-[29%] @5xl:rounded-[20px]">
|
||||
{!!profile?.banner && (
|
||||
<Image
|
||||
className="absolute inset-0 h-full w-full object-cover align-middle"
|
||||
src={profile.banner}
|
||||
width={400}
|
||||
height={100}
|
||||
alt="banner"
|
||||
unoptimized
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative mx-auto mb-4 mt-[calc(-0.4375_*_4rem)] flex max-w-[800px] items-end justify-between gap-2 px-3 sm:mt-[calc(-0.4375_*_4.5rem)] sm:px-5 md:mt-[calc(-0.5625_*_5rem)] lg:mt-[calc(-0.5625_*_6rem)]">
|
||||
<div className="z-1 ml-[calc(-1_*_3px)] overflow-hidden rounded-[0.5rem] bg-background p-[3px] sm:ml-[calc(-1_*_4px)] sm:p-[4px] lg:ml-[calc(-1_*_6px)] lg:rounded-[1rem] lg:p-[6px]">
|
||||
{profile?.image ? (
|
||||
<div className="relative mx-auto max-w-5xl space-y-4 p-2 sm:p-4">
|
||||
<div className="relative overflow-hidden rounded-[1rem] border bg-muted p-[0.5rem] @container">
|
||||
<div className="overflow-hidden rounded-[0.5rem] p-0">
|
||||
<div className="relative w-full overflow-hidden bg-gradient-to-b from-primary pb-[50%] @5xl:rounded-[20px] md:pb-[40%]">
|
||||
{!!image && (
|
||||
<Image
|
||||
src={profile.image}
|
||||
className="aspect-square w-[4rem] overflow-hidden rounded-[calc(0.5rem_-_3px)] object-cover object-center sm:w-[4.5rem] sm:rounded-[calc(0.5rem_-_4px)] md:w-[5rem] lg:w-[6rem] lg:rounded-[calc(1rem_-_6px)]"
|
||||
className="absolute inset-0 h-full w-full object-cover align-middle"
|
||||
src={image}
|
||||
width={400}
|
||||
height={100}
|
||||
alt="banner"
|
||||
unoptimized
|
||||
alt="profile picture"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
) : (
|
||||
<div className="center aspect-square w-[4rem] overflow-hidden rounded-[calc(0.5rem_-_3px)] bg-muted object-cover object-center text-primary @xl:text-2xl sm:w-[4.5rem] sm:rounded-[calc(0.5rem_-_4px)] md:w-[5rem] lg:w-[6rem] lg:rounded-[calc(1rem_-_6px)]"></div>
|
||||
)}
|
||||
</div>
|
||||
<Button size={"sm"} className="rounded-sm px-5 sm:hidden">
|
||||
Follow
|
||||
</Button>
|
||||
<Button className="rounded-sm px-5 max-sm:hidden">Follow</Button>
|
||||
</div>
|
||||
<div className="mx-auto max-w-[800px] space-y-1 px-4">
|
||||
<div className="flex items-center gap-x-1.5 lg:gap-x-2.5">
|
||||
<h2 className="text-xl font-semibold sm:text-2xl lg:text-3xl">
|
||||
{title}
|
||||
</h2>
|
||||
{!!profile?.nip05 && (
|
||||
<HiCheckBadge className="h-5 w-5 text-primary lg:h-7 lg:w-7" />
|
||||
)}
|
||||
<div className="space-y-1 p-3 @sm:px-3.5 @sm:pb-2 @sm:pt-5">
|
||||
<div className="flex justify-between gap-x-1.5 @lg:gap-x-2.5">
|
||||
<div className="space-y-1 @sm:space-y-2">
|
||||
<h2 className="font-condensed text-2xl font-semibold sm:text-3xl lg:text-4xl">
|
||||
{title}
|
||||
</h2>
|
||||
<div className="flex items-center">
|
||||
<ProfileInfo pubkey={pubkey} />
|
||||
</div>
|
||||
</div>
|
||||
<Button>Subscribe</Button>
|
||||
</div>
|
||||
<div className="flex items-center text-xs text-muted-foreground/80 md:text-sm">
|
||||
{!!profile?.name && <p>{profile.name}</p>}
|
||||
{!!profile?.name && !!profile.nip05 && (
|
||||
<>
|
||||
<div className="inline-flex px-1">·</div>
|
||||
<p>{profile.nip05}</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="pt-1 md:pt-2">
|
||||
|
||||
<div className="pt-1 @md:pt-2">
|
||||
{!!description && (
|
||||
<p className="line-clamp-3 text-xs text-muted-foreground md:text-sm">
|
||||
<p className="line-clamp-3 text-sm text-muted-foreground md:text-sm">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx-auto max-w-[800px] space-y-6">
|
||||
<div className="flex max-w-2xl flex-col gap-5">
|
||||
{demo.map((e) => (
|
||||
<SubscriptionCard key={e.id} {...e} />
|
||||
))}
|
||||
</div>
|
||||
<div className="">
|
||||
<Tabs
|
||||
tabs={[
|
||||
{
|
||||
name: "feed",
|
||||
label: "Feed",
|
||||
},
|
||||
{
|
||||
name: "media",
|
||||
label: "Media",
|
||||
},
|
||||
{
|
||||
name: "subscriptions",
|
||||
label: "Subscriptions",
|
||||
},
|
||||
]}
|
||||
activeTab={activeTab}
|
||||
setActiveTab={(t) => setActiveTab(t.name)}
|
||||
<div className="relative overflow-hidden rounded-[1rem] border bg-muted p-[0.5rem] @container">
|
||||
<div className="overflow-hidden rounded-[0.5rem] p-0">
|
||||
<Feed
|
||||
filter={{
|
||||
ids: noteIds,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Avatar, AvatarImage, AvatarFallback } from "@radix-ui/react-avatar";
|
||||
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
||||
import { HiCheckBadge } from "react-icons/hi2";
|
||||
import Link from "next/link";
|
||||
import useProfile from "@/lib/hooks/useProfile";
|
||||
|
Loading…
x
Reference in New Issue
Block a user