## Summary
- Fixed translation key format compatibility with next-intl
- Fixed pluralization format from i18next to next-intl format
- Fixed dynamic translation key error handling
- Updated server components to match API response structure
- Fixed useSearchParams import location
## Changes
- Changed pluralization from `{{count}} items` to `{count} items` format
- Added proper error handling for missing translation keys
- Fixed import paths for next-intl hooks
- Fixed PartyPageClient trying to set non-existent appState.parties
## Test plan
- [x] Verified translations render correctly
- [x] Tested pluralization works with different counts
- [x] Confirmed no console errors about missing translations
- [x] Tested party page functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
113 lines
2.5 KiB
TypeScript
113 lines
2.5 KiB
TypeScript
import React, { ComponentProps, PropsWithChildren } from 'react'
|
|
import { useTranslations } from 'next-intl'
|
|
import classNames from 'classnames'
|
|
import { CommandItem } from '~components/common/Command'
|
|
import styles from './index.module.scss'
|
|
|
|
interface Props extends ComponentProps<'div'> {
|
|
className?: string
|
|
icon?: {
|
|
alt: string
|
|
src: string
|
|
}
|
|
extra: boolean
|
|
selected: boolean
|
|
tabIndex?: number
|
|
value: string | number
|
|
onSelect: () => void
|
|
onArrowKeyPressed?: (direction: 'Up' | 'Down') => void
|
|
onEscapeKeyPressed?: () => void
|
|
}
|
|
|
|
const placeholderSlugs = [
|
|
'all',
|
|
'farming',
|
|
'three-gauge',
|
|
'five-gauge',
|
|
'ex-plus',
|
|
'nm90',
|
|
'nm95',
|
|
'nm100',
|
|
'nm150',
|
|
'nm200',
|
|
'1-star',
|
|
'2-star',
|
|
'3-star',
|
|
'4-star',
|
|
'5-star',
|
|
'db95',
|
|
'db135',
|
|
'db175',
|
|
]
|
|
const RaidItem = React.forwardRef<HTMLDivElement, PropsWithChildren<Props>>(
|
|
function Item(
|
|
{
|
|
icon,
|
|
value,
|
|
extra,
|
|
selected,
|
|
tabIndex,
|
|
children,
|
|
onEscapeKeyPressed,
|
|
onArrowKeyPressed,
|
|
...props
|
|
}: PropsWithChildren<Props>,
|
|
forwardedRef
|
|
) {
|
|
const t = useTranslations('common')
|
|
|
|
const classes = classNames({
|
|
raid: true,
|
|
[styles.item]: true,
|
|
})
|
|
|
|
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
if (event.key === 'Escape' && onEscapeKeyPressed) {
|
|
event.preventDefault()
|
|
onEscapeKeyPressed()
|
|
}
|
|
|
|
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
|
|
event.preventDefault()
|
|
if (onArrowKeyPressed) {
|
|
onArrowKeyPressed(event.key === 'ArrowUp' ? 'Up' : 'Down')
|
|
}
|
|
}
|
|
|
|
if (event.key === 'Enter') {
|
|
event.preventDefault()
|
|
props.onSelect()
|
|
}
|
|
}
|
|
|
|
return (
|
|
<CommandItem
|
|
{...props}
|
|
className={classes}
|
|
tabIndex={tabIndex}
|
|
value={`${value}`}
|
|
onClick={props.onSelect}
|
|
onKeyDown={handleKeyDown}
|
|
ref={forwardedRef}
|
|
>
|
|
{placeholderSlugs.includes(`${value}`) ? (
|
|
<div className={styles.placeholder} />
|
|
) : (
|
|
icon && <img alt={icon.alt} src={icon.src} />
|
|
)}
|
|
<span className={styles.text}>{children}</span>
|
|
{selected && (
|
|
<i className={styles.selected}>{t('combobox.selected')}</i>
|
|
)}
|
|
{extra && <i className={styles.extraIndicator}>EX</i>}
|
|
</CommandItem>
|
|
)
|
|
}
|
|
)
|
|
|
|
RaidItem.defaultProps = {
|
|
extra: false,
|
|
selected: false,
|
|
}
|
|
|
|
export default RaidItem
|