126 lines
3 KiB
TypeScript
126 lines
3 KiB
TypeScript
import {defineArrayMember, defineField, defineType} from 'sanity'
|
|
import {CalendarIcon} from '@sanity/icons'
|
|
import {countryList} from './country-list'
|
|
import {CountryInput} from '../components/CountryInput'
|
|
|
|
export const concertType = defineType({
|
|
name: 'concert',
|
|
title: 'Concert',
|
|
type: 'document',
|
|
icon: CalendarIcon,
|
|
|
|
fieldsets: [{name: 'details', title: 'Details', options: {columns: 2}}],
|
|
|
|
fields: [
|
|
defineField({
|
|
name: 'title',
|
|
title: 'Title',
|
|
type: 'string',
|
|
}),
|
|
defineField({
|
|
name: 'subtitle',
|
|
title: 'Subtitle',
|
|
type: 'string',
|
|
}),
|
|
|
|
defineField({
|
|
name: 'date',
|
|
title: 'Date',
|
|
type: 'date',
|
|
fieldset: 'details',
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
defineField({
|
|
name: 'time',
|
|
title: 'Time',
|
|
type: 'string',
|
|
fieldset: 'details',
|
|
description: '24-hour format, e.g. 20:00',
|
|
validation: (Rule) =>
|
|
Rule.required().custom((value) => {
|
|
if (typeof value !== 'string') return 'Time is required'
|
|
return /^([01]\d|2[0-3]):[0-5]\d$/.test(value.trim())
|
|
? true
|
|
: 'Use HH:mm in 24-hour format (e.g. 14:30, 20:00)'
|
|
}),
|
|
}),
|
|
|
|
defineField({
|
|
name: 'locationName',
|
|
title: 'Location',
|
|
type: 'string',
|
|
fieldset: 'details',
|
|
description: 'e.g. "Concertgebouw"',
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
defineField({
|
|
name: 'city',
|
|
title: 'City',
|
|
type: 'string',
|
|
fieldset: 'details',
|
|
description: 'e.g. "Amsterdam"',
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
defineField({
|
|
name: 'country',
|
|
title: 'Country',
|
|
type: 'string',
|
|
fieldset: 'details',
|
|
components: {input: CountryInput},
|
|
options: {
|
|
list: countryList,
|
|
},
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
|
|
defineField({
|
|
name: 'artists',
|
|
title: 'Related Artist(s)',
|
|
type: 'array',
|
|
of: [defineArrayMember({type: 'reference', to: [{type: 'artist'}]})],
|
|
}),
|
|
|
|
defineField({
|
|
name: 'ticketUrl',
|
|
title: 'Ticket URL',
|
|
type: 'url',
|
|
}),
|
|
],
|
|
|
|
orderings: [
|
|
{
|
|
title: 'Date (Asc.)',
|
|
name: 'dateAsc',
|
|
by: [
|
|
{field: 'date', direction: 'asc'},
|
|
{field: 'time', direction: 'asc'},
|
|
],
|
|
},
|
|
{
|
|
title: 'Date (Desc.)',
|
|
name: 'dateDesc',
|
|
by: [
|
|
{field: 'date', direction: 'desc'},
|
|
{field: 'time', direction: 'desc'},
|
|
],
|
|
},
|
|
],
|
|
|
|
preview: {
|
|
select: {
|
|
title: 'title',
|
|
date: 'date',
|
|
time: 'time',
|
|
locationName: 'locationName',
|
|
city: 'city',
|
|
},
|
|
prepare({title, date, time, locationName, city}) {
|
|
const parts = [locationName, city].filter(Boolean).join(', ')
|
|
const when = [date, time].filter(Boolean).join(' · ')
|
|
return {
|
|
title: title || parts || '(Untitled concert)',
|
|
subtitle: [when, title ? parts : null].filter(Boolean).join(' • '),
|
|
}
|
|
},
|
|
},
|
|
})
|