-
|
navigate(`/admin/events/${event.id}`)}>
diff --git a/src/views/EventDetail.tsx b/src/views/EventDetail.tsx
index be19a93..dfcc819 100644
--- a/src/views/EventDetail.tsx
+++ b/src/views/EventDetail.tsx
@@ -8,6 +8,8 @@ import type * as Types from "@/lib/types";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
+import GalleryLightbox, { type GalleryLightboxItem } from "@/components/GalleryLightbox";
+import ProgressiveImage from "@/components/ProgressiveImage";
import { useToast } from "@/hooks/use-toast";
import Markdown from "@/components/Markdown";
import CouponDialogFa from "@/components/CouponDialogFa";
@@ -15,7 +17,12 @@ import {
formatJalali,
formatNumberPersian,
formatToman,
- getThumbUrl,
+ getEventCardImageUrl,
+ getEventHeroImageUrl,
+ getEventSeoImageUrl,
+ getGalleryImageBlurUrl,
+ getGalleryImageFullUrl,
+ getGalleryImagePreviewUrl,
resolveErrorMessage,
toPersianDigits,
} from "@/lib/utils";
@@ -62,8 +69,9 @@ export default function EventDetail({ initialEvent = null }: EventDetailProps) {
const [event, setEvent] = useState(initialEvent);
const [eventThumb, setEventThumb] = useState(
- initialEvent ? getThumbUrl(initialEvent) : null,
+ initialEvent ? getEventCardImageUrl(initialEvent) : null,
);
+ const [lightboxIndex, setLightboxIndex] = useState(null);
const [loading, setLoading] = useState(!initialEvent);
const [open, setOpen] = useState(false);
const [submitting, setSubmitting] = useState(false);
@@ -94,7 +102,7 @@ export default function EventDetail({ initialEvent = null }: EventDetailProps) {
const canonicalUrl = event ? `${siteUrl}/events/${event.slug}` : `${siteUrl}/events`;
const primaryImage = event
- ? toAbsoluteUrl(getThumbUrl(event)) ?? `${siteUrl}/favicon.ico`
+ ? toAbsoluteUrl(getEventSeoImageUrl(event)) ?? `${siteUrl}/favicon.ico`
: `${siteUrl}/favicon.ico`;
const pageTitle = event ? `${event.title} | ${siteName}` : `جزئیات رویداد | ${siteName}`;
const pageDescription = sanitizeDescription(event?.description);
@@ -257,14 +265,14 @@ export default function EventDetail({ initialEvent = null }: EventDetailProps) {
if (initialEvent && initialEvent.slug === slug) {
setEvent(initialEvent);
- setEventThumb(getThumbUrl(initialEvent));
+ setEventThumb(getEventCardImageUrl(initialEvent));
return;
}
const data = await api.getEventBySlug(slug);
if (cancelled) return;
setEvent(data);
- setEventThumb(getThumbUrl(data));
+ setEventThumb(getEventCardImageUrl(data));
} catch (error: unknown) {
if (cancelled) return;
toast({
@@ -335,6 +343,19 @@ export default function EventDetail({ initialEvent = null }: EventDetailProps) {
return { registrationOpen, remaining, full };
}, [deadlineTs, event, nowTs, rsTs]);
+ const galleryItems = useMemo(
+ () =>
+ (event?.gallery_images ?? []).map((image) => ({
+ id: image.id,
+ alt: image.title || event?.title || "تصویر رویداد",
+ title: image.title,
+ previewSrc: getGalleryImagePreviewUrl(image),
+ blurSrc: getGalleryImageBlurUrl(image),
+ fullSrc: getGalleryImageFullUrl(image),
+ })),
+ [event],
+ );
+
const eventStructuredData = useMemo(() => {
if (!event) return null;
@@ -501,12 +522,12 @@ export default function EventDetail({ initialEvent = null }: EventDetailProps) {
-
@@ -529,17 +550,25 @@ export default function EventDetail({ initialEvent = null }: EventDetailProps) {
- {event.gallery_images?.length ? (
+ {galleryItems.length ? (
گالری تصاویر
- {event.gallery_images.map((image) => (
- ![]() (
+
+ type="button"
+ className="overflow-hidden rounded-md text-right transition-transform hover:scale-[1.01] focus:outline-none focus:ring-2 focus:ring-primary/40"
+ onClick={() => setLightboxIndex(index)}
+ >
+
+
))}
@@ -608,6 +637,17 @@ export default function EventDetail({ initialEvent = null }: EventDetailProps) {
+
+ {
+ if (!isOpen) {
+ setLightboxIndex(null);
+ }
+ }}
+ />
);
}
diff --git a/src/views/Events.tsx b/src/views/Events.tsx
index 82a8b7c..d01ec4e 100644
--- a/src/views/Events.tsx
+++ b/src/views/Events.tsx
@@ -8,8 +8,9 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
+import ProgressiveImage from "@/components/ProgressiveImage";
import type * as Types from "@/lib/types";
-import { formatJalali, formatNumberPersian, formatToman, getThumbUrl } from "@/lib/utils";
+import { formatJalali, formatNumberPersian, formatToman, getEventCardImageUrl } from "@/lib/utils";
import { siteUrl } from "@/lib/site";
type EventsProps = {
@@ -73,7 +74,7 @@ export default function Events({
const ogImage = useMemo(() => {
if (!events.length) return `${siteUrl}/favicon.ico`;
- return toAbsoluteUrl(getThumbUrl(events[0])) ?? `${siteUrl}/favicon.ico`;
+ return toAbsoluteUrl(getEventCardImageUrl(events[0])) ?? `${siteUrl}/favicon.ico`;
}, [events]);
const listStructuredData = useMemo(() => {
@@ -93,7 +94,7 @@ export default function Events({
listItem.endDate = eventItem.end_time;
}
- const imageUrl = toAbsoluteUrl(getThumbUrl(eventItem));
+ const imageUrl = toAbsoluteUrl(getEventCardImageUrl(eventItem));
if (imageUrl) {
listItem.image = imageUrl;
}
@@ -210,12 +211,11 @@ export default function Events({
-
|