Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(studio): add aboutUsPage page #46

Merged
merged 1 commit into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/studio/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { PluginOptions } from 'sanity';
import { structureTool } from 'sanity/structure';
import { media } from 'sanity-plugin-media';

import aboutUsPage from '@/schemas/single-pages/about-us';
import contactPage from '@/schemas/single-pages/contact';
import groupsPage from '@/schemas/single-pages/groups';
import homePage from '@/schemas/single-pages/home';
Expand All @@ -26,6 +27,7 @@ export function getPlugins() {
structureTool({
structure: pageStructure([
homePage,
aboutUsPage,
contactPage,
membershipPage,
newsArticlePage,
Expand All @@ -41,6 +43,7 @@ export function getPlugins() {
// to suit the Settings document singleton
singletonPlugin([
homePage.name,
aboutUsPage.name,
contactPage.name,
membershipPage.name,
newsArticlePage.name,
Expand Down
4 changes: 4 additions & 0 deletions apps/studio/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import columns from './objects/columns';
import contactTo from './objects/contact-to';
import extendedImage from './objects/extended-image';
import externalLink from './objects/external-link';
import imageCard from './objects/image-card';
import internalLink from './objects/internal-link';
import link from './objects/link';
import metFields from './objects/meta';
Expand All @@ -18,6 +19,7 @@ import blockContent from './sections/block-content';
import grid from './sections/grid';
import mainImage from './sections/main-image';
import spacer from './sections/spacer';
import aboutUsPage from './single-pages/about-us';
import contactPage from './single-pages/contact';
import groupsPage from './single-pages/groups';
import homePage from './single-pages/home';
Expand Down Expand Up @@ -47,6 +49,7 @@ export const schemaTypes = [
contactTo,
extendedImage,
externalLink,
imageCard,
internalLink,
link,
metFields,
Expand All @@ -61,6 +64,7 @@ export const schemaTypes = [
spacer,

// Single Pages
aboutUsPage,
contactPage,
groupsPage,
homePage,
Expand Down
29 changes: 29 additions & 0 deletions apps/studio/schemas/objects/image-card.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { RiExternalLinkLine } from 'react-icons/ri';
import { defineField } from 'sanity';

const imageCard = defineField({
title: 'Kachel mit Bild',
name: 'imageCard',
type: 'object',
description: 'Die Abschnitte der Chronik.',
icon: RiExternalLinkLine,
fields: [
defineField({
title: 'Titel',
name: 'title',
type: 'string',
}),
defineField({
title: 'Beschreibung',
name: 'description',
type: 'text',
}),
defineField({
title: 'Bild',
name: 'image',
type: 'extendedImage',
}),
],
});

export default imageCard;
24 changes: 24 additions & 0 deletions apps/studio/schemas/single-pages/about-us/_groups.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const chronicle = {
title: 'Chronik',
name: 'chronicle',
};

export const contactPersons = {
title: 'Ansprechpartner',
name: 'contactPersons',
};

export const gallery = {
title: 'Galerie',
name: 'gallery',
};

export const stats = {
title: 'Stats',
name: 'stats',
};

export const vision = {
title: 'Vision',
name: 'vision',
};
23 changes: 23 additions & 0 deletions apps/studio/schemas/single-pages/about-us/chronicle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { RiLinksLine } from 'react-icons/ri';
import { defineField } from 'sanity';

import { getDefaultPageFieldsWithGroup } from '@/shared/fields/general';

export const chronicleField = defineField({
title: 'Chronik',
name: 'chronicleSection',
type: 'object',
icon: RiLinksLine,
group: 'chronicle',
fields: [
...getDefaultPageFieldsWithGroup(),

defineField({
title: 'Chronik',
name: 'chronicle',
type: 'array',
of: [{ type: 'imageCard' }],
description: 'Die Abschnitte der Chronik.',
}),
],
});
25 changes: 25 additions & 0 deletions apps/studio/schemas/single-pages/about-us/gallery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { RiLinksLine } from 'react-icons/ri';
import { defineField } from 'sanity';

import { getDefaultPageFieldsWithGroup } from '@/shared/fields/general';
import { getLengthRule } from '@/shared/validation-rules';

export const galleryField = defineField({
title: 'Galerie',
name: 'gallerySection',
type: 'object',
icon: RiLinksLine,
group: 'gallery',
fields: [
...getDefaultPageFieldsWithGroup(),

defineField({
title: 'Bilder',
name: 'venues',
type: 'array',
of: [{ type: 'extendedImage' }],
description: 'Diese gewählten Bilder werden in der gewünschten Reihenfolge angezeigt.',
validation: rule => [getLengthRule(rule, 3, 'Es müssen genau 3 Bilder ausgewählt werden.')],
}),
],
});
48 changes: 48 additions & 0 deletions apps/studio/schemas/single-pages/about-us/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// cSpell:words verein
import { RiBookletLine, RiLinksLine } from 'react-icons/ri';
import { defineField, defineType } from 'sanity';

import { content, general, meta } from '@/shared/field-groups';
import { defaultPageFields, getHiddenSlugField } from '@/shared/fields/general';
import { metaField } from '@/shared/fields/meta';
import { contactPersonsSectionField } from '@/shared/sections/contact-persons';
import { statsField } from '@/shared/sections/stats';
import { visionField } from '@/shared/sections/vision';

import { chronicle, contactPersons, gallery, stats, vision } from './_groups';
import { chronicleField } from './chronicle';
import { galleryField } from './gallery';

const aboutUsPage = defineType({
title: 'Über uns',
name: 'aboutUs',
type: 'document',
icon: RiBookletLine,
groups: [general, meta, content],
fields: [
// (hidden)
getHiddenSlugField('verein'),

// general
...defaultPageFields,

// meta
metaField,

// content
defineField({
title: 'Inhalte',
name: 'content',
type: 'object',
icon: RiLinksLine,
group: 'content',
groups: [gallery, chronicle, vision, stats, contactPersons],
fields: [galleryField, chronicleField, visionField, statsField, contactPersonsSectionField],
}),
],
preview: {
prepare: () => ({ title: 'Über uns' }),
},
});

export default aboutUsPage;
6 changes: 3 additions & 3 deletions apps/studio/schemas/single-pages/groups/_groups.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
export const contactPersons = {
title: 'ContactPersons',
title: 'Ansprechpartner',
name: 'contactPersons',
};

export const groups = {
title: 'Groups',
title: 'Gruppen',
name: 'groups',
};

export const venues = {
title: 'venues',
title: 'Sportstätten',
name: 'venues',
};

Expand Down
10 changes: 5 additions & 5 deletions apps/studio/schemas/single-pages/home/_groups.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
export const contactPersons = {
title: 'ContactPersons',
title: 'Ansprechpartner',
name: 'contactPersons',
};

export const features = {
title: 'Features',
title: 'Merkmale',
name: 'features',
};

export const groups = {
title: 'Groups',
title: 'Gruppen',
name: 'groups',
};

Expand All @@ -19,7 +19,7 @@ export const news = {
};

export const pricing = {
title: 'Pricing',
title: 'Preise',
name: 'pricing',
};

Expand All @@ -29,7 +29,7 @@ export const stats = {
};

export const testimonial = {
title: 'Testimonial',
title: 'Referenz',
name: 'testimonial',
};

Expand Down
2 changes: 1 addition & 1 deletion apps/studio/schemas/single-pages/home/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { defaultPageFields, getHiddenSlugField } from '@/shared/fields/general';
import { metaField } from '@/shared/fields/meta';
import { contactPersonsSectionField } from '@/shared/sections/contact-persons';
import { statsField } from '@/shared/sections/stats';
import { visionField } from '@/shared/sections/vision';

import {
contactPersons,
Expand All @@ -22,7 +23,6 @@ import { groupsField } from './groups';
import { newsField } from './news';
import { pricingField } from './pricing';
import { testimonialField } from './testimonial';
import { visionField } from './vision';

const homePage = defineType({
title: 'Home',
Expand Down
2 changes: 1 addition & 1 deletion apps/studio/schemas/single-pages/single-group/_groups.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const contactPersons = {
title: 'ContactPersons',
title: 'Ansprechpartner',
name: 'contactPersons',
};

Expand Down
3 changes: 1 addition & 2 deletions apps/studio/schemas/single-pages/single-group/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// cSpell:words angebot
import { RiBookletLine, RiLinksLine } from 'react-icons/ri';
import { defineField, defineType } from 'sanity';

Expand All @@ -8,7 +7,7 @@ import { metaField } from '@/shared/fields/meta';
import { contactPersonsSectionField } from '@/shared/sections/contact-persons';

import { contactPersons, gallery } from './_groups';
import { galleryField } from './groups';
import { galleryField } from './gallery';

const singleGroupPage = defineType({
title: 'Einzel-Gruppe',
Expand Down
30 changes: 27 additions & 3 deletions apps/studio/shared/validation-rules.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { StringRule } from 'sanity';

interface RuleOptions {
inputType?: 'array' | 'text';
message?: string;
type?: 'error' | 'warning';
}

const defaultRuleOptions: RuleOptions = { type: 'error' };
const defaultRuleOptions: RuleOptions = { inputType: 'text', type: 'error' };

interface BaseRule<Rule> {
error: (message: string) => Rule;
Expand All @@ -16,6 +17,10 @@ interface RequiredRule<Rule> extends BaseRule<Rule> {
required: () => Rule;
}

interface LengthRule<Rule> extends BaseRule<Rule>, RequiredRule<Rule> {
length: (length: number) => Rule;
}

interface MaxLengthRule<Rule> extends BaseRule<Rule> {
max: (length: number) => Rule;
}
Expand All @@ -24,14 +29,32 @@ interface MinLengthRule<Rule> extends BaseRule<Rule>, RequiredRule<Rule> {
min: (length: number) => Rule;
}

function getTextByInputType(inputType: RuleOptions['inputType'], length: number) {
const arrayOutput = length === 1 ? 'Eintrag' : 'Einträge';
return inputType === 'array' ? arrayOutput : 'Zeichen';
}

export function getLengthRule<Rule extends LengthRule<Rule>>(
rule: Rule,
length: number,
title: string,
options = { ...defaultRuleOptions, type: 'warning' },
) {
const validationRule = rule.length(length);
const itemText = getTextByInputType(options.inputType, length);
const message = options.message ?? `${title} muss genau ${length} ${itemText} lang sein`;
return options.type === 'error' ? validationRule.error(message) : validationRule.warning(message);
}

export function getMaxLengthRule<Rule extends MaxLengthRule<Rule>>(
rule: Rule,
length: number,
title: string,
options = { ...defaultRuleOptions, type: 'warning' },
) {
const validationRule = rule.max(length);
const message = options.message ?? `${title} sollte maximal ${length} Zeichen lang sein`;
const itemText = getTextByInputType(options.inputType, length);
const message = options.message ?? `${title} sollte maximal ${length} ${itemText} lang sein`;
return options.type === 'error' ? validationRule.error(message) : validationRule.warning(message);
}

Expand All @@ -42,7 +65,8 @@ export function getMinLengthRule<Rule extends MinLengthRule<Rule>>(
options = defaultRuleOptions,
) {
const validationRule = rule.required().min(length);
const message = options.message ?? `${title} muss mindestens ${length} Zeichen lang sein`;
const itemText = getTextByInputType(options.inputType, length);
const message = options.message ?? `${title} muss mindestens ${length} ${itemText} lang sein`;
return options.type === 'error' ? validationRule.error(message) : validationRule.warning(message);
}

Expand Down