Created
March 12, 2025 18:05
-
-
Save ainsleyclark/fffac030ef3b81cfbf8f1fc09228cd07 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { lexicalHTML } from '@payloadcms/richtext-lexical'; | |
| import { CollectionConfig, PayloadRequest } from 'payload'; | |
| import { mergeCentres } from '@/collections/Centres/endpoints/mergeCentres'; | |
| import { renameCentreField } from '@/collections/Centres/endpoints/rename'; | |
| import { actions } from '@/collections/Centres/fields/actions'; | |
| import { agencies } from '@/collections/Centres/fields/agencies'; | |
| import { capabilitiesGrouped } from '@/collections/Centres/fields/capabilities'; | |
| import { contact } from '@/collections/Centres/fields/contact'; | |
| import { diveDestinations } from '@/collections/Centres/fields/diveDestinations'; | |
| import { nearbyCentres } from '@/collections/Centres/fields/nearbyCentres'; | |
| import { centreTypeField } from '@/collections/Centres/fields/type'; | |
| import { updateCapabilities } from '@/collections/Centres/hooks/capabilities'; | |
| import { updateGoogleData } from '@/collections/Centres/hooks/google'; | |
| import { updateCentrePages } from '@/collections/Centres/hooks/pages'; | |
| import { updateScore } from '@/collections/Centres/hooks/score'; | |
| import { updateType } from '@/collections/Centres/hooks/type'; | |
| import updateReviewAggregation from '@/collections/Reviews/hooks/aggregation'; | |
| import { Address } from '@/fields/Address'; | |
| import { Location } from '@/fields/Location'; | |
| import { ReviewAggregation } from '@/fields/ReviewAggregation'; | |
| import { SeaTemperatures } from '@/fields/seatemp'; | |
| import { URLField } from '@/fields/URL'; | |
| import { Weather } from '@/fields/weather'; | |
| import { Centre } from '@/types/payload'; | |
| import { frontendURL, urlPaths } from '@/util/url'; | |
| export const Centres: CollectionConfig = { | |
| slug: 'centres', | |
| dbName: 'centres', | |
| timestamps: true, | |
| labels: { | |
| singular: 'Centre', | |
| plural: 'Centres', | |
| }, | |
| versions: { | |
| drafts: true, | |
| maxPerDoc: 10, | |
| }, | |
| access: { | |
| read: () => true, | |
| }, | |
| defaultPopulate: { | |
| centrePage: false, | |
| }, | |
| admin: { | |
| group: 'Dive Centres', | |
| defaultColumns: ['id', 'name', 'url', 'score', 'agencies', 'updatedAt', 'createdAt'], | |
| useAsTitle: 'name', | |
| pagination: { | |
| defaultLimit: 50, | |
| limits: [10, 20, 50, 100], | |
| }, | |
| meta: { | |
| title: 'Dive Centres', | |
| }, | |
| preview: (doc): string | null => { | |
| return `${frontendURL()}${doc.url}`; | |
| } | |
| }, | |
| hooks: { | |
| beforeChange: [ | |
| updateCapabilities, | |
| updateType, | |
| updateCentrePages, | |
| ], | |
| afterChange: [ | |
| updateReviewAggregation, | |
| updateGoogleData, | |
| updateScore, | |
| ], | |
| }, | |
| endpoints: [ | |
| { | |
| path: '/merge', | |
| method: 'post', | |
| handler: mergeCentres, | |
| }, | |
| { | |
| path: '/rename/country', | |
| method: 'post', | |
| handler: async (req: PayloadRequest) => { | |
| return renameCentreField(req, 'countrySlug', 'country'); | |
| }, | |
| }, | |
| { | |
| path: '/rename/region', | |
| method: 'post', | |
| handler: async (req: PayloadRequest) => { | |
| return renameCentreField(req, 'regionSlug', 'region'); | |
| }, | |
| } | |
| ], | |
| fields: [ | |
| { | |
| type: 'tabs', | |
| tabs: [ | |
| { | |
| label: 'Content', | |
| description: '', | |
| fields: [ | |
| { | |
| name: 'name', | |
| type: 'text', | |
| required: true, | |
| label: 'Name', | |
| admin: { | |
| description: 'The official name of the dive centre obtained from the provider', | |
| }, | |
| }, | |
| { | |
| name: 'summary', | |
| label: 'Summary', | |
| type: 'textarea', | |
| localized: true, | |
| admin: { | |
| description: 'The brief outline of the dive centre that will appear on cards throughout the site', | |
| } | |
| }, | |
| { | |
| name: 'description', | |
| label: 'Description', | |
| type: 'richText', | |
| localized: true, | |
| admin: { | |
| description: 'Test', | |
| } | |
| }, | |
| lexicalHTML('description', { | |
| name: 'descriptionHtml', | |
| storeInDB: true, | |
| }), | |
| { | |
| type: 'row', | |
| fields: [ | |
| { | |
| name: 'isFiveStar', | |
| label: 'Is Five Star', | |
| type: 'checkbox', | |
| defaultValue: false, | |
| required: true, | |
| admin: { | |
| width: '33%', | |
| description: 'Determines if the dive centre 5 stars, this is what the provider classifies the centre as.', | |
| } | |
| }, | |
| { | |
| name: 'isClub', | |
| label: 'Is Club', | |
| type: 'checkbox', | |
| defaultValue: false, | |
| required: true, | |
| admin: { | |
| width: '33%', | |
| description: 'Determines if the dive centre if a club which usually means that the centre is not qualified for teaching courses.', | |
| } | |
| }, | |
| { | |
| name: 'isInstructor', | |
| label: 'Is Instructor', | |
| type: 'checkbox', | |
| defaultValue: false, | |
| required: true, | |
| admin: { | |
| width: '33%', | |
| description: 'Determines if the centre is a physical person instead of a company.', | |
| } | |
| }, | |
| ], | |
| }, | |
| { | |
| type: 'row', | |
| fields: [ | |
| { | |
| name: 'languages', | |
| label: 'Languages', | |
| type: 'text', | |
| hasMany: true, | |
| admin: { | |
| width: '50%', | |
| description: 'The languages associated with the centre', | |
| }, | |
| }, | |
| centreTypeField({ | |
| adminOptions: { | |
| width: '50%', | |
| readOnly: true, | |
| } | |
| }) | |
| ] | |
| }, | |
| { | |
| type: 'row', | |
| fields: [ | |
| { | |
| name: 'score', | |
| label: 'Score', | |
| type: 'number', | |
| required: true, | |
| defaultValue: 0, | |
| min: 0, | |
| max: 100, | |
| admin: { | |
| readOnly: true, | |
| description: 'The official Seek Scuba score of the dive centre which is automatically generated', | |
| width: '50%', | |
| }, | |
| }, | |
| { | |
| name: 'scoreOverride', | |
| label: 'Score Override', | |
| type: 'number', | |
| required: true, | |
| defaultValue: 0, | |
| min: 0, | |
| max: 100, | |
| access: { | |
| read: ({req}) => { | |
| return req.payloadAPI === 'local'; | |
| }, | |
| }, | |
| admin: { | |
| description: 'The Seek Scuba score override, you can use this to manually update the centre\'s score', | |
| width: '50%', | |
| } | |
| }, | |
| ] | |
| }, | |
| capabilitiesGrouped(), | |
| ] | |
| }, | |
| { | |
| label: 'Agencies', | |
| fields: agencies, | |
| }, | |
| { | |
| label: 'Media', | |
| fields: [ | |
| { | |
| name: 'media', | |
| label: '', | |
| type: 'group', | |
| admin: { | |
| hideGutter: true, | |
| }, | |
| fields: [ | |
| { | |
| name: 'featuredImage', | |
| label: 'Featured Image', | |
| type: 'upload', | |
| relationTo: 'media', | |
| filterOptions: { | |
| mimeType: {contains: 'image'}, | |
| }, | |
| }, | |
| { | |
| name: 'logo', | |
| label: 'Logo', | |
| type: 'upload', | |
| relationTo: 'media', | |
| filterOptions: { | |
| mimeType: {contains: 'image'}, | |
| }, | |
| }, | |
| { | |
| name: 'images', | |
| label: 'Images', | |
| type: 'upload', | |
| relationTo: 'media', | |
| hasMany: true, | |
| filterOptions: { | |
| mimeType: {contains: 'image'}, | |
| }, | |
| }, | |
| { | |
| name: 'videos', | |
| label: 'Videos', | |
| type: 'upload', | |
| relationTo: 'media', | |
| hasMany: true, | |
| filterOptions: { | |
| mimeType: {contains: 'video'}, | |
| }, | |
| }, | |
| ] | |
| } | |
| ], | |
| }, | |
| { | |
| label: 'Location', | |
| fields: [ | |
| Location({entity: 'dive centre'}), | |
| Address({entity: 'dive centre'}), | |
| ] | |
| }, | |
| { | |
| label: 'Contact', | |
| fields: contact, | |
| }, | |
| { | |
| label: 'Reviews', | |
| fields: [ | |
| { | |
| type: 'relationship', | |
| name: 'reviews', | |
| label: 'Reviews', | |
| relationTo: 'reviews', | |
| hasMany: true, | |
| admin: { | |
| allowCreate: false, | |
| }, | |
| }, | |
| ReviewAggregation(), | |
| ], | |
| }, | |
| { | |
| label: 'Meteorology', | |
| fields: [ | |
| SeaTemperatures(), | |
| Weather(), | |
| ], | |
| }, | |
| { | |
| label: 'Meta', | |
| description: 'Any other meta information associated with the Dive Centre.', | |
| fields: [ | |
| { | |
| name: 'centreMeta', | |
| label: 'Meta', | |
| type: 'json', | |
| defaultValue: '{}', | |
| admin: { | |
| description: 'Meta data associated with the dive centre', | |
| readOnly: true, | |
| } | |
| }, | |
| ], | |
| }, | |
| ], | |
| }, | |
| { | |
| name: 'centreButtons', | |
| type: 'ui', | |
| admin: { | |
| position: 'sidebar', | |
| components: { | |
| Field: { | |
| path: '/collections/Centres/components/Buttons#CentreButtons', | |
| } | |
| }, | |
| }, | |
| }, | |
| { | |
| name: 'slug', | |
| type: 'text', | |
| index: true, | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| }, | |
| { | |
| name: 'countrySlug', | |
| type: 'text', | |
| required: true, | |
| index: true, | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| }, | |
| { | |
| name: 'regionSlug', | |
| type: 'text', | |
| index: true, | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| }, | |
| URLField((data: Partial<Centre>) => { | |
| let url = `/${urlPaths.DIVE_CENTRES}/${data.countrySlug}/`; | |
| if (data.regionSlug && data.regionSlug !== '') { | |
| url += `${data.regionSlug}/`; | |
| } | |
| url += `${data.slug}/`; | |
| return url; | |
| }), | |
| { | |
| name: 'checkedAt', | |
| type: 'date', | |
| required: true, | |
| defaultValue: () => { | |
| return new Date(); | |
| }, | |
| admin: { | |
| hidden: true, | |
| position: 'sidebar', | |
| }, | |
| }, | |
| { | |
| name: 'website', | |
| label: 'Website', | |
| type: 'text', | |
| required: false, | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| }, | |
| { | |
| name: 'googlePlaceID', | |
| label: 'Google Place ID', | |
| type: 'text', | |
| admin: { | |
| position: 'sidebar', | |
| } | |
| }, | |
| actions, | |
| ], | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment