feat(ui): add Team block to about pages and fix Affiliation link

This commit is contained in:
MichalC
2026-09-03 23:29:14 +02:00
parent fa13a3e13d
commit 2964cf66c5
7 changed files with 146 additions and 5 deletions
+11 -5
View File
@@ -13,7 +13,7 @@ const iconMap = {
landmark: Landmark,
}
export const AffiliationBlock: React.FC<Props> = ({ eyebrow, title, description, logo, linkText, trustPoints }) => {
export const AffiliationBlock: React.FC<Props> = ({ eyebrow, title, description, logo, linkText, linkUrl, trustPoints }) => {
return (
<section className="py-20 md:py-32 bg-background border-t border-border overflow-hidden">
<div className="container-premium">
@@ -32,10 +32,16 @@ export const AffiliationBlock: React.FC<Props> = ({ eyebrow, title, description,
<img src={logo.url} alt={logo.alt || "Logo stowarzyszenia"} className="max-w-full h-auto grayscale hover:grayscale-0 transition-all duration-300" />
</div>
)}
{linkText && (
<Link href="/stowarzyszenie" className="text-accent font-semibold text-lg hover:text-accent-hover underline underline-offset-4">
{linkText}
</Link>
{linkText && linkUrl && (
linkUrl.startsWith('#') ? (
<a href={linkUrl} className="text-accent font-semibold text-lg hover:text-accent-hover underline underline-offset-4">
{linkText}
</a>
) : (
<Link href={linkUrl} className="text-accent font-semibold text-lg hover:text-accent-hover underline underline-offset-4">
{linkText}
</Link>
)
)}
</div>
</div>
+1
View File
@@ -26,5 +26,6 @@ export const Affiliation: Block = {
],
},
{ name: 'linkText', type: 'text', localized: true },
{ name: 'linkUrl', type: 'text', localized: true },
],
}
+2
View File
@@ -15,6 +15,7 @@ import { FinalCTABlock } from './FinalCTA/Component'
import { PageHeaderBlock } from './PageHeader/Component'
import { ContactInfoBlock } from './ContactInfo/Component'
import { BioBlock } from './Bio/Component'
import { TeamBlock } from './Team/Component'
import { ServicesDetailedBlock } from './ServicesDetailed/Component'
import { EligibilityBlock } from './Eligibility/Component'
import { StatsBlock } from './Stats/Component'
@@ -23,6 +24,7 @@ const blockComponents = {
pageHeader: PageHeaderBlock,
contactInfo: ContactInfoBlock,
bio: BioBlock,
team: TeamBlock,
servicesDetailed: ServicesDetailedBlock,
eligibility: EligibilityBlock,
hero: HeroBlock,
+77
View File
@@ -0,0 +1,77 @@
'use client'
import React from 'react'
import type { Page, Media } from '../../payload-types'
import Image from 'next/image'
import Link from 'next/link'
import { motion } from 'framer-motion'
type Props = Extract<NonNullable<Page['layout']>[0], { blockType: 'team' }>
export const TeamBlock: React.FC<Props> = ({ members }) => {
if (!members || members.length === 0) return null
return (
<section className="py-20 md:py-32 bg-background border-y border-border overflow-hidden">
<div className="container-premium">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.6, ease: "easeOut" }}
className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 md:gap-12"
>
{members.map((member: NonNullable<Props['members']>[0], index: number) => {
const photo = typeof member.photo === 'object' && member.photo !== null ? (member.photo as Media) : null
const initial = member.name ? member.name.charAt(0).toUpperCase() : ''
return (
<div key={member.id || index} className="flex flex-col bg-card border border-border rounded-none overflow-hidden hover:border-accent/50 transition-colors h-full">
<div className="relative aspect-square w-full bg-border/30 flex items-center justify-center shrink-0">
{photo && photo.url ? (
<Image
src={photo.url}
alt={photo.alt || member.name}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
className="object-cover grayscale hover:grayscale-0 transition-all duration-700"
/>
) : (
<div className="w-full h-full flex items-center justify-center bg-accent text-background font-heading text-6xl font-bold">
{initial}
</div>
)}
</div>
<div className="p-8 flex flex-col flex-1">
<h3 className="font-heading text-2xl font-bold text-foreground mb-1">
{member.name}
</h3>
<p className="text-accent font-semibold text-sm uppercase tracking-wide mb-6">
{member.role}
</p>
{member.description && (
<p className="text-foreground/75 leading-relaxed mb-8 flex-1">
{member.description}
</p>
)}
{member.bookingUrl && (
<div className="mt-auto pt-4 border-t border-border">
<Link
href={member.bookingUrl}
className="inline-flex items-center text-sm font-semibold text-foreground hover:text-accent uppercase tracking-wider transition-colors"
>
Umów się
</Link>
</div>
)}
</div>
</div>
)
})}
</motion.div>
</div>
</section>
)
}
+20
View File
@@ -0,0 +1,20 @@
import type { Block } from 'payload'
export const Team: Block = {
slug: 'team',
fields: [
{
name: 'members',
type: 'array',
localized: true,
maxRows: 20,
fields: [
{ name: 'name', type: 'text', required: true },
{ name: 'role', type: 'text', required: true },
{ name: 'description', type: 'textarea' },
{ name: 'photo', type: 'upload', relationTo: 'media' },
{ name: 'bookingUrl', type: 'text' },
],
},
],
}
+2
View File
@@ -17,6 +17,7 @@ import { Eligibility } from '../blocks/Eligibility/config'
import { Stats } from '../blocks/Stats/config'
import { TestimonialsGrid } from '../blocks/TestimonialsGrid/config'
import { Bio } from '../blocks/Bio/config'
import { Team } from '../blocks/Team/config'
export const Pages: CollectionConfig = {
slug: 'pages',
@@ -43,6 +44,7 @@ export const Pages: CollectionConfig = {
PageHeader,
ContactInfo,
Bio,
Team,
ServicesDetailed,
Eligibility,
Hero,
+33
View File
@@ -246,6 +246,21 @@ export interface Page {
blockName?: string | null;
blockType: 'bio';
}
| {
members?:
| {
name: string;
role: string;
description?: string | null;
photo?: (number | null) | Media;
bookingUrl?: string | null;
id?: string | null;
}[]
| null;
id?: string | null;
blockName?: string | null;
blockType: 'team';
}
| {
title: string;
subtitle?: string | null;
@@ -385,6 +400,7 @@ export interface Page {
}[]
| null;
linkText?: string | null;
linkUrl?: string | null;
id?: string | null;
blockName?: string | null;
blockType: 'affiliation';
@@ -653,6 +669,22 @@ export interface PagesSelect<T extends boolean = true> {
id?: T;
blockName?: T;
};
team?:
| T
| {
members?:
| T
| {
name?: T;
role?: T;
description?: T;
photo?: T;
bookingUrl?: T;
id?: T;
};
id?: T;
blockName?: T;
};
servicesDetailed?:
| T
| {
@@ -814,6 +846,7 @@ export interface PagesSelect<T extends boolean = true> {
id?: T;
};
linkText?: T;
linkUrl?: T;
id?: T;
blockName?: T;
};