better laodign states

This commit is contained in:
zmeyer44 2023-10-27 14:49:16 -04:00
parent 092a262653
commit 4980e4335d
3 changed files with 95 additions and 8 deletions

View File

@ -1,13 +1,19 @@
"use client"; "use client";
import { useRef, useEffect, useState } from "react"; import { useRef, useEffect, useState } from "react";
import { CardLoading } from "@/components/Cards/CalendarEvent"; import {
import { formatDate, fromUnix, relativeTime } from "@/lib/utils/dates"; formatDate,
fromUnix,
relativeTime,
addMinutesToDate,
} from "@/lib/utils/dates";
import useCurrentUser from "@/lib/hooks/useCurrentUser"; import useCurrentUser from "@/lib/hooks/useCurrentUser";
import { DUMMY_1 } from "@/constants";
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";
import LargeFeedCard from "@/components/Cards/CalendarEvent/LargeFeedCard"; import LargeFeedCard, {
LoadingCard,
} from "@/components/Cards/CalendarEvent/LargeFeedCard";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
type CalendarSectionProps = { type CalendarSectionProps = {
events: NDKEvent[]; events: NDKEvent[];
@ -43,6 +49,32 @@ export default function CalendarSection({ events }: CalendarSectionProps) {
</div> </div>
); );
} }
export function CalendarSectionLoading() {
const startDate = addMinutesToDate(new Date(), 60);
return (
<div className="relative flex w-full items-start gap-x-3 @container">
{/* Date Indicator */}
<div className="sticky top-[calc(var(--header-height)_+_28px)] hidden w-[230px] shrink-0 md:block">
<CalendarIcon date={startDate} />
</div>
{/* Date Indicator Mobile */}
<div className="absolute inset-y-0 right-0 z-50 md:hidden">
<div className="sticky top-[calc(var(--header-height)_+_14px)] shrink-0">
<CalendarIconOpacity date={startDate} />
</div>
</div>
{/* Events */}
<div className="flex-1 space-y-4 max-md:pt-[60px]">
<LoadingCard />
<LoadingCard />
<LoadingCard />
<LoadingCard />
</div>
</div>
);
}
function CalendarIcon({ date }: { date: Date }) { function CalendarIcon({ date }: { date: Date }) {
return ( return (
<div <div

View File

@ -1,11 +1,13 @@
"use client"; "use client";
import { NDKEvent, type NDKKind } from "@nostr-dev-kit/ndk"; import { NDKEvent, type NDKKind } from "@nostr-dev-kit/ndk";
import CalendarSection from "./_components/CalendarSection"; import CalendarSection, {
CalendarSectionLoading,
} from "./_components/CalendarSection";
import useEvents from "@/lib/hooks/useEvents"; import useEvents from "@/lib/hooks/useEvents";
import { getTagValues } from "@/lib/nostr/utils"; import { getTagValues } from "@/lib/nostr/utils";
import { fromUnix, daysOffset } from "@/lib/utils/dates"; import { fromUnix, daysOffset } from "@/lib/utils/dates";
export default function Page() { export default function Page() {
const { events } = useEvents({ const { events, isLoading } = useEvents({
filter: { filter: {
kinds: [31923 as NDKKind], kinds: [31923 as NDKKind],
limit: 100, limit: 100,
@ -13,6 +15,16 @@ export default function Page() {
}); });
const eventsByDay = groupEventsByDay(events); const eventsByDay = groupEventsByDay(events);
if (isLoading && !eventsByDay.length) {
return (
<div className="relative flex-col px-5 pt-5 sm:pt-7">
<div className="mx-auto max-w-[900px] space-y-4">
<CalendarSectionLoading />
</div>
</div>
);
}
return ( return (
<div className="relative flex-col px-5 pt-5 sm:pt-7"> <div className="relative flex-col px-5 pt-5 sm:pt-7">
<div className="mx-auto max-w-[900px] space-y-4"> <div className="mx-auto max-w-[900px] space-y-4">

View File

@ -15,6 +15,8 @@ import AvatarStack from "@/components/ProfileContainers/AvatarStack";
import { NDKEvent } from "@nostr-dev-kit/ndk"; import { NDKEvent } from "@nostr-dev-kit/ndk";
import { getTagValues, getTagAllValues } from "@/lib/nostr/utils"; import { getTagValues, getTagAllValues } from "@/lib/nostr/utils";
import { HiOutlineMapPin, HiOutlineUserCircle } from "react-icons/hi2"; import { HiOutlineMapPin, HiOutlineUserCircle } from "react-icons/hi2";
import { Skeleton } from "@/components/ui/skeleton";
import { AspectRatio } from "@/components/ui/aspect-ratio";
type LargeFeedCardProps = { type LargeFeedCardProps = {
event: NDKEvent; event: NDKEvent;
@ -69,7 +71,7 @@ export default function LargeFeedCard({ event }: LargeFeedCardProps) {
</div> </div>
</div> </div>
</CardHeader> </CardHeader>
<div className="absolute inset-y-[0.5rem] right-[0.5rem] w-2/5"> <div className="absolute inset-y-[0.5rem] right-[0.5rem] w-2/5 overflow-hidden rounded-[0.5rem]">
{image ? ( {image ? (
<Image <Image
src={image} src={image}
@ -81,9 +83,50 @@ export default function LargeFeedCard({ event }: LargeFeedCardProps) {
)} )}
/> />
) : ( ) : (
<div className=""></div> <div className="h-[100px] w-full rounded-[0.5rem] bg-gradient-to-b from-primary/50"></div>
)} )}
</div> </div>
</Card> </Card>
); );
} }
export function LoadingCard() {
return (
<Card className="relative flex justify-between gap-x-4 rounded-[1rem] bg-muted p-[0.5rem]">
<CardHeader className="w-3/5 justify-between p-0 pr-5">
<div className="">
<div className="flex gap-x-1">
<Skeleton className="h-3 w-3" />
<Skeleton className="h-3 w-[50px]" />
</div>
<div className="pl-3">
<Skeleton className="mt-3 h-5 w-[220px]" />
<div className="mt-2 space-y-1.5">
<Skeleton className="h-3.5 w-3/4" />
<Skeleton className="h-3.5 w-3/5" />
<Skeleton className="h-3.5 w-1/4" />
</div>
</div>
</div>
<div className="mt-2 flex items-center gap-x-4 pl-2">
<div className="flex items-center gap-x-2">
<Skeleton className="h-3 w-3" />
<Skeleton className="h-3 w-[50px]" />
</div>
</div>
<div className="flex w-full flex-col justify-end self-start pl-2 pt-2">
<div className="flex w-3/4 items-center justify-stretch gap-3">
<Skeleton className="h-8 w-1/3 rounded-md" />
<Skeleton className="h-8 w-1/3 rounded-md" />
</div>
</div>
</CardHeader>
<div className="absolute inset-y-[0.5rem] right-[0.5rem] w-2/5 overflow-hidden rounded-[0.5rem]">
<AspectRatio
ratio={16 / 9}
className="w-full rounded-[0.5rem] bg-primary/20"
></AspectRatio>
</div>
</Card>
);
}