Enhanced FDContactFormBlock with dark mode, remove search, add FormBlock to pages
This commit is contained in:
parent
9038b0c894
commit
5cf9186ee2
BIN
media/08-FD-Grön-Fiber-04.mp4
Normal file
BIN
media/08-FD-Grön-Fiber-04.mp4
Normal file
Binary file not shown.
BIN
media/08-FD-Grön-Fiber-5.mp4
Normal file
BIN
media/08-FD-Grön-Fiber-5.mp4
Normal file
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 146 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.7 MiB |
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
@ -1,6 +1,6 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
import "./.next/types/routes.d.ts";
|
import "./.next/dev/types/routes.d.ts";
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import React, { useState, useEffect, useRef } from 'react'
|
|||||||
import type { Header as HeaderType } from '@/payload-types'
|
import type { Header as HeaderType } from '@/payload-types'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { usePathname } from 'next/navigation'
|
import { usePathname } from 'next/navigation'
|
||||||
import { SearchIcon, MenuIcon, XIcon, ChevronDownIcon, ChevronRightIcon } from 'lucide-react'
|
import { MenuIcon, XIcon, ChevronDownIcon, ChevronRightIcon } from 'lucide-react'
|
||||||
|
|
||||||
// ─── Types ───────────────────────────────────────────────────────────────────
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
||||||
type NavChild = {
|
type NavChild = {
|
||||||
@ -258,11 +258,6 @@ export const HeaderNav: React.FC<{ data: HeaderType }> = ({ data }) => {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<Link href="/search" className="text-fd-navy hover:text-fd-yellow transition-colors">
|
|
||||||
<span className="sr-only">Sök</span>
|
|
||||||
<SearchIcon className="w-5" />
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<SwedishFlag />
|
<SwedishFlag />
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@ -351,15 +346,6 @@ export const HeaderNav: React.FC<{ data: HeaderType }> = ({ data }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<Link
|
|
||||||
href="/search"
|
|
||||||
onClick={closeMobile}
|
|
||||||
className="py-4 text-white font-joey-medium text-xl border-b border-white/10 hover:text-fd-yellow transition-colors flex items-center gap-3"
|
|
||||||
>
|
|
||||||
<SearchIcon className="w-5 h-5" />
|
|
||||||
Sök
|
|
||||||
</Link>
|
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -17,8 +17,6 @@ import { PreviewComponent as PreviewComponent_a8a977ebc872c5d5ea7ee689724c0860 }
|
|||||||
import { SlugField as SlugField_2b8867833a34864a02ddf429b0728a40 } from '@payloadcms/next/client'
|
import { SlugField as SlugField_2b8867833a34864a02ddf429b0728a40 } from '@payloadcms/next/client'
|
||||||
import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
|
import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
|
||||||
import { BlocksFeatureClient as BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
|
import { BlocksFeatureClient as BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
|
||||||
import { LinkToDoc as LinkToDoc_aead06e4cbf6b2620c5c51c9ab283634 } from '@payloadcms/plugin-search/client'
|
|
||||||
import { ReindexButton as ReindexButton_aead06e4cbf6b2620c5c51c9ab283634 } from '@payloadcms/plugin-search/client'
|
|
||||||
import { RowLabel as RowLabel_ec255a65fa6fa8d1faeb09cf35284224 } from '@/Header/RowLabel'
|
import { RowLabel as RowLabel_ec255a65fa6fa8d1faeb09cf35284224 } from '@/Header/RowLabel'
|
||||||
import { RowLabel as RowLabel_1f6ff6ff633e3695d348f4f3c58f1466 } from '@/Footer/RowLabel'
|
import { RowLabel as RowLabel_1f6ff6ff633e3695d348f4f3c58f1466 } from '@/Footer/RowLabel'
|
||||||
import { default as default_c1363893506d7ed29a71d1a4da01ddb5 } from '@/components/AdminIcon'
|
import { default as default_c1363893506d7ed29a71d1a4da01ddb5 } from '@/components/AdminIcon'
|
||||||
@ -47,8 +45,6 @@ export const importMap = {
|
|||||||
"@payloadcms/next/client#SlugField": SlugField_2b8867833a34864a02ddf429b0728a40,
|
"@payloadcms/next/client#SlugField": SlugField_2b8867833a34864a02ddf429b0728a40,
|
||||||
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
"@payloadcms/plugin-search/client#LinkToDoc": LinkToDoc_aead06e4cbf6b2620c5c51c9ab283634,
|
|
||||||
"@payloadcms/plugin-search/client#ReindexButton": ReindexButton_aead06e4cbf6b2620c5c51c9ab283634,
|
|
||||||
"@/Header/RowLabel#RowLabel": RowLabel_ec255a65fa6fa8d1faeb09cf35284224,
|
"@/Header/RowLabel#RowLabel": RowLabel_ec255a65fa6fa8d1faeb09cf35284224,
|
||||||
"@/Footer/RowLabel#RowLabel": RowLabel_1f6ff6ff633e3695d348f4f3c58f1466,
|
"@/Footer/RowLabel#RowLabel": RowLabel_1f6ff6ff633e3695d348f4f3c58f1466,
|
||||||
"@/components/AdminIcon#default": default_c1363893506d7ed29a71d1a4da01ddb5,
|
"@/components/AdminIcon#default": default_c1363893506d7ed29a71d1a4da01ddb5,
|
||||||
|
|||||||
@ -5,11 +5,23 @@ import type { FDContactFormBlock as FDContactFormBlockProps } from '@/payload-ty
|
|||||||
import type { Media } from '@/payload-types'
|
import type { Media } from '@/payload-types'
|
||||||
import { FDImage } from '@/components/FDImage'
|
import { FDImage } from '@/components/FDImage'
|
||||||
|
|
||||||
const bgMap: Record<string, string> = {
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Theme maps */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
const sectionBgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-[#F0F0F0]',
|
||||||
|
navy: 'bg-fd-navy',
|
||||||
|
navyGradient: 'bg-gradient-to-br from-fd-navy via-[#153350] to-fd-navy',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isDark = (bg: string) => bg === 'navy' || bg === 'navyGradient'
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Component */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
||||||
heading,
|
heading,
|
||||||
description,
|
description,
|
||||||
@ -20,31 +32,35 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
privacyLinkUrl,
|
privacyLinkUrl,
|
||||||
sideImage,
|
sideImage,
|
||||||
background = 'white',
|
background = 'white',
|
||||||
|
layout = 'standard',
|
||||||
|
externalApi,
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState<Record<string, string>>({})
|
const [formData, setFormData] = useState<Record<string, string>>({})
|
||||||
const [status, setStatus] = useState<'idle' | 'sending' | 'sent' | 'error'>('idle')
|
const [status, setStatus] = useState<'idle' | 'sending' | 'sent' | 'error'>('idle')
|
||||||
|
|
||||||
const media = sideImage as Media | undefined
|
const media = sideImage as Media | undefined
|
||||||
const hasSideImage = Boolean(media?.url)
|
const hasSideImage = layout === 'withImage' && Boolean(media?.url)
|
||||||
const sectionBg = bgMap[background || 'white']
|
const dark = isDark(background || 'white')
|
||||||
|
const sectionBg = sectionBgMap[background || 'white']
|
||||||
|
const isCard = layout === 'card'
|
||||||
|
|
||||||
// Extract form object — could be a populated object or just an ID
|
// Extract form object
|
||||||
const form = formRelation && typeof formRelation === 'object' ? formRelation : null
|
const form = formRelation && typeof formRelation === 'object' ? formRelation : null
|
||||||
const formId = form ? form.id : (formRelation ?? null)
|
const formId = form ? form.id : (formRelation ?? null)
|
||||||
|
|
||||||
|
/* ---- Handlers ---- */
|
||||||
|
|
||||||
const handleChange = (name: string, value: string) => {
|
const handleChange = (name: string, value: string) => {
|
||||||
setFormData((prev) => ({ ...prev, [name]: value }))
|
setFormData((prev) => ({ ...prev, [name]: value }))
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (!formId) {
|
if (!formId) return
|
||||||
console.warn('No form ID configured')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setStatus('sending')
|
setStatus('sending')
|
||||||
try {
|
try {
|
||||||
|
// 1. Submit to Payload
|
||||||
const res = await fetch('/api/form-submissions', {
|
const res = await fetch('/api/form-submissions', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@ -56,14 +72,55 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
})),
|
})),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 2. Submit to external API if configured
|
||||||
|
if (externalApi?.enabled && externalApi?.endpoint) {
|
||||||
|
const headers: Record<string, string> = { 'Content-Type': 'application/json' }
|
||||||
|
if (externalApi.authToken) {
|
||||||
|
headers['Authorization'] = `Bearer ${externalApi.authToken}`
|
||||||
|
}
|
||||||
|
// Fire and forget — don't block UX on external API
|
||||||
|
fetch(externalApi.endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify({
|
||||||
|
formId,
|
||||||
|
formName: form?.title || '',
|
||||||
|
data: formData,
|
||||||
|
submittedAt: new Date().toISOString(),
|
||||||
|
}),
|
||||||
|
}).catch(() => {}) // silently fail
|
||||||
|
}
|
||||||
|
|
||||||
setStatus(res.ok ? 'sent' : 'error')
|
setStatus(res.ok ? 'sent' : 'error')
|
||||||
} catch {
|
} catch {
|
||||||
setStatus('error')
|
setStatus('error')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseInputClass =
|
/* ---- Input styles (light vs dark) ---- */
|
||||||
'w-full bg-gray-100 rounded-lg px-4 py-3 font-joey text-fd-navy text-base outline-none focus:ring-2 focus:ring-fd-navy/20 transition-shadow'
|
|
||||||
|
const inputBase = 'w-full rounded-xl px-4 py-3 font-joey text-base outline-none transition-all'
|
||||||
|
const inputLight = `${inputBase} bg-gray-100 text-fd-navy placeholder:text-fd-navy/40 focus:ring-2 focus:ring-fd-navy/20 focus:bg-white`
|
||||||
|
const inputDark = `${inputBase} bg-white/10 text-white placeholder:text-white/40 border border-white/20 focus:ring-2 focus:ring-fd-yellow/30 focus:bg-white/15 focus:border-fd-yellow/50`
|
||||||
|
const inputClass = dark ? inputDark : inputLight
|
||||||
|
|
||||||
|
const checkboxLight = 'w-5 h-5 rounded border-gray-300 text-fd-navy focus:ring-fd-navy/20'
|
||||||
|
const checkboxDark = 'w-5 h-5 rounded border-white/30 text-fd-yellow focus:ring-fd-yellow/30'
|
||||||
|
const checkboxClass = dark ? checkboxDark : checkboxLight
|
||||||
|
|
||||||
|
/* ---- Text color helpers ---- */
|
||||||
|
|
||||||
|
const headingColor = dark ? 'text-fd-yellow' : 'text-fd-navy'
|
||||||
|
const bodyColor = dark ? 'text-white/80' : 'text-fd-navy/80'
|
||||||
|
const labelColor = dark ? 'text-white' : 'text-fd-navy'
|
||||||
|
const mutedColor = dark ? 'text-white/50' : 'text-fd-navy/60'
|
||||||
|
const linkColor = dark
|
||||||
|
? 'underline underline-offset-2 hover:text-fd-yellow transition-colors'
|
||||||
|
: 'underline underline-offset-2 hover:text-fd-navy transition-colors'
|
||||||
|
const errorColor = dark ? 'text-red-300' : 'text-red-600'
|
||||||
|
|
||||||
|
/* ---- Field renderer ---- */
|
||||||
|
|
||||||
const renderFormField = (field: any) => {
|
const renderFormField = (field: any) => {
|
||||||
const blockType = field.blockType
|
const blockType = field.blockType
|
||||||
@ -80,7 +137,7 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
name={name}
|
name={name}
|
||||||
required={required}
|
required={required}
|
||||||
rows={4}
|
rows={4}
|
||||||
className={`${baseInputClass} resize-y`}
|
className={`${inputClass} resize-y`}
|
||||||
value={formData[name] || ''}
|
value={formData[name] || ''}
|
||||||
onChange={(e) => handleChange(name, e.target.value)}
|
onChange={(e) => handleChange(name, e.target.value)}
|
||||||
/>
|
/>
|
||||||
@ -90,7 +147,7 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
<select
|
<select
|
||||||
name={name}
|
name={name}
|
||||||
required={required}
|
required={required}
|
||||||
className={baseInputClass}
|
className={inputClass}
|
||||||
value={formData[name] || ''}
|
value={formData[name] || ''}
|
||||||
onChange={(e) => handleChange(name, e.target.value)}
|
onChange={(e) => handleChange(name, e.target.value)}
|
||||||
>
|
>
|
||||||
@ -108,7 +165,8 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
type="email"
|
type="email"
|
||||||
name={name}
|
name={name}
|
||||||
required={required}
|
required={required}
|
||||||
className={baseInputClass}
|
className={inputClass}
|
||||||
|
placeholder={field.placeholder || ''}
|
||||||
value={formData[name] || ''}
|
value={formData[name] || ''}
|
||||||
onChange={(e) => handleChange(name, e.target.value)}
|
onChange={(e) => handleChange(name, e.target.value)}
|
||||||
/>
|
/>
|
||||||
@ -119,23 +177,23 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
type="number"
|
type="number"
|
||||||
name={name}
|
name={name}
|
||||||
required={required}
|
required={required}
|
||||||
className={baseInputClass}
|
className={inputClass}
|
||||||
value={formData[name] || ''}
|
value={formData[name] || ''}
|
||||||
onChange={(e) => handleChange(name, e.target.value)}
|
onChange={(e) => handleChange(name, e.target.value)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case 'checkbox':
|
case 'checkbox':
|
||||||
return (
|
return (
|
||||||
<label className="flex items-center gap-2 cursor-pointer">
|
<label className="flex items-center gap-3 cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name={name}
|
name={name}
|
||||||
required={required}
|
required={required}
|
||||||
className="w-5 h-5 rounded border-gray-300 text-fd-navy focus:ring-fd-navy/20"
|
className={checkboxClass}
|
||||||
checked={formData[name] === 'true'}
|
checked={formData[name] === 'true'}
|
||||||
onChange={(e) => handleChange(name, e.target.checked ? 'true' : 'false')}
|
onChange={(e) => handleChange(name, e.target.checked ? 'true' : 'false')}
|
||||||
/>
|
/>
|
||||||
<span className="font-joey text-fd-navy text-sm">{label}</span>
|
<span className={`font-joey text-sm ${labelColor}`}>{label}</span>
|
||||||
</label>
|
</label>
|
||||||
)
|
)
|
||||||
case 'country':
|
case 'country':
|
||||||
@ -147,7 +205,8 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
type="text"
|
type="text"
|
||||||
name={name}
|
name={name}
|
||||||
required={required}
|
required={required}
|
||||||
className={baseInputClass}
|
className={inputClass}
|
||||||
|
placeholder={field.placeholder || ''}
|
||||||
value={formData[name] || ''}
|
value={formData[name] || ''}
|
||||||
onChange={(e) => handleChange(name, e.target.value)}
|
onChange={(e) => handleChange(name, e.target.value)}
|
||||||
/>
|
/>
|
||||||
@ -162,9 +221,9 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
return {
|
return {
|
||||||
element: (
|
element: (
|
||||||
<div className="flex flex-col gap-1.5">
|
<div className="flex flex-col gap-1.5">
|
||||||
<label className="font-joey text-fd-navy text-sm md:text-base">
|
<label className={`font-joey text-sm md:text-base ${labelColor}`}>
|
||||||
{label}
|
{label}
|
||||||
{required && ' *'}
|
{required && <span className={dark ? 'text-fd-yellow' : 'text-fd-navy'}> *</span>}
|
||||||
</label>
|
</label>
|
||||||
{input}
|
{input}
|
||||||
</div>
|
</div>
|
||||||
@ -173,6 +232,8 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Fields layout (handles half-width pairing) ---- */
|
||||||
|
|
||||||
const renderFields = () => {
|
const renderFields = () => {
|
||||||
if (!form?.fields) return null
|
if (!form?.fields) return null
|
||||||
|
|
||||||
@ -183,12 +244,9 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
while (i < fields.length) {
|
while (i < fields.length) {
|
||||||
const field = fields[i]
|
const field = fields[i]
|
||||||
|
|
||||||
// Skip message blocks — render them inline
|
|
||||||
if (field.blockType === 'message') {
|
if (field.blockType === 'message') {
|
||||||
elements.push(
|
elements.push(
|
||||||
<div key={i} className="font-joey text-fd-navy/70 text-sm">
|
<div key={i} className={`font-joey text-sm ${mutedColor}`} />,
|
||||||
{/* Message blocks contain rich text, render as simple text for now */}
|
|
||||||
</div>,
|
|
||||||
)
|
)
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
@ -199,7 +257,8 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
|
|
||||||
if (isHalf) {
|
if (isHalf) {
|
||||||
const nextField = i + 1 < fields.length ? fields[i + 1] : null
|
const nextField = i + 1 < fields.length ? fields[i + 1] : null
|
||||||
const nextResult = nextField && nextField.blockType !== 'message' ? renderFormField(nextField) : null
|
const nextResult =
|
||||||
|
nextField && nextField.blockType !== 'message' ? renderFormField(nextField) : null
|
||||||
const nextIsHalf = nextResult && nextResult.width <= 50
|
const nextIsHalf = nextResult && nextResult.width <= 50
|
||||||
|
|
||||||
if (nextIsHalf && nextResult) {
|
if (nextIsHalf && nextResult) {
|
||||||
@ -225,13 +284,19 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
return elements
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Success state ---- */
|
||||||
|
|
||||||
if (status === 'sent') {
|
if (status === 'sent') {
|
||||||
// Use confirmation message from Payload form if available
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${sectionBg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8 text-center">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8 text-center">
|
||||||
<h2 className="font-joey-heavy text-fd-navy text-3xl md:text-4xl mb-4">Tack!</h2>
|
<div className={`inline-flex items-center justify-center w-16 h-16 rounded-full mb-6 ${dark ? 'bg-fd-yellow/20' : 'bg-fd-mint/20'}`}>
|
||||||
<p className="font-joey text-fd-navy text-lg">
|
<svg className={`w-8 h-8 ${dark ? 'text-fd-yellow' : 'text-fd-mint'}`} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h2 className={`font-joey-heavy text-3xl md:text-4xl mb-4 ${headingColor}`}>Tack!</h2>
|
||||||
|
<p className={`font-joey text-lg ${bodyColor}`}>
|
||||||
Vi har tagit emot din förfrågan och återkommer så snart vi kan.
|
Vi har tagit emot din förfrågan och återkommer så snart vi kan.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -239,28 +304,31 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Empty state ---- */
|
||||||
|
|
||||||
if (!form) {
|
if (!form) {
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${sectionBg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8 text-center">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8 text-center">
|
||||||
<p className="font-joey text-fd-navy/60">Inget formulär valt.</p>
|
<p className={`font-joey ${mutedColor}`}>Inget formulär valt.</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
/* ---- Form content ---- */
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${sectionBg}`}>
|
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
const formContent = (
|
||||||
<div className={`flex flex-col ${hasSideImage ? 'lg:flex-row' : ''} gap-10 lg:gap-16`}>
|
<>
|
||||||
<div className={hasSideImage ? 'flex-1' : 'max-w-[800px]'}>
|
|
||||||
{heading && (
|
{heading && (
|
||||||
<h2 className="font-joey-heavy text-fd-navy text-3xl md:text-4xl lg:text-5xl leading-tight mb-3">
|
<h2
|
||||||
|
className={`font-joey-heavy text-3xl md:text-4xl lg:text-5xl leading-tight mb-3 ${headingColor}`}
|
||||||
|
>
|
||||||
{heading}
|
{heading}
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
{description && (
|
{description && (
|
||||||
<p className="font-joey text-fd-navy/80 text-base md:text-lg mb-8">{description}</p>
|
<p className={`font-joey text-base md:text-lg mb-8 ${bodyColor}`}>{description}</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
|
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
|
||||||
@ -269,27 +337,28 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={status === 'sending'}
|
disabled={status === 'sending'}
|
||||||
className="self-start inline-flex items-center justify-center px-8 py-3 bg-fd-yellow hover:bg-fd-yellow/90 rounded-full font-joey-bold text-fd-navy text-lg transition-colors disabled:opacity-60 mt-2"
|
className={`self-start inline-flex items-center justify-center px-8 py-3 rounded-full font-joey-bold text-lg transition-colors disabled:opacity-60 mt-2 ${
|
||||||
|
dark
|
||||||
|
? 'bg-fd-yellow hover:bg-fd-yellow/90 text-fd-navy'
|
||||||
|
: 'bg-fd-yellow hover:bg-fd-yellow/90 text-fd-navy'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{status === 'sending' ? 'Skickar...' : submitText}
|
{status === 'sending' ? 'Skickar...' : submitText}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{status === 'error' && (
|
{status === 'error' && (
|
||||||
<p className="font-joey text-red-600 text-sm">
|
<p className={`font-joey text-sm ${errorColor}`}>
|
||||||
Något gick fel. Försök igen eller kontakta oss direkt.
|
Något gick fel. Försök igen eller kontakta oss direkt.
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{privacyText && (
|
{privacyText && (
|
||||||
<p className="font-joey text-fd-navy/60 text-xs md:text-sm leading-relaxed mt-2">
|
<p className={`font-joey text-xs md:text-sm leading-relaxed mt-2 ${mutedColor}`}>
|
||||||
{privacyText}{' '}
|
{privacyText}{' '}
|
||||||
{privacyLinkText && privacyLinkUrl && (
|
{privacyLinkText && privacyLinkUrl && (
|
||||||
<>
|
<>
|
||||||
Läs mer i vår{' '}
|
Läs mer i vår{' '}
|
||||||
<a
|
<a href={privacyLinkUrl} className={linkColor}>
|
||||||
href={privacyLinkUrl}
|
|
||||||
className="underline underline-offset-2 hover:text-fd-navy transition-colors"
|
|
||||||
>
|
|
||||||
{privacyLinkText}
|
{privacyLinkText}
|
||||||
</a>
|
</a>
|
||||||
.
|
.
|
||||||
@ -298,21 +367,59 @@ export const FDContactFormBlockComponent: React.FC<FDContactFormBlockProps> = ({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
{hasSideImage && (
|
/* ---- Layout: Card ---- */
|
||||||
<div className="hidden lg:block flex-shrink-0">
|
|
||||||
<FDImage
|
if (isCard) {
|
||||||
media={media!}
|
return (
|
||||||
size="medium"
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
className="w-[380px] h-auto max-h-[500px] object-cover rounded-[20px]"
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
sizes="380px"
|
<div
|
||||||
fallbackAlt={heading || ''}
|
className={`max-w-[720px] mx-auto p-8 md:p-12 rounded-[40px] md:rounded-[70px] ${
|
||||||
/>
|
dark
|
||||||
</div>
|
? 'bg-white/5 border border-white/10 backdrop-blur-sm'
|
||||||
)}
|
: 'bg-white shadow-lg border border-gray-100'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{formContent}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Layout: With image ---- */
|
||||||
|
|
||||||
|
if (hasSideImage) {
|
||||||
|
return (
|
||||||
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
|
<div className="flex flex-col lg:flex-row gap-10 lg:gap-16 items-start">
|
||||||
|
<div className="flex-1">{formContent}</div>
|
||||||
|
<div className="hidden lg:block flex-shrink-0">
|
||||||
|
<FDImage
|
||||||
|
media={media!}
|
||||||
|
size="medium"
|
||||||
|
className="w-[380px] h-auto max-h-[560px] object-cover rounded-[20px]"
|
||||||
|
sizes="380px"
|
||||||
|
fallbackAlt={heading || ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Layout: Standard (full width) ---- */
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
|
<div className="max-w-[800px]">{formContent}</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,11 @@ export const FDContactFormBlock: Block = {
|
|||||||
slug: 'fdContactForm',
|
slug: 'fdContactForm',
|
||||||
interfaceName: 'FDContactFormBlock',
|
interfaceName: 'FDContactFormBlock',
|
||||||
labels: {
|
labels: {
|
||||||
singular: 'FD Contact Form',
|
singular: 'FD Kontaktformulär',
|
||||||
plural: 'FD Contact Forms',
|
plural: 'FD Kontaktformulär',
|
||||||
},
|
},
|
||||||
fields: [
|
fields: [
|
||||||
|
// --- Content ---
|
||||||
{
|
{
|
||||||
name: 'form',
|
name: 'form',
|
||||||
type: 'relationship',
|
type: 'relationship',
|
||||||
@ -30,7 +31,7 @@ export const FDContactFormBlock: Block = {
|
|||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
label: 'Beskrivning',
|
label: 'Beskrivning',
|
||||||
defaultValue:
|
defaultValue:
|
||||||
'Tell us about your goals, our team will reach out to you and help you achieve the right solution.',
|
'Berätta om era mål — vårt team kontaktar er och hjälper er hitta rätt lösning.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'submitText',
|
name: 'submitText',
|
||||||
@ -38,6 +39,50 @@ export const FDContactFormBlock: Block = {
|
|||||||
label: 'Skicka-knapp text',
|
label: 'Skicka-knapp text',
|
||||||
defaultValue: 'Skicka förfrågan',
|
defaultValue: 'Skicka förfrågan',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// --- Layout ---
|
||||||
|
{
|
||||||
|
type: 'row',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'background',
|
||||||
|
type: 'select',
|
||||||
|
label: 'Bakgrund',
|
||||||
|
defaultValue: 'white',
|
||||||
|
options: [
|
||||||
|
{ label: 'Vit', value: 'white' },
|
||||||
|
{ label: 'Ljusgrå', value: 'gray' },
|
||||||
|
{ label: 'Navy (mörk)', value: 'navy' },
|
||||||
|
{ label: 'Navy gradient', value: 'navyGradient' },
|
||||||
|
],
|
||||||
|
admin: { width: '50%' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'layout',
|
||||||
|
type: 'select',
|
||||||
|
label: 'Layout',
|
||||||
|
defaultValue: 'standard',
|
||||||
|
options: [
|
||||||
|
{ label: 'Standard (helbredd)', value: 'standard' },
|
||||||
|
{ label: 'Med sidobild', value: 'withImage' },
|
||||||
|
{ label: 'Kort (centrerat)', value: 'card' },
|
||||||
|
],
|
||||||
|
admin: { width: '50%' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sideImage',
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'media',
|
||||||
|
label: 'Sidobild',
|
||||||
|
admin: {
|
||||||
|
description: 'Visas till höger om formuläret på desktop',
|
||||||
|
condition: (_, siblingData) => siblingData?.layout === 'withImage',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// --- Privacy ---
|
||||||
{
|
{
|
||||||
name: 'privacyText',
|
name: 'privacyText',
|
||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
@ -45,35 +90,59 @@ export const FDContactFormBlock: Block = {
|
|||||||
defaultValue:
|
defaultValue:
|
||||||
'Vi använder din kontaktinformation för att svara på din förfrågan och dela detaljer om våra produkter och tjänster. Du kan när som helst avregistrera dig.',
|
'Vi använder din kontaktinformation för att svara på din förfrågan och dela detaljer om våra produkter och tjänster. Du kan när som helst avregistrera dig.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'row',
|
||||||
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'privacyLinkText',
|
name: 'privacyLinkText',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
label: 'Integritetslänk text',
|
label: 'Integritetslänk text',
|
||||||
defaultValue: 'integritetspolicy',
|
defaultValue: 'integritetspolicy',
|
||||||
|
admin: { width: '50%' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'privacyLinkUrl',
|
name: 'privacyLinkUrl',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
label: 'Integritetslänk URL',
|
label: 'Integritetslänk URL',
|
||||||
defaultValue: '/integritetspolicy',
|
defaultValue: '/integritetspolicy',
|
||||||
|
admin: { width: '50%' },
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// --- External API (optional) ---
|
||||||
{
|
{
|
||||||
name: 'sideImage',
|
name: 'externalApi',
|
||||||
type: 'upload',
|
type: 'group',
|
||||||
relationTo: 'media',
|
label: 'Extern API-integration (valfri)',
|
||||||
label: 'Sidobild (valfri)',
|
|
||||||
admin: {
|
admin: {
|
||||||
description: 'Bild som visas till höger om formuläret',
|
description: 'Skicka formulärdata till ett externt system (t.ex. Lime CRM) utöver Payload',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'enabled',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Aktivera extern API',
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'endpoint',
|
||||||
|
type: 'text',
|
||||||
|
label: 'API-URL',
|
||||||
|
admin: {
|
||||||
|
description: 'T.ex. https://api.lime-crm.se/webhook/forms',
|
||||||
|
condition: (_, siblingData) => Boolean(siblingData?.enabled),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'background',
|
name: 'authToken',
|
||||||
type: 'select',
|
type: 'text',
|
||||||
label: 'Bakgrund',
|
label: 'Auth-token (Bearer)',
|
||||||
defaultValue: 'white',
|
admin: {
|
||||||
options: [
|
description: 'Skickas som Authorization: Bearer {token}',
|
||||||
{ label: 'Vit', value: 'white' },
|
condition: (_, siblingData) => Boolean(siblingData?.enabled),
|
||||||
{ label: 'Grå', value: 'gray' },
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -75,7 +75,6 @@ export interface Config {
|
|||||||
redirects: Redirect;
|
redirects: Redirect;
|
||||||
forms: Form;
|
forms: Form;
|
||||||
'form-submissions': FormSubmission;
|
'form-submissions': FormSubmission;
|
||||||
search: Search;
|
|
||||||
'payload-kv': PayloadKv;
|
'payload-kv': PayloadKv;
|
||||||
'payload-jobs': PayloadJob;
|
'payload-jobs': PayloadJob;
|
||||||
'payload-locked-documents': PayloadLockedDocument;
|
'payload-locked-documents': PayloadLockedDocument;
|
||||||
@ -92,7 +91,6 @@ export interface Config {
|
|||||||
redirects: RedirectsSelect<false> | RedirectsSelect<true>;
|
redirects: RedirectsSelect<false> | RedirectsSelect<true>;
|
||||||
forms: FormsSelect<false> | FormsSelect<true>;
|
forms: FormsSelect<false> | FormsSelect<true>;
|
||||||
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
|
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
|
||||||
search: SearchSelect<false> | SearchSelect<true>;
|
|
||||||
'payload-kv': PayloadKvSelect<false> | PayloadKvSelect<true>;
|
'payload-kv': PayloadKvSelect<false> | PayloadKvSelect<true>;
|
||||||
'payload-jobs': PayloadJobsSelect<false> | PayloadJobsSelect<true>;
|
'payload-jobs': PayloadJobsSelect<false> | PayloadJobsSelect<true>;
|
||||||
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||||
@ -758,14 +756,29 @@ export interface FDContactFormBlock {
|
|||||||
heading: string;
|
heading: string;
|
||||||
description?: string | null;
|
description?: string | null;
|
||||||
submitText?: string | null;
|
submitText?: string | null;
|
||||||
|
background?: ('white' | 'gray' | 'navy' | 'navyGradient') | null;
|
||||||
|
layout?: ('standard' | 'withImage' | 'card') | null;
|
||||||
|
/**
|
||||||
|
* Visas till höger om formuläret på desktop
|
||||||
|
*/
|
||||||
|
sideImage?: (number | null) | Media;
|
||||||
privacyText?: string | null;
|
privacyText?: string | null;
|
||||||
privacyLinkText?: string | null;
|
privacyLinkText?: string | null;
|
||||||
privacyLinkUrl?: string | null;
|
privacyLinkUrl?: string | null;
|
||||||
/**
|
/**
|
||||||
* Bild som visas till höger om formuläret
|
* Skicka formulärdata till ett externt system (t.ex. Lime CRM) utöver Payload
|
||||||
*/
|
*/
|
||||||
sideImage?: (number | null) | Media;
|
externalApi?: {
|
||||||
background?: ('white' | 'gray') | null;
|
enabled?: boolean | null;
|
||||||
|
/**
|
||||||
|
* T.ex. https://api.lime-crm.se/webhook/forms
|
||||||
|
*/
|
||||||
|
endpoint?: string | null;
|
||||||
|
/**
|
||||||
|
* Skickas som Authorization: Bearer {token}
|
||||||
|
*/
|
||||||
|
authToken?: string | null;
|
||||||
|
};
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
blockName?: string | null;
|
blockName?: string | null;
|
||||||
blockType: 'fdContactForm';
|
blockType: 'fdContactForm';
|
||||||
@ -1364,37 +1377,6 @@ export interface FormSubmission {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated.
|
|
||||||
*
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "search".
|
|
||||||
*/
|
|
||||||
export interface Search {
|
|
||||||
id: number;
|
|
||||||
title?: string | null;
|
|
||||||
priority?: number | null;
|
|
||||||
doc: {
|
|
||||||
relationTo: 'posts';
|
|
||||||
value: number | Post;
|
|
||||||
};
|
|
||||||
slug?: string | null;
|
|
||||||
meta?: {
|
|
||||||
title?: string | null;
|
|
||||||
description?: string | null;
|
|
||||||
image?: (number | null) | Media;
|
|
||||||
};
|
|
||||||
categories?:
|
|
||||||
| {
|
|
||||||
relationTo?: string | null;
|
|
||||||
categoryID?: string | null;
|
|
||||||
title?: string | null;
|
|
||||||
id?: string | null;
|
|
||||||
}[]
|
|
||||||
| null;
|
|
||||||
updatedAt: string;
|
|
||||||
createdAt: string;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-kv".
|
* via the `definition` "payload-kv".
|
||||||
@ -1542,10 +1524,6 @@ export interface PayloadLockedDocument {
|
|||||||
| ({
|
| ({
|
||||||
relationTo: 'form-submissions';
|
relationTo: 'form-submissions';
|
||||||
value: number | FormSubmission;
|
value: number | FormSubmission;
|
||||||
} | null)
|
|
||||||
| ({
|
|
||||||
relationTo: 'search';
|
|
||||||
value: number | Search;
|
|
||||||
} | null);
|
} | null);
|
||||||
globalSlug?: string | null;
|
globalSlug?: string | null;
|
||||||
user: {
|
user: {
|
||||||
@ -1952,11 +1930,19 @@ export interface FDContactFormBlockSelect<T extends boolean = true> {
|
|||||||
heading?: T;
|
heading?: T;
|
||||||
description?: T;
|
description?: T;
|
||||||
submitText?: T;
|
submitText?: T;
|
||||||
|
background?: T;
|
||||||
|
layout?: T;
|
||||||
|
sideImage?: T;
|
||||||
privacyText?: T;
|
privacyText?: T;
|
||||||
privacyLinkText?: T;
|
privacyLinkText?: T;
|
||||||
privacyLinkUrl?: T;
|
privacyLinkUrl?: T;
|
||||||
sideImage?: T;
|
externalApi?:
|
||||||
background?: T;
|
| T
|
||||||
|
| {
|
||||||
|
enabled?: T;
|
||||||
|
endpoint?: T;
|
||||||
|
authToken?: T;
|
||||||
|
};
|
||||||
id?: T;
|
id?: T;
|
||||||
blockName?: T;
|
blockName?: T;
|
||||||
}
|
}
|
||||||
@ -2520,33 +2506,6 @@ export interface FormSubmissionsSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "search_select".
|
|
||||||
*/
|
|
||||||
export interface SearchSelect<T extends boolean = true> {
|
|
||||||
title?: T;
|
|
||||||
priority?: T;
|
|
||||||
doc?: T;
|
|
||||||
slug?: T;
|
|
||||||
meta?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
title?: T;
|
|
||||||
description?: T;
|
|
||||||
image?: T;
|
|
||||||
};
|
|
||||||
categories?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
relationTo?: T;
|
|
||||||
categoryID?: T;
|
|
||||||
title?: T;
|
|
||||||
id?: T;
|
|
||||||
};
|
|
||||||
updatedAt?: T;
|
|
||||||
createdAt?: T;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-kv_select".
|
* via the `definition` "payload-kv_select".
|
||||||
|
|||||||
@ -3,12 +3,9 @@ import { FixedToolbarFeature, HeadingFeature, lexicalEditor } from '@payloadcms/
|
|||||||
import { nestedDocsPlugin } from '@payloadcms/plugin-nested-docs'
|
import { nestedDocsPlugin } from '@payloadcms/plugin-nested-docs'
|
||||||
import { redirectsPlugin } from '@payloadcms/plugin-redirects'
|
import { redirectsPlugin } from '@payloadcms/plugin-redirects'
|
||||||
import { seoPlugin } from '@payloadcms/plugin-seo'
|
import { seoPlugin } from '@payloadcms/plugin-seo'
|
||||||
import { searchPlugin } from '@payloadcms/plugin-search'
|
|
||||||
import { Plugin } from 'payload'
|
import { Plugin } from 'payload'
|
||||||
import { revalidateRedirects } from '@/hooks/revalidateRedirects'
|
import { revalidateRedirects } from '@/hooks/revalidateRedirects'
|
||||||
import { GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'
|
import { GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'
|
||||||
import { searchFields } from '@/search/fieldOverrides'
|
|
||||||
import { beforeSyncWithSearch } from '@/search/beforeSync'
|
|
||||||
import { Page, Post } from '@/payload-types'
|
import { Page, Post } from '@/payload-types'
|
||||||
import { getServerSideURL } from '@/utilities/getURL'
|
import { getServerSideURL } from '@/utilities/getURL'
|
||||||
|
|
||||||
@ -79,13 +76,4 @@ export const plugins: Plugin[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
searchPlugin({
|
|
||||||
collections: ['posts'],
|
|
||||||
beforeSync: beforeSyncWithSearch,
|
|
||||||
searchOverrides: {
|
|
||||||
fields: ({ defaultFields }) => {
|
|
||||||
return [...defaultFields, ...searchFields]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]
|
]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user