diff options
| -rw-r--r-- | src/config/seo.ts | 4 | ||||
| -rw-r--r-- | src/pages/cv.tsx | 48 | ||||
| -rw-r--r-- | src/services/graphql/pages.ts | 48 | ||||
| -rw-r--r-- | src/ts/types/pages.ts | 29 |
4 files changed, 129 insertions, 0 deletions
diff --git a/src/config/seo.ts b/src/config/seo.ts index 98bccfc..c5853e9 100644 --- a/src/config/seo.ts +++ b/src/config/seo.ts @@ -9,4 +9,8 @@ export const seo = { title: t`Blog: development, open source | Armand Philippot`, description: t`Discover Armand Philippot's writings. He talks about web development and open source mostly.`, }, + cv: { + title: t`CV Front-end developer | Armand Philippot`, + description: t`Discover the curriculum of Armand Philippot, front-end developer located in France: skills, experiences and training.`, + }, }; diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx new file mode 100644 index 0000000..5b913f3 --- /dev/null +++ b/src/pages/cv.tsx @@ -0,0 +1,48 @@ +import Layout from '@components/Layouts/Layout'; +import { seo } from '@config/seo'; +import { getCVPage } from '@services/graphql/pages'; +import { NextPageWithLayout } from '@ts/types/app'; +import { PageProps } from '@ts/types/pages'; +import { loadTranslation } from '@utils/helpers/i18n'; +import { GetStaticProps, GetStaticPropsContext } from 'next'; +import Head from 'next/head'; +import { ReactElement } from 'react'; + +const CV: NextPageWithLayout<PageProps> = ({ page }) => { + return ( + <> + <Head> + <title>{seo.cv.title}</title> + <meta name="description" content={seo.cv.description} /> + </Head> + <article> + <header> + <h1>{page.title}</h1> + <div dangerouslySetInnerHTML={{ __html: page.intro }}></div> + </header> + <div dangerouslySetInnerHTML={{ __html: page.content }}></div> + </article> + </> + ); +}; + +CV.getLayout = (page: ReactElement) => <Layout>{page}</Layout>; + +export const getStaticProps: GetStaticProps = async ( + context: GetStaticPropsContext +) => { + const translation = await loadTranslation( + context.locale!, + process.env.NODE_ENV === 'production' + ); + const page = await getCVPage(); + + return { + props: { + page, + translation, + }, + }; +}; + +export default CV; diff --git a/src/services/graphql/pages.ts b/src/services/graphql/pages.ts new file mode 100644 index 0000000..6689e37 --- /dev/null +++ b/src/services/graphql/pages.ts @@ -0,0 +1,48 @@ +import { + FetchPageByUriReturn, + GetCVPageReturn, + Page, + PageResponse, + RawPage, +} from '@ts/types/pages'; +import { gql } from 'graphql-request'; +import { getGraphQLClient } from './client'; + +const fetchPageByUri: FetchPageByUriReturn = async (uri: string) => { + const client = getGraphQLClient(); + const query = gql` + query PageByUri($uri: String!) { + pageBy(uri: $uri) { + contentParts { + afterMore + beforeMore + } + date + modified + title + } + } + `; + + const variables = { uri }; + + try { + const response: PageResponse = await client.request(query, variables); + return response.pageBy; + } catch (error) { + console.error(JSON.stringify(error, undefined, 2)); + process.exit(1); + } +}; + +export const getCVPage: GetCVPageReturn = async () => { + const rawCV = await fetchPageByUri('/cv/'); + + const formattedCV: Page = { + ...rawCV, + content: rawCV.contentParts.afterMore, + intro: rawCV.contentParts.beforeMore, + }; + + return formattedCV; +}; diff --git a/src/ts/types/pages.ts b/src/ts/types/pages.ts new file mode 100644 index 0000000..fa4d05d --- /dev/null +++ b/src/ts/types/pages.ts @@ -0,0 +1,29 @@ +export type Page = { + content: string; + date: string; + intro: string; + modified: string; + title: string; +}; + +export type RawPage = { + contentParts: { + afterMore: string; + beforeMore: string; + }; + date: string; + modified: string; + title: string; +}; + +export type PageResponse = { + pageBy: RawPage; +}; + +export type FetchPageByUriReturn = (uri: string) => Promise<RawPage>; + +export type GetCVPageReturn = () => Promise<Page>; + +export type PageProps = { + page: Page; +}; |
