Replace version page with supply event page

This commit is contained in:
Sakura Knoll
2021-12-27 23:26:24 +09:00 Unverified
parent 9cd2f1a5ce
commit 123ac57643
38 changed files with 551 additions and 460 deletions
+176
View File
@@ -0,0 +1,176 @@
import { Box, Flex, Text } from '@theme-ui/components'
import {
differenceInCalendarDays,
differenceInCalendarWeeks,
format,
} from 'date-fns'
import { times } from 'ramda'
import { useMemo, MouseEventHandler } from 'react'
export interface GanttChartItem {
id: string
row: number
duration: [string, string]
label: React.ReactNode
onClick?: MouseEventHandler<HTMLDivElement>
}
interface GanttChartProps {
startDate: string
endDate: string
today: string
items: GanttChartItem[]
}
const GanttChart = ({
startDate: startDateString,
endDate: endDateString,
today: todayDateString,
items,
}: GanttChartProps) => {
const startDate = new Date(startDateString)
const endDate = new Date(endDateString)
const todayDate = new Date(todayDateString)
const totalDays = differenceInCalendarDays(endDate, startDate)
const totalWeeks = differenceInCalendarWeeks(endDate, startDate)
const totalRow = useMemo(() => {
return items.reduce((max, item) => {
return item.row > max ? item.row : max
}, 1)
}, [])
return (
<Box mb={3} sx={{ width: totalWeeks * 280 }}>
<Flex
sx={{
marginLeft: -20,
}}
>
{times((index) => {
const weekNumber = index + 1
return (
<Box
key={`week-${weekNumber}`}
sx={{
width: 280,
textAlign: 'center',
fontWeight: 700,
}}
>
Week {weekNumber}
</Box>
)
}, totalWeeks)}
</Flex>
<Box
sx={{
position: 'relative',
height: totalRow * 50 + 40,
borderBottomStyle: 'solid',
borderBottomWidth: 1,
borderBottomColor: 'gray.5',
borderTopStyle: 'solid',
borderTopWidth: 1,
borderTopColor: 'gray.5',
}}
>
{times((index) => {
return (
<Box
sx={{
position: 'absolute',
height: totalRow * 50 + 40,
borderRightStyle: 'solid',
borderRightWidth: 1,
borderRightColor: index % 7 === 6 ? 'gray.5' : 'gray.3',
left: (index + 1) * 40 - 1 - 20,
}}
/>
)
}, totalDays)}
<Box
sx={{
boxSizing: 'border-box',
position: 'absolute',
width: 40,
height: totalRow * 50 + 40,
backgroundColor: 'blue.5',
borderStyle: 'solid',
borderColor: 'blue.7',
opacity: 0.2,
zIndex: 20,
borderRadius: 4,
left: differenceInCalendarDays(todayDate, startDate) * 40 - 20,
pointerEvents: 'none',
}}
/>
<Text
sx={{
position: 'absolute',
color: 'blue.7',
transform: 'rotate(90deg)',
zIndex: 21,
top: 150,
left:
differenceInCalendarDays(new Date(todayDate), startDate) * 40 -
150,
width: 300,
pointerEvents: 'none',
}}
>
Today ({format(todayDate, 'P')})
</Text>
{items.map((item) => {
const offset =
differenceInCalendarDays(new Date(item.duration[0]), startDate) * 40
const length =
differenceInCalendarDays(
new Date(item.duration[1]),
new Date(item.duration[0])
) * 40
return (
<Flex
key={item.id}
py={2}
px={3}
sx={{
boxSizing: 'border-box',
position: 'absolute',
borderColor: 'gray.5',
borderWidth: 1,
borderStyle: 'solid',
backgroundColor: 'white',
width: length,
left: offset,
top: (item.row - 1) * 50 + 20,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
height: 40,
borderRadius: 40,
fontWeight: 700,
zIndex: 10,
'&:hover': {
minWidth: length,
width: 'inherit',
zIndex: 25,
boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
transition: 'box-shadow 200ms ease-in-out',
},
}}
>
{item.label}
</Flex>
)
})}
</Box>
</Box>
)
}
export default GanttChart
@@ -16,6 +16,11 @@ const Honkai3rdNavigator = () => {
</NextLink>
</Heading>
</Flex>
<NextLink href='/honkai3rd/versions' passHref>
<NavLink mr={3} sx={{ fontFamily: 'monospace' }}>
Versions
</NavLink>
</NextLink>
<Flex sx={{ height: 40, alignItems: 'center' }}>
<NextLink href='/honkai3rd/battlesuits' passHref>
<NavLink mr={3} sx={{ fontFamily: 'monospace' }}>
+14 -40
View File
@@ -1,6 +1,6 @@
import { readdirSync, readJsonFileSync } from '../../lib/data'
export interface SupplyEvent {
export interface SupplyEventData {
id: string
verified: boolean
track: number
@@ -33,46 +33,20 @@ export interface SupplyEvent {
}[]
}
const supplyEventFileNameList = readdirSync('supply-events/global-americas')
const supplyEventFileList = supplyEventFileNameList
.map((fileName) => {
const filePathname = 'supply-events/global-americas/' + fileName
const data = readJsonFileSync(filePathname)
export function listSupplyEventsByVersion(version: string) {
const supplyEventsDirectoryPathname = `versions/${version}/supply-events`
return { ...data, id: fileName.replace(/\.json/, '') } as SupplyEvent
})
.sort((a, b) => {
return -a.id.localeCompare(b.id)
})
const supplyEventFileNameList = readdirSync(supplyEventsDirectoryPathname)
const supplyEventList = supplyEventFileNameList
.map((fileName) => {
const filePathname = `${supplyEventsDirectoryPathname}/` + fileName
const data = readJsonFileSync(filePathname)
const supplyEventMap = supplyEventFileList.reduce((map, stigmata) => {
map.set(stigmata.id, stigmata)
return map
}, new Map<string, SupplyEvent>())
return { ...data, id: fileName.replace(/\.json/, '') } as SupplyEventData
})
.sort((a, b) => {
return -a.id.localeCompare(b.id)
})
const versionSupplyEventListMap = supplyEventFileList.reduce(
(map, supplyEvent) => {
let supplyEvents = map.get(supplyEvent.version)
if (supplyEvents == null) {
supplyEvents = []
map.set(supplyEvent.version, supplyEvents)
}
supplyEvents.push(supplyEvent)
return map
},
new Map<number, SupplyEvent[]>()
)
export function listSupplyEvents() {
return supplyEventFileList
}
export function getSupplyEventById(id: string) {
return supplyEventMap.get(id)
}
export function getSupplyEventListByVersion(version: number) {
return versionSupplyEventListMap.get(version) || []
return supplyEventList
}
+52
View File
@@ -0,0 +1,52 @@
import { format } from 'date-fns'
import { readdirSync, readFileSync, readJsonFileSync } from '../../lib/data'
import { compareVersion } from '../../lib/string'
export interface VersionData {
version: string
name: string
duration: [string, string]
verified: boolean
newBattlesuits: string[]
newWeapons: string[]
description: string
}
const versionDirectoryList = readdirSync('versions')
const versionDataList = versionDirectoryList
.map((directoryName) => {
const directoryPathname = 'versions/' + directoryName
const data: VersionData = {
version: directoryName,
...readJsonFileSync(directoryPathname + '/version-data.json'),
description: readFileSync(
directoryPathname + '/description.md'
).toString(),
}
return data
})
.sort((a, b) => {
return compareVersion(b.version, a.version)
})
export function listVersionData() {
return versionDataList
}
export function getVersion(version: number | string) {
return versionDataList.find((versionData) => {
return versionData.version.toString() === version.toString()
})
}
export function getCurrentVersion() {
const todayDateString = format(new Date(), 'yyyy-MM-dd')
return versionDataList.find((versionData) => {
const [startDateString] = versionData.duration
return startDateString.localeCompare(todayDateString) < 0
})
}
+22
View File
@@ -0,0 +1,22 @@
export function isVersionString(version: string): boolean {
return /[0-9]+\.[0-9]+(\.[0-9]+)?/.test(version)
}
export function compareVersion(aVersion: string, bVersion: string): number {
const [aMajor, aMinor = '0', aPatch = '0'] = aVersion.split('.')
const [bMajor, bMinor = '0', bPatch = '0'] = bVersion.split('.')
let result = parseInt(aMajor, 10) - parseInt(bMajor, 10)
if (result !== 0) {
return result
}
result = parseInt(aMinor, 10) - parseInt(bMinor, 10)
if (result !== 0) {
return result
}
return parseInt(aPatch, 10) - parseInt(bPatch, 10)
}
-420
View File
@@ -1,420 +0,0 @@
/** @jsxImportSource theme-ui */
import { Text, Box, Heading, Link, Flex } from '@theme-ui/components'
import NextLink from 'next/link'
import Breadcrumb from '../../../components/organisms/Breadcrumb'
import Honkai3rdNavigator from '../../../components/organisms/Honkai3rdNavigator'
import { pick, times } from 'ramda'
import {
listSupplyEvents,
SupplyEvent,
} from '../../../data/honkai3rd/supply-events'
import { getStigmataById, StigmataData } from '../../../data/honkai3rd/stigmata'
import { getWeaponById, WeaponData } from '../../../data/honkai3rd/weapons'
import {
BattlesuitData,
getBattlesuitById,
} from '../../../data/honkai3rd/battlesuits'
import { ElfData, getElfById } from '../../../data/honkai3rd/elfs'
import {
format as formatDate,
differenceInCalendarDays,
differenceInCalendarWeeks,
format,
} from 'date-fns'
import SquareImageBox from '../../../components/atoms/SquareImageBox'
import { useMemo } from 'react'
type ObjectMap<T> = { [key: string]: T }
type StigmataObjectMap = ObjectMap<Pick<StigmataData, 'id' | 'name'>>
type WeaponObjectMap = ObjectMap<Pick<WeaponData, 'id' | 'name'>>
type BattlesuitObjectMap = ObjectMap<Pick<BattlesuitData, 'id' | 'name'>>
type ElfObjectMap = ObjectMap<Pick<ElfData, 'id' | 'name'>>
interface SupplyEventListPageProps {
supplyEventList: Pick<
SupplyEvent,
'id' | 'version' | 'name' | 'featured' | 'duration' | 'track' | 'verified'
>[]
stigmataObjectMap: StigmataObjectMap
weaponObjectMap: WeaponObjectMap
battlesuitObjectMap: BattlesuitObjectMap
elfObjectMap: ElfObjectMap
}
const SupplyEventListPage = ({
supplyEventList,
battlesuitObjectMap,
weaponObjectMap,
stigmataObjectMap,
elfObjectMap,
}: SupplyEventListPageProps) => {
const startDate = new Date('2021-12-02')
const endDate = new Date('2022-01-13')
const todayDate = new Date(formatDate(new Date(), 'yyyy-MM-dd'))
const totalDays = differenceInCalendarDays(endDate, startDate)
const totalWeeks = differenceInCalendarWeeks(endDate, startDate)
const totalRow = useMemo(() => {
return supplyEventList.reduce((max, supplyEvent) => {
return supplyEvent.track > max ? supplyEvent.track : max
}, 1)
}, [])
return (
<Box>
<Honkai3rdNavigator />
<Box p={3}>
<Breadcrumb
items={[
{ href: '/honkai3rd', label: 'Honkai 3rd' },
{ href: '/honkai3rd/supply-events', label: 'Supply Events' },
]}
/>
<Heading as='h1' mb={3}>
Supply Events
</Heading>
<Box mb={3} sx={{ width: totalWeeks * 280 }}>
<Flex
sx={{
marginLeft: -20,
}}
>
{times((index) => {
const weekNumber = index + 1
return (
<Box
key={`week-${weekNumber}`}
sx={{
width: 280,
textAlign: 'center',
fontWeight: 700,
}}
>
Week {weekNumber}
</Box>
)
}, totalWeeks)}
</Flex>
<Box
sx={{
position: 'relative',
height: totalRow * 50 + 40,
borderBottomStyle: 'solid',
borderBottomWidth: 1,
borderBottomColor: 'gray.5',
borderTopStyle: 'solid',
borderTopWidth: 1,
borderTopColor: 'gray.5',
}}
>
{times((index) => {
return (
<Box
sx={{
position: 'absolute',
height: totalRow * 50 + 40,
borderRightStyle: 'solid',
borderRightWidth: 1,
borderRightColor: index % 7 === 6 ? 'gray.5' : 'gray.3',
left: (index + 1) * 40 - 1 - 20,
}}
/>
)
}, totalDays)}
<Box
sx={{
boxSizing: 'border-box',
position: 'absolute',
width: 40,
height: totalRow * 50 + 40,
backgroundColor: 'blue.5',
borderStyle: 'solid',
borderColor: 'blue.7',
opacity: 0.2,
zIndex: 20,
borderRadius: 4,
left: differenceInCalendarDays(todayDate, startDate) * 40 - 20,
pointerEvents: 'none',
}}
/>
<Text
sx={{
position: 'absolute',
color: 'blue.7',
transform: 'rotate(90deg)',
zIndex: 21,
top: 150,
left:
differenceInCalendarDays(new Date(todayDate), startDate) *
40 -
150,
width: 300,
pointerEvents: 'none',
}}
>
Today ({format(todayDate, 'P')})
</Text>
{supplyEventList
.slice()
.reverse()
.map((supplyEvent) => {
const offset =
differenceInCalendarDays(
new Date(supplyEvent.duration[0]),
startDate
) * 40
const length =
differenceInCalendarDays(
new Date(supplyEvent.duration[1]),
new Date(supplyEvent.duration[0])
) * 40
const featuredIconProps = getIconPropsOfItem(
supplyEvent.featured[0],
{
battlesuitObjectMap,
weaponObjectMap,
stigmataObjectMap,
elfObjectMap,
}
)
return (
<Flex
key={supplyEvent.id}
py={2}
px={3}
sx={{
boxSizing: 'border-box',
position: 'absolute',
borderColor: 'gray.5',
borderWidth: 1,
borderStyle: 'solid',
backgroundColor: 'white',
width: length,
left: offset,
top: (supplyEvent.track - 1) * 50 + 20,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
height: 40,
borderRadius: 40,
fontWeight: 700,
zIndex: 10,
'&:hover': {
minWidth: length,
width: 'inherit',
zIndex: 25,
boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
transition: 'box-shadow 200ms ease-in-out',
},
}}
>
{featuredIconProps != null && (
<SquareImageBox
size={20}
src={featuredIconProps.src}
alt={featuredIconProps.alt}
mr={2}
/>
)}
<Text
sx={{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{supplyEvent.name}
{!supplyEvent.verified && ' (❓)'}
</Text>
</Flex>
)
})}
</Box>
</Box>
<Box>
{supplyEventList.map((supplyEvent) => {
return (
<Box key={supplyEvent.id}>
<Box mb={3}>
<Heading>
<NextLink
href={`/honkai3rd/supply-events/${supplyEvent.id}`}
key={supplyEvent.id}
passHref={true}
>
<Link>
[{supplyEvent.version}] {supplyEvent.name} (
{supplyEvent.duration.join(' ~ ')})
</Link>
</NextLink>
</Heading>
<Flex>
{supplyEvent.featured.map((item) => {
const props = getIconPropsOfItem(item, {
battlesuitObjectMap,
weaponObjectMap,
stigmataObjectMap,
elfObjectMap,
})
if (props == null) {
return (
<Text>
{item.type} : {item.id}
</Text>
)
}
return (
<SquareImageBox
key={`${item.type}/${item.id}`}
mr={2}
size={50}
src={props.src}
alt={props.alt}
/>
)
})}
</Flex>
</Box>
</Box>
)
})}
</Box>
</Box>
</Box>
)
}
export default SupplyEventListPage
export async function getStaticProps() {
const supplyEventList = listSupplyEvents()
const stigmataObjectMap: {
[key: string]: Pick<StigmataData, 'id' | 'name'>
} = {}
const weaponObjectMap: {
[key: string]: Pick<WeaponData, 'id' | 'name'>
} = {}
const battlesuitObjectMap: {
[key: string]: Pick<BattlesuitData, 'id' | 'name'>
} = {}
const elfObjectMap: {
[key: string]: Pick<ElfData, 'id' | 'name'>
} = {}
supplyEventList.forEach((supplyEvent) => {
supplyEvent.featured.forEach((item) => {
switch (item.type) {
case 'battlesuit':
const battlesuit = getBattlesuitById(item.id)
if (battlesuit != null) {
battlesuitObjectMap[battlesuit.id] = pick(
['id', 'name'],
battlesuit
)
}
break
case 'weapon':
const weapon = getWeaponById(item.id)
if (weapon != null) {
weaponObjectMap[weapon.id] = pick(['id', 'name'], weapon)
}
break
case 'stigmata':
const stigmata = getStigmataById(item.id)
if (stigmata != null) {
stigmataObjectMap[stigmata.id] = pick(['id', 'name'], stigmata)
}
break
case 'elf':
const elf = getElfById(item.id)
if (elf != null) {
elfObjectMap[elf.id] = pick(['id', 'name'], elf)
}
break
}
})
})
return {
props: {
supplyEventList: supplyEventList.map((supplyEvent) => {
return pick(
[
'id',
'version',
'name',
'featured',
'duration',
'track',
'verified',
],
supplyEvent
)
}),
battlesuitObjectMap,
weaponObjectMap,
stigmataObjectMap,
elfObjectMap,
},
revalidate: true,
}
}
function getIconPropsOfItem(
item: { type: string; id: string },
{
battlesuitObjectMap,
weaponObjectMap,
stigmataObjectMap,
elfObjectMap,
}: {
stigmataObjectMap: StigmataObjectMap
weaponObjectMap: WeaponObjectMap
battlesuitObjectMap: BattlesuitObjectMap
elfObjectMap: ElfObjectMap
}
): { src: string; alt: string } | null {
switch (item.type) {
case 'battlesuit':
const battlesuit = battlesuitObjectMap[item.id]
if (battlesuit != null) {
return {
src: `/assets/honkai3rd/battlesuits/portrait-${battlesuit.id}.png`,
alt: battlesuit.name,
}
}
case 'weapon':
const weapon = weaponObjectMap[item.id]
if (weapon != null) {
return {
src: `/assets/honkai3rd/weapons/${weapon.id}.png`,
alt: weapon.name,
}
}
case 'stigmata':
const stigmata = stigmataObjectMap[item.id]
if (stigmata != null) {
return {
src: `/assets/honkai3rd/stigmata/icon-${stigmata.id}.png`,
alt: stigmata.name,
}
}
case 'elf':
const elf = elfObjectMap[item.id]
if (elf != null) {
return {
src: `/assets/honkai3rd/elfs/icon-${elf.id}.png`,
alt: elf.name,
}
}
}
return null
}
@@ -0,0 +1,47 @@
/** @jsxImportSource theme-ui */
import { NextPageContext } from 'next'
import {
getVersion,
listVersionData,
VersionData,
} from '../../../data/honkai3rd/versions'
interface VersionShowPageProps {
versionData: VersionData
}
const VersionShowPage = ({ versionData }: VersionShowPageProps) => {
return (
<div>
{versionData.version} : {versionData.name}
<pre>
<code>{JSON.stringify(versionData, null, 2)}</code>
</pre>
</div>
)
}
export default VersionShowPage
export async function getStaticProps({
params,
}: NextPageContext & { params: { versionId: string } }) {
return {
props: {
versionData: getVersion(params.versionId),
},
}
}
export async function getStaticPaths() {
return {
paths: listVersionData().map((versionData) => {
return {
params: {
versionId: versionData.version.toString(),
},
}
}),
fallback: false,
}
}
+218
View File
@@ -0,0 +1,218 @@
/** @jsxImportSource theme-ui */
import { Box, Flex, Heading, Link, Text } from '@theme-ui/components'
import { format } from 'date-fns'
import NextLink from 'next/link'
import SquareImageBox from '../../../components/atoms/SquareImageBox'
import Breadcrumb from '../../../components/organisms/Breadcrumb'
import GanttChart from '../../../components/organisms/GanttChart'
import Honkai3rdNavigator from '../../../components/organisms/Honkai3rdNavigator'
import {
BattlesuitData,
getBattlesuitById,
} from '../../../data/honkai3rd/battlesuits'
import {
listSupplyEventsByVersion,
SupplyEventData as SupplyEventData,
} from '../../../data/honkai3rd/supply-events'
import {
getCurrentVersion,
listVersionData,
VersionData,
} from '../../../data/honkai3rd/versions'
import { getWeaponById, WeaponData } from '../../../data/honkai3rd/weapons'
interface VersionIndexPageProps {
versionDataList: VersionData[]
currentVersionData: VersionData
currentVersionNewBattlesuits: BattlesuitData[]
currentVersionNewWeapons: WeaponData[]
currentVersionSupplyEvents: SupplyEventData[]
}
const VersionIndexPage = ({
currentVersionData,
currentVersionNewBattlesuits,
versionDataList,
currentVersionNewWeapons,
currentVersionSupplyEvents,
}: VersionIndexPageProps) => {
return (
<Box>
<Honkai3rdNavigator />
<Box p={3}>
<Breadcrumb
items={[
{ href: '/honkai3rd', label: 'Honkai 3rd' },
{ href: '/honkai3rd/versions', label: 'Versions' },
]}
/>
<Box mb={3}>
<Heading as='h2' mb={4}>
v{currentVersionData.version} : {currentVersionData.name}
<br />
<small>(Current Version)</small>
</Heading>
<Box>
<Heading as='h3'>New Battlesuits</Heading>
<Box mb={4}>
{currentVersionNewBattlesuits.map((battlesuit) => {
return (
<NextLink
href={`/honkai3rd/battlesuits/${battlesuit.id}`}
passHref
>
<Link>
<Flex sx={{ alignItems: 'center' }} mb={2}>
<SquareImageBox
size={40}
src={`/assets/honkai3rd/battlesuits/portrait-${battlesuit.id}.png`}
alt={`${battlesuit.name}`}
mr={2}
/>
<Text>{battlesuit.name}</Text>
</Flex>
</Link>
</NextLink>
)
})}
</Box>
<Heading as='h3'>New Weapons</Heading>
<Box mb={4}>
{currentVersionNewWeapons.map((weapon) => {
return (
<NextLink href={`/honkai3rd/weapons/${weapon.id}`} passHref>
<Link>
<Flex sx={{ alignItems: 'center' }} mb={2}>
<SquareImageBox
size={40}
src={`/assets/honkai3rd/weapons/${weapon.id}.png`}
alt={`${weapon.name}`}
mr={2}
/>
<Text>{weapon.name}</Text>
</Flex>
</Link>
</NextLink>
)
})}
</Box>
</Box>
<Heading as='h3'>Supply Events</Heading>
<Box mb={4}>
<GanttChart
items={currentVersionSupplyEvents.map((supplyEventData) => {
const imgSrc = getIconSrcFromItem(supplyEventData.featured[0])
return {
id: supplyEventData.id,
label: (
<Flex sx={{ alignItems: 'center' }}>
{imgSrc != null && (
<SquareImageBox
size={20}
src={imgSrc}
alt={supplyEventData.featured[0].id}
mr={1}
/>
)}
<Text>{supplyEventData.name}</Text>
</Flex>
),
duration: supplyEventData.duration,
row: supplyEventData.track,
}
})}
today={format(new Date(), 'yyyy-MM-dd')}
startDate={currentVersionData.duration[0]}
endDate={currentVersionData.duration[1]}
/>
</Box>
<Box>
<NextLink
href={`/honkai3rd/versions/${currentVersionData.version}`}
passHref
>
<Link>Learn more...</Link>
</NextLink>
</Box>
</Box>
<Heading as='h2'>All Versions</Heading>
<Box>
{versionDataList.map((versionData) => {
return (
<Box key={versionData.version}>
<Heading as='h3'>
<NextLink
href={`/honkai3rd/versions/${versionData.version}`}
passHref
>
<Link>
{versionData.version} : {versionData.name} (
{format(new Date(versionData.duration[0]), 'yyyy/MM/dd')}-
{versionData.duration[1] != null
? format(
new Date(versionData.duration[1]),
'yyyy/MM/dd'
)
: ''}
)
</Link>
</NextLink>
</Heading>
</Box>
)
})}
</Box>
</Box>
</Box>
)
}
export async function getStaticProps() {
const currentVersionData = getCurrentVersion()!
const currentVersionNewBattlesuits = currentVersionData.newBattlesuits.map(
(battlesuitId) => {
return getBattlesuitById(battlesuitId)
}
)
const currentVersionNewWeapons = currentVersionData.newWeapons.map(
(weaponId) => {
return getWeaponById(weaponId)
}
)
const currentVersionSupplyEvents = listSupplyEventsByVersion(
currentVersionData.version
)
return {
props: {
currentVersionData,
currentVersionNewBattlesuits,
currentVersionNewWeapons,
currentVersionSupplyEvents,
versionDataList: listVersionData(),
},
}
}
export default VersionIndexPage
function getIconSrcFromItem(item: { type: string; id: string }): string | null {
switch (item.type) {
case 'battlesuit':
return `/assets/honkai3rd/battlesuits/portrait-${item.id}.png`
case 'weapon':
return `/assets/honkai3rd/weapons/${item.id}.png`
case 'stigmata':
return `/assets/honkai3rd/stigmata/icon-${item.id}.png`
case 'elf':
return `/assets/honkai3rd/elfs/icon-${item.id}.png`
}
return null
}