feat: open contact modal from vendor card

This commit is contained in:
Zotov Ivan Yuryevich
2026-04-21 22:19:29 +03:00
parent c9a199da91
commit 83330e9fd7
9 changed files with 57 additions and 12 deletions

View File

@@ -27,6 +27,7 @@ export interface ContactFormValues {
export interface ContactFormProps {
visibleFields?: readonly ContactFormField[]
prefillValues?: Partial<ContactFormValues>
submissionSource?: string
submitLabel?: string
className?: string
idPrefix?: string
@@ -42,6 +43,7 @@ function withPrefix(prefix: string, fieldName: string): string {
export function ContactForm({
visibleFields = DEFAULT_VISIBLE_FIELDS,
prefillValues,
submissionSource,
submitLabel = 'Отправить заявку',
className = 'space-y-5',
idPrefix = 'contact-form',
@@ -54,6 +56,7 @@ export function ContactForm({
return (
<form className={className} onSubmit={onSubmit}>
{submissionSource ? <input type="hidden" name="submissionSource" value={submissionSource} /> : null}
{showNameCompanyRow && (
<div className="grid md:grid-cols-2 gap-5">
{fields.has('name') && (

View File

@@ -12,6 +12,7 @@ interface ContactModalProps {
contacts: readonly SiteConfigContact[]
formVisibleFields?: readonly ContactFormField[]
formPrefillValues?: Partial<ContactFormValues>
submissionSource?: string
}
const DEFAULT_MODAL_VISIBLE_FIELDS: readonly ContactFormField[] = [
@@ -31,6 +32,7 @@ export function ContactModal({
contacts,
formVisibleFields = DEFAULT_MODAL_VISIBLE_FIELDS,
formPrefillValues,
submissionSource,
}: ContactModalProps) {
useEffect(() => {
if (isOpen) {
@@ -74,6 +76,7 @@ export function ContactModal({
idPrefix="contact-modal-form"
visibleFields={formVisibleFields}
prefillValues={formPrefillValues}
submissionSource={submissionSource}
/>
<div className="mt-8 pt-8 border-t border-gray-100">

View File

@@ -2,9 +2,10 @@ interface VendorCardProps {
name?: string
description?: string
products?: string[]
onLearnMore?: (vendorName?: string) => void
}
export function VendorCard({ name, description, products }: VendorCardProps) {
export function VendorCard({ name, description, products, onLearnMore }: VendorCardProps) {
return (
<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">
@@ -29,7 +30,11 @@ export function VendorCard({ name, description, products }: VendorCardProps) {
</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>
</div>

View File

@@ -76,7 +76,7 @@ const vendors = (category.vendors?.filter(v => v != null) ?? []).map(vendor => (
<Layout>
<div class="min-h-screen bg-white w-full overflow-x-hidden">
<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} />
</div>
</Layout>

View File

@@ -6,9 +6,10 @@ export interface ContactProps {
contacts: readonly SiteConfigContact[]
formVisibleFields?: readonly ContactFormField[]
formPrefillValues?: Partial<ContactFormValues>
submissionSource?: string
}
export function Contact({ contacts, formVisibleFields, formPrefillValues }: ContactProps) {
export function Contact({ contacts, formVisibleFields, formPrefillValues, submissionSource }: ContactProps) {
return (
<section className="py-4 bg-gray-50">
<div className="max-w-225 mx-auto px-6">
@@ -24,6 +25,7 @@ export function Contact({ contacts, formVisibleFields, formPrefillValues }: Cont
idPrefix="contact-section-form"
visibleFields={formVisibleFields}
prefillValues={formPrefillValues}
submissionSource={submissionSource}
/>
</div>

View File

@@ -218,7 +218,12 @@ export function Header({ contacts = [], solutions = [], services = [] }: HeaderP
</div>
)}
</nav>
<ContactModal isOpen={isContactModalOpen} onClose={() => setIsContactModalOpen(false)} contacts={contacts} />
<ContactModal
isOpen={isContactModalOpen}
onClose={() => setIsContactModalOpen(false)}
contacts={contacts}
submissionSource="header_modal"
/>
</header>
)
}

View File

@@ -8,15 +8,22 @@ interface Vendor {
interface VendorsProps {
vendors?: Vendor[]
onVendorLearnMore?: (vendorName?: string) => void
}
export function Vendors({ vendors }: VendorsProps) {
export function Vendors({ vendors, onVendorLearnMore }: VendorsProps) {
if (vendors && vendors.length > 0) {
return (
<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">
{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>

View File

@@ -1,18 +1,33 @@
import type { ComponentProps } from 'react'
import { useState, type ComponentProps } from 'react'
import { CategoryPageHero } from '../sections/CategoryPageHero'
import { Vendors } from '../sections/Vendors'
import { ContactModal } from '../components/ContactModal'
import type { SiteConfigContact } from '../lib/cms/contact/types'
export type CategoryViewProps = {
title?: string
description?: string
badge?: string
contacts?: readonly SiteConfigContact[]
} & 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 (
<div className="min-h-screen bg-gray-50">
<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>
)
}

View File

@@ -85,9 +85,14 @@ export function HomePage({ homePage, contacts = [] }: HomePageProps) {
<About data={about} />
</div>
<div id="contact" style={{ scrollMarginTop: HEADER_OFFSET_PX }}>
<Contact contacts={contacts} />
<Contact contacts={contacts} submissionSource="home_contact_section" />
</div>
<ContactModal isOpen={contactOpen} onClose={() => setContactOpen(false)} contacts={contacts} />
<ContactModal
isOpen={contactOpen}
onClose={() => setContactOpen(false)}
contacts={contacts}
submissionSource="home_modal"
/>
</>
)
}