From d329662756509b0b450c82f49c3a56032b2e7e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fede=20=C3=81lvarez?= <78366796+fedealvarezcampos@users.noreply.github.com> Date: Fri, 20 May 2022 11:11:07 +0200 Subject: [PATCH] Work on Careers page (#68) --- .../sections/careers/hero/hero.module.scss | 172 ++++++++++++++++++ .../sections/careers/hero/index.tsx | 64 +++++++ .../sections/careers/positions/index.tsx | 89 +++++++++ .../careers/positions/positions.module.scss | 145 +++++++++++++++ .../sections/careers/values/index.tsx | 99 ++++++++++ .../careers/values/values.module.scss | 136 ++++++++++++++ src/components/sections/careers/why/index.tsx | 79 ++++++++ .../sections/careers/why/why.module.scss | 83 +++++++++ src/lib/cms/queries/careers.js | 105 +++++++++++ src/pages/careers.tsx | 87 +++++++++ 10 files changed, 1059 insertions(+) create mode 100644 src/components/sections/careers/hero/hero.module.scss create mode 100644 src/components/sections/careers/hero/index.tsx create mode 100644 src/components/sections/careers/positions/index.tsx create mode 100644 src/components/sections/careers/positions/positions.module.scss create mode 100644 src/components/sections/careers/values/index.tsx create mode 100644 src/components/sections/careers/values/values.module.scss create mode 100644 src/components/sections/careers/why/index.tsx create mode 100644 src/components/sections/careers/why/why.module.scss create mode 100644 src/lib/cms/queries/careers.js create mode 100644 src/pages/careers.tsx diff --git a/src/components/sections/careers/hero/hero.module.scss b/src/components/sections/careers/hero/hero.module.scss new file mode 100644 index 0000000..8b9dcf6 --- /dev/null +++ b/src/components/sections/careers/hero/hero.module.scss @@ -0,0 +1,172 @@ +@import '~/css/helpers'; + +.section { + @include respond-to('mobile') { + margin-bottom: tovw(88px, 'mobile'); + padding: 0; + width: 100vw; + justify-content: flex-start; + } + + display: flex; + flex-direction: column; + justify-content: center; + padding: tovw(100px, 'default', 50px) 0; + max-width: 100%; + min-height: calc(var(--vh) * 100); + + .container { + @include respond-to('mobile') { + padding: 0 tovw(56px, 'default', 16px); + } + } + + .video_container { + align-self: center; + position: relative; + margin-top: tovw(-165px, 'default'); + margin-bottom: tovw(-140px, 'default'); + padding-top: tovw(30px, 'default', 20px); + width: 82%; + mix-blend-mode: lighten; + + video { + @include respond-to('mobile') { + display: none; + } + + width: 100%; + } + + &::after { + position: absolute; + top: 0; + left: 0; + z-index: 1; + background: radial-gradient( + ellipse, + rgb(3 3 3 / 0) 60%, + rgb(3 3 3 / 1) 75%, + rgb(3 3 3 / 1) 100% + ); + width: 100%; + height: 100%; + content: ''; + } + } + + .hero__mobile { + @include respond-to('mobile') { + display: flex; + margin: tovw(50px, 'mobile', 130px) 0 tovw(50px, 'mobile', 70px) + tovw(16px, 'mobile', 20px); + width: 200%; + mix-blend-mode: screen; + place-self: center; + mask-image: linear-gradient( + 0deg, + rgb(255 255 255 / 0) 0%, + rgb(0 0 0) 25% + ); + } + + display: none; + } + + .body { + @include respond-to('mobile') { + flex-direction: column; + align-items: flex-start; + } + + display: flex; + justify-content: space-between; + align-items: center; + margin-top: tovw(16px, 'default', 10px); + + h1 { + @include respond-to('mobile') { + width: 100%; + font-size: tovw(50px, 'mobile'); + } + + margin: 0; + width: tovw(600px, 'default', 300px); + text-shadow: 0 0 tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4); + } + + .text__container { + @include respond-to('mobile') { + margin-top: tovw(25px, 'mobile'); + } + + display: flex; + align-items: center; + + h2 { + @include respond-to('mobile') { + min-width: tovw(75px, 'mobile'); + } + + line-height: 120%; + padding-top: tovw(15px, 'default', 15px); + width: tovw(500px, 'default', 300px); + } + + .line { + @include respond-to('mobile') { + top: unset; + margin: 0; + left: 0; + height: tovw(100px, 'default', 90px); + transform: rotate(0deg) translateY(tovw(8px, 'default', 8px)) + scaleX(1.2) scaleY(1.4); + } + + margin-top: tovw(5px, 'default', 5px); + height: tovw(140px, 'default', 140px); + transform: scaleX(1.5); + padding-right: tovw(25px, 'default', 15px); + } + } + + div:first-child { + @include respond-to('mobile') { + width: 100%; + display: flex; + justify-content: space-between; + } + + .arrow { + @include respond-to('mobile') { + display: unset; + position: relative; + align-self: flex-end; + padding-bottom: tovw(10px, 'mobile', 10px); + width: tovw(18px, 'mobile', 18px); + } + + display: none; + } + } + } + + .gradient { + @include respond-to('mobile') { + height: 80%; + } + + position: absolute; + top: 0; + left: 0; + z-index: 2; + mix-blend-mode: screen; + background: linear-gradient( + 180deg, + rgb(0 0 244 / 0.9) 1.63%, + rgb(0 0 244 / 0) 99.89% + ); + width: 100%; + height: tovw(740px, 'default', 740px); + } +} diff --git a/src/components/sections/careers/hero/index.tsx b/src/components/sections/careers/hero/index.tsx new file mode 100644 index 0000000..5553f69 --- /dev/null +++ b/src/components/sections/careers/hero/index.tsx @@ -0,0 +1,64 @@ +import { useRef } from 'react' + +import { Arrow } from '~/components/icons/arrow' +import Line from '~/components/icons/line' +import { Container } from '~/components/layout/container' +import Section from '~/components/layout/section' +import Heading from '~/components/primitives/heading' + +import s from './hero.module.scss' + +interface Props { + data: { + heroHeading: string + heroLine: string + } +} + +const Hero = ({ data }: Props) => { + const heroVideoRef = useRef(null) + + return ( +
+
+
+ +
+ hero + +
+
+ + {data?.heroHeading} + + +
+
+ + + {data?.heroLine} + +
+
+
+
+ ) +} + +export default Hero diff --git a/src/components/sections/careers/positions/index.tsx b/src/components/sections/careers/positions/index.tsx new file mode 100644 index 0000000..1f63c52 --- /dev/null +++ b/src/components/sections/careers/positions/index.tsx @@ -0,0 +1,89 @@ +import { Arrow } from '~/components/icons/arrow' +import { Container } from '~/components/layout/container' +import Section from '~/components/layout/section' +import Heading from '~/components/primitives/heading' +import Link from '~/components/primitives/link' + +import s from './positions.module.scss' + +interface Props { + data: { + positionsHeading: string + positionsHeadingNumber: string + positionsLinkLabel: string + positionsCercHead: string + positionsXylmHead: string + } + positionsData: { + id: string + positionLink: string + positionName: string + positionTeam: string + }[] +} + +const Positions = ({ data, positionsData }: Props) => { + const cercPositions = positionsData?.filter((team) => + team.positionTeam.includes('Cerc') + ) + const xylmPositions = positionsData?.filter((team) => + team.positionTeam.includes('Xylm') + ) + + return ( +
+ +
+ + {data?.positionsHeading} + + {data?.positionsHeadingNumber} +
+
+ {cercPositions && ( +
+
+ + {data?.positionsCercHead} + + +
+
    + {cercPositions?.map((position) => ( +
  • + {position?.positionName} + + {data?.positionsLinkLabel} + +
  • + ))} +
+
+ )} + {xylmPositions && ( +
+
+ + {data?.positionsXylmHead} + + +
+
    + {xylmPositions?.map((position) => ( +
  • + {position?.positionName} + + {data?.positionsLinkLabel} + +
  • + ))} +
+
+ )} +
+
+
+ ) +} + +export default Positions diff --git a/src/components/sections/careers/positions/positions.module.scss b/src/components/sections/careers/positions/positions.module.scss new file mode 100644 index 0000000..358c96e --- /dev/null +++ b/src/components/sections/careers/positions/positions.module.scss @@ -0,0 +1,145 @@ +@import '~/css/helpers'; + +.section { + @include respond-to('mobile') { + margin-top: 0; + } + + position: relative; + margin: tovw(105px, 'default', 70px) 0; + padding: tovw(104px, 'default', 95px) 0; + + .container { + @include respond-to('mobile') { + padding: 0 tovw(56px, 'default', 16px); + width: 100%; + } + + position: relative; + width: tovw(1076px, 'default', 400px); + + .header { + @include respond-to('mobile') { + align-items: flex-end; + } + + display: flex; + justify-content: space-between; + border-bottom: tovw(1px, 'default', 1px) solid var(--color-grey-light); + padding-bottom: tovw(36px, 'default', 24px); + + > h2 { + text-shadow: 0 0 tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4); + } + + span { + padding-top: tovw(35px, 'default', 14px); + color: var(--color-grey-light); + font-family: var(--font-dm-mono), sans-serif; + font-size: tovw(18px, 'default', 12px); + } + } + + .careers { + @include respond-to('mobile') { + gap: tovw(80px, 'default', 70px); + } + + display: flex; + flex-direction: column; + justify-content: space-between; + gap: tovw(150px); + margin-top: tovw(70px, 'default', 40px); + + div { + @include respond-to('mobile') { + flex-direction: column; + } + + display: flex; + + ul { + @include respond-to('mobile') { + padding: 0; + } + + display: flex; + flex-direction: column; + margin: 0; + padding-left: tovw(124px, 'default', 45px); + list-style: none; + width: 100%; + + li { + @include respond-to('mobile') { + flex-direction: column; + height: fit-content; + gap: tovw(15px, 'default', 15px); + justify-content: unset; + margin-top: tovw(30px, 'default', 20px); + padding-bottom: tovw(25px, 'default', 25px); + } + + display: flex; + align-items: flex-start; + justify-content: space-between; + width: 100%; + height: tovw(56px, 'default', 35px); + border-bottom: tovw(1px, 'default', 1px) solid + var(--color-grey-light); + + &:not(:first-child) { + margin-top: tovw(28px, 'default', 20px); + } + + span { + @include respond-to('mobile') { + font-size: tovw(18px, 'default', 18px); + } + + font-family: var(--font-tt-hoves); + font-size: tovw(24px, 'default', 16px); + } + + a { + @include respond-to('mobile') { + font-size: tovw(18px, 'default', 18px); + } + + font-size: tovw(18px, 'default', 12px); + margin-right: tovw(25px, 'default', 12px); + } + } + } + + .heading { + @include respond-to('mobile') { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + height: tovw(80px, 'default', 80px); + border-bottom: tovw(1px, 'default', 1px) solid + var(--color-grey-light); + } + + h3 { + margin-top: tovw(-10px, 'default', -10px); + } + + .arrow { + @include respond-to('mobile') { + position: relative; + left: 0; + } + + position: absolute; + width: tovw(23px, 'default', 15px); + left: tovw(172px, 'default', 100px); + } + } + } + } + } +} diff --git a/src/components/sections/careers/values/index.tsx b/src/components/sections/careers/values/index.tsx new file mode 100644 index 0000000..7995c41 --- /dev/null +++ b/src/components/sections/careers/values/index.tsx @@ -0,0 +1,99 @@ +// import { Arrow } from '~/components/icons/arrow' +import { Container } from '~/components/layout/container' +import Section from '~/components/layout/section' +import Heading from '~/components/primitives/heading' + +import s from './values.module.scss' + +interface Props { + data: { + valuesHeading: string + valuesPoint01Head: string + valuesPoint01Line: string + valuesPoint01Image: { + url: string + } + valuesPoint02Head: string + valuesPoint02Line: string + valuesPoint02Image: { + url: string + } + valuesPoint03Head: string + valuesPoint03Line: string + valuesPoint03Image: { + url: string + } + valuesPoint04Head: string + valuesPoint04Line: string + valuesPoint04Image: { + url: string + } + } +} + +const Network = ({ data }: Props) => { + return ( +
+ +
+ network + network +
+ + {data?.valuesHeading} + +
+
+ detail +
+ + {data?.valuesPoint01Head} + +

{data?.valuesPoint01Line}

+
+
+
+ detail +
+ + {data?.valuesPoint02Head} + +

{data?.valuesPoint02Line}

+
+
+
+ detail +
+ + {data?.valuesPoint03Head} + +

{data?.valuesPoint03Line}

+
+
+
+ detail +
+ + {data?.valuesPoint04Head} + +

{data?.valuesPoint04Line}

+
+
+
+
+
+
+
+
+ ) +} + +export default Network diff --git a/src/components/sections/careers/values/values.module.scss b/src/components/sections/careers/values/values.module.scss new file mode 100644 index 0000000..e69c7e2 --- /dev/null +++ b/src/components/sections/careers/values/values.module.scss @@ -0,0 +1,136 @@ +@import '~/css/helpers'; + +.section { + @include respond-to('mobile') { + padding: 0; + padding-bottom: tovw(18px, 'mobile'); + } + + position: relative; + padding: tovw(180px, 'default', 100px) 0; + + .container { + @include respond-to('mobile') { + padding: 0 tovw(56px, 'default', 16px); + } + + display: flex; + justify-content: flex-end; + position: relative; + + div:first-child { + @include respond-to('mobile') { + width: 100%; + } + + h2 { + @include respond-to('mobile') { + width: tovw(200px, 'mobile'); + } + + text-shadow: 0 0 tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4); + } + + .features { + @include respond-to('mobile') { + display: flex; + flex-direction: column; + } + + display: grid; + margin-top: tovw(95px, 'default', 50px); + gap: tovw(55px, 'default', 30px) tovw(40px, 'default', 20px); + grid-template-columns: repeat(2, tovw(405px, 'default', 212px)); + + > div { + display: grid; + gap: tovw(23px, 'default', 16px); + grid-template-columns: auto 1fr; + + h3 { + line-height: 1.3; + font-size: tovw(40px, 'default', 25px); + } + + img { + flex: 1; + width: tovw(55px, 'default', 45px); + } + + p { + @include respond-to('mobile') { + width: 100%; + font-size: tovw(18px, 'default', 18px); + padding-right: tovw(10px, 'default', 10px); + } + + margin: 0; + margin-top: tovw(20px, 'default', 16px); + line-height: 1.6; + color: var(--color-grey-light); + font-size: tovw(24px, 'default', 15px); + } + + &:last-child { + p { + @include respond-to('mobile') { + width: 100%; + } + + width: tovw(300px, 'default', 85px); + } + } + } + } + } + + .network__img { + @include respond-to('mobile') { + display: none; + } + + position: absolute; + bottom: tovw(-300px, 'default', -300px); + z-index: -1; + right: tovw(750px, 'default', 50px); + width: tovw(920px, 'default', 350px); + mix-blend-mode: screen; + } + + .network__img__mobile { + @include respond-to('mobile') { + display: unset; + margin: tovw(60px, 'mobile') 0 tovw(40px, 'mobile') 0; + width: 100%; + mix-blend-mode: screen; + } + + display: none; + } + } + + .gradient { + @include respond-to('mobile') { + display: none; + } + + position: absolute; + right: 0; + bottom: tovw(80px, 'default', 80px); + left: 0; + opacity: 0.4; + margin-left: 0; + background: linear-gradient( + 180deg, + rgb(229 229 229 / 0) 0%, + rgb(241 241 241 / 0.4) 48.91%, + rgb(241 241 241 / 0) 96% + ); + width: 100%; + height: tovw(600px, 'default', 180px); + content: ''; + pointer-events: none; + user-select: none; + z-index: -1; + } +} diff --git a/src/components/sections/careers/why/index.tsx b/src/components/sections/careers/why/index.tsx new file mode 100644 index 0000000..22cd60a --- /dev/null +++ b/src/components/sections/careers/why/index.tsx @@ -0,0 +1,79 @@ +import { Container } from '~/components/layout/container' +import Section from '~/components/layout/section' +import Heading from '~/components/primitives/heading' + +import s from './why.module.scss' + +interface Props { + data: { + whyHeading: string + whyHeadNumber: string + whyPoint01Line: string + whyPoint01Img: { + url: string + } + whyPoint02Line: string + whyPoint02Img: { + url: string + } + whyPoint03Line: string + whyPoint03Img: { + url: string + } + whyPoint04Line: string + whyPoint04Img: { + url: string + } + whyPoint05Line: string + whyPoint05Img: { + url: string + } + whyPoint06Line: string + whyPoint06Img: { + url: string + } + } +} + +const WhyJoin = ({ data }: Props) => { + return ( +
+ +
+ + {data?.whyHeading} + + {data?.whyHeadNumber} +
+
+
+ detail +

{data?.whyPoint01Line}

+
+
+ detail +

{data?.whyPoint02Line}

+
+
+ detail +

{data?.whyPoint03Line}

+
+
+ detail +

{data?.whyPoint04Line}

+
+
+ detail +

{data?.whyPoint05Line}

+
+
+ detail +

{data?.whyPoint06Line}

+
+
+
+
+ ) +} + +export default WhyJoin diff --git a/src/components/sections/careers/why/why.module.scss b/src/components/sections/careers/why/why.module.scss new file mode 100644 index 0000000..7f2674e --- /dev/null +++ b/src/components/sections/careers/why/why.module.scss @@ -0,0 +1,83 @@ +@import '~/css/helpers'; + +.section { + @include respond-to('mobile') { + padding-bottom: 0; + } + + position: relative; + margin: tovw(140px, 'default', 110px) 0; + padding: tovw(104px, 'default', 90px) 0; + + .container { + @include respond-to('mobile') { + padding: 0 tovw(56px, 'default', 16px); + width: 100%; + } + + position: relative; + width: tovw(1076px, 'default', 400px); + + .header { + @include respond-to('mobile') { + align-items: flex-end; + } + + display: flex; + justify-content: space-between; + border-bottom: tovw(1px, 'default', 1px) solid var(--color-grey-light); + padding-bottom: tovw(36px, 'default', 24px); + + > h2 { + text-shadow: 0 0 tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4); + } + + span { + padding-top: tovw(35px, 'default', 14px); + color: var(--color-grey-light); + font-family: var(--font-dm-mono), sans-serif; + font-size: tovw(18px, 'default', 12px); + } + } + + .features { + @include respond-to('mobile') { + display: flex; + flex-direction: column; + } + + display: grid; + justify-content: space-between; + margin-top: tovw(80px, 'default', 40px); + gap: tovw(64px, 'default', 40px) 0; + grid-template-columns: repeat(3, tovw(250px, 'default', 130px)); + + > div { + @include respond-to('mobile') { + margin: 0 tovw(10px, 'mobile'); + } + + display: grid; + justify-content: space-between; + gap: tovw(15px, 'default', 10px); + grid-template-columns: auto 1fr; + + img { + flex: 1; + width: tovw(55px, 'default', 45px); + } + + p { + @include respond-to('mobile') { + width: 100%; + } + + margin: 0; + margin-top: tovw(10px, 'default', 8px); + line-height: 1.6; + font-size: tovw(24px, 'default', 15px); + } + } + } + } +} diff --git a/src/lib/cms/queries/careers.js b/src/lib/cms/queries/careers.js new file mode 100644 index 0000000..790860a --- /dev/null +++ b/src/lib/cms/queries/careers.js @@ -0,0 +1,105 @@ +const CareersHero = { + query: ` + { + careersPage { + heroHeading + heroLine + } + }` +} + +const CareersValues = { + query: ` + { + careersPage { + valuesHeading + valuesPoint01Head + valuesPoint01Image { + url + } + valuesPoint01Line + valuesPoint02Head + valuesPoint02Image { + url + } + valuesPoint02Line + valuesPoint03Head + valuesPoint03Image { + url + } + valuesPoint03Line + valuesPoint04Head + valuesPoint04Image { + url + } + valuesPoint04Line + } + }` +} + +const CareersWhy = { + query: ` + { + careersPage { + whyHeading + whyPoint01Img { + url + } + whyPoint01Line + whyPoint02Img { + url + } + whyPoint02Line + whyPoint03Img { + url + } + whyPoint03Line + whyPoint04Img { + url + } + whyPoint04Line + whyPoint05Img { + url + } + whyPoint05Line + whyPoint06Img { + url + } + whyPoint06Line + whyHeadNumber + } + }` +} + +const CareersPositions = { + query: ` + { + allPositions { + id + positionLink + positionName + positionTeam + } + }` +} + +const CareersPositionsSection = { + query: ` + { + careersPage { + positionsHeading + positionsHeadingNumber + positionsLinkLabel + positionsXylmHead + positionsCercHead + } + }` +} + +export { + CareersHero, + CareersPositions, + CareersPositionsSection, + CareersValues, + CareersWhy +} diff --git a/src/pages/careers.tsx b/src/pages/careers.tsx new file mode 100644 index 0000000..d023455 --- /dev/null +++ b/src/pages/careers.tsx @@ -0,0 +1,87 @@ +import { + getBlogPosts as serverGetBlogPosts, + getBlogPostsCategories as serverGetBlogPostsCategories +} from 'lib/blog' +import { InferGetStaticPropsType } from 'next' + +import { Meta } from '~/components/common/meta' +import { PageLayout } from '~/components/layout/page' +import Related from '~/components/sections/about/related' +import Hero from '~/components/sections/careers/hero' +import Positions from '~/components/sections/careers/positions' +import Values from '~/components/sections/careers/values' +import WhyJoin from '~/components/sections/careers/why' +import { + CareersHero, + CareersPositions, + CareersPositionsSection, + CareersValues, + CareersWhy +} from '~/lib/cms/queries/careers' + +import { request } from '../lib/datocms' + +export const getStaticProps = async () => { + const [allBlogPosts, categories] = await Promise.all([ + serverGetBlogPosts({ page: 1 }), + serverGetBlogPostsCategories() + ]) + + const heroBlogPost = allBlogPosts.data[0] + + const [heroData, valuesData, whyData, positionsData, positionsSectData] = + await Promise.all([ + request(CareersHero), + request(CareersValues), + request(CareersWhy), + request(CareersPositions), + request(CareersPositionsSection) + ]) + + return { + props: { + heroData: heroData?.careersPage, + valuesData: valuesData?.careersPage, + positionsSectData: positionsSectData?.careersPage, + whyData: whyData?.careersPage, + positionsData: positionsData?.allPositions, + initialBlogPosts: { + pagination: allBlogPosts.pagination, + data: allBlogPosts.data.slice(0, 3) + }, + categories, + page: + { + heroBlogPost + } ?? null + }, + revalidate: 60 + } +} + +const About = ({ + heroData, + valuesData, + initialBlogPosts, + whyData, + positionsData, + positionsSectData +}: InferGetStaticPropsType) => { + return ( + + + + + + + + + ) +} + +export default About