Work on Careers page (#68)

This commit is contained in:
Fede Álvarez 2022-05-20 11:11:07 +02:00 committed by GitHub
parent a04dc09bb7
commit d329662756
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1059 additions and 0 deletions

View File

@ -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);
}
}

View File

@ -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<HTMLVideoElement>(null)
return (
<Section className={s['section']} disableFadeIn>
<div className={s.gradient} />
<div className={s.video_container}>
<video
autoPlay
ref={heroVideoRef}
controls={false}
loop
muted
playsInline={true}
preload="true"
>
<source src="/videos/banner-products.webm" type="video/webm" />
<source src="/videos/banner-products.mp4" type="video/mp4" />
</video>
</div>
<img
className={s.hero__mobile}
loading="eager"
alt="hero"
src="/images/products/products.jpg"
/>
<Container className={s['container']}>
<div className={s.body}>
<div>
<Heading as="h1" variant="xl">
{data?.heroHeading}
</Heading>
<Arrow className={s['arrow']} />
</div>
<div className={s.text__container}>
<Line className={s.line} height={144} />
<Heading as="h2" variant="sm">
{data?.heroLine}
</Heading>
</div>
</div>
</Container>
</Section>
)
}
export default Hero

View File

@ -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 (
<Section className={s['section']}>
<Container className={s['container']}>
<div className={s['header']}>
<Heading as="h2" variant="md">
{data?.positionsHeading}
</Heading>
<span>{data?.positionsHeadingNumber}</span>
</div>
<div className={s.careers}>
{cercPositions && (
<div>
<div className={s.heading}>
<Heading as="h3" variant="sm">
{data?.positionsCercHead}
</Heading>
<Arrow className={s.arrow} />
</div>
<ul>
{cercPositions?.map((position) => (
<li key={position?.id}>
<span>{position?.positionName}</span>
<Link href={position?.positionLink}>
{data?.positionsLinkLabel}
</Link>
</li>
))}
</ul>
</div>
)}
{xylmPositions && (
<div>
<div className={s.heading}>
<Heading as="h3" variant="sm">
{data?.positionsXylmHead}
</Heading>
<Arrow className={s.arrow} />
</div>
<ul>
{xylmPositions?.map((position) => (
<li key={position?.id}>
<span>{position?.positionName}</span>
<Link href={position?.positionLink}>
{data?.positionsLinkLabel}
</Link>
</li>
))}
</ul>
</div>
)}
</div>
</Container>
</Section>
)
}
export default Positions

View File

@ -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);
}
}
}
}
}
}

View File

@ -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 (
<Section className={s['section']} id="laconicnetwork">
<Container className={s['container']}>
<div>
<img
className={s.network__img__mobile}
src="/images/products/network-mobile.jpg"
alt="network"
/>
<img
className={s.network__img}
src="/images/products/network.jpg"
alt="network"
/>
<div>
<Heading as="h2" variant="lg">
{data?.valuesHeading}
</Heading>
<div className={s.features}>
<div>
<img src={data?.valuesPoint01Image?.url} alt="detail" />
<div>
<Heading as="h3" variant="sm">
{data?.valuesPoint01Head}
</Heading>
<p>{data?.valuesPoint01Line}</p>
</div>
</div>
<div>
<img src={data?.valuesPoint02Image?.url} alt="detail" />
<div>
<Heading as="h3" variant="sm">
{data?.valuesPoint02Head}
</Heading>
<p>{data?.valuesPoint02Line}</p>
</div>
</div>
<div>
<img src={data?.valuesPoint03Image?.url} alt="detail" />
<div>
<Heading as="h3" variant="sm">
{data?.valuesPoint03Head}
</Heading>
<p>{data?.valuesPoint03Line}</p>
</div>
</div>
<div>
<img src={data?.valuesPoint04Image?.url} alt="detail" />
<div>
<Heading as="h3" variant="sm">
{data?.valuesPoint04Head}
</Heading>
<p>{data?.valuesPoint04Line}</p>
</div>
</div>
</div>
</div>
</div>
</Container>
<div className={s.gradient} />
</Section>
)
}
export default Network

View File

@ -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;
}
}

View File

@ -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 (
<Section className={s['section']}>
<Container className={s['container']}>
<div className={s['header']}>
<Heading as="h2" variant="md">
{data?.whyHeading}
</Heading>
<span>{data?.whyHeadNumber}</span>
</div>
<div className={s.features}>
<div>
<img src={data?.whyPoint01Img?.url} alt="detail" />
<p>{data?.whyPoint01Line}</p>
</div>
<div>
<img src={data?.whyPoint02Img?.url} alt="detail" />
<p>{data?.whyPoint02Line}</p>
</div>
<div>
<img src={data?.whyPoint03Img?.url} alt="detail" />
<p>{data?.whyPoint03Line}</p>
</div>
<div>
<img src={data?.whyPoint04Img?.url} alt="detail" />
<p>{data?.whyPoint04Line}</p>
</div>
<div>
<img src={data?.whyPoint05Img?.url} alt="detail" />
<p>{data?.whyPoint05Line}</p>
</div>
<div>
<img src={data?.whyPoint06Img?.url} alt="detail" />
<p>{data?.whyPoint06Line}</p>
</div>
</div>
</Container>
</Section>
)
}
export default WhyJoin

View File

@ -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);
}
}
}
}
}

View File

@ -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
}

87
src/pages/careers.tsx Normal file
View File

@ -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<typeof getStaticProps>) => {
return (
<PageLayout>
<Meta
preload={[
{ href: '/videos/banner-products.mp4', as: 'fetch' },
{ href: '/videos/banner-products.webm', as: 'fetch' }
]}
/>
<Hero data={heroData} />
<Values data={valuesData} />
<WhyJoin data={whyData} />
<Positions data={positionsSectData} positionsData={positionsData} />
<Related data={initialBlogPosts?.data} />
</PageLayout>
)
}
export default About