2024-02-15 11:45:46 -08:00
|
|
|
'use client'
|
2024-02-12 20:50:00 -08:00
|
|
|
import Link from 'next/link'
|
2024-02-15 11:45:46 -08:00
|
|
|
import { Fragment, useState } from 'react'
|
2024-02-12 20:50:00 -08:00
|
|
|
import { affiliations, nationalities, authors } from '../../db/data'
|
|
|
|
import { Zilla_Slab } from 'next/font/google'
|
2024-02-12 21:21:55 -08:00
|
|
|
import { notFound } from 'next/navigation'
|
2024-02-14 10:56:05 -08:00
|
|
|
import DocumentCard from '@/app/components/DocumentCard'
|
|
|
|
import findDocumentsByAuthor from './findDocumentsByAuthor'
|
2024-02-14 16:32:36 -08:00
|
|
|
import cardEffects from '@/app/styles/cardEffects.module.css'
|
2024-02-15 11:45:46 -08:00
|
|
|
import Konami from 'react-konami-code'
|
|
|
|
import Snowfall from 'react-snowfall'
|
2024-02-12 20:50:00 -08:00
|
|
|
|
|
|
|
const zillaSlab = Zilla_Slab({ subsets: ['latin'], weight: ['500'] })
|
|
|
|
|
|
|
|
export default function AuthorDisplay({
|
|
|
|
author,
|
|
|
|
}: Readonly<{ author: string }>) {
|
|
|
|
const data = authors[author]
|
2024-02-12 21:21:55 -08:00
|
|
|
if (!data) {
|
|
|
|
notFound()
|
|
|
|
}
|
|
|
|
|
2024-02-15 11:45:46 -08:00
|
|
|
const [snowfallActivated, setSnowfallActivated] = useState<boolean>(false)
|
2024-02-12 20:50:00 -08:00
|
|
|
const { name, affiliation, image, nationality, formerAffiliations } = data
|
|
|
|
|
2024-02-14 10:56:05 -08:00
|
|
|
const authorsDocuments = findDocumentsByAuthor(author)
|
2024-02-15 11:45:46 -08:00
|
|
|
const handleKonami = () => {
|
|
|
|
setSnowfallActivated(!snowfallActivated)
|
|
|
|
}
|
2024-02-14 10:56:05 -08:00
|
|
|
|
2024-02-12 20:50:00 -08:00
|
|
|
const MainPosition = () => {
|
|
|
|
const mainAffiliationShort = affiliation[0].split('@')[1]
|
|
|
|
const mainPosition = affiliation[0].split('@')[0]
|
|
|
|
const mainAffiliation = affiliations[mainAffiliationShort]
|
|
|
|
const { website } = data
|
2024-02-15 11:45:46 -08:00
|
|
|
|
|
|
|
const images: HTMLImageElement[] = []
|
2024-02-15 11:46:20 -08:00
|
|
|
nationality.forEach((n) => {
|
2024-02-15 11:45:46 -08:00
|
|
|
const { flag } = nationalities[n]
|
|
|
|
const image = new Image()
|
|
|
|
image.src = flag
|
|
|
|
images.push(image)
|
|
|
|
})
|
|
|
|
|
2024-02-12 20:50:00 -08:00
|
|
|
return (
|
|
|
|
<>
|
2024-02-15 11:45:46 -08:00
|
|
|
<Konami action={handleKonami} />
|
2024-02-15 11:46:20 -08:00
|
|
|
{snowfallActivated && (
|
2024-02-15 11:45:46 -08:00
|
|
|
<Snowfall
|
|
|
|
snowflakeCount={500}
|
2024-02-15 11:46:20 -08:00
|
|
|
color='white'
|
2024-02-15 11:45:46 -08:00
|
|
|
images={images}
|
|
|
|
radius={[20, 60]}
|
|
|
|
style={{
|
|
|
|
position: 'absolute',
|
|
|
|
top: 0,
|
|
|
|
left: 0,
|
|
|
|
zIndex: -1,
|
|
|
|
pointerEvents: 'none',
|
|
|
|
height: `${document.documentElement.scrollHeight}px`,
|
|
|
|
}}
|
|
|
|
/>
|
2024-02-15 11:46:20 -08:00
|
|
|
)}
|
2024-02-12 20:50:00 -08:00
|
|
|
<span>{mainPosition} at </span>
|
|
|
|
<Link href={`/affiliation/${mainAffiliationShort}`}>
|
|
|
|
{mainAffiliation.name}
|
|
|
|
</Link>
|
|
|
|
{website ? (
|
|
|
|
<div className='mt-2'>
|
|
|
|
Visit {name.nickname ? name.nickname : name.first} at:{' '}
|
|
|
|
<a href={website} target='_blank'>
|
|
|
|
{website}
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
) : null}
|
2024-02-15 11:45:46 -08:00
|
|
|
<div className='my-4 max-h-16 flex flex-wrap gap-2'>
|
2024-02-12 20:50:00 -08:00
|
|
|
{affiliation.map((a: string) => (
|
2024-02-14 16:32:36 -08:00
|
|
|
<Link
|
|
|
|
key={a}
|
|
|
|
href={`/affiliation/${a.split('@')[1]}`}
|
2024-02-15 11:45:46 -08:00
|
|
|
className={`${cardEffects['card-small']} rounded-md`}
|
2024-02-14 16:32:36 -08:00
|
|
|
>
|
2024-02-12 20:50:00 -08:00
|
|
|
<img
|
|
|
|
src={affiliations[a.split('@')[1]].image}
|
|
|
|
alt={affiliations[a.split('@')[1]].name}
|
2024-02-15 11:45:46 -08:00
|
|
|
className='h-16 rounded-md p-2'
|
2024-02-12 20:50:00 -08:00
|
|
|
/>
|
|
|
|
</Link>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const OtherPositions = () => {
|
|
|
|
if (affiliation.length === 1) return
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h1 className='text-3xl md:mt-6 mt-4 mb-2 font-serif'>
|
2024-02-14 10:56:05 -08:00
|
|
|
Other Positions
|
2024-02-12 20:50:00 -08:00
|
|
|
</h1>
|
|
|
|
{affiliation.slice(1).map((a: string, i: number) => {
|
|
|
|
const position = a.split('@')[0]
|
|
|
|
const affiliation = affiliations[a.split('@')[1]].name
|
|
|
|
return (
|
|
|
|
<Fragment key={`${position}@${affiliation}`}>
|
|
|
|
<span className='text-slate-500 text-lg'>
|
|
|
|
{position} at{' '}
|
|
|
|
<Link href={`/affiliation/${a.split('@')[1]}`}>
|
|
|
|
{affiliation}
|
|
|
|
</Link>
|
|
|
|
</span>
|
|
|
|
</Fragment>
|
|
|
|
)
|
|
|
|
})}
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const FormerPositions = () => {
|
|
|
|
if (!formerAffiliations) return null
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h1 className='text-3xl md:mt-6 mt-4 mb-2 font-serif'>
|
2024-02-14 10:56:05 -08:00
|
|
|
Former Positions
|
2024-02-12 20:50:00 -08:00
|
|
|
</h1>
|
|
|
|
{formerAffiliations?.map((a: string, i: number) => {
|
|
|
|
const position = a.split('@')[0]
|
|
|
|
const affiliation = affiliations[a.split('@')[1]].name
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Fragment key={`${position}@${affiliation}`}>
|
|
|
|
<span className='text-slate-500 text-lg'>
|
|
|
|
{position} at{' '}
|
|
|
|
<Link href={`/affiliation/${a.split('@')[1]}`}>
|
|
|
|
{affiliation}
|
|
|
|
</Link>
|
|
|
|
</span>
|
|
|
|
</Fragment>
|
|
|
|
)
|
|
|
|
})}
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const NationalityDisplay = ({
|
|
|
|
nationality,
|
|
|
|
}: Readonly<{ nationality: string }>) => {
|
|
|
|
const nationalityData = nationalities[nationality]
|
|
|
|
const { demonym, flag } = nationalityData
|
|
|
|
return (
|
|
|
|
<div className='flex items-center'>
|
|
|
|
<img
|
|
|
|
src={flag}
|
2024-02-14 00:38:45 -08:00
|
|
|
className='w-10 shadow-md shadow-slate-300'
|
2024-02-12 20:50:00 -08:00
|
|
|
alt={`${demonym} flag`}
|
|
|
|
/>
|
|
|
|
<span className='mx-3 font-semibold'>{demonym}</span>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const Bio = () => {
|
|
|
|
const { bio } = data
|
|
|
|
if (!bio) return null
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
2024-02-15 11:45:46 -08:00
|
|
|
<h1 className='text-3xl md:mt-6 mt-4 mb-2 font-serif'>Bio</h1>
|
|
|
|
<p className='mb-2'>{bio}</p>
|
2024-02-12 20:50:00 -08:00
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<div className='grid grid-cols-1 md:grid-cols-2 items-center max-w-3xl mx-auto'>
|
|
|
|
<div className='aspect-square w-[60vw] md:w-[30vw] lg:w-[20vw] 2xl:w-[15vw] overflow-hidden mx-auto mb-4'>
|
|
|
|
<img
|
|
|
|
alt='profile'
|
|
|
|
className='rounded-full mx-auto object-cover w-full h-full border-slate-800 border-4'
|
|
|
|
src={image}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<span
|
|
|
|
className={`${zillaSlab.className} font-bold text-5xl text-center md:text-left`}
|
|
|
|
>
|
|
|
|
{name.first}
|
|
|
|
{name.nickname ? ` "${name.nickname}"` : null} {name.last}
|
|
|
|
</span>
|
|
|
|
<div className='text-slate-600 text-md sm:text-lg mt-4'>
|
|
|
|
<MainPosition />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='max-w-3xl mx-auto grid grid-cols-1 justify-center'>
|
|
|
|
<hr className='mx-auto w-full h-1 border-0 bg-slate-200 my-2 rounded-md' />
|
|
|
|
<OtherPositions />
|
|
|
|
<FormerPositions />
|
|
|
|
<h1 className='text-3xl md:my-6 my-4 font-serif'>
|
2024-02-14 10:56:05 -08:00
|
|
|
Ethnicity and Nationality
|
2024-02-12 20:50:00 -08:00
|
|
|
</h1>
|
|
|
|
<div className='flex gap-2 flex-wrap'>
|
|
|
|
{nationality.map((n: string) => (
|
|
|
|
<Fragment key={n}>
|
|
|
|
<NationalityDisplay nationality={n} />
|
|
|
|
</Fragment>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
<Bio />
|
2024-02-14 10:56:05 -08:00
|
|
|
{authorsDocuments.length > 0 && (
|
|
|
|
<>
|
2024-02-15 12:04:32 -08:00
|
|
|
<hr className='mx-auto w-full h-1 border-0 bg-slate-200 my-2 rounded-md mt-8' />
|
2024-02-14 10:56:05 -08:00
|
|
|
<h1 className='text-3xl md:my-6 my-4 font-serif'>
|
2024-02-15 11:45:46 -08:00
|
|
|
Published documents {`(${authorsDocuments.length})`}
|
2024-02-14 10:56:05 -08:00
|
|
|
</h1>
|
|
|
|
{authorsDocuments.map((d) => (
|
2024-02-14 12:42:04 -08:00
|
|
|
<Fragment key={d.slug}>
|
|
|
|
<DocumentCard doc={d.doc} href={`/document/view/${d.slug}`} />
|
|
|
|
</Fragment>
|
2024-02-14 10:56:05 -08:00
|
|
|
))}
|
|
|
|
</>
|
|
|
|
)}
|
2024-02-12 20:50:00 -08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|