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

GO: Builds indicator for artifacts #2620

Merged
merged 10 commits into from
Jan 26, 2025
5 changes: 4 additions & 1 deletion libs/gi/localization/assets/locales/en/artifact.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,8 @@
"rvSliderBtn": {
"maximum": "MRV",
"current": "RV"
}
},
"builds_one": "{{count}} Build",
"builds_other": "{{count}} Builds",
"artifactUsage": "Artifact is used in the following builds: "
}
96 changes: 91 additions & 5 deletions libs/gi/ui/src/components/artifact/ArtifactCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client'
// use client due to hydration difference between client rendering and server in translation
import { useBoolState } from '@genshin-optimizer/common/react-util'
import { iconInlineProps } from '@genshin-optimizer/common/svgicons'
import {
BootstrapTooltip,
Expand All @@ -8,7 +9,9 @@ import {
ConditionalWrapper,
InfoTooltip,
InfoTooltipInline,
ModalWrapper,
NextImage,
SqBadge,
StarsDisplay,
} from '@genshin-optimizer/common/ui'
import { clamp, clamp01, getUnitStr } from '@genshin-optimizer/common/util'
Expand All @@ -23,7 +26,7 @@ import {
allSubstatKeys,
} from '@genshin-optimizer/gi/consts'
import type { ICachedArtifact, ICachedSubstat } from '@genshin-optimizer/gi/db'
import { useArtifact } from '@genshin-optimizer/gi/db-ui'
import { useArtifact, useDatabase } from '@genshin-optimizer/gi/db-ui'
import { SlotIcon, StatIcon } from '@genshin-optimizer/gi/svgicons'
import {
artDisplayValue,
Expand All @@ -40,16 +43,20 @@ import {
Button,
CardActionArea,
CardContent,
CardHeader,
Chip,
IconButton,
List,
ListItem,
ListItemText,
Skeleton,
SvgIcon,
Typography,
} from '@mui/material'
import type { ReactNode } from 'react'
import { Suspense, useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { ExcludeIcon } from '../../consts'
import { CloseIcon, ExcludeIcon } from '../../consts'
import { PercentBadge } from '../PercentBadge'
import { LocationAutocomplete, LocationName } from '../character'
import { ArtifactSetTooltipContent } from './ArtifactSetTooltip'
Expand Down Expand Up @@ -96,7 +103,7 @@ export function ArtifactCardObj({
} & Data) {
const { t } = useTranslation(['artifact', 'ui'])
const { t: tk } = useTranslation('statKey_gen')

const [showUsage, onShowUsage, onHideUsage] = useBoolState(false)
const wrapperFunc = useCallback(
(children: ReactNode) => (
<CardActionArea
Expand Down Expand Up @@ -153,7 +160,17 @@ export function ArtifactCardObj({
Math.min(mainStatAssumptionLevel, rarity * 4),
level
)

const database = useDatabase()
const { buildNames, numberOfBuilds } = useMemo(() => {
failchon marked this conversation as resolved.
Show resolved Hide resolved
const names: string[] = []
const builds = database.builds.data
failchon marked this conversation as resolved.
Show resolved Hide resolved
for (const buildId in builds) {
if (builds[buildId]?.artifactIds[artifact.slotKey] === artifact.id) {
names.push(builds[buildId].name)
}
}
return { buildNames: names, numberOfBuilds: names.length }
}, [database.builds.data, artifact.slotKey, artifact.id])
const artifactValid = maxEfficiency !== 0
const slotName = <ArtifactSetSlotName setKey={setKey} slotKey={slotKey} />
const slotDesc = <ArtifactSetSlotDesc setKey={setKey} slotKey={slotKey} />
Expand All @@ -178,6 +195,14 @@ export function ArtifactCardObj({
/>
}
>
<Suspense fallback={false}>
<ArtifactBuildUsageModal
show={showUsage}
onHide={onHideUsage}
buildNames={buildNames}
usageText={t('artifact:artifactUsage')}
/>
</Suspense>
<CardThemed
bgt="light"
sx={{ height: '100%', display: 'flex', flexDirection: 'column' }}
Expand Down Expand Up @@ -350,14 +375,32 @@ export function ArtifactCardObj({
</Typography>
)}
<Box flexGrow={1} />
<Typography color="success.main">
<Typography
color="success.main"
sx={{
display: 'flex',
gap: 1,
alignItems: 'center',
mt: 1,
}}
>
{(setKey && <ArtifactSetName setKey={setKey} />) ||
'Artifact Set'}{' '}
{setKey && (
<InfoTooltipInline
title={<ArtifactSetTooltipContent setKey={setKey} />}
/>
)}
<SqBadge
sx={{
ml: 'auto',
cursor: numberOfBuilds ? 'pointer' : 'default',
}}
color={numberOfBuilds ? 'success' : 'secondary'}
onClick={numberOfBuilds ? onShowUsage : undefined}
>
{t('builds', { count: numberOfBuilds })}
</SqBadge>
</Typography>
</CardContent>
</ConditionalWrapper>
Expand Down Expand Up @@ -488,3 +531,46 @@ function SubstatDisplay({
</Box>
)
}

function ArtifactBuildUsageModal({
show,
onHide,
buildNames,
usageText,
}: {
show: boolean
onHide: () => void
buildNames: string[]
usageText: string
}) {
return (
<ModalWrapper open={show} onClose={onHide}>
<CardThemed>
<CardHeader
title={
<Typography
variant="h6"
flexGrow={1}
display="flex"
alignItems="center"
>
{usageText}
</Typography>
}
action={
<IconButton onClick={onHide}>
<CloseIcon />
</IconButton>
}
/>
<List>
{buildNames.map((name, index) => (
<ListItem key={index}>
<ListItemText primary={name} />
failchon marked this conversation as resolved.
Show resolved Hide resolved
</ListItem>
))}
</List>
</CardThemed>
</ModalWrapper>
)
}
Loading