From c354c8840c891915429d0f1a0cfecbb05c024d1b Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sun, 27 Nov 2022 18:55:31 -0800 Subject: [PATCH 01/41] Ignore job skill images --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e6fbad6e..34d553d3 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,7 @@ dist/ public/images/weapon* public/images/summon* public/images/chara* -public/images/jobs +public/images/job* # Typescript v1 declaration files typings/ From 5598e7246388c3d118a659d3bd0b06f97e792951 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sun, 27 Nov 2022 18:55:51 -0800 Subject: [PATCH 02/41] Add JobSkill type --- types/JobSkill.d.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 types/JobSkill.d.ts diff --git a/types/JobSkill.d.ts b/types/JobSkill.d.ts new file mode 100644 index 00000000..412000ce --- /dev/null +++ b/types/JobSkill.d.ts @@ -0,0 +1,16 @@ +interface JobSkill { + id: string + job: Job + name: { + [key: string]: string + en: string + ja: string + } + slug: string + group: number + main: boolean + base: boolean + sub: boolean + emp: boolean + order: number +} From 5d4ca78ddab16df3418a3724548317c9c64bec5e Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sun, 27 Nov 2022 20:18:38 -0800 Subject: [PATCH 03/41] Add endpoint for fetching skills --- utils/api.tsx | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/utils/api.tsx b/utils/api.tsx index 0fd196a7..8563cf1f 100644 --- a/utils/api.tsx +++ b/utils/api.tsx @@ -25,7 +25,7 @@ class Api { url: string endpoints: { [key: string]: EndpointMap } - constructor({url}: {url: string}) { + constructor({ url }: { url: string }) { this.url = url this.endpoints = {} } @@ -92,6 +92,12 @@ class Api { const resourceUrl = `${this.url}/characters/resolve` return axios.post(resourceUrl, body, { headers: params }) } + + allSkills(params: {}) { + const resourceUrl = `${this.url}/jobs/skills` + return axios.get(resourceUrl, params) + } + savedTeams(params: {}) { const resourceUrl = `${this.url}/parties/favorites` return axios.get(resourceUrl, params) @@ -127,15 +133,15 @@ class Api { } const api: Api = new Api({ url: process.env.NEXT_PUBLIC_SIERO_API_URL || 'https://localhost:3000/api/v1'}) -api.createEntity( { name: 'users' }) -api.createEntity( { name: 'parties' }) -api.createEntity( { name: 'grid_weapons' }) -api.createEntity( { name: 'characters' }) -api.createEntity( { name: 'weapons' }) -api.createEntity( { name: 'summons' }) -api.createEntity( { name: 'jobs' }) -api.createEntity( { name: 'raids' }) -api.createEntity( { name: 'weapon_keys' }) -api.createEntity( { name: 'favorites' }) +api.createEntity({ name: 'users' }) +api.createEntity({ name: 'parties' }) +api.createEntity({ name: 'grid_weapons' }) +api.createEntity({ name: 'characters' }) +api.createEntity({ name: 'weapons' }) +api.createEntity({ name: 'summons' }) +api.createEntity({ name: 'jobs' }) +api.createEntity({ name: 'raids' }) +api.createEntity({ name: 'weapon_keys' }) +api.createEntity({ name: 'favorites' }) export default api From 1d571f1a21d19060f6cd125b4f769d608f3c1357 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sun, 27 Nov 2022 20:19:18 -0800 Subject: [PATCH 04/41] Register jobs and skills in app state --- utils/appState.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/appState.tsx b/utils/appState.tsx index 3a6725a6..9ba87f54 100644 --- a/utils/appState.tsx +++ b/utils/appState.tsx @@ -53,6 +53,8 @@ interface AppState { } } raids: Raid[] + jobs: Job[] + jobSkills: JobSkill[] } export const initialAppState: AppState = { @@ -91,6 +93,8 @@ export const initialAppState: AppState = { }, }, raids: [], + jobs: [], + jobSkills: [], } export const appState = proxy(initialAppState) From c599a8352a72c7ce69f173e1beff62c62951bf94 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sun, 27 Nov 2022 20:24:47 -0800 Subject: [PATCH 05/41] Fetch and store the jobs and skills in app state --- pages/new/index.tsx | 26 +++++++++++++++++++++++++- pages/p/[party].tsx | 28 +++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/pages/new/index.tsx b/pages/new/index.tsx index b429e8f4..a4208a7e 100644 --- a/pages/new/index.tsx +++ b/pages/new/index.tsx @@ -1,13 +1,17 @@ -import React from "react" +import React, { useEffect } from "react" import { getCookie } from "cookies-next" import { serverSideTranslations } from "next-i18next/serverSideTranslations" import Party from "~components/Party" + +import { appState } from "~utils/appState" import api from "~utils/api" import type { NextApiRequest, NextApiResponse } from "next" interface Props { + jobs: Job[] + jobSkills: JobSkill[] raids: Raid[] sortedRaids: Raid[][] } @@ -18,6 +22,17 @@ const NewRoute: React.FC = (props: Props) => { window.history.replaceState(null, `Grid Tool`, `${path}`) } + useEffect(() => { + persistStaticData() + }, [persistStaticData]) + + function persistStaticData() { + console.log("Persisting static data...") + appState.raids = props.raids + appState.jobs = props.jobs + appState.jobSkills = props.jobSkills + } + return (
@@ -51,8 +66,17 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex .getAll({ params: headers }) .then((response) => organizeRaids(response.data.map((r: any) => r.raid))) + let jobs = await api.endpoints.jobs + .getAll({ params: headers }) + .then((response) => { return response.data }) + + let jobSkills = await api.allSkills(headers) + .then((response) => { return response.data }) + return { props: { + jobs: jobs, + jobSkills: jobSkills, raids: raids, sortedRaids: sortedRaids, ...(await serverSideTranslations(locale, ["common"])), diff --git a/pages/p/[party].tsx b/pages/p/[party].tsx index 9a37db1f..4c412bf6 100644 --- a/pages/p/[party].tsx +++ b/pages/p/[party].tsx @@ -1,20 +1,34 @@ -import React from "react" +import React, { useEffect } from "react" import { getCookie } from "cookies-next" import { serverSideTranslations } from "next-i18next/serverSideTranslations" import Party from "~components/Party" +import { appState } from "~utils/appState" import api from "~utils/api" import type { NextApiRequest, NextApiResponse } from "next" interface Props { party: Party + jobs: Job[] + jobSkills: JobSkill[] raids: Raid[] sortedRaids: Raid[][] } const PartyRoute: React.FC = (props: Props) => { + useEffect(() => { + persistStaticData() + }, [persistStaticData]) + + function persistStaticData() { + console.log("Persisting static data...") + appState.raids = props.raids + appState.jobs = props.jobs + appState.jobSkills = props.jobSkills + } + return (
@@ -48,6 +62,16 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex .getAll() .then((response) => organizeRaids(response.data.map((r: any) => r.raid))) + let jobs = await api.endpoints.jobs + .getAll({ params: headers }) + .then((response) => { + return response.data + }) + + let jobSkills = await api.allSkills(headers).then((response) => { + return response.data + }) + let party: Party | null = null if (query.party) { let response = await api.endpoints.parties.getOne({ id: query.party, params: headers }) @@ -59,6 +83,8 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex return { props: { party: party, + job: jobs, + jobSkills: jobSkills, raids: raids, sortedRaids: sortedRaids, ...(await serverSideTranslations(locale, ["common"])), From 79a0095d225b537360b1708b1625b2fdf04d35d6 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 28 Nov 2022 20:36:12 -0800 Subject: [PATCH 06/41] Add basic interface for skills Skills change when the job changes, but can't be selected on their own yet --- components/JobDropdown/index.tsx | 129 +++++++++++++++-------------- components/JobSection/index.scss | 95 ++++++++++++--------- components/JobSection/index.tsx | 117 ++++++++++++++++---------- components/JobSkillItem/index.scss | 42 ++++++++++ components/JobSkillItem/index.tsx | 52 ++++++++++++ 5 files changed, 291 insertions(+), 144 deletions(-) create mode 100644 components/JobSkillItem/index.scss create mode 100644 components/JobSkillItem/index.tsx diff --git a/components/JobDropdown/index.tsx b/components/JobDropdown/index.tsx index b0a6019f..187b9de5 100644 --- a/components/JobDropdown/index.tsx +++ b/components/JobDropdown/index.tsx @@ -1,25 +1,25 @@ -import React, { useCallback, useEffect, useState } from 'react' -import { useRouter } from 'next/router' +import React, { useEffect, useState } from "react" +import { useRouter } from "next/router" -import api from '~utils/api' -import { appState } from '~utils/appState' -import { jobGroups } from '~utils/jobGroups' +import { appState } from "~utils/appState" +import { jobGroups } from "~utils/jobGroups" -import './index.scss' +import "./index.scss" // Props interface Props { - currentJob?: string - onChange?: (job?: Job) => void - onBlur?: (event: React.ChangeEvent) => void + currentJob?: string + onChange?: (job?: Job) => void + onBlur?: (event: React.ChangeEvent) => void } type GroupedJob = { [key: string]: Job[] } -const JobDropdown = React.forwardRef(function useFieldSet(props, ref) { +const JobDropdown = React.forwardRef( + function useFieldSet(props, ref) { // Set up router for locale const router = useRouter() - const locale = router.locale || 'en' + const locale = router.locale || "en" // Set up local states for storing jobs const [currentJob, setCurrentJob] = useState() @@ -27,71 +27,78 @@ const JobDropdown = React.forwardRef(function useField const [sortedJobs, setSortedJobs] = useState() // Organize jobs into groups on mount - const organizeJobs = useCallback((jobs: Job[]) => { - const jobGroups = jobs.map(job => job.row).filter((value, index, self) => self.indexOf(value) === index) - let groupedJobs: GroupedJob = {} - - jobGroups.forEach(group => { - groupedJobs[group] = jobs.filter(job => job.row === group) - }) - - setJobs(jobs) - setSortedJobs(groupedJobs) - appState.jobs = jobs - }, []) - - // Fetch all jobs on mount useEffect(() => { - api.endpoints.jobs.getAll() - .then(response => organizeJobs(response.data)) - }, [organizeJobs]) + const jobGroups = appState.jobs + .map((job) => job.row) + .filter((value, index, self) => self.indexOf(value) === index) + let groupedJobs: GroupedJob = {} + + jobGroups.forEach((group) => { + groupedJobs[group] = appState.jobs.filter((job) => job.row === group) + }) + + setJobs(appState.jobs) + setSortedJobs(groupedJobs) + }, [appState]) // Set current job on mount useEffect(() => { - if (jobs && props.currentJob) { - const job = jobs.find(job => job.id === props.currentJob) - setCurrentJob(job) - } - }, [jobs, props.currentJob]) + if (jobs && props.currentJob) { + const job = appState.jobs.find((job) => job.id === props.currentJob) + setCurrentJob(job) + } + }, [appState, props.currentJob]) // Enable changing select value function handleChange(event: React.ChangeEvent) { - if (jobs) { - const job = jobs.find(job => job.id === event.target.value) - if (props.onChange) props.onChange(job) - setCurrentJob(job) - } + if (jobs) { + const job = jobs.find((job) => job.id === event.target.value) + if (props.onChange) props.onChange(job) + setCurrentJob(job) + } } // Render JSX for each job option, sorted into optgroups function renderJobGroup(group: string) { - const options = sortedJobs && sortedJobs[group].length > 0 && - sortedJobs[group].sort((a, b) => a.order - b.order).map((item, i) => { - return ( - - ) - }) + const options = + sortedJobs && + sortedJobs[group].length > 0 && + sortedJobs[group] + .sort((a, b) => a.order - b.order) + .map((item, i) => { + return ( + + ) + }) - const groupName = jobGroups.find(g => g.slug === group)?.name[locale] + const groupName = jobGroups.find((g) => g.slug === group)?.name[locale] - return ( - - {options} - - ) + return ( + + {options} + + ) } - + return ( - + ) -}) + } +) export default JobDropdown diff --git a/components/JobSection/index.scss b/components/JobSection/index.scss index bf1e710c..9348ecb2 100644 --- a/components/JobSection/index.scss +++ b/components/JobSection/index.scss @@ -1,44 +1,65 @@ #Job { + display: flex; + margin-bottom: $unit * 3; + + select { + flex-grow: 1; + width: auto; + } + + .JobDetails { display: flex; - margin-bottom: $unit * 3; + flex-direction: column; + width: 100%; select { - flex-grow: 1; - width: auto; + flex-grow: 0; } - .JobImage { - $height: 249px; - $width: 447px; - - background: url('/images/background_a.jpg'); - background-size: 500px 281px; - border-radius: $unit; - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); - display: block; - flex-grow: 2; - height: $height; - margin-right: $unit * 3; - max-height: $height; - max-width: $width; - overflow: hidden; - position: relative; - width: $width; - transition: box-shadow 0.15s ease-in-out; - - img { - position: relative; - top: $unit * -4; - left: 50%; - transform: translateX(-50%); - width: 100%; - z-index: 2; - } - - .Overlay { - background: rgba(255, 255, 255, 0.12); - position: absolute; - z-index: 1; - } + .JobSkills { + flex-grow: 2; } -} \ No newline at end of file + } + + .JobImage { + $height: 249px; + $width: 447px; + + background: url("/images/background_a.jpg"); + background-size: 500px 281px; + border-radius: $unit; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + display: block; + flex-grow: 2; + flex-shrink: 0; + height: $height; + margin-right: $unit * 3; + max-height: $height; + max-width: $width; + overflow: hidden; + position: relative; + width: $width; + transition: box-shadow 0.15s ease-in-out; + + img { + position: relative; + top: $unit * -4; + left: 50%; + transform: translateX(-50%); + width: 100%; + z-index: 2; + } + + .Overlay { + background: rgba(255, 255, 255, 0.12); + position: absolute; + z-index: 1; + } + } + + .JobSkills { + display: flex; + flex-direction: column; + gap: $unit; + } +} diff --git a/components/JobSection/index.tsx b/components/JobSection/index.tsx index 464f261f..1bd64ce1 100644 --- a/components/JobSection/index.tsx +++ b/components/JobSection/index.tsx @@ -1,64 +1,89 @@ -import React, { useEffect, useState } from 'react' -import { useSnapshot } from 'valtio' +import React, { useEffect, useState } from "react" +import { useSnapshot } from "valtio" -import JobDropdown from '~components/JobDropdown' +import JobDropdown from "~components/JobDropdown" +import JobSkillItem from "~components/JobSkillItem" -import { appState } from '~utils/appState' +import { appState } from "~utils/appState" -import './index.scss' +import "./index.scss" // Props interface Props {} const JobSection = (props: Props) => { - const [job, setJob] = useState() - const [imageUrl, setImageUrl] = useState('') + const [job, setJob] = useState() + const [imageUrl, setImageUrl] = useState("") - const { party } = useSnapshot(appState) + const { party } = useSnapshot(appState) - useEffect(() => { - // Set current job based on ID - setJob(party.job) - }, []) + const [numSkills, setNumSkills] = useState(4) + const [skills, setSkills] = useState([]) - useEffect(() => { - generateImageUrl() - }) + useEffect(() => { + // Set current job based on ID + setJob(party.job) + }, []) - useEffect(() => { - if (job) appState.party.job = job - }, [job]) + useEffect(() => { + generateImageUrl() + }) - function receiveJob(job?: Job) { - setJob(job) + useEffect(() => { + if (job) appState.party.job = job + }, [job]) + + function receiveJob(job?: Job) { + console.log(`Receiving job! Row ${job?.row}: ${job?.name.en}`) + if (job) { + setJob(job) + + const baseSkills = appState.jobSkills.filter( + (skill) => skill.job.id === job.id && skill.main + ) + + if (job.row === "1") setNumSkills(3) + else setNumSkills(4) + + setSkills(baseSkills) + } + } + + function generateImageUrl() { + let imgSrc = "" + + if (job) { + const slug = job?.name.en.replaceAll(" ", "-").toLowerCase() + const gender = party.user && party.user.gender == 1 ? "b" : "a" + + imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/jobs/${slug}_${gender}.png` } - function generateImageUrl() { - let imgSrc = "" - - if (job) { - const slug = job?.name.en.replaceAll(' ', '-').toLowerCase() - const gender = (party.user && party.user.gender == 1) ? 'b' : 'a' + setImageUrl(imgSrc) + } - imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/jobs/${slug}_${gender}.png` - } - - setImageUrl(imgSrc) - } - - // Render: JSX components - return ( -
-
- -
-
- -
- ) + // Render: JSX components + return ( +
+
+ +
+
+
+ +
    + {[...Array(numSkills)].map((e, i) => ( +
  • + +
  • + ))} +
+
+
+ ) } -export default JobSection \ No newline at end of file +export default JobSection diff --git a/components/JobSkillItem/index.scss b/components/JobSkillItem/index.scss new file mode 100644 index 00000000..3d944180 --- /dev/null +++ b/components/JobSkillItem/index.scss @@ -0,0 +1,42 @@ +.JobSkill { + display: flex; + gap: $unit; + align-items: center; + + &:hover p.placeholder { + color: $grey-20; + } + + &.editable:hover > img, + &.editable:hover > .placeholder { + border: $hover-stroke; + box-shadow: $hover-shadow; + cursor: pointer; + transform: $scale-tall; + } + + & > img, + & > .placeholder { + background: white; + border-radius: calc($unit / 2); + border: 1px solid rgba(0, 0, 0, 0); + width: $unit * 5; + height: $unit * 5; + } + + & > .placeholder { + display: flex; + align-items: center; + justify-content: center; + + & > svg { + fill: $grey-60; + width: $unit * 2; + height: $unit * 2; + } + } + + p.placeholder { + color: $grey-50; + } +} diff --git a/components/JobSkillItem/index.tsx b/components/JobSkillItem/index.tsx new file mode 100644 index 00000000..b1238863 --- /dev/null +++ b/components/JobSkillItem/index.tsx @@ -0,0 +1,52 @@ +import React from "react" +import { useRouter } from "next/router" +import { useTranslation } from "next-i18next" + +import classNames from "classnames" + +import PlusIcon from "~public/icons/Add.svg" + +import "./index.scss" + +// Props +interface Props { + skill?: JobSkill + editable: boolean +} + +const JobSkillItem = (props: Props) => { + const router = useRouter() + const { t } = useTranslation("common") + const locale = + router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en" + + const classes = classNames({ + JobSkill: true, + editable: props.editable, + }) + + return ( +
+ {props.skill ? ( + {props.skill.name[locale]} + ) : ( +
+ +
+ )} +
+ {/* {props.skill ?
Grouping
: ""} */} + {props.skill ? ( +

{props.skill.name[locale]}

+ ) : ( +

Select a skill

+ )} +
+
+ ) +} + +export default JobSkillItem From 235f36814fe4fccb7c19d9401906beedda9464af Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 29 Nov 2022 00:58:48 -0800 Subject: [PATCH 07/41] Fix name of color attribute on JobSkill --- types/JobSkill.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/JobSkill.d.ts b/types/JobSkill.d.ts index 412000ce..f1067964 100644 --- a/types/JobSkill.d.ts +++ b/types/JobSkill.d.ts @@ -7,7 +7,7 @@ interface JobSkill { ja: string } slug: string - group: number + color: number main: boolean base: boolean sub: boolean From 5d6ca051439df10089f2cad36f944a48098d6416 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 29 Nov 2022 00:59:28 -0800 Subject: [PATCH 08/41] Add different groupings of skills `skillClassification` is for pills shown in results `skillGroups` is for the dropdown that filters all skills --- utils/skillGroups.tsx | 91 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 utils/skillGroups.tsx diff --git a/utils/skillGroups.tsx b/utils/skillGroups.tsx new file mode 100644 index 00000000..63d6ccd2 --- /dev/null +++ b/utils/skillGroups.tsx @@ -0,0 +1,91 @@ +export interface SkillGroup { + id: number + name: { + [key: string]: string + en: string + ja: string + } +} + +export const skillClassification: SkillGroup[] = [ + { + id: 0, + name: { + en: "Buffing", + ja: "強化アビリティ", + }, + }, + { + id: 1, + name: { + en: "Debuffing", + ja: "弱体アビリティ", + }, + }, + { + id: 2, + name: { + en: "Damaging", + ja: "ダメージアビリティ", + }, + }, + { + id: 3, + name: { + en: "Healing", + ja: "回復アビリティ", + }, + }, + { + id: 4, + name: { + en: "Field", + ja: "フィールドアビリティ", + }, + }, +] + +export const skillGroups: SkillGroup[] = [ + { + id: 0, + name: { + en: "Buffing", + ja: "強化アビリティ", + }, + }, + { + id: 1, + name: { + en: "Debuffing", + ja: "弱体アビリティ", + }, + }, + { + id: 2, + name: { + en: "Damaging", + ja: "ダメージアビリティ", + }, + }, + { + id: 3, + name: { + en: "Healing", + ja: "回復アビリティ", + }, + }, + { + id: 4, + name: { + en: "Extended Mastery", + ja: "リミットアビリティ", + }, + }, + { + id: 5, + name: { + en: "Base", + ja: "ベースアビリティ", + }, + }, +] From ab28d8c4bfcff0d1768fc5d872c8f9f1b9b8ed45 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 29 Nov 2022 00:59:47 -0800 Subject: [PATCH 09/41] Added JobSkillResult component --- components/JobSkillResult/index.scss | 71 ++++++++++++++++++++++++++++ components/JobSkillResult/index.tsx | 41 ++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 components/JobSkillResult/index.scss create mode 100644 components/JobSkillResult/index.tsx diff --git a/components/JobSkillResult/index.scss b/components/JobSkillResult/index.scss new file mode 100644 index 00000000..c8308b05 --- /dev/null +++ b/components/JobSkillResult/index.scss @@ -0,0 +1,71 @@ +.JobSkillResult { + border-radius: 6px; + display: flex; + gap: $unit; + padding: $unit * 1.5; + align-items: center; + + &:hover { + background: $grey-90; + cursor: pointer; + + .Info .skill.pill { + background: $grey-80; + } + } + + .Info { + display: flex; + flex-direction: row; + gap: calc($unit / 2); + width: 100%; + + .skill.pill { + background: $grey-90; + border-radius: $unit * 2; + color: $grey-00; + display: inline; + font-size: $font-tiny; + font-weight: $medium; + padding: calc($unit / 2) $unit; + + &.buffing { + background-color: $light-bg-dark; + color: $light-text-dark; + } + + &.debuffing { + background-color: $water-bg-dark; + color: $water-text-dark; + } + + &.healing { + background-color: $wind-bg-dark; + color: $wind-text-dark; + } + + &.damaging { + background-color: $fire-bg-dark; + color: $fire-text-dark; + } + + &.field { + background-color: $dark-bg-dark; + color: $dark-text-dark; + } + } + + h5 { + color: #555; + display: inline-block; + font-size: $font-medium; + font-weight: $medium; + flex-grow: 1; + } + } + + img { + width: $unit * 6; + height: $unit * 6; + } +} diff --git a/components/JobSkillResult/index.tsx b/components/JobSkillResult/index.tsx new file mode 100644 index 00000000..09c08028 --- /dev/null +++ b/components/JobSkillResult/index.tsx @@ -0,0 +1,41 @@ +import React, { useEffect, useState } from "react" +import { useRouter } from "next/router" +import { SkillGroup, skillClassification } from "~utils/skillGroups" + +import "./index.scss" + +interface Props { + data: JobSkill + onClick: () => void +} + +const JobSkillResult = (props: Props) => { + const router = useRouter() + const locale = + router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en" + + const skill = props.data + + const [group, setGroup] = useState() + + useEffect(() => { + setGroup(skillClassification.find((group) => group.id === skill.color)) + }, [skill, setGroup, skillClassification]) + + const jobSkillUrl = () => + `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-skills/${skill.slug}.png` + + return ( +
  • + {skill.name[locale]} +
    +
    {skill.name[locale]}
    +
    + {group?.name[locale]} +
    +
    +
  • + ) +} + +export default JobSkillResult From 7e6e9f244ac34563a744e1da8d401ccc3c6a4dd5 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 29 Nov 2022 01:00:52 -0800 Subject: [PATCH 10/41] Add JobSkillModal component --- components/JobSkillModal/index.scss | 16 +++ components/JobSkillModal/index.tsx | 203 ++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 components/JobSkillModal/index.scss create mode 100644 components/JobSkillModal/index.tsx diff --git a/components/JobSkillModal/index.scss b/components/JobSkillModal/index.scss new file mode 100644 index 00000000..58615f4d --- /dev/null +++ b/components/JobSkillModal/index.scss @@ -0,0 +1,16 @@ +#Header #Bar select { + background-color: $grey-90; +} +#Header label { + margin: 0 $unit * 3; + + .Input { + border: 1px solid $grey-80; + border-radius: calc($unit / 1.5); + box-sizing: border-box; + font-size: $font-regular; + padding: $unit * 1.5; + text-align: left; + width: 100%; + } +} diff --git a/components/JobSkillModal/index.tsx b/components/JobSkillModal/index.tsx new file mode 100644 index 00000000..415ff74f --- /dev/null +++ b/components/JobSkillModal/index.tsx @@ -0,0 +1,203 @@ +import React, { useEffect, useState } from "react" +import { getCookie, setCookie } from "cookies-next" +import { useRouter } from "next/router" +import { useSnapshot } from "valtio" +import { useTranslation } from "react-i18next" +import InfiniteScroll from "react-infinite-scroll-component" + +import { appState } from "~utils/appState" +import { skillGroups } from "~utils/skillGroups" + +import * as Dialog from "@radix-ui/react-dialog" +import JobSkillResult from "~components/JobSkillResult" + +import CrossIcon from "~public/icons/Cross.svg" + +import "./index.scss" + +interface Props { + send: (skill: JobSkill, position: number) => any + job?: Job + fromPosition: number + children: React.ReactNode +} + +const JobSkillModal = (props: Props) => { + // Set up router + const router = useRouter() + const locale = router.locale + + // Set up translation + const { t } = useTranslation("common") + + let searchInput = React.createRef() + let scrollContainer = React.createRef() + + const [currentGroup, setCurrentGroup] = useState(-1) + const [currentGroupName, setCurrentGroupName] = useState("") + const [open, setOpen] = useState(false) + const [query, setQuery] = useState("") + const [results, setResults] = useState([]) + + // Pagination states + const [recordCount, setRecordCount] = useState(0) + const [currentPage, setCurrentPage] = useState(1) + const [totalPages, setTotalPages] = useState(1) + + useEffect(() => { + setResults(appState.jobSkills.filter((skill) => skill.main === false)) + setRecordCount( + appState.jobSkills.filter((skill) => skill.main === false).length + ) + }, [appState, setResults]) + + useEffect(() => { + if (searchInput.current) searchInput.current.focus() + }, [searchInput]) + + useEffect(() => { + setRecordCount(results.length) + }, [results]) + + useEffect(() => { + const name = skillGroups + .find((skill) => skill.id === currentGroup) + ?.name["en"].toLowerCase() + setCurrentGroupName(name ? name : "") + }, [currentGroup]) + + function onChange(event: React.ChangeEvent) { + const newValue = parseInt(event.target.value) + setCurrentGroup(newValue) + + if (newValue >= 0) { + setResults( + appState.jobSkills.filter((skill, i) => { + if (newValue === 4) { + return skill.emp && !skill.main + } else if (newValue === 5) { + return skill.base && !skill.main + } else { + return skill.color === newValue && !skill.main + } + }) + ) + } else { + setResults(appState.jobSkills.filter((skill) => skill.main === false)) + } + } + + function inputChanged(event: React.ChangeEvent) { + const text = event.target.value + if (text.length) { + setQuery(text) + } else { + setQuery("") + } + } + + function openChange() { + if (open) { + setQuery("") + // setFirstLoad(true) + setResults([]) + setRecordCount(0) + setCurrentPage(1) + setOpen(false) + } else { + setOpen(true) + } + } + + function onBlur() {} + + function render() { + const rows = results.map((result: JobSkill, i: number) => { + return ( + {}} /> + ) + }) + return ( + 0 ? results.length : 0} + next={() => setCurrentPage(currentPage + 1)} + hasMore={totalPages > currentPage} + scrollableTarget="Results" + loader={
    Loading...
    } + > + {rows} +
    + ) + } + return ( + + {props.children} + + + + +
    +
    + {t("search.result_count", { record_count: recordCount })} +
    + {open ? render() : ""} +
    +
    + +
    +
    + ) +} + +export default JobSkillModal From bf04d951bd9098dc0484be739186ddc77420974e Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 29 Nov 2022 02:05:34 -0800 Subject: [PATCH 11/41] Fix CSS bug --- components/JobSkillModal/index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/JobSkillModal/index.scss b/components/JobSkillModal/index.scss index 58615f4d..136f26b8 100644 --- a/components/JobSkillModal/index.scss +++ b/components/JobSkillModal/index.scss @@ -1,7 +1,7 @@ #Header #Bar select { background-color: $grey-90; } -#Header label { +#Header > label { margin: 0 $unit * 3; .Input { From 89e157dc6d4f85513d4d61f969dd13f32296555a Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 29 Nov 2022 02:05:53 -0800 Subject: [PATCH 12/41] Refactor CSS --- components/JobSkillItem/index.scss | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/components/JobSkillItem/index.scss b/components/JobSkillItem/index.scss index 3d944180..55cd1ea5 100644 --- a/components/JobSkillItem/index.scss +++ b/components/JobSkillItem/index.scss @@ -3,20 +3,24 @@ gap: $unit; align-items: center; - &:hover p.placeholder { - color: $grey-20; - } - - &.editable:hover > img, - &.editable:hover > .placeholder { - border: $hover-stroke; - box-shadow: $hover-shadow; + &.editable:hover { cursor: pointer; - transform: $scale-tall; + + & > img, + & > div.placeholder { + border: $hover-stroke; + box-shadow: $hover-shadow; + cursor: pointer; + transform: $scale-tall; + } + + & p.placeholder { + color: $grey-20; + } } & > img, - & > .placeholder { + & > div.placeholder { background: white; border-radius: calc($unit / 2); border: 1px solid rgba(0, 0, 0, 0); @@ -24,7 +28,7 @@ height: $unit * 5; } - & > .placeholder { + & > div.placeholder { display: flex; align-items: center; justify-content: center; From 322964d7677ae781ed42d6f946cd853b6015fe98 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 05:17:57 -0800 Subject: [PATCH 13/41] Update translations --- public/locales/en/common.json | 12 +++++++++++- public/locales/ja/common.json | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index f43a79a0..67cbd939 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -232,7 +232,8 @@ "placeholders": { "weapon": "Search for a weapon...", "summon": "Search for a summon...", - "character": "Search for a character..." + "character": "Search for a character...", + "job_skill": "Search job skills..." } }, "teams": { @@ -240,6 +241,15 @@ "loading": "Loading teams...", "not_found": "No teams found" }, + "job_skills": { + "all": "All skills", + "buffing": "Buffing", + "debuffing": "Debuffing", + "damaging": "Damaging", + "healing": "Healing", + "emp": "Extended Mastery", + "base": "Base Skills" + }, "extra_weapons": "Additional Weapons", "coming_soon": "Coming Soon", "no_title": "Untitled", diff --git a/public/locales/ja/common.json b/public/locales/ja/common.json index 21d147bc..04f7ba36 100644 --- a/public/locales/ja/common.json +++ b/public/locales/ja/common.json @@ -233,7 +233,8 @@ "placeholders": { "weapon": "武器を検索...", "summon": "召喚石を検索...", - "character": "キャラを検索..." + "character": "キャラを検索...", + "job_skill": "ジョブのスキルを検索..." } }, "teams": { @@ -241,6 +242,15 @@ "loading": "ロード中...", "not_found": "編成は見つかりませんでした" }, + "job_skills": { + "all": "全てのアビリティ", + "buffing": "強化アビリティ", + "debuffing": "弱体アビリティ", + "damaging": "ダメージアビリティ", + "healing": "回復アビリティ", + "emp": "リミットアビリティ", + "base": "ベースアビリティ" + }, "extra_weapons": "Additional
    Weapons", "coming_soon": "開発中", "no_title": "無題", From 73944becf4674ea67caeb432885e69b16b8350dd Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 05:19:43 -0800 Subject: [PATCH 14/41] Add type alias for searchable objects --- components/CharacterUnit/index.tsx | 207 ++++++++++++++------------- components/SearchModal/index.tsx | 34 +++-- components/SummonUnit/index.tsx | 217 +++++++++++++++------------- components/WeaponUnit/index.tsx | 222 +++++++++++++++-------------- types/index.d.ts | 2 + 5 files changed, 368 insertions(+), 314 deletions(-) create mode 100644 types/index.d.ts diff --git a/components/CharacterUnit/index.tsx b/components/CharacterUnit/index.tsx index 337357e3..13e46635 100644 --- a/components/CharacterUnit/index.tsx +++ b/components/CharacterUnit/index.tsx @@ -1,130 +1,137 @@ -import React, { useEffect, useState } from 'react' -import { useRouter } from 'next/router' -import { useSnapshot } from 'valtio' -import { useTranslation } from 'next-i18next' -import classnames from 'classnames' +import React, { useEffect, useState } from "react" +import { useRouter } from "next/router" +import { useSnapshot } from "valtio" +import { useTranslation } from "next-i18next" +import classnames from "classnames" -import { appState } from '~utils/appState' +import { appState } from "~utils/appState" -import CharacterHovercard from '~components/CharacterHovercard' -import SearchModal from '~components/SearchModal' -import UncapIndicator from '~components/UncapIndicator' -import PlusIcon from '~public/icons/Add.svg' +import CharacterHovercard from "~components/CharacterHovercard" +import SearchModal from "~components/SearchModal" +import UncapIndicator from "~components/UncapIndicator" +import PlusIcon from "~public/icons/Add.svg" -import './index.scss' -import { getRedirectStatus } from 'next/dist/lib/load-custom-routes' +import type { SearchableObject } from "~types" + +import "./index.scss" interface Props { - gridCharacter: GridCharacter | undefined - position: number - editable: boolean - updateObject: (object: Character | Weapon | Summon, position: number) => void - updateUncap: (id: string, position: number, uncap: number) => void + gridCharacter?: GridCharacter + position: number + editable: boolean + updateObject: (object: SearchableObject, position: number) => void + updateUncap: (id: string, position: number, uncap: number) => void } const CharacterUnit = (props: Props) => { - const { t } = useTranslation('common') + const { t } = useTranslation("common") - const { party, grid } = useSnapshot(appState) + const { party, grid } = useSnapshot(appState) - const router = useRouter() - const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en' + const router = useRouter() + const locale = + router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en" - const [imageUrl, setImageUrl] = useState('') + const [imageUrl, setImageUrl] = useState("") - const classes = classnames({ - CharacterUnit: true, - 'editable': props.editable, - 'filled': (props.gridCharacter !== undefined) - }) + const classes = classnames({ + CharacterUnit: true, + editable: props.editable, + filled: props.gridCharacter !== undefined, + }) - const gridCharacter = props.gridCharacter - const character = gridCharacter?.object + const gridCharacter = props.gridCharacter + const character = gridCharacter?.object - useEffect(() => { - generateImageUrl() - }) + useEffect(() => { + generateImageUrl() + }) - function generateImageUrl() { - let imgSrc = "" - - if (props.gridCharacter) { - const character = props.gridCharacter.object! + function generateImageUrl() { + let imgSrc = "" - // Change the image based on the uncap level - let suffix = '01' - if (props.gridCharacter.uncap_level == 6) - suffix = '04' - else if (props.gridCharacter.uncap_level == 5) - suffix = '03' - else if (props.gridCharacter.uncap_level > 2) - suffix = '02' + if (props.gridCharacter) { + const character = props.gridCharacter.object! - // Special casing for Lyria (and Young Cat eventually) - if (props.gridCharacter.object.granblue_id === '3030182000') { - let element = 1 - if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) { - element = grid.weapons.mainWeapon.element - } else if (party.element != 0) { - element = party.element - } + // Change the image based on the uncap level + let suffix = "01" + if (props.gridCharacter.uncap_level == 6) suffix = "04" + else if (props.gridCharacter.uncap_level == 5) suffix = "03" + else if (props.gridCharacter.uncap_level > 2) suffix = "02" - suffix = `${suffix}_0${element}` - } - - imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/chara-main/${character.granblue_id}_${suffix}.jpg` + // Special casing for Lyria (and Young Cat eventually) + if (props.gridCharacter.object.granblue_id === "3030182000") { + let element = 1 + if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) { + element = grid.weapons.mainWeapon.element + } else if (party.element != 0) { + element = party.element } - setImageUrl(imgSrc) + suffix = `${suffix}_0${element}` + } + + imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/chara-main/${character.granblue_id}_${suffix}.jpg` } - function passUncapData(uncap: number) { - if (props.gridCharacter) - props.updateUncap(props.gridCharacter.id, props.position, uncap) - } + setImageUrl(imgSrc) + } - const image = ( -
    - {character?.name.en} - { (props.editable) ? : '' } -
    - ) + function passUncapData(uncap: number) { + if (props.gridCharacter) + props.updateUncap(props.gridCharacter.id, props.position, uncap) + } - const editableImage = ( - - {image} - - ) + const image = ( +
    + {character?.name.en} + {props.editable ? ( + + + + ) : ( + "" + )} +
    + ) - const unitContent = ( -
    - { (props.editable) ? editableImage : image } - { (gridCharacter && character) ? - : '' } -

    {character?.name[locale]}

    -
    - ) + const editableImage = ( + + {image} + + ) - const withHovercard = ( - - {unitContent} - - ) + const unitContent = ( +
    + {props.editable ? editableImage : image} + {gridCharacter && character ? ( + + ) : ( + "" + )} +

    {character?.name[locale]}

    +
    + ) - return ( - (gridCharacter && !props.editable) ? withHovercard : unitContent - ) + const withHovercard = ( + + {unitContent} + + ) + + return gridCharacter && !props.editable ? withHovercard : unitContent } export default CharacterUnit diff --git a/components/SearchModal/index.tsx b/components/SearchModal/index.tsx index 45d9b5ce..e049a33e 100644 --- a/components/SearchModal/index.tsx +++ b/components/SearchModal/index.tsx @@ -17,13 +17,14 @@ import SummonSearchFilterBar from "~components/SummonSearchFilterBar" import CharacterResult from "~components/CharacterResult" import WeaponResult from "~components/WeaponResult" import SummonResult from "~components/SummonResult" +import type { SearchableObject, SearchableObjectArray } from "~types" import "./index.scss" import CrossIcon from "~public/icons/Cross.svg" import cloneDeep from "lodash.clonedeep" interface Props { - send: (object: Character | Weapon | Summon, position: number) => any + send: (object: SearchableObject, position: number) => any placeholderText: string fromPosition: number object: "weapons" | "characters" | "summons" @@ -51,7 +52,7 @@ const SearchModal = (props: Props) => { const [filters, setFilters] = useState<{ [key: string]: number[] }>() const [open, setOpen] = useState(false) const [query, setQuery] = useState("") - const [results, setResults] = useState<(Weapon | Summon | Character)[]>([]) + const [results, setResults] = useState([]) // Pagination states const [recordCount, setRecordCount] = useState(0) @@ -99,10 +100,7 @@ const SearchModal = (props: Props) => { }) } - function replaceResults( - count: number, - list: Weapon[] | Summon[] | Character[] - ) { + function replaceResults(count: number, list: SearchableObjectArray) { if (count > 0) { setResults(list) } else { @@ -110,26 +108,36 @@ const SearchModal = (props: Props) => { } } - function appendResults(list: Weapon[] | Summon[] | Character[]) { + function appendResults(list: SearchableObjectArray) { setResults([...results, ...list]) } - function storeRecentResult(result: Character | Weapon | Summon) { + function storeRecentResult(result: SearchableObject) { const key = `recent_${props.object}` const cookie = getCookie(key) - const cookieObj: Character[] | Weapon[] | Summon[] = cookie + const cookieObj: SearchableObjectArray = cookie ? JSON.parse(cookie as string) : [] - let recents: Character[] | Weapon[] | Summon[] = [] + let recents: SearchableObjectArray = [] if (props.object === "weapons") { recents = cloneDeep(cookieObj as Weapon[]) || [] - if (!recents.find((item) => item.granblue_id === result.granblue_id)) { + if ( + !recents.find( + (item) => + (item as Weapon).granblue_id === (result as Weapon).granblue_id + ) + ) { recents.unshift(result as Weapon) } } else if (props.object === "summons") { recents = cloneDeep(cookieObj as Summon[]) || [] - if (!recents.find((item) => item.granblue_id === result.granblue_id)) { + if ( + !recents.find( + (item) => + (item as Summon).granblue_id === (result as Summon).granblue_id + ) + ) { recents.unshift(result as Summon) } } @@ -139,7 +147,7 @@ const SearchModal = (props: Props) => { sendData(result) } - function sendData(result: Character | Weapon | Summon) { + function sendData(result: SearchableObject) { props.send(result, props.fromPosition) openChange() } diff --git a/components/SummonUnit/index.tsx b/components/SummonUnit/index.tsx index 7128551f..462a9db0 100644 --- a/components/SummonUnit/index.tsx +++ b/components/SummonUnit/index.tsx @@ -1,120 +1,143 @@ -import React, { useEffect, useState } from 'react' -import { useRouter } from 'next/router' -import { useTranslation } from 'next-i18next' -import classnames from 'classnames' +import React, { useEffect, useState } from "react" +import { useRouter } from "next/router" +import { useTranslation } from "next-i18next" +import classnames from "classnames" -import SearchModal from '~components/SearchModal' -import SummonHovercard from '~components/SummonHovercard' -import UncapIndicator from '~components/UncapIndicator' -import PlusIcon from '~public/icons/Add.svg' +import SearchModal from "~components/SearchModal" +import SummonHovercard from "~components/SummonHovercard" +import UncapIndicator from "~components/UncapIndicator" +import PlusIcon from "~public/icons/Add.svg" -import './index.scss' +import type { SearchableObject } from "~types" + +import "./index.scss" interface Props { - gridSummon: GridSummon | undefined - unitType: 0 | 1 | 2 - position: number - editable: boolean - updateObject: (object: Character | Weapon | Summon, position: number) => void - updateUncap: (id: string, position: number, uncap: number) => void + gridSummon: GridSummon | undefined + unitType: 0 | 1 | 2 + position: number + editable: boolean + updateObject: (object: SearchableObject, position: number) => void + updateUncap: (id: string, position: number, uncap: number) => void } const SummonUnit = (props: Props) => { - const { t } = useTranslation('common') - - const [imageUrl, setImageUrl] = useState('') + const { t } = useTranslation("common") - const router = useRouter() - const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en' + const [imageUrl, setImageUrl] = useState("") - const classes = classnames({ - SummonUnit: true, - 'main': props.unitType == 0, - 'grid': props.unitType == 1, - 'friend': props.unitType == 2, - 'editable': props.editable, - 'filled': (props.gridSummon !== undefined) - }) + const router = useRouter() + const locale = + router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en" - const gridSummon = props.gridSummon - const summon = gridSummon?.object + const classes = classnames({ + SummonUnit: true, + main: props.unitType == 0, + grid: props.unitType == 1, + friend: props.unitType == 2, + editable: props.editable, + filled: props.gridSummon !== undefined, + }) - useEffect(() => { - generateImageUrl() - }) + const gridSummon = props.gridSummon + const summon = gridSummon?.object - function generateImageUrl() { - let imgSrc = "" - if (props.gridSummon) { - const summon = props.gridSummon.object! + useEffect(() => { + generateImageUrl() + }) - const upgradedSummons = [ - '2040094000', '2040100000', '2040080000', '2040098000', - '2040090000', '2040084000', '2040003000', '2040056000', - '2040020000', '2040034000', '2040028000', '2040027000', - '2040046000', '2040047000' - ] - - let suffix = '' - if (upgradedSummons.indexOf(summon.granblue_id.toString()) != -1 && props.gridSummon.uncap_level == 5) - suffix = '_02' - - // Generate the correct source for the summon - if (props.unitType == 0 || props.unitType == 2) - imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-main/${summon.granblue_id}${suffix}.jpg` - else - imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}${suffix}.jpg` - } - - setImageUrl(imgSrc) + function generateImageUrl() { + let imgSrc = "" + if (props.gridSummon) { + const summon = props.gridSummon.object! + + const upgradedSummons = [ + "2040094000", + "2040100000", + "2040080000", + "2040098000", + "2040090000", + "2040084000", + "2040003000", + "2040056000", + "2040020000", + "2040034000", + "2040028000", + "2040027000", + "2040046000", + "2040047000", + ] + + let suffix = "" + if ( + upgradedSummons.indexOf(summon.granblue_id.toString()) != -1 && + props.gridSummon.uncap_level == 5 + ) + suffix = "_02" + + // Generate the correct source for the summon + if (props.unitType == 0 || props.unitType == 2) + imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-main/${summon.granblue_id}${suffix}.jpg` + else + imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}${suffix}.jpg` } - function passUncapData(uncap: number) { - if (props.gridSummon) - props.updateUncap(props.gridSummon.id, props.position, uncap) - } + setImageUrl(imgSrc) + } - const image = ( -
    - {summon?.name.en} - { (props.editable) ? : '' } -
    - ) + function passUncapData(uncap: number) { + if (props.gridSummon) + props.updateUncap(props.gridSummon.id, props.position, uncap) + } - const editableImage = ( - - {image} - - ) + const image = ( +
    + {summon?.name.en} + {props.editable ? ( + + + + ) : ( + "" + )} +
    + ) - const unitContent = ( -
    - { (props.editable) ? editableImage : image } - { (gridSummon) ? - : '' - } -

    {summon?.name[locale]}

    -
    - ) + const editableImage = ( + + {image} + + ) - const withHovercard = ( - - {unitContent} - - ) + const unitContent = ( +
    + {props.editable ? editableImage : image} + {gridSummon ? ( + + ) : ( + "" + )} +

    {summon?.name[locale]}

    +
    + ) - return (gridSummon && !props.editable) ? withHovercard : unitContent + const withHovercard = ( + {unitContent} + ) + + return gridSummon && !props.editable ? withHovercard : unitContent } export default SummonUnit diff --git a/components/WeaponUnit/index.tsx b/components/WeaponUnit/index.tsx index faecf00f..51edee6e 100644 --- a/components/WeaponUnit/index.tsx +++ b/components/WeaponUnit/index.tsx @@ -1,131 +1,145 @@ -import React, { useEffect, useState } from 'react' -import { useRouter } from 'next/router' -import { useTranslation } from 'next-i18next' -import classnames from 'classnames' +import React, { useEffect, useState } from "react" +import { useRouter } from "next/router" +import { useTranslation } from "next-i18next" +import classnames from "classnames" -import SearchModal from '~components/SearchModal' -import WeaponModal from '~components/WeaponModal' -import WeaponHovercard from '~components/WeaponHovercard' -import UncapIndicator from '~components/UncapIndicator' -import Button from '~components/Button' +import SearchModal from "~components/SearchModal" +import WeaponModal from "~components/WeaponModal" +import WeaponHovercard from "~components/WeaponHovercard" +import UncapIndicator from "~components/UncapIndicator" +import Button from "~components/Button" -import { ButtonType } from '~utils/enums' +import { ButtonType } from "~utils/enums" +import type { SearchableObject } from "~types" -import PlusIcon from '~public/icons/Add.svg' -import './index.scss' +import PlusIcon from "~public/icons/Add.svg" +import "./index.scss" interface Props { - gridWeapon: GridWeapon | undefined - unitType: 0 | 1 - position: number - editable: boolean - updateObject: (object: Character | Weapon | Summon, position: number) => void - updateUncap: (id: string, position: number, uncap: number) => void + gridWeapon: GridWeapon | undefined + unitType: 0 | 1 + position: number + editable: boolean + updateObject: (object: SearchableObject, position: number) => void + updateUncap: (id: string, position: number, uncap: number) => void } const WeaponUnit = (props: Props) => { - const { t } = useTranslation('common') + const { t } = useTranslation("common") - const [imageUrl, setImageUrl] = useState('') + const [imageUrl, setImageUrl] = useState("") - const router = useRouter() - const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en' + const router = useRouter() + const locale = + router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en" - const classes = classnames({ - WeaponUnit: true, - 'mainhand': props.unitType == 0, - 'grid': props.unitType == 1, - 'editable': props.editable, - 'filled': (props.gridWeapon !== undefined) - }) + const classes = classnames({ + WeaponUnit: true, + mainhand: props.unitType == 0, + grid: props.unitType == 1, + editable: props.editable, + filled: props.gridWeapon !== undefined, + }) - const gridWeapon = props.gridWeapon - const weapon = gridWeapon?.object + const gridWeapon = props.gridWeapon + const weapon = gridWeapon?.object - useEffect(() => { - generateImageUrl() - }) + useEffect(() => { + generateImageUrl() + }) - function generateImageUrl() { - let imgSrc = "" - if (props.gridWeapon) { - const weapon = props.gridWeapon.object! - - if (props.unitType == 0) { - if (props.gridWeapon.object.element == 0 && props.gridWeapon.element) - imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}_${props.gridWeapon.element}.jpg` - else - imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}.jpg` - } else { - if (props.gridWeapon.object.element == 0 && props.gridWeapon.element) - imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${props.gridWeapon.element}.jpg` - else - imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg` - } - } - - setImageUrl(imgSrc) + function generateImageUrl() { + let imgSrc = "" + if (props.gridWeapon) { + const weapon = props.gridWeapon.object! + + if (props.unitType == 0) { + if (props.gridWeapon.object.element == 0 && props.gridWeapon.element) + imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}_${props.gridWeapon.element}.jpg` + else + imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}.jpg` + } else { + if (props.gridWeapon.object.element == 0 && props.gridWeapon.element) + imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${props.gridWeapon.element}.jpg` + else + imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg` + } } - function passUncapData(uncap: number) { - if (props.gridWeapon) - props.updateUncap(props.gridWeapon.id, props.position, uncap) - } + setImageUrl(imgSrc) + } - function canBeModified(gridWeapon: GridWeapon) { - const weapon = gridWeapon.object + function passUncapData(uncap: number) { + if (props.gridWeapon) + props.updateUncap(props.gridWeapon.id, props.position, uncap) + } - return weapon.ax > 0 || - (weapon.series) && [2, 3, 17, 22, 24].includes(weapon.series) - } + function canBeModified(gridWeapon: GridWeapon) { + const weapon = gridWeapon.object - const image = ( -
    - {weapon?.name.en} - { (props.editable) ? : '' } -
    + return ( + weapon.ax > 0 || + (weapon.series && [2, 3, 17, 22, 24].includes(weapon.series)) ) + } - const editableImage = ( - - {image} - - ) + const image = ( +
    + {weapon?.name.en} + {props.editable ? ( + + + + ) : ( + "" + )} +
    + ) - const unitContent = ( -
    - { (props.editable && gridWeapon && canBeModified(gridWeapon)) ? - -
    -
    -
    : '' } - { (props.editable) ? editableImage : image } - { (gridWeapon) ? - : '' - } -

    {weapon?.name[locale]}

    -
    - ) + const editableImage = ( + + {image} + + ) - const withHovercard = ( - - {unitContent} - - ) + const unitContent = ( +
    + {props.editable && gridWeapon && canBeModified(gridWeapon) ? ( + +
    +
    +
    + ) : ( + "" + )} + {props.editable ? editableImage : image} + {gridWeapon ? ( + + ) : ( + "" + )} +

    {weapon?.name[locale]}

    +
    + ) - return (gridWeapon && !props.editable) ? withHovercard : unitContent + const withHovercard = ( + {unitContent} + ) + + return gridWeapon && !props.editable ? withHovercard : unitContent } export default WeaponUnit diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 00000000..be978e8d --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,2 @@ +export type SearchableObject = Character | Weapon | Summon | JobSkill +export type SearchableObjectArray = (Character | Weapon | Summon | JobSkill)[] From ee7dc0bc4a469eaa6bb1959aa0c608e1cf74fcff Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 05:19:51 -0800 Subject: [PATCH 15/41] Update API --- utils/api.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/api.tsx b/utils/api.tsx index 8563cf1f..d1b1b477 100644 --- a/utils/api.tsx +++ b/utils/api.tsx @@ -56,13 +56,14 @@ class Api { return axios.post(`${ oauthUrl }/token`, object) } - search({ object, query, filters, locale = "en", page = 0 }: - { object: string, query: string, filters?: { [key: string]: number[] }, locale?: string, page?: number }) { + search({ object, query, job, filters, locale = "en", page = 0 }: + { object: string, query: string, job?: string, filters?: { [key: string]: number[] }, locale?: string, page?: number }) { const resourceUrl = `${this.url}/${name}` return axios.post(`${resourceUrl}search/${object}`, { search: { query: query, filters: filters, + job: job, locale: locale, page: page } From 6ef73583df4cf5c11a61ea35e63a442e5d884d36 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 05:20:22 -0800 Subject: [PATCH 16/41] Implement job skill search --- components/CharacterGrid/index.tsx | 2 +- components/JobSection/index.tsx | 58 ++++- components/JobSkillItem/index.scss | 4 +- components/JobSkillItem/index.tsx | 66 ++++-- components/JobSkillModal/index.scss | 16 -- components/JobSkillModal/index.tsx | 203 ------------------ components/JobSkillSearchFilterBar/index.scss | 3 + components/JobSkillSearchFilterBar/index.tsx | 71 ++++++ components/SearchModal/index.tsx | 55 +++-- 9 files changed, 219 insertions(+), 259 deletions(-) delete mode 100644 components/JobSkillModal/index.scss delete mode 100644 components/JobSkillModal/index.tsx create mode 100644 components/JobSkillSearchFilterBar/index.scss create mode 100644 components/JobSkillSearchFilterBar/index.tsx diff --git a/components/CharacterGrid/index.tsx b/components/CharacterGrid/index.tsx index af9b4721..6f7f7c8a 100644 --- a/components/CharacterGrid/index.tsx +++ b/components/CharacterGrid/index.tsx @@ -254,7 +254,7 @@ const CharacterGrid = (props: Props) => { return (
    - + { + const { t } = useTranslation("common") + const [job, setJob] = useState() const [imageUrl, setImageUrl] = useState("") @@ -20,9 +28,11 @@ const JobSection = (props: Props) => { const [numSkills, setNumSkills] = useState(4) const [skills, setSkills] = useState([]) + const [skillRefs, setSkillRefs] = useState[]>([]) + useEffect(() => { // Set current job based on ID - setJob(party.job) + if (party.job) setJob(party.job) }, []) useEffect(() => { @@ -33,6 +43,14 @@ const JobSection = (props: Props) => { if (job) appState.party.job = job }, [job]) + useEffect(() => { + setSkillRefs(Array(numSkills).fill(React.createRef())) + }, [numSkills]) + + useEffect(() => { + console.log(skillRefs) + }, [skillRefs]) + function receiveJob(job?: Job) { console.log(`Receiving job! Row ${job?.row}: ${job?.name.en}`) if (job) { @@ -62,6 +80,34 @@ const JobSection = (props: Props) => { setImageUrl(imgSrc) } + const skillItem = (index: number, editable: boolean) => { + return ( + + ) + } + + const editableSkillItem = (index: number) => { + return ( + + {skillItem(index, true)} + + ) + } + + function updateObject(object: SearchableObject, position: number) {} + // Render: JSX components return (
    @@ -76,8 +122,10 @@ const JobSection = (props: Props) => { />
      {[...Array(numSkills)].map((e, i) => ( -
    • - +
    • + {job && job.id != "-1" && !skills[i]?.main && props.editable + ? editableSkillItem(i) + : skillItem(i, false)}
    • ))}
    diff --git a/components/JobSkillItem/index.scss b/components/JobSkillItem/index.scss index 55cd1ea5..539beb60 100644 --- a/components/JobSkillItem/index.scss +++ b/components/JobSkillItem/index.scss @@ -6,8 +6,8 @@ &.editable:hover { cursor: pointer; - & > img, - & > div.placeholder { + & > img.editable, + & > div.placeholder.editable { border: $hover-stroke; box-shadow: $hover-shadow; cursor: pointer; diff --git a/components/JobSkillItem/index.tsx b/components/JobSkillItem/index.tsx index b1238863..02f2db1f 100644 --- a/components/JobSkillItem/index.tsx +++ b/components/JobSkillItem/index.tsx @@ -12,9 +12,10 @@ import "./index.scss" interface Props { skill?: JobSkill editable: boolean + hasJob: boolean } -const JobSkillItem = (props: Props) => { +const JobSkillItem = React.forwardRef((props, ref) => { const router = useRouter() const { t } = useTranslation("common") const locale = @@ -25,28 +26,57 @@ const JobSkillItem = (props: Props) => { editable: props.editable, }) - return ( -
    - {props.skill ? ( + const imageClasses = classNames({ + placeholder: !props.skill, + editable: props.editable && props.hasJob, + }) + + const skillImage = () => { + let jsx: React.ReactNode + + if (props.skill) { + jsx = ( {props.skill.name[locale]} - ) : ( -
    - + ) + } else { + jsx = ( +
    + {props.editable && props.hasJob ? : ""}
    - )} -
    - {/* {props.skill ?
    Grouping
    : ""} */} - {props.skill ? ( -

    {props.skill.name[locale]}

    - ) : ( -

    Select a skill

    - )} + ) + } + + return jsx + } + + const label = () => { + let jsx: React.ReactNode + + if (props.skill) { + jsx =

    {props.skill.name[locale]}

    + } else if (props.editable && props.hasJob) { + jsx =

    Select a skill

    + } else { + jsx =

    No skill

    + } + + return jsx + } + + const skillItem = () => { + return ( +
    + {skillImage()} + {label()}
    -
    - ) -} + ) + } + + return skillItem() +}) export default JobSkillItem diff --git a/components/JobSkillModal/index.scss b/components/JobSkillModal/index.scss deleted file mode 100644 index 136f26b8..00000000 --- a/components/JobSkillModal/index.scss +++ /dev/null @@ -1,16 +0,0 @@ -#Header #Bar select { - background-color: $grey-90; -} -#Header > label { - margin: 0 $unit * 3; - - .Input { - border: 1px solid $grey-80; - border-radius: calc($unit / 1.5); - box-sizing: border-box; - font-size: $font-regular; - padding: $unit * 1.5; - text-align: left; - width: 100%; - } -} diff --git a/components/JobSkillModal/index.tsx b/components/JobSkillModal/index.tsx deleted file mode 100644 index 415ff74f..00000000 --- a/components/JobSkillModal/index.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import React, { useEffect, useState } from "react" -import { getCookie, setCookie } from "cookies-next" -import { useRouter } from "next/router" -import { useSnapshot } from "valtio" -import { useTranslation } from "react-i18next" -import InfiniteScroll from "react-infinite-scroll-component" - -import { appState } from "~utils/appState" -import { skillGroups } from "~utils/skillGroups" - -import * as Dialog from "@radix-ui/react-dialog" -import JobSkillResult from "~components/JobSkillResult" - -import CrossIcon from "~public/icons/Cross.svg" - -import "./index.scss" - -interface Props { - send: (skill: JobSkill, position: number) => any - job?: Job - fromPosition: number - children: React.ReactNode -} - -const JobSkillModal = (props: Props) => { - // Set up router - const router = useRouter() - const locale = router.locale - - // Set up translation - const { t } = useTranslation("common") - - let searchInput = React.createRef() - let scrollContainer = React.createRef() - - const [currentGroup, setCurrentGroup] = useState(-1) - const [currentGroupName, setCurrentGroupName] = useState("") - const [open, setOpen] = useState(false) - const [query, setQuery] = useState("") - const [results, setResults] = useState([]) - - // Pagination states - const [recordCount, setRecordCount] = useState(0) - const [currentPage, setCurrentPage] = useState(1) - const [totalPages, setTotalPages] = useState(1) - - useEffect(() => { - setResults(appState.jobSkills.filter((skill) => skill.main === false)) - setRecordCount( - appState.jobSkills.filter((skill) => skill.main === false).length - ) - }, [appState, setResults]) - - useEffect(() => { - if (searchInput.current) searchInput.current.focus() - }, [searchInput]) - - useEffect(() => { - setRecordCount(results.length) - }, [results]) - - useEffect(() => { - const name = skillGroups - .find((skill) => skill.id === currentGroup) - ?.name["en"].toLowerCase() - setCurrentGroupName(name ? name : "") - }, [currentGroup]) - - function onChange(event: React.ChangeEvent) { - const newValue = parseInt(event.target.value) - setCurrentGroup(newValue) - - if (newValue >= 0) { - setResults( - appState.jobSkills.filter((skill, i) => { - if (newValue === 4) { - return skill.emp && !skill.main - } else if (newValue === 5) { - return skill.base && !skill.main - } else { - return skill.color === newValue && !skill.main - } - }) - ) - } else { - setResults(appState.jobSkills.filter((skill) => skill.main === false)) - } - } - - function inputChanged(event: React.ChangeEvent) { - const text = event.target.value - if (text.length) { - setQuery(text) - } else { - setQuery("") - } - } - - function openChange() { - if (open) { - setQuery("") - // setFirstLoad(true) - setResults([]) - setRecordCount(0) - setCurrentPage(1) - setOpen(false) - } else { - setOpen(true) - } - } - - function onBlur() {} - - function render() { - const rows = results.map((result: JobSkill, i: number) => { - return ( - {}} /> - ) - }) - return ( - 0 ? results.length : 0} - next={() => setCurrentPage(currentPage + 1)} - hasMore={totalPages > currentPage} - scrollableTarget="Results" - loader={
    Loading...
    } - > - {rows} -
    - ) - } - return ( - - {props.children} - - - - -
    -
    - {t("search.result_count", { record_count: recordCount })} -
    - {open ? render() : ""} -
    -
    - -
    -
    - ) -} - -export default JobSkillModal diff --git a/components/JobSkillSearchFilterBar/index.scss b/components/JobSkillSearchFilterBar/index.scss new file mode 100644 index 00000000..6ccb5e2e --- /dev/null +++ b/components/JobSkillSearchFilterBar/index.scss @@ -0,0 +1,3 @@ +.SearchFilterBar select { + background-color: $grey-90; +} diff --git a/components/JobSkillSearchFilterBar/index.tsx b/components/JobSkillSearchFilterBar/index.tsx new file mode 100644 index 00000000..1de78add --- /dev/null +++ b/components/JobSkillSearchFilterBar/index.tsx @@ -0,0 +1,71 @@ +import React, { useEffect, useState } from "react" +import { useRouter } from "next/router" +import { useTranslation } from "react-i18next" + +import { skillGroups } from "~utils/skillGroups" + +import "./index.scss" + +interface Props { + sendFilters: (filters: { [key: string]: number }) => void +} + +const JobSkillSearchFilterBar = (props: Props) => { + // Set up translation + const { t } = useTranslation("common") + + const [currentGroup, setCurrentGroup] = useState(-1) + + function onChange(event: React.ChangeEvent) { + setCurrentGroup(parseInt(event.target.value)) + } + + function onBlur(event: React.ChangeEvent) {} + + function sendFilters() { + const filters = { + group: currentGroup, + } + + props.sendFilters(filters) + } + + useEffect(() => { + sendFilters() + }, [currentGroup]) + + return ( +
    + +
    + ) +} + +export default JobSkillSearchFilterBar diff --git a/components/SearchModal/index.tsx b/components/SearchModal/index.tsx index e049a33e..317ab5eb 100644 --- a/components/SearchModal/index.tsx +++ b/components/SearchModal/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from "react" +import React, { useEffect, useState } from "react" import { getCookie, setCookie } from "cookies-next" import { useRouter } from "next/router" import { useSnapshot } from "valtio" @@ -13,10 +13,13 @@ import * as Dialog from "@radix-ui/react-dialog" import CharacterSearchFilterBar from "~components/CharacterSearchFilterBar" import WeaponSearchFilterBar from "~components/WeaponSearchFilterBar" import SummonSearchFilterBar from "~components/SummonSearchFilterBar" +import JobSkillSearchFilterBar from "~components/JobSkillSearchFilterBar" import CharacterResult from "~components/CharacterResult" import WeaponResult from "~components/WeaponResult" import SummonResult from "~components/SummonResult" +import JobSkillResult from "~components/JobSkillResult" + import type { SearchableObject, SearchableObjectArray } from "~types" import "./index.scss" @@ -27,14 +30,12 @@ interface Props { send: (object: SearchableObject, position: number) => any placeholderText: string fromPosition: number - object: "weapons" | "characters" | "summons" + job?: Job + object: "weapons" | "characters" | "summons" | "job_skills" children: React.ReactNode } const SearchModal = (props: Props) => { - // Set up snapshot of app state - let { grid, search } = useSnapshot(appState) - // Set up router const router = useRouter() const locale = router.locale @@ -46,10 +47,7 @@ const SearchModal = (props: Props) => { let scrollContainer = React.createRef() const [firstLoad, setFirstLoad] = useState(true) - const [objects, setObjects] = useState<{ - [id: number]: GridCharacter | GridWeapon | GridSummon | undefined - }>() - const [filters, setFilters] = useState<{ [key: string]: number[] }>() + const [filters, setFilters] = useState<{ [key: string]: any }>() const [open, setOpen] = useState(false) const [query, setQuery] = useState("") const [results, setResults] = useState([]) @@ -59,10 +57,6 @@ const SearchModal = (props: Props) => { const [currentPage, setCurrentPage] = useState(1) const [totalPages, setTotalPages] = useState(1) - useEffect(() => { - setObjects(grid[props.object]) - }, [grid, props.object]) - useEffect(() => { if (searchInput.current) searchInput.current.focus() }, [searchInput]) @@ -77,15 +71,19 @@ const SearchModal = (props: Props) => { } function fetchResults({ replace = false }: { replace?: boolean }) { + console.log("Fetch results!!!") api .search({ object: props.object, query: query, + job: props.job?.id, filters: filters, locale: locale, page: currentPage, }) .then((response) => { + console.log("resp") + console.log(response) setTotalPages(response.data.total_pages) setRecordCount(response.data.count) @@ -152,7 +150,7 @@ const SearchModal = (props: Props) => { openChange() } - function receiveFilters(filters: { [key: string]: number[] }) { + function receiveFilters(filters: { [key: string]: any }) { setCurrentPage(1) setResults([]) setFilters(filters) @@ -208,6 +206,9 @@ const SearchModal = (props: Props) => { case "characters": jsx = renderCharacterSearchResults(results) break + case "job_skills": + jsx = renderJobSkillSearchResults(results) + break } return ( @@ -286,6 +287,27 @@ const SearchModal = (props: Props) => { return jsx } + function renderJobSkillSearchResults(results: { [key: string]: any }) { + let jsx: React.ReactNode + + const castResults: JobSkill[] = results as JobSkill[] + if (castResults && Object.keys(castResults).length > 0) { + jsx = castResults.map((result: JobSkill) => { + return ( + { + storeRecentResult(result) + }} + /> + ) + }) + } + + return jsx + } + function openChange() { if (open) { setQuery("") @@ -338,6 +360,11 @@ const SearchModal = (props: Props) => { ) : ( "" )} + {props.object === "job_skills" ? ( + + ) : ( + "" + )}
    From 725e989bd7b3acfe4a76d4647876b8952b44f1ff Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 05:21:11 -0800 Subject: [PATCH 17/41] Remove console logs --- components/JobSection/index.tsx | 4 - components/SearchModal/index.tsx | 3 - components/UncapIndicator/index.tsx | 192 ++++++++++++++++------------ 3 files changed, 110 insertions(+), 89 deletions(-) diff --git a/components/JobSection/index.tsx b/components/JobSection/index.tsx index d1737df1..37efada4 100644 --- a/components/JobSection/index.tsx +++ b/components/JobSection/index.tsx @@ -47,10 +47,6 @@ const JobSection = (props: Props) => { setSkillRefs(Array(numSkills).fill(React.createRef())) }, [numSkills]) - useEffect(() => { - console.log(skillRefs) - }, [skillRefs]) - function receiveJob(job?: Job) { console.log(`Receiving job! Row ${job?.row}: ${job?.name.en}`) if (job) { diff --git a/components/SearchModal/index.tsx b/components/SearchModal/index.tsx index 317ab5eb..9ba47017 100644 --- a/components/SearchModal/index.tsx +++ b/components/SearchModal/index.tsx @@ -71,7 +71,6 @@ const SearchModal = (props: Props) => { } function fetchResults({ replace = false }: { replace?: boolean }) { - console.log("Fetch results!!!") api .search({ object: props.object, @@ -82,8 +81,6 @@ const SearchModal = (props: Props) => { page: currentPage, }) .then((response) => { - console.log("resp") - console.log(response) setTotalPages(response.data.total_pages) setRecordCount(response.data.count) diff --git a/components/UncapIndicator/index.tsx b/components/UncapIndicator/index.tsx index 56de4114..eb292067 100644 --- a/components/UncapIndicator/index.tsx +++ b/components/UncapIndicator/index.tsx @@ -1,101 +1,129 @@ -import React, { useEffect, useRef, useState } from 'react' -import UncapStar from '~components/UncapStar' +import React, { useEffect, useRef, useState } from "react" +import UncapStar from "~components/UncapStar" -import './index.scss' +import "./index.scss" interface Props { - type: 'character' | 'weapon' | 'summon' - rarity?: number - uncapLevel?: number - flb: boolean - ulb: boolean - special: boolean - updateUncap?: (uncap: number) => void + type: "character" | "weapon" | "summon" + rarity?: number + uncapLevel?: number + flb: boolean + ulb: boolean + special: boolean + updateUncap?: (uncap: number) => void } const UncapIndicator = (props: Props) => { - const [uncap, setUncap] = useState(props.uncapLevel) + const [uncap, setUncap] = useState(props.uncapLevel) - const numStars = setNumStars() - function setNumStars() { - let numStars - - if (props.type === 'character') { - if (props.special) { - if (props.ulb) { - numStars = 5 - } else if (props.flb) { - numStars = 4 - } else { - numStars = 3 - } - } else { - if (props.ulb) { - numStars = 6 - } else if (props.flb) { - numStars = 5 - } else { - numStars = 4 - } - } + const numStars = setNumStars() + function setNumStars() { + let numStars + + if (props.type === "character") { + if (props.special) { + if (props.ulb) { + numStars = 5 + } else if (props.flb) { + numStars = 4 } else { - if (props.ulb) { - numStars = 5 - } else if (props.flb) { - numStars = 4 - } else { - numStars = 3 - } + numStars = 3 } - - return numStars - } - - function toggleStar(index: number, empty: boolean) { - if (props.updateUncap) { - if (empty) props.updateUncap(index + 1) - else props.updateUncap(index) + } else { + if (props.ulb) { + numStars = 6 + } else if (props.flb) { + numStars = 5 + } else { + numStars = 4 } + } + } else { + if (props.ulb) { + numStars = 5 + } else if (props.flb) { + numStars = 4 + } else { + numStars = 3 + } } - const transcendence = (i: number) => { - return = props.uncapLevel : false } key={`star_${i}`} index={i} onClick={toggleStar} /> - } + return numStars + } - const ulb = (i: number) => { - return = props.uncapLevel : false } key={`star_${i}`} index={i} onClick={toggleStar} /> - } - - const flb = (i: number) => { - return = props.uncapLevel : false } key={`star_${i}`} index={i} onClick={toggleStar} /> - } - - const mlb = (i: number) => { - // console.log("MLB; Number of stars:", props.uncapLevel) - return = props.uncapLevel : false } key={`star_${i}`} index={i} onClick={toggleStar} /> + function toggleStar(index: number, empty: boolean) { + if (props.updateUncap) { + if (empty) props.updateUncap(index + 1) + else props.updateUncap(index) } + } + const transcendence = (i: number) => { return ( -
      - { - Array.from(Array(numStars)).map((x, i) => { - if (props.type === 'character' && i > 4) { - if (props.special) - return ulb(i) - else - return transcendence(i) - } else if ( - props.special && props.type === 'character' && i == 3 || - props.type === 'character' && i == 4 || - props.type !== 'character' && i > 2) { - return flb(i) - } else { - return mlb(i) - } - }) - } -
    + = props.uncapLevel : false} + key={`star_${i}`} + index={i} + onClick={toggleStar} + /> ) + } + + const ulb = (i: number) => { + return ( + = props.uncapLevel : false} + key={`star_${i}`} + index={i} + onClick={toggleStar} + /> + ) + } + + const flb = (i: number) => { + return ( + = props.uncapLevel : false} + key={`star_${i}`} + index={i} + onClick={toggleStar} + /> + ) + } + + const mlb = (i: number) => { + // console.log("MLB; Number of stars:", props.uncapLevel) + return ( + = props.uncapLevel : false} + key={`star_${i}`} + index={i} + onClick={toggleStar} + /> + ) + } + + return ( +
      + {Array.from(Array(numStars)).map((x, i) => { + if (props.type === "character" && i > 4) { + if (props.special) return ulb(i) + else return transcendence(i) + } else if ( + (props.special && props.type === "character" && i == 3) || + (props.type === "character" && i == 4) || + (props.type !== "character" && i > 2) + ) { + return flb(i) + } else { + return mlb(i) + } + })} +
    + ) } -export default UncapIndicator \ No newline at end of file +export default UncapIndicator From 97f22b852af23c7ae04eeb3a369d6467f89db81e Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 06:09:32 -0800 Subject: [PATCH 18/41] Remove dead ref code --- components/JobSection/index.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/components/JobSection/index.tsx b/components/JobSection/index.tsx index 37efada4..90510a2f 100644 --- a/components/JobSection/index.tsx +++ b/components/JobSection/index.tsx @@ -28,8 +28,6 @@ const JobSection = (props: Props) => { const [numSkills, setNumSkills] = useState(4) const [skills, setSkills] = useState([]) - const [skillRefs, setSkillRefs] = useState[]>([]) - useEffect(() => { // Set current job based on ID if (party.job) setJob(party.job) @@ -43,10 +41,6 @@ const JobSection = (props: Props) => { if (job) appState.party.job = job }, [job]) - useEffect(() => { - setSkillRefs(Array(numSkills).fill(React.createRef())) - }, [numSkills]) - function receiveJob(job?: Job) { console.log(`Receiving job! Row ${job?.row}: ${job?.name.en}`) if (job) { @@ -83,7 +77,6 @@ const JobSection = (props: Props) => { editable={!skills[index]?.main && editable} key={`skill-${index}`} hasJob={job != undefined && job.id != "-1"} - ref={skillRefs[index]} /> ) } From 055c70624a103680eb4ea30faa3d596e303d5eea Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 06:09:40 -0800 Subject: [PATCH 19/41] Add translations --- public/locales/en/common.json | 6 +++++- public/locales/ja/common.json | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 67cbd939..63af7fdc 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -248,7 +248,11 @@ "damaging": "Damaging", "healing": "Healing", "emp": "Extended Mastery", - "base": "Base Skills" + "base": "Base Skills", + "state": { + "selectable": "Select a skill", + "no_skill": "No skill" + } }, "extra_weapons": "Additional Weapons", "coming_soon": "Coming Soon", diff --git a/public/locales/ja/common.json b/public/locales/ja/common.json index 04f7ba36..d49f722c 100644 --- a/public/locales/ja/common.json +++ b/public/locales/ja/common.json @@ -249,7 +249,11 @@ "damaging": "ダメージアビリティ", "healing": "回復アビリティ", "emp": "リミットアビリティ", - "base": "ベースアビリティ" + "base": "ベースアビリティ", + "state": { + "selectable": "アビリティを選択", + "no_skill": "設定されていません" + } }, "extra_weapons": "Additional
    Weapons", "coming_soon": "開発中", From 1202985f803a0f6232e04779cdeff22246e0c288 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 06:09:55 -0800 Subject: [PATCH 20/41] Fix forwardRef and refactor rendering --- components/JobSkillItem/index.tsx | 97 +++++++++++++++---------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/components/JobSkillItem/index.tsx b/components/JobSkillItem/index.tsx index 02f2db1f..ba1ce9a0 100644 --- a/components/JobSkillItem/index.tsx +++ b/components/JobSkillItem/index.tsx @@ -3,80 +3,79 @@ import { useRouter } from "next/router" import { useTranslation } from "next-i18next" import classNames from "classnames" - import PlusIcon from "~public/icons/Add.svg" import "./index.scss" // Props -interface Props { +interface Props extends React.ComponentPropsWithoutRef<"div"> { skill?: JobSkill editable: boolean hasJob: boolean } -const JobSkillItem = React.forwardRef((props, ref) => { - const router = useRouter() - const { t } = useTranslation("common") - const locale = - router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en" +const JobSkillItem = React.forwardRef( + ({ ...props }, forwardedRef) => { + const router = useRouter() + const { t } = useTranslation("common") + const locale = + router.locale && ["en", "ja"].includes(router.locale) + ? router.locale + : "en" - const classes = classNames({ - JobSkill: true, - editable: props.editable, - }) + const classes = classNames({ + JobSkill: true, + editable: props.editable, + }) - const imageClasses = classNames({ - placeholder: !props.skill, - editable: props.editable && props.hasJob, - }) + const imageClasses = classNames({ + placeholder: !props.skill, + editable: props.editable && props.hasJob, + }) - const skillImage = () => { - let jsx: React.ReactNode + const skillImage = () => { + let jsx: React.ReactNode - if (props.skill) { - jsx = ( - {props.skill.name[locale]} - ) - } else { - jsx = ( -
    - {props.editable && props.hasJob ? : ""} -
    - ) + if (props.skill) { + jsx = ( + {props.skill.name[locale]} + ) + } else { + jsx = ( +
    + {props.editable && props.hasJob ? : ""} +
    + ) + } + + return jsx } - return jsx - } + const label = () => { + let jsx: React.ReactNode - const label = () => { - let jsx: React.ReactNode + if (props.skill) { + jsx =

    {props.skill.name[locale]}

    + } else if (props.editable && props.hasJob) { + jsx =

    {t("job_skills.state.selectable")}

    + } else { + jsx =

    {t("job_skills.state.no_skill")}

    + } - if (props.skill) { - jsx =

    {props.skill.name[locale]}

    - } else if (props.editable && props.hasJob) { - jsx =

    Select a skill

    - } else { - jsx =

    No skill

    + return jsx } - return jsx - } - - const skillItem = () => { return ( -
    +
    {skillImage()} {label()}
    ) } - - return skillItem() -}) +) export default JobSkillItem From cbbad53e0982a0a23c11bf9778421f702c538cd0 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 09:00:50 -0800 Subject: [PATCH 21/41] Fix typo that broke job persistence --- pages/p/[party].tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pages/p/[party].tsx b/pages/p/[party].tsx index 4c412bf6..672c8084 100644 --- a/pages/p/[party].tsx +++ b/pages/p/[party].tsx @@ -23,7 +23,6 @@ const PartyRoute: React.FC = (props: Props) => { }, [persistStaticData]) function persistStaticData() { - console.log("Persisting static data...") appState.raids = props.raids appState.jobs = props.jobs appState.jobSkills = props.jobSkills @@ -83,7 +82,7 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex return { props: { party: party, - job: jobs, + jobs: jobs, jobSkills: jobSkills, raids: raids, sortedRaids: sortedRaids, From 6af2ace6b06048d5a36ea382783afcc47581e0b7 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 09:01:33 -0800 Subject: [PATCH 22/41] Use SearchableObject type --- components/CharacterGrid/index.tsx | 6 ++- components/ExtraSummons/index.tsx | 71 +++++++++++++++--------------- components/SummonGrid/index.tsx | 6 +-- components/WeaponGrid/index.tsx | 7 ++- 4 files changed, 44 insertions(+), 46 deletions(-) diff --git a/components/CharacterGrid/index.tsx b/components/CharacterGrid/index.tsx index 6f7f7c8a..171f2f77 100644 --- a/components/CharacterGrid/index.tsx +++ b/components/CharacterGrid/index.tsx @@ -8,12 +8,14 @@ import debounce from "lodash.debounce" import JobSection from "~components/JobSection" import CharacterUnit from "~components/CharacterUnit" +import CharacterConflictModal from "~components/CharacterConflictModal" + +import type { SearchableObject } from "~types" import api from "~utils/api" import { appState } from "~utils/appState" import "./index.scss" -import CharacterConflictModal from "~components/CharacterConflictModal" // Props interface Props { @@ -73,7 +75,7 @@ const CharacterGrid = (props: Props) => { // Methods: Adding an object from search function receiveCharacterFromSearch( - object: Character | Weapon | Summon, + object: SearchableObject, position: number ) { const character = object as Character diff --git a/components/ExtraSummons/index.tsx b/components/ExtraSummons/index.tsx index 54e888e3..c064ba25 100644 --- a/components/ExtraSummons/index.tsx +++ b/components/ExtraSummons/index.tsx @@ -1,47 +1,46 @@ -import React from 'react' -import { useTranslation } from 'next-i18next' -import SummonUnit from '~components/SummonUnit' -import './index.scss' +import React from "react" +import { useTranslation } from "next-i18next" +import SummonUnit from "~components/SummonUnit" +import { SearchableObject } from "~types" +import "./index.scss" // Props interface Props { - grid: GridArray - editable: boolean - exists: boolean - found?: boolean - offset: number - updateObject: (object: Character | Weapon | Summon, position: number) => void - updateUncap: (id: string, position: number, uncap: number) => void + grid: GridArray + editable: boolean + exists: boolean + found?: boolean + offset: number + updateObject: (object: SearchableObject, position: number) => void + updateUncap: (id: string, position: number, uncap: number) => void } const ExtraSummons = (props: Props) => { - const numSummons: number = 2 + const numSummons: number = 2 - const { t } = useTranslation('common') + const { t } = useTranslation("common") - return ( -
    - {t('summons.subaura')} -
      - { - Array.from(Array(numSummons)).map((x, i) => { - return ( -
    • - -
    • - ) - }) - } -
    -
    - ) + return ( +
    + {t("summons.subaura")} +
      + {Array.from(Array(numSummons)).map((x, i) => { + return ( +
    • + +
    • + ) + })} +
    +
    + ) } export default ExtraSummons diff --git a/components/SummonGrid/index.tsx b/components/SummonGrid/index.tsx index e115da5d..96a3c652 100644 --- a/components/SummonGrid/index.tsx +++ b/components/SummonGrid/index.tsx @@ -12,6 +12,7 @@ import ExtraSummons from "~components/ExtraSummons" import api from "~utils/api" import { appState } from "~utils/appState" +import type { SearchableObject } from "~types" import "./index.scss" @@ -83,10 +84,7 @@ const SummonGrid = (props: Props) => { ]) // Methods: Adding an object from search - function receiveSummonFromSearch( - object: Character | Weapon | Summon, - position: number - ) { + function receiveSummonFromSearch(object: SearchableObject, position: number) { const summon = object as Summon if (!party.id) { diff --git a/components/WeaponGrid/index.tsx b/components/WeaponGrid/index.tsx index 86169c2c..339a16ed 100644 --- a/components/WeaponGrid/index.tsx +++ b/components/WeaponGrid/index.tsx @@ -12,6 +12,8 @@ import ExtraWeapons from "~components/ExtraWeapons" import api from "~utils/api" import { appState } from "~utils/appState" +import type { SearchableObject } from "~types" + import "./index.scss" // Props @@ -71,10 +73,7 @@ const WeaponGrid = (props: Props) => { }, [appState.grid.weapons.mainWeapon, appState.grid.weapons.allWeapons]) // Methods: Adding an object from search - function receiveWeaponFromSearch( - object: Character | Weapon | Summon, - position: number - ) { + function receiveWeaponFromSearch(object: SearchableObject, position: number) { const weapon = object as Weapon if (position == 1) appState.party.element = weapon.element From 8f06fb87700913ffeb30632293d3e6c2e0e936c5 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 30 Nov 2022 09:01:39 -0800 Subject: [PATCH 23/41] Remove log --- components/CharacterConflictModal/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/components/CharacterConflictModal/index.tsx b/components/CharacterConflictModal/index.tsx index 04ade165..1f1ff6c0 100644 --- a/components/CharacterConflictModal/index.tsx +++ b/components/CharacterConflictModal/index.tsx @@ -40,7 +40,6 @@ const CharacterConflictModal = (props: Props) => { else if (uncap == 5) suffix = "03" else if (uncap > 2) suffix = "02" - console.log(appState.grid.weapons.mainWeapon) // Special casing for Lyria (and Young Cat eventually) if (character?.granblue_id === "3030182000") { let element = 1 From 0096a49a074a8c216d9573272a733472ccdbdf42 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Thu, 1 Dec 2022 01:45:31 -0800 Subject: [PATCH 24/41] Added jobSkills to data structures --- types/Party.d.ts | 7 +++++++ utils/appState.tsx | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/types/Party.d.ts b/types/Party.d.ts index 5a1dea6b..3d3f808d 100644 --- a/types/Party.d.ts +++ b/types/Party.d.ts @@ -3,6 +3,13 @@ interface Party { name: string description: string raid: Raid + job: Job + job_skills: { + [key: number]: JobSkill + 1: JobSkill + 2: JobSkill + 3: JobSkill + } shortcode: string extra: boolean favorited: boolean diff --git a/utils/appState.tsx b/utils/appState.tsx index 9ba87f54..f161cba4 100644 --- a/utils/appState.tsx +++ b/utils/appState.tsx @@ -25,6 +25,11 @@ interface AppState { name: string | undefined description: string | undefined job: Job + jobSkills: { + 1: JobSkill | undefined + 2: JobSkill | undefined + 3: JobSkill | undefined + } raid: Raid | undefined element: number extra: boolean @@ -65,6 +70,11 @@ export const initialAppState: AppState = { name: undefined, description: undefined, job: emptyJob, + jobSkills: { + 1: undefined, + 2: undefined, + 3: undefined, + }, raid: undefined, element: 0, extra: false, From 1cb9d6c8438b7aa9408c6ed7074a145ab77efb8c Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Thu, 1 Dec 2022 01:45:47 -0800 Subject: [PATCH 25/41] Restore job when loading party --- components/JobDropdown/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/JobDropdown/index.tsx b/components/JobDropdown/index.tsx index 187b9de5..6cfa6f03 100644 --- a/components/JobDropdown/index.tsx +++ b/components/JobDropdown/index.tsx @@ -67,7 +67,11 @@ const JobDropdown = React.forwardRef( .sort((a, b) => a.order - b.order) .map((item, i) => { return ( - ) From 6070164150f83016e4d68907cc25776ad5880fe5 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Thu, 1 Dec 2022 01:46:11 -0800 Subject: [PATCH 26/41] Save job and job skill to party --- components/CharacterGrid/index.tsx | 42 +++++++++++++++++++++++++++++- components/JobSection/index.tsx | 24 ++++++++++++----- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/components/CharacterGrid/index.tsx b/components/CharacterGrid/index.tsx index 171f2f77..17bb23ed 100644 --- a/components/CharacterGrid/index.tsx +++ b/components/CharacterGrid/index.tsx @@ -165,6 +165,42 @@ const CharacterGrid = (props: Props) => { setIncoming(undefined) } + // Methods: Saving job and job skills + const saveJob = function (job: Job) { + console.log("Save job!") + if (party.id && appState.party.editable) { + api.endpoints.parties.update( + party.id, + { + party: { job_id: job ? job.id : "" }, + }, + headers + ) + } + } + + const saveJobSkill = function (skill: JobSkill, position: number) { + if (party.id && appState.party.editable) { + const positionedKey = `skill${position}_id` + + let skillObject: { + [key: string]: string | undefined + skill1_id?: string + skill2_id?: string + skill3_id?: string + } = {} + + skillObject[positionedKey] = skill.id + api.endpoints.parties.update( + party.id, + { + party: skillObject, + }, + headers + ) + } + } + // Methods: Helpers function characterUncapLevel(character: Character) { let uncapLevel @@ -256,7 +292,11 @@ const CharacterGrid = (props: Props) => { return (
    - + void + saveSkill: (skill: JobSkill, position: number) => void } const JobSection = (props: Props) => { @@ -38,14 +40,23 @@ const JobSection = (props: Props) => { }) useEffect(() => { - if (job) appState.party.job = job + if (job) { + appState.party.job = job + setBaseSkills(job) + } }, [job]) function receiveJob(job?: Job) { console.log(`Receiving job! Row ${job?.row}: ${job?.name.en}`) if (job) { setJob(job) + props.saveJob(job) + setBaseSkills(job) + } + } + function setBaseSkills(job?: Job) { + if (job) { const baseSkills = appState.jobSkills.filter( (skill) => skill.job.id === job.id && skill.main ) @@ -95,7 +106,11 @@ const JobSection = (props: Props) => { ) } - function updateObject(object: SearchableObject, position: number) {} + function updateObject(object: SearchableObject, position: number) { + const skill = object as JobSkill + + props.saveSkill(skill, position) + } // Render: JSX components return ( @@ -105,10 +120,7 @@ const JobSection = (props: Props) => {
    - +
      {[...Array(numSkills)].map((e, i) => (
    • From c307fcb18fa0eca85987780d4f8fc3dbde4a179d Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Thu, 1 Dec 2022 02:00:58 -0800 Subject: [PATCH 27/41] Remove logs --- components/CharacterGrid/index.tsx | 1 - components/JobSection/index.tsx | 1 - components/Party/index.tsx | 23 ----------------------- pages/new/index.tsx | 1 - 4 files changed, 26 deletions(-) diff --git a/components/CharacterGrid/index.tsx b/components/CharacterGrid/index.tsx index 17bb23ed..207d1b1d 100644 --- a/components/CharacterGrid/index.tsx +++ b/components/CharacterGrid/index.tsx @@ -167,7 +167,6 @@ const CharacterGrid = (props: Props) => { // Methods: Saving job and job skills const saveJob = function (job: Job) { - console.log("Save job!") if (party.id && appState.party.editable) { api.endpoints.parties.update( party.id, diff --git a/components/JobSection/index.tsx b/components/JobSection/index.tsx index dfb6a7a9..4b5a9ce1 100644 --- a/components/JobSection/index.tsx +++ b/components/JobSection/index.tsx @@ -47,7 +47,6 @@ const JobSection = (props: Props) => { }, [job]) function receiveJob(job?: Job) { - console.log(`Receiving job! Row ${job?.row}: ${job?.name.en}`) if (job) { setJob(job) props.saveJob(job) diff --git a/components/Party/index.tsx b/components/Party/index.tsx index 2530de64..921fd259 100644 --- a/components/Party/index.tsx +++ b/components/Party/index.tsx @@ -42,9 +42,6 @@ const Party = (props: Props) => { // Set up states const { party } = useSnapshot(appState) - const jobState = party.job - - const [job, setJob] = useState() const [currentTab, setCurrentTab] = useState(GridType.Weapon) // Reset state on first load @@ -54,14 +51,6 @@ const Party = (props: Props) => { if (props.team) storeParty(props.team) }, []) - useEffect(() => { - setJob(jobState) - }, [jobState]) - - useEffect(() => { - jobChanged() - }, [job]) - // Methods: Creating a new party async function createParty(extra: boolean = false) { let body = { @@ -89,18 +78,6 @@ const Party = (props: Props) => { } } - function jobChanged() { - if (party.id && appState.party.editable) { - api.endpoints.parties.update( - party.id, - { - party: { job_id: job ? job.id : "" }, - }, - headers - ) - } - } - function updateDetails(name?: string, description?: string, raid?: Raid) { if ( appState.party.name !== name || diff --git a/pages/new/index.tsx b/pages/new/index.tsx index a4208a7e..d2762f02 100644 --- a/pages/new/index.tsx +++ b/pages/new/index.tsx @@ -27,7 +27,6 @@ const NewRoute: React.FC = (props: Props) => { }, [persistStaticData]) function persistStaticData() { - console.log("Persisting static data...") appState.raids = props.raids appState.jobs = props.jobs appState.jobSkills = props.jobSkills From 6d602462fb25ab52519ad971d4f6433b0d897522 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Thu, 1 Dec 2022 04:00:39 -0800 Subject: [PATCH 28/41] Fix restoring party state Instead of pulling it down from props on mount we're just pulling from state --- components/JobDropdown/index.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/components/JobDropdown/index.tsx b/components/JobDropdown/index.tsx index 6cfa6f03..179034f4 100644 --- a/components/JobDropdown/index.tsx +++ b/components/JobDropdown/index.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from "react" import { useRouter } from "next/router" +import { useSnapshot } from "valtio" import { appState } from "~utils/appState" import { jobGroups } from "~utils/jobGroups" @@ -21,11 +22,19 @@ const JobDropdown = React.forwardRef( const router = useRouter() const locale = router.locale || "en" + // Create snapshot of app state + const { party } = useSnapshot(appState) + // Set up local states for storing jobs const [currentJob, setCurrentJob] = useState() const [jobs, setJobs] = useState() const [sortedJobs, setSortedJobs] = useState() + // Set current job from state on mount + useEffect(() => { + setCurrentJob(party.job) + }, []) + // Organize jobs into groups on mount useEffect(() => { const jobGroups = appState.jobs @@ -67,11 +76,7 @@ const JobDropdown = React.forwardRef( .sort((a, b) => a.order - b.order) .map((item, i) => { return ( - ) @@ -88,8 +93,8 @@ const JobDropdown = React.forwardRef( return (