Skip to content

Commit bf2646e

Browse files
authored
wip: page for the photographer (#325)
1 parent b583393 commit bf2646e

5 files changed

Lines changed: 160 additions & 2 deletions

File tree

sanity/schema.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import travelSupport from './schemaTypes/travelSupport'
2323
import travelExpense from './schemaTypes/travelExpense'
2424
import volunteer from './schemaTypes/volunteer'
2525
import workshopSignup from './schemaTypes/workshopSignup'
26+
import staff from './schemaTypes/staff'
2627

2728
export const schema: { types: SchemaTypeDefinition[] } = {
2829
types: [
@@ -38,6 +39,7 @@ export const schema: { types: SchemaTypeDefinition[] } = {
3839
dashboardConfig,
3940
imageGallery,
4041
volunteer,
42+
staff,
4143

4244
// Topics & Talks
4345
talk,
@@ -54,10 +56,10 @@ export const schema: { types: SchemaTypeDefinition[] } = {
5456

5557
// Sponsors
5658
sponsor,
57-
sponsorTier,
58-
sponsorForConference,
5959
sponsorActivity,
6060
sponsorEmailTemplate,
61+
sponsorForConference,
62+
sponsorTier,
6163
contractTemplate,
6264
],
6365
}

sanity/schemaTypes/staff.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { defineField, defineType } from 'sanity'
2+
3+
export default defineType({
4+
name: 'staff',
5+
title: 'Staff',
6+
type: 'document',
7+
fields: [
8+
defineField({
9+
name: 'name',
10+
title: 'Name',
11+
type: 'string',
12+
validation: (Rule) => Rule.required(),
13+
}),
14+
defineField({
15+
name: 'role',
16+
title: 'Role',
17+
type: 'string',
18+
validation: (Rule) => Rule.required(),
19+
}),
20+
defineField({
21+
name: 'email',
22+
title: 'Email',
23+
type: 'string',
24+
validation: (Rule) => Rule.required(),
25+
}),
26+
defineField({
27+
name: 'company',
28+
title: 'Company',
29+
type: 'string',
30+
validation: (Rule) => Rule.required(),
31+
}),
32+
defineField({
33+
name: 'image',
34+
title: 'Image',
35+
type: 'image',
36+
options: {
37+
hotspot: true,
38+
},
39+
fields: [
40+
{
41+
name: 'alt',
42+
type: 'string',
43+
title: 'Alternative Text',
44+
},
45+
],
46+
}),
47+
defineField({
48+
name: 'link',
49+
title: 'Link',
50+
type: 'url',
51+
validation: (Rule) => Rule.required(),
52+
}),
53+
],
54+
preview: {
55+
select: {
56+
title: 'name',
57+
media: 'image',
58+
},
59+
},
60+
})
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import Image from 'next/image'
2+
import { cacheLife, cacheTag } from 'next/cache'
3+
import { getStaffMembers } from '@/lib/staff/sanity'
4+
import { Container } from '@/components/Container'
5+
6+
async function CachedStaffContent({ role }: { role: string }) {
7+
'use cache'
8+
cacheLife('hours')
9+
cacheTag('content:staff')
10+
11+
const staff = await getStaffMembers(role)
12+
13+
return (
14+
<>
15+
<div className="mx-auto max-w-2xl px-4 py-10 sm:px-6 lg:max-w-4xl lg:px-8">
16+
<Container className="relative print:max-w-none print:px-0">
17+
<h1 className="font-jetbrains text-4xl font-bold tracking-tighter text-brand-cloud-blue sm:text-6xl dark:text-blue-400">
18+
Photographers
19+
</h1>
20+
{staff.data.length === 0 && 'No staff found'}
21+
{staff.data.map((member) => {
22+
return (
23+
<div
24+
key={member.id ?? Math.floor(Math.random() * 10000)}
25+
className="mx-auto max-w-2xl px-4 py-10 sm:px-6 lg:max-w-4xl lg:px-8"
26+
>
27+
<h3 className="font-jetbrains text-3xl font-bold tracking-tighter text-brand-cloud-blue sm:text-5xl dark:text-blue-400">
28+
{member.name}
29+
</h3>
30+
<div className="mt-7 columns-1 gap-6 md:columns-2">
31+
<a href={member.link.toString()}>{member.name}</a>
32+
<Image
33+
src={
34+
member.imageURL?.toString() ??
35+
'https://placehold.co/800x600/e5e7eb/6b7280?text=Photographer'
36+
}
37+
alt={member.name}
38+
width={800}
39+
height={600}
40+
className="rounded-md"
41+
unoptimized
42+
/>
43+
</div>
44+
</div>
45+
)
46+
})}
47+
</Container>
48+
</div>
49+
</>
50+
)
51+
}
52+
53+
export default async function StaffPage({
54+
params,
55+
}: {
56+
params: Promise<{ role: string }>
57+
}) {
58+
const { role } = await params
59+
return <CachedStaffContent role={role} />
60+
}

src/lib/staff/sanity.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Staff } from '@/lib/staff/types'
2+
import { clientReadUncached as clientRead } from '@/lib/sanity/client'
3+
import { defineQuery } from 'next-sanity'
4+
5+
export async function getStaffMembers(
6+
role: string,
7+
): Promise<{ data: Staff[]; err?: Error }> {
8+
const query = defineQuery(`
9+
* [_type == "staff" && role == $role]
10+
{
11+
"id": _id,
12+
name,
13+
role,
14+
email,
15+
company,
16+
"imageURL": image.asset->url,
17+
link
18+
}
19+
`)
20+
21+
try {
22+
const queryResult = await clientRead.fetch<Staff[]>(query, { role: role })
23+
return { data: queryResult }
24+
} catch (error) {
25+
return { data: [], err: error as Error }
26+
}
27+
}

src/lib/staff/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface Staff {
2+
id: string
3+
name: string
4+
role: string
5+
email?: string
6+
company?: string
7+
imageURL?: URL
8+
link: URL
9+
}

0 commit comments

Comments
 (0)