Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

47 team page #48

Merged
merged 24 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
28 changes: 28 additions & 0 deletions e2e/team.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { test, expect } from '@playwright/test';

test('shows the team', async ({ page }) => {
await page.goto('/#/team')

const teamContainer = page.getByLabel('team-container')

const heading = teamContainer.getByText('✨ Leadership Team ✨')
await expect(heading).toBeVisible()

const cards = await teamContainer.getByLabel('team-member-card').all()
expect(cards).toHaveLength(7)
const ann = cards[0]
await expect(ann.getByText('Ann Kilzer')).toBeVisible()
await expect(ann.getByText('Director')).toBeVisible()
const annPhoto = ann.getByRole('img').first()
await expect(annPhoto).toBeVisible()
await expect(annPhoto).toHaveAttribute('alt-text', 'Ann Kilzer photo')

// verify links
const links = await page.getByLabel('link-wrapper').all()
expect(links).toHaveLength(1)
const annLink = links[0]
await expect(annLink).toBeVisible()
await expect(annLink).toHaveRole('link')
await expect(annLink).toHaveAttribute('href', 'https://annkilzer.net')
await expect(annLink).toHaveAttribute('target', '_blank')
});
Binary file added public/Ann.png
ann-kilzer marked this conversation as resolved.
Show resolved Hide resolved
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/Placeholder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/components/Header/DesktopHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ const DesktopHeader: FC = () => {
<Typography variant="h1">WiSE Japan</Typography>
<Typography variant="caption">{t('header.subtitle')}</Typography>
</StyledNavLink>

<StyledNavLink to="/team" style={{ textDecoration: 'none', color: 'white' }}>
<Typography variant="overline">{t('header.team')}</Typography>
</StyledNavLink>
<StyledNavLink to="/codeofconduct" style={{ textDecoration: 'none', color: 'white' }}>
<Typography variant="overline">{t('header.codeOfConduct')}</Typography>
</StyledNavLink>
Expand Down
8 changes: 7 additions & 1 deletion src/components/Header/__test__/DesktopToolbar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ describe('Header', () => {
expect(title).toBeVisible()
})

it.todo('should show navigation links')
it('should show navigation links', async () => {
render(<DesktopHeader />)
const team = await screen.findByText('Team')
expect(team).toBeVisible()
const codeOfConduct = await screen.findByText('Code of Conduct')
expect(codeOfConduct).toBeVisible()
})
})
20 changes: 20 additions & 0 deletions src/components/OptionalLinkWrapper/OptionalLinkWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FC, ReactNode } from 'react'

interface OptionalLinkWrapperProps {
url?: string
children: ReactNode
}

/**
* If url is falsy, returns children. If url is truthy, returns the component wrapped in a link
*/
const OptionalLinkWrapper: FC<OptionalLinkWrapperProps> = ({ url, children }) => {
if (url) {
return <a href={url} target='_blank' rel="noreferrer" aria-label='link-wrapper'>
{children}
</a>
}
return children
}

export default OptionalLinkWrapper
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { describe, expect, it } from 'vitest'
import { render } from '@/tests/customRender'
import { screen } from '@testing-library/react'
import OptionalLinkWrapper from '../OptionalLinkWrapper';


describe('OptionalLinkWrapper', () => {
const exampleURL = 'https://example.com'

it('should render the link when URL is set', async () => {
render(<OptionalLinkWrapper url={exampleURL}>
<span>child</span>
</OptionalLinkWrapper>)

const link = await screen.findByRole('link')
expect(link).toHaveAttribute('href', exampleURL)

const child = await screen.findByText('child')
expect(child).toBeVisible()
})

it.each(['', undefined])('should render the child component when URL is %i', async (url: string | undefined) => {
render(<OptionalLinkWrapper url={url}>
<span>child</span>
</OptionalLinkWrapper>)

const child = await screen.findByText('child')
expect(child).toBeVisible()

const link = screen.queryByRole('link')
expect(link).toBeNull()
})
});
7 changes: 6 additions & 1 deletion src/components/SideDrawer/DrawerContents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,22 @@ import { useTheme } from '@mui/material/styles'
import useMediaQuery from '@mui/material/useMediaQuery'
import StyledNavLink from '../StyledNavLink/StyledNavLink'
import LocaleToggle from '../LocaleToggle/LocaleToggle'
import { useTranslation } from 'react-i18next'

const DrawerContents: FC = () => {
const theme = useTheme()
const { t } = useTranslation();
let navList = <></>
if (useMediaQuery(theme.breakpoints.down('sm'))) {
navList = (<>
<ListItem>
<StyledNavLink to='/'>Home</StyledNavLink>
</ListItem>
<ListItem>
<StyledNavLink to='/codeofconduct'>Code of Conduct</StyledNavLink>
<StyledNavLink to='/team'>{t('sidebar.team')}</StyledNavLink>
</ListItem>
<ListItem>
<StyledNavLink to='/codeofconduct'>{t('sidebar.codeOfConduct')}</StyledNavLink>
</ListItem>
<Divider />
</>)
Expand Down
50 changes: 50 additions & 0 deletions src/components/TeamMemberCard/TeamMemberCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { FC, useEffect, useState } from 'react'
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent'
import CardMedia from '@mui/material/CardMedia'
import Typography from '@mui/material/Typography'
import TeamMember from '@/types/TeamMember'
import i18next from 'i18next'
import OptionalLinkWrapper from '../OptionalLinkWrapper/OptionalLinkWrapper';

interface TeamMemberCardProps {
member: TeamMember
}

const TeamMemberCard: FC<TeamMemberCardProps> = ({ member }) => {
const [name, setName] = useState(member.nameEN)
const [title, setTitle] = useState(member.titleEN)

useEffect(() => {
ann-kilzer marked this conversation as resolved.
Show resolved Hide resolved
console.log(i18next.resolvedLanguage)
if (i18next.resolvedLanguage === 'en') {
setName(member.nameEN)
setTitle(member.titleEN)
} else if (i18next.resolvedLanguage === 'ja') {
setName(member.nameJA)
setTitle(member.titleJA)
}
}, [member])

return <OptionalLinkWrapper url={member.url}>
<Card sx={{ height: 420 }} aria-label="team-member-card">
<CardMedia
sx={{ height: 300, width: 300 }}
image={member.image || 'Placeholder.png'}
title={name}
alt-text={`${name} photo`}
/>
<CardContent>
<Typography variant='h6'>
{name}
</Typography>
<Typography variant="subtitle1">
{title}
</Typography>

</CardContent>
</Card>
</OptionalLinkWrapper>
}

export default TeamMemberCard
48 changes: 48 additions & 0 deletions src/components/TeamMemberCard/__team__/TeamMemberCard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { describe, expect, it } from 'vitest'
import { render } from '@/tests/customRender'
import { screen } from '@testing-library/react'
import TeamMemberCard from '../TeamMemberCard';
import TeamMember from '@/types/TeamMember';
import '@/i18n/config';
import i18next from 'i18next';
import { I18nextProvider } from 'react-i18next';


describe('TeamMemberCard', () => {
const member = {
nameEN: 'Alice',
nameJA: 'アリス',
titleEN: 'Lead',
titleJA: 'リード',
image: 'example.png',
url: 'https://example.com'
} as TeamMember

it('should render a TeamMemberCard in English', async () => {
render(<TeamMemberCard member={member} />)
const name = await screen.findByText(member.nameEN)
expect(name).toBeVisible()
const title = await screen.findByText(member.titleEN)
expect(title).toBeVisible()
const link = await screen.findByRole('link')
expect(link).toHaveAttribute('href', member.url)
const image = await screen.findByRole('img')
expect(image).toBeVisible()
})

it('should render a TeamMemberCard in Japanese', async () => {
await i18next.changeLanguage('ja')
render(<I18nextProvider i18n={i18next}>
<TeamMemberCard member={member} />
</I18nextProvider>)

const name = await screen.findByText(member.nameJA)
expect(name).toBeVisible()
const title = await screen.findByText(member.titleJA)
expect(title).toBeVisible()
const link = await screen.findByRole('link')
expect(link).toHaveAttribute('href', member.url)
const image = await screen.findByRole('img')
expect(image).toBeVisible()
})
});
12 changes: 10 additions & 2 deletions src/i18n/en/translation.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
{
"header": {
"codeOfConduct": "Code of Conduct",
"subtitle": "Women in Software Engineering Japan"
"subtitle": "Women in Software Engineering Japan",
"team": "Team"
},
"home": {
"helloWorld": "✨ Hello World ✨",
"joinUs": "✨ Join us on Slack ✨",
"paragraph1": "Many of us were saddened to hear of the sudden closure of Women Who Code. There is a need for an organization to empower diverse women in technology careers in Tokyo and across Japan.",
"paragraph2": "We are not giving up on this mission. Please join us in rebuilding community so that we can empower women in Japan in Software Engineering careers.",
"paragraph3": "Our events target professional women in software careers with 2+ years of experience. Beginners to seasoned professionals are welcome to participate. While this organization focuses on women, all genders are welcome at our events. Software-adjacent roles like Data Science, Product, UI/UX, Machine Learning, etc., are welcome, too."
},
"sidebar": {
"codeOfConduct": "Code of Conduct",
"team": "Team"
},
"team": {
"title": "✨ Leadership Team ✨"
}
}
}
12 changes: 10 additions & 2 deletions src/i18n/ja/translation.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
{
"header": {
"codeOfConduct": "行動規範",
"subtitle": "ウーマン・イン・ソフトウェアエンジニアリング"
"subtitle": "ウーマン・イン・ソフトウェアエンジニアリング",
"team": "チーム"
},
"home": {
"helloWorld": "✨ Hello 世界 ✨",
"joinUs": "✨ スラックに参加する ✨",
"paragraph1": "Women Who Code(WWCode)の活動中止のニュースに対し、多くの人々が悲しみました。東京や日本全体で、IT業界の多様な女性を支援する組織が必要とされています。",
"paragraph2": "この使命を諦めるつもりはありません。WWCodeの志を引き継ぐために、日本の女性がソフトウェアエンジニアとしてキャリアを築けるよう、私たちと共にコミュニティを再構築していきます。",
"paragraph3": "私たちのイベントは、2年以上の経験を持つITプロフェッショナルの女性を中心に、新卒からベテランまでどなたでも参加できるイベントをやっています。この組織は女性に焦点を当てていますが、イベントにはすべてのジェンダーの方が歓迎されています。また、データサイエンティスト、プロダクトマネジャー、UI/UXデザイナー、機械学習エンジニアなどのソフトウェアに関連した役割も歓迎いたします。"
},
"sidebar": {
"codeOfConduct": "Code of Conduct",
"team": "チーム"
},
"team": {
"title": "✨ リーダーシップ・チーム ✨"
}
}
}
5 changes: 5 additions & 0 deletions src/routes/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Home from './Home/Home'
import BaseLayout from './BaseLayout'
import NotFound from './NotFound/NotFound'
import CodeOfConduct from './CodeOfConduct/CodeOfConduct'
import Team from './Team/Team'

const browserRouter = createHashRouter([{
element: <BaseLayout />,
Expand All @@ -20,6 +21,10 @@ const browserRouter = createHashRouter([{
path: 'codeofconduct',
element: <CodeOfConduct />
},
{
path: 'team',
element: <Team />
},
{
path: 'theme',
element: <ThemePreview />
Expand Down
32 changes: 32 additions & 0 deletions src/routes/Team/Team.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { FC, ReactNode } from 'react'
import Container from '@mui/material/Container'
import Grid from '@mui/material/Grid'
import Stack from '@mui/material/Stack'
import Typography from '@mui/material/Typography'
import { useTranslation } from 'react-i18next'
import TeamMember from '@/types/TeamMember'
import TeamMemberCard from '@/components/TeamMemberCard/TeamMemberCard'
import team from './team.json'


const Team: FC = () => {
const { t } = useTranslation();

const teamGrid: ReactNode[] = []
team.forEach((member: TeamMember) => {
teamGrid.push(<Grid item key={member.nameEN}>
<TeamMemberCard member={member} />
</Grid>)
})

return <Container style={{ padding: 32 }} aria-label="team-container">
<Stack spacing={2}>
<Typography variant="h1">{t('team.title')}</Typography>
<Grid container spacing={2}>
{teamGrid}
</Grid>
</Stack>
</Container>
}

export default Team
12 changes: 12 additions & 0 deletions src/routes/Team/__test__/Team.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { describe, expect, it } from 'vitest'
import { render } from '@/tests/customRender'
import { screen } from '@testing-library/react'
import Team from '../Team';

describe('Team', () => {
it('should render the Team page', async () => {
render(<Team />)
const title = await screen.findByText('✨ Leadership Team ✨')
expect(title).toBeVisible()
})
});
Loading
Loading