384 lines
12 KiB
TypeScript
384 lines
12 KiB
TypeScript
'use client'
|
|
|
|
import Link from '@/framework/link'
|
|
import Image from '@/framework/image'
|
|
import {
|
|
Button,
|
|
Box,
|
|
Container,
|
|
Flex,
|
|
Grid,
|
|
Stack,
|
|
Text,
|
|
Title,
|
|
Group,
|
|
Space,
|
|
} from '@pikku/mantine/core'
|
|
import { IconCheck } from '@tabler/icons-react'
|
|
import { useI18n } from '@/context/i18n-provider'
|
|
import { HomeResultsPreview } from '@/components/home/HomeResultsPreview'
|
|
import React from 'react'
|
|
import { useParams } from '@/framework/navigation'
|
|
import { asI18n, type I18nString } from '@pikku/react'
|
|
|
|
const FeatureCard: React.FunctionComponent<{
|
|
title: I18nString
|
|
description: I18nString
|
|
}> = ({ title, description }) => {
|
|
return (
|
|
<Stack gap={0}>
|
|
<Group align="center" gap="xs" mb={{ base: 0, lg: 'xs' }}>
|
|
<Box
|
|
w={32}
|
|
h={32}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
borderRadius: '50%',
|
|
border: '1px solid'
|
|
}}
|
|
c={{ base: 'white', lg: 'black' }}
|
|
bd={{ base: 'white', lg: 'black' }}
|
|
>
|
|
<IconCheck size={16} />
|
|
</Box>
|
|
<Title
|
|
order={2}
|
|
style={{
|
|
fontSize: 'clamp(1.25rem, 2vw, 2.25rem)',
|
|
lineHeight: 1.2
|
|
}}
|
|
c={{ base: 'white', lg: 'gray.8' }}
|
|
>
|
|
{asI18n(title)}
|
|
</Title>
|
|
</Group>
|
|
<Text
|
|
ml={44}
|
|
ta="left"
|
|
c={{ base: 'white', lg: 'gray.6' }}
|
|
style={{ lineHeight: 1.5 }}
|
|
>
|
|
{asI18n(description)}
|
|
</Text>
|
|
</Stack>
|
|
)
|
|
}
|
|
|
|
const Features: React.FunctionComponent = () => {
|
|
const t = useI18n()
|
|
const features = [
|
|
{ title: t('website.features.fast.title'), description: t('website.features.fast.description') },
|
|
{ title: t('website.features.free.title'), description: t('website.features.free.description') },
|
|
{ title: t('website.features.easy.title'), description: t('website.features.easy.description') },
|
|
]
|
|
|
|
return (
|
|
<Grid gutter={{ base: 'sm', lg: 'lg' }} p={{ base: 'sm', lg: 'lg' }}>
|
|
{features.map((feature) => (
|
|
<Grid.Col key={feature.title} span={{ base: 12, md: 4 }}>
|
|
<FeatureCard
|
|
title={feature.title}
|
|
description={feature.description}
|
|
/>
|
|
</Grid.Col>
|
|
))}
|
|
</Grid>
|
|
)
|
|
}
|
|
|
|
const HeroSection: React.FunctionComponent = () => {
|
|
const t = useI18n()
|
|
const { lang } = useParams<{ lang: string }>()
|
|
const isRtl = t.locale === 'ar'
|
|
|
|
return (
|
|
<Box pos="relative" mih={{ base: '40rem', lg: 0 }}>
|
|
<Container size="xl" h="100%" style={{ position: 'relative', zIndex: 20 }}>
|
|
<Flex
|
|
direction={{ base: 'column', lg: 'row' }}
|
|
justify={{ base: 'center', md: 'normal' }}
|
|
h="100%"
|
|
>
|
|
<Box maw={{ base: '100%', lg: '50%' }}>
|
|
<Box
|
|
py={{ base: 'md', lg: 'xl', xl: '4rem' }}
|
|
ta="start"
|
|
>
|
|
<Title
|
|
order={1}
|
|
c={{ base: 'white', lg: 'gray.9' }}
|
|
mb={{ base: 'sm', lg: 'lg', xl: '3.5rem' }}
|
|
mt={{ base: 'md' }}
|
|
style={{
|
|
fontSize: 'clamp(2rem, 4vw, 3rem)',
|
|
lineHeight: 1.3,
|
|
fontWeight: 400
|
|
}}
|
|
>
|
|
<span style={{ display: 'block' }}>{t('website.hero.title')}</span>
|
|
</Title>
|
|
|
|
<Box mt={{ base: 'md', lg: '2.5rem' }}>
|
|
<Flex
|
|
wrap="wrap"
|
|
align="center"
|
|
justify={{ base: 'flex-start', lg: 'center' }}
|
|
fw={700}
|
|
c={{ base: 'white', lg: 'black' }}
|
|
style={{
|
|
fontSize: 'clamp(2.5rem, 6vw, 3rem)',
|
|
lineHeight: 1.26,
|
|
fontWeight: 700
|
|
}}
|
|
>
|
|
{t('website.hero.checkqualification')}
|
|
</Flex>
|
|
<Flex
|
|
wrap="nowrap"
|
|
align="center"
|
|
justify={{ base: 'flex-start', lg: 'center' }}
|
|
mb={{ base: '2rem', lg: '2.5rem' }}
|
|
mih={{ base: 0, lg: 80 }}
|
|
>
|
|
<Flex align="center" justify={{ base: 'flex-start', lg: 'center' }} mb="xs" pos="relative">
|
|
<Text
|
|
fw={700}
|
|
me="md"
|
|
c={{ base: 'white', lg: 'black' }}
|
|
style={{
|
|
fontSize: 'clamp(2.5rem, 6vw, 3rem)',
|
|
lineHeight: 1.26
|
|
}}
|
|
>
|
|
{t('website.hero.in')}
|
|
</Text>
|
|
<Box pos="relative" display="inline-block">
|
|
<Box
|
|
component="span"
|
|
pos="absolute"
|
|
display="flex"
|
|
style={{
|
|
top: '1.75em',
|
|
left: '-0.25em',
|
|
width: 'calc(100% + 0.5em)',
|
|
justifyContent: 'center',
|
|
zIndex: 5
|
|
}}
|
|
>
|
|
<svg
|
|
width="100%"
|
|
height="0.57em"
|
|
viewBox="0 0 250 10"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
preserveAspectRatio="none"
|
|
>
|
|
<rect y="4" width="250" height="6" rx="2" fill="#ebb305" />
|
|
</svg>
|
|
</Box>
|
|
<Text
|
|
component="span"
|
|
fw={700}
|
|
pos="relative"
|
|
c={{ base: 'white', lg: 'black' }}
|
|
style={{
|
|
fontSize: 'clamp(2.5rem, 6vw, 3rem)',
|
|
lineHeight: 1.26,
|
|
zIndex: 3
|
|
}}
|
|
>
|
|
{t('website.hero.months')}
|
|
</Text>
|
|
</Box>
|
|
</Flex>
|
|
<Space w={{ base: '1rem', lg: '1.75rem' }} />
|
|
<Flex align="center" justify={{ base: 'flex-start', lg: 'center' }} style={{ position: 'relative', top: -2, whiteSpace: 'nowrap' }}>
|
|
<Box component="span">
|
|
<svg
|
|
width="42"
|
|
height="37"
|
|
viewBox="0 0 42 37"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
style={{ width: 'clamp(28px, 4vw, 42px)', height: 'auto' }}
|
|
>
|
|
<path d="M25.772 8.644C26.19 8.19 26.159 7.485 25.702 7.069L18.252 0.293C17.794 -0.123 17.084 -0.092 16.666 0.362C16.247 0.816 16.278 1.522 16.736 1.937L23.358 7.961L17.295 14.54C16.876 14.995 16.908 15.7 17.365 16.116C17.822 16.532 18.532 16.5 18.951 16.046Z M2.795 34.253C1.714 29.036 2.066 22.916 5.271 18.019C8.441 13.175 14.554 9.301 25.49 8.822L25.391 6.594C13.93 7.096 7.052 11.208 3.389 16.803C-0.238 22.346 -0.56 29.12 0.597 34.703Z" fill="#ebb305" transform="translate(7.348 4.299) rotate(33 13 17.25)" />
|
|
</svg>
|
|
</Box>
|
|
<Text
|
|
fw={700}
|
|
ml="xs"
|
|
c="#ebb305"
|
|
style={{
|
|
fontSize: 'clamp(2.5rem, 6vw, 3rem)',
|
|
lineHeight: 1.26,
|
|
letterSpacing: '-0.01em'
|
|
}}
|
|
>
|
|
{t('website.hero.days')}
|
|
</Text>
|
|
</Flex>
|
|
</Flex>
|
|
</Box>
|
|
|
|
<Text
|
|
mb='sm'
|
|
c={{ base: 'rgba(255, 255, 255, 0.9)', lg: 'gray.7' }}
|
|
style={{
|
|
fontSize: 'clamp(1rem, 1.5vw, 1.125rem)',
|
|
lineHeight: 1.5,
|
|
maxWidth: '100%'
|
|
}}
|
|
>
|
|
{t('website.hero.subtitle')}
|
|
</Text>
|
|
<Text
|
|
mb="lg"
|
|
c={{ base: 'rgba(255, 255, 255, 0.9)', lg: 'gray.7' }}
|
|
style={{
|
|
fontSize: 'clamp(1rem, 1.5vw, 1.125rem)',
|
|
lineHeight: 1.5,
|
|
maxWidth: '100%'
|
|
}}
|
|
>
|
|
{t('website.hero.description')}
|
|
</Text>
|
|
<Features />
|
|
<Flex align="center" justify="center" gap="md">
|
|
<Link href={`/${lang}/jobs/apply`}>
|
|
<Button type="button" m="md" mb="2.5rem">
|
|
{t('website.hero.cta')}
|
|
</Button>
|
|
</Link>
|
|
</Flex>
|
|
</Box>
|
|
</Box>
|
|
</Flex>
|
|
</Container>
|
|
|
|
<Box
|
|
pos="absolute"
|
|
top={0}
|
|
right={0}
|
|
bottom={0}
|
|
hiddenFrom="base"
|
|
visibleFrom="lg"
|
|
style={{
|
|
width: '50%',
|
|
zIndex: 10
|
|
}}
|
|
>
|
|
<Image
|
|
src="/home_nurse.webp"
|
|
alt="Nurse reviewing qualifications for a healthcare role in Germany"
|
|
placeholder="blur"
|
|
priority
|
|
sizes="(max-width: 62em) 0vw, 50vw"
|
|
style={{
|
|
height: '100%',
|
|
width: '100%',
|
|
objectFit: 'cover',
|
|
clipPath: isRtl ? 'none' : 'polygon(12% 0, 100% 0%, 100% 100%, 0 100%)',
|
|
transform: isRtl ? 'scaleX(-1)' : 'none'
|
|
}}
|
|
/>
|
|
</Box>
|
|
|
|
<Box
|
|
pos="absolute"
|
|
inset={0}
|
|
hiddenFrom="lg"
|
|
style={{ zIndex: 1 }}
|
|
>
|
|
<Box
|
|
pos="absolute"
|
|
inset={0}
|
|
bg="rgba(0, 0, 0, 0.85)"
|
|
style={{ zIndex: 10 }}
|
|
/>
|
|
<Image
|
|
src="/home_nurse.webp"
|
|
alt=""
|
|
aria-hidden="true"
|
|
placeholder="blur"
|
|
sizes="100vw"
|
|
style={{
|
|
height: '100%',
|
|
width: '100%',
|
|
objectFit: 'cover'
|
|
}}
|
|
/>
|
|
</Box>
|
|
</Box>
|
|
)
|
|
}
|
|
|
|
const CallToActionSection: React.FunctionComponent = () => {
|
|
const t = useI18n()
|
|
const { lang } = useParams<{ lang: string }>()
|
|
return (
|
|
<Box component="section">
|
|
<Container size="xl" w="100%" py="5rem">
|
|
<Stack align="center">
|
|
<Title
|
|
order={2}
|
|
fw={700}
|
|
mb="md"
|
|
ta="center"
|
|
style={{
|
|
fontSize: 'clamp(1.5rem, 3vw, 1.875rem)',
|
|
lineHeight: 1.2
|
|
}}
|
|
>
|
|
{t('website.cta.title')}
|
|
</Title>
|
|
<Container size="sm" px={0}>
|
|
<Text
|
|
mb="md"
|
|
ta="left"
|
|
style={{
|
|
fontSize: 'clamp(0.875rem, 1.5vw, 1rem)',
|
|
lineHeight: 1.5
|
|
}}
|
|
>
|
|
{t('website.cta.description')}
|
|
</Text>
|
|
</Container>
|
|
<Flex align="center" justify="center">
|
|
<Stack pt="md" align="center">
|
|
<Link href={`/${lang}/jobs/apply`}>
|
|
<Button>{t('website.cta.button')}</Button>
|
|
</Link>
|
|
<Text
|
|
ta="center"
|
|
c="dimmed"
|
|
mt="xs"
|
|
style={{
|
|
fontSize: 'clamp(0.75rem, 1.2vw, 0.875rem)',
|
|
lineHeight: 1.4
|
|
}}
|
|
>
|
|
{t('website.cta.disclaimer')}
|
|
</Text>
|
|
</Stack>
|
|
</Flex>
|
|
<Box mt="2.5rem" mb="4rem" w="100%">
|
|
<HomeResultsPreview />
|
|
</Box>
|
|
</Stack>
|
|
</Container>
|
|
</Box>
|
|
)
|
|
}
|
|
|
|
export function HomePage() {
|
|
return (
|
|
<>
|
|
<HeroSection />
|
|
<CallToActionSection />
|
|
</>
|
|
)
|
|
}
|