From 1b3f2b4d6e282340d00314a62213348c874ec475 Mon Sep 17 00:00:00 2001 From: zmeyer44 Date: Tue, 31 Oct 2023 10:26:17 -0400 Subject: [PATCH] calendar improvments --- .../_components/EditCalendarButton.tsx | 9 +- .../calendar/[naddr]/_components/Header.tsx | 2 +- app/(app)/calendar/[naddr]/page.tsx | 1 - .../[naddr]/_components/CalendarInfo.tsx | 86 +++++++++++++++ .../[naddr]/_components/EditEventButton.tsx | 21 ++++ .../event/[naddr]/_components/Header.tsx | 32 ++---- .../explore/_components/CalendarCard.tsx | 24 +++-- components/Modals/CreateCalendar.tsx | 65 +++++++++-- components/Modals/EditCalendar.tsx | 102 ++++++++++++++++++ components/Modals/EditEvent.tsx | 22 ++-- components/Modals/FormModal.tsx | 82 +++++++++++++- components/ui/button.tsx | 12 ++- .../EventsTimeline/EventsFromCalendar.tsx | 7 +- lib/actions/create.ts | 9 +- lib/utils/index.ts | 9 ++ 15 files changed, 419 insertions(+), 64 deletions(-) create mode 100644 app/(app)/event/[naddr]/_components/CalendarInfo.tsx create mode 100644 app/(app)/event/[naddr]/_components/EditEventButton.tsx create mode 100644 components/Modals/EditCalendar.tsx diff --git a/app/(app)/calendar/[naddr]/_components/EditCalendarButton.tsx b/app/(app)/calendar/[naddr]/_components/EditCalendarButton.tsx index 50025aa..b471bc8 100644 --- a/app/(app)/calendar/[naddr]/_components/EditCalendarButton.tsx +++ b/app/(app)/calendar/[naddr]/_components/EditCalendarButton.tsx @@ -1,18 +1,19 @@ import { Button } from "@/components/ui/button"; import { useModal } from "@/app/_providers/modal/provider"; -import RSVPModal from "@/components/Modals/RSVP"; +import EditCalendarModal from "@/components/Modals/EditCalendar"; +import { NostrEvent } from "@nostr-dev-kit/ndk"; type RSVPButtonProps = { - eventReference: string; + event: NostrEvent; }; -export default function RSVPButton({ eventReference }: RSVPButtonProps) { +export default function RSVPButton({ event }: RSVPButtonProps) { const modal = useModal(); return ( diff --git a/app/(app)/calendar/[naddr]/_components/Header.tsx b/app/(app)/calendar/[naddr]/_components/Header.tsx index 217eb99..f6074eb 100644 --- a/app/(app)/calendar/[naddr]/_components/Header.tsx +++ b/app/(app)/calendar/[naddr]/_components/Header.tsx @@ -135,7 +135,7 @@ export default function Header({ event }: { event: NDKEvent }) { {!!currentUser && currentUser.pubkey === pubkey && ( <> - + )} diff --git a/app/(app)/calendar/[naddr]/page.tsx b/app/(app)/calendar/[naddr]/page.tsx index aa276f4..eaabff9 100644 --- a/app/(app)/calendar/[naddr]/page.tsx +++ b/app/(app)/calendar/[naddr]/page.tsx @@ -46,7 +46,6 @@ export default function EventPage({ } const { tags } = event; const eventReference = event.encode(); - return (
diff --git a/app/(app)/event/[naddr]/_components/CalendarInfo.tsx b/app/(app)/event/[naddr]/_components/CalendarInfo.tsx new file mode 100644 index 0000000..7a3d6ad --- /dev/null +++ b/app/(app)/event/[naddr]/_components/CalendarInfo.tsx @@ -0,0 +1,86 @@ +"use client"; +import { useState, useEffect } from "react"; +import Link from "next/link"; +import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; +import { nip19 } from "nostr-tools"; +import { getLettersPlain } from "@/lib/utils"; +import { Skeleton } from "@/components/ui/skeleton"; +import { HiMiniChevronRight, HiCalendarDays } from "react-icons/hi2"; +import useEvents from "@/lib/hooks/useEvents"; +import { getTagValues } from "@/lib/nostr/utils"; +import ProfileInfo from "./ProfileInfo"; +import { type NDKKind, type NDKEvent } from "@nostr-dev-kit/ndk"; +import { useNDK } from "@/app/_providers/ndk"; + +type CalendarInfoProps = { + eventReference: string; +}; +export default function CalendarInfo({ eventReference }: CalendarInfoProps) { + console.log("eventReference", eventReference); + const { type, data } = nip19.decode(eventReference); + if (type !== "naddr") { + throw new Error("Invalid list"); + } + const { pubkey } = data; + const { ndk } = useNDK(); + const [event, setEvent] = useState(); + const [isFetching, setIsFetching] = useState(false); + + useEffect(() => { + if (!ndk || isFetching || event) return; + handleFetchEvent(); + }, [ndk, eventReference]); + + async function handleFetchEvent() { + if (!ndk) return; + setIsFetching(true); + + const calendarEvent = await ndk + .fetchEvent({ + authors: [pubkey], + ["#a"]: [eventReference], + kinds: [31924 as NDKKind], + }) + .catch((err) => console.log("err")); + if (calendarEvent) { + console.log("Found calendar", calendarEvent); + setEvent(calendarEvent); + } + setIsFetching(false); + } + + if (!event) { + return ; + } + const image = getTagValues("image", event.tags); + const name = getTagValues("name", event.tags); + return ( + + + + + {getLettersPlain(name)} + + +
+ {name ?? "Calendar"} + +
+ + + ); +} + +export function LoadingCalendarInfo() { + return ( +
+ +
+ +
+
+ ); +} diff --git a/app/(app)/event/[naddr]/_components/EditEventButton.tsx b/app/(app)/event/[naddr]/_components/EditEventButton.tsx new file mode 100644 index 0000000..87378b4 --- /dev/null +++ b/app/(app)/event/[naddr]/_components/EditEventButton.tsx @@ -0,0 +1,21 @@ +import { Button } from "@/components/ui/button"; +import { useModal } from "@/app/_providers/modal/provider"; +import EditEventModal from "@/components/Modals/EditEvent"; +import { NostrEvent } from "@nostr-dev-kit/ndk"; + +type EditEventProps = { + event: NostrEvent; +}; + +export default function EditEvent({ event }: EditEventProps) { + const modal = useModal(); + + return ( + + ); +} diff --git a/app/(app)/event/[naddr]/_components/Header.tsx b/app/(app)/event/[naddr]/_components/Header.tsx index b0f3431..e140416 100644 --- a/app/(app)/event/[naddr]/_components/Header.tsx +++ b/app/(app)/event/[naddr]/_components/Header.tsx @@ -12,6 +12,7 @@ import { getTagsValues, } from "@/lib/nostr/utils"; import ProfileInfo from "./ProfileInfo"; +import CalendarInfo from "./CalendarInfo"; import useCurrentUser from "@/lib/hooks/useCurrentUser"; import { useNDK } from "@/app/_providers/ndk"; import { toast } from "sonner"; @@ -30,13 +31,8 @@ import LocationIcon from "@/components/EventIcons/LocationIcon"; const RSVPButton = dynamic(() => import("./RSVPButton"), { ssr: false, }); -const CreateListEvent = dynamic( - () => import("@/components/Modals/ShortTextNoteOnList"), - { - ssr: false, - }, -); -const ConfirmModal = dynamic(() => import("@/components/Modals/Confirm"), { + +const EditEventButton = dynamic(() => import("./EditEventButton"), { ssr: false, }); @@ -151,26 +147,14 @@ export default function Header({ event }: { event: NDKEvent }) { {title}
- +
- {/* {!!currentUser && currentUser.pubkey === pubkey && ( - <> - - - - )} */} - + {!!currentUser && currentUser.pubkey === pubkey && ( + + )} + {!isMember && } {/* {!isMember && (hasValidPayment ? ( diff --git a/app/(app)/explore/_components/CalendarCard.tsx b/app/(app)/explore/_components/CalendarCard.tsx index 3b76f6f..7ca9095 100644 --- a/app/(app)/explore/_components/CalendarCard.tsx +++ b/app/(app)/explore/_components/CalendarCard.tsx @@ -10,7 +10,7 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; -import { cn } from "@/lib/utils"; +import { cn, getLettersPlain, getTwoLetters } from "@/lib/utils"; import { NDKEvent } from "@nostr-dev-kit/ndk"; import { BANNER } from "@/constants/app"; import { getNameToShow } from "@/lib/utils"; @@ -21,6 +21,7 @@ import { getTagAllValues, getTagValues } from "@/lib/nostr/utils"; import { useNDK } from "@/app/_providers/ndk"; import { Skeleton } from "@/components/ui/skeleton"; import { AspectRatio } from "@/components/ui/aspect-ratio"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; type CalendarCardProps = { calendar: NDKEvent; @@ -35,6 +36,9 @@ export default function CalendarCard({ calendar }: CalendarCardProps) { const [upcomingEvents, setUpcomingEvents] = useState([]); const [isFetching, setIsFetching] = useState(false); const name = getTagValues("name", tags); + const image = getTagValues("image", tags); + const banner = + getTagValues("banner", tags) ?? profile?.image ?? profile?.banner ?? BANNER; const description = content ?? getTagValues("about", tags); const calendarEvents = getTagAllValues("a", tags); const calendarEventIdentifiers = calendarEvents @@ -78,7 +82,7 @@ export default function CalendarCard({ calendar }: CalendarCardProps) { background - + + + {getLettersPlain(name ?? profile?.displayName ?? profile?.name)} + + + {/* user + /> */} Upcoming Events: diff --git a/components/Modals/CreateCalendar.tsx b/components/Modals/CreateCalendar.tsx index 0ea7526..7648074 100644 --- a/components/Modals/CreateCalendar.tsx +++ b/components/Modals/CreateCalendar.tsx @@ -11,14 +11,8 @@ import { addMinutesToDate, toUnix, convertToTimezone } from "@/lib/utils/dates"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; -import { DatePicker } from "@/components/ui/date-picker"; -import { TimePicker } from "@/components/ui/time-picker"; -import { TimezoneSelector } from "@/components/ui/timezone"; import { Label } from "@/components/ui/label"; -import SmallCalendarIcon from "@/components/EventIcons/DateIcon"; -import LocationIcon from "@/components/EventIcons/LocationIcon"; -import LocationSearchInput from "@/components/LocationSearch"; import Spinner from "../spinner"; import useAutosizeTextArea from "@/lib/hooks/useAutoSizeTextArea"; @@ -40,6 +34,13 @@ export default function CreateCalendarEventModal() { imageUrl, status: imageStatus, } = useImageUpload("event"); + const { + ImageUploadButton: BannerImageUploadButton, + clear: clearBanner, + imagePreview: bannerImagePreview, + imageUrl: bannerImageUrl, + status: bannerImageStatus, + } = useImageUpload("event"); const [error, setError] = useState(""); const [name, setName] = useState(""); const [description, setDescription] = useState(""); @@ -73,6 +74,9 @@ export default function CreateCalendarEventModal() { if (imageUrl) { tags.push(["image", imageUrl]); } + if (bannerImageUrl) { + tags.push(["banner", bannerImageUrl]); + } const preEvent = { content: description, pubkey: currentUser.pubkey, @@ -134,7 +138,7 @@ export default function CreateCalendarEventModal() { placeholder="Some into about this calendar..." />
-
+
{imagePreview ? (
@@ -178,13 +182,58 @@ export default function CreateCalendarEventModal() { )} + {bannerImagePreview ? ( +
+
+ Image +
+ {bannerImageStatus === "uploading" && ( + + )} + {bannerImageStatus === "success" && ( + + )} +
+ ) : ( + + + + )}
+ )} + {(status === "success" || value) && ( + + )} +
+ ) : ( + + + + )} +
+ ); +} diff --git a/components/ui/button.tsx b/components/ui/button.tsx index d9713b7..0b0da32 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -43,7 +43,15 @@ export interface ButtonProps const Button = React.forwardRef( ( - { className, variant, size, asChild = false, loading = false, ...props }, + { + className, + variant, + size, + asChild = false, + type = "button", + loading = false, + ...props + }, ref, ) => { const Comp = asChild ? Slot : "button"; @@ -52,6 +60,7 @@ const Button = React.forwardRef(
{props.children}
@@ -65,6 +74,7 @@ const Button = React.forwardRef( ); diff --git a/containers/EventsTimeline/EventsFromCalendar.tsx b/containers/EventsTimeline/EventsFromCalendar.tsx index 732c08b..f7f8f1c 100644 --- a/containers/EventsTimeline/EventsFromCalendar.tsx +++ b/containers/EventsTimeline/EventsFromCalendar.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, useEffect } from "react"; import { NDKEvent } from "@nostr-dev-kit/ndk"; -import { getTagAllValues } from "@/lib/nostr/utils"; +import { getTagsValues } from "@/lib/nostr/utils"; import { groupEventsByDay } from "."; import { useNDK } from "@/app/_providers/ndk"; import { nip19 } from "nostr-tools"; @@ -18,11 +18,13 @@ export default function EventsFromCalendar({ loader: Loader, empty: Empty, }: EventsFromCalendar) { - const calendarEvents = getTagAllValues("a", calendar.tags); + const calendarEvents = getTagsValues("a", calendar.tags); const { ndk } = useNDK(); const [events, setEvents] = useState([]); const [isFetching, setIsFetching] = useState(false); + const calendarEventIdentifiers = calendarEvents + .filter(Boolean) .map((e) => nip19.decode(e)) .filter(({ type }) => type === "naddr") .map((e) => e.data as nip19.AddressPointer); @@ -33,6 +35,7 @@ export default function EventsFromCalendar({ const events: NDKEvent[] = []; const promiseArray = []; for (const info of data) { + console.log("INFO", info); const calendarEventPromise = ndk .fetchEvent({ authors: [info.pubkey], diff --git a/lib/actions/create.ts b/lib/actions/create.ts index 92b93b0..8852e3e 100644 --- a/lib/actions/create.ts +++ b/lib/actions/create.ts @@ -244,6 +244,7 @@ export async function createEventOnList( return true; } +const multipleTag = ["a", "p", "e"]; export async function updateList( ndk: NDK, list: NostrEvent, @@ -254,7 +255,13 @@ export async function updateList( const index = tags.findIndex(([tK]) => tK === key); if (index !== -1) { // Replace old - tags[index] = [key, value]; + if (multipleTag.includes(key)) { + if (value !== tags[index]?.[1]) { + tags.push([key, value]); + } + } else { + tags[index] = [key, value]; + } } else { tags.push([key, value]); } diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 01e6846..7d302e7 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -37,6 +37,15 @@ export function getNameToShow(user: { user.profile?.displayName ?? user.profile?.name ?? truncateText(user.npub) ); } +export function getLettersPlain(text?: string) { + if (!text) return ""; + const splitString = text + .split(" ") + .map((s) => s[0]) + .filter(Boolean) + .join(" "); + return splitString; +} export function getTwoLetters(user: { npub: string; profile?: {