diff --git a/src/components/WeaponGrid/WeaponGrid.tsx b/src/components/WeaponGrid/WeaponGrid.tsx index bf181711..975a7177 100644 --- a/src/components/WeaponGrid/WeaponGrid.tsx +++ b/src/components/WeaponGrid/WeaponGrid.tsx @@ -1,112 +1,77 @@ import React, { useEffect, useState } from 'react' -import { withRouter } from 'react-router' import api from '~utils/api' -import WeaponGridMainhand from '~components/WeaponGridMainhand/WeaponGridMainhand' -import WeaponGridUnit from '~components/WeaponGridUnit/WeaponGridUnit' +import WeaponUnit from '~components/WeaponUnit/WeaponUnit' +import Button from '~components/Button/Button' import './WeaponGrid.css' -interface GridWeapon { - id: string - mainhand: boolean - position: number | null - weapon: Weapon -} - interface Props { - shortcode: string + userId: string + partyId: string + mainhand: Weapon | undefined + grid: GridArray editable: boolean + exists: boolean + found: boolean } -type GridArray = { [key: number]: Weapon } +type GridArray = { [key: number]: Weapon } const WeaponGrid = (props: Props) => { - const [partyId, setPartyId] = useState() - const [shortcode, setShortcode] = useState() + const numWeapons: number = 9 const [mainhand, setMainhand] = useState() const [weapons, setWeapons] = useState({}) - const numWeapons: number = 9 - useEffect(() => { - if (props.shortcode) { - fetchGrid(props.shortcode) - } else { - setIsValid(true) - } - }, []) + if (props.exists && props.found) + configure() + }, [props.mainhand, props.grid]) - function fetchGrid(shortcode: string) { - return api.endpoints.parties.getOne({ id: shortcode }) - .then(response => { - setupGrid(response) - }) - .catch(error => { - if (error.response.status == 404) { - gridNotFound() - } - }) - } - - function receiveMainhand(weapon: Weapon, _: number) { - // Store the mainhand weapon - setMainhand(weapon) - - if (partyId === undefined) { - let _partyId = '' - - createParty().then(response => { - const party = response.data.party - - setPartyId(party.id) - _partyId = party.id - - return party.shortcode - }) - .then((code: string) => { - setShortcode(shortcode) - window.history.replaceState(null, `Grid Tool: ${code}`, `/p/${code}`) - }) - .then(() => { - saveMainhand(_partyId, weapon) - }) - } else { - saveMainhand(partyId, weapon) - } - } - - function receiveWeapon(weapon: Weapon, position: number) { - // Store the grid unit weapon at the correct position - let newWeapons = Object.assign({}, weapons) - newWeapons[position] = weapon - setWeapons(newWeapons) - - if (partyId === undefined) { - let _partyId = '' - - createParty().then(response => { - const party = response.data.party - setPartyId(party.id) - _partyId = party.id - - return party.shortcode - }) - .then((code: string) => { - setShortcode(shortcode) - window.history.replaceState(null, `Grid Tool: ${code}`, `/p/${code}`) - }) - .then(() => { - saveWeapon(_partyId, weapon, position) - }) - } else { - saveWeapon(partyId, weapon, position) - } + function configure() { + setMainhand(props.mainhand) + setWeapons(props.grid) } function createParty() { - return api.endpoints.parties.create({}) + const body = (props.userId === '') ? {} : { + party: { + user_id: props.userId + } + } + + return api.endpoints.parties.create(body) + } + + function receiveWeapon(weapon: Weapon, position: number) { + const isMainhand = position == -1 + + if (isMainhand) { + setMainhand(weapon) + } else { + // Store the grid unit weapon at the correct position + let newWeapons = Object.assign({}, weapons) + newWeapons[position] = weapon + setWeapons(newWeapons) + } + + if (props.partyId == undefined) { + createParty() + .then(response => { + return response.data.party + }) + .then(party => { + window.history.replaceState(null, `Grid Tool`, `/p/${party.shortcode}`) + + return party.id + }) + .then(partyId => { + saveWeapon(partyId, weapon, position) + }) + } else { + saveWeapon(props.partyId, weapon, position) + } } function saveWeapon(pid: string, weapon: Weapon, position: number) { @@ -115,50 +80,56 @@ const WeaponGrid = (props: Props) => { 'party_id': pid, 'weapon_id': weapon.id, 'position': position, - 'mainhand': false + 'mainhand': (position == -1) } } api.endpoints.weapons.create(body) } - function saveMainhand(pid: string, weapon: Weapon) { - const body = { - 'weapon': { - 'party_id': pid, - 'weapon_id': weapon.id, - 'mainhand': true - } - } - - api.endpoints.weapons.create(body) + function renderGrid() { + return ( +
+ + +
    + { + Array.from(Array(numWeapons)).map((x, i) => { + return ( +
  • + +
  • + ) + }) + } +
+
+ ) } - return ( -
- + function renderGridNotFound() { + return ( +
+

There's no grid here.

+ +
+ ) + } -
    - { - Array.from(Array(numWeapons)).map((x, i) => { - return - }) - } -
-
- ) + return (props.found) ? renderGrid() : renderGridNotFound() } -export default withRouter(WeaponGrid) +export default WeaponGrid diff --git a/src/components/WeaponGridMainhand/WeaponGridMainhand.css b/src/components/WeaponGridMainhand/WeaponGridMainhand.css deleted file mode 100644 index 7cc4f1c6..00000000 --- a/src/components/WeaponGridMainhand/WeaponGridMainhand.css +++ /dev/null @@ -1,67 +0,0 @@ -.WeaponGridMainhand { - display: flex; - flex-direction: column; - gap: 4px; - font-size: 14px; - margin-right: 24px; - max-width: 200px; -} - -.WeaponGridMainhand .WeaponGridImage { - display: flex; - align-items: center; - justify-content: center; - - background: white; - border: 1px solid rgba(0, 0, 0, 0); - border-radius: 8px; - height: 420px; - overflow: hidden; - transition: all 0.18s ease-in-out; - width: 200px; -} - -.editable .WeaponGridMainhand:hover { - border: 1px solid rgba(0, 0, 0, 0.1); - box-shadow: rgba(0, 0, 0, 0.14) 0px 0px 14px; - cursor: pointer; - transform: scale(1.05, 1.05); -} - -.WeaponGridMainhand h3 { - color: #333; - font-weight: 500; - margin: 0; - text-align: center; -} - -.WeaponGridMainhand img { - position: relative; - width: 100%; - z-index: 2; -} - -.WeaponGridImage .icon { - position: absolute; - color: #c9c9c9; - height: 20px; - width: 20px; - z-index: 1; -} - -.WeaponGridImage:hover .icon { - color: #555; -} - -.WeaponGridMainhand h3, -.WeaponGridMainhand ul { - display: none; -} - -.filled h3 { - display: block; -} - -.filled ul { - display: flex; -} \ No newline at end of file diff --git a/src/components/WeaponGridMainhand/WeaponGridMainhand.tsx b/src/components/WeaponGridMainhand/WeaponGridMainhand.tsx deleted file mode 100644 index 82b9823f..00000000 --- a/src/components/WeaponGridMainhand/WeaponGridMainhand.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React, { useEffect } from 'react' -import classnames from 'classnames' -import { useModal as useModal } from '~utils/useModal' - -import SearchModal from '~components/SearchModal/SearchModal' -import UncapIndicator from '~components/UncapIndicator/UncapIndicator' - -import mainhandImages from '../../images/mainhand/*.jpg' -import Plus from '../../../assets/plus.svg' - -import './WeaponGridMainhand.css' - -function WeaponGridMainhand(props: WeaponGridProps) { - const { open, openModal, closeModal } = useModal() - - useEffect(() => { - // console.log('Mainhand weapon prop was updated.') - }, [props.weapon]) - - let imgSrc - if (props.weapon) { - const weapon = props.weapon! - - if (process.env.NODE_ENV === 'development') { - imgSrc = mainhandImages[weapon.granblue_id] - } else if (process.env.NODE_ENV === 'production') { - imgSrc = `${process.env.SIERO_IMG_URL}/mainhand/${weapon.granblue_id}.jpg` - } - } - - const openModalIfEditable = (props.editable) ? openModal : () => {} - - const classes = classnames({ - WeaponGridMainhand: true, - 'editable': props.editable, - 'filled': (props.weapon !== undefined) - }) - - const weapon = props.weapon - - return ( -
-
-
- - { (props.editable) ? : '' } -
- -

{weapon?.name.en}

-
- {open ? ( - - ) : null} -
- ) -} - -export default WeaponGridMainhand diff --git a/src/components/WeaponGridUnit/WeaponGridUnit.tsx b/src/components/WeaponGridUnit/WeaponGridUnit.tsx deleted file mode 100644 index 22bbb4cc..00000000 --- a/src/components/WeaponGridUnit/WeaponGridUnit.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react' -import classnames from 'classnames' -import { useModal as useModal } from '~utils/useModal' - -import SearchModal from '~components/SearchModal/SearchModal' -import UncapIndicator from '~components/UncapIndicator/UncapIndicator' - -import gridImages from '../../images/grid/*.jpg' -import Plus from '../../../assets/plus.svg' - -import './WeaponGridUnit.css' - -function WeaponGridUnit(props: WeaponGridProps) { - const { open, openModal, closeModal } = useModal() - - let imgSrc - if (props.weapon) { - const weapon = props.weapon! - - // Generate the correct source for the weapon - if (process.env.NODE_ENV === 'development') { - imgSrc = gridImages[weapon.granblue_id] - } else if (process.env.NODE_ENV === 'production') { - imgSrc = `${process.env.SIERO_IMG_URL}/grid/${weapon.granblue_id}.jpg` - } - } - - const openModalIfEditable = (props.editable) ? openModal : () => {} - - const classes = classnames({ - WeaponGridUnit: true, - 'editable': props.editable, - 'filled': (props.weapon !== undefined) - }) - - const weapon = props.weapon - - return ( -
  • -
    -
    - - { (props.editable) ? : '' } -
    - -

    {weapon?.name.en}

    -
    - {open ? ( - - ) : null} -
  • - ) -} - -export default WeaponGridUnit diff --git a/src/components/WeaponGridUnit/WeaponGridUnit.css b/src/components/WeaponUnit/WeaponUnit.css similarity index 63% rename from src/components/WeaponGridUnit/WeaponGridUnit.css rename to src/components/WeaponUnit/WeaponUnit.css index 7d2d579b..8bf721b0 100644 --- a/src/components/WeaponGridUnit/WeaponGridUnit.css +++ b/src/components/WeaponUnit/WeaponUnit.css @@ -1,47 +1,54 @@ -.WeaponGridUnit { +.WeaponUnit { display: flex; flex-direction: column; gap: 4px; - font-size: 14px; - max-width: 160px; } -.WeaponGridUnit .WeaponGridImage { - display: flex; - align-items: center; - justify-content: center; - +.WeaponUnit .WeaponImage { background: white; border: 1px solid rgba(0, 0, 0, 0); border-radius: 8px; - height: 92px; - list-style-type: none; + display: flex; + align-items: center; + justify-content: center; overflow: hidden; transition: all 0.18s ease-in-out; - width: 160px; } -.editable .WeaponGridImage:hover { +.WeaponUnit.editable .WeaponImage:hover { border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: rgba(0, 0, 0, 0.14) 0px 0px 14px; cursor: pointer; transform: scale(1.1, 1.1); } -.WeaponGridUnit h3 { +.WeaponUnit.filled h3 { + display: block; +} + +.WeaponUnit.filled ul { + display: flex; +} + +.WeaponUnit h3, +.WeaponUnit ul { + display: none; +} + +.WeaponUnit h3 { color: #333; font-weight: 500; margin: 0; text-align: center; } -.WeaponGridUnit img { +.WeaponUnit img { position: relative; width: 100%; z-index: 2; } -.WeaponGridImage .icon { +.WeaponImage .icon { position: absolute; color: #c9c9c9; height: 20px; @@ -49,19 +56,28 @@ z-index: 1; } -.WeaponGridImage:hover .icon { +.WeaponImage:hover .icon { color: #555; } -.WeaponGridUnit h3, -.WeaponGridUnit ul { - display: none; +/* Mainhand */ +.WeaponUnit.mainhand { + margin-right: 24px; + max-width: 200px; } -.filled h3 { - display: block; +.WeaponUnit.mainhand .WeaponImage { + height: 420px; + width: 200px; } -.filled ul { - display: flex; +/* Grid */ +.WeaponUnit.grid { + max-width: 160px; +} + +.WeaponUnit.grid .WeaponImage { + list-style-type: none; + height: 92px; + width: 160px; } \ No newline at end of file diff --git a/src/components/WeaponUnit/WeaponUnit.tsx b/src/components/WeaponUnit/WeaponUnit.tsx new file mode 100644 index 00000000..fac0ba84 --- /dev/null +++ b/src/components/WeaponUnit/WeaponUnit.tsx @@ -0,0 +1,96 @@ +import React, { useEffect, useState } from 'react' +import classnames from 'classnames' +import { useModal as useModal } from '~utils/useModal' + +import SearchModal from '~components/SearchModal/SearchModal' +import UncapIndicator from '~components/UncapIndicator/UncapIndicator' + +import mainhandImages from '../../images/mainhand/*.jpg' +import gridImages from '../../images/grid/*.jpg' +import Plus from '../../../assets/plus.svg' + +import './WeaponUnit.css' + +interface Props { + onReceiveData: (weapon: Weapon, position: number) => void + weapon: Weapon | undefined + position: number + editable: boolean + unitType: 0 | 1 +} + +function WeaponUnit(props: Props) { + const [imageUrl, setImageUrl] = useState('') + + const { open, openModal, closeModal } = useModal() + + const openModalIfEditable = (props.editable) ? openModal : () => {} + + const classes = classnames({ + WeaponUnit: true, + 'mainhand': props.unitType == 0, + 'grid': props.unitType == 1, + 'editable': props.editable, + 'filled': (props.weapon !== undefined) + }) + + const weapon = props.weapon + + useEffect(() => { + generateImageUrl() + }) + + function generateImageUrl() { + let imgSrc + if (props.weapon) { + const weapon = props.weapon! + + // Generate the correct source for the weapon + if (process.env.NODE_ENV === 'development') { + if (props.unitType == 0) + imgSrc = mainhandImages[weapon.granblue_id] + else + imgSrc = gridImages[weapon.granblue_id] + } else if (process.env.NODE_ENV === 'production') { + if (props.unitType == 0) + imgSrc = `${process.env.SIERO_IMG_URL}/mainhand/${weapon.granblue_id}.jpg` + else + imgSrc = `${process.env.SIERO_IMG_URL}/grid/${weapon.granblue_id}.jpg` + } + } + + setImageUrl(imgSrc) + } + + return ( +
    +
    +
    + { + (imageUrl != '') + ? + : + + } + { (props.editable) ? : '' } +
    + +

    {weapon?.name.en}

    +
    + {open ? ( + + ) : null} +
    + ) +} + +export default WeaponUnit diff --git a/src/routes/Party/Party.tsx b/src/routes/Party/Party.tsx index 2f52be9a..cd46e87e 100644 --- a/src/routes/Party/Party.tsx +++ b/src/routes/Party/Party.tsx @@ -1,24 +1,95 @@ -import React from 'react' -import { RouteComponentProps, withRouter } from 'react-router' +import React, { useEffect, useState } from 'react' +import { withCookies, useCookies, Cookies } from 'react-cookie' +import { RouteComponentProps, withRouter } from 'react-router-dom' +import api from '~utils/api' import WeaponGrid from '../../components/WeaponGrid/WeaponGrid' -interface RouterProps { +interface Props { hash: string } -interface PartyProps extends RouteComponentProps { - +interface State { + found: boolean + editable: boolean + mainhand: Weapon, + grid: GridArray, + partyId: string } -const Party: React.FC = ({ match }) => { +interface PartyProps extends RouteComponentProps {} + +type GridArray = { [key: number]: Weapon } +interface GridWeapon { + id: string + mainhand: boolean + position: number | null + weapon: Weapon +} + +const Party: React.FC = ({ match }, state: State) => { + const [found, setFound] = useState(false) + const [editable, setEditable] = useState(false) + const [grid, setGrid] = useState({}) + const [mainhand, setMainhand] = useState() + const [partyId, setPartyId] = useState('') + const [cookies, setCookie] = useCookies(['userId']) + const shortcode = match.params.hash || '' + useEffect(() => { + fetchGrid(shortcode) + }, []) + + async function fetchGrid(shortcode: string) { + return api.endpoints.parties.getOne({ id: shortcode }) + .then(response => { + const party = response.data.party + + if (party.user_id === cookies.user_id) + setEditable(true) + + let weapons: GridArray = {} + party.grid.forEach((gridWeapon: GridWeapon) => { + if (gridWeapon.mainhand) + setMainhand(gridWeapon.weapon) + else if (!gridWeapon.mainhand && gridWeapon.position != null) + weapons[gridWeapon.position] = gridWeapon.weapon + }) + + setFound(true) + setGrid(weapons) + setPartyId(party.id) + }) + .catch(error => { + if (error.response != null) { + if (error.response.status == 404) { + setFound(false) + } + } else { + console.error(error) + } + }) + } + return (
    - +
    ) } -export default withRouter(Party) \ No newline at end of file +export default + withCookies( + withRouter( + Party + ) + ) \ No newline at end of file