From a113a7ae2ad0314f132bf1a3e4e06d956e02ec2b Mon Sep 17 00:00:00 2001 From: christinaroise Date: Tue, 3 Sep 2024 14:14:46 +0200 Subject: [PATCH 01/10] cleanup compensation and add compensationDetails --- studio/schemas/documents/compensations.ts | 33 ++++++++++++++-------- studio/schemas/objects/compensationData.ts | 32 +++++++++++++++++++++ 2 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 studio/schemas/objects/compensationData.ts diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index 44d57f3c5..70f9934ab 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -4,6 +4,7 @@ import seo from "../objects/seo"; import locations from "../objects/locations"; import { title } from "../fields/text"; import { benefitId } from "./benefit"; +import { compensationDetails } from "../objects/compensationData"; // maximum number of locations to display in the preview without truncating const LOCATIONS_PREVIEW_CUTOFF = 3; @@ -15,17 +16,21 @@ const compensations = defineType({ type: "document", title: "Compensations", fields: [ - locations, title, titleSlug, - seo, + locations, defineField({ - name: "showSalaryCalculator", - title: "Show Salary Calculator", - description: "Should the salary calculator be visible on the page?", - type: "boolean", - initialValue: true, + ...compensationDetails, + readOnly: ({ parent }) => !parent?.showEstimatedSalary, }), + { + name: "showEstimatedSalary", + title: "Show Estimated Salary", + type: "boolean", + description: + "Toggle this option to show or hide the estimated salary for the locations you've selected. Disable this if the feature isn't ready or if you prefer not to display salary details at this time.", + initialValue: false, + }, defineField({ name: "benefits", title: "Benefits", @@ -33,6 +38,12 @@ const compensations = defineType({ type: "array", of: [{ type: benefitId }], }), + { + ...seo, + options: { + collapsed: true, + }, + }, ], preview: { select: { @@ -44,7 +55,7 @@ const compensations = defineType({ */ ...[...Array(LOCATIONS_PREVIEW_CUTOFF + 1).keys()].reduce( (o, i) => ({ ...o, [`location${i}`]: `locations.${i}.basicTitle` }), - {}, + {} ), }, prepare({ title, ...locationsMap }) { @@ -52,7 +63,7 @@ const compensations = defineType({ title, subtitle: previewStringFromLocationsMap( locationsMap, - LOCATIONS_PREVIEW_CUTOFF, + LOCATIONS_PREVIEW_CUTOFF ), }; }, @@ -70,10 +81,10 @@ function previewStringFromLocationsMap( locationsMap: { [key: string]: string; }, - cutoff: number, + cutoff: number ): string | undefined { const locations = Object.values(locationsMap).filter( - (o) => o !== undefined, + (o) => o !== undefined ); if (locations.length === 0) { return undefined; diff --git a/studio/schemas/objects/compensationData.ts b/studio/schemas/objects/compensationData.ts new file mode 100644 index 000000000..c662ba436 --- /dev/null +++ b/studio/schemas/objects/compensationData.ts @@ -0,0 +1,32 @@ +import { defineField } from "sanity"; + +export const compensationDetailsID = "compensationDetails"; + +export const compensationDetails = defineField({ + name: compensationDetailsID, + title: "Compensation Details", + description: + "Add and manage detailed information on compensation elements like salary, bonuses, pensions, and other financial benefits.", + type: "object", + options: { + collapsible: true, + collapsed: true, + }, + fields: [ + { + name: "replaceMe", + title: "Replace me", + type: "string", + }, + ], + preview: { + select: { + title: "basicTitle", + }, + prepare(selection) { + return { + title: selection.title, + }; + }, + }, +}); From bd82336294a5ee54b538ba698c9c7cb9ce5666cc Mon Sep 17 00:00:00 2001 From: christinaroise Date: Tue, 3 Sep 2024 14:17:35 +0200 Subject: [PATCH 02/10] keep seo.collapsed as false --- studio/schemas/documents/compensations.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index 70f9934ab..3ed19df20 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -38,12 +38,7 @@ const compensations = defineType({ type: "array", of: [{ type: benefitId }], }), - { - ...seo, - options: { - collapsed: true, - }, - }, + seo, ], preview: { select: { From 00999918fa1a97230e2811c1c096c97013abce46 Mon Sep 17 00:00:00 2001 From: christinaroise Date: Tue, 3 Sep 2024 14:21:41 +0200 Subject: [PATCH 03/10] fix lint --- studio/schemas/documents/compensations.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index 3ed19df20..3ddb37ada 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -50,7 +50,7 @@ const compensations = defineType({ */ ...[...Array(LOCATIONS_PREVIEW_CUTOFF + 1).keys()].reduce( (o, i) => ({ ...o, [`location${i}`]: `locations.${i}.basicTitle` }), - {} + {}, ), }, prepare({ title, ...locationsMap }) { @@ -58,7 +58,7 @@ const compensations = defineType({ title, subtitle: previewStringFromLocationsMap( locationsMap, - LOCATIONS_PREVIEW_CUTOFF + LOCATIONS_PREVIEW_CUTOFF, ), }; }, @@ -76,10 +76,10 @@ function previewStringFromLocationsMap( locationsMap: { [key: string]: string; }, - cutoff: number + cutoff: number, ): string | undefined { const locations = Object.values(locationsMap).filter( - (o) => o !== undefined + (o) => o !== undefined, ); if (locations.length === 0) { return undefined; From fe576903699fc41b55602fd19ffd9dd637dd4eb0 Mon Sep 17 00:00:00 2001 From: christinaroise Date: Tue, 3 Sep 2024 15:07:02 +0200 Subject: [PATCH 04/10] move show toggle above compensation details --- studio/schemas/documents/compensations.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index 3ddb37ada..ccfca3c9c 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -19,10 +19,6 @@ const compensations = defineType({ title, titleSlug, locations, - defineField({ - ...compensationDetails, - readOnly: ({ parent }) => !parent?.showEstimatedSalary, - }), { name: "showEstimatedSalary", title: "Show Estimated Salary", @@ -31,6 +27,10 @@ const compensations = defineType({ "Toggle this option to show or hide the estimated salary for the locations you've selected. Disable this if the feature isn't ready or if you prefer not to display salary details at this time.", initialValue: false, }, + defineField({ + ...compensationDetails, + readOnly: ({ parent }) => !parent?.showEstimatedSalary, + }), defineField({ name: "benefits", title: "Benefits", @@ -50,7 +50,7 @@ const compensations = defineType({ */ ...[...Array(LOCATIONS_PREVIEW_CUTOFF + 1).keys()].reduce( (o, i) => ({ ...o, [`location${i}`]: `locations.${i}.basicTitle` }), - {}, + {} ), }, prepare({ title, ...locationsMap }) { @@ -58,7 +58,7 @@ const compensations = defineType({ title, subtitle: previewStringFromLocationsMap( locationsMap, - LOCATIONS_PREVIEW_CUTOFF, + LOCATIONS_PREVIEW_CUTOFF ), }; }, @@ -76,10 +76,10 @@ function previewStringFromLocationsMap( locationsMap: { [key: string]: string; }, - cutoff: number, + cutoff: number ): string | undefined { const locations = Object.values(locationsMap).filter( - (o) => o !== undefined, + (o) => o !== undefined ); if (locations.length === 0) { return undefined; From 362c272e0228e658ca83cda57bb1554f2b714bce Mon Sep 17 00:00:00 2001 From: christinaroise Date: Tue, 3 Sep 2024 15:25:40 +0200 Subject: [PATCH 05/10] move toggle inside details --- studio/schemas/documents/compensations.ts | 13 +------------ studio/schemas/objects/compensationData.ts | 13 +++++++++++-- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index ccfca3c9c..1e918a0ac 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -19,18 +19,7 @@ const compensations = defineType({ title, titleSlug, locations, - { - name: "showEstimatedSalary", - title: "Show Estimated Salary", - type: "boolean", - description: - "Toggle this option to show or hide the estimated salary for the locations you've selected. Disable this if the feature isn't ready or if you prefer not to display salary details at this time.", - initialValue: false, - }, - defineField({ - ...compensationDetails, - readOnly: ({ parent }) => !parent?.showEstimatedSalary, - }), + compensationDetails, defineField({ name: "benefits", title: "Benefits", diff --git a/studio/schemas/objects/compensationData.ts b/studio/schemas/objects/compensationData.ts index c662ba436..5075545c1 100644 --- a/studio/schemas/objects/compensationData.ts +++ b/studio/schemas/objects/compensationData.ts @@ -6,17 +6,26 @@ export const compensationDetails = defineField({ name: compensationDetailsID, title: "Compensation Details", description: - "Add and manage detailed information on compensation elements like salary, bonuses, pensions, and other financial benefits.", + "Add and manage detailed information on compensation elements like estimated salary, bonuses, pensions, and other financial benefits.", type: "object", options: { collapsible: true, - collapsed: true, + collapsed: false, }, fields: [ + { + name: "showEstimatedSalary", + title: "Show Estimated Salary", + type: "boolean", + description: + "Toggle this option to show or hide the estimated salary for the locations you've selected. Disable this if the feature isn't ready or if you prefer not to display salary details at this time.", + initialValue: false, + }, { name: "replaceMe", title: "Replace me", type: "string", + readOnly: ({ parent }) => !parent?.showEstimatedSalary, }, ], preview: { From 506c90a6d5f5c88b402504b91da63b71caffac27 Mon Sep 17 00:00:00 2001 From: christinaroise Date: Tue, 3 Sep 2024 15:28:50 +0200 Subject: [PATCH 06/10] update benefits title and description --- studio/schemas/documents/compensations.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index 1e918a0ac..2160a096f 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -22,8 +22,9 @@ const compensations = defineType({ compensationDetails, defineField({ name: "benefits", - title: "Benefits", - description: "Manage benefits for the compensations page", + title: "Included Benefits", + description: + "Add and manage information on the benefits included with the compensation package, such as health insurance, retirement plans, and paid time off.", type: "array", of: [{ type: benefitId }], }), From f56a048d10df20d76d6d094f615d8c63dd2ad246 Mon Sep 17 00:00:00 2001 From: christinaroise Date: Tue, 3 Sep 2024 15:29:01 +0200 Subject: [PATCH 07/10] fix lint --- studio/schemas/documents/compensations.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index 2160a096f..70f316a8b 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -40,7 +40,7 @@ const compensations = defineType({ */ ...[...Array(LOCATIONS_PREVIEW_CUTOFF + 1).keys()].reduce( (o, i) => ({ ...o, [`location${i}`]: `locations.${i}.basicTitle` }), - {} + {}, ), }, prepare({ title, ...locationsMap }) { @@ -48,7 +48,7 @@ const compensations = defineType({ title, subtitle: previewStringFromLocationsMap( locationsMap, - LOCATIONS_PREVIEW_CUTOFF + LOCATIONS_PREVIEW_CUTOFF, ), }; }, @@ -66,10 +66,10 @@ function previewStringFromLocationsMap( locationsMap: { [key: string]: string; }, - cutoff: number + cutoff: number, ): string | undefined { const locations = Object.values(locationsMap).filter( - (o) => o !== undefined + (o) => o !== undefined, ); if (locations.length === 0) { return undefined; From b9dc3461ff789faf7c911c41a29c389253be7fa4 Mon Sep 17 00:00:00 2001 From: christinaroise Date: Wed, 4 Sep 2024 13:57:47 +0200 Subject: [PATCH 08/10] cleanup compensation and group location specific bonus --- studio/schema.ts | 4 +- studio/schemas/deskStructure.ts | 24 +++-- studio/schemas/documents/companyLocations.ts | 20 ++++ studio/schemas/documents/compensations.ts | 84 +++++++--------- studio/schemas/documents/location.ts | 14 --- studio/schemas/objects/compensationData.ts | 41 -------- .../compensations/bonusesByLocation.ts | 97 +++++++++++++++++++ studio/schemas/objects/locations.ts | 34 ++++--- studio/schemas/objects/seo.ts | 4 +- 9 files changed, 191 insertions(+), 131 deletions(-) create mode 100644 studio/schemas/documents/companyLocations.ts delete mode 100644 studio/schemas/documents/location.ts delete mode 100644 studio/schemas/objects/compensationData.ts create mode 100644 studio/schemas/objects/compensations/bonusesByLocation.ts diff --git a/studio/schema.ts b/studio/schema.ts index 043f5c69e..22220e0c0 100644 --- a/studio/schema.ts +++ b/studio/schema.ts @@ -12,7 +12,7 @@ import posts from "./schemas/documents/post"; import categories from "./schemas/fields/categories"; import legalDocument from "./schemas/documents/legalDocuments"; import benefit from "./schemas/documents/benefit"; -import location from "./schemas/documents/location"; +import companyLocations from "./schemas/documents/companyLocations"; import compensations from "./schemas/documents/compensations"; import salaryAndBenefits from "./schemas/documents/salaryAndBenefits"; import siteSettings from "./schemas/documents/siteSettings"; @@ -35,6 +35,6 @@ export const schema: { types: SchemaTypeDefinition[] } = { compensations, salaryAndBenefits, benefit, - location, + companyLocations, ], }; diff --git a/studio/schemas/deskStructure.ts b/studio/schemas/deskStructure.ts index 1bd7443dc..bf287431f 100644 --- a/studio/schemas/deskStructure.ts +++ b/studio/schemas/deskStructure.ts @@ -17,6 +17,7 @@ import { soMeLinksID } from "./documents/socialMediaProfiles"; import { companyInfoID } from "./documents/companyInfo"; import { legalDocumentID } from "./documents/legalDocuments"; import { compensationsId } from "./documents/compensations"; +import { companyLocationsID } from "./documents/companyLocations"; export default (S: StructureBuilder) => S.list() @@ -36,13 +37,17 @@ export default (S: StructureBuilder) => S.document() .schemaType(companyInfoID) .documentId(companyInfoID) - .title("Company Information"), + .title("Company Information") ), S.listItem() - .title("Locations") + .title("Company Locations") .icon(PinIcon) - .child(S.documentTypeList("location").title("Locations")), - ]), + .child( + S.documentTypeList(companyLocationsID).title( + "Company Locations" + ) + ), + ]) ), S.listItem() .title("Legal Documents") @@ -59,7 +64,7 @@ export default (S: StructureBuilder) => S.document() .schemaType("navigationManager") .documentId("navigationManager") - .title("Navigation Manager"), + .title("Navigation Manager") ), S.listItem() .title("Dynamic Pages") @@ -79,14 +84,17 @@ export default (S: StructureBuilder) => S.document() .schemaType(blogId) .documentId(blogId) - .title("Blog Overview & Settings"), + .title("Blog Overview & Settings") ), S.listItem() .title("Compensations") .icon(HeartIcon) .child( - S.documentTypeList(compensationsId).title("Compensations"), + S.document() + .schemaType(compensationsId) + .documentId(compensationsId) + .title("Compensations") ), - ]), + ]) ), ]); diff --git a/studio/schemas/documents/companyLocations.ts b/studio/schemas/documents/companyLocations.ts new file mode 100644 index 000000000..3b11ac541 --- /dev/null +++ b/studio/schemas/documents/companyLocations.ts @@ -0,0 +1,20 @@ +import { defineField } from "sanity"; + +export const companyLocationsID = "companyLocations"; +export const companyLocationID = "companyLocation"; + +const companyLocations = defineField({ + name: companyLocationsID, + type: "document", + title: "Location", + description: "Content related to an individual location within the company", + fields: [ + defineField({ + name: companyLocationID, + type: "string", + title: "Location", + }), + ], +}); + +export default companyLocations; diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index 70f316a8b..8d85c73c4 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -1,13 +1,9 @@ import { defineField, defineType } from "sanity"; import { titleSlug } from "../schemaTypes/slug"; import seo from "../objects/seo"; -import locations from "../objects/locations"; import { title } from "../fields/text"; import { benefitId } from "./benefit"; -import { compensationDetails } from "../objects/compensationData"; - -// maximum number of locations to display in the preview without truncating -const LOCATIONS_PREVIEW_CUTOFF = 3; +import { bonusesByLocation } from "../objects/compensations/bonusesByLocation"; export const compensationsId = "compensations"; @@ -16,10 +12,39 @@ const compensations = defineType({ type: "document", title: "Compensations", fields: [ - title, + { + ...title, + title: "Compensation Page Title", + description: + "Enter the primary title that will be displayed at the top of the compensation page. This is what users will see when they visit the page.", + }, titleSlug, - locations, - compensationDetails, + // add pension here. pension doesn't rely on locations + bonusesByLocation, + // add salary here + // benefits should be updated to match the grouping by location: + // defineField({ + // name: "benefits", + // title: "Benefits", + // type: "array", + // of: [ + // defineField({ + // name: "benefitGroup", + // title: "Benefit Group", + // type: "object", + // fields: [ + // locations, + // defineField({ + // name: "benefitsList", + // title: "List of Benefits", + // type: "array", + // of: [{ type: benefitId }], + // }), + // ], + // }), + // ], + // }), + // IMPORTANT: this is just a very simple mockup and might not represent a good ux defineField({ name: "benefits", title: "Included Benefits", @@ -32,53 +57,14 @@ const compensations = defineType({ ], preview: { select: { - title: "basicTitle", - /* - Access array object values using dot notation with the array index, e.g., "locations.0.basicTitle". - This approach allows selecting a subset of the array for preview purposes. - For more details, see: https://www.sanity.io/docs/previews-list-views#62febb15a63a - */ - ...[...Array(LOCATIONS_PREVIEW_CUTOFF + 1).keys()].reduce( - (o, i) => ({ ...o, [`location${i}`]: `locations.${i}.basicTitle` }), - {}, - ), + title: "title", }, - prepare({ title, ...locationsMap }) { + prepare({ title }) { return { title, - subtitle: previewStringFromLocationsMap( - locationsMap, - LOCATIONS_PREVIEW_CUTOFF, - ), }; }, }, }); -/** - * Generates a preview string based on the selected office locations. - * - * @param {Object} locationsMap - A map of office titles selected for preview, e.g., { office0: "Trondheim", office1: "Oslo", ... }. - * @param {number} cutoff - The maximum number of locations to display before shortening the preview string. - * @returns {string|undefined} - A formatted string summarizing the selected locations or `undefined` if no locations are selected. - */ -function previewStringFromLocationsMap( - locationsMap: { - [key: string]: string; - }, - cutoff: number, -): string | undefined { - const locations = Object.values(locationsMap).filter( - (o) => o !== undefined, - ); - if (locations.length === 0) { - return undefined; - } else if (locations.length === 1) { - return `Location: ${locations[0]}`; - } else if (locations.length > cutoff) { - return `Locations: ${locations.toSpliced(cutoff - 1).join(", ")}, and more`; - } - return `Locations: ${locations.toSpliced(-1).join(", ")} and ${locations.at(-1)}`; -} - export default compensations; diff --git a/studio/schemas/documents/location.ts b/studio/schemas/documents/location.ts deleted file mode 100644 index 9c5970dc2..000000000 --- a/studio/schemas/documents/location.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineType } from "sanity"; -import { title } from "../fields/text"; - -export const locationId = "location"; - -const location = defineType({ - name: locationId, - type: "document", - title: "Location", - description: "Content related to an individual location within the company", - fields: [title], -}); - -export default location; diff --git a/studio/schemas/objects/compensationData.ts b/studio/schemas/objects/compensationData.ts deleted file mode 100644 index 5075545c1..000000000 --- a/studio/schemas/objects/compensationData.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { defineField } from "sanity"; - -export const compensationDetailsID = "compensationDetails"; - -export const compensationDetails = defineField({ - name: compensationDetailsID, - title: "Compensation Details", - description: - "Add and manage detailed information on compensation elements like estimated salary, bonuses, pensions, and other financial benefits.", - type: "object", - options: { - collapsible: true, - collapsed: false, - }, - fields: [ - { - name: "showEstimatedSalary", - title: "Show Estimated Salary", - type: "boolean", - description: - "Toggle this option to show or hide the estimated salary for the locations you've selected. Disable this if the feature isn't ready or if you prefer not to display salary details at this time.", - initialValue: false, - }, - { - name: "replaceMe", - title: "Replace me", - type: "string", - readOnly: ({ parent }) => !parent?.showEstimatedSalary, - }, - ], - preview: { - select: { - title: "basicTitle", - }, - prepare(selection) { - return { - title: selection.title, - }; - }, - }, -}); diff --git a/studio/schemas/objects/compensations/bonusesByLocation.ts b/studio/schemas/objects/compensations/bonusesByLocation.ts new file mode 100644 index 000000000..06d9bb411 --- /dev/null +++ b/studio/schemas/objects/compensations/bonusesByLocation.ts @@ -0,0 +1,97 @@ +import { defineField } from "sanity"; +import { location, locationID } from "../locations"; +import { companyLocationID } from "studio/schemas/documents/companyLocations"; + +export const bonusesByLocation = defineField({ + name: "bonusesByLocation", + title: "Bonus by Location", + description: + "Enter the average bonus amount for each company location. Each location can have only one bonus entry, but you can assign the same bonus amount to multiple locations.", + type: "array", + of: [ + defineField({ + name: "bonusData", + title: "Bonus Information", + description: + "Details of the bonus amount specific to a particular location. Each location should have a unique entry with the average bonus calculated for that site.", + type: "object", + fields: [ + { + ...location, + description: + "Select the company location for which you are entering the average bonus information. Each location must be unique.", + validation: (Rule) => Rule.required(), + }, + defineField({ + name: "averageBonus", + title: "Average Bonus", + description: + "Enter the average bonus amount for this location. Ensure the amount is positive and reflective of the compensation package for this location.", + type: "number", + validation: (Rule) => + Rule.required() + .min(0) + .error("Please enter a positive bonus amount."), + }), + ], + preview: { + select: { + averageBonus: "averageBonus", + location: `${locationID}.${companyLocationID}`, + }, + prepare({ averageBonus, location }) { + return { + title: `Average Bonus: ${averageBonus || "N/A"}`, + subtitle: `Location: ${location || "No location selected"}`, + }; + }, + }, + }), + ], + validation: (Rule) => + Rule.custom((bonusesByLocation, context) => { + const duplicateCheck = checkForDuplicateLocations( + bonusesByLocation as BonusEntry[] | undefined + ); + + if (duplicateCheck !== true) return duplicateCheck; + + return true; + }), +}); + +interface LocationReference { + _ref: string; + _type: string; + title?: string; +} + +interface BonusEntry { + location: LocationReference; + averageBonus: number; +} + +/** + * Checks for duplicate location references in the bonusesByLocation array. + * Ensures each location has a unique bonus entry. + * + * @param {BonusEntry[] | undefined} bonusesByLocation - The array of bonus entries, each with one or more locations. + * @returns {string | true} - Returns an error message if duplicate locations are found, or true if all are unique. + */ +const checkForDuplicateLocations = ( + bonusesByLocation: BonusEntry[] | undefined +): string | true => { + if (!bonusesByLocation) return true; + + const locationRefs = bonusesByLocation + .map((entry) => entry.location?._ref) + .filter(Boolean); + + const uniqueRefs = new Set(locationRefs); + + if (uniqueRefs.size !== locationRefs.length) { + return "Each location should be listed only once in the bonuses list. You can assign the same bonus amount to multiple locations, but make sure no location appears more than once."; + } + + return true; +}; diff --git a/studio/schemas/objects/locations.ts b/studio/schemas/objects/locations.ts index 36673297f..ed889e922 100644 --- a/studio/schemas/objects/locations.ts +++ b/studio/schemas/objects/locations.ts @@ -1,22 +1,26 @@ import { defineField } from "sanity"; -import { locationId } from "../documents/location"; +import { companyLocationsID } from "../documents/companyLocations"; -const locations = defineField({ - name: "locations", +export const locationsID = "locations"; +export const locationID = "location"; + +export const location = defineField({ + name: locationID, + type: "reference", + title: "Select a location", + description: + "Select the office location this content applies to. If it applies to all locations, you can leave this field empty.", + to: [{ type: companyLocationsID }], + options: { + disableNew: true, + }, +}); + +export const locations = defineField({ + name: locationsID, type: "array", title: "Relevant Locations", description: "You can tailor this content to specific office locations by selecting them here. If the content applies to all locations, just leave this field empty.", - of: [ - { - title: "Select a location", - type: "reference", - to: [{ type: locationId }], - options: { - disableNew: true, - }, - }, - ], + of: [location], }); - -export default locations; diff --git a/studio/schemas/objects/seo.ts b/studio/schemas/objects/seo.ts index af7189e7f..ffceb4876 100644 --- a/studio/schemas/objects/seo.ts +++ b/studio/schemas/objects/seo.ts @@ -37,10 +37,10 @@ const seo = defineField({ "An optional but recommended short description to boost visitor engagement from social media and search engines. Try to keep it between 70-160 characters.", validation: (Rule) => [ Rule.min(70).warning( - "A description of at least 70 characters has a higher chance of converting visitors", + "A description of at least 70 characters has a higher chance of converting visitors" ), Rule.max(160).warning( - "A description of more than 160 characters has a lower chance of converting visitors", + "A description of more than 160 characters has a lower chance of converting visitors" ), ], }), From 30433d1ca3f328f772cdb41fde6535543ff33c72 Mon Sep 17 00:00:00 2001 From: christinaroise Date: Wed, 4 Sep 2024 13:58:51 +0200 Subject: [PATCH 09/10] fix lint --- studio/schemas/deskStructure.ts | 16 ++++++++-------- .../objects/compensations/bonusesByLocation.ts | 4 ++-- studio/schemas/objects/seo.ts | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/studio/schemas/deskStructure.ts b/studio/schemas/deskStructure.ts index bf287431f..50079f3b8 100644 --- a/studio/schemas/deskStructure.ts +++ b/studio/schemas/deskStructure.ts @@ -37,17 +37,17 @@ export default (S: StructureBuilder) => S.document() .schemaType(companyInfoID) .documentId(companyInfoID) - .title("Company Information") + .title("Company Information"), ), S.listItem() .title("Company Locations") .icon(PinIcon) .child( S.documentTypeList(companyLocationsID).title( - "Company Locations" - ) + "Company Locations", + ), ), - ]) + ]), ), S.listItem() .title("Legal Documents") @@ -64,7 +64,7 @@ export default (S: StructureBuilder) => S.document() .schemaType("navigationManager") .documentId("navigationManager") - .title("Navigation Manager") + .title("Navigation Manager"), ), S.listItem() .title("Dynamic Pages") @@ -84,7 +84,7 @@ export default (S: StructureBuilder) => S.document() .schemaType(blogId) .documentId(blogId) - .title("Blog Overview & Settings") + .title("Blog Overview & Settings"), ), S.listItem() .title("Compensations") @@ -93,8 +93,8 @@ export default (S: StructureBuilder) => S.document() .schemaType(compensationsId) .documentId(compensationsId) - .title("Compensations") + .title("Compensations"), ), - ]) + ]), ), ]); diff --git a/studio/schemas/objects/compensations/bonusesByLocation.ts b/studio/schemas/objects/compensations/bonusesByLocation.ts index 06d9bb411..4d72daf6b 100644 --- a/studio/schemas/objects/compensations/bonusesByLocation.ts +++ b/studio/schemas/objects/compensations/bonusesByLocation.ts @@ -51,7 +51,7 @@ export const bonusesByLocation = defineField({ validation: (Rule) => Rule.custom((bonusesByLocation, context) => { const duplicateCheck = checkForDuplicateLocations( - bonusesByLocation as BonusEntry[] | undefined + bonusesByLocation as BonusEntry[] | undefined, ); if (duplicateCheck !== true) return duplicateCheck; @@ -79,7 +79,7 @@ interface BonusEntry { * @returns {string | true} - Returns an error message if duplicate locations are found, or true if all are unique. */ const checkForDuplicateLocations = ( - bonusesByLocation: BonusEntry[] | undefined + bonusesByLocation: BonusEntry[] | undefined, ): string | true => { if (!bonusesByLocation) return true; diff --git a/studio/schemas/objects/seo.ts b/studio/schemas/objects/seo.ts index ffceb4876..af7189e7f 100644 --- a/studio/schemas/objects/seo.ts +++ b/studio/schemas/objects/seo.ts @@ -37,10 +37,10 @@ const seo = defineField({ "An optional but recommended short description to boost visitor engagement from social media and search engines. Try to keep it between 70-160 characters.", validation: (Rule) => [ Rule.min(70).warning( - "A description of at least 70 characters has a higher chance of converting visitors" + "A description of at least 70 characters has a higher chance of converting visitors", ), Rule.max(160).warning( - "A description of more than 160 characters has a lower chance of converting visitors" + "A description of more than 160 characters has a lower chance of converting visitors", ), ], }), From a86a5e618d226bc17b695b75dc24b8fdcc3c418d Mon Sep 17 00:00:00 2001 From: christinaroise <54266462+christinaroise@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:13:53 +0200 Subject: [PATCH 10/10] Update studio/schemas/objects/compensations/bonusesByLocation.ts Co-authored-by: Mathias Oterhals Myklebust <24361490+mathiazom@users.noreply.github.com> --- studio/schemas/objects/compensations/bonusesByLocation.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/studio/schemas/objects/compensations/bonusesByLocation.ts b/studio/schemas/objects/compensations/bonusesByLocation.ts index 4d72daf6b..afed9f86a 100644 --- a/studio/schemas/objects/compensations/bonusesByLocation.ts +++ b/studio/schemas/objects/compensations/bonusesByLocation.ts @@ -54,9 +54,7 @@ export const bonusesByLocation = defineField({ bonusesByLocation as BonusEntry[] | undefined, ); - if (duplicateCheck !== true) return duplicateCheck; - - return true; + return duplicateCheck; }), });