Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/images/jura-hanbok.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-christmas/sean.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/bekzattilekbay.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/chae.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/chanyoungpark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/daeheon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/daeun.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/eugenechoi.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/eunhye.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/eunyoung.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/gosuchoi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/haerilee.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/hayeon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/heechan_lee.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/hyehyun.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/hyewon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/hyungyu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/hyunjungyi.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/hyunseok.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/hyunwoo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/jaesang.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/jaeyoung.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/jennyyang.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/jihohanan.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/juhokim.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/members-hanbok/juhyeon.png
Binary file added public/members-hanbok/junhomyung.png
Binary file added public/members-hanbok/kihoon.png
Binary file added public/members-hanbok/mingyu.png
Binary file added public/members-hanbok/minju.jpg
Binary file added public/members-hanbok/nadia.jpg
Binary file added public/members-hanbok/oaksil.jpg
Binary file added public/members-hanbok/saelyne.jpg
Binary file added public/members-hanbok/sclee.jpg
Binary file added public/members-hanbok/sean.jpg
Binary file added public/members-hanbok/sehoon.png
Binary file added public/members-hanbok/seoyeon.jpg
Binary file added public/members-hanbok/seungju.jpg
Binary file added public/members-hanbok/shujun.jpg
Binary file added public/members-hanbok/taesoo.png
Binary file added public/members-hanbok/yeonsupark.jpg
Binary file added public/members-hanbok/yoonseo.jpg
Binary file added public/members-hanbok/yoonsu.jpg
Binary file added public/members-hanbok/yuri.png
Binary file added public/members-hanbok/zhengwei.jpg
Binary file added public/members/jaeyoung.jpeg
Binary file removed public/members/jaeyoung.jpg
Diff not rendered.
Binary file modified public/members/juhyeon.jpg
4 changes: 2 additions & 2 deletions src/app/people/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { FontVariant, ScreenSize, linearlyScaleSize } from '@/app/theme'
import { AlumniCard, SpecialThanksCard } from '@/components/AlumniCard'
import { Divider } from '@/components/Divider'
import { MemberCard } from '@/components/MemberCard'
import { MemberCard, CurrentMode } from '@/components/MemberCard'
import { Section, SectionTitle, Sections } from '@/components/Section'
import { Sidebar } from '@/components/SideBar'
import { ALUMNI_MEMBERS_BY_POSITION, CURRENT_MEMBERS_BY_POSITION, KixlabPositions } from '@/data/members'
Expand Down Expand Up @@ -104,7 +104,7 @@ export default function Page() {
<SectionTitle>{position}</SectionTitle>
<SectionContent>
{CURRENT_MEMBERS_BY_POSITION[position].map(member => (
<MemberCard key={member.email} member={member} />
<MemberCard key={member.email} member={member} mode={CurrentMode} />
))}
</SectionContent>
</Section>
Expand Down
52 changes: 50 additions & 2 deletions src/components/AlumniCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
'use client'

import React from 'react'
import React, { useState } from 'react'
import styled from '@emotion/styled'
import { FontVariant, Color } from '@/app/theme'
import Link from 'next/link'
import { Member } from '@/data/members'
import Image from 'next/image'
import { CurrentMode } from './MemberCard'

const AlumniCardContainer = styled.div`
width: 100%;
Expand Down Expand Up @@ -127,6 +128,28 @@ export const AlumniCard = ({ mem }: { mem: Member }) => {
)
}

const JuraImageWrapper = styled.div`
position: relative;
width: 200px;
height: 200px;
flex-shrink: 0;
`

const FadingImage = styled.div<{ opacity: number }>`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transition: opacity 0.3s ease-in-out;
opacity: ${({ opacity }) => opacity};
`

const juraHoverImages: Partial<Record<string, string>> = {
DEFAULT: '/images/jura.png',
HANBOK: '/images/jura-hanbok.jpg',
}

export const SpecialThanksCard = ({
img,
name,
Expand All @@ -138,9 +161,34 @@ export const SpecialThanksCard = ({
position: string
description: string
}) => {
const [isHovered, setIsHovered] = useState(false)

const hoverImg = juraHoverImages[CurrentMode]
const hasHover = Boolean(hoverImg)

const toggleHover = () => {
setIsHovered(prev => !prev)
}

return (
<SpecialThanksContainer>
<Image src={img} alt="Jura Coffee Machine" width={200} height={200} />
<JuraImageWrapper
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onClick={toggleHover}
>
{/* Base Image */}
<FadingImage opacity={hasHover && isHovered ? 0 : 1}>
<Image src={img} alt="Jura Coffee Machine" width={200} height={200} priority />
</FadingImage>

{/* Hover Image */}
{hasHover && hoverImg && (
<FadingImage opacity={isHovered ? 1 : 0}>
<Image src={hoverImg} alt="Jura Coffee Machine (Hover)" width={200} height={200} priority />
</FadingImage>
)}
</JuraImageWrapper>
<div>
<TextRow>
<Name>{name}</Name>
Expand Down
27 changes: 23 additions & 4 deletions src/components/ImageWithFallback.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
import { useState } from 'react'
import { useEffect, useState } from 'react'
import Image, { ImageProps } from 'next/image'

export const ImageWithFallback = ({ fallbackSrc, ...props }: { fallbackSrc: string } & ImageProps) => {
const [imageSrc, setImageSrc] = useState(props.src)
interface Props extends Omit<ImageProps, 'onError' | 'src'> {
src: ImageProps['src']
fallbackSrc: string | string[]
}

export const ImageWithFallback = ({ fallbackSrc, src, ...props }: Props) => {
const [imageSrc, setImageSrc] = useState<ImageProps['src']>(src)
const [errorIndex, setErrorIndex] = useState(0)

useEffect(() => {
setImageSrc(src)
setErrorIndex(0)
}, [src])

const onError = () => {
if (Array.isArray(fallbackSrc)) {
if (errorIndex < fallbackSrc.length) {
const next = fallbackSrc[errorIndex]
setImageSrc(next)
setErrorIndex(prev => prev + 1)
}
return
}
setImageSrc(fallbackSrc)
}

return <Image {...props} src={imageSrc} alt={props.alt} onError={onError} />
return <Image {...props} src={imageSrc} onError={onError} />
}
61 changes: 56 additions & 5 deletions src/components/MemberCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
'use client'

import React from 'react'
import React, { useMemo, useState } from 'react'
import styled from '@emotion/styled'
import { FontVariant, Color } from '@/app/theme'
import { ImageWithFallback } from '@/components/ImageWithFallback'
import { Member } from '@/data/members'
import Link from 'next/link'

enum ProfileMode {
DEFAULT = 'DEFAULT',
CHRISTMAS = 'CHRISTMAS',
CHILDREN = 'CHILDREN',
APRIL_FOOLS = 'APRIL-FOOLS',
HANBOK = 'HANBOK',
}

export const CurrentMode = ProfileMode.HANBOK

const Card = styled.div`
max-width: 250px;
Expand Down Expand Up @@ -96,21 +105,63 @@ const ThesisButton = styled.a`

interface Props {
member: Member
mode?: ProfileMode
}

export const MemberCard = ({ member }: Props) => {
export const MemberCard = ({ member, mode = ProfileMode.DEFAULT }: Props) => {
const [isHovered, setIsHovered] = useState(false)

const originalSrc = member.img ? `/members/${member.img}` : '/members/default.png'
const hoverSrc = useMemo(() => {
if (mode === ProfileMode.DEFAULT) return undefined
return member.hoverImg?.[mode]
}, [member.hoverImg, mode])

const hasHover = Boolean(hoverSrc)

const handleEnter = () => {
if (!hasHover) return
setIsHovered(true)
}
const handleLeave = () => {
if (!hasHover) return
setIsHovered(false)
}
const handleClick = () => {
if (!hasHover) return
setIsHovered(prev => !prev)
}

return (
<Card>
<ImageContainer>
<ImageContainer onMouseEnter={handleEnter} onMouseLeave={handleLeave} onClick={handleClick}>
<MemberImage
placeholder="blur"
blurDataURL="/members/default.png"
fallbackSrc="/members/default.png"
width={180}
height={180}
src={`/members/${member.img}`}
src={originalSrc}
alt={member.firstName}
/>
{hasHover && (
<MemberImage
key={hoverSrc}
placeholder="blur"
blurDataURL="/members/default.png"
fallbackSrc="/members/default.png"
width={180}
height={180}
src={`/${hoverSrc}`}
alt={member.firstName}
style={{
opacity: isHovered ? 1 : 0,
transition: 'opacity 0.3s ease-in-out',
zIndex: 1,
pointerEvents: 'none',
}}
/>
)}
</ImageContainer>
<Info>
<Name>
Expand Down
Loading