auto select calendar and some other simple stuff

This commit is contained in:
zmeyer44 2023-11-02 09:48:06 -04:00
parent 80be2c0197
commit e3156d7e21
6 changed files with 97 additions and 111 deletions

View File

@ -3,16 +3,20 @@ import { useModal } from "@/app/_providers/modal/provider";
import CreateCalendarEventModal from "@/components/Modals/CreateCalendarEvent"; import CreateCalendarEventModal from "@/components/Modals/CreateCalendarEvent";
type CreateEventButtonProps = { type CreateEventButtonProps = {
eventReference: string; eventIdentifier: string;
}; };
export default function CreateEventButton({ export default function CreateEventButton({
eventReference, eventIdentifier,
}: CreateEventButtonProps) { }: CreateEventButtonProps) {
const modal = useModal(); const modal = useModal();
return ( return (
<Button onClick={() => modal?.show(<CreateCalendarEventModal />)}> <Button
onClick={() =>
modal?.show(<CreateCalendarEventModal calendar={eventIdentifier} />)
}
>
Create Event Create Event
</Button> </Button>
); );

View File

@ -19,9 +19,9 @@ import {
checkPayment, checkPayment,
updateListUsersFromZaps, updateListUsersFromZaps,
} from "@/lib/actions/zap"; } from "@/lib/actions/zap";
import { useModal } from "@/app/_providers/modal/provider";
import { type NDKEvent } from "@nostr-dev-kit/ndk"; import { type NDKEvent } from "@nostr-dev-kit/ndk";
import { btcToSats, formatNumber } from "@/lib/utils"; import { btcToSats, formatNumber } from "@/lib/utils";
import { nip19 } from "nostr-tools";
const CreateEventButton = dynamic(() => import("./CreateEventButton"), { const CreateEventButton = dynamic(() => import("./CreateEventButton"), {
ssr: false, ssr: false,
@ -32,13 +32,12 @@ const EditCalendarButton = dynamic(() => import("./EditCalendarButton"), {
export default function Header({ event }: { event: NDKEvent }) { export default function Header({ event }: { event: NDKEvent }) {
const { currentUser } = useCurrentUser(); const { currentUser } = useCurrentUser();
const modal = useModal();
const { ndk } = useNDK(); const { ndk } = useNDK();
const [checkingPayment, setCheckingPayment] = useState(false); const [checkingPayment, setCheckingPayment] = useState(false);
const [hasValidPayment, setHasValidPayment] = useState(false); const [hasValidPayment, setHasValidPayment] = useState(false);
const { pubkey, tags } = event; const { pubkey, tags } = event;
const { profile } = useProfile(pubkey); const { profile } = useProfile(pubkey);
const eventReference = event.encode(); const identifier = event.tagId();
const name = getTagValues("name", tags) ?? "Untitled"; const name = getTagValues("name", tags) ?? "Untitled";
const image = const image =
getTagValues("banner", tags) ?? getTagValues("banner", tags) ??
@ -134,7 +133,7 @@ export default function Header({ event }: { event: NDKEvent }) {
<div className="flex flex-wrap items-center justify-end gap-3"> <div className="flex flex-wrap items-center justify-end gap-3">
{!!currentUser && currentUser.pubkey === pubkey && ( {!!currentUser && currentUser.pubkey === pubkey && (
<> <>
<CreateEventButton eventReference={eventReference} /> <CreateEventButton eventIdentifier={identifier} />
<EditCalendarButton event={event.rawEvent()} /> <EditCalendarButton event={event.rawEvent()} />
</> </>
)} )}

View File

@ -13,15 +13,17 @@ import {
import { cn, getLettersPlain, getTwoLetters } from "@/lib/utils"; import { cn, getLettersPlain, getTwoLetters } from "@/lib/utils";
import { NDKEvent } from "@nostr-dev-kit/ndk"; import { NDKEvent } from "@nostr-dev-kit/ndk";
import { BANNER } from "@/constants/app"; import { BANNER } from "@/constants/app";
import { getNameToShow } from "@/lib/utils";
import { nip19 } from "nostr-tools"; import { nip19 } from "nostr-tools";
import useProfile from "@/lib/hooks/useProfile"; import useProfile from "@/lib/hooks/useProfile";
import useEvents from "@/lib/hooks/useEvents"; import useEvents from "@/lib/hooks/useEvents";
import { getTagsValues, getTagValues } from "@/lib/nostr/utils"; import {
import { useNDK } from "@/app/_providers/ndk"; getTagsValues,
getTagValues,
sortEventsByTagNumber,
} from "@/lib/nostr/utils";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { AspectRatio } from "@/components/ui/aspect-ratio";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { unixTimeNowInSeconds } from "@/lib/nostr/dates";
type CalendarCardProps = { type CalendarCardProps = {
calendar: NDKEvent; calendar: NDKEvent;
@ -29,12 +31,9 @@ type CalendarCardProps = {
export default function CalendarCard({ calendar }: CalendarCardProps) { export default function CalendarCard({ calendar }: CalendarCardProps) {
const { pubkey, tags, content } = calendar; const { pubkey, tags, content } = calendar;
const { ndk } = useNDK();
const npub = nip19.npubEncode(pubkey);
const { profile } = useProfile(pubkey); const { profile } = useProfile(pubkey);
const encodedEvent = calendar.encode(); const encodedEvent = calendar.encode();
const [upcomingEvents, setUpcomingEvents] = useState<NDKEvent[]>([]); const [upcomingEvents, setUpcomingEvents] = useState<NDKEvent[]>([]);
const [isFetching, setIsFetching] = useState(false);
const name = getTagValues("name", tags); const name = getTagValues("name", tags);
const image = getTagValues("image", tags); const image = getTagValues("image", tags);
const banner = const banner =
@ -46,38 +45,25 @@ export default function CalendarCard({ calendar }: CalendarCardProps) {
.map((e) => nip19.decode(e)) .map((e) => nip19.decode(e))
.filter(({ type }) => type === "naddr") .filter(({ type }) => type === "naddr")
.map((e) => e.data as nip19.AddressPointer); .map((e) => e.data as nip19.AddressPointer);
const { events } = useEvents({
async function handleFetchEvents(data: nip19.AddressPointer[]) { filter: {
if (!ndk) return; kinds: calendarEventIdentifiers.map((k) => k.kind),
setIsFetching(true); authors: calendarEventIdentifiers.map((k) => k.pubkey),
const events: NDKEvent[] = []; ["#d"]: calendarEventIdentifiers.map((k) => k.identifier),
const promiseArray = []; },
for (const info of data) { });
const calendarEventPromise = ndk
.fetchEvent({
authors: [info.pubkey],
["#d"]: [info.identifier],
kinds: [info.kind],
})
.then((e) => e && events.push(e))
.catch((err) => console.log("err"));
promiseArray.push(calendarEventPromise);
}
await Promise.all(promiseArray);
setUpcomingEvents(events);
setIsFetching(false);
}
useEffect(() => { useEffect(() => {
if ( if (events) {
!ndk || const filteredEvents = events.filter(
calendarEventIdentifiers.length === 0 || (e) =>
isFetching || parseInt(getTagValues("start", e.tags) ?? "0") >
upcomingEvents.length unixTimeNowInSeconds(),
) );
return; const sortedEvents = sortEventsByTagNumber(filteredEvents, "start");
handleFetchEvents(calendarEventIdentifiers); setUpcomingEvents(sortedEvents);
}, [ndk, calendarEventIdentifiers]); }
}, [events]);
return ( return (
<Card className="relative h-[350px] w-[250px] min-w-[250] overflow-hidden"> <Card className="relative h-[350px] w-[250px] min-w-[250] overflow-hidden">
@ -119,34 +105,40 @@ export default function CalendarCard({ calendar }: CalendarCardProps) {
<CardTitle>Upcoming Events:</CardTitle> <CardTitle>Upcoming Events:</CardTitle>
</CardHeader> </CardHeader>
<CardContent className="overflow-hidden px-0"> <CardContent className="overflow-hidden px-0">
<ul className="w-full"> {upcomingEvents.length ? (
{upcomingEvents.map((item) => { <ul className="w-full">
const { tags, content } = item; {upcomingEvents.map((item) => {
const encodedEvent = item.encode(); const { tags, content } = item;
const name = getTagValues("name", tags); const encodedEvent = item.encode();
const description = content; const name = getTagValues("name", tags);
return ( const description = content;
<li key={item.id} className="w-full overflow-hidden"> return (
<Link <li key={item.id} className="w-full overflow-hidden">
href={`/event/${encodedEvent}`} <Link
className="flex max-w-full items-center justify-between overflow-hidden py-1.5 pl-4 pr-2 transition-colors hover:bg-muted hover:text-primary" href={`/event/${encodedEvent}`}
> className="flex max-w-full items-center justify-between overflow-hidden py-1.5 pl-4 pr-2 transition-colors hover:bg-muted hover:text-primary"
<div className="shrink overflow-x-hidden"> >
<h4 className="line-clamp-1 text-sm font-semibold text-card-foreground"> <div className="shrink overflow-x-hidden">
{name} <h4 className="line-clamp-1 text-sm font-semibold text-card-foreground">
</h4> {name}
<p className="line-clamp-2 text-[10px] leading-4 text-muted-foreground"> </h4>
{description ?? ""} <p className="line-clamp-2 text-[10px] leading-4 text-muted-foreground">
</p> {description ?? ""}
</div> </p>
<div className="center ml-auto shrink-0 pl-2"> </div>
<RiArrowRightLine className="h-5 w-5" /> <div className="center ml-auto shrink-0 pl-2">
</div> <RiArrowRightLine className="h-5 w-5" />
</Link> </div>
</li> </Link>
); </li>
})} );
</ul> })}
</ul>
) : (
<div className="py-3 text-center text-sm text-muted-foreground">
<p>No upcoming events</p>
</div>
)}
</CardContent> </CardContent>
</Card> </Card>
</div> </div>

View File

@ -34,7 +34,14 @@ import useCurrentUser from "@/lib/hooks/useCurrentUser";
import useImageUpload from "@/lib/hooks/useImageUpload"; import useImageUpload from "@/lib/hooks/useImageUpload";
import { NDKEvent } from "@nostr-dev-kit/ndk"; import { NDKEvent } from "@nostr-dev-kit/ndk";
import { getTagValues } from "@/lib/nostr/utils"; import { getTagValues } from "@/lib/nostr/utils";
export default function CreateCalendarEventModal() {
type CreateCalendarEventModalProps = {
calendar?: string;
};
export default function CreateCalendarEventModal({
calendar: _calendar,
}: CreateCalendarEventModalProps) {
const modal = useModal(); const modal = useModal();
const now = new Date(new Date().setHours(12, 0, 0, 0)); const now = new Date(new Date().setHours(12, 0, 0, 0));
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@ -73,7 +80,7 @@ export default function CreateCalendarEventModal() {
const [timezone, setTimezone] = useState( const [timezone, setTimezone] = useState(
Intl.DateTimeFormat().resolvedOptions().timeZone, Intl.DateTimeFormat().resolvedOptions().timeZone,
); );
const [calendar, setCalendar] = useState<string>(); const [calendar, setCalendar] = useState<string>(_calendar ?? "");
const [location, setLocation] = useState<{ const [location, setLocation] = useState<{
address: string; address: string;
name: string; name: string;
@ -154,6 +161,7 @@ export default function CreateCalendarEventModal() {
kind: 31923, kind: 31923,
}; };
const event = await createEvent(ndk, preEvent); const event = await createEvent(ndk, preEvent);
if (event) { if (event) {
const encodedEvent = event.encode(); const encodedEvent = event.encode();
if (calendar) { if (calendar) {
@ -326,7 +334,7 @@ export default function CreateCalendarEventModal() {
({ ({
...o, ...o,
label: getTagValues("name", o.tags) as string, label: getTagValues("name", o.tags) as string,
value: o.encode(), value: o.tagId(),
}) as NDKEvent & { }) as NDKEvent & {
label: string; label: string;
value: string; value: string;
@ -339,7 +347,7 @@ export default function CreateCalendarEventModal() {
} }
className="px-0 pr-1 font-normal" className="px-0 pr-1 font-normal"
value={calendar} value={calendar}
onChange={(calendar) => setCalendar(calendar.encode())} onChange={(calendar) => setCalendar(calendar.tagId())}
/> />
</div> </div>
</div> </div>

View File

@ -35,47 +35,12 @@ export default function EventsFromCalendar({
["#d"]: calendarEventIdentifiers.map((k) => k.identifier), ["#d"]: calendarEventIdentifiers.map((k) => k.identifier),
}, },
}); });
// async function handleFetchEvents(data: nip19.AddressPointer[]) {
// if (!ndk) return;
// setIsFetching(true);
// const events: NDKEvent[] = [];
// const promiseArray = [];
// for (const info of data) {
// console.log("INFO", info);
// const calendarEventPromise = ndk
// .fetchEvent({
// authors: [info.pubkey],
// ["#d"]: [info.identifier],
// kinds: [info.kind],
// })
// .then((e) => e && events.push(e))
// .catch((err) => console.log("err"));
// promiseArray.push(calendarEventPromise);
// }
// await Promise.all(promiseArray);
// setEvents(events);
// setIsFetching(false);
// }
// useEffect(() => {
// if (
// !ndk ||
// calendarEventIdentifiers.length === 0 ||
// isFetching ||
// events.length
// )
// return;
// handleFetchEvents(calendarEventIdentifiers);
// }, [ndk, calendarEventIdentifiers]);
useEffect(() => { useEffect(() => {
if (events) { if (events) {
const grouped = groupEventsByDay(events); const grouped = groupEventsByDay(events);
console.log("Runnign group", events, " to", grouped);
setEventsByDay(grouped); setEventsByDay(grouped);
} }
}, [events]); }, [events]);
console.log(eventsByDay);
if (isFetching) { if (isFetching) {
if (Loader) { if (Loader) {
return <Loader />; return <Loader />;

View File

@ -43,11 +43,29 @@ export function aTagToNip19(aTag: string[]): string {
identifier: tagIdSplit[2] as string, identifier: tagIdSplit[2] as string,
}); });
} }
export function sortEventsByTagNumber<T extends { tags: string[][] }>(
events: T[],
key: string,
swap?: boolean,
) {
const direction = swap ? -1 : 1;
return events.sort((a, b) => {
const aVal = parseInt(getTagValues(key, a.tags) ?? "0");
const bVal = parseInt(getTagValues(key, b.tags) ?? "0");
if (aVal > bVal) {
return direction;
} else if (aVal < bVal) {
return direction * -1;
}
return 0;
});
}
export const getTagValues = (name: string, tags: string[][]) => { export const getTagValues = (name: string, tags: string[][]) => {
const [itemTag] = tags.filter((tag: string[]) => tag[0] === name); const [itemTag] = tags.filter((tag: string[]) => tag[0] === name);
const [, item] = itemTag || [, undefined]; const [, item] = itemTag || [, undefined];
return item; return item;
}; };
export const getTagAllValues = (name: string, tags: string[][]) => { export const getTagAllValues = (name: string, tags: string[][]) => {
const [itemTag] = tags.filter((tag: string[]) => tag[0] === name); const [itemTag] = tags.filter((tag: string[]) => tag[0] === name);
const itemValues = itemTag || [, undefined]; const itemValues = itemTag || [, undefined];