diff --git a/app/(app)/app/_sections/UpcomingEvents.tsx b/app/(app)/app/_sections/UpcomingEvents.tsx
new file mode 100644
index 0000000..c9d3e0f
--- /dev/null
+++ b/app/(app)/app/_sections/UpcomingEvents.tsx
@@ -0,0 +1,84 @@
+"use client";
+import {
+ Section,
+ SectionHeader,
+ SectionTitle,
+ SectionContent,
+} from "@/containers/PageSection";
+import { Button } from "@/components/ui/button";
+import { RiArrowRightLine } from "react-icons/ri";
+import CalendarEventCard, {
+ CardLoading,
+} from "@/components/Cards/CalendarEvent";
+import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
+import Link from "next/link";
+import useEvents from "@/lib/hooks/useEvents";
+import { Event } from "nostr-tools";
+import KindLoading from "@/components/KindCard/loading";
+import { nip19 } from "nostr-tools";
+import { getTagValues, getTagsValues } from "@/lib/nostr/utils";
+import { type NDKKind } from "@nostr-dev-kit/ndk";
+import { uniqBy } from "ramda";
+
+export default function UpcomingEventsSection() {
+ const { events } = useEvents({
+ filter: {
+ kinds: [31923 as NDKKind],
+ limit: 10,
+ },
+ });
+
+ console.log("UpcomingEventsSection", events);
+
+ const processedEvents = uniqBy(
+ (e) => getTagValues("name", e.tags),
+ events,
+ ).sort((a, b) => {
+ const aImage = getTagValues("image", a.tags);
+ const bImage = getTagValues("image", b.tags);
+ if (aImage && bImage) {
+ return 0;
+ }
+ if (bImage) return 1;
+ return -1;
+ });
+
+ return (
+
+
+
+ Upcoming Events
+
+
+
+
+
+
+ {processedEvents?.length > 3 ? (
+ processedEvents.slice(0, 6).map((e, idx) => {
+ return (
+
+
+
+ );
+ })
+ ) : (
+ <>
+
+
+
+
+ >
+ )}
+
+
+
+
+
+ );
+}
diff --git a/app/(app)/app/page.tsx b/app/(app)/app/page.tsx
index c19d0d8..970cbfe 100644
--- a/app/(app)/app/page.tsx
+++ b/app/(app)/app/page.tsx
@@ -1,5 +1,6 @@
import dynamic from "next/dynamic";
import ExploreCreators from "./_sections/ExploreCreators";
+import UpcomingEvents from "./_sections/UpcomingEvents";
import LongFormContentSection from "./_sections/LongFormContent";
import BecomeACreator from "./_sections/BecomeACreator";
@@ -23,6 +24,7 @@ export default function Page() {
return (
+
diff --git a/app/(app)/event/[naddr]/_components/Header.tsx b/app/(app)/event/[naddr]/_components/Header.tsx
index 55d1be5..c6afdb2 100644
--- a/app/(app)/event/[naddr]/_components/Header.tsx
+++ b/app/(app)/event/[naddr]/_components/Header.tsx
@@ -46,14 +46,10 @@ export default function Header({ event }: { event: NDKEvent }) {
const { ndk } = useNDK();
const [checkingPayment, setCheckingPayment] = useState(false);
const [hasValidPayment, setHasValidPayment] = useState(false);
- const [syncingUsers, setSyncingUsers] = useState(false);
const { pubkey, tags } = event;
const { profile } = useProfile(pubkey);
- console.log("EVENT", tags);
- const noteIds = getTagsValues("e", tags).filter(Boolean);
const title = getTagValues("name", tags) ?? "Untitled";
- console.log("tite", tags);
const image =
getTagValues("image", tags) ??
getTagValues("picture", tags) ??
@@ -110,19 +106,7 @@ export default function Header({ event }: { event: NDKEvent }) {
setCheckingPayment(false);
}
}
- async function handleSyncUsers() {
- if (!event || !ndk) return;
- setSyncingUsers(true);
- try {
- console.log("handleSyncUsers");
- await updateListUsersFromZaps(ndk, event.tagId(), rawEvent);
- toast.success("Users Synced!");
- } catch (err) {
- console.log("error syncing users", err);
- } finally {
- setSyncingUsers(false);
- }
- }
+
async function handleSendZap() {
try {
const result = await sendZap(
@@ -163,7 +147,7 @@ export default function Header({ event }: { event: NDKEvent }) {
-
+
{title}
@@ -175,14 +159,7 @@ export default function Header({ event }: { event: NDKEvent }) {
{!!currentUser && currentUser.pubkey === pubkey && (
<>
-
-
+
{!!description && (
-
+
{description}
)}
-
+
{!!startDate && (
-
+
{formatDate(startDate, "dddd, MMMM Do")}
{!!endDate ? (
-
{`${formatDate(
+
{`${formatDate(
startDate,
"h:mm a",
)} to ${formatDate(endDate, "h:mm a")}`}
) : (
-
{`${formatDate(
+
{`${formatDate(
startDate,
"h:mm a",
)}`}
@@ -270,8 +247,10 @@ export default function Header({ event }: { event: NDKEvent }) {
{location.length > 2 ? (
<>
-
{location[1]}
-
+
+ {location[1]}
+
+
{location[2]}
>
diff --git a/components/Cards/CalendarEvent/index.tsx b/components/Cards/CalendarEvent/index.tsx
new file mode 100644
index 0000000..40d478d
--- /dev/null
+++ b/components/Cards/CalendarEvent/index.tsx
@@ -0,0 +1,159 @@
+"use client";
+import Image from "next/image";
+import { cn, formatNumber } from "@/lib/utils";
+import { Badge } from "@/components/ui/badge";
+import { RxClock, RxCalendar } from "react-icons/rx";
+import { HiOutlineUsers } from "react-icons/hi";
+import { AspectRatio } from "@/components/ui/aspect-ratio";
+import { Skeleton } from "@/components/ui/skeleton";
+import { formatDate } from "@/lib/utils/dates";
+import { NostrEvent } from "@nostr-dev-kit/ndk";
+import {
+ getTagAllValues,
+ getTagValues,
+ getTagsValues,
+} from "@/lib/nostr/utils";
+import useProfile from "@/lib/hooks/useProfile";
+import SmallProfileLine from "@/components/ProfileContainers/SmallProfileLine";
+
+type CalendarEventCardProps = {
+ event: NostrEvent;
+ className?: string;
+};
+
+export default function CalendarEventCard({
+ className,
+ event,
+}: CalendarEventCardProps) {
+ const { pubkey, tags } = event;
+ const { profile } = useProfile(pubkey);
+
+ const title = getTagValues("name", tags) || "Untitled";
+ console.log("tite", tags);
+ const image =
+ getTagValues("image", tags) ??
+ getTagValues("picture", tags) ??
+ getTagValues("banner", tags) ??
+ profile?.banner;
+
+ const description = event.content;
+ const startDate = getTagValues("start", tags)
+ ? new Date(parseInt(getTagValues("start", tags) as string) * 1000)
+ : null;
+ const endDate = getTagValues("end", tags)
+ ? new Date(parseInt(getTagValues("end", tags) as string) * 1000)
+ : null;
+ const getLocation = () => {
+ let temp = getTagAllValues("location", tags);
+ if (temp[0]) {
+ return temp;
+ }
+ return getTagAllValues("address", tags);
+ };
+ const location = getLocation();
+
+ const users = getTagsValues("p", tags);
+ const hashtags = getTagsValues("t", tags);
+ return (
+
+
+
+
{title}
+
+
+ {!!startDate && (
+ <>
+ {startDate.getDay() === endDate?.getDay() ? (
+
+
+ {formatDate(startDate, "ddd, MMM D")}
+
+ ) : (
+
+
+ {formatDate(startDate, "ddd, MMM D")}
+ {!!endDate && (
+ <>
+ {" "}
+ -{" "}
+ {formatDate(endDate, "MMM D")}
+ >
+ )}
+
+ )}
+
+
+
+ {formatDate(startDate, "h:mm a")}
+ {!!endDate && (
+ <>
+ {" "}
+ -{" "}
+ {formatDate(endDate, "h:mm a")}
+ >
+ )}
+
+ >
+ )}
+ {!!users.length && (
+
+
+ {formatNumber(users.length)}
+
+ )}
+
+
+
+
+
+
+
+ );
+}
+export function CardLoading({ className }: { className: string }) {
+ return (
+
+ );
+}
diff --git a/components/ProfileContainers/SmallProfileLine.tsx b/components/ProfileContainers/SmallProfileLine.tsx
new file mode 100644
index 0000000..0701247
--- /dev/null
+++ b/components/ProfileContainers/SmallProfileLine.tsx
@@ -0,0 +1,43 @@
+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 (
+
+
+
+
+ {getTwoLetters({ npub, profile })}
+
+
+
+ {getNameToShow({ npub, profile })}
+ {!!profile?.nip05 && }
+
+
+ );
+}
+
+export function LoadingProfileInfo() {
+ return (
+
+ );
+}