feat: open contact modal from vendor card
This commit is contained in:
@@ -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') && (
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user