feature: group events and end time
This commit is contained in:
parent
15a4db17c8
commit
5ee3d48434
9 changed files with 26120 additions and 17 deletions
|
|
@ -20,6 +20,7 @@ import { CollapsibleImageWithTextBlock } from '@/collections/blocks/CollapsibleI
|
||||||
import { CollapsibleMapWithTextBlock } from '@/collections/blocks/CollapsibleMapWithText'
|
import { CollapsibleMapWithTextBlock } from '@/collections/blocks/CollapsibleMapWithText'
|
||||||
import { CollapsiblesBlock } from '@/collections/blocks/Collapsibles'
|
import { CollapsiblesBlock } from '@/collections/blocks/Collapsibles'
|
||||||
import { EventsBlock } from '@/collections/blocks/Events'
|
import { EventsBlock } from '@/collections/blocks/Events'
|
||||||
|
import { GroupEventsBlock } from '@/collections/blocks/GroupEvents'
|
||||||
import { PublicationAndNewsletterBlock } from '@/collections/blocks/PublicationAndNewsletter'
|
import { PublicationAndNewsletterBlock } from '@/collections/blocks/PublicationAndNewsletter'
|
||||||
import { ContactPersonBlock } from '@/collections/blocks/ContactPersonBlock'
|
import { ContactPersonBlock } from '@/collections/blocks/ContactPersonBlock'
|
||||||
import { ImageCardsBlock } from '@/collections/blocks/ImageCards'
|
import { ImageCardsBlock } from '@/collections/blocks/ImageCards'
|
||||||
|
|
@ -106,6 +107,7 @@ export const Pages: CollectionConfig = {
|
||||||
CollapsiblesBlock,
|
CollapsiblesBlock,
|
||||||
MassTimesBlock,
|
MassTimesBlock,
|
||||||
EventsBlock,
|
EventsBlock,
|
||||||
|
GroupEventsBlock,
|
||||||
ContactPersonBlock,
|
ContactPersonBlock,
|
||||||
ImageCardsBlock,
|
ImageCardsBlock,
|
||||||
ClassifiedsBlock,
|
ClassifiedsBlock,
|
||||||
|
|
|
||||||
24
src/collections/blocks/GroupEvents.ts
Normal file
24
src/collections/blocks/GroupEvents.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { Block } from 'payload'
|
||||||
|
|
||||||
|
export const GroupEventsBlock: Block = {
|
||||||
|
slug: 'groupEvents',
|
||||||
|
labels: {
|
||||||
|
singular: {
|
||||||
|
de: 'Gruppen-Veranstaltungen',
|
||||||
|
},
|
||||||
|
plural: {
|
||||||
|
de: 'Gruppen-Veranstaltungen',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'group',
|
||||||
|
type: 'relationship',
|
||||||
|
relationTo: 'group',
|
||||||
|
required: true,
|
||||||
|
label: {
|
||||||
|
de: 'Gruppe',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,17 @@ export const EventInJanuary: Story = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const EventWithEnd: Story = {
|
||||||
|
args: {
|
||||||
|
date: '2024-01-06T15:00:00+01:00',
|
||||||
|
end: '2024-01-06T17:00:00+01:00',
|
||||||
|
title: 'Herz Jesu Feier',
|
||||||
|
href: 'https://www.herzJesuFeier.com',
|
||||||
|
location: "St. Clara",
|
||||||
|
cancelled: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export const EventInMarch: Story = {
|
export const EventInMarch: Story = {
|
||||||
args: {
|
args: {
|
||||||
date: '2024-03-24T15:00:00+01:00',
|
date: '2024-03-24T15:00:00+01:00',
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import Link from 'next/link'
|
||||||
export type EventRowProps = {
|
export type EventRowProps = {
|
||||||
/** datetime 8601 format */
|
/** datetime 8601 format */
|
||||||
date: string,
|
date: string,
|
||||||
|
end?: string,
|
||||||
showDate?: boolean
|
showDate?: boolean
|
||||||
title: string,
|
title: string,
|
||||||
href?: string,
|
href?: string,
|
||||||
|
|
@ -42,9 +43,10 @@ const shortMonth = (date: string) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const EventRow = ({date, title, location, cancelled, href, color = "base", showDate = true}: EventRowProps) => {
|
export const EventRow = ({date, end, title, location, cancelled, href, color = "base", showDate = true}: EventRowProps) => {
|
||||||
const day = useMemo(() => date.substring(8, 10), [date]);
|
const day = useMemo(() => date.substring(8, 10), [date]);
|
||||||
const dateObj = useMemo(() => new Date(date), [date]);
|
const dateObj = useMemo(() => new Date(date), [date]);
|
||||||
|
const endObj = useMemo(() => end ? new Date(end) : undefined, [end]);
|
||||||
const month = useMemo(() => shortMonth(date), [date]);
|
const month = useMemo(() => shortMonth(date), [date]);
|
||||||
const [dayFormat, setDayFormat] = useState<"long" | "short">("long")
|
const [dayFormat, setDayFormat] = useState<"long" | "short">("long")
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -79,7 +81,9 @@ export const EventRow = ({date, title, location, cancelled, href, color = "base"
|
||||||
{ showDate &&
|
{ showDate &&
|
||||||
<>
|
<>
|
||||||
{dateObj.toLocaleDateString("de-DE", { weekday: "long" })}
|
{dateObj.toLocaleDateString("de-DE", { weekday: "long" })}
|
||||||
{dayFormat === "long" && " " + dateObj.toLocaleDateString("de-DE", { dateStyle: "medium" })}, {dateObj.toLocaleTimeString("de-DE", { timeStyle: "short", timeZone: "Europe/Berlin" })} Uhr
|
{dayFormat === "long" && " " + dateObj.toLocaleDateString("de-DE", { dateStyle: "short" })}, {dateObj.toLocaleTimeString("de-DE", { timeStyle: "short", timeZone: "Europe/Berlin" })}
|
||||||
|
{ endObj ? <> - {endObj.toLocaleTimeString("de-DE", { timeStyle: "short", timeZone: "Europe/Berlin" })}</> : "" }
|
||||||
|
Uhr
|
||||||
<br />
|
<br />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import { EventsBlock } from '@/compositions/Blocks/EventsBlock'
|
||||||
import { ImageCardsBlock } from '@/compositions/Blocks/ImageCardsBlock'
|
import { ImageCardsBlock } from '@/compositions/Blocks/ImageCardsBlock'
|
||||||
import { ClassifiedsFromApi } from '@/components/Classifieds/ClassifiedsFromApi'
|
import { ClassifiedsFromApi } from '@/components/Classifieds/ClassifiedsFromApi'
|
||||||
import { NextPrevButtons } from '@/components/NextPrevButtons/NextPrevButtons'
|
import { NextPrevButtons } from '@/components/NextPrevButtons/NextPrevButtons'
|
||||||
|
import { GroupEvents } from '@/compositions/GroupEvents/GroupEvents'
|
||||||
|
|
||||||
type BlocksProps = {
|
type BlocksProps = {
|
||||||
content: Blog['content']['content'] | NonNullable<Page['content']>
|
content: Blog['content']['content'] | NonNullable<Page['content']>
|
||||||
|
|
@ -277,6 +278,18 @@ export function Blocks({ content }: BlocksProps) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.blockType === 'groupEvents') {
|
||||||
|
const groupId =
|
||||||
|
typeof item.group === 'object' ? item.group.id : item.group
|
||||||
|
return (
|
||||||
|
<Section key={item.id} padding={'small'}>
|
||||||
|
<Container>
|
||||||
|
<GroupEvents id={groupId} />
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (item.blockType === 'imageCards') {
|
if (item.blockType === 'imageCards') {
|
||||||
return <ImageCardsBlock key={item.id} items={item.items} />
|
return <ImageCardsBlock key={item.id} items={item.items} />
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25980
src/migrations/20260605_095112.json
Normal file
25980
src/migrations/20260605_095112.json
Normal file
File diff suppressed because it is too large
Load diff
50
src/migrations/20260605_095112.ts
Normal file
50
src/migrations/20260605_095112.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||||
|
|
||||||
|
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
CREATE TABLE "pages_blocks_group_events" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" uuid NOT NULL,
|
||||||
|
"_path" text NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL,
|
||||||
|
"group_id" uuid,
|
||||||
|
"block_name" varchar
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "_pages_v_blocks_group_events" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" uuid NOT NULL,
|
||||||
|
"_path" text NOT NULL,
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"group_id" uuid,
|
||||||
|
"_uuid" varchar,
|
||||||
|
"block_name" varchar
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE "announcement" ALTER COLUMN "date" SET DEFAULT '2026-06-07T09:51:11.853Z';
|
||||||
|
ALTER TABLE "calendar" ALTER COLUMN "date" SET DEFAULT '2026-06-07T09:51:12.181Z';
|
||||||
|
ALTER TABLE "classifieds" ALTER COLUMN "until" SET DEFAULT '2026-07-05T09:51:12.265Z';
|
||||||
|
ALTER TABLE "pages_blocks_group_events" ADD CONSTRAINT "pages_blocks_group_events_group_id_group_id_fk" FOREIGN KEY ("group_id") REFERENCES "public"."group"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
ALTER TABLE "pages_blocks_group_events" ADD CONSTRAINT "pages_blocks_group_events_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "_pages_v_blocks_group_events" ADD CONSTRAINT "_pages_v_blocks_group_events_group_id_group_id_fk" FOREIGN KEY ("group_id") REFERENCES "public"."group"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
ALTER TABLE "_pages_v_blocks_group_events" ADD CONSTRAINT "_pages_v_blocks_group_events_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
CREATE INDEX "pages_blocks_group_events_order_idx" ON "pages_blocks_group_events" USING btree ("_order");
|
||||||
|
CREATE INDEX "pages_blocks_group_events_parent_id_idx" ON "pages_blocks_group_events" USING btree ("_parent_id");
|
||||||
|
CREATE INDEX "pages_blocks_group_events_path_idx" ON "pages_blocks_group_events" USING btree ("_path");
|
||||||
|
CREATE INDEX "pages_blocks_group_events_group_idx" ON "pages_blocks_group_events" USING btree ("group_id");
|
||||||
|
CREATE INDEX "_pages_v_blocks_group_events_order_idx" ON "_pages_v_blocks_group_events" USING btree ("_order");
|
||||||
|
CREATE INDEX "_pages_v_blocks_group_events_parent_id_idx" ON "_pages_v_blocks_group_events" USING btree ("_parent_id");
|
||||||
|
CREATE INDEX "_pages_v_blocks_group_events_path_idx" ON "_pages_v_blocks_group_events" USING btree ("_path");
|
||||||
|
CREATE INDEX "_pages_v_blocks_group_events_group_idx" ON "_pages_v_blocks_group_events" USING btree ("group_id");`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
ALTER TABLE "pages_blocks_group_events" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "_pages_v_blocks_group_events" DISABLE ROW LEVEL SECURITY;
|
||||||
|
DROP TABLE "pages_blocks_group_events" CASCADE;
|
||||||
|
DROP TABLE "_pages_v_blocks_group_events" CASCADE;
|
||||||
|
ALTER TABLE "announcement" ALTER COLUMN "date" SET DEFAULT '2026-05-10T07:03:55.605Z';
|
||||||
|
ALTER TABLE "calendar" ALTER COLUMN "date" SET DEFAULT '2026-05-10T07:03:55.910Z';
|
||||||
|
ALTER TABLE "classifieds" ALTER COLUMN "until" SET DEFAULT '2026-06-03T07:03:55.993Z';`)
|
||||||
|
}
|
||||||
|
|
@ -44,6 +44,7 @@ import * as migration_20260423_115311 from './20260423_115311';
|
||||||
import * as migration_20260423_131226_add_event_end_date_time from './20260423_131226_add_event_end_date_time';
|
import * as migration_20260423_131226_add_event_end_date_time from './20260423_131226_add_event_end_date_time';
|
||||||
import * as migration_20260429_121105_collapsible_map_with_text from './20260429_121105_collapsible_map_with_text';
|
import * as migration_20260429_121105_collapsible_map_with_text from './20260429_121105_collapsible_map_with_text';
|
||||||
import * as migration_20260504_070356_next_prev_buttons from './20260504_070356_next_prev_buttons';
|
import * as migration_20260504_070356_next_prev_buttons from './20260504_070356_next_prev_buttons';
|
||||||
|
import * as migration_20260605_095112 from './20260605_095112';
|
||||||
|
|
||||||
export const migrations = [
|
export const migrations = [
|
||||||
{
|
{
|
||||||
|
|
@ -274,6 +275,11 @@ export const migrations = [
|
||||||
{
|
{
|
||||||
up: migration_20260504_070356_next_prev_buttons.up,
|
up: migration_20260504_070356_next_prev_buttons.up,
|
||||||
down: migration_20260504_070356_next_prev_buttons.down,
|
down: migration_20260504_070356_next_prev_buttons.down,
|
||||||
name: '20260504_070356_next_prev_buttons'
|
name: '20260504_070356_next_prev_buttons',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
up: migration_20260605_095112.up,
|
||||||
|
down: migration_20260605_095112.down,
|
||||||
|
name: '20260605_095112'
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -675,6 +675,12 @@ export interface Page {
|
||||||
blockName?: string | null;
|
blockName?: string | null;
|
||||||
blockType: 'events';
|
blockType: 'events';
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
group: string | Group;
|
||||||
|
id?: string | null;
|
||||||
|
blockName?: string | null;
|
||||||
|
blockType: 'groupEvents';
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
contact: string | ContactPerson;
|
contact: string | ContactPerson;
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
|
|
@ -728,20 +734,6 @@ export interface Page {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "contactPerson".
|
|
||||||
*/
|
|
||||||
export interface ContactPerson {
|
|
||||||
id: string;
|
|
||||||
photo?: (string | null) | Media;
|
|
||||||
name: string;
|
|
||||||
role?: string | null;
|
|
||||||
email?: string | null;
|
|
||||||
telephone?: string | null;
|
|
||||||
updatedAt: string;
|
|
||||||
createdAt: string;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "group".
|
* via the `definition` "group".
|
||||||
|
|
@ -911,6 +903,20 @@ export interface Group {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "contactPerson".
|
||||||
|
*/
|
||||||
|
export interface ContactPerson {
|
||||||
|
id: string;
|
||||||
|
photo?: (string | null) | Media;
|
||||||
|
name: string;
|
||||||
|
role?: string | null;
|
||||||
|
email?: string | null;
|
||||||
|
telephone?: string | null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "worship".
|
* via the `definition` "worship".
|
||||||
|
|
@ -2294,6 +2300,13 @@ export interface PagesSelect<T extends boolean = true> {
|
||||||
id?: T;
|
id?: T;
|
||||||
blockName?: T;
|
blockName?: T;
|
||||||
};
|
};
|
||||||
|
groupEvents?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
group?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
};
|
||||||
contactPersonBlock?:
|
contactPersonBlock?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue