Files
payload/packages/plugin-seo/src/fields/MetaTitle.tsx
Paul e091a37241 chore: update seo plugin (#5309)
* chore: update seo plugin

* fix translations export
2024-03-12 18:47:14 -03:00

159 lines
4.0 KiB
TypeScript

'use client'
import type { FieldType, FormFieldBase, Options } from '@payloadcms/ui'
import { useFieldPath } from '@payloadcms/ui'
import {
TextInput,
useAllFormFields,
useDocumentInfo,
useField,
useLocale,
useTranslation,
} from '@payloadcms/ui'
import React, { useCallback } from 'react'
import type { GenerateTitle } from '../types.js'
import { defaults } from '../defaults.js'
import { LengthIndicator } from '../ui/LengthIndicator.js'
import './index.scss'
const { maxLength, minLength } = defaults.title
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
type MetaTitleProps = FormFieldBase & {
hasGenerateTitleFn: boolean
}
export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
const { Label, hasGenerateTitleFn, path, required } = props || {}
const { path: pathFromContext } = useFieldPath()
const { t } = useTranslation()
const field: FieldType<string> = useField({
path,
} as Options)
const locale = useLocale()
const [fields] = useAllFormFields()
const docInfo = useDocumentInfo()
const { errorMessage, setValue, showError, value } = field
const regenerateTitle = useCallback(async () => {
if (!hasGenerateTitleFn) return
const genTitleResponse = await fetch('/api/plugin-seo/generate-title', {
body: JSON.stringify({
...docInfo,
doc: { ...fields },
locale: typeof locale === 'object' ? locale?.code : locale,
} satisfies Parameters<GenerateTitle>[0]),
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
})
const { result: generatedTitle } = await genTitleResponse.json()
setValue(generatedTitle || '')
}, [fields, setValue, hasGenerateTitleFn, locale, docInfo])
return (
<div
style={{
marginBottom: '20px',
}}
>
<div
style={{
marginBottom: '5px',
position: 'relative',
}}
>
<div className="plugin-seo__field">
{Label}
{required && (
<span
style={{
color: 'var(--theme-error-500)',
marginLeft: '5px',
}}
>
*
</span>
)}
{hasGenerateTitleFn && (
<React.Fragment>
&nbsp; &mdash; &nbsp;
<button
onClick={regenerateTitle}
style={{
background: 'none',
backgroundColor: 'transparent',
border: 'none',
color: 'currentcolor',
cursor: 'pointer',
padding: 0,
textDecoration: 'underline',
}}
type="button"
>
{t('plugin-seo:autoGenerate')}
</button>
</React.Fragment>
)}
</div>
<div
style={{
color: '#9A9A9A',
}}
>
{t('plugin-seo:lengthTipTitle', { maxLength, minLength })}
<a
href="https://developers.google.com/search/docs/advanced/appearance/title-link#page-titles"
rel="noopener noreferrer"
target="_blank"
>
{t('plugin-seo:bestPractices')}
</a>
.
</div>
</div>
<div
style={{
marginBottom: '10px',
position: 'relative',
}}
>
<TextInput
Error={errorMessage} // TODO: fix errormessage
onChange={setValue}
path={pathFromContext}
required={required}
showError={showError}
style={{
marginBottom: 0,
}}
value={value}
/>
</div>
<div
style={{
alignItems: 'center',
display: 'flex',
width: '100%',
}}
>
<LengthIndicator maxLength={maxLength} minLength={minLength} text={value} />
</div>
</div>
)
}