@@ -6,18 +6,19 @@ import { useState } from "react"
66import FormattedLink from "../../components/FormattedLink"
77import Main from "../../components/Main"
88import YouTube from "../../components/YouTube"
9- import { CharacterCurves , CostTemplates , getCharacterCurves , getCharacters , getCostTemplates , urlify } from "../../utils/data-cache"
10- import { elements , ElementType , getCharStatsAt , getCostsFromTemplate , image , isFullCharacter , stat , weapons } from "../../utils/utils"
9+ import { CharacterCurves , CostTemplates , getCharacterCurves , getCharacters , getCostTemplates } from "../../utils/data-cache"
1110import { Character , CharacterFull , CostTemplate , CurveEnum , Meta , Skills } from "../../utils/types"
11+ import { elements , ElementType , getCharStatsAt , getCostsFromTemplate , getGuidesFor , getLinkToGuide , image , isFullCharacter , stat , urlify , weapons } from "../../utils/utils"
1212import styles from "../style.module.css"
1313
1414interface Props {
1515 char : Character ,
1616 characterCurves : CharacterCurves | null
1717 costTemplates : CostTemplates | null
18+ guides ?: string [ ] [ ]
1819}
1920
20- export default function CharacterWebpage ( { char, location, characterCurves, costTemplates } : Props & { location : string } ) {
21+ export default function CharacterWebpage ( { char, location, characterCurves, costTemplates, guides } : Props & { location : string } ) {
2122 const charElems = char . skills ?. map ( skill => skill . ult ?. type ) . filter ( x => x ) as ElementType [ ] ?? [ char . meta . element ]
2223 return (
2324 < Main >
@@ -39,9 +40,10 @@ export default function CharacterWebpage({ char, location, characterCurves, cost
3940
4041 < div className = "float-right border-2 border-slate-500 dark:bg-slate-600 bg-slate-200 m-2 px-2" >
4142 Table of Contents
42- { isFullCharacter ( char ) && characterCurves && < TOC href = "#stats" title = "Stats / Ascensions " /> }
43- { char . meta && < TOC href = "#meta " title = "Meta " /> }
43+ { isFullCharacter ( char ) && characterCurves && < TOC href = "#stats" title = "Stats" /> }
44+ { char . ascensionCosts && costTemplates && < TOC href = "#ascensions " title = "Ascensions " /> }
4445 { char . media . videos && < TOC href = "#videos" title = { Object . keys ( char . media . videos ) . length > 1 ? "Videos" : "Video" } /> }
46+ { char . meta && < TOC href = "#meta" title = "Meta" /> }
4547 </ div >
4648
4749 < div id = "description" >
@@ -67,10 +69,11 @@ export default function CharacterWebpage({ char, location, characterCurves, cost
6769
6870 { char . ascensionCosts && < AscensionCosts costs = { char . ascensionCosts } /> }
6971 { char . skills && < TalentCosts skills = { char . skills } /> }
72+ { guides && guides . length > 0 && < Guides guides = { guides } /> }
7073 { isFullCharacter ( char ) && characterCurves && < Stats char = { char } curves = { characterCurves } /> }
7174 { char . ascensionCosts && costTemplates && < FullAscensionCosts template = { char . ascensionCosts } costTemplates = { costTemplates } /> }
72- { char . meta && < Meta meta = { char . meta } /> }
7375 { char . media . videos && < Videos videos = { char . media . videos } /> }
76+ { char . meta && < Meta meta = { char . meta } /> }
7477 </ div >
7578 </ Main >
7679 )
@@ -98,33 +101,43 @@ function AscensionCosts({ costs }: { costs: CostTemplate }) {
98101}
99102
100103function FullAscensionCosts ( { template, costTemplates } : { template : CostTemplate , costTemplates : CostTemplates } ) {
104+ const [ expanded , setExpanded ] = useState ( false )
101105 const costs = getCostsFromTemplate ( template , costTemplates )
102106
103107 return < >
104- < table className = { `table-auto w-full ${ styles . table } mb-2` } >
108+ < h3 className = "text-lg font-bold pt-1" id = "ascensions" > Ascensions:</ h3 >
109+ < table className = { `table-auto w-full ${ styles . table } mb-2 ${ expanded ? "" : "cursor-pointer" } ` } onClick = { ( ) => setExpanded ( true ) } >
105110 < thead className = "font-semibold divide-x divide-gray-200 dark:divide-gray-500" >
106111 < td > Asc.</ td >
107112 < td > Mora</ td >
108113 < td > Items</ td >
109114 </ thead >
110115 < tbody className = "divide-y divide-gray-200 dark:divide-gray-500" >
111- { costs . slice ( 1 ) . map ( ( { mora, items } , ind ) => {
112- let newItems = items
113- if ( ind == 0 && template . mapping . BossMat )
114- newItems = [ items [ 0 ] , { name : "" , count : 0 } , ...items . slice ( 1 ) ]
115- return < tr className = "pr-1 divide-x divide-gray-200 dark:divide-gray-500" key = { ind } >
116- < td > A{ ind + 1 } </ td >
117- < td className = "text-right" > { mora } </ td >
118- { newItems . map ( ( { count, name } ) => < td key = { name } >
119- { count > 0 &&
120- < div className = "flex flex-row align-middle items-center" >
121- < div > { count } ×</ div >
122- < div className = "pr-1 w-6 h-6 md:h-8 md:w-8" >
123- < img src = { image ( "material" , name ) } alt = { name } width = { 256 } height = { 256 } />
124- </ div >
125- < div > { name } </ div > </ div > }
126- </ td > ) }
127- </ tr > } ) }
116+ { costs
117+ . slice ( 1 )
118+ . map ( ( { mora, items } , ind ) => {
119+ let newItems = items
120+ if ( ind == 0 && template . mapping . BossMat )
121+ newItems = [ items [ 0 ] , { name : "" , count : 0 } , ...items . slice ( 1 ) ]
122+ return < tr className = "pr-1 divide-x divide-gray-200 dark:divide-gray-500" key = { ind } >
123+ < td > A{ ind + 1 } </ td >
124+ < td className = "text-right" > { mora } </ td >
125+ { newItems . map ( ( { count, name } ) => < td key = { name } >
126+ { count > 0 &&
127+ < div className = "flex flex-row align-middle items-center" >
128+ < div > { count } ×</ div >
129+ < div className = "pr-1 w-8 h-8 sm:h-6 sm:w-6 md:h-8 md:w-8" >
130+ < img src = { image ( "material" , name ) } alt = { name } width = { 256 } height = { 256 } />
131+ </ div >
132+ < div className = "md:text-sm lg:text-base sm:not-sr-only sr-only text-xs" > { name } </ div > </ div > }
133+ </ td > ) }
134+ </ tr >
135+ } )
136+ . filter ( ( _ , i , arr ) => expanded ? true : ( i == arr . length - 1 ) ) }
137+ { ! expanded && < tr className = "pr-1 cursor-pointer text-blue-700 dark:text-blue-300 hover:text-blue-400 dark:hover:text-blue-400 no-underline transition-all duration-200 font-semibold" >
138+ < td colSpan = { costs [ costs . length - 1 ] . items . length + 2 } style = { ( { textAlign : "center" } ) } > Click to expand...</ td >
139+ </ tr >
140+ }
128141 </ tbody >
129142 </ table >
130143 </ >
@@ -163,6 +176,8 @@ function TalentCosts({ skills }: { skills: Skills[] }) {
163176}
164177
165178function Stats ( { char, curves } : { char : CharacterFull , curves : Record < CurveEnum , number [ ] > } ) {
179+ const [ expanded , setExpanded ] = useState ( false )
180+
166181 const maxAscension = char . ascensions [ char . ascensions . length - 1 ]
167182
168183 const levels : { a : number , lv : number } [ ] = [ ]
@@ -176,19 +191,24 @@ function Stats({ char, curves }: { char: CharacterFull, curves: Record<CurveEnum
176191 const max = getCharStatsAt ( char , maxAscension . maxLevel , maxAscension . level , curves )
177192
178193 return < >
179- < h3 className = "text-lg font-bold pt-1" id = "stats" > Stats / Ascensions :</ h3 >
180- < table className = { `table-auto w-full ${ styles . table } ${ styles . stattable } mb-2` } >
194+ < h3 className = "text-lg font-bold pt-1" id = "stats" > Stats:</ h3 >
195+ < table className = { `table-auto w-full ${ styles . table } ${ styles . stattable } mb-2 ${ expanded ? "" : "cursor-pointer" } sm:text-sm md:text-base text-xs` } onClick = { ( ) => setExpanded ( true ) } >
181196 < thead className = "font-semibold divide-x divide-gray-200 dark:divide-gray-500" >
182197 < td > Asc.</ td >
183198 < td > Lv.</ td >
184199 { Object . keys ( max ) . map ( ( name ) => < td key = { name } > { name } </ td > ) }
185200 </ thead >
186201 < tbody className = "divide-y divide-gray-200 dark:divide-gray-500" >
187- { levels . map ( ( { a, lv } ) => < tr className = "pr-1 divide-x divide-gray-200 dark:divide-gray-500" key = { a + "," + lv } >
188- < td > A{ a } </ td >
189- < td > { lv } </ td >
190- { Object . entries ( getCharStatsAt ( char , lv , a , curves ) ) . map ( ( [ name , value ] ) => < td key = { name } > { stat ( name , value ) } </ td > ) }
191- </ tr > ) }
202+ { levels
203+ . filter ( ( r ) => expanded ? true : ( r . a == 0 && r . lv == 1 ) || ( r . a == maxAscension . level && r . lv == maxAscension . maxLevel ) )
204+ . map ( ( { a, lv } ) => < tr className = "pr-1 divide-x divide-gray-200 dark:divide-gray-500" key = { a + "," + lv } >
205+ < td > A{ a } </ td >
206+ < td > { lv } </ td >
207+ { Object . entries ( getCharStatsAt ( char , lv , a , curves ) ) . map ( ( [ name , value ] ) => < td key = { name } > { stat ( name , value ) } </ td > ) }
208+ </ tr > ) }
209+ { ! expanded && < tr className = "pr-1 cursor-pointer text-blue-700 dark:text-blue-300 hover:text-blue-400 dark:hover:text-blue-400 no-underline transition-all duration-200 font-semibold" >
210+ < td colSpan = { Object . keys ( getCharStatsAt ( char , 1 , 1 , curves ) ) . length + 2 } style = { ( { textAlign : "center" } ) } > Click to expand...</ td >
211+ </ tr > }
192212 </ tbody >
193213 </ table >
194214 </ >
@@ -242,6 +262,15 @@ function Video({ name, link }: { name: string, link: string }) {
242262 </ div >
243263}
244264
265+ function Guides ( { guides } : { guides : string [ ] [ ] } ) {
266+ const multiple = guides . length > 1
267+
268+ return < >
269+ < h3 className = "text-lg font-bold pt-1" id = "guides" > { multiple ? "Guides" : "Guide" } :</ h3 >
270+ { guides . map ( ( [ name , link ] ) => < div key = { name } > < FormattedLink href = { link } size = "base" > { name } </ FormattedLink > </ div > ) }
271+ </ >
272+ }
273+
245274export async function getStaticProps ( context : GetStaticPropsContext ) : Promise < GetStaticPropsResult < Props > > {
246275 const charName = context . params ?. name
247276 const data = await getCharacters ( )
@@ -269,11 +298,14 @@ export async function getStaticProps(context: GetStaticPropsContext): Promise<Ge
269298
270299 }
271300
301+ const guides = ( await getGuidesFor ( "character" , char . name ) ) ?. map ( ( { guide, page } ) => [ page . name , getLinkToGuide ( guide , page ) ] )
302+
272303 return {
273304 props : {
274305 char,
275306 characterCurves,
276- costTemplates
307+ costTemplates,
308+ guides
277309 } ,
278310 revalidate : 60 * 60
279311 }
0 commit comments