Skip to content

Commit 6d1911d

Browse files
committed
Add used by
1 parent 67f74fa commit 6d1911d

File tree

6 files changed

+144
-75
lines changed

6 files changed

+144
-75
lines changed

components/Icon.tsx

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,52 @@
1+
/* eslint-disable @next/next/no-img-element */
12
import Image from "next/image"
3+
import { SmallChar } from "../utils/types"
4+
import { elements, getStarColor, image, urlify, weapons } from "../utils/utils"
5+
import FormattedLink from "./FormattedLink"
26

3-
export default function Icon({ icon, className }: { icon: {name: string, icon?: string}, className?: string }) {
4-
const src = icon.icon ?? "img/unknown.png"
7+
export default function Icon({ icon, className }: { icon: { name: string, icon?: string }, className?: string }) {
8+
const src = icon.icon ?? "img/unknown.png"
59

6-
if (src.startsWith("img"))
7-
// eslint-disable-next-line @next/next/no-img-element
8-
return <img alt={icon.name} src={"/" + src} className={className} width={256} height={256} onError={(e) => (e.target as HTMLImageElement).src = "/img/unknown.png"} loading="eager" />
10+
if (src.startsWith("img"))
11+
// eslint-disable-next-line @next/next/no-img-element
12+
return <img alt={icon.name} src={"/" + src} className={className} width={256} height={256} onError={(e) => (e.target as HTMLImageElement).src = "/img/unknown.png"} loading="eager" />
913

10-
return <Image alt={icon.name} src={src} className={className} width={256} height={256} onError={(e) => (e.target as HTMLImageElement).src = "/img/unknown.png"} loading="eager" />
11-
}
14+
return <Image alt={icon.name} src={src} className={className} width={256} height={256} onError={(e) => (e.target as HTMLImageElement).src = "/img/unknown.png"} loading="eager" />
15+
}
16+
17+
export function IconName({ name, type, urltype }: { name: string, type: string, urltype: string }) {
18+
return <FormattedLink href={`/${urltype}/${urlify(name, false)}`} className="flex flex-row align-middle items-center">
19+
<div className="pr-1 w-12 h-12 md:h-16 md:w-16">
20+
<img src={image(type, name)} alt={name} width={256} height={256} />
21+
</div>
22+
<div className="font-semibold md:text-xl">{name}</div>
23+
</FormattedLink>
24+
}
25+
26+
27+
export function CharIcon({ char, location }: { char: SmallChar, location: string }) {
28+
const color = getStarColor(char.stars ?? 0)
29+
30+
return <FormattedLink key={char.name} location={location} href={`/characters/${urlify(char.name, false)}`} className="bg-slate-300 dark:bg-slate-800 w-24 sm:w-28 lg:w-32 m-1 relative rounded-xl transition-all duration-100 hover:outline outline-slate-800 dark:outline-slate-300 font-bold text-sm" >
31+
<div className={`${color} rounded-t-xl h-24 sm:h-28 lg:h-32`}>
32+
<Icon icon={char} className="rounded-t-xl m-0 p-0" />
33+
<span className="absolute block p-0.5 top-0 w-full">
34+
<div className="flex flex-col">
35+
{char.element && char.element.map(e => <div key={e} className="w-6 md:w-8">
36+
<Image src={elements[e]} alt={`${e} Element`} loading="eager" />
37+
</div>)}
38+
</div>
39+
</span>
40+
<span className="absolute block p-0.5 top-0 w-full">
41+
<div className="flex flex-col float-right">
42+
{char.weapon && <div className="w-6 md:w-8">
43+
<Image src={weapons[char.weapon]} alt={char.weapon} loading="eager" />
44+
</div>}
45+
</div>
46+
</span>
47+
</div>
48+
<span className="flex justify-center items-center h-10 md:h-12 m-0 p-0 duration-200 md:text-base">
49+
{char.name}
50+
</span>
51+
</FormattedLink>
52+
}

components/Material.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,19 @@ import FormattedLink from "./FormattedLink"
33

44
/* eslint-disable @next/next/no-img-element */
55
export function MaterialImage({ name }: { name: string }) {
6-
return <FormattedLink className="inline-block pr-1 w-6 h-6 md:h-8 md:w-8" href={`/materials/${urlify(name, false)}`}>
7-
<img src={image("material", name)} alt={name} width={256} height={256} />
8-
</FormattedLink>
6+
return <FormattedLink className="inline-block pr-1 w-6 h-6 md:h-8 md:w-8" href={`/materials/${urlify(name, false)}`}>
7+
<img src={image("material", name)} alt={name} width={256} height={256} />
8+
</FormattedLink>
99
}
1010

11-
1211
export function MaterialCost({ name, count }: { name: string, count: number }) {
13-
return <div className="flex flex-row align-middle items-center">
14-
<div>{count}&times;</div>
15-
<FormattedLink href={`/materials/${urlify(name, false)}`} className="flex flex-row align-middle items-center">
16-
<div className="pr-1 w-8 h-8 sm:h-6 sm:w-6 md:h-8 md:w-8">
17-
<img src={image("material", name)} alt={name} width={256} height={256} />
18-
</div>
19-
<div className="md:text-sm lg:text-base sm:not-sr-only sr-only text-xs font-normal">{name}</div>
20-
</FormattedLink>
21-
</div>
12+
return <div className="flex flex-row align-middle items-center">
13+
<div>{count}&times;</div>
14+
<FormattedLink href={`/materials/${urlify(name, false)}`} className="flex flex-row align-middle items-center">
15+
<div className="pr-1 w-8 h-8 sm:h-6 sm:w-6 md:h-8 md:w-8">
16+
<img src={image("material", name)} alt={name} width={256} height={256} />
17+
</div>
18+
<div className="md:text-sm lg:text-base sm:not-sr-only sr-only text-xs font-normal">{name}</div>
19+
</FormattedLink>
20+
</div>
2221
}

pages/characters/index.tsx

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,13 @@ import Head from "next/head"
33
import Image from "next/image"
44
import { useState } from "react"
55
import { ExclusiveButton, ToggleAllButton, ToggleButton } from "../../components/Filters"
6-
import FormattedLink from "../../components/FormattedLink"
7-
import Icon from "../../components/Icon"
6+
import { CharIcon } from "../../components/Icon"
87
import Main from "../../components/Main"
98
import { getCharacters } from "../../utils/data-cache"
10-
import { WeaponType } from "../../utils/types"
11-
import { elements, ElementType, getStarColor, isFullCharacter, urlify, weapons } from "../../utils/utils"
9+
import { SmallChar, WeaponType } from "../../utils/types"
10+
import { createSmallChar, elements, ElementType, isFullCharacter, weapons } from "../../utils/utils"
1211

1312

14-
interface SmallChar {
15-
name: string
16-
stars?: number
17-
element?: ElementType[]
18-
weapon?: WeaponType
19-
icon?: string
20-
}
21-
2213
interface Props {
2314
characters: SmallChar[]
2415
}
@@ -118,32 +109,7 @@ export default function Characters(props: Props & { location: string }) {
118109
.filter(c => starFilter == 0 || starFilter == c.stars)
119110
.filter(c => elementFilter.some(e => c.element?.includes(e)) || c.element == undefined)
120111
.filter(c => weaponFilter.some(e => c.weapon?.includes(e)) || c.weapon == undefined)
121-
.map(char => {
122-
const color = getStarColor(char.stars ?? 0)
123-
124-
return <FormattedLink key={char.name} location={props.location} href={`/characters/${urlify(char.name, false)}`} className="bg-slate-300 dark:bg-slate-800 w-24 sm:w-28 lg:w-32 m-1 relative rounded-xl transition-all duration-100 hover:outline outline-slate-800 dark:outline-slate-300 font-bold text-sm" >
125-
<div className={`${color} rounded-t-xl h-24 sm:h-28 lg:h-32`}>
126-
<Icon icon={char} className="rounded-t-xl m-0 p-0" />
127-
<span className="absolute block p-0.5 top-0 w-full">
128-
<div className="flex flex-col">
129-
{char.element && char.element.map(e => <div key={e} className="w-6 md:w-8">
130-
<Image src={elements[e]} alt={`${e} Element`} loading="eager" />
131-
</div>)}
132-
</div>
133-
</span>
134-
<span className="absolute block p-0.5 top-0 w-full">
135-
<div className="flex flex-col float-right">
136-
{char.weapon && <div className="w-6 md:w-8">
137-
<Image src={weapons[char.weapon]} alt={char.weapon} loading="eager" />
138-
</div>}
139-
</div>
140-
</span>
141-
</div>
142-
<span className="flex justify-center items-center h-10 md:h-12 m-0 p-0 duration-200 md:text-base">
143-
{char.name}
144-
</span>
145-
</FormattedLink>
146-
})}
112+
.map(char => <CharIcon key={char.name} char={char} location={props.location} />)}
147113
</div>
148114
</Main>
149115
)
@@ -173,15 +139,7 @@ export async function getStaticProps(context: GetStaticPropsContext): Promise<Ge
173139
return -1
174140
else return a.name.localeCompare(b.name)
175141
})
176-
.map(c => {
177-
const char: SmallChar = { name: c.name }
178-
if (c.star) char.stars = c.star
179-
if (c.meta.element) char.element = [c.meta.element as ElementType]
180-
if (c.skills) char.element = c.skills.map(skill => skill.ult?.type).filter(x => x) as ElementType[]
181-
if (c.weaponType) char.weapon = c.weaponType
182-
if (c.icon) char.icon = c.icon
183-
return char
184-
})
142+
.map(c => createSmallChar(c))
185143
},
186144
revalidate: 60 * 60
187145
}

pages/materials/[material].tsx

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@ import Head from "next/head"
44
import ReactMarkdown from "react-markdown"
55
import FormattedLink from "../../components/FormattedLink"
66
import Guides from "../../components/Guides"
7-
import Icon from "../../components/Icon"
7+
import Icon, { CharIcon, IconName } from "../../components/Icon"
88
import Main from "../../components/Main"
9-
import { getMaterials } from "../../utils/data-cache"
10-
import { Material } from "../../utils/types"
11-
import { getGuidesFor, getLinkToGuide, getStarColor, urlify } from "../../utils/utils"
9+
import { CostTemplates, getCharacters, getCostTemplates, getMaterials } from "../../utils/data-cache"
10+
import { Cost, CostTemplate, Material, SmallChar } from "../../utils/types"
11+
import { createSmallChar, getCostsFromTemplate, getGuidesFor, getLinkToGuide, getStarColor, urlify } from "../../utils/utils"
1212

1313
interface Props {
1414
mat: Material,
15-
guides?: string[][]
15+
guides?: string[][],
16+
usedBy: {
17+
charTalents: SmallChar[]
18+
charAscension: SmallChar[]
19+
}
1620
}
1721

18-
export default function CharacterWebpage({ mat, location, guides }: Props & { location: string }) {
22+
export default function CharacterWebpage({ mat, location, guides, usedBy }: Props & { location: string }) {
1923
const color = getStarColor(mat.stars ?? 1)
2024

2125
return (
@@ -74,6 +78,20 @@ export default function CharacterWebpage({ mat, location, guides }: Props & { lo
7478
{mat.sources.map(s => <div key={s}>{s}</div>)}
7579
</>}
7680

81+
{usedBy.charTalents.length > 0 && <>
82+
<h3 className="text-lg font-bold pt-1" id="chartalents">Used by character talents:</h3>
83+
<div className="flex flex-wrap justify-start text-center mt-2">
84+
{usedBy.charTalents.map(c => <CharIcon key={c.name} char={c} location={location} />)}
85+
</div>
86+
</>}
87+
88+
{usedBy.charAscension.length > 0 && <>
89+
<h3 className="text-lg font-bold pt-1" id="charascension">Used by character ascensions:</h3>
90+
<div className="flex flex-wrap justify-start text-center mt-2">
91+
{usedBy.charAscension.map(c => <CharIcon key={c.name} char={c} location={location} />)}
92+
</div>
93+
</>}
94+
7795
{mat.longDesc && <>
7896
<h3 className="text-lg font-bold pt-1" id="longdesc">Description:</h3>
7997
<blockquote className="pl-5 mb-2 border-l-2">
@@ -86,6 +104,16 @@ export default function CharacterWebpage({ mat, location, guides }: Props & { lo
86104
}
87105

88106

107+
function isInCosts(template: CostTemplate | Cost[], costTemplates: CostTemplates, name: string): boolean {
108+
const costs = Array.isArray(template) ? template : getCostsFromTemplate(template, costTemplates)
109+
110+
for (const c of costs)
111+
if (c.items.some(i => i.name == name))
112+
return true
113+
114+
return false
115+
}
116+
89117
export async function getStaticProps(context: GetStaticPropsContext): Promise<GetStaticPropsResult<Props>> {
90118
const matName = context.params?.material
91119
const data = await getMaterials()
@@ -100,10 +128,33 @@ export async function getStaticProps(context: GetStaticPropsContext): Promise<Ge
100128

101129
const guides = (await getGuidesFor("material", mat.name))?.map(({ guide, page }) => [page.name, getLinkToGuide(guide, page)])
102130

131+
const char = await getCharacters()
132+
const costTemplates = await getCostTemplates()
133+
const charAscension: SmallChar[] = []
134+
const charTalents: SmallChar[] = []
135+
136+
if (char && costTemplates) {
137+
for (const c of Object.values(char)) {
138+
if (c.ascensionCosts && isInCosts(c.ascensionCosts, costTemplates, mat.name))
139+
charAscension.push(createSmallChar(c))
140+
141+
if (c.skills) {
142+
const talents = c.skills.flatMap(s => [...(s.talents ?? []), s.ult])
143+
144+
if (talents.some(x => x?.costs && isInCosts(x.costs, costTemplates, mat.name)))
145+
charTalents.push(createSmallChar(c))
146+
}
147+
}
148+
}
149+
103150
return {
104151
props: {
105152
mat,
106-
guides
153+
guides,
154+
usedBy: {
155+
charAscension,
156+
charTalents
157+
}
107158
},
108159
revalidate: 60 * 60
109160
}

utils/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ElementType } from "./utils"
2+
13
export interface DiscordUser {
24
id: string
35
username: string
@@ -213,3 +215,11 @@ export interface GuidePage {
213215
character?: string[]
214216
}
215217
}
218+
219+
export interface SmallChar {
220+
name: string
221+
stars?: number
222+
element?: ElementType[]
223+
weapon?: WeaponType
224+
icon?: string
225+
}

utils/utils.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Claymore from "../public/img/weapon_types/Claymore.png"
1111
import Polearm from "../public/img/weapon_types/Polearm.png"
1212
import Sword from "../public/img/weapon_types/Sword.png"
1313
import { getGuides } from "./data-cache"
14-
import { Character, CharacterFull, Cost, CostTemplate, CurveEnum, Guide, GuidePage, TalentTable, TalentValue, WeaponType } from "./types"
14+
import { Character, CharacterFull, Cost, CostTemplate, CurveEnum, Guide, GuidePage, SmallChar, TalentTable, TalentValue, WeaponType } from "./types"
1515

1616
export const elements = {
1717
Pyro, Electro, Cryo, Hydro, Anemo, Geo, Dendro
@@ -134,3 +134,13 @@ export function getStarColor(star: number): string {
134134
if (star == 1) return "onestar"
135135
return ""
136136
}
137+
138+
export function createSmallChar(c: Character): SmallChar {
139+
const char: SmallChar = { name: c.name }
140+
if (c.star) char.stars = c.star
141+
if (c.meta.element) char.element = [c.meta.element as ElementType]
142+
if (c.skills) char.element = c.skills.map(skill => skill.ult?.type).filter(x => x) as ElementType[]
143+
if (c.weaponType) char.weapon = c.weaponType
144+
if (c.icon) char.icon = c.icon
145+
return char
146+
}

0 commit comments

Comments
 (0)