Added signets pages
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
/** @jsxImportSource theme-ui */
|
||||
import { Card, Box, Paragraph, Heading, Flex, Text } from '@theme-ui/components'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { assetsBucketBaseUrl } from '../../lib/consts'
|
||||
import { SignetData } from '../../lib/honkai3rd/elysianRealm'
|
||||
import SquareImageBox from '../atoms/SquareImageBox'
|
||||
|
||||
interface SignetCardProps {
|
||||
signet: SignetData
|
||||
headingLevel?: 1 | 2 | 3 | 4 | 5
|
||||
m?: number
|
||||
}
|
||||
|
||||
const SignetCard = ({ signet, headingLevel = 3, m = 2 }: SignetCardProps) => {
|
||||
const [signetGroupId] = signet.id.split('-')
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<Card sx={{ mb: 2 }}>
|
||||
<Box sx={{ p: 2 }}>
|
||||
<Heading as={`h${headingLevel}`}>
|
||||
<Flex sx={{ alignItems: 'center' }}>
|
||||
<SquareImageBox
|
||||
mr={2}
|
||||
size={30}
|
||||
alt={signet.name}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/signets/${signetGroupId}.png`}
|
||||
/>
|
||||
<Text>{signet.name}</Text>
|
||||
</Flex>
|
||||
</Heading>
|
||||
<Paragraph>{signet.description}</Paragraph>
|
||||
</Box>
|
||||
<Box>
|
||||
{signet.upgrades.map((upgrade, index) => {
|
||||
return (
|
||||
<Box
|
||||
key={`${signet.id}-${index + 1}`}
|
||||
sx={{ borderTop: 'default', p: 2 }}
|
||||
>
|
||||
<Heading as={`h${headingLevel + 1}` as 'h1'}>
|
||||
{upgrade.name}
|
||||
</Heading>
|
||||
<Paragraph>{upgrade.description}</Paragraph>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
{signet.upgrades.length === 0 && (
|
||||
<Box sx={{ borderTop: 'default', p: 2 }}>
|
||||
<Text sx={{ color: 'secondary' }}>
|
||||
{t('elysian-realm.no-upgrades')}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignetCard
|
||||
@@ -0,0 +1,53 @@
|
||||
/** @jsxImportSource theme-ui */
|
||||
import { Card, Text, Flex } from '@theme-ui/components'
|
||||
import { useRouter } from 'next/router'
|
||||
import { assetsBucketBaseUrl } from '../../lib/consts'
|
||||
import { signetGroups } from '../../lib/honkai3rd/elysianRealm'
|
||||
import { translate } from '../../lib/i18n'
|
||||
import PageLink from '../atoms/PageLink'
|
||||
import SquareImageBox from '../atoms/SquareImageBox'
|
||||
|
||||
interface SignetGroupNavigatorProps {
|
||||
size?: 'sm' | 'default'
|
||||
}
|
||||
|
||||
const SignetGroupNavigator = ({
|
||||
size = 'default',
|
||||
}: SignetGroupNavigatorProps) => {
|
||||
const { locale } = useRouter()
|
||||
return (
|
||||
<Flex sx={{ flexWrap: 'wrap' }}>
|
||||
{signetGroups.map((signet) => {
|
||||
const signetName = translate(
|
||||
locale,
|
||||
{ ['ko-KR']: signet.krName },
|
||||
signet.name
|
||||
)
|
||||
return (
|
||||
<Card key={signet.id} sx={{ p: 1, m: 1 }}>
|
||||
<PageLink href={`/honkai3rd/elysian-realm/signets/${signet.id}`}>
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: size === 'default' ? 'column' : 'row',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<SquareImageBox
|
||||
size={size === 'default' ? 70 : 30}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/signets/${signet.id}.png`}
|
||||
/>
|
||||
<Text
|
||||
sx={{ textAlign: 'center', ml: size === 'default' ? 0 : 1 }}
|
||||
>
|
||||
{signetName}
|
||||
</Text>
|
||||
</Flex>
|
||||
</PageLink>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignetGroupNavigator
|
||||
@@ -0,0 +1,152 @@
|
||||
export const erVersions = [
|
||||
{
|
||||
version: '5.0',
|
||||
battlesuits: ['hfs', 'hot', 'hor', 'sn', 'aka', 'ri', 'vg', 'pv'],
|
||||
},
|
||||
{
|
||||
version: '5.1',
|
||||
battlesuits: ['mpe', 'bke', 'lk', 'stfu'],
|
||||
},
|
||||
{
|
||||
version: '5.2',
|
||||
battlesuits: ['io', 'ma', 'nyx'],
|
||||
},
|
||||
{
|
||||
version: '5.3',
|
||||
battlesuits: ['sns', 'tp', 'hos'],
|
||||
},
|
||||
{
|
||||
version: '5.4',
|
||||
battlesuits: ['sw', 'da'],
|
||||
},
|
||||
{
|
||||
version: '5.5',
|
||||
battlesuits: ['pe', 'spa'],
|
||||
},
|
||||
].reverse()
|
||||
|
||||
export const erBattlesuits = erVersions.reduce<string[]>((list, version) => {
|
||||
list.push(...version.battlesuits)
|
||||
return list
|
||||
}, [])
|
||||
|
||||
export const supportBattlesuitIds = [
|
||||
'vc',
|
||||
'dp',
|
||||
'ss',
|
||||
'le',
|
||||
'vke',
|
||||
'bke',
|
||||
'ae',
|
||||
'br',
|
||||
]
|
||||
|
||||
export const rememberanceSigilIds = [
|
||||
'the-moth-insignia',
|
||||
'home-lost',
|
||||
'false-hope',
|
||||
'tin-flask',
|
||||
'ruined-legacy',
|
||||
'burden',
|
||||
'gold-goblet',
|
||||
'mad-king-s-mask',
|
||||
'light-as-a-bodhi-leaf',
|
||||
'forget-me-not',
|
||||
'forbidden-seed',
|
||||
'memory',
|
||||
'crystal-rose',
|
||||
'abandoned',
|
||||
'good-old-days',
|
||||
'shattered-shackles',
|
||||
'heavy-as-a-million-lives',
|
||||
'stained-sakura',
|
||||
'the-first-scale',
|
||||
'resolve',
|
||||
]
|
||||
|
||||
export interface SignetData {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
upgrades: {
|
||||
name: string
|
||||
description: string
|
||||
}[]
|
||||
}
|
||||
|
||||
export interface SignetGroup {
|
||||
id: string
|
||||
name: string
|
||||
krName: string
|
||||
setIds: string[]
|
||||
}
|
||||
|
||||
export const signetGroups = [
|
||||
{
|
||||
id: 'elysia',
|
||||
name: 'Elysia',
|
||||
krName: '엘리시아',
|
||||
setIds: erBattlesuits.map((battlesuitId) => {
|
||||
return `elysia-${battlesuitId}`
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: 'eden',
|
||||
name: 'Eden',
|
||||
krName: '에덴',
|
||||
setIds: ['eden-normal', 'eden-nexus-1', 'eden-nexus-2'],
|
||||
},
|
||||
{
|
||||
id: 'hua',
|
||||
name: 'Hua',
|
||||
krName: '화',
|
||||
setIds: ['hua-normal', 'hua-nexus-1', 'hua-nexus-2'],
|
||||
},
|
||||
{
|
||||
id: 'kalpas',
|
||||
name: 'Kalpas',
|
||||
krName: '칼파스',
|
||||
setIds: ['kalpas-normal', 'kalpas-nexus-1', 'kalpas-nexus-2'],
|
||||
},
|
||||
{
|
||||
id: 'kevin',
|
||||
name: 'Kevin',
|
||||
krName: '케빈',
|
||||
setIds: ['kevin-normal', 'kevin-nexus-1', 'kevin-nexus-2'],
|
||||
},
|
||||
{
|
||||
id: 'mobius',
|
||||
name: 'Mobius',
|
||||
krName: '뫼비우스',
|
||||
setIds: ['mobius-normal', 'mobius-nexus-1', 'mobius-nexus-2'],
|
||||
},
|
||||
{
|
||||
id: 'sakura',
|
||||
name: 'Sakura',
|
||||
krName: '사쿠라',
|
||||
setIds: ['sakura-normal', 'sakura-nexus-1', 'sakura-nexus-2'],
|
||||
},
|
||||
{
|
||||
id: 'su',
|
||||
name: 'Su',
|
||||
krName: '수',
|
||||
setIds: ['su-normal', 'su-nexus-1', 'su-nexus-2'],
|
||||
},
|
||||
]
|
||||
|
||||
export const signetGroupMap = signetGroups.reduce((map, group) => {
|
||||
map.set(group.id, group)
|
||||
return map
|
||||
}, new Map<string, SignetGroup>())
|
||||
|
||||
export interface SignetSet {
|
||||
id: string
|
||||
name: string
|
||||
signets: SignetData[]
|
||||
}
|
||||
|
||||
export interface PopulatedSignetGroup {
|
||||
id: string
|
||||
name: string
|
||||
sets: SignetSet[]
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/** @jsxImportSource theme-ui */
|
||||
import { Box, Heading, Image } from '@theme-ui/components'
|
||||
import { NextPageContext } from 'next'
|
||||
import Breadcrumb from '../../../../components/organisms/Breadcrumb'
|
||||
import {
|
||||
BattlesuitData,
|
||||
battlesuitFeatures,
|
||||
battlesuitTypes,
|
||||
valkyries,
|
||||
} from '../../../../lib/honkai3rd/battlesuits'
|
||||
import { generateI18NPaths, getI18NProps } from '../../../../server/i18n'
|
||||
import {
|
||||
getBattlesuitById,
|
||||
listBattlesuits,
|
||||
} from '../../../../server/data/honkai3rd/battlesuits'
|
||||
import { translate, useTranslation } from '../../../../lib/i18n'
|
||||
import { useRouter } from 'next/router'
|
||||
import Head from '../../../../components/atoms/Head'
|
||||
import { capitalize } from '../../../../lib/string'
|
||||
import { assetsBucketBaseUrl } from '../../../../lib/consts'
|
||||
import Honkai3rdLayout from '../../../../components/layouts/Honkai3rdLayout'
|
||||
import { WeaponData } from '../../../../lib/honkai3rd/weapons'
|
||||
import { getWeaponMapByIds } from '../../../../server/data/honkai3rd/weapons'
|
||||
import { StigmataData } from '../../../../lib/honkai3rd/stigmata'
|
||||
import { getStigmataMapByIds } from '../../../../server/data/honkai3rd/stigmata'
|
||||
import { getSignetGroupById } from '../../../../server/data/honkai3rd/elysianRealm'
|
||||
import { SignetSet } from '../../../../lib/honkai3rd/elysianRealm'
|
||||
import SignetCard from '../../../../components/molecules/SignetCard'
|
||||
|
||||
type WeaponObjectMap = { [key: string]: WeaponData }
|
||||
type StigmataObjectMap = { [key: string]: StigmataData }
|
||||
|
||||
interface BattlesuitShowPageProps {
|
||||
battlesuit: BattlesuitData
|
||||
weaponMap: WeaponObjectMap
|
||||
stigmataMap: StigmataObjectMap
|
||||
signetSet: SignetSet
|
||||
}
|
||||
|
||||
const BattlesuitShowPage = ({
|
||||
battlesuit,
|
||||
weaponMap,
|
||||
stigmataMap,
|
||||
signetSet,
|
||||
}: BattlesuitShowPageProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { locale } = useRouter()
|
||||
|
||||
const battlesuitName = translate(
|
||||
locale,
|
||||
{ ['ko-KR']: battlesuit.krName },
|
||||
battlesuit.name
|
||||
)
|
||||
|
||||
const { label: valkyrieLabel, krLabel } = valkyries.find(
|
||||
(aValkyrie) => aValkyrie.value === battlesuit.valkyrie
|
||||
) || { label: battlesuit.valkyrie, krLabel: battlesuit.valkyrie }
|
||||
|
||||
const valkyrieName = translate(locale, { 'ko-KR': krLabel }, valkyrieLabel)
|
||||
|
||||
const battlesuitType = battlesuitTypes.find(
|
||||
(aType) => aType.value === battlesuit.type
|
||||
)
|
||||
const battlesuitTypeLabel = battlesuitType
|
||||
? translate(
|
||||
locale,
|
||||
{ 'ko-KR': battlesuitType.krLabel },
|
||||
battlesuitType.label
|
||||
)
|
||||
: capitalize(battlesuit.type)
|
||||
|
||||
return (
|
||||
<Honkai3rdLayout>
|
||||
<Head
|
||||
title={`${t('common.honkai-3rd')}: ${battlesuitName} - ${t(
|
||||
'common.abyss-lab'
|
||||
)}`}
|
||||
description={`${t('common.honkai-3rd')} ${t(
|
||||
'battlesuit-show.battlesuit'
|
||||
)} / ${valkyrieName} / ${battlesuitTypeLabel} / ${battlesuit.features
|
||||
.map((feature) => {
|
||||
const featureData = battlesuitFeatures.find(
|
||||
(aFeature) => aFeature.value === feature
|
||||
)
|
||||
if (featureData == null) {
|
||||
return feature
|
||||
}
|
||||
|
||||
const { label, krLabel } = featureData
|
||||
|
||||
return translate(locale, { 'ko-KR': krLabel }, label)
|
||||
})
|
||||
.join(', ')}`}
|
||||
/>
|
||||
|
||||
<Box p={3}>
|
||||
<Breadcrumb
|
||||
items={[
|
||||
{ href: '/honkai3rd', label: t('common.honkai-3rd') },
|
||||
{
|
||||
href: '/honkai3rd/elysian-realm',
|
||||
label: t('common.elysian-realm'),
|
||||
},
|
||||
{
|
||||
href: `/honkai3rd/elysian-realm/battlesuits/${battlesuit.id}`,
|
||||
label: battlesuitName,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<Heading as='h1'>{battlesuitName}</Heading>
|
||||
|
||||
<Box mb={3}>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
width: '100%',
|
||||
maxWidth: [300, 400],
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
alt={battlesuitName}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/battlesuits/${battlesuit.id}.png`}
|
||||
width={400}
|
||||
height={400}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Heading as='h2'>{t('elysian-realm.exclusive-signets')}</Heading>
|
||||
|
||||
<Box>
|
||||
{signetSet.signets.map((signet) => {
|
||||
return <SignetCard key={signet.id} signet={signet} />
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
</Honkai3rdLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default BattlesuitShowPage
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
locale,
|
||||
}: NextPageContext & { params: { battlesuitId: string } }) {
|
||||
try {
|
||||
const battlesuit = getBattlesuitById(params.battlesuitId)!
|
||||
const { weaponIds, stigmataIds } = (battlesuit.equipment || []).reduce<{
|
||||
weaponIds: string[]
|
||||
stigmataIds: string[]
|
||||
}>(
|
||||
(acc, equipmentItem) => {
|
||||
acc.weaponIds.push(equipmentItem.weapon)
|
||||
acc.stigmataIds.push(
|
||||
equipmentItem.stigmataTop,
|
||||
equipmentItem.stigmataMid,
|
||||
equipmentItem.stigmataBot
|
||||
)
|
||||
return acc
|
||||
},
|
||||
{ weaponIds: [], stigmataIds: [] }
|
||||
)
|
||||
const weaponMap = getWeaponMapByIds(weaponIds)
|
||||
|
||||
const stigmataMap = getStigmataMapByIds(stigmataIds)
|
||||
|
||||
const signetGroup = getSignetGroupById('elysia', locale)
|
||||
const signetSet = signetGroup.sets.find((set) => {
|
||||
return set.id === `elysia-${params.battlesuitId}`
|
||||
})
|
||||
|
||||
return {
|
||||
props: {
|
||||
battlesuit,
|
||||
weaponMap,
|
||||
stigmataMap,
|
||||
signetSet,
|
||||
...(await getI18NProps(locale)),
|
||||
},
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: generateI18NPaths(
|
||||
listBattlesuits().map((battlesuit) => {
|
||||
return {
|
||||
params: { battlesuitId: battlesuit.id },
|
||||
}
|
||||
})
|
||||
),
|
||||
fallback: false,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/** @jsxImportSource theme-ui */
|
||||
import { Box, Heading, Flex, Card } from '@theme-ui/components'
|
||||
import Breadcrumb from '../../../components/organisms/Breadcrumb'
|
||||
import { getBattlesuitMapByIds } from '../../../server/data/honkai3rd/battlesuits'
|
||||
import { BattlesuitData } from '../../../lib/honkai3rd/battlesuits'
|
||||
import BattlesuitCard from '../../../components/molecules/BattlesuitCard'
|
||||
|
||||
import { NextPageContext } from 'next'
|
||||
import { getI18NProps } from '../../../server/i18n'
|
||||
import { useTranslation } from '../../../lib/i18n'
|
||||
import Head from '../../../components/atoms/Head'
|
||||
import Honkai3rdLayout from '../../../components/layouts/Honkai3rdLayout'
|
||||
import {
|
||||
erVersions,
|
||||
rememberanceSigilIds,
|
||||
supportBattlesuitIds,
|
||||
} from '../../../lib/honkai3rd/elysianRealm'
|
||||
import SquareImageBox from '../../../components/atoms/SquareImageBox'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import PageLink from '../../../components/atoms/PageLink'
|
||||
import SignetGroupNavigator from '../../../components/organisms/SignetGroupNavigator'
|
||||
|
||||
type BattlesuitListItemData = Pick<
|
||||
BattlesuitData,
|
||||
'id' | 'name' | 'krName' | 'features' | 'type' | 'valkyrie'
|
||||
>
|
||||
|
||||
interface BattlesuitListPageProps {
|
||||
battlesuitMap: { [id: string]: BattlesuitListItemData }
|
||||
}
|
||||
|
||||
const ElysianRealmIndexPage = ({ battlesuitMap }: BattlesuitListPageProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Honkai3rdLayout>
|
||||
<Head
|
||||
title={`${t('common.honkai-3rd')}: ${t('common.elysian-realm')} - ${t(
|
||||
'common.abyss-lab'
|
||||
)}`}
|
||||
description={t('common.elysian-realm')}
|
||||
/>
|
||||
|
||||
<Box p={3}>
|
||||
<Breadcrumb
|
||||
items={[
|
||||
{ href: '/honkai3rd', label: t('common.honkai-3rd') },
|
||||
{
|
||||
href: '/honkai3rd/elysian-realm',
|
||||
label: t('common.elysian-realm'),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<Heading as='h1'>{t('common.elysian-realm')}</Heading>
|
||||
|
||||
<Heading as='h2'>{t('common.battlesuits')}</Heading>
|
||||
|
||||
<Box sx={{ mb: 3 }}>
|
||||
{erVersions.map((erVersion) => {
|
||||
return (
|
||||
<Box key={erVersion.version} sx={{ mb: 2 }}>
|
||||
<Heading as='h3' m={0}>
|
||||
{erVersion.version}
|
||||
</Heading>
|
||||
<Flex sx={{ flexWrap: 'wrap' }}>
|
||||
{erVersion.battlesuits.map((battlesuitId) => {
|
||||
return (
|
||||
<BattlesuitCard
|
||||
key={battlesuitId}
|
||||
battlesuit={battlesuitMap[battlesuitId]}
|
||||
size='sm'
|
||||
href={`/honkai3rd/elysian-realm/battlesuits/${battlesuitId}`}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Heading as='h2'>{t('elysian-realm.signets')}</Heading>
|
||||
|
||||
<SignetGroupNavigator />
|
||||
</Box>
|
||||
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Heading as='h2'>{t('elysian-realm.supports')}</Heading>
|
||||
|
||||
<Flex sx={{ flexWrap: 'wrap' }}>
|
||||
{supportBattlesuitIds.map((battlesuitId) => {
|
||||
return (
|
||||
<Card key={battlesuitId} sx={{ p: 1, m: 1 }}>
|
||||
<PageLink
|
||||
href={`/honkai3rd/elysian-realm/support-battlesuits#${battlesuitId}`}
|
||||
>
|
||||
<SquareImageBox
|
||||
size={70}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/battlesuits/portrait-${battlesuitId}.png`}
|
||||
/>
|
||||
</PageLink>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Heading as='h2'>{t('elysian-realm.remembrance-sigil')}</Heading>
|
||||
|
||||
<Flex sx={{ flexWrap: 'wrap' }}>
|
||||
{rememberanceSigilIds.map((sigilId) => {
|
||||
return (
|
||||
<Card key={sigilId} sx={{ p: 1, m: 1 }}>
|
||||
<PageLink
|
||||
href={`/honkai3rd/elysian-realm/remembrance-sigils#${sigilId}`}
|
||||
>
|
||||
<SquareImageBox
|
||||
size={70}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/remembrance-sigils/${sigilId}.png`}
|
||||
/>
|
||||
</PageLink>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
</Box>
|
||||
</Box>
|
||||
</Honkai3rdLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default ElysianRealmIndexPage
|
||||
|
||||
export async function getStaticProps({ locale }: NextPageContext) {
|
||||
const erBattlesuitIds = erVersions.reduce<string[]>((list, version) => {
|
||||
list.push(...version.battlesuits)
|
||||
return list
|
||||
}, [])
|
||||
return {
|
||||
props: {
|
||||
battlesuitMap: getBattlesuitMapByIds(erBattlesuitIds),
|
||||
...(await getI18NProps(locale)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/** @jsxImportSource theme-ui */
|
||||
import { Box, Heading, Flex, Text } from '@theme-ui/components'
|
||||
import { NextPageContext } from 'next'
|
||||
import Breadcrumb from '../../../../components/organisms/Breadcrumb'
|
||||
|
||||
import { generateI18NPaths, getI18NProps } from '../../../../server/i18n'
|
||||
import { useTranslation } from '../../../../lib/i18n'
|
||||
import Head from '../../../../components/atoms/Head'
|
||||
import Honkai3rdLayout from '../../../../components/layouts/Honkai3rdLayout'
|
||||
import {
|
||||
PopulatedSignetGroup,
|
||||
signetGroups,
|
||||
} from '../../../../lib/honkai3rd/elysianRealm'
|
||||
import { getSignetGroupById } from '../../../../server/data/honkai3rd/elysianRealm'
|
||||
import SignetCard from '../../../../components/molecules/SignetCard'
|
||||
import SignetGroupNavigator from '../../../../components/organisms/SignetGroupNavigator'
|
||||
import SquareImageBox from '../../../../components/atoms/SquareImageBox'
|
||||
import { assetsBucketBaseUrl } from '../../../../lib/consts'
|
||||
import PageLink from '../../../../components/atoms/PageLink'
|
||||
|
||||
interface SignetShowPageProps {
|
||||
signetId: string
|
||||
signetGroup: PopulatedSignetGroup
|
||||
}
|
||||
|
||||
const SignetShowPage = ({ signetId, signetGroup }: SignetShowPageProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Honkai3rdLayout>
|
||||
<Head
|
||||
title={`${t('common.honkai-3rd')}: ${signetGroup.name} - ${t(
|
||||
'common.abyss-lab'
|
||||
)}`}
|
||||
description={`${t('common.honkai-3rd')} ${t('elysian-realm.signet')}`}
|
||||
/>
|
||||
|
||||
<Box p={3}>
|
||||
<Breadcrumb
|
||||
items={[
|
||||
{ href: '/honkai3rd', label: t('common.honkai-3rd') },
|
||||
{
|
||||
href: '/honkai3rd/elysian-realm',
|
||||
label: t('common.elysian-realm'),
|
||||
},
|
||||
{
|
||||
href: `/honkai3rd/elysian-realm/signets/${signetId}`,
|
||||
label: signetGroup.name,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<Box sx={{ mb: 4 }}>
|
||||
<SignetGroupNavigator size={'sm'} />
|
||||
</Box>
|
||||
<Heading as='h1' sx={{ mb: 4, display: 'flex', alignItems: 'center' }}>
|
||||
<SquareImageBox
|
||||
mr={2}
|
||||
size={40}
|
||||
alt={signetGroup.name}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/signets/${signetGroup.id}.png`}
|
||||
/>{' '}
|
||||
{signetGroup.name} {t('elysian-realm.signets')}
|
||||
</Heading>
|
||||
|
||||
{signetGroup.sets.map((set) => {
|
||||
const signetType = set.id.split('-')[1]
|
||||
return (
|
||||
<Box key={set.id} sx={{ mb: 4 }}>
|
||||
<Heading as='h2' sx={{ mb: 2 }}>
|
||||
{signetGroup.id === 'elysia' ? (
|
||||
<PageLink
|
||||
href={`/honkai3rd/elysian-realm/battlesuits/${signetType}`}
|
||||
>
|
||||
<Flex sx={{ alignItems: 'center' }}>
|
||||
<SquareImageBox
|
||||
size={30}
|
||||
mr={2}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/battlesuits/portrait-${signetType}.png`}
|
||||
/>
|
||||
<Text>{set.name}</Text>
|
||||
</Flex>
|
||||
</PageLink>
|
||||
) : (
|
||||
set.name
|
||||
)}
|
||||
</Heading>
|
||||
<Box>
|
||||
{set.signets.map((signet) => {
|
||||
return <SignetCard key={signet.id} signet={signet} />
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
</Honkai3rdLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignetShowPage
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
locale,
|
||||
}: NextPageContext & { params: { signetId: string } }) {
|
||||
const { signetId } = params
|
||||
|
||||
return {
|
||||
props: {
|
||||
signetId,
|
||||
signetGroup: getSignetGroupById(signetId, locale),
|
||||
...(await getI18NProps(locale)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: generateI18NPaths(
|
||||
signetGroups.map((signet) => {
|
||||
return {
|
||||
params: { signetId: signet.id },
|
||||
}
|
||||
})
|
||||
),
|
||||
fallback: false,
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,12 @@ export function readdirSync(pathname: string) {
|
||||
}
|
||||
|
||||
export function readFileSync(pathname: string) {
|
||||
return fs.readFileSync(resolvePathname(pathname))
|
||||
try {
|
||||
return fs.readFileSync(resolvePathname(pathname))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export function readJsonFileSync(pathname: string) {
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
import { readFileSync } from '../fs'
|
||||
import {
|
||||
PopulatedSignetGroup,
|
||||
SignetData,
|
||||
signetGroups,
|
||||
SignetSet,
|
||||
} from '../../../lib/honkai3rd/elysianRealm'
|
||||
import { getBattlesuitById } from './battlesuits'
|
||||
|
||||
const signetGroupMap = signetGroups.reduce<{
|
||||
[key: string]: PopulatedSignetGroup
|
||||
}>((map, group) => {
|
||||
let populatedGroup = map[group.id]
|
||||
if (populatedGroup == null) {
|
||||
populatedGroup = {
|
||||
id: group.id,
|
||||
name: group.name,
|
||||
sets: [],
|
||||
}
|
||||
}
|
||||
|
||||
for (const setId of group.setIds) {
|
||||
const rawSetData = readFileSync(
|
||||
`honkai3rd/elysianRealm/signets/${setId}.md`
|
||||
).toString()
|
||||
|
||||
const [, setType, setIndex] = setId.split('-')
|
||||
|
||||
const name =
|
||||
group.id === 'elysia'
|
||||
? `${getBattlesuitById(setType)!.name} Exclusive Signets`
|
||||
: `${setType === 'nexus' ? 'Nexus Signets' : 'Normal Signets'}${
|
||||
setIndex != null ? ` ${setIndex}` : ''
|
||||
}`
|
||||
const signetSet: SignetSet = {
|
||||
id: setId,
|
||||
name,
|
||||
signets: [],
|
||||
}
|
||||
|
||||
if (setId.startsWith('elysia-') || setId.endsWith('normal')) {
|
||||
const signets = parseNormalSignetsRawData(setId, rawSetData)
|
||||
signetSet.signets.push(...signets)
|
||||
} else {
|
||||
const signets = parseNexusSignetsRawData(setId, rawSetData)
|
||||
signetSet.signets.push(...signets)
|
||||
}
|
||||
|
||||
populatedGroup.sets.push(signetSet)
|
||||
}
|
||||
map[group.id] = populatedGroup
|
||||
|
||||
return map
|
||||
}, {})
|
||||
|
||||
const krSignetGroupMap = signetGroups.reduce<{
|
||||
[key: string]: PopulatedSignetGroup
|
||||
}>((map, group) => {
|
||||
let populatedGroup = map[group.id]
|
||||
if (populatedGroup == null) {
|
||||
populatedGroup = {
|
||||
id: group.id,
|
||||
name: group.krName,
|
||||
sets: [],
|
||||
}
|
||||
}
|
||||
|
||||
for (const setId of group.setIds) {
|
||||
const rawSetData = readFileSync(
|
||||
`honkai3rd/ko-KR/elysianRealm/signets/${setId}.md`
|
||||
).toString()
|
||||
|
||||
const [, setType, setIndex] = setId.split('-')
|
||||
|
||||
const name =
|
||||
group.id === 'elysia'
|
||||
? `${getBattlesuitById(setType)!.krName} 전용 각인`
|
||||
: `${setType === 'nexus' ? '증폭 각인' : '일반 각인'}${
|
||||
setIndex != null ? ` ${setIndex}` : ''
|
||||
}`
|
||||
const signetSet: SignetSet = {
|
||||
id: setId,
|
||||
name,
|
||||
signets: [],
|
||||
}
|
||||
|
||||
if (setId.startsWith('elysia-') || setId.endsWith('normal')) {
|
||||
const signets = parseNormalSignetsRawData(setId, rawSetData)
|
||||
signetSet.signets.push(...signets)
|
||||
} else {
|
||||
const signets = parseNexusSignetsRawData(setId, rawSetData)
|
||||
signetSet.signets.push(...signets)
|
||||
}
|
||||
|
||||
populatedGroup.sets.push(signetSet)
|
||||
}
|
||||
map[group.id] = populatedGroup
|
||||
|
||||
return map
|
||||
}, {})
|
||||
|
||||
export function getSignetGroupById(id: string, locale = 'en-US') {
|
||||
if (locale === 'ko-KR') {
|
||||
return krSignetGroupMap[id]
|
||||
}
|
||||
return signetGroupMap[id]
|
||||
}
|
||||
|
||||
function parseNormalSignetsRawData(setId: string, data: string) {
|
||||
const signetSections = data.replace(/\\\*/g, '*').slice(2).split('\n# ')
|
||||
const signets: SignetData[] = []
|
||||
for (const index in signetSections) {
|
||||
const section = signetSections[index]
|
||||
const [name, description, ...upgradeTextBlocks] = section.split('\n\n')
|
||||
const upgradeList = upgradeTextBlocks
|
||||
.join('\n\n')
|
||||
.split('## ')
|
||||
.slice(1)
|
||||
.map((upgradeTextBlock) => {
|
||||
const [name, description] = upgradeTextBlock.split('\n\n')
|
||||
return {
|
||||
name,
|
||||
description,
|
||||
krName: name,
|
||||
krDescription: description,
|
||||
}
|
||||
})
|
||||
signets.push({
|
||||
id: `${setId}-${index + 1}`,
|
||||
name,
|
||||
description,
|
||||
upgrades: upgradeList,
|
||||
})
|
||||
}
|
||||
return signets
|
||||
}
|
||||
|
||||
function parseNexusSignetsRawData(setId: string, data: string) {
|
||||
const signetSections = data.replace(/\\\*/g, '*').slice(2).split('\n## ')
|
||||
const coreSignetSection = signetSections.shift()
|
||||
const [coreSignetName, coreSignetDescription] =
|
||||
coreSignetSection!.split('\n\n')
|
||||
const coreSignet = {
|
||||
id: `${setId}-1`,
|
||||
name: coreSignetName,
|
||||
description: coreSignetDescription,
|
||||
krName: coreSignetName,
|
||||
krDescription: coreSignetDescription,
|
||||
upgrades: [],
|
||||
}
|
||||
const signets: SignetData[] = []
|
||||
signets.push(coreSignet)
|
||||
for (const index in signetSections) {
|
||||
const section = signetSections[index]
|
||||
const [name, description, ...upgradeTextBlocks] = section.split('\n\n')
|
||||
const upgradeList = upgradeTextBlocks
|
||||
.join('\n\n')
|
||||
.split('### ')
|
||||
.slice(1)
|
||||
.map((upgradeTextBlock) => {
|
||||
const [name, description] = upgradeTextBlock.split('\n\n')
|
||||
return {
|
||||
name,
|
||||
description,
|
||||
krName: name,
|
||||
krDescription: description,
|
||||
}
|
||||
})
|
||||
signets.push({
|
||||
id: `${setId}-${index + 2}`,
|
||||
name,
|
||||
description,
|
||||
upgrades: upgradeList,
|
||||
})
|
||||
}
|
||||
return signets
|
||||
}
|
||||
Reference in New Issue
Block a user