Add active/inactive styling to ClassPicker
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
- [ ] Add redux
|
- [ ] Add redux
|
||||||
- [ ] Prevent reducing talent points on a talent that is a requirement for another talent with points in it
|
|
||||||
- [ ] Talent tooltips
|
- [ ] Talent tooltips
|
||||||
- [ ] Generate URL for chosen talents
|
- [ ] Generate URL for chosen talents
|
||||||
- [ ] Responsive on mobile
|
- [ ] Responsive on mobile
|
||||||
- [ ] Pretty ClassPicker
|
- [ ] Pretty ClassPicker
|
||||||
- [x] Add react-router
|
- [x] Add react-router
|
||||||
- [x] Prevent reducing talent points on a row when it is a dependency for points already spent in the next row
|
- [x] Prevent reducing talent points on a row when it is a dependency for points already spent in the next row
|
||||||
|
- [x] Prevent reducing talent points on a talent that is a requirement for another talent with points in it
|
||||||
|
|||||||
+16
-6
@@ -3,7 +3,6 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.calculator {
|
.calculator {
|
||||||
|
|
||||||
&__points {
|
&__points {
|
||||||
color: white;
|
color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -40,15 +39,26 @@ body {
|
|||||||
|
|
||||||
.class-picker {
|
.class-picker {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
&__class {
|
&__class {
|
||||||
margin-right: 2em;
|
margin-right: 2em;
|
||||||
}
|
opacity: .8;
|
||||||
|
|
||||||
// TODO: Make BEM
|
&:hover {
|
||||||
a {
|
opacity: 1;
|
||||||
&.active {
|
}
|
||||||
font-weight: bold;
|
|
||||||
|
&--active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--inactive {
|
||||||
|
opacity: .4;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,39 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink, Link } from 'react-router-dom'
|
||||||
import { classByName } from '../data/classes'
|
import { classByName } from '../data/classes'
|
||||||
|
import { Icon } from './Icon'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
/** Name of the selected class, lowercase */
|
||||||
|
selected?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ClassPicker: React.FC<Props> = () => {
|
const classNameForItem = (c: ClassData, selected: string) => classNames('class-picker__class', {
|
||||||
return (
|
'class-picker__class--active': c.name.toLowerCase() === selected,
|
||||||
<ul className="class-picker">
|
'class-picker__class--inactive': !!selected && c.name.toLowerCase() !== selected
|
||||||
|
})
|
||||||
|
|
||||||
|
export class ClassPicker extends React.PureComponent<Props> {
|
||||||
|
static whyDidYouRender = true
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selected } = this.props
|
||||||
|
|
||||||
|
const cn = classNames('class-picker', {
|
||||||
|
'class-picker--has-selection': !!selected
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className={cn}>
|
||||||
{Object.values(classByName).map((c) =>
|
{Object.values(classByName).map((c) =>
|
||||||
<li key={c.id} className="class-picker__class">
|
<li key={c.id} className={classNameForItem(c, selected)}>
|
||||||
<NavLink to={`/${c.name.toLowerCase()}`}>{c.name}</NavLink>
|
<Link to={`/${c.name.toLowerCase()}`} title={c.name}>
|
||||||
|
<Icon name={c.icon} />
|
||||||
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,33 +1,29 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Calculator } from './Calculator'
|
import { Calculator } from './Calculator'
|
||||||
import { ClassPicker } from './ClassPicker'
|
import { ClassPicker } from './ClassPicker'
|
||||||
|
import { match } from 'react-router-dom'
|
||||||
|
import { RouteComponentProps } from 'react-router'
|
||||||
|
|
||||||
interface Props {
|
interface Props extends RouteComponentProps {
|
||||||
pointString?: string // e.g. 2305302300--001
|
match: match<{
|
||||||
match: any
|
selectedClass: string
|
||||||
history: any
|
pointString: string
|
||||||
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IndexRoute extends React.PureComponent<Props> {
|
export class IndexRoute extends React.PureComponent<Props> {
|
||||||
static whyDidYouRender = true
|
static whyDidYouRender = true
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { match, history } = this.props
|
const { match } = this.props
|
||||||
const { selectedClass, pointString } = match.params
|
const { selectedClass, pointString } = match.params
|
||||||
|
|
||||||
if (!selectedClass) {
|
|
||||||
history.replace('/warlock')
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="index">
|
<div className="index">
|
||||||
<ClassPicker />
|
<ClassPicker selected={selectedClass} />
|
||||||
|
|
||||||
{selectedClass &&
|
{selectedClass &&
|
||||||
<Calculator
|
<Calculator selectedClass={selectedClass} />
|
||||||
selectedClass={selectedClass}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
interface ClassData {
|
|
||||||
id: number
|
|
||||||
name: string
|
|
||||||
icon: string
|
|
||||||
specs: number[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const classes: ClassData[] = [
|
export const classes: ClassData[] = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|||||||
+9
-11
@@ -25,9 +25,9 @@ export function calcMeetsRequirements(talent: TalentData, known: Map<number, num
|
|||||||
if (talent.requires.length === 0) {
|
if (talent.requires.length === 0) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return talent.requires.reduce((prev, current) => {
|
return talent.requires.reduce((prev, req) => {
|
||||||
if (!prev) return false
|
if (!prev) return false
|
||||||
return known.get(current.id, 0) >= current.qty
|
return known.get(req.id, 0) >= req.qty
|
||||||
}, true)
|
}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,11 +74,14 @@ export const removeTalentPoint = (known: Map<number, number>, talent: TalentData
|
|||||||
return known
|
return known
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isDependency = false
|
||||||
let highestRow = 0
|
let highestRow = 0
|
||||||
let cumulativePointsPerRow = {}
|
let cumulativePointsPerRow = {}
|
||||||
|
|
||||||
known.forEach((points, talentId) => {
|
known.forEach((points, talentId) => {
|
||||||
const t = talentsBySpec[specId][talentId]
|
const t = talentsBySpec[specId][talentId]
|
||||||
if (t) {
|
if (t) {
|
||||||
|
isDependency = isDependency || t.requires.some((req) => req.id === talent.id)
|
||||||
highestRow = t.row > highestRow ? t.row : highestRow
|
highestRow = t.row > highestRow ? t.row : highestRow
|
||||||
for (let row = t.row; row < MAX_ROWS; row++) {
|
for (let row = t.row; row < MAX_ROWS; row++) {
|
||||||
cumulativePointsPerRow[row] = (cumulativePointsPerRow[row] || 0) + points
|
cumulativePointsPerRow[row] = (cumulativePointsPerRow[row] || 0) + points
|
||||||
@@ -93,15 +96,10 @@ export const removeTalentPoint = (known: Map<number, number>, talent: TalentData
|
|||||||
return known
|
return known
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Prevent if another talent depends on this
|
// Prevent if another talent depends on this
|
||||||
// const isDependency = known.reduce((prev, current, key) => {
|
if (isDependency) {
|
||||||
// if (prev) return prev
|
return known
|
||||||
// const t = talentsBySpec[specId][key]
|
}
|
||||||
// if (t.requires.length === 0) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
// t.requires.map((d) => d.id === talent.id ? d : undefined)
|
|
||||||
// }, false)
|
|
||||||
|
|
||||||
return currentPoints === 1
|
return currentPoints === 1
|
||||||
? known.remove(talent.id)
|
? known.remove(talent.id)
|
||||||
|
|||||||
Vendored
+7
@@ -5,6 +5,13 @@ interface TalentTree {
|
|||||||
talents: Talent[]
|
talents: Talent[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ClassData {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
icon: string
|
||||||
|
specs: number[]
|
||||||
|
}
|
||||||
|
|
||||||
interface TalentData {
|
interface TalentData {
|
||||||
/** ID for the Talent */
|
/** ID for the Talent */
|
||||||
id: number
|
id: number
|
||||||
|
|||||||
Reference in New Issue
Block a user