This commit is contained in:
Ravi Gulhane 2026-07-10 09:56:03 +05:30
parent 4bfc64f56d
commit 3148ce6182
5 changed files with 112 additions and 32 deletions

View File

@ -108,11 +108,17 @@ export function FormShell({ eventId, formId, titleOverride }: Props) {
return ( return (
<div className={embed ? 'form-page-center form-page-center--embed' : 'form-page-center'}> <div className={embed ? 'form-page-center form-page-center--embed' : 'form-page-center'}>
<div className="form-panel" style={{ maxWidth: 520 }}> <div className="form-panel" style={{ maxWidth: 520 }}>
{ev ? <PublicFormEventHeader event={ev} variant="embedded" /> : null} {ev ? (
<PublicFormEventHeader
event={ev}
variant="embedded"
display={form.settings?.eventHeader}
/>
) : null}
<h1 className="form-title" style={{ fontSize: '1.2rem' }}> <h1 className="form-title" style={{ fontSize: '1.2rem' }}>
{titleOverride || form.name} {titleOverride || form.name}
</h1> </h1>
<p style={{ margin: 0, fontSize: '0.95rem', lineHeight: 1.5 }}>{msg}</p> <p className="form-success-message">{msg}</p>
</div> </div>
</div> </div>
); );
@ -124,7 +130,7 @@ export function FormShell({ eventId, formId, titleOverride }: Props) {
return ( return (
<div className={embed ? 'form-page form-page--embed' : 'form-page'}> <div className={embed ? 'form-page form-page--embed' : 'form-page'}>
<div className="form-card"> <div className="form-card">
{ev ? <PublicFormEventHeader event={ev} /> : null} {ev ? <PublicFormEventHeader event={ev} display={form.settings?.eventHeader} /> : null}
<h1 className="form-title" style={{ fontSize: ev ? '1.25rem' : '1.5rem' }}> <h1 className="form-title" style={{ fontSize: ev ? '1.25rem' : '1.5rem' }}>
{pageTitle} {pageTitle}
</h1> </h1>

View File

@ -1,4 +1,9 @@
import type { ReactNode } from 'react';
import type { PublicFormEventSummary } from '../../types'; import type { PublicFormEventSummary } from '../../types';
import {
resolveFormEventHeaderDisplay,
type FormEventHeaderDisplay,
} from '../../utils/formEventHeaderDisplay';
const EVENT_TYPE_LABEL: Record<string, string> = { const EVENT_TYPE_LABEL: Record<string, string> = {
conference: 'Conference', conference: 'Conference',
@ -46,51 +51,74 @@ function locationKindClass(locationType?: string): string {
export function PublicFormEventHeader({ export function PublicFormEventHeader({
event, event,
variant = 'default', variant = 'default',
display,
}: { }: {
event: PublicFormEventSummary; event: PublicFormEventSummary;
variant?: 'default' | 'embedded'; variant?: 'default' | 'embedded';
display?: FormEventHeaderDisplay | null;
}) { }) {
const d = resolveFormEventHeaderDisplay(display);
const typeLabel = formatEventType(event.eventType); const typeLabel = formatEventType(event.eventType);
const dateLine = formatEventDateRange(event); const dateLine = formatEventDateRange(event);
const kind = formatLocationKind(event.locationType); const kind = formatLocationKind(event.locationType);
const showLoc = shouldShowLocation(event); const showLoc = d.showVenue && shouldShowLocation(event);
const embedded = variant === 'embedded'; const embedded = variant === 'embedded';
const showBanner = d.showLogo && !!event.imageUrl && !event.logoUrl;
const showLogo = d.showLogo && !!event.logoUrl;
const showTitle = d.showTitle && !!event.name;
const showSubtitle = d.showTitle && !!event.subtitle?.trim();
const metaItems: ReactNode[] = [];
if (d.showDateRange && dateLine) {
metaItems.push(<span className="form-event-meta-date">{dateLine}</span>);
}
if (d.showEventType && typeLabel) {
metaItems.push(<span>{typeLabel}</span>);
}
if (d.showLocationType && kind) {
metaItems.push(
<span className={`form-event-meta-kind ${locationKindClass(event.locationType)}`}>{kind}</span>,
);
}
if (showLoc) {
metaItems.push(<span className="form-event-meta-location">{event.location!.trim()}</span>);
}
if (!showBanner && !showLogo && !showTitle && !showSubtitle && metaItems.length === 0) {
return null;
}
return ( return (
<div className={`form-event-header${embedded ? ' form-event-header--embedded' : ''}`}> <div className={`form-event-header${embedded ? ' form-event-header--embedded' : ''}`}>
{event.imageUrl && !event.logoUrl ? ( {showBanner ? (
<div className="form-event-banner"> <div className="form-event-banner">
<img src={event.imageUrl} alt="" /> <img src={event.imageUrl!} alt="" />
</div> </div>
) : null} ) : null}
{event.logoUrl ? <img src={event.logoUrl} alt={event.name} className="form-event-logo" /> : null} {showLogo ? (
<div> <img src={event.logoUrl!} alt={event.name} className="form-event-logo" />
<h1 className="form-event-name">{event.name}</h1> ) : null}
{event.subtitle ? <p className="form-event-subtitle">{event.subtitle}</p> : null} {showTitle || showSubtitle || metaItems.length > 0 ? (
<div className="form-event-meta"> <div>
<span className="form-event-meta-date">{dateLine}</span> {showTitle ? <h1 className="form-event-name">{event.name}</h1> : null}
{typeLabel ? ( {showSubtitle ? <p className="form-event-subtitle">{event.subtitle}</p> : null}
<> {metaItems.length > 0 ? (
<span aria-hidden="true" style={{ opacity: 0.5 }}> <div className="form-event-meta">
· {metaItems.map((item, index) => (
</span> <span key={index} className="form-event-meta-item">
<span>{typeLabel}</span> {index > 0 ? (
</> <span aria-hidden="true" className="form-event-meta-sep">
) : null} ·
<span aria-hidden="true" style={{ opacity: 0.5 }}> </span>
· ) : null}
</span> {item}
<span className={`form-event-meta-kind ${locationKindClass(event.locationType)}`}>{kind}</span> </span>
{showLoc ? ( ))}
<> </div>
<span aria-hidden="true" style={{ opacity: 0.5 }}>
·
</span>
<span className="form-event-meta-location">{event.location!.trim()}</span>
</>
) : null} ) : null}
</div> </div>
</div> ) : null}
</div> </div>
); );
} }

View File

@ -464,6 +464,18 @@
cursor: pointer; cursor: pointer;
} }
.form-success-message {
margin: 0;
padding: 12px 16px;
border-radius: 0.375rem;
background-color: #d1e7dd;
color: #198754;
font-weight: 700;
font-size: 0.95rem;
line-height: 1.5;
border: 1px solid #badbcc;
}
.form-captcha-reload:disabled { .form-captcha-reload:disabled {
opacity: 0.6; opacity: 0.6;
cursor: not-allowed; cursor: not-allowed;

View File

@ -18,9 +18,11 @@ export interface FormField {
export interface PublicFormEventSummary { export interface PublicFormEventSummary {
name: string; name: string;
subtitle?: string; subtitle?: string;
description?: string;
eventType?: string; eventType?: string;
startDate?: string | null; startDate?: string | null;
endDate?: string | null; endDate?: string | null;
date?: string;
location?: string; location?: string;
locationType?: string; locationType?: string;
logoUrl?: string | null; logoUrl?: string | null;
@ -39,6 +41,14 @@ export interface PublicFormDefinition {
showThankYou?: boolean; showThankYou?: boolean;
collectEmail?: boolean; collectEmail?: boolean;
allowAnonymous?: boolean; allowAnonymous?: boolean;
eventHeader?: {
showLogo?: boolean;
showTitle?: boolean;
showDateRange?: boolean;
showEventType?: boolean;
showLocationType?: boolean;
showVenue?: boolean;
};
}; };
} }
@ -58,6 +68,7 @@ export interface MicrositeSpeaker {
export interface AgendaItem { export interface AgendaItem {
title?: string; title?: string;
date?: string;
time?: string; time?: string;
track?: string; track?: string;
description?: string; description?: string;

View File

@ -0,0 +1,23 @@
export interface FormEventHeaderDisplay {
showLogo?: boolean;
showTitle?: boolean;
showDateRange?: boolean;
showEventType?: boolean;
showLocationType?: boolean;
showVenue?: boolean;
}
export type ResolvedFormEventHeaderDisplay = Required<FormEventHeaderDisplay>;
export function resolveFormEventHeaderDisplay(
display?: FormEventHeaderDisplay | null,
): ResolvedFormEventHeaderDisplay {
return {
showLogo: display?.showLogo !== false,
showTitle: display?.showTitle !== false,
showDateRange: display?.showDateRange !== false,
showEventType: display?.showEventType !== false,
showLocationType: display?.showLocationType !== false,
showVenue: display?.showVenue !== false,
};
}