Skip to content

Commit

Permalink
Add senator mouseover summary (#442)
Browse files Browse the repository at this point in the history
* Add senator summary

Add a senator summary. This is a MUI Popover that appears when hovering over a senator portrait. It shows their faction, titles and some attributes.

* Make Popover render conditional

Make the senator summary Popover render conditional. This will potentially improve performance.
  • Loading branch information
iamlogand authored Mar 15, 2024
1 parent aac601f commit 6583c87
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 66 deletions.
10 changes: 7 additions & 3 deletions frontend/components/AttributeFlex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ interface AttributeGridProps {
attributes: Attribute[]
}

const getAttributeItem = (item: Attribute, darkMode: boolean, index?: number) => {

const getAttributeItem = (
item: Attribute,
darkMode: boolean,
index?: number
) => {
const titleCaseName = capitalize(item.name)
return (
<Tooltip key={index} title={titleCaseName} arrow>
Expand Down Expand Up @@ -53,7 +56,8 @@ const AttributeFlex = ({ attributes }: AttributeGridProps) => {
const { darkMode } = useCookieContext()

const getButton = (item: Attribute, index: number) => {
if (item.onClick === undefined) return getAttributeItem(item, darkMode, index)
if (item.onClick === undefined)
return getAttributeItem(item, darkMode, index)
return (
<button
key={index}
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/FactionListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const FactionListItem = (props: FactionListItemProps) => {
senator={senator}
size={80}
selectable
nameTooltip
summary
blurryPlaceholder
/>
))}
Expand Down
5 changes: 2 additions & 3 deletions frontend/components/GamePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ const GamePage = (props: GamePageProps) => {
latestActions,
setLatestActions,
} = useGameContext()


// Set game-specific state using initial data
useEffect(() => {
Expand Down Expand Up @@ -626,10 +625,10 @@ const GamePage = (props: GamePageProps) => {
)
)
}
}, [latestActions, latestStep])
}, [latestActions, setLatestActions, latestStep])

const handleMainTabChange = (
event: React.SyntheticEvent,
_: React.SyntheticEvent,
newValue: number
) => {
setMainTab(newValue)
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/SenateSeat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const SenateSeat = ({ angle, radius, size, senator }: SenateSeatProps) => {
size={size}
selectable
round
nameTooltip
summary
/>
</div>
</div>
Expand Down
71 changes: 71 additions & 0 deletions frontend/components/SenatorFactionAndFacts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import Faction from "@/classes/Faction"
import { useGameContext } from "@/contexts/GameContext"
import FactionLink from "@/components/FactionLink"
import Senator from "@/classes/Senator"
import SenatorFactList from "@/components/SenatorFactList"
import FactionIcon from "./FactionIcon"

interface SenatorFactionAndFactsProps {
senator: Senator
selectable?: boolean
}

const SenatorFactionAndFacts = ({
senator,
selectable,
}: SenatorFactionAndFactsProps) => {
const { allFactions, allTitles } = useGameContext()

// Get senator-specific data
const faction: Faction | null = senator?.faction
? allFactions.byId[senator.faction] ?? null
: null
const isFactionLeader: boolean = senator
? allTitles.asArray.some(
(t) => t.senator === senator.id && t.name == "Faction Leader"
)
: false

// Get JSX for the faction description
const getFactionDescription = () => {
if (!faction) return null
return (
<span className="ml-px">
{selectable ? (
<FactionLink faction={faction} includeIcon={true} />
) : (
<span>
<span style={{ marginRight: 4 }}>
<FactionIcon faction={faction} size={17} />
</span>
{faction.getName()} Faction
</span>
)}
{isFactionLeader ? " Leader" : " Member"}
</span>
)
}

return (
<div className="flex flex-col gap-4">
<p>
{faction && senator.alive ? (
<span>{getFactionDescription()}</span>
) : senator.alive ? (
"Unaligned"
) : (
<span>
{faction ? (
<span>Died as {getFactionDescription()}</span>
) : (
"Was always Unaligned"
)}
</span>
)}
</p>
<SenatorFactList senator={senator} selectable={selectable} />
</div>
)
}

export default SenatorFactionAndFacts
9 changes: 6 additions & 3 deletions frontend/components/SenatorLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Link } from "@mui/material"
import { useGameContext } from "@/contexts/GameContext"
import Senator from "@/classes/Senator"
import SelectedDetail from "@/types/SelectedDetail"
import SenatorSummary from "@/components/SenatorSummary"

interface SenatorLinkProps {
senator: Senator
Expand All @@ -26,9 +27,11 @@ const SenatorLink = ({ senator }: SenatorLinkProps) => {
return <span>{senator.displayName}</span>

return (
<Link href="#" onClick={handleClick} sx={{ verticalAlign: "baseline" }}>
{senator.displayName}
</Link>
<SenatorSummary senator={senator}>
<Link href="#" onClick={handleClick} sx={{ verticalAlign: "baseline" }}>
{senator.displayName}
</Link>
</SenatorSummary>
)
}

Expand Down
20 changes: 9 additions & 11 deletions frontend/components/SenatorPortrait.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useEffect, useState } from "react"
import { useState, MouseEvent } from "react"
import Image, { StaticImageData } from "next/image"
import { Tooltip } from "@mui/material"

import Senator from "@/classes/Senator"
import Faction from "@/classes/Faction"
import styles from "./SenatorPortrait.module.css"
import styles from "@/components/SenatorPortrait.module.css"
import Title from "@/classes/Title"
import TitleIcon from "@/components/TitleIcon"
import SelectedDetail from "@/types/SelectedDetail"
Expand All @@ -12,7 +13,7 @@ import FactionLeaderPattern from "@/images/patterns/factionLeader.svg"
import DeadIcon from "@/images/icons/dead.svg"
import { useGameContext } from "@/contexts/GameContext"
import Collection from "@/classes/Collection"
import { Tooltip } from "@mui/material"
import SenatorSummary from "@/components/SenatorSummary"

import Cornelius from "@/images/portraits/cornelius.png"
import Fabius from "@/images/portraits/fabius.png"
Expand Down Expand Up @@ -63,7 +64,7 @@ interface SenatorPortraitProps {
senator: Senator
size: number
selectable?: boolean
nameTooltip?: boolean
summary?: boolean
blurryPlaceholder?: boolean
round?: boolean
}
Expand All @@ -74,7 +75,7 @@ const SenatorPortrait = ({
senator,
size,
selectable,
nameTooltip,
summary,
blurryPlaceholder,
round,
}: SenatorPortraitProps) => {
Expand Down Expand Up @@ -216,6 +217,7 @@ const SenatorPortrait = ({

// Get JSX for the portrait
const PortraitElement = selectable ? "button" : "div"

const getPortrait = () => (
<PortraitElement
className={`select-none ${styles.senatorPortrait} ${
Expand Down Expand Up @@ -301,12 +303,8 @@ const SenatorPortrait = ({
</PortraitElement>
)

if (nameTooltip) {
return (
<Tooltip title={senator.displayName} arrow>
{getPortrait()}
</Tooltip>
)
if (summary) {
return <SenatorSummary senator={senator}>{getPortrait()}</SenatorSummary>
} else {
return getPortrait()
}
Expand Down
79 changes: 79 additions & 0 deletions frontend/components/SenatorSummary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { MouseEvent, ReactNode, useState } from "react"
import Senator from "@/classes/Senator"
import { Popover } from "@mui/material"
import AttributeFlex, { Attribute } from "@/components/AttributeFlex"
import InfluenceIcon from "@/images/icons/influence.svg"
import TalentsIcon from "@/images/icons/talents.svg"
import VotesIcon from "@/images/icons/votes.svg"
import SenatorFactionAndFacts from "@/components/SenatorFactionAndFacts"

interface SenatorSummaryProps {
senator: Senator
children: ReactNode
}

const SenatorSummary = ({ senator, children }: SenatorSummaryProps) => {
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)
const handleOpen = (event: MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget)
}
const handleClose = () => {
setAnchorEl(null)
}
const open = Boolean(anchorEl)

// Attribute data
const attributeItems: Attribute[] = [
{
name: "influence",
value: senator.influence,
icon: InfluenceIcon,
},
{ name: "talents", value: senator.talents, icon: TalentsIcon },
{ name: "votes", value: senator.votes, icon: VotesIcon },
]

return (
<>
<div
onMouseEnter={handleOpen}
onMouseLeave={handleClose}
className="inline"
>
{children}
</div>
{open && (
<Popover
sx={{
pointerEvents: "none",
marginTop: "4px",
}}
open={open}
anchorEl={anchorEl}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
transformOrigin={{
vertical: "top",
horizontal: "center",
}}
onClose={handleClose}
disableRestoreFocus
>
<div className="py-3 px-4 max-w-[260px] flex flex-col gap-4">
<p className="font-semibold w-full text-center">
{senator.displayName}
</p>
<SenatorFactionAndFacts senator={senator} />
<div className="flex justify-center">
<AttributeFlex attributes={attributeItems}></AttributeFlex>
</div>
</div>
</Popover>
)}
</>
)
}

export default SenatorSummary
10 changes: 4 additions & 6 deletions frontend/components/WarStrength.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react"
import { useState, MouseEvent } from "react"
import EnemyLeader from "@/classes/EnemyLeader"
import War from "@/classes/War"
import { useGameContext } from "@/contexts/GameContext"
Expand All @@ -12,8 +12,8 @@ interface WarStrengthProps {
const WarStrength = ({ war, type }: WarStrengthProps) => {
const { wars, enemyLeaders } = useGameContext()

const [anchorEl, setAnchorEl] = React.useState<HTMLElement | null>(null)
const handlePopoverOpen = (event: React.MouseEvent<HTMLElement>) => {
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)
const handlePopoverOpen = (event: MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget)
}
const handlePopoverClose = () => {
Expand Down Expand Up @@ -76,9 +76,7 @@ const WarStrength = ({ war, type }: WarStrengthProps) => {
<div className="py-3 px-4 flex flex-col gap-1">
<p>
Base {capitalize(type)} Strength{" "}
<span className="font-bold">
{baseStrength}
</span>
<span className="font-bold">{baseStrength}</span>
</p>
{matchingActiveWars.length > 0 &&
matchingActiveWars.map((matchingWar) => (
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/entityDetails/EntityDetail_Faction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ const FactionDetails = () => {
senator={senator}
size={90}
selectable
nameTooltip
summary
/>
))}
</div>
Expand Down
Loading

0 comments on commit 6583c87

Please sign in to comment.