feature: Contact person photo

This commit is contained in:
Benno Tielen 2024-12-17 15:21:32 +01:00
parent a6a20fb7cc
commit f119e9a705
11 changed files with 6075 additions and 15 deletions

View file

@ -12,6 +12,11 @@ export const ContactPerson: CollectionConfig = {
}
},
fields: [
{
name: 'photo',
type: 'upload',
relationTo: 'media',
},
{
name: 'name',
type: 'text',

View file

@ -1,4 +1,5 @@
import { Meta, StoryObj } from '@storybook/react'
import portrait from "./portrait.jpeg"
import { ContactPerson2 } from './ContactPerson2'
const meta: Meta<typeof ContactPerson2> = {
@ -26,3 +27,22 @@ export const NotFound: Story = {
contact: "Some weird id"
},
}
export const WithPhoto: Story = {
args: {
...Default.args,
photo: portrait
}
}
export const WithPhotoMinimal: Story = {
args: {
contact: {
id: "some_id",
name: "Pfr. M. Mustermann",
createdAt: "2021-03-01T00:00:00.000Z",
updatedAt: ""
},
photo: portrait
}
}

View file

@ -1,29 +1,41 @@
import styles from "./styles.module.scss"
import { ContactPerson } from '@/payload-types'
import Image, { StaticImageData } from 'next/image'
type ContactPerson2Props = {
contact: null | string | undefined | ContactPerson
photo?: StaticImageData
}
export const ContactPerson2 = ({contact}: ContactPerson2Props) => {
export const ContactPerson2 = ({contact, photo}: ContactPerson2Props) => {
if (contact === null || contact === undefined || typeof contact === 'string') {
return "Unbekannt"
}
return (
<div className={styles.contact}>
{contact.name}
{contact.email &&
<>
<br/> <a href={`mailto:${contact.email}`} className={styles.hover}>{contact.email}</a>
</>
}
{
contact.telephone &&
<>
<br/> <a href={`tel:${contact.telephone}`}>{contact.telephone}</a>
</>
{ photo &&
<Image
className={styles.photo}
src={photo}
alt={contact.name}
unoptimized={true}
/>
}
<div>
{contact.name}
{contact.email &&
<>
<br/> <a href={`mailto:${contact.email}`} className={styles.hover}>{contact.email}</a>
</>
}
{
contact.telephone &&
<>
<br/> <a href={`tel:${contact.telephone}`}>{contact.telephone}</a>
</>
}
</div>
</div>
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

View file

@ -1,3 +1,16 @@
.contact {
display: flex;
gap: 20px;
align-items: center;
}
.photo {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 50%;
}
.contact a {
text-decoration: none;
color: inherit;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,21 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ payload, req }: MigrateUpArgs): Promise<void> {
await payload.db.drizzle.execute(sql`
ALTER TABLE "contact_person" ADD COLUMN "photo_id" uuid;
DO $$ BEGIN
ALTER TABLE "contact_person" ADD CONSTRAINT "contact_person_photo_id_media_id_fk" FOREIGN KEY ("photo_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
CREATE INDEX IF NOT EXISTS "contact_person_photo_idx" ON "contact_person" USING btree ("photo_id");`)
}
export async function down({ payload, req }: MigrateDownArgs): Promise<void> {
await payload.db.drizzle.execute(sql`
ALTER TABLE "contact_person" DROP CONSTRAINT "contact_person_photo_id_media_id_fk";
DROP INDEX IF EXISTS "contact_person_photo_idx";
ALTER TABLE "contact_person" DROP COLUMN IF EXISTS "photo_id";`)
}

View file

@ -1,9 +1,15 @@
import * as migration_20241205_121237 from './20241205_121237';
import * as migration_20241217_135114_contact_person_photo from './20241217_135114_contact_person_photo';
export const migrations = [
{
up: migration_20241205_121237.up,
down: migration_20241205_121237.down,
name: '20241205_121237'
name: '20241205_121237',
},
{
up: migration_20241217_135114_contact_person_photo.up,
down: migration_20241217_135114_contact_person_photo.down,
name: '20241217_135114_contact_person_photo'
},
];

View file

@ -14,6 +14,7 @@ import { Button } from '@/components/Button/Button'
import { StaticImageData } from 'next/image'
import { locationString } from '@/utils/dto/location'
import { ContactPerson2 } from '@/components/ContactPerson2/ContactPerson2'
import { getPhoto } from '@/utils/dto/gallery'
type EventProps = {
title: string,
@ -49,6 +50,7 @@ export function EventPage(
const published = useDate(createdAt)
const readableDate = readableDateTime(date)
const where = locationString(location);
const contactPersonPhoto = typeof contact === "object" ? getPhoto("thumbnail", contact.photo) : undefined;
return (
<>
@ -146,7 +148,10 @@ export function EventPage(
<TextDiv text={where} />
</EventExcerptRow>
<EventExcerptRow label={"Ansprechperson:"}>
<ContactPerson2 contact={contact} />
<ContactPerson2
contact={contact}
photo={contactPersonPhoto}
/>
</EventExcerptRow>
</EventExcerpt>

View file

@ -455,6 +455,7 @@ export interface Group {
*/
export interface ContactPerson {
id: string;
photo?: (string | null) | Media;
name: string;
email?: string | null;
telephone?: string | null;
@ -810,6 +811,7 @@ export interface EventSelect<T extends boolean = true> {
* via the `definition` "contactPerson_select".
*/
export interface ContactPersonSelect<T extends boolean = true> {
photo?: T;
name?: T;
email?: T;
telephone?: T;

View file

@ -22,7 +22,7 @@ export const tranformWorship = (worship: Worship[]): (EventRowProps & {id: strin
return worship.map(w => {
return {
id: w.id,
title: typeof w.title === "string" ? w.title : transformCategory(w.type),
title: typeof w.title === "string" && w.title.length > 0 ? w.title : transformCategory(w.type),
date: w.date,
href: `/gottesdienst/${w.id}`,
location: typeof w.location === 'string' ? w.location : w.location.name,