Merge branch 'main' into better-documents
This commit is contained in:
commit
5bfcf96987
9 changed files with 122 additions and 49 deletions
|
@ -5,6 +5,7 @@ import { Zilla_Slab } from 'next/font/google'
|
||||||
import { notFound } from 'next/navigation'
|
import { notFound } from 'next/navigation'
|
||||||
import DocumentCard from '@/app/components/DocumentCard'
|
import DocumentCard from '@/app/components/DocumentCard'
|
||||||
import findDocumentsByAuthor from './findDocumentsByAuthor'
|
import findDocumentsByAuthor from './findDocumentsByAuthor'
|
||||||
|
import cardEffects from '@/app/styles/cardEffects.module.css'
|
||||||
|
|
||||||
const zillaSlab = Zilla_Slab({ subsets: ['latin'], weight: ['500'] })
|
const zillaSlab = Zilla_Slab({ subsets: ['latin'], weight: ['500'] })
|
||||||
|
|
||||||
|
@ -41,11 +42,15 @@ export default function AuthorDisplay({
|
||||||
) : null}
|
) : null}
|
||||||
<div className='my-4 max-h-12 flex flex-wrap gap-2'>
|
<div className='my-4 max-h-12 flex flex-wrap gap-2'>
|
||||||
{affiliation.map((a: string) => (
|
{affiliation.map((a: string) => (
|
||||||
<Link key={a} href={`/affiliation/${a.split('@')[1]}`}>
|
<Link
|
||||||
|
key={a}
|
||||||
|
href={`/affiliation/${a.split('@')[1]}`}
|
||||||
|
className={cardEffects['card-small']}
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src={affiliations[a.split('@')[1]].image}
|
src={affiliations[a.split('@')[1]].image}
|
||||||
alt={affiliations[a.split('@')[1]].name}
|
alt={affiliations[a.split('@')[1]].name}
|
||||||
className='h-12 shadow-sm shadow-slate-400 rounded-md'
|
className='h-12 rounded-md'
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -14,7 +14,7 @@ const DocumentCard = ({ doc, href }: { doc: Document; href: string }) => {
|
||||||
return (
|
return (
|
||||||
<Link href={href} className='no-link-style'>
|
<Link href={href} className='no-link-style'>
|
||||||
<div
|
<div
|
||||||
className={`${cardEffects.card} border-4 rounded-lg border-gray-300 hover:border-blue-500 p-5 my-4 w-full cursor-pointer shadow-slate-300 shadow-md`}
|
className={`${cardEffects['card-large']} border-4 rounded-lg border-gray-300 hover:border-blue-500 p-5 my-4 w-full cursor-pointer shadow-slate-300 shadow-md`}
|
||||||
role='button' // this is a critical DEI concern as we have marked this element as a button with ARIA role, yet we have not supported button accessiblity features
|
role='button' // this is a critical DEI concern as we have marked this element as a button with ARIA role, yet we have not supported button accessiblity features
|
||||||
>
|
>
|
||||||
<h2 className={`${zillaSlab.className} text-3xl`}>{title}</h2>
|
<h2 className={`${zillaSlab.className} text-3xl`}>{title}</h2>
|
||||||
|
|
|
@ -31,19 +31,21 @@ export default function MobileMenu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-20'>
|
<>
|
||||||
<button
|
<div className='w-20'>
|
||||||
className='p-2 rounded-xl hover:bg-blue-400'
|
<button
|
||||||
onClick={handleClick}
|
className='p-2 rounded-xl hover:bg-blue-400'
|
||||||
>
|
onClick={handleClick}
|
||||||
<RxHamburgerMenu size={40} />
|
>
|
||||||
</button>
|
<RxHamburgerMenu size={40} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${isOpen ? '' : styles['menu-hidden']} ${styles.menu} shadow-md shadow-slate-300`}
|
className={`${isOpen ? '' : styles['menu-hidden']} ${styles.menu} shadow-md shadow-slate-300`}
|
||||||
>
|
>
|
||||||
<span className={styles['search-bar']}>
|
<div className={styles['search-bar']}>
|
||||||
<SearchBar onSubmit={handleSubmit} />
|
<SearchBar onSubmit={handleSubmit} />
|
||||||
</span>
|
</div>
|
||||||
<p className='text-slate-600 mx-4 my-4'>
|
<p className='text-slate-600 mx-4 my-4'>
|
||||||
We gratefully acknowledge support from our volunteer peer reviewers,
|
We gratefully acknowledge support from our volunteer peer reviewers,
|
||||||
member institutions, and all{' '}
|
member institutions, and all{' '}
|
||||||
|
@ -56,6 +58,6 @@ export default function MobileMenu() {
|
||||||
.
|
.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@ export default function SearchBar({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-full flex flex-nowrap'>
|
<div className='mx-2 flex flex-nowrap gap-2'>
|
||||||
<input
|
<input
|
||||||
type='text'
|
type='text'
|
||||||
className='py-3 px-5 rounded-xl text-slate-800 flex-grow'
|
className='py-3 px-5 rounded-xl text-slate-800 flex-grow flex-shrink min-w-0'
|
||||||
name='q'
|
name='q'
|
||||||
placeholder='Search...'
|
placeholder='Search...'
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
|
@ -37,7 +37,7 @@ export default function SearchBar({
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type='submit'
|
type='submit'
|
||||||
className='p-2.5 mx-4 border-2 rounded-xl hover:bg-blue-300 flex-shrink'
|
className='p-2.5 border-2 rounded-xl hover:bg-blue-300 flex-shrink'
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
Search
|
Search
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
.menu {
|
.menu {
|
||||||
@apply overflow-hidden left-[0] top-[235px] z-10 absolute bg-slate-200;
|
@apply overflow-hidden top-[235px] z-10 absolute bg-slate-200;
|
||||||
@apply duration-300;
|
height: 180px;
|
||||||
height: fit-content;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
transition: height 0.2s ease-in-out;
|
transition: height 0.2s ease-in-out;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
right: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-bar {
|
.search-bar {
|
||||||
@apply w-full flex justify-center z-10 px-4 py-2 bg-slate-300;
|
@apply z-10 mt-2 mx-[2px] sm:m-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-bar button {
|
.search-bar button {
|
||||||
|
@ -18,5 +16,4 @@
|
||||||
|
|
||||||
.menu-hidden {
|
.menu-hidden {
|
||||||
height: 0;
|
height: 0;
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -415,7 +415,7 @@ export const authors: Readonly<{ [key: string]: Author }> = {
|
||||||
'Student@srvhs',
|
'Student@srvhs',
|
||||||
],
|
],
|
||||||
image: '/img/profiles/wlin.jpg',
|
image: '/img/profiles/wlin.jpg',
|
||||||
nationality: ['twn', 'chn', 'usa'],
|
nationality: ['twn', 'chn', 'jpn', 'usa'],
|
||||||
formerAffiliations: ['Intern@raid-zero'],
|
formerAffiliations: ['Intern@raid-zero'],
|
||||||
bio: 'Hi, I am Kaito or Warren. I am a Self-taught programmer and engineer. I go around doing dumb things such as my projects. I have a dream of building a community. I am currently part of many projects.',
|
bio: 'Hi, I am Kaito or Warren. I am a Self-taught programmer and engineer. I go around doing dumb things such as my projects. I have a dream of building a community. I am currently part of many projects.',
|
||||||
website: 'https://kaitotlex.carrd.co/',
|
website: 'https://kaitotlex.carrd.co/',
|
||||||
|
@ -442,7 +442,7 @@ export const authors: Readonly<{ [key: string]: Author }> = {
|
||||||
'Mentor@team-1280',
|
'Mentor@team-1280',
|
||||||
],
|
],
|
||||||
formerAffiliations: ['Captain@team-1280', 'Student@srvhs'],
|
formerAffiliations: ['Captain@team-1280', 'Student@srvhs'],
|
||||||
nationality: ['usa'],
|
nationality: ['irl', 'usa'],
|
||||||
image: '/img/profiles/edanko.jpg',
|
image: '/img/profiles/edanko.jpg',
|
||||||
},
|
},
|
||||||
arvenkatesh: {
|
arvenkatesh: {
|
||||||
|
@ -742,6 +742,11 @@ export const nationalities: Readonly<{ [key: string]: Nationality }> = {
|
||||||
demonym: 'Filipino',
|
demonym: 'Filipino',
|
||||||
flag: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Flag_of_the_Philippines.svg/2880px-Flag_of_the_Philippines.svg.png',
|
flag: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Flag_of_the_Philippines.svg/2880px-Flag_of_the_Philippines.svg.png',
|
||||||
},
|
},
|
||||||
|
irl: {
|
||||||
|
name: 'Republic of Ireland',
|
||||||
|
demonym: 'Irish',
|
||||||
|
flag: 'https://upload.wikimedia.org/wikipedia/commons/4/45/Flag_of_Ireland.svg',
|
||||||
|
},
|
||||||
unknown: {
|
unknown: {
|
||||||
name: 'Undetermined',
|
name: 'Undetermined',
|
||||||
demonym: 'Undetermined',
|
demonym: 'Undetermined',
|
||||||
|
|
|
@ -1,28 +1,65 @@
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { documents, authors, affiliations } from './db/data'
|
import { documents, authors, affiliations, Author } from './db/data'
|
||||||
import News from './components/News'
|
import News from './components/News'
|
||||||
import RandomDocs from './components/RandomDocs'
|
import RandomDocs from './components/RandomDocs'
|
||||||
import RecentDocuments from './components/RecentDocuments'
|
import RecentDocuments from './components/RecentDocuments'
|
||||||
|
|
||||||
|
function sortAuthorsByDocumentsPublished(authors: {
|
||||||
|
[key: string]: Author
|
||||||
|
}): { id: string; author: Author }[] {
|
||||||
|
// Initialize a map to count documents for each author
|
||||||
|
const authorDocumentCount: { [key: string]: number } = {}
|
||||||
|
|
||||||
|
// Iterate over documents to count the number for each author
|
||||||
|
Object.values(documents).forEach((document) => {
|
||||||
|
document.manifest.authors.forEach((authorId) => {
|
||||||
|
if (authorDocumentCount[authorId]) {
|
||||||
|
authorDocumentCount[authorId] += 1
|
||||||
|
} else {
|
||||||
|
authorDocumentCount[authorId] = 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Convert the authors object into an array of objects including the author ID
|
||||||
|
const authorsWithId = Object.keys(authors).map((id) => ({
|
||||||
|
id,
|
||||||
|
author: authors[id],
|
||||||
|
count: authorDocumentCount[id] || 0, // Include the count for sorting
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Sort authors by their document count in descending order
|
||||||
|
authorsWithId.sort((a, b) => b.count - a.count)
|
||||||
|
|
||||||
|
// Return the sorted array, excluding the count property
|
||||||
|
return authorsWithId.map(({ id, author }) => ({ id, author }))
|
||||||
|
}
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const AuthorDisplay = () => {
|
const AuthorDisplay = () => {
|
||||||
return Object.entries(authors).map(([author, data], index) => {
|
return (
|
||||||
let affiliationSlug = data.affiliation[0].split('@')[1]
|
<ol className='list-decimal pl-4 space-y-2'>
|
||||||
let affiliation = affiliations[affiliationSlug]
|
{sortAuthorsByDocumentsPublished(authors).map(({ id, author }) => {
|
||||||
return (
|
let data = author
|
||||||
<div key={author}>
|
|
||||||
<Link href={`/author/${author}`}>
|
let affiliationSlug = data.affiliation[0].split('@')[1]
|
||||||
{data.name.first}
|
let affiliation = affiliations[affiliationSlug]
|
||||||
{data.name.nickname ? ` "${data.name.nickname}" ` : ' '}
|
return (
|
||||||
{data.name.last}
|
<li key={id}>
|
||||||
</Link>{' '}
|
<Link href={`/author/${id}`}>
|
||||||
of{' '}
|
{data.name.first}
|
||||||
<Link href={`/affiliation/${affiliationSlug}`}>
|
{data.name.nickname ? ` "${data.name.nickname}" ` : ' '}
|
||||||
{affiliation.short}
|
{data.name.last}
|
||||||
</Link>
|
</Link>{' '}
|
||||||
</div>
|
of{' '}
|
||||||
)
|
<Link href={`/affiliation/${affiliationSlug}`}>
|
||||||
})
|
{affiliation.short}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ol>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -58,7 +95,7 @@ export default function Home() {
|
||||||
<hr className='mx-auto w-full h-1 border-0 bg-slate-200 my-2 rounded-md' />
|
<hr className='mx-auto w-full h-1 border-0 bg-slate-200 my-2 rounded-md' />
|
||||||
<br />
|
<br />
|
||||||
<div className='font-serif text-xl'>
|
<div className='font-serif text-xl'>
|
||||||
Our esteemed faculty and alumni
|
Our esteemed faculty and alumni (ranked by research output)
|
||||||
</div>
|
</div>
|
||||||
<AuthorDisplay />
|
<AuthorDisplay />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -42,7 +42,7 @@ const SearchResult = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${cardEffects.card} border-4 rounded-lg border-gray-300 hover:border-blue-500 p-5 my-4 w-full cursor-pointer`}
|
className={`${cardEffects['card-large']} border-4 rounded-lg border-gray-300 hover:border-blue-500 p-5 my-4 w-full cursor-pointer`}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
role='button' // this is a critical DEI concern as we have marked this element as a button with ARIA role, yet we have not supported button accessiblity features
|
role='button' // this is a critical DEI concern as we have marked this element as a button with ARIA role, yet we have not supported button accessiblity features
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/* creates a 3D card effect using a pseudo element for performance reasons */
|
/* creates a 3D card effect using a pseudo element for performance reasons */
|
||||||
|
|
||||||
.card {
|
.card-large {
|
||||||
@apply shadow-sm shadow-slate-300;
|
@apply shadow-sm shadow-slate-300;
|
||||||
/* box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); */
|
/* box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); */
|
||||||
transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
|
transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.card::after {
|
.card-large::after {
|
||||||
@apply shadow-lg shadow-slate-500;
|
@apply shadow-lg shadow-slate-500;
|
||||||
content: '';
|
content: '';
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
|
@ -19,10 +19,37 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card:hover {
|
.card-large:hover {
|
||||||
transform: scale(1.02, 1.02);
|
transform: scale(1.02, 1.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card:hover::after {
|
.card-large:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-small {
|
||||||
|
@apply shadow-sm shadow-slate-300;
|
||||||
|
/* box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); */
|
||||||
|
transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.card-small::after {
|
||||||
|
@apply shadow-md shadow-slate-500;
|
||||||
|
content: '';
|
||||||
|
z-index: -1;
|
||||||
|
transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-small:hover {
|
||||||
|
transform: scale(1.08, 1.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-small:hover::after {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue