Skip to content

Commit 189ca6b

Browse files
Fix: Gallery
1 parent f450ca7 commit 189ca6b

8 files changed

Lines changed: 136 additions & 72 deletions

File tree

sanity/schemas/event.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,29 @@ export default {
4646
title: 'RSVP Link',
4747
type: 'url',
4848
},
49+
{
50+
name: 'gallery',
51+
title: 'Event Gallery',
52+
type: 'array',
53+
of: [
54+
{
55+
type: 'image',
56+
fields: [
57+
{
58+
name: 'caption',
59+
title: 'Caption',
60+
type: 'string',
61+
options: {
62+
isHighlighted: true,
63+
},
64+
},
65+
],
66+
options: {
67+
hotspot: true,
68+
},
69+
},
70+
],
71+
},
4972
],
5073
preview: {
5174
select: {

src/app/gallery/GalleryClient.js

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,66 @@
11
'use client';
22

3-
import React, { useState } from 'react';
3+
import React, { useState, useEffect } from 'react';
44
import Image from 'next/image';
55
import styles from './gallery.module.css';
6-
import { client } from '@/sanity/lib/client';
7-
import imageUrlBuilder from '@sanity/image-url';
8-
9-
const builder = imageUrlBuilder(client);
10-
const urlFor = (source) => builder.image(source);
116

127
const GalleryClient = ({ images }) => {
138
const [selectedImage, setSelectedImage] = useState(null);
149

1510
const openLightbox = (image) => setSelectedImage(image);
1611
const closeLightbox = () => setSelectedImage(null);
1712

13+
useEffect(() => {
14+
const handleKeyDown = (event) => {
15+
if (event.key === 'Escape') {
16+
closeLightbox();
17+
}
18+
};
19+
20+
if (selectedImage) {
21+
window.addEventListener('keydown', handleKeyDown);
22+
}
23+
24+
return () => {
25+
window.removeEventListener('keydown', handleKeyDown);
26+
};
27+
}, [selectedImage]);
28+
1829
return (
1930
<>
2031
<div className={styles.galleryGrid}>
2132
{images.map((image) => (
2233
<div
23-
key={image._id}
34+
key={image._key}
2435
className={styles.gridItem}
2536
onClick={() => openLightbox(image)}
2637
>
2738
<Image
28-
src={urlFor(image.imageUrl).url()}
39+
src={image.imageUrl}
2940
alt={image.alt}
3041
width={image.metadata.dimensions.width}
3142
height={image.metadata.dimensions.height}
3243
className={styles.image}
3344
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
3445
/>
3546
<div className={styles.overlay}>
36-
<h3 className={styles.imageTitle}>{image.title}</h3>
47+
<h3 className={styles.imageTitle}>{image.caption}</h3>
3748
</div>
3849
</div>
3950
))}
4051
</div>
4152

4253
{selectedImage && (
4354
<div className={styles.lightboxOverlay} onClick={closeLightbox}>
44-
<button className={styles.closeButton}>&times;</button>
4555
<div
4656
className={styles.lightboxContent}
4757
onClick={(e) => e.stopPropagation()}
4858
>
59+
<button className={styles.closeButton} onClick={closeLightbox}>
60+
&times;
61+
</button>
4962
<Image
50-
src={urlFor(selectedImage.imageUrl).url()}
63+
src={selectedImage.imageUrl}
5164
alt={selectedImage.alt}
5265
width={selectedImage.metadata.dimensions.width}
5366
height={selectedImage.metadata.dimensions.height}

src/app/gallery/gallery.module.css

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,43 +32,34 @@
3232
line-height: 1.6;
3333
}
3434

35-
/* --- Asymmetrical Grid --- */
35+
/* --- Masonry Grid Layout --- */
3636
.galleryGrid {
37-
display: grid;
38-
grid-template-columns: repeat(12, 1fr);
39-
grid-auto-rows: 300px;
40-
gap: 1.5rem;
37+
column-count: 3; /* Default for large screens */
38+
column-gap: 1.5rem;
4139
}
4240

4341
.gridItem {
4442
position: relative;
4543
overflow: hidden;
4644
border: 2px solid var(--text-primary);
47-
cursor: pointer; /* Add pointer cursor to indicate clickable */
45+
cursor: pointer;
46+
margin-bottom: 1.5rem; /* Space between rows */
47+
break-inside: avoid; /* Prevents items from breaking across columns */
48+
-webkit-column-break-inside: avoid;
49+
page-break-inside: avoid;
4850
}
4951

50-
/* --- Specific Item Placement for a Curated Look --- */
51-
.gridItem:nth-child(1) { grid-column: span 6; grid-row: span 2; }
52-
.gridItem:nth-child(2) { grid-column: span 3; grid-row: span 1; }
53-
.gridItem:nth-child(3) { grid-column: span 3; grid-row: span 1; }
54-
.gridItem:nth-child(4) { grid-column: span 6; grid-row: span 2; }
55-
.gridItem:nth-child(5) { grid-column: span 3; grid-row: span 1; }
56-
.gridItem:nth-child(6) { grid-column: span 3; grid-row: span 2; }
57-
.gridItem:nth-child(7) { grid-column: span 3; grid-row: span 1; }
58-
.gridItem:nth-child(8) { grid-column: span 3; grid-row: span 1; }
59-
.gridItem:nth-child(9) { grid-column: span 6; grid-row: span 1; }
60-
61-
6252
.image {
6353
width: 100%;
64-
height: 100%;
54+
height: auto; /* Let height be natural */
6555
object-fit: cover;
6656
transition: transform 0.4s ease, opacity 0.4s ease;
57+
display: block; /* Remove any bottom space */
6758
}
6859

6960
.gridItem:hover .image {
7061
transform: scale(1.05);
71-
opacity: 0.7; /* New hover effect */
62+
opacity: 0.7;
7263
}
7364

7465
/* --- Overlay & Title --- */
@@ -122,46 +113,44 @@
122113

123114
.lightboxContent {
124115
position: relative;
125-
max-width: 90vw;
126-
max-height: 90vh;
116+
width: 90vw;
117+
height: 90vh;
127118
}
128119

129120
.lightboxImage {
130-
width: auto;
131-
height: auto;
132-
max-width: 100%;
133-
max-height: 100%;
121+
width: 100%;
122+
height: 100%;
134123
object-fit: contain;
135124
}
136125

137126
.closeButton {
138127
position: absolute;
139-
top: -2.5rem;
140-
right: 0;
141-
background: none;
128+
top: 1rem;
129+
right: 1rem;
130+
background: rgba(0, 0, 0, 0.5);
142131
border: none;
143132
color: white;
144-
font-size: 2.5rem;
133+
font-size: 2rem;
145134
cursor: pointer;
135+
z-index: 1001; /* Ensure it's above the image */
136+
border-radius: 50%;
137+
width: 40px;
138+
height: 40px;
139+
line-height: 40px;
140+
text-align: center;
146141
}
147142

148-
149143
/* --- Responsive Adjustments --- */
150144
@media (max-width: 1200px) {
151-
.gridItem:nth-child(n) {
152-
grid-column: span 6;
153-
grid-row: span 1;
145+
.galleryGrid {
146+
column-count: 2; /* Two columns for tablets */
154147
}
155-
.gridItem:nth-child(1) { grid-row: span 2; }
156-
.gridItem:nth-child(4) { grid-row: span 2; }
157148
}
158149

159150
@media (max-width: 768px) {
160151
.container { padding: 4rem 1rem; }
161152
.title { font-size: 3rem; }
162-
.galleryGrid { grid-auto-rows: 250px; }
163-
.gridItem:nth-child(n) {
164-
grid-column: span 12;
165-
grid-row: span 1;
153+
.galleryGrid {
154+
column-count: 1; /* Single column for mobile */
166155
}
167156
}

src/app/gallery/page.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,18 @@ export const revalidate = 0;
1313
async function getGalleryImages() {
1414
noStore(); // 🔒 disable caching for this fetch path
1515

16-
const query = `*[_type == "galleryImage"] | order(_createdAt desc)[0...9]{
17-
_id,
18-
title,
19-
alt,
20-
"imageUrl": image.asset->url,
21-
"metadata": image.asset->metadata
22-
}`;
23-
24-
return client.fetch(query); // no { next:{...} } here
16+
const query = `*[_type == "gallery"] | order(_createdAt desc) {
17+
"images": images[]{
18+
_key,
19+
alt,
20+
caption,
21+
"imageUrl": image.asset->url,
22+
"metadata": image.asset->metadata
23+
}
24+
}.images`;
25+
26+
const result = await client.fetch(query);
27+
return result ? result.flat().slice(0, 9) : [];
2528
}
2629

2730
export default async function GalleryPage() {

src/sanity/schemaTypes/gallery.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// src/sanity/schemaTypes/gallery.js
2+
export default {
3+
name: 'gallery',
4+
title: 'Gallery',
5+
type: 'document',
6+
fields: [
7+
{
8+
name: 'title',
9+
title: 'Title',
10+
type: 'string',
11+
description: 'A title for this gallery collection (e.g., "Workshop Photos").',
12+
validation: (Rule) => Rule.required(),
13+
},
14+
{
15+
name: 'images',
16+
title: 'Images',
17+
type: 'array',
18+
of: [
19+
{
20+
type: 'galleryImage',
21+
},
22+
],
23+
options: {
24+
layout: 'grid',
25+
},
26+
},
27+
],
28+
preview: {
29+
select: {
30+
title: 'title',
31+
media: 'images.0.image.asset'
32+
}
33+
}
34+
}

src/sanity/schemaTypes/galleryImage.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,8 @@
22
export default {
33
name: 'galleryImage',
44
title: 'Gallery Image',
5-
type: 'document',
5+
type: 'object',
66
fields: [
7-
{
8-
name: 'title',
9-
title: 'Title',
10-
type: 'string',
11-
description: 'A descriptive title for the image.',
12-
},
137
{
148
name: 'image',
159
title: 'Image',
@@ -19,12 +13,19 @@ export default {
1913
},
2014
validation: (Rule) => Rule.required(),
2115
},
16+
{
17+
name: 'caption',
18+
title: 'Caption',
19+
type: 'string',
20+
options: {
21+
isHighlighted: true,
22+
},
23+
},
2224
{
2325
name: 'alt',
2426
title: 'Alternative Text',
2527
type: 'string',
2628
description: 'Important for accessibility. Describe the image for screen readers.',
27-
validation: (Rule) => Rule.required(),
2829
},
2930
],
3031
}

src/sanity/schemaTypes/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import event from './event'
22
import member from './member'
3-
import galleryImage from './galleryImage'
43
import project from './project'
54
import projectProposal from './projectProposal'
5+
import gallery from './gallery'
6+
import galleryImage from './galleryImage'
67

7-
export const schemaTypes = [event, member, galleryImage, project, projectProposal]
8+
export const schemaTypes = [event, member, project, projectProposal, gallery, galleryImage]
89

src/sanity/structure.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const structure = (S) =>
2323
.title('Projects')
2424
.child(S.documentList().title('Projects').filter('_type == "project"')),
2525
S.listItem()
26-
.title('Gallery Images')
27-
.child(S.documentList().title('Gallery Images').filter('_type == "galleryImage"')),
26+
.title('Galleries')
27+
.child(S.documentList().title('Galleries').filter('_type == "gallery"')),
2828
])
2929

0 commit comments

Comments
 (0)