feat: open contact modal from vendor card
This commit is contained in:
@@ -27,6 +27,7 @@ export interface ContactFormValues {
|
|||||||
export interface ContactFormProps {
|
export interface ContactFormProps {
|
||||||
visibleFields?: readonly ContactFormField[]
|
visibleFields?: readonly ContactFormField[]
|
||||||
prefillValues?: Partial<ContactFormValues>
|
prefillValues?: Partial<ContactFormValues>
|
||||||
|
submissionSource?: string
|
||||||
submitLabel?: string
|
submitLabel?: string
|
||||||
className?: string
|
className?: string
|
||||||
idPrefix?: string
|
idPrefix?: string
|
||||||
@@ -42,6 +43,7 @@ function withPrefix(prefix: string, fieldName: string): string {
|
|||||||
export function ContactForm({
|
export function ContactForm({
|
||||||
visibleFields = DEFAULT_VISIBLE_FIELDS,
|
visibleFields = DEFAULT_VISIBLE_FIELDS,
|
||||||
prefillValues,
|
prefillValues,
|
||||||
|
submissionSource,
|
||||||
submitLabel = 'Отправить заявку',
|
submitLabel = 'Отправить заявку',
|
||||||
className = 'space-y-5',
|
className = 'space-y-5',
|
||||||
idPrefix = 'contact-form',
|
idPrefix = 'contact-form',
|
||||||
@@ -54,6 +56,7 @@ export function ContactForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form className={className} onSubmit={onSubmit}>
|
<form className={className} onSubmit={onSubmit}>
|
||||||
|
{submissionSource ? <input type="hidden" name="submissionSource" value={submissionSource} /> : null}
|
||||||
{showNameCompanyRow && (
|
{showNameCompanyRow && (
|
||||||
<div className="grid md:grid-cols-2 gap-5">
|
<div className="grid md:grid-cols-2 gap-5">
|
||||||
{fields.has('name') && (
|
{fields.has('name') && (
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ interface ContactModalProps {
|
|||||||
contacts: readonly SiteConfigContact[]
|
contacts: readonly SiteConfigContact[]
|
||||||
formVisibleFields?: readonly ContactFormField[]
|
formVisibleFields?: readonly ContactFormField[]
|
||||||
formPrefillValues?: Partial<ContactFormValues>
|
formPrefillValues?: Partial<ContactFormValues>
|
||||||
|
submissionSource?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_MODAL_VISIBLE_FIELDS: readonly ContactFormField[] = [
|
const DEFAULT_MODAL_VISIBLE_FIELDS: readonly ContactFormField[] = [
|
||||||
@@ -31,6 +32,7 @@ export function ContactModal({
|
|||||||
contacts,
|
contacts,
|
||||||
formVisibleFields = DEFAULT_MODAL_VISIBLE_FIELDS,
|
formVisibleFields = DEFAULT_MODAL_VISIBLE_FIELDS,
|
||||||
formPrefillValues,
|
formPrefillValues,
|
||||||
|
submissionSource,
|
||||||
}: ContactModalProps) {
|
}: ContactModalProps) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
@@ -74,6 +76,7 @@ export function ContactModal({
|
|||||||
idPrefix="contact-modal-form"
|
idPrefix="contact-modal-form"
|
||||||
visibleFields={formVisibleFields}
|
visibleFields={formVisibleFields}
|
||||||
prefillValues={formPrefillValues}
|
prefillValues={formPrefillValues}
|
||||||
|
submissionSource={submissionSource}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="mt-8 pt-8 border-t border-gray-100">
|
<div className="mt-8 pt-8 border-t border-gray-100">
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ interface VendorCardProps {
|
|||||||
name?: string
|
name?: string
|
||||||
description?: string
|
description?: string
|
||||||
products?: string[]
|
products?: string[]
|
||||||
|
onLearnMore?: (vendorName?: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VendorCard({ name, description, products }: VendorCardProps) {
|
export function VendorCard({ name, description, products, onLearnMore }: VendorCardProps) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-white rounded-2xl p-8 hover:shadow-lg transition-all border border-gray-100 group flex flex-col">
|
<div className="bg-white rounded-2xl p-8 hover:shadow-lg transition-all border border-gray-100 group flex flex-col">
|
||||||
<div className="space-y-4 flex-1 flex flex-col">
|
<div className="space-y-4 flex-1 flex flex-col">
|
||||||
@@ -29,7 +30,11 @@ export function VendorCard({ name, description, products }: VendorCardProps) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<button className="mt-auto w-full py-3 bg-blue-50 text-blue-600 rounded-xl hover:bg-blue-600 hover:text-white transition-all">
|
<button
|
||||||
|
type="button"
|
||||||
|
className="mt-auto w-full py-3 bg-blue-50 text-blue-600 rounded-xl hover:bg-blue-600 hover:text-white transition-all cursor-pointer"
|
||||||
|
onClick={() => onLearnMore?.(name)}
|
||||||
|
>
|
||||||
Узнать больше
|
Узнать больше
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ const vendors = (category.vendors?.filter(v => v != null) ?? []).map(vendor => (
|
|||||||
<Layout>
|
<Layout>
|
||||||
<div class="min-h-screen bg-white w-full overflow-x-hidden">
|
<div class="min-h-screen bg-white w-full overflow-x-hidden">
|
||||||
<Header client:load contacts={contacts} solutions={solutionCategories} services={serviceCategories} />
|
<Header client:load contacts={contacts} solutions={solutionCategories} services={serviceCategories} />
|
||||||
<CategoryView client:load badge={badge} title={title} description={description} vendors={vendors} />
|
<CategoryView client:load badge={badge} title={title} description={description} vendors={vendors} contacts={contacts} />
|
||||||
<Footer client:load contacts={contacts} solutionCategories={solutionCategories} />
|
<Footer client:load contacts={contacts} solutionCategories={solutionCategories} />
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ export interface ContactProps {
|
|||||||
contacts: readonly SiteConfigContact[]
|
contacts: readonly SiteConfigContact[]
|
||||||
formVisibleFields?: readonly ContactFormField[]
|
formVisibleFields?: readonly ContactFormField[]
|
||||||
formPrefillValues?: Partial<ContactFormValues>
|
formPrefillValues?: Partial<ContactFormValues>
|
||||||
|
submissionSource?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Contact({ contacts, formVisibleFields, formPrefillValues }: ContactProps) {
|
export function Contact({ contacts, formVisibleFields, formPrefillValues, submissionSource }: ContactProps) {
|
||||||
return (
|
return (
|
||||||
<section className="py-4 bg-gray-50">
|
<section className="py-4 bg-gray-50">
|
||||||
<div className="max-w-225 mx-auto px-6">
|
<div className="max-w-225 mx-auto px-6">
|
||||||
@@ -24,6 +25,7 @@ export function Contact({ contacts, formVisibleFields, formPrefillValues }: Cont
|
|||||||
idPrefix="contact-section-form"
|
idPrefix="contact-section-form"
|
||||||
visibleFields={formVisibleFields}
|
visibleFields={formVisibleFields}
|
||||||
prefillValues={formPrefillValues}
|
prefillValues={formPrefillValues}
|
||||||
|
submissionSource={submissionSource}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -218,7 +218,12 @@ export function Header({ contacts = [], solutions = [], services = [] }: HeaderP
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
<ContactModal isOpen={isContactModalOpen} onClose={() => setIsContactModalOpen(false)} contacts={contacts} />
|
<ContactModal
|
||||||
|
isOpen={isContactModalOpen}
|
||||||
|
onClose={() => setIsContactModalOpen(false)}
|
||||||
|
contacts={contacts}
|
||||||
|
submissionSource="header_modal"
|
||||||
|
/>
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,15 +8,22 @@ interface Vendor {
|
|||||||
|
|
||||||
interface VendorsProps {
|
interface VendorsProps {
|
||||||
vendors?: Vendor[]
|
vendors?: Vendor[]
|
||||||
|
onVendorLearnMore?: (vendorName?: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Vendors({ vendors }: VendorsProps) {
|
export function Vendors({ vendors, onVendorLearnMore }: VendorsProps) {
|
||||||
if (vendors && vendors.length > 0) {
|
if (vendors && vendors.length > 0) {
|
||||||
return (
|
return (
|
||||||
<div className="max-w-400 mx-auto px-6 xl:px-12 2xl:px-16 py-20">
|
<div className="max-w-400 mx-auto px-6 xl:px-12 2xl:px-16 py-20">
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
{vendors.map(({ name, description, products }, index) => (
|
{vendors.map(({ name, description, products }, index) => (
|
||||||
<VendorCard key={index} name={name} description={description} products={products} />
|
<VendorCard
|
||||||
|
key={index}
|
||||||
|
name={name}
|
||||||
|
description={description}
|
||||||
|
products={products}
|
||||||
|
onLearnMore={onVendorLearnMore}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,18 +1,33 @@
|
|||||||
import type { ComponentProps } from 'react'
|
import { useState, type ComponentProps } from 'react'
|
||||||
import { CategoryPageHero } from '../sections/CategoryPageHero'
|
import { CategoryPageHero } from '../sections/CategoryPageHero'
|
||||||
import { Vendors } from '../sections/Vendors'
|
import { Vendors } from '../sections/Vendors'
|
||||||
|
import { ContactModal } from '../components/ContactModal'
|
||||||
|
import type { SiteConfigContact } from '../lib/cms/contact/types'
|
||||||
|
|
||||||
export type CategoryViewProps = {
|
export type CategoryViewProps = {
|
||||||
title?: string
|
title?: string
|
||||||
description?: string
|
description?: string
|
||||||
badge?: string
|
badge?: string
|
||||||
|
contacts?: readonly SiteConfigContact[]
|
||||||
} & ComponentProps<typeof Vendors>
|
} & ComponentProps<typeof Vendors>
|
||||||
|
|
||||||
export function CategoryView({ title, description, vendors = [], badge }: CategoryViewProps) {
|
export function CategoryView({ title, description, vendors = [], badge, contacts = [] }: CategoryViewProps) {
|
||||||
|
const [isContactModalOpen, setIsContactModalOpen] = useState(false)
|
||||||
|
|
||||||
|
const handleVendorLearnMore = () => {
|
||||||
|
setIsContactModalOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-50">
|
<div className="min-h-screen bg-gray-50">
|
||||||
<CategoryPageHero badge={badge} title={title} description={description} />
|
<CategoryPageHero badge={badge} title={title} description={description} />
|
||||||
<Vendors vendors={vendors} />
|
<Vendors vendors={vendors} onVendorLearnMore={handleVendorLearnMore} />
|
||||||
|
<ContactModal
|
||||||
|
isOpen={isContactModalOpen}
|
||||||
|
onClose={() => setIsContactModalOpen(false)}
|
||||||
|
contacts={contacts}
|
||||||
|
submissionSource="vendor_card_modal"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,9 +85,14 @@ export function HomePage({ homePage, contacts = [] }: HomePageProps) {
|
|||||||
<About data={about} />
|
<About data={about} />
|
||||||
</div>
|
</div>
|
||||||
<div id="contact" style={{ scrollMarginTop: HEADER_OFFSET_PX }}>
|
<div id="contact" style={{ scrollMarginTop: HEADER_OFFSET_PX }}>
|
||||||
<Contact contacts={contacts} />
|
<Contact contacts={contacts} submissionSource="home_contact_section" />
|
||||||
</div>
|
</div>
|
||||||
<ContactModal isOpen={contactOpen} onClose={() => setContactOpen(false)} contacts={contacts} />
|
<ContactModal
|
||||||
|
isOpen={contactOpen}
|
||||||
|
onClose={() => setContactOpen(false)}
|
||||||
|
contacts={contacts}
|
||||||
|
submissionSource="home_modal"
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user