feat: static site
* feat: mui support & basic theming * feat: entgamers favicon * feat: public images until dynamic content can be used * feat: entgamers & gaming assets * feat: eslint extra rules * feat: mui theme modifications * feat: fontawesome, gsap, bundle analyzer * feat: common interfaces * feat: basic layout * chore: upadted dependencies * chore: updated dependencies * feat: updated link styles * feat: layout now have better interfaces * feat: basic seo component * feat: static website * feat: env variable rules in .gitignore * feat: added lint to pre-commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faChevronRight } from '@fortawesome/free-solid-svg-icons/faChevronRight'
|
||||
import { Box, NoSsr, Typography } from '@mui/material'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { FC } from 'react'
|
||||
|
||||
import { PositionJoinTeamProps } from '@interfaces'
|
||||
|
||||
const UnirseForm = dynamic(() => import('@components/pages/equipo/unirse/UnirseForm'), {
|
||||
ssr: false,
|
||||
suspense: false
|
||||
})
|
||||
|
||||
const PositionJoinTeam:FC<PositionJoinTeamProps> = (
|
||||
{ benefits, description, requirements, title }
|
||||
) => {
|
||||
return (
|
||||
<Box>
|
||||
<Box
|
||||
sx={{
|
||||
marginBlock: '1rem'
|
||||
}}
|
||||
>
|
||||
<Typography variant="h2" align="center" gutterBottom>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="body1" align="center" gutterBottom>
|
||||
{description}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={theme => ({
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '1fr',
|
||||
gap: 2,
|
||||
[theme.breakpoints.up('md')]: {
|
||||
gridTemplateColumns: '1fr 1fr'
|
||||
}
|
||||
})}
|
||||
>
|
||||
<Box>
|
||||
<Typography variant="h3" align="center" gutterBottom>
|
||||
Rellenar formulario
|
||||
</Typography>
|
||||
<NoSsr>
|
||||
<UnirseForm
|
||||
role={title}
|
||||
/>
|
||||
</NoSsr>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography variant="h3" gutterBottom>
|
||||
Requisitos
|
||||
</Typography>
|
||||
<ul className="fa-ul">
|
||||
{requirements.map(({ title, description }, index) => (
|
||||
<li key={index}>
|
||||
<FontAwesomeIcon icon={faChevronRight} className="fa-li" />
|
||||
<Typography variant="body1" gutterBottom>
|
||||
<strong>{title}</strong>
|
||||
</Typography>
|
||||
<Typography variant="body1" gutterBottom>
|
||||
{description}
|
||||
</Typography>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Typography variant="h3" gutterBottom>
|
||||
Beneficios
|
||||
</Typography>
|
||||
<ul className="fa-ul">
|
||||
{benefits.map(({ title, description }, index) => (
|
||||
<li key={index}>
|
||||
<FontAwesomeIcon icon={faChevronRight} className="fa-li" />
|
||||
<Typography variant="body1" gutterBottom>
|
||||
<strong>{title}</strong>
|
||||
</Typography>
|
||||
<Typography variant="body1" gutterBottom>
|
||||
{description}
|
||||
</Typography>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
export default PositionJoinTeam
|
||||
@@ -0,0 +1,133 @@
|
||||
import { useFormik } from 'formik'
|
||||
import { Box, Button, TextField, Typography } from '@mui/material'
|
||||
import { FC, useState } from 'react'
|
||||
import { object, string } from 'yup'
|
||||
|
||||
import { UnirseFormData, UnirseFormProps } from '@interfaces'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const unirseFormSchema = object({
|
||||
name: string().required('El nombre es requerido'),
|
||||
email: string().email('El email no es válido').required('El email es requerido'),
|
||||
role: string().required('El rol es requerido'),
|
||||
discordUserName: string().matches(/^.{3,32}#[0-9]{4}$/, 'El formato correcto es userName#0000').required('El nombre de usuario de Discord es requerido'),
|
||||
experience: string().required('La experiencia es requerida')
|
||||
})
|
||||
|
||||
const UnirseForm: FC<UnirseFormProps> = ({ role }) => {
|
||||
const [isSended, setIsSended] = useState(false)
|
||||
const formik = useFormik<UnirseFormData>({
|
||||
initialValues: {
|
||||
name: '',
|
||||
email: '',
|
||||
role: role || '',
|
||||
discordUserName: '',
|
||||
experience: ''
|
||||
},
|
||||
onSubmit: async (values) => {
|
||||
try {
|
||||
const response = await fetch('/api/equipo/unirse/send-form', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(values)
|
||||
})
|
||||
if (response.ok) {
|
||||
setIsSended(true)
|
||||
formik.resetForm()
|
||||
} else {
|
||||
console.error('Error sending form')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
},
|
||||
validationSchema: unirseFormSchema
|
||||
})
|
||||
return isSended
|
||||
? (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'column',
|
||||
marginBlock: 1
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1" align="center" color={(theme) => theme.palette.success.main} gutterBottom>
|
||||
¡Gracias por tu interés! Te contactaremos lo antes posible.
|
||||
</Typography>
|
||||
</Box>
|
||||
)
|
||||
: (
|
||||
<Box
|
||||
component="form"
|
||||
onSubmit={formik.handleSubmit}
|
||||
>
|
||||
<TextField
|
||||
name="name"
|
||||
label="Nombre"
|
||||
placeholder="Escribe tu nombre"
|
||||
value={formik.values.name}
|
||||
onChange={formik.handleChange}
|
||||
error={formik.touched.name && !!formik.errors.name}
|
||||
helperText={formik.touched.name && formik.errors.name}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
/>
|
||||
<TextField
|
||||
name="email"
|
||||
label="Correo electrónico"
|
||||
placeholder="Usaremos este correo para contactarte"
|
||||
value={formik.values.email}
|
||||
onChange={formik.handleChange}
|
||||
error={formik.touched.email && !!formik.errors.email}
|
||||
helperText={formik.touched.email && formik.errors.email}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
/>
|
||||
<TextField
|
||||
name="discordUserName"
|
||||
label="Nombre de usuario de Discord"
|
||||
placeholder="userName#0000"
|
||||
value={formik.values.discordUserName}
|
||||
onChange={formik.handleChange}
|
||||
error={formik.touched.discordUserName && !!formik.errors.discordUserName}
|
||||
helperText={formik.touched.discordUserName && formik.errors.discordUserName}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
/>
|
||||
<TextField
|
||||
name="experience"
|
||||
label="Experiencia"
|
||||
placeholder="¿Tienes experiencia en el área? ¿Qué conocimientos tienes?"
|
||||
value={formik.values.experience}
|
||||
onChange={formik.handleChange}
|
||||
error={formik.touched.experience && !!formik.errors.experience}
|
||||
helperText={formik.touched.experience && formik.errors.experience}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
multiline
|
||||
rows={4}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
marginBlock: 1
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
type="submit"
|
||||
endIcon={formik.isSubmitting ? <FontAwesomeIcon icon={faSpinner} spin /> : undefined}
|
||||
>
|
||||
Enviar
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
export default UnirseForm
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Box, Button, Container, Paper, Typography } from '@mui/material'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { FC } from 'react'
|
||||
|
||||
import ClanesImage from '@assets/images/Clanes.png'
|
||||
|
||||
export interface ClanesProps {
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
|
||||
const Clanes: FC<ClanesProps> = ({ description, title }) => {
|
||||
return (
|
||||
<div
|
||||
id="clanes"
|
||||
css={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url("/images/backgrounds/bricks.png")'
|
||||
}}
|
||||
>
|
||||
<Paper
|
||||
variant='glass'
|
||||
component={Container}
|
||||
>
|
||||
<Typography
|
||||
variant="h2"
|
||||
align="center"
|
||||
gutterBottom
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
<Box
|
||||
sx={(theme) => ({
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '1fr',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
gridTemplateColumns: '1fr 1fr'
|
||||
}
|
||||
})}
|
||||
>
|
||||
<div>
|
||||
<Image src={ClanesImage} alt="EntGamers" width={600} height={315} />
|
||||
</div>
|
||||
<div
|
||||
css={{
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1" gutterBottom >
|
||||
{description}
|
||||
</Typography>
|
||||
<Button variant="contained" color="primary" LinkComponent={Link} component="a" href="/clanes">
|
||||
Ver clanes
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Clanes
|
||||
@@ -0,0 +1,181 @@
|
||||
import { Container, IconButton, Typography } from '@mui/material'
|
||||
import { faArrowDown } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import gsap, { Elastic, Linear } from 'gsap'
|
||||
import ScrollTrigger from 'gsap/dist/ScrollTrigger'
|
||||
import ScrollToPlugin from 'gsap/dist/ScrollToPlugin'
|
||||
import Image from 'next/image'
|
||||
import { FC, useEffect, useRef } from 'react'
|
||||
|
||||
import EntGamers from '@assets/images/EntGamers.png'
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger, ScrollToPlugin)
|
||||
|
||||
export interface HeroProps {
|
||||
title: string
|
||||
subtitle: string
|
||||
}
|
||||
|
||||
const Hero: FC<HeroProps> = ({ subtitle, title }) => {
|
||||
const layer01 = useRef<HTMLDivElement| null>(null)
|
||||
const layer02 = useRef<HTMLDivElement| null>(null)
|
||||
const layer03 = useRef<HTMLDivElement| null>(null)
|
||||
const layer04 = useRef<HTMLDivElement| null>(null)
|
||||
const layer05 = useRef<HTMLDivElement| null>(null)
|
||||
const layer06 = useRef<HTMLDivElement| null>(null)
|
||||
const verMasButton = useRef<HTMLButtonElement| null>(null)
|
||||
useEffect(() => {
|
||||
const scrollTrigger = {
|
||||
trigger: layer01.current,
|
||||
start: 'top bottom',
|
||||
end: 'bottom top',
|
||||
toggleActions: 'play pause resume pause'
|
||||
}
|
||||
const timeLine = gsap.timeline({ duration: 1, repeat: -1, repeatDelay: 4, scrollTrigger })
|
||||
const layer01Animation = gsap.to(layer01.current, { duration: 175, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
const layer02Animation = gsap.to(layer02.current, { duration: 150, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
const layer03Animation = gsap.to(layer03.current, { duration: 125, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
const layer04Animation = gsap.to(layer04.current, { duration: 100, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
const layer05Animation = gsap.to(layer05.current, { duration: 75, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
const layer06Animation = gsap.to(layer06.current, { duration: 50, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
timeLine
|
||||
.to(verMasButton.current, { y: '+=15', duration: 0.5 })
|
||||
.to(verMasButton.current, { y: '-=15', ease: Elastic.easeOut.config(2, 0.1), duration: 3 })
|
||||
return () => {
|
||||
layer01Animation.kill()
|
||||
layer02Animation.kill()
|
||||
layer03Animation.kill()
|
||||
layer04Animation.kill()
|
||||
layer05Animation.kill()
|
||||
layer06Animation.kill()
|
||||
timeLine.kill()
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={layer01}
|
||||
css={{
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/MysteriousForestNightLayer01.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'top',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={layer02}
|
||||
css={{
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/MysteriousForestNightLayer02.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'bottom',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={layer03}
|
||||
css={{
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/MysteriousForestNightLayer03.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'bottom',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={layer04}
|
||||
css={{
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/MysteriousForestNightLayer04.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'bottom',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={layer05}
|
||||
css={{
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/MysteriousForestNightLayer05.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'bottom',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={layer06}
|
||||
css={{
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/MysteriousForestNightLayer06.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'bottom',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<Container
|
||||
fixed
|
||||
sx={(theme) => ({
|
||||
display: 'grid',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
gridTemplateColumns: '1fr',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
gridTemplateColumns: '1fr 1fr'
|
||||
}
|
||||
})}
|
||||
>
|
||||
<div>
|
||||
<Image src={EntGamers} alt="EntGamers" width={600} height={600} loading="eager" />
|
||||
</div>
|
||||
<div>
|
||||
<Typography variant="h1" gutterBottom align="center">
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="h2" gutterBottom align="center">
|
||||
{subtitle}
|
||||
</Typography>
|
||||
</div>
|
||||
</Container>
|
||||
<IconButton
|
||||
ref={verMasButton}
|
||||
sx={(theme) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
position: 'absolute',
|
||||
bottom: '2rem',
|
||||
right: '1rem',
|
||||
aspectRatio: '1',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
bottom: '1rem',
|
||||
right: 'calc(50% - 1rem)'
|
||||
}
|
||||
})}
|
||||
onClick={() => {
|
||||
gsap.to(window, { duration: 0.3, scrollTo: '#clanes' })
|
||||
}}
|
||||
color='primary'
|
||||
>
|
||||
<FontAwesomeIcon icon={faArrowDown} fixedWidth />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Hero
|
||||
@@ -0,0 +1,101 @@
|
||||
import gsap, { Linear } from 'gsap'
|
||||
import ScrollTrigger from 'gsap/dist/ScrollTrigger'
|
||||
import ScrollToPlugin from 'gsap/dist/ScrollToPlugin'
|
||||
import { Container, Paper } from '@mui/material'
|
||||
import { FC, useEffect, useRef } from 'react'
|
||||
|
||||
import SocialSlider, { SocialSliderProps } from '@components/pages/home/socialNetworks/SocialSlider'
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger, ScrollToPlugin)
|
||||
|
||||
export interface SocialNetworksProps {
|
||||
socialNetworks: SocialSliderProps['slides']
|
||||
}
|
||||
|
||||
const SocialNetworks: FC<SocialNetworksProps> = ({ socialNetworks }) => {
|
||||
const layer01 = useRef<HTMLDivElement| null>(null)
|
||||
const layer02 = useRef<HTMLDivElement| null>(null)
|
||||
const layer03 = useRef<HTMLDivElement| null>(null)
|
||||
const layer04 = useRef<HTMLDivElement| null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const scrollTrigger = {
|
||||
trigger: layer01.current,
|
||||
start: 'top bottom',
|
||||
end: 'bottom top',
|
||||
toggleActions: 'play pause resume pause'
|
||||
}
|
||||
const layer02Animation = gsap.to(layer02.current, { duration: 150, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
const layer03Animation = gsap.to(layer03.current, { duration: 60, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
const layer04Animation = gsap.to(layer04.current, { duration: 125, backgroundPositionX: '2048px', repeat: -1, ease: Linear.easeNone, scrollTrigger })
|
||||
|
||||
return () => {
|
||||
layer02Animation.kill()
|
||||
layer03Animation.kill()
|
||||
layer04Animation.kill()
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={layer01}
|
||||
css={{
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/SkyNightLayer01.png)',
|
||||
backgroundPositionX: 'center',
|
||||
backgroundPositionY: 'center',
|
||||
backgroundSize: 'auto'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={layer02}
|
||||
css={{
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/SkyNightLayer02.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'center',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={layer03}
|
||||
css={{
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/SkyNightLayer03.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'center',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={layer04}
|
||||
css={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/SkyNightLayer04.png)',
|
||||
backgroundPositionX: '0',
|
||||
backgroundPositionY: 'center',
|
||||
backgroundSize: 'auto',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<Paper
|
||||
component={Container}
|
||||
variant='glass'
|
||||
>
|
||||
<SocialSlider
|
||||
slides={socialNetworks}
|
||||
/>
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SocialNetworks
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Container, Button, Typography } from '@mui/material'
|
||||
import NextLink from 'next/link'
|
||||
import { FC } from 'react'
|
||||
|
||||
import ProfileCard, { ProfileCardProps } from '@components/profiles/ProfileCard'
|
||||
|
||||
export interface TeamProps {
|
||||
title: string
|
||||
teamMembers: ProfileCardProps[]
|
||||
viewTeamButtonText: string
|
||||
joinTeamButtonText: string
|
||||
}
|
||||
|
||||
const Team: FC<TeamProps> = ({ title, teamMembers, joinTeamButtonText, viewTeamButtonText }) => {
|
||||
return (
|
||||
<div
|
||||
css={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minHeight: '100vh',
|
||||
backgroundImage: 'url(/images/backgrounds/MysteriousForest.jpg)',
|
||||
backgroundPositionX: 'bottom',
|
||||
backgroundPositionY: 'center',
|
||||
backgroundSize: 'cover',
|
||||
backgroundRepeat: 'repeat-x'
|
||||
}}
|
||||
>
|
||||
<Container>
|
||||
<Typography variant='h2' align="center" gutterBottom>{title}</Typography>
|
||||
<div
|
||||
css={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
||||
gridGap: '1rem',
|
||||
justifyContent: 'center',
|
||||
justifyItems: 'center',
|
||||
marginBlock: 2
|
||||
}}
|
||||
>
|
||||
{teamMembers.map(({ avatar, biography, socialNetworks, userName, role }) => (
|
||||
<ProfileCard
|
||||
key={`profile-card-${userName}` }
|
||||
avatar={avatar}
|
||||
biography={biography}
|
||||
socialNetworks={socialNetworks}
|
||||
userName={userName}
|
||||
role={role}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div
|
||||
css={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-around',
|
||||
alignItems: 'center',
|
||||
marginBlock: '16px'
|
||||
}}
|
||||
>
|
||||
<NextLink href="/equipo" passHref>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="info"
|
||||
component="a"
|
||||
>
|
||||
{viewTeamButtonText}
|
||||
</Button>
|
||||
</NextLink>
|
||||
<NextLink href="/equipo/unirse" passHref>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="success"
|
||||
component="a"
|
||||
>
|
||||
{joinTeamButtonText}
|
||||
</Button>
|
||||
</NextLink>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Team
|
||||
@@ -0,0 +1,95 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faFacebook, faInstagram, faTwitch, faTwitter, faYoutube } from '@fortawesome/free-brands-svg-icons'
|
||||
import { Button, Typography } from '@mui/material'
|
||||
import { Navigation, Pagination, A11y } from 'swiper'
|
||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||
|
||||
import 'swiper/css'
|
||||
import 'swiper/css/navigation'
|
||||
import 'swiper/css/pagination'
|
||||
import { FC } from 'react'
|
||||
import { Button as ButtonType } from '@interfaces'
|
||||
|
||||
export interface SlideProps {
|
||||
socialNetwork: 'facebook' | 'twitter' | 'instagram' | 'youtube' | 'twitch'
|
||||
description: string
|
||||
links: ButtonType[]
|
||||
}
|
||||
|
||||
const Slide:FC<SlideProps> = ({ description, socialNetwork, links }) => {
|
||||
return (
|
||||
<div
|
||||
css={{
|
||||
marginInline: '36px',
|
||||
marginBlock: '16px',
|
||||
padding: '16px'
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1" component="div" align="center" >
|
||||
{{
|
||||
facebook: <FontAwesomeIcon style={{ filter: 'drop-shadow(2px 2px 2px rgb(0 0 0 / 0.4)' }}icon={faFacebook} size="5x" fixedWidth />,
|
||||
twitter: <FontAwesomeIcon style={{ filter: 'drop-shadow(2px 2px 2px rgb(0 0 0 / 0.4)' }}icon={faTwitter} size="5x" fixedWidth />,
|
||||
instagram: <FontAwesomeIcon style={{ filter: 'drop-shadow(2px 2px 2px rgb(0 0 0 / 0.4)' }}icon={faInstagram} size="5x" fixedWidth />,
|
||||
youtube: <FontAwesomeIcon style={{ filter: 'drop-shadow(2px 2px 2px rgb(0 0 0 / 0.4)' }}icon={faYoutube} size="5x" fixedWidth />,
|
||||
twitch: <FontAwesomeIcon style={{ filter: 'drop-shadow(2px 2px 2px rgb(0 0 0 / 0.4)' }}icon={faTwitch} size="5x" fixedWidth />
|
||||
}[socialNetwork]}
|
||||
</Typography>
|
||||
<Typography sx={(theme) => ({ textShadow: `2px 2px 2px ${theme.palette.background.default}` })} variant="body1" align="center" >
|
||||
{description}
|
||||
</Typography>
|
||||
<div
|
||||
css={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-around',
|
||||
alignItems: 'center',
|
||||
marginBlock: '1rem'
|
||||
}}
|
||||
>
|
||||
{links.map(({ url, label, color, variant }) => (
|
||||
<Button
|
||||
key={url}
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
variant={variant}
|
||||
color={color}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export interface SocialSliderProps {
|
||||
slides: SlideProps[]
|
||||
}
|
||||
|
||||
const SocialSlider: FC<SocialSliderProps> = ({ slides }) => {
|
||||
return (
|
||||
<Swiper
|
||||
modules={[Navigation, Pagination, A11y]}
|
||||
spaceBetween={16}
|
||||
slidesPerView={1}
|
||||
navigation
|
||||
pagination={{ clickable: true }}
|
||||
scrollbar={{ draggable: true }}
|
||||
>
|
||||
{slides.map(({ socialNetwork, description, links }) => (
|
||||
|
||||
<SwiperSlide
|
||||
key={socialNetwork}
|
||||
>
|
||||
<Slide
|
||||
socialNetwork={socialNetwork}
|
||||
description={description}
|
||||
links={links}
|
||||
/>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
)
|
||||
}
|
||||
|
||||
export default SocialSlider
|
||||
Reference in New Issue
Block a user