Add Battlesuit page

This commit is contained in:
Sakura Knoll
2023-07-09 07:31:28 +09:00 Unverified
parent 9ce20302a3
commit f6f2a0866d
21 changed files with 1463 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
import { Image, ThemeUIStyleObject } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
import { AttributeType } from '../../lib/v2-pre/data/types'
interface AttributeIconProps {
attributeType: AttributeType
size?: number
className?: string
sx?: ThemeUIStyleObject
}
const AttributeIcon = ({ size, attributeType, className, sx }: AttributeIconProps) => {
return (
<Image src={getAttributeIconSrc(attributeType)} width={size} className={className} sx={sx} alt={attributeType} />
)
}
export default AttributeIcon
function getAttributeIconSrc(attributeType: AttributeType) {
switch (attributeType) {
case 'bio':
return `${assetsBucketBaseUrl}/raw/avatarattricons/AvatarShengWu.png`
case 'psy':
return `${assetsBucketBaseUrl}/raw/avatarattricons/AvatarYiNeng.png`
case 'mech':
return `${assetsBucketBaseUrl}/raw/avatarattricons/AvatarJiXie.png`
case 'qua':
return `${assetsBucketBaseUrl}/raw/avatarattricons/AvatarLiangZi.png`
case 'img':
return `${assetsBucketBaseUrl}/raw/avatarattricons/AvatarXuShu.png`
case 'none':
default:
return `${assetsBucketBaseUrl}/raw/avatarattricons/AvatarNone.png`
}
}
@@ -0,0 +1,21 @@
import { Image, ThemeUICSSObject } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
interface AvatarFigureImageProps {
battlesuitId: string
className?: string
sx?: ThemeUICSSObject
}
const AvatarFigureImage = ({ battlesuitId, className, sx }: AvatarFigureImageProps) => {
return <Image src={getAvatarFigureImageSrc(battlesuitId)} className={className} alt={battlesuitId} sx={sx} />
}
export default AvatarFigureImage
function getAvatarFigureImageSrc(battlesuitId: string) {
if (battlesuitId.length < 4) {
return `${assetsBucketBaseUrl}/raw/avatarcardfigures/60${battlesuitId}.png`
}
return `${assetsBucketBaseUrl}/raw/avatarcardfigures/6${battlesuitId}.png`
}
+20
View File
@@ -0,0 +1,20 @@
import { Box } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
interface AvatarSkillIconProps {
icon: string
}
const AvatarSkillIcon = ({ icon: fileName }: AvatarSkillIconProps) => {
return (
<Box
sx={{
width: 40,
height: 40,
background: `no-repeat 50%/80% url(${assetsBucketBaseUrl}/raw/skillicons/${fileName}.png)`
}}
/>
)
}
export default AvatarSkillIcon
@@ -0,0 +1,20 @@
import { Box } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
interface AvatarSubSkillIconProps {
icon: string
}
const AvatarSubSkillIcon = ({ icon: fileName }: AvatarSubSkillIconProps) => {
return (
<Box
sx={{
width: 40,
height: 40,
background: `no-repeat 50%/80% url(${assetsBucketBaseUrl}/raw/subskillicons/${fileName}.png)`
}}
/>
)
}
export default AvatarSubSkillIcon
@@ -0,0 +1,61 @@
import { Box } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
import { AttributeType, BattlesuitCatalogItem } from '../../lib/v2-pre/data/types'
interface BattlesuitAvatarIconProps {
battlesuit: BattlesuitCatalogItem
}
const BattlesuitAvatarIcon = ({ battlesuit }: BattlesuitAvatarIconProps) => {
return (
<Box>
<Box
sx={{
borderRadius: 5,
background: `no-repeat 50% / 130px url(${assetsBucketBaseUrl}/raw/avataricon/${
battlesuit.id
}.png), no-repeat 50% / 130px url(${getAttributeBgImageSrc(battlesuit.attributeType)})`,
width: 130,
height: 120
}}
></Box>
</Box>
)
}
export default BattlesuitAvatarIcon
function getAttributeBgImageSrc(attrId: AttributeType, square = false) {
if (square) {
switch (attrId) {
case 'bio':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrShengWu1.png`
case 'psy':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrYiNeng1.png`
case 'mech':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrJiXie1.png`
case 'qua':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrLiangZi1.png`
case 'img':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrXuShu1.png`
case 'none':
default:
return `${assetsBucketBaseUrl}/raw/avataricon/AttrDefault.png`
}
}
switch (attrId) {
case 'bio':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrShengWu.png`
case 'psy':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrYiNeng.png`
case 'mech':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrJiXie.png`
case 'qua':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrLiangZi.png`
case 'img':
return `${assetsBucketBaseUrl}/raw/avataricon/AttrXuShu.png`
case 'none':
default:
return `${assetsBucketBaseUrl}/raw/avataricon/AttrDefault.png`
}
}
@@ -0,0 +1,39 @@
import { Box } from 'theme-ui'
import { BattlesuitCatalogItem } from '../../lib/v2-pre/data/types'
import BattlesuitAvatarIcon from './BattlesuitAvatarIcon'
interface BattlesuitCatalogItemCardProps {
battlesuit: BattlesuitCatalogItem
label?: boolean
}
const BattlesuitCatalogItemCard = ({ battlesuit, label = false }: BattlesuitCatalogItemCardProps) => {
return (
<Box
sx={{
mb: 2,
transform: 'scale(1)',
transition: 'transform 200ms ease-in-out',
'&:hover': {
transform: 'scale(1.05)'
}
}}
>
<BattlesuitAvatarIcon battlesuit={battlesuit} />
<Box
sx={{
textAlign: 'center',
overflow: 'hidden',
width: 110,
marginLeft: -10,
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}}
>
{battlesuit.fullName}
</Box>
</Box>
)
}
export default BattlesuitCatalogItemCard
+90
View File
@@ -0,0 +1,90 @@
import { Box } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
import { CharacterType } from '../../lib/v2-pre/data/types'
interface ChibiIconProps {
id: string
}
const ChibiIcon = ({ id }: ChibiIconProps) => {
return (
<Box
sx={{
width: 30,
height: 30,
background: `no-repeat 50% 50% / 30px url(${assetsBucketBaseUrl}/raw/avatarchibiicons/${getChibiIconName(
id
)}.png)`
}}
></Box>
)
}
export default ChibiIcon
export function getChibiIconName(idOrType: string | CharacterType) {
switch (idOrType) {
case 'kiana':
return '106'
case 'mei':
return '206'
case 'bronya':
return '317'
case 'himeko':
return '412'
case 'theresa':
return '502_05_01'
case 'fuhua':
return '612'
case 'rita':
return '706'
case 'sakura':
return '212'
case 'kallen':
return '111'
case 'olenyevas':
return '422_05_01'
case 'seele':
return '713'
case 'durandal':
return '804'
case 'fischl':
return '2101'
case 'elysia':
return '2202'
case 'mobius':
return '2301'
case 'raven':
return '2401'
case 'carole':
return '2501'
case 'pardofelis':
return '2601'
case 'aponia':
return '2701'
case 'eden':
return '2801'
case 'griseo':
return '2901'
case 'vill-v':
return '3001'
case 'sushang':
return '3101'
case 'ai':
return '3201'
case 'susannah':
return '3301'
case 'hare':
return '3401'
case 'prometheus':
return '3501'
case 'kira':
return '3601'
case 'asuka':
return '901'
case 'keqing':
return '2001'
default:
return 'IconAvatarQuestion'
}
}
+53
View File
@@ -0,0 +1,53 @@
import { Text } from 'theme-ui'
import { FormattedTextToken, tokenize } from '../../lib/v2-pre/formattedText/tokenize'
interface FormattedTextProps {
children: string
}
const FormattedText = ({ children }: FormattedTextProps) => {
const tokens = tokenize(children)
return <>{renderTokens(tokens)}</>
function renderTokens(tokens: FormattedTextToken[]) {
return tokens.map((token, index) => {
if (token.type === 'element') {
return (
<Text key={index} style={{ color: adjustColor(token.attributes.color) }}>
{renderTokens(token.children)}
</Text>
)
}
return token.text
})
}
}
export default FormattedText
function adjustColor(color: unknown): string | undefined {
if (typeof color !== 'string') {
return undefined
}
const normalizedColor = color.toUpperCase()
if (normalizedColor.startsWith('#FEDF4C')) {
return '#e6c010'
}
if (normalizedColor.startsWith('#FFC741')) {
return '#f0a030'
}
if (
normalizedColor.startsWith('#23B2E') ||
normalizedColor.startsWith('#23B2E') ||
normalizedColor.startsWith('#23B2E')
) {
return '#1d9ecc'
}
return color
}
+48
View File
@@ -0,0 +1,48 @@
import { Box } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
import { StarRank } from '../../lib/v2-pre/data/types'
interface StarIconProps {
star: StarRank
}
const StarIcon = ({ star }: StarIconProps) => {
return (
<Box
sx={{
width: 30,
height: 30,
background: `no-repeat 50% / 30px url(${getStarIconPath(star)})`
}}
/>
)
}
export default StarIcon
function getStarIconPath(star: StarRank) {
switch (star) {
case 'b':
return `${assetsBucketBaseUrl}/raw/avatarstar/Star_Avatar_1.png`
case 'a':
return `${assetsBucketBaseUrl}/raw/avatarstar/Star_Avatar_2.png`
case 's':
return `${assetsBucketBaseUrl}/raw/avatarstar/Star_Avatar_3.png`
case 'ss':
return `${assetsBucketBaseUrl}/raw/avatarstar/Star_Avatar_4.png`
case 'sss':
return `${assetsBucketBaseUrl}/raw/avatarstar/Star_Avatar_5.png`
case 's1':
return `${assetsBucketBaseUrl}/raw/avatarstarskill/S1.png`
case 's2':
return `${assetsBucketBaseUrl}/raw/avatarstarskill/S2.png`
case 's3':
return `${assetsBucketBaseUrl}/raw/avatarstarskill/S3.png`
case 'ss1':
return `${assetsBucketBaseUrl}/raw/avatarstarskill/SS1.png`
case 'ss2':
return `${assetsBucketBaseUrl}/raw/avatarstarskill/SS2.png`
case 'ss3':
return `${assetsBucketBaseUrl}/raw/avatarstarskill/SS3.png`
}
}
+98
View File
@@ -0,0 +1,98 @@
import { Box } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
import { TagType } from '../../lib/v2-pre/data/types'
interface TagIconProps {
type: TagType
strength?: 1 | 2 | 3 | 4
size?: 'sm' | 'md'
comment?: string
}
const TagIcon = ({ type, strength, size = 'md', comment }: TagIconProps) => {
const boxSizePx = size === 'md' ? '30px' : '20px'
const iconSizePx = size === 'md' ? '24px' : '16px'
return (
<Box sx={{ position: 'relative' }}>
<Box
sx={{
position: 'absolute',
right: '2px',
top: '-2px',
fontSize: 0,
color: 'white',
textShadow:
'#555 0px 0px 1px, #555 0px 0px 1px, #555 0px 0px 1px,#555 0px 0px 1px, #555 0px 0px 1px, #555 0px 0px 1px'
}}
>
{strength}
</Box>
<Box
title={comment}
sx={{
borderRadius: 5,
width: boxSizePx,
height: boxSizePx,
background: `no-repeat 50% / ${iconSizePx} ${iconSizePx} url(${assetsBucketBaseUrl}/raw/newstateicon/${getTagIconFileName(
type
)}.png), #5a8cb0`
}}
/>
</Box>
)
}
export default TagIcon
function getTagIconFileName(type: TagType) {
switch (type) {
case 'branch':
return 'State_Branch'
case 'charge':
return 'State_Charge'
case 'physical-dmg':
return 'State_Physical'
case 'fire-dmg':
return 'State_Fire'
case 'ice-dmg':
return 'State_Ice'
case 'lightning-dmg':
return 'State_Lightning'
case 'freeze':
return 'State_Frozen'
case 'paralyze':
return 'State_Paralysis'
case 'stun':
return 'State_Stun'
case 'ignite':
return 'State_Burn'
case 'bleed':
return 'State_Bleading'
case 'heavy-atk':
return 'State_Smash'
case 'weaken':
return 'State_Weak'
case 'impair':
return 'State_Fragile'
case 'float':
return 'State_Float'
case 'time-mastery':
return 'State_WitchTime'
case 'gather':
return 'State_SlowDown'
case 'heal':
return 'State_Heal'
case 'fast-atk':
return 'State_HighFreq'
case 'burst':
return 'State_Burst'
case 'shield':
return 'State_Shield'
case 'aerial':
return 'State_AntiAir'
case 'ranged':
return 'State_Remote'
case 'meele':
return 'State_Meele'
}
}
+50
View File
@@ -0,0 +1,50 @@
import { Box } from 'theme-ui'
import { assetsBucketBaseUrl } from '../../lib/consts'
import { WeaponType } from '../../lib/v2-pre/data/types'
interface WeaponTypeIconProps {
type: WeaponType
}
const WeaponTypeIcon = ({ type }: WeaponTypeIconProps) => {
return (
<Box
sx={{
borderRadius: 5,
width: 30,
height: 30,
background: `no-repeat 50% 50% / 24px url(${assetsBucketBaseUrl}/raw/weapontypeicons/${getWeaponIconPath(
type
)}.png), #5a8cb0`
}}
></Box>
)
}
export default WeaponTypeIcon
function getWeaponIconPath(type: WeaponType) {
switch (type) {
case 'pistols':
return 'DoublePistolType'
case 'cannon':
return 'MissileType'
case 'katana':
return 'SwordType'
case 'cross':
return 'CrossType'
case '2-handed':
return 'ClaymoreType'
case 'scythe':
return 'ScytheType'
case 'lance':
return 'LanceType'
case 'fists':
return 'FistType'
case 'bow':
return 'BowType'
case 'chakram':
return 'BladeRingType'
case 'javelin':
return 'JavelinType'
}
}