fix: match events loading skeleton to page layout

This commit is contained in:
2026-10-02 13:10:45 +03:30
parent c1f4c140fc
commit 22fe66bf3c
4 changed files with 55 additions and 60 deletions

View File

@@ -1,5 +1,5 @@
import { ListingPageLoading } from "@/components/page-loading"; import { EventsPageLoading } from "@/components/page-loading";
export default function Loading() { export default function Loading() {
return <ListingPageLoading />; return <EventsPageLoading />;
} }

View File

@@ -0,0 +1,32 @@
export function EventResultsSkeleton() {
return (
<div role="status" aria-live="polite" className="space-y-3">
<span className="sr-only">در حال اعمال فیلترها و دریافت رویدادها…</span>
<div
aria-hidden="true"
className="grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4 xl:grid-cols-3"
>
{Array.from({ length: 6 }, (_, index) => (
<article
key={index}
className="flex h-full min-w-0 flex-col overflow-hidden rounded-xl border border-border bg-card"
>
<div className="aspect-video w-full shrink-0 animate-pulse bg-muted motion-reduce:animate-none" />
<div className="flex flex-1 flex-col p-3 md:p-4">
<div className="ms-auto h-5 w-4/5 animate-pulse rounded bg-muted motion-reduce:animate-none" />
<div className="mt-3 grid gap-3 md:mt-4">
{["w-32", "w-40", "w-24", "w-36"].map((width, lineIndex) => (
<div key={`${width}-${lineIndex}`} className="flex items-center justify-end gap-2">
<div className={`h-3.5 ${width} animate-pulse rounded bg-muted motion-reduce:animate-none`} />
<div className="size-4 animate-pulse rounded-full bg-muted motion-reduce:animate-none" />
</div>
))}
</div>
<div className="mt-auto min-h-10 w-full animate-pulse rounded-md bg-muted pt-2 md:mt-5 md:min-h-11 motion-reduce:animate-none" />
</div>
</article>
))}
</div>
</div>
);
}

View File

@@ -1,4 +1,5 @@
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { EventResultsSkeleton } from "@/components/events/EventResultsSkeleton";
export function BlogCardsSkeleton({ count = 6 }: { count?: number }) { export function BlogCardsSkeleton({ count = 6 }: { count?: number }) {
return ( return (
@@ -131,35 +132,27 @@ export function BlogDetailPageLoading() {
); );
} }
export function ListingPageLoading() { export function EventsPageLoading() {
return ( return (
<div className="min-h-screen bg-background" dir="rtl"> <div className="min-h-screen bg-background" dir="rtl">
<div className="container mx-auto px-4 py-8"> <main className="container mx-auto max-w-screen-2xl px-3 py-5 sm:px-4 sm:py-8 lg:px-6">
<Skeleton className="mb-8 h-10 w-40" /> <header className="mb-6 border-b border-border pb-5 sm:mb-8 sm:pb-6" aria-hidden="true">
<Skeleton className="mb-8 h-10 w-full max-w-md" /> <Skeleton className="h-8 w-48 sm:h-9 sm:w-56 motion-reduce:animate-none" />
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3"> <div className="mt-2 grid max-w-3xl gap-2">
{Array.from({ length: 6 }).map((_, index) => ( <Skeleton className="h-4 w-full max-w-3xl motion-reduce:animate-none" />
<div <Skeleton className="h-4 w-3/5 max-w-xl motion-reduce:animate-none" />
key={index} </div>
className="overflow-hidden rounded-lg border bg-card" </header>
>
<Skeleton className="aspect-video w-full rounded-none" /> <section aria-label="نتایج رویدادها" aria-busy="true" className="min-w-0">
<div className="space-y-4 p-6"> <div aria-hidden="true" dir="rtl" className="mb-4 flex items-center gap-2 sm:mb-5">
<div className="flex items-start justify-between gap-3"> <Skeleton className="h-11 min-w-0 flex-1 rounded-md motion-reduce:animate-none" />
<Skeleton className="h-6 flex-1" /> <Skeleton className="h-11 w-10 shrink-0 rounded-md min-[640px]:w-24 motion-reduce:animate-none" />
<Skeleton className="h-6 w-16" /> </div>
</div>
<Skeleton className="h-4 w-32" /> <EventResultsSkeleton />
<div className="space-y-3 pt-2"> </section>
<Skeleton className="h-4 w-full" /> </main>
<Skeleton className="h-4 w-5/6" />
<Skeleton className="h-10 w-full" />
</div>
</div>
</div>
))}
</div>
</div>
</div> </div>
); );
} }

View File

@@ -8,6 +8,7 @@ import { Link } from "@/lib/router";
import { buildAuthPath } from "@/lib/auth-return"; import { buildAuthPath } from "@/lib/auth-return";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { EventCard } from "@/components/events/EventCard"; import { EventCard } from "@/components/events/EventCard";
import { EventResultsSkeleton } from "@/components/events/EventResultsSkeleton";
import { EventFiltersDrawer } from "@/components/events/EventFiltersDrawer"; import { EventFiltersDrawer } from "@/components/events/EventFiltersDrawer";
import type { EventBrowsePageSchema } from "@/lib/types"; import type { EventBrowsePageSchema } from "@/lib/types";
import { api } from "@/lib/api"; import { api } from "@/lib/api";
@@ -34,37 +35,6 @@ function defaultFilters(search: string, priceCeiling: number): EventCatalogFilte
}; };
} }
function EventCardSkeleton() {
return (
<article aria-hidden="true" className="flex h-full min-w-0 flex-col overflow-hidden rounded-xl border border-border bg-card">
<div className="aspect-video w-full shrink-0 animate-pulse bg-muted motion-reduce:animate-none" />
<div className="flex flex-1 flex-col p-3 md:p-4">
<div className="ms-auto h-5 w-4/5 animate-pulse rounded bg-muted motion-reduce:animate-none" />
<div className="mt-3 grid gap-3 md:mt-4">
{["w-32", "w-40", "w-24", "w-36"].map((width) => (
<div key={width} className="flex items-center justify-end gap-2">
<div className={`h-3.5 ${width} animate-pulse rounded bg-muted motion-reduce:animate-none`} />
<div className="size-4 animate-pulse rounded-full bg-muted motion-reduce:animate-none" />
</div>
))}
</div>
<div className="mt-auto min-h-10 w-full animate-pulse rounded-md bg-muted pt-2 md:mt-5 md:min-h-11 motion-reduce:animate-none" />
</div>
</article>
);
}
function EventResultsSkeleton() {
return (
<div role="status" aria-live="polite" className="space-y-3">
<span className="sr-only">در حال اعمال فیلترها و دریافت رویدادها…</span>
<div aria-hidden="true" className="grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4 xl:grid-cols-3">
{Array.from({ length: 6 }, (_, index) => <EventCardSkeleton key={index} />)}
</div>
</div>
);
}
function getPageNumbers(total: number, current: number): Array<number | "ellipsis-left" | "ellipsis-right"> { function getPageNumbers(total: number, current: number): Array<number | "ellipsis-left" | "ellipsis-right"> {
if (total <= 7) return Array.from({ length: total }, (_, index) => index + 1); if (total <= 7) return Array.from({ length: total }, (_, index) => index + 1);