-
Notifications
You must be signed in to change notification settings - Fork 175
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
714cb80
commit b19dea6
Showing
6 changed files
with
452 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { | ||
Card, CardContent, Icon, Table, | ||
} from 'semantic-ui-react'; | ||
import React from 'react'; | ||
|
||
function CountStat({ title, data, color }) { | ||
return ( | ||
<Card fluid className="small-card" color={color}> | ||
<Card.Content> | ||
<Card.Header textAlign="center"> | ||
{title} | ||
</Card.Header> | ||
<Card.Description> | ||
<Table basic="very" className="count-stat" unstackable> | ||
<Table.Body> | ||
{data.map((d) => ( | ||
<Table.Row key={d.label}> | ||
<Table.Cell> | ||
<Icon name={d.icon} color={d.iconColor} /> | ||
| ||
{d.label} | ||
</Table.Cell> | ||
<Table.Cell textAlign="center">{d.count}</Table.Cell> | ||
</Table.Row> | ||
))} | ||
</Table.Body> | ||
</Table> | ||
</Card.Description> | ||
</Card.Content> | ||
<CardContent extra> | ||
Total: | ||
{' '} | ||
{data.reduce((acc, d) => acc + d.count, 0)} | ||
</CardContent> | ||
</Card> | ||
); | ||
} | ||
|
||
export default function CountStats({ person }) { | ||
return ( | ||
<> | ||
{person.medals.total > 0 && ( | ||
<CountStat | ||
title="Medals" | ||
color="yellow" | ||
data={[ | ||
{ | ||
label: 'Gold', icon: 'trophy', iconColor: 'yellow', count: person.medals.gold, | ||
}, | ||
{ | ||
label: 'Silver', icon: 'trophy', iconColor: 'grey', count: person.medals.silver, | ||
}, | ||
{ | ||
label: 'Bronze', icon: 'trophy', iconColor: 'orange', count: person.medals.bronze, | ||
}, | ||
]} | ||
/> | ||
)} | ||
{person.records.total > 0 && ( | ||
<CountStat | ||
title="Records" | ||
color="red" | ||
data={[ | ||
{ | ||
label: 'WR', icon: 'globe', iconColor: 'green', count: person.records.world, | ||
}, | ||
{ | ||
label: 'CR', icon: 'map', iconColor: 'teal', count: person.records.continental, | ||
}, | ||
{ | ||
label: 'NR', icon: 'flag', iconColor: 'blue', count: person.records.national, | ||
}, | ||
]} | ||
/> | ||
)} | ||
</> | ||
); | ||
} |
69 changes: 69 additions & 0 deletions
69
app/webpacker/components/Persons/NewPerson/ProfileDetails.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import React from 'react'; | ||
import { Card, Grid, Header } from 'semantic-ui-react'; | ||
import i18n from "../../../lib/i18n"; | ||
|
||
function Stat({ children, label, width }) { | ||
return ( | ||
<Grid.Column | ||
stretched | ||
className="stat" | ||
width={width} | ||
> | ||
<Header size="tiny" sub block> | ||
{label} | ||
<Header className="stat">{children}</Header> | ||
</Header> | ||
</Grid.Column> | ||
); | ||
} | ||
|
||
function FlagIcon({ countryIso2 }) { | ||
return ( | ||
<span | ||
className={`fi fi-${countryIso2.toLowerCase()}`} | ||
/> | ||
); | ||
} | ||
|
||
export default function ProfileDetails({ person }) { | ||
const profile = { | ||
region: person.country, | ||
wcaId: person.wcaId, | ||
gender: person.gender, | ||
competitions: person.competitionCount, | ||
solves: person.completedSolves, | ||
}; | ||
const statCount = 2 | ||
+ (profile.gender ? 1 : 0) | ||
+ (profile.competitions ? 1 : 0) | ||
+ (profile.solves ? 1 : 0); | ||
|
||
const regionWidth = 16; // (statCount % 2) == 1 ? 11 : 8; | ||
const idWidth = (statCount % 2) === 0 ? 16 : 8; | ||
const otherWidth = 8; | ||
|
||
return ( | ||
<Card fluid className="large-card" color="blue"> | ||
<Card.Content> | ||
<Card.Header textAlign="center"> | ||
Profile | ||
</Card.Header> | ||
<Grid textAlign="center" className="stat-grid"> | ||
<Stat label="Region" width={regionWidth}> | ||
<FlagIcon countryIso2={profile.region.iso2} /> | ||
{' '} | ||
{profile.region.name} | ||
</Stat> | ||
<Stat label="WCA ID" width={idWidth}>{profile.wcaId}</Stat> | ||
{profile.gender && ( | ||
<Stat label="Gender" width={otherWidth}> | ||
{i18n.t(`enums.user.gender.${profile.gender}`)} | ||
</Stat> | ||
)} | ||
{profile.solves && <Stat label="Solves" width={otherWidth}>{profile.solves}</Stat>} | ||
{profile.competitions && <Stat label="Competitions" width={otherWidth}>{profile.competitions}</Stat>} | ||
</Grid> | ||
</Card.Content> | ||
</Card> | ||
); | ||
} |
111 changes: 111 additions & 0 deletions
111
app/webpacker/components/Persons/NewPerson/RecordTable.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import React from 'react'; | ||
import { Icon, Popup, Table } from 'semantic-ui-react'; | ||
import I18nHTMLTranslate from '../../I18nHTMLTranslate'; | ||
import { events } from '../../../lib/wca-data.js.erb'; | ||
import I18n from '../../../lib/i18n'; | ||
import EventIcon from '../../wca/EventIcon'; | ||
|
||
function RankCell({ ranks, type }) { | ||
if (!ranks) return <Table.Cell />; | ||
|
||
const rank = ranks[`${type}Rank`]; | ||
if (rank === undefined) return <Table.Cell />; | ||
|
||
const opacity = rank === 1 ? 1 : { | ||
country: 0.6, | ||
continent: 0.8, | ||
world: 1, | ||
}[type]; | ||
|
||
const color = rank === 1 ? 'red' : undefined; | ||
|
||
return ( | ||
<Table.Cell> | ||
<span | ||
style={{ | ||
opacity, | ||
color, | ||
}} | ||
> | ||
{rank === 0 ? '-' : rank} | ||
</span> | ||
</Table.Cell> | ||
); | ||
} | ||
|
||
function EventData({ event, person, anyOdd }) { | ||
const singles = person.singleRanks; | ||
const averages = person.averageRanks; | ||
|
||
const singleForEvent = singles.find((r) => r.eventId === event); | ||
const averageForEvent = averages.find((r) => r.eventId === event); | ||
if (!singleForEvent && !averageForEvent) return null; | ||
|
||
const isOdd = singleForEvent.oddRank || averageForEvent?.oddRank; | ||
|
||
return ( | ||
<Table.Row textAlign="right"> | ||
<Table.Cell textAlign="left"> | ||
<EventIcon id={event} /> | ||
{' '} | ||
<I18nHTMLTranslate i18nKey={`events.${event}`} /> | ||
</Table.Cell> | ||
<RankCell ranks={singleForEvent} type="country" /> | ||
<RankCell ranks={singleForEvent} type="continent" /> | ||
<RankCell ranks={singleForEvent} type="world" /> | ||
<Table.Cell><b>{singleForEvent?.time}</b></Table.Cell> | ||
<Table.Cell><b>{averageForEvent?.time}</b></Table.Cell> | ||
<RankCell ranks={averageForEvent} type="world" /> | ||
<RankCell ranks={averageForEvent} type="continent" /> | ||
<RankCell ranks={averageForEvent} type="country" /> | ||
{anyOdd && ( | ||
<Table.Cell> | ||
{isOdd && ( | ||
<Popup | ||
content={I18n.t('persons.show.odd_rank_reason')} | ||
trigger={( | ||
<Icon | ||
name="question circle" | ||
/> | ||
)} | ||
/> | ||
)} | ||
</Table.Cell> | ||
)} | ||
</Table.Row> | ||
); | ||
} | ||
|
||
export default function RecordTable({ person }) { | ||
const { singleRanks, averageRanks } = person; | ||
const anyOddRank = singleRanks.some((r) => r.oddRank) || averageRanks.some((r) => r.oddRank); | ||
|
||
return ( | ||
<Table unstackable compact="very" singleLine basic="very" striped> | ||
<Table.Header> | ||
<Table.Row textAlign="right"> | ||
<Table.HeaderCell textAlign="left">Event</Table.HeaderCell> | ||
<Table.HeaderCell>NR</Table.HeaderCell> | ||
<Table.HeaderCell>CR</Table.HeaderCell> | ||
<Table.HeaderCell>WR</Table.HeaderCell> | ||
<Table.HeaderCell>Single</Table.HeaderCell> | ||
<Table.HeaderCell>Average</Table.HeaderCell> | ||
<Table.HeaderCell>WR</Table.HeaderCell> | ||
<Table.HeaderCell>CR</Table.HeaderCell> | ||
<Table.HeaderCell>NR</Table.HeaderCell> | ||
{anyOddRank && <Table.HeaderCell />} | ||
</Table.Row> | ||
</Table.Header> | ||
<Table.Body> | ||
{events.official.map((event) => ( | ||
<EventData | ||
key={event.id} | ||
event={event.id} | ||
person={person} | ||
anyOdd={anyOddRank} | ||
/> | ||
))} | ||
</Table.Body> | ||
</Table> | ||
); | ||
} |
Oops, something went wrong.