diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-05-06 18:21:16 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-05-07 15:54:35 +0200 |
| commit | 339c6957fe92c4ec1809159f09c55201d3794c18 (patch) | |
| tree | 74f1dd407c7871c46db6583f2b44cebbe20f7fdd /src/pages | |
| parent | a13022cd4c0a7cf0f00a6db49fad13db22d63dd6 (diff) | |
chore: add a Contact page
Diffstat (limited to 'src/pages')
| -rw-r--r-- | src/pages/contact.tsx | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/pages/contact.tsx b/src/pages/contact.tsx new file mode 100644 index 0000000..d88a8a1 --- /dev/null +++ b/src/pages/contact.tsx @@ -0,0 +1,181 @@ +import Notice, { NoticeKind } from '@components/atoms/layout/notice'; +import { BreadcrumbItem } from '@components/molecules/nav/breadcrumb'; +import ContactForm, { + ContactFormProps, +} from '@components/organisms/forms/contact-form'; +import SocialMedia from '@components/organisms/widgets/social-media'; +import PageLayout from '@components/templates/page/page-layout'; +import { meta } from '@content/pages/contact.mdx'; +import styles from '@styles/pages/contact.module.scss'; +import { sendMail } from '@services/graphql/contact'; +import { loadTranslation } from '@utils/helpers/i18n'; +import useSettings from '@utils/hooks/use-settings'; +import { GetStaticProps, NextPage } from 'next'; +import Head from 'next/head'; +import { useRouter } from 'next/router'; +import Script from 'next/script'; +import { useState } from 'react'; +import { useIntl } from 'react-intl'; +import { ContactPage as ContactPageSchema, Graph, WebPage } from 'schema-dts'; + +const ContactPage: NextPage = () => { + const { dates, intro, seo, title } = meta; + const intl = useIntl(); + const homeLabel = intl.formatMessage({ + defaultMessage: 'Home', + description: 'Breadcrumb: home label', + id: 'j5k9Fe', + }); + const breadcrumb: BreadcrumbItem[] = [ + { id: 'home', name: homeLabel, url: '/' }, + { id: 'contact', name: title, url: '/contact' }, + ]; + + const socialMediaTitle = intl.formatMessage({ + defaultMessage: 'Find me elsewhere', + description: 'ContactPage: social media widget title', + id: 'Qh2CwH', + }); + + const { website } = useSettings(); + const { asPath } = useRouter(); + const pageUrl = `${website.url}${asPath}`; + const pagePublicationDate = new Date(dates.publication); + const pageUpdateDate = new Date(dates.update); + + const webpageSchema: WebPage = { + '@id': `${pageUrl}`, + '@type': 'WebPage', + breadcrumb: { '@id': `${website.url}/#breadcrumb` }, + name: seo.title, + description: seo.description, + reviewedBy: { '@id': `${website.url}/#branding` }, + url: `${pageUrl}`, + isPartOf: { + '@id': `${website.url}`, + }, + }; + + const contactSchema: ContactPageSchema = { + '@id': `${website.url}/#contact`, + '@type': 'ContactPage', + name: title, + description: intro, + author: { '@id': `${website.url}/#branding` }, + creator: { '@id': `${website.url}/#branding` }, + dateCreated: pagePublicationDate.toISOString(), + dateModified: pageUpdateDate.toISOString(), + datePublished: pagePublicationDate.toISOString(), + editor: { '@id': `${website.url}/#branding` }, + inLanguage: website.locales.default, + license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr', + mainEntityOfPage: { '@id': `${pageUrl}` }, + }; + + const schemaJsonLd: Graph = { + '@context': 'https://schema.org', + '@graph': [webpageSchema, contactSchema], + }; + + const widgets = [ + <SocialMedia + key="social-media" + title={socialMediaTitle} + level={2} + media={[ + { name: 'Github', url: 'https://github.com/ArmandPhilippot' }, + { name: 'Gitlab', url: 'https://gitlab.com/ArmandPhilippot' }, + { + name: 'LinkedIn', + url: 'https://www.linkedin.com/in/armandphilippot', + }, + ]} + />, + ]; + + const [status, setStatus] = useState<NoticeKind>('info'); + const [statusMessage, setStatusMessage] = useState<string>(''); + + const submitMail: ContactFormProps['sendMail'] = async (data, reset) => { + const { email, message, name, subject } = data; + const messageHTML = message.replace(/\r?\n/g, '<br />'); + const body = `Message received from ${name} <${email}> on ${website.url}.<br /><br />${messageHTML}`; + const replyTo = `${name} <${email}>`; + const mailData = { + body, + clientMutationId: 'contact', + replyTo, + subject, + }; + const { message: mutationMessage, sent } = await sendMail(mailData); + + if (sent) { + setStatus('success'); + setStatusMessage( + intl.formatMessage({ + defaultMessage: + 'Thanks. Your message was successfully sent. I will answer it as soon as possible.', + description: 'Contact: success message', + id: '3Pipok', + }) + ); + reset(); + } else { + const errorPrefix = intl.formatMessage({ + defaultMessage: 'An error occurred:', + description: 'Contact: error message', + id: 'TpyFZ6', + }); + const error = `${errorPrefix} ${mutationMessage}`; + setStatus('error'); + setStatusMessage(error); + } + }; + + return ( + <> + <Head> + <title>{`${seo.title} - ${website.name}`}</title> + <meta name="description" content={seo.description} /> + <meta property="og:url" content={`${pageUrl}`} /> + <meta property="og:type" content="article" /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={intro} /> + </Head> + <Script + id="schema-contact" + type="application/ld+json" + dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }} + /> + <PageLayout + title="Contact" + intro={intro} + breadcrumb={breadcrumb} + widgets={widgets} + > + <ContactForm + sendMail={submitMail} + Notice={ + <Notice + kind={status} + message={statusMessage} + className={styles.notice} + /> + } + /> + </PageLayout> + </> + ); +}; + +export const getStaticProps: GetStaticProps = async ({ locale }) => { + const translation = await loadTranslation(locale); + + return { + props: { + translation, + }, + }; +}; + +export default ContactPage; |
