commit
aa20d0d4ac
26 changed files with 609 additions and 29 deletions
|
|
@ -3,6 +3,7 @@ import { useRouter } from 'next/router'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
import clonedeep from 'lodash.clonedeep'
|
import clonedeep from 'lodash.clonedeep'
|
||||||
|
import * as Scroll from 'react-scroll'
|
||||||
|
|
||||||
import * as AlertDialog from '@radix-ui/react-alert-dialog'
|
import * as AlertDialog from '@radix-ui/react-alert-dialog'
|
||||||
|
|
||||||
|
|
@ -21,6 +22,7 @@ const BottomHeader = () => {
|
||||||
const app = useSnapshot(appState)
|
const app = useSnapshot(appState)
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const scroll = Scroll.animateScroll;
|
||||||
|
|
||||||
// Cookies
|
// Cookies
|
||||||
const [cookies] = useCookies(['user'])
|
const [cookies] = useCookies(['user'])
|
||||||
|
|
@ -30,6 +32,15 @@ const BottomHeader = () => {
|
||||||
}
|
}
|
||||||
} : {}
|
} : {}
|
||||||
|
|
||||||
|
function toggleDetails() {
|
||||||
|
appState.party.detailsVisible = !appState.party.detailsVisible
|
||||||
|
|
||||||
|
if (appState.party.detailsVisible)
|
||||||
|
scroll.scrollToBottom()
|
||||||
|
else
|
||||||
|
scroll.scrollToTop()
|
||||||
|
}
|
||||||
|
|
||||||
function deleteTeam(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
|
function deleteTeam(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
|
||||||
if (appState.party.editable && appState.party.id) {
|
if (appState.party.editable && appState.party.id) {
|
||||||
api.endpoints.parties.destroy(appState.party.id, headers)
|
api.endpoints.parties.destroy(appState.party.id, headers)
|
||||||
|
|
@ -53,9 +64,11 @@ const BottomHeader = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const leftNav = () => {
|
const leftNav = () => {
|
||||||
return (
|
if (app.party.detailsVisible) {
|
||||||
<Button icon="edit" click={() => {}}>Add more info</Button>
|
return (<Button icon="edit" active={true} click={toggleDetails}>Hide info</Button>)
|
||||||
)
|
} else {
|
||||||
|
return (<Button icon="edit" click={toggleDetails}>Edit info</Button>)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rightNav = () => {
|
const rightNav = () => {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.Active {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
&.btn-blue {
|
&.btn-blue {
|
||||||
background: $blue;
|
background: $blue;
|
||||||
color: #8b8b8b;
|
color: #8b8b8b;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import './index.scss'
|
||||||
import { ButtonType } from '~utils/enums'
|
import { ButtonType } from '~utils/enums'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
active: boolean
|
||||||
disabled: boolean
|
disabled: boolean
|
||||||
icon: string | null
|
icon: string | null
|
||||||
type: ButtonType
|
type: ButtonType
|
||||||
|
|
@ -26,6 +27,7 @@ interface State {
|
||||||
|
|
||||||
class Button extends React.Component<Props, State> {
|
class Button extends React.Component<Props, State> {
|
||||||
static defaultProps: Props = {
|
static defaultProps: Props = {
|
||||||
|
active: false,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
icon: null,
|
icon: null,
|
||||||
type: ButtonType.Base,
|
type: ButtonType.Base,
|
||||||
|
|
@ -65,6 +67,7 @@ class Button extends React.Component<Props, State> {
|
||||||
|
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
Button: true,
|
Button: true,
|
||||||
|
'Active': this.props.active,
|
||||||
'btn-pressed': this.state.isPressed,
|
'btn-pressed': this.state.isPressed,
|
||||||
'btn-disabled': this.props.disabled,
|
'btn-disabled': this.props.disabled,
|
||||||
'destructive': this.props.type == ButtonType.Destructive
|
'destructive': this.props.type == ButtonType.Destructive
|
||||||
|
|
|
||||||
29
components/CharLimitedFieldset/index.scss
Normal file
29
components/CharLimitedFieldset/index.scss
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
.Limited {
|
||||||
|
background: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
gap: $unit;
|
||||||
|
padding-right: $unit * 2;
|
||||||
|
|
||||||
|
&:focus-within {
|
||||||
|
border: 2px solid #275DC5;
|
||||||
|
box-shadow: 0 2px rgba(255, 255, 255, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.Counter {
|
||||||
|
color: $grey-50;
|
||||||
|
font-weight: $bold;
|
||||||
|
line-height: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Input {
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
components/CharLimitedFieldset/index.tsx
Normal file
54
components/CharLimitedFieldset/index.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import './index.scss'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
fieldName: string
|
||||||
|
placeholder: string
|
||||||
|
value?: string
|
||||||
|
limit: number
|
||||||
|
error: string
|
||||||
|
onBlur?: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||||
|
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const CharLimitedFieldset = React.forwardRef<HTMLInputElement, Props>(function fieldSet(props, ref) {
|
||||||
|
const fieldType = (['password', 'confirm_password'].includes(props.fieldName)) ? 'password' : 'text'
|
||||||
|
|
||||||
|
const [currentCount, setCurrentCount] = useState(0)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentCount((props.value) ? props.limit - props.value.length : props.limit)
|
||||||
|
}, [props.limit, props.value])
|
||||||
|
|
||||||
|
function onChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||||
|
setCurrentCount(props.limit - event.currentTarget.value.length)
|
||||||
|
if (props.onChange) props.onChange(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<fieldset className="Fieldset">
|
||||||
|
<div className="Limited">
|
||||||
|
<input
|
||||||
|
autoComplete="off"
|
||||||
|
className="Input"
|
||||||
|
type={fieldType}
|
||||||
|
name={props.fieldName}
|
||||||
|
placeholder={props.placeholder}
|
||||||
|
defaultValue={props.value || ''}
|
||||||
|
onBlur={props.onBlur}
|
||||||
|
onChange={onChange}
|
||||||
|
maxLength={props.limit}
|
||||||
|
ref={ref}
|
||||||
|
formNoValidate
|
||||||
|
/>
|
||||||
|
<span className="Counter">{currentCount}</span>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
props.error.length > 0 &&
|
||||||
|
<p className='InputError'>{props.error}</p>
|
||||||
|
}
|
||||||
|
</fieldset>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default CharLimitedFieldset
|
||||||
|
|
@ -4,6 +4,7 @@ import './index.scss'
|
||||||
interface Props {
|
interface Props {
|
||||||
fieldName: string
|
fieldName: string
|
||||||
placeholder: string
|
placeholder: string
|
||||||
|
value?: string
|
||||||
error: string
|
error: string
|
||||||
onBlur?: (event: React.ChangeEvent<HTMLInputElement>) => void
|
onBlur?: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||||
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
|
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||||
|
|
@ -17,9 +18,10 @@ const Fieldset = React.forwardRef<HTMLInputElement, Props>(function fieldSet(pro
|
||||||
<input
|
<input
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
className="Input"
|
className="Input"
|
||||||
name={props.fieldName}
|
|
||||||
type={fieldType}
|
type={fieldType}
|
||||||
|
name={props.fieldName}
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
|
defaultValue={props.value || ''}
|
||||||
onBlur={props.onBlur}
|
onBlur={props.onBlur}
|
||||||
onChange={props.onChange}
|
onChange={props.onChange}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
.Extra {
|
#Party {
|
||||||
|
margin-bottom: $unit * 4;
|
||||||
|
}
|
||||||
|
#Party .Extra {
|
||||||
color: #888;
|
color: #888;
|
||||||
display: flex;
|
display: flex;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import React, { useEffect, useState } from 'react'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
|
||||||
|
|
||||||
import PartySegmentedControl from '~components/PartySegmentedControl'
|
import PartySegmentedControl from '~components/PartySegmentedControl'
|
||||||
|
import PartyDetails from '~components/PartyDetails'
|
||||||
import WeaponGrid from '~components/WeaponGrid'
|
import WeaponGrid from '~components/WeaponGrid'
|
||||||
import SummonGrid from '~components/SummonGrid'
|
import SummonGrid from '~components/SummonGrid'
|
||||||
import CharacterGrid from '~components/CharacterGrid'
|
import CharacterGrid from '~components/CharacterGrid'
|
||||||
|
|
@ -13,6 +13,7 @@ import { appState } from '~utils/appState'
|
||||||
import { GridType, TeamElement } from '~utils/enums'
|
import { GridType, TeamElement } from '~utils/enums'
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
import { AxiosResponse } from 'axios'
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -33,29 +34,60 @@ const Party = (props: Props) => {
|
||||||
const { party } = useSnapshot(appState)
|
const { party } = useSnapshot(appState)
|
||||||
const [currentTab, setCurrentTab] = useState<GridType>(GridType.Weapon)
|
const [currentTab, setCurrentTab] = useState<GridType>(GridType.Weapon)
|
||||||
|
|
||||||
|
// Fetch data from the server
|
||||||
|
useEffect(() => {
|
||||||
|
const shortcode = (props.slug) ? props.slug : undefined
|
||||||
|
|
||||||
|
if (shortcode)
|
||||||
|
fetchDetails(shortcode)
|
||||||
|
else
|
||||||
|
appState.party.editable = true
|
||||||
|
}, [props.slug])
|
||||||
|
|
||||||
// Methods: Creating a new party
|
// Methods: Creating a new party
|
||||||
async function createParty(extra: boolean = false) {
|
async function createParty(extra: boolean = false) {
|
||||||
let body = {
|
let body = {
|
||||||
party: {
|
party: {
|
||||||
...(cookies.user) && { user_id: cookies.user.user_id },
|
...(cookies.user) && { user_id: cookies.user.user_id },
|
||||||
is_extra: extra
|
extra: extra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return await api.endpoints.parties.create(body, headers)
|
return await api.endpoints.parties.create(body, headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods: Updating the party's extra flag
|
// Methods: Updating the party's details
|
||||||
function checkboxChanged(event: React.ChangeEvent<HTMLInputElement>) {
|
function checkboxChanged(event: React.ChangeEvent<HTMLInputElement>) {
|
||||||
appState.party.extra = event.target.checked
|
appState.party.extra = event.target.checked
|
||||||
|
|
||||||
if (party.id) {
|
if (party.id) {
|
||||||
api.endpoints.parties.update(party.id, {
|
api.endpoints.parties.update(party.id, {
|
||||||
'party': { 'is_extra': event.target.checked }
|
'party': { 'extra': event.target.checked }
|
||||||
}, headers)
|
}, headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateDetails(name?: string, description?: string, raid?: Raid) {
|
||||||
|
if (appState.party.name !== name ||
|
||||||
|
appState.party.description !== description ||
|
||||||
|
appState.party.raid?.id !== raid?.id) {
|
||||||
|
if (appState.party.id)
|
||||||
|
api.endpoints.parties.update(appState.party.id, {
|
||||||
|
'party': {
|
||||||
|
'name': name,
|
||||||
|
'description': description,
|
||||||
|
'raid_id': raid?.id
|
||||||
|
}
|
||||||
|
}, headers)
|
||||||
|
.then(() => {
|
||||||
|
appState.party.name = name
|
||||||
|
appState.party.description = description
|
||||||
|
appState.party.raid = raid
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Methods: Navigating with segmented control
|
// Methods: Navigating with segmented control
|
||||||
function segmentClicked(event: React.ChangeEvent<HTMLInputElement>) {
|
function segmentClicked(event: React.ChangeEvent<HTMLInputElement>) {
|
||||||
switch(event.target.value) {
|
switch(event.target.value) {
|
||||||
|
|
@ -76,6 +108,33 @@ const Party = (props: Props) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Methods: Fetch party details
|
||||||
|
function fetchDetails(shortcode: string) {
|
||||||
|
return api.endpoints.parties.getOne({ id: shortcode })
|
||||||
|
.then(response => processResult(response))
|
||||||
|
.catch(error => processError(error))
|
||||||
|
}
|
||||||
|
|
||||||
|
function processResult(response: AxiosResponse) {
|
||||||
|
appState.party.id = response.data.party.id
|
||||||
|
|
||||||
|
// Store the party's user-generated details
|
||||||
|
appState.party.name = response.data.party.name
|
||||||
|
appState.party.description = response.data.party.description
|
||||||
|
appState.party.raid = response.data.party.raid
|
||||||
|
}
|
||||||
|
|
||||||
|
function processError(error: any) {
|
||||||
|
if (error.response != null) {
|
||||||
|
if (error.response.status == 404) {
|
||||||
|
// setFound(false)
|
||||||
|
// setLoading(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render: JSX components
|
// Render: JSX components
|
||||||
const navigation = (
|
const navigation = (
|
||||||
<PartySegmentedControl
|
<PartySegmentedControl
|
||||||
|
|
@ -123,7 +182,13 @@ const Party = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{ navigation }
|
{ navigation }
|
||||||
{ currentGrid() }
|
<section id="Party">
|
||||||
|
{ currentGrid() }
|
||||||
|
</section>
|
||||||
|
{ <PartyDetails
|
||||||
|
editable={party.editable}
|
||||||
|
updateCallback={updateDetails}
|
||||||
|
/>}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
87
components/PartyDetails/index.scss
Normal file
87
components/PartyDetails/index.scss
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
.Details {
|
||||||
|
display: none; // This breaks transition, find a workaround
|
||||||
|
opacity: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: $unit * 95;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.Editable {
|
||||||
|
top: $unit;
|
||||||
|
height: 0;
|
||||||
|
z-index: 2;
|
||||||
|
transition: opacity 0.2s ease-in-out,
|
||||||
|
top 0.2s ease-in-out;
|
||||||
|
|
||||||
|
|
||||||
|
&.Visible {
|
||||||
|
display: block;
|
||||||
|
height: auto;
|
||||||
|
margin-bottom: 40vh;
|
||||||
|
opacity: 1;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
min-height: $unit * 20;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
appearance: none;
|
||||||
|
background-image: url('/icons/Arrow.svg');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position-y: center;
|
||||||
|
background-position-x: 98%;
|
||||||
|
background-size: $unit * 1.5;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: $grey-00;
|
||||||
|
margin-bottom: $unit;
|
||||||
|
font-size: $font-regular;
|
||||||
|
padding: 0 ($unit * 2);
|
||||||
|
height: $unit * 6;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ReadOnly {
|
||||||
|
top: $unit * -1;
|
||||||
|
transition: opacity 0.2s ease-in-out,
|
||||||
|
top 0.2s ease-in-out;
|
||||||
|
|
||||||
|
&.Visible {
|
||||||
|
display: block;
|
||||||
|
height: auto;
|
||||||
|
opacity: 1;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: $font-xlarge;
|
||||||
|
font-weight: $normal;
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: $unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Raid {
|
||||||
|
color: $grey-50;
|
||||||
|
font-size: $font-regular;
|
||||||
|
font-weight: $medium;
|
||||||
|
margin-bottom: $unit * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: $font-regular;
|
||||||
|
line-height: $font-regular * 1.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
components/PartyDetails/index.tsx
Normal file
114
components/PartyDetails/index.tsx
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { useSnapshot } from 'valtio'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
|
||||||
|
import CharLimitedFieldset from '~components/CharLimitedFieldset'
|
||||||
|
import TextFieldset from '~components/TextFieldset'
|
||||||
|
|
||||||
|
import { appState } from '~utils/appState'
|
||||||
|
|
||||||
|
import './index.scss'
|
||||||
|
import RaidDropdown from '~components/RaidDropdown'
|
||||||
|
|
||||||
|
// Props
|
||||||
|
interface Props {
|
||||||
|
editable: boolean
|
||||||
|
updateCallback: (name?: string, description?: string, raid?: Raid) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const PartyDetails = (props: Props) => {
|
||||||
|
const appSnapshot = useSnapshot(appState)
|
||||||
|
|
||||||
|
const nameInput = React.createRef<HTMLInputElement>()
|
||||||
|
const descriptionInput = React.createRef<HTMLTextAreaElement>()
|
||||||
|
const raidSelect = React.createRef<HTMLSelectElement>()
|
||||||
|
|
||||||
|
const readOnlyClasses = classNames({
|
||||||
|
'Details': true,
|
||||||
|
'ReadOnly': true,
|
||||||
|
'Visible': !appSnapshot.party.detailsVisible
|
||||||
|
})
|
||||||
|
|
||||||
|
const editableClasses = classNames({
|
||||||
|
'Details': true,
|
||||||
|
'Editable': true,
|
||||||
|
'Visible': appSnapshot.party.detailsVisible
|
||||||
|
})
|
||||||
|
|
||||||
|
const [errors, setErrors] = useState<{ [key: string]: string }>({
|
||||||
|
name: '',
|
||||||
|
description: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
const { name, value } = event.target
|
||||||
|
let newErrors = errors
|
||||||
|
|
||||||
|
setErrors(newErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTextAreaChange(event: React.ChangeEvent<HTMLTextAreaElement>) {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
const { name, value } = event.target
|
||||||
|
let newErrors = errors
|
||||||
|
|
||||||
|
setErrors(newErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDetails(event: React.ChangeEvent) {
|
||||||
|
const nameValue = nameInput.current?.value
|
||||||
|
const descriptionValue = descriptionInput.current?.value
|
||||||
|
const raid = appSnapshot.raids.find(raid => raid.id == raidSelect.current?.value)
|
||||||
|
|
||||||
|
props.updateCallback(nameValue, descriptionValue, raid)
|
||||||
|
}
|
||||||
|
|
||||||
|
const editable = (
|
||||||
|
<section className={editableClasses}>
|
||||||
|
<CharLimitedFieldset
|
||||||
|
fieldName="name"
|
||||||
|
placeholder="Name your team"
|
||||||
|
value={appSnapshot.party.name}
|
||||||
|
limit={50}
|
||||||
|
onBlur={updateDetails}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
error={errors.name}
|
||||||
|
ref={nameInput}
|
||||||
|
/>
|
||||||
|
<RaidDropdown
|
||||||
|
selected={appSnapshot.party.raid?.id || ''}
|
||||||
|
onBlur={updateDetails}
|
||||||
|
ref={raidSelect}
|
||||||
|
/>
|
||||||
|
<TextFieldset
|
||||||
|
fieldName="name"
|
||||||
|
placeholder={"Write your notes here\n\n\nWatch out for the 50% trigger!\nMake sure to click Fediel’s 1 first\nGood luck with RNG!"}
|
||||||
|
value={appSnapshot.party.description}
|
||||||
|
onBlur={updateDetails}
|
||||||
|
onChange={handleTextAreaChange}
|
||||||
|
error={errors.description}
|
||||||
|
ref={descriptionInput}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
|
||||||
|
const readOnly = (
|
||||||
|
<section className={readOnlyClasses}>
|
||||||
|
<h1>{ (appSnapshot.party.name) ? appSnapshot.party.name : 'No title' }</h1>
|
||||||
|
{ (appSnapshot.party.raid) ? <div className="Raid">{appSnapshot.party.raid.name.en}</div> : '' }
|
||||||
|
<p>{ (appSnapshot.party.description) ? appSnapshot.party.description : '' }</p>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{readOnly}
|
||||||
|
{editable}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartyDetails
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
gap: 58px;
|
gap: 58px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
margin-bottom: $unit * 3;
|
||||||
max-width: 760px;
|
max-width: 760px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
components/RaidDropdown/index.scss
Normal file
0
components/RaidDropdown/index.scss
Normal file
93
components/RaidDropdown/index.tsx
Normal file
93
components/RaidDropdown/index.tsx
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useCookies } from 'react-cookie'
|
||||||
|
|
||||||
|
import { appState } from '~utils/appState'
|
||||||
|
import api from '~utils/api'
|
||||||
|
|
||||||
|
import './index.scss'
|
||||||
|
|
||||||
|
// Props
|
||||||
|
interface Props {
|
||||||
|
selected?: string
|
||||||
|
onBlur: (event: React.ChangeEvent<HTMLSelectElement>) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function fieldSet(props, ref) {
|
||||||
|
const [cookies, _] = useCookies(['user'])
|
||||||
|
const headers = (cookies.user != null) ? {
|
||||||
|
headers: { 'Authorization': `Bearer ${cookies.user.access_token}` }
|
||||||
|
} : {}
|
||||||
|
|
||||||
|
const [raids, setRaids] = useState<Raid[][]>()
|
||||||
|
const [flatRaids, setFlatRaids] = useState<Raid[]>()
|
||||||
|
|
||||||
|
const raidGroups = [
|
||||||
|
'Assorted',
|
||||||
|
'Omega',
|
||||||
|
'T1 Summons',
|
||||||
|
'T2 Summons',
|
||||||
|
'Primarchs',
|
||||||
|
'Nightmare',
|
||||||
|
'Omega (Impossible)',
|
||||||
|
'Omega II',
|
||||||
|
'Tier 1 Summons (Impossible)',
|
||||||
|
'Tier 3 Summons',
|
||||||
|
'Ennead',
|
||||||
|
'Malice',
|
||||||
|
'6-Star Raids',
|
||||||
|
'Six-Dragons',
|
||||||
|
'Nightmare (Impossible)',
|
||||||
|
'Astral',
|
||||||
|
'Super Ultimate'
|
||||||
|
]
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchRaids()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
function fetchRaids() {
|
||||||
|
api.endpoints.raids.getAll(headers)
|
||||||
|
.then((response) => {
|
||||||
|
const raids = response.data.map((r: any) => r.raid)
|
||||||
|
|
||||||
|
appState.raids = raids
|
||||||
|
organizeRaids(raids)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function organizeRaids(raids: Raid[]) {
|
||||||
|
const numGroups = Math.max.apply(Math, raids.map(raid => raid.group))
|
||||||
|
let groupedRaids = []
|
||||||
|
|
||||||
|
for (let i = 0; i <= numGroups; i++) {
|
||||||
|
groupedRaids[i] = raids.filter(raid => raid.group == i)
|
||||||
|
}
|
||||||
|
|
||||||
|
setRaids(groupedRaids)
|
||||||
|
}
|
||||||
|
|
||||||
|
function raidGroup(index: number) {
|
||||||
|
const options = raids && raids.length > 0 && raids[index].length > 0 &&
|
||||||
|
raids[index].sort((a, b) => a.element - b.element).map((item, i) => {
|
||||||
|
return (
|
||||||
|
<option key={i} value={item.id}>{item.name.en}</option>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<optgroup key={index} label={raidGroups[index]}>
|
||||||
|
{options}
|
||||||
|
</optgroup>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<select key={props.selected} defaultValue={props.selected} onBlur={props.onBlur} ref={ref}>
|
||||||
|
{ Array.from(Array(raids?.length)).map((x, i) => {
|
||||||
|
return raidGroup(i)
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default RaidDropdown
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
.SegmentedControlWrapper {
|
.SegmentedControlWrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: $unit * 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.SegmentedControl {
|
.SegmentedControl {
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ const SignupModal = (props: Props) => {
|
||||||
|
|
||||||
setErrors(newErrors)
|
setErrors(newErrors)
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.log(error)
|
console.error(error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +88,7 @@ const SignupModal = (props: Props) => {
|
||||||
|
|
||||||
props.close()
|
props.close()
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.log(error)
|
console.error(error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
components/TextFieldset/index.scss
Normal file
5
components/TextFieldset/index.scss
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
.Fieldset textarea {
|
||||||
|
color: $grey-00;
|
||||||
|
font-family: system-ui, -apple-system, 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 21px;
|
||||||
|
}
|
||||||
33
components/TextFieldset/index.tsx
Normal file
33
components/TextFieldset/index.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react'
|
||||||
|
import './index.scss'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
fieldName: string
|
||||||
|
placeholder: string
|
||||||
|
value?: string
|
||||||
|
error: string
|
||||||
|
onBlur?: (event: React.ChangeEvent<HTMLTextAreaElement>) => void
|
||||||
|
onChange?: (event: React.ChangeEvent<HTMLTextAreaElement>) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const TextFieldset = React.forwardRef<HTMLTextAreaElement, Props>(function fieldSet(props, ref) {
|
||||||
|
return (
|
||||||
|
<fieldset className="Fieldset">
|
||||||
|
<textarea
|
||||||
|
className="Input"
|
||||||
|
name={props.fieldName}
|
||||||
|
placeholder={props.placeholder}
|
||||||
|
defaultValue={props.value || ''}
|
||||||
|
onBlur={props.onBlur}
|
||||||
|
onChange={props.onChange}
|
||||||
|
ref={ref}
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
props.error.length > 0 &&
|
||||||
|
<p className='InputError'>{props.error}</p>
|
||||||
|
}
|
||||||
|
</fieldset>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default TextFieldset
|
||||||
|
|
@ -21,6 +21,10 @@
|
||||||
margin-bottom: $unit * 2;
|
margin-bottom: $unit * 2;
|
||||||
margin-right: $unit * 2;
|
margin-right: $unit * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:nth-last-child(-n+3) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid_weapons > *:nth-child(3n+3) {
|
.grid_weapons > *:nth-child(3n+3) {
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ const WeaponGrid = (props: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function processResult(response: AxiosResponse) {
|
function processResult(response: AxiosResponse) {
|
||||||
|
console.log("Retrieved data from server...")
|
||||||
|
|
||||||
// Store the response
|
// Store the response
|
||||||
const party = response.data.party
|
const party = response.data.party
|
||||||
|
|
||||||
|
|
@ -252,7 +254,7 @@ const WeaponGrid = (props: Props) => {
|
||||||
|
|
||||||
const extraGridElement = (
|
const extraGridElement = (
|
||||||
<ExtraWeapons
|
<ExtraWeapons
|
||||||
grid={appState.grid.weapons.allWeapons}
|
grid={grid.weapons.allWeapons}
|
||||||
editable={party.editable}
|
editable={party.editable}
|
||||||
offset={numWeapons}
|
offset={numWeapons}
|
||||||
updateObject={receiveWeaponFromSearch}
|
updateObject={receiveWeaponFromSearch}
|
||||||
|
|
|
||||||
60
package-lock.json
generated
60
package-lock.json
generated
|
|
@ -24,6 +24,7 @@
|
||||||
"react-cookie": "^4.1.1",
|
"react-cookie": "^4.1.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-i18next": "^11.15.3",
|
"react-i18next": "^11.15.3",
|
||||||
|
"react-scroll": "^1.8.5",
|
||||||
"sass": "^1.49.0",
|
"sass": "^1.49.0",
|
||||||
"valtio": "^1.3.0"
|
"valtio": "^1.3.0"
|
||||||
},
|
},
|
||||||
|
|
@ -33,6 +34,7 @@
|
||||||
"@types/node": "17.0.11",
|
"@types/node": "17.0.11",
|
||||||
"@types/react": "17.0.38",
|
"@types/react": "17.0.38",
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^17.0.11",
|
||||||
|
"@types/react-scroll": "^1.8.3",
|
||||||
"eslint": "8.7.0",
|
"eslint": "8.7.0",
|
||||||
"eslint-config-next": "12.0.8",
|
"eslint-config-next": "12.0.8",
|
||||||
"eslint-plugin-valtio": "^0.4.1",
|
"eslint-plugin-valtio": "^0.4.1",
|
||||||
|
|
@ -3093,6 +3095,15 @@
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-scroll": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-scroll/-/react-scroll-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-Xt0+Y58pwrIv+vRFxcyKDoo0gBWBR2eNMJ4XRMhQpZdGUtmjnszPi/wFEJSAY+5r83ypJsSA+hOpSc3hRpYlWw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/scheduler": {
|
"node_modules/@types/scheduler": {
|
||||||
"version": "0.16.2",
|
"version": "0.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||||
|
|
@ -5330,6 +5341,11 @@
|
||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.throttle": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||||
|
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
||||||
|
},
|
||||||
"node_modules/loose-envify": {
|
"node_modules/loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
|
@ -5792,7 +5808,6 @@
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
|
|
@ -5802,8 +5817,7 @@
|
||||||
"node_modules/prop-types/node_modules/react-is": {
|
"node_modules/prop-types/node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/proxy-compare": {
|
"node_modules/proxy-compare": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
|
|
@ -5957,6 +5971,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-scroll": {
|
||||||
|
"version": "1.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-scroll/-/react-scroll-1.8.5.tgz",
|
||||||
|
"integrity": "sha512-VcYFWDV2yGeuqeVCt3vxWTGWT4yCcefXOgvNZ16hSD0QTFzNNWiyZKWAVEgmz22PTKJlwRkspALaFI5+cr73OQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash.throttle": "^4.1.1",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^15.5.4 || ^16.0.0 || ^17.0.0",
|
||||||
|
"react-dom": "^15.5.4 || ^16.0.0 || ^17.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-style-singleton": {
|
"node_modules/react-style-singleton": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.1.1.tgz",
|
||||||
|
|
@ -8943,6 +8970,15 @@
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-scroll": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-scroll/-/react-scroll-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-Xt0+Y58pwrIv+vRFxcyKDoo0gBWBR2eNMJ4XRMhQpZdGUtmjnszPi/wFEJSAY+5r83ypJsSA+hOpSc3hRpYlWw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/scheduler": {
|
"@types/scheduler": {
|
||||||
"version": "0.16.2",
|
"version": "0.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||||
|
|
@ -10594,6 +10630,11 @@
|
||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"lodash.throttle": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||||
|
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
||||||
|
},
|
||||||
"loose-envify": {
|
"loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
|
@ -10918,7 +10959,6 @@
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
|
|
@ -10928,8 +10968,7 @@
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -11020,6 +11059,15 @@
|
||||||
"tslib": "^1.0.0"
|
"tslib": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-scroll": {
|
||||||
|
"version": "1.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-scroll/-/react-scroll-1.8.5.tgz",
|
||||||
|
"integrity": "sha512-VcYFWDV2yGeuqeVCt3vxWTGWT4yCcefXOgvNZ16hSD0QTFzNNWiyZKWAVEgmz22PTKJlwRkspALaFI5+cr73OQ==",
|
||||||
|
"requires": {
|
||||||
|
"lodash.throttle": "^4.1.1",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-style-singleton": {
|
"react-style-singleton": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.1.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
"react-cookie": "^4.1.1",
|
"react-cookie": "^4.1.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-i18next": "^11.15.3",
|
"react-i18next": "^11.15.3",
|
||||||
|
"react-scroll": "^1.8.5",
|
||||||
"sass": "^1.49.0",
|
"sass": "^1.49.0",
|
||||||
"valtio": "^1.3.0"
|
"valtio": "^1.3.0"
|
||||||
},
|
},
|
||||||
|
|
@ -38,6 +39,7 @@
|
||||||
"@types/node": "17.0.11",
|
"@types/node": "17.0.11",
|
||||||
"@types/react": "17.0.38",
|
"@types/react": "17.0.38",
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^17.0.11",
|
||||||
|
"@types/react-scroll": "^1.8.3",
|
||||||
"eslint": "8.7.0",
|
"eslint": "8.7.0",
|
||||||
"eslint-config-next": "12.0.8",
|
"eslint-config-next": "12.0.8",
|
||||||
"eslint-plugin-valtio": "^0.4.1",
|
"eslint-plugin-valtio": "^0.4.1",
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,9 @@ import React from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
import Party from '~components/Party'
|
import Party from '~components/Party'
|
||||||
import * as AlertDialog from '@radix-ui/react-alert-dialog'
|
|
||||||
|
|
||||||
const PartyRoute: React.FC = () => {
|
const PartyRoute: React.FC = () => {
|
||||||
const router = useRouter()
|
const { party: slug } = useRouter().query
|
||||||
const { party: slug } = router.query
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="Content">
|
<div id="Content">
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 14 14" fill="#444" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.3121 4.60937C2.09636 4.43701 1.78173 4.47219 1.60937 4.68793C1.43701 4.90368 1.47219 5.2183 1.68793 5.39066L6.68107 9.37966C6.75234 9.4366 6.8344 9.47089 6.91856 9.48351C7.05774 9.51055 7.20746 9.47854 7.32678 9.38296L12.311 5.39025C12.5265 5.21761 12.5613 4.90294 12.3886 4.68742C12.216 4.4719 11.9013 4.43714 11.6858 4.60979L7.00557 8.35897L2.3121 4.60937Z" >
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.3121 4.60937C2.09636 4.43701 1.78173 4.47219 1.60937 4.68793C1.43701 4.90368 1.47219 5.2183 1.68793 5.39066L6.68107 9.37966C6.75234 9.4366 6.8344 9.47089 6.91856 9.48351C7.05774 9.51055 7.20746 9.47854 7.32678 9.38296L12.311 5.39025C12.5265 5.21761 12.5613 4.90294 12.3886 4.68742C12.216 4.4719 11.9013 4.43714 11.6858 4.60979L7.00557 8.35897L2.3121 4.60937Z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 495 B |
10
types/Raid.d.ts
vendored
Normal file
10
types/Raid.d.ts
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
interface Raid {
|
||||||
|
id: string
|
||||||
|
name: {
|
||||||
|
en: string
|
||||||
|
jp: string
|
||||||
|
}
|
||||||
|
level: number
|
||||||
|
group: number
|
||||||
|
element: TeamElement
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ interface Entity {
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type CollectionEndpoint = ({ query }: { query: AxiosRequestConfig }) => Promise<AxiosResponse<any>>
|
type CollectionEndpoint = (headers?: {}) => Promise<AxiosResponse<any>>
|
||||||
type IdEndpoint = ({ id }: { id: string }) => Promise<AxiosResponse<any>>
|
type IdEndpoint = ({ id }: { id: string }) => Promise<AxiosResponse<any>>
|
||||||
type IdWithObjectEndpoint = ({ id, object }: { id: string, object: string }) => Promise<AxiosResponse<any>>
|
type IdWithObjectEndpoint = ({ id, object }: { id: string, object: string }) => Promise<AxiosResponse<any>>
|
||||||
type PostEndpoint = (object: {}, headers?: {}) => Promise<AxiosResponse<any>>
|
type PostEndpoint = (object: {}, headers?: {}) => Promise<AxiosResponse<any>>
|
||||||
|
|
@ -41,7 +41,7 @@ class Api {
|
||||||
const resourceUrl = `${this.url}/${name}`
|
const resourceUrl = `${this.url}/${name}`
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getAll: ({ query }: { query: AxiosRequestConfig }) => axios.get(resourceUrl, { params: { query }}),
|
getAll: (headers?: {}) => axios.get(resourceUrl, headers),
|
||||||
getOne: ({ id }: { id: string }) => axios.get(`${resourceUrl}/${id}/`),
|
getOne: ({ id }: { id: string }) => axios.get(`${resourceUrl}/${id}/`),
|
||||||
getOneWithObject: ({ id, object }: { id: string, object: string }) => axios.get(`${resourceUrl}/${id}/${object}`),
|
getOneWithObject: ({ id, object }: { id: string, object: string }) => axios.get(`${resourceUrl}/${id}/${object}`),
|
||||||
create: (object: {}, headers?: {}) => axios.post(resourceUrl, object, headers),
|
create: (object: {}, headers?: {}) => axios.post(resourceUrl, object, headers),
|
||||||
|
|
@ -88,5 +88,6 @@ api.createEntity( { name: 'parties' })
|
||||||
api.createEntity( { name: 'characters' })
|
api.createEntity( { name: 'characters' })
|
||||||
api.createEntity( { name: 'weapons' })
|
api.createEntity( { name: 'weapons' })
|
||||||
api.createEntity( { name: 'summons' })
|
api.createEntity( { name: 'summons' })
|
||||||
|
api.createEntity( { name: 'raids' })
|
||||||
|
|
||||||
export default api
|
export default api
|
||||||
|
|
@ -6,6 +6,10 @@ interface AppState {
|
||||||
party: {
|
party: {
|
||||||
id: string | undefined,
|
id: string | undefined,
|
||||||
editable: boolean,
|
editable: boolean,
|
||||||
|
detailsVisible: boolean,
|
||||||
|
name: string | undefined,
|
||||||
|
description: string | undefined,
|
||||||
|
raid: Raid | undefined,
|
||||||
element: number,
|
element: number,
|
||||||
extra: boolean
|
extra: boolean
|
||||||
},
|
},
|
||||||
|
|
@ -23,13 +27,18 @@ interface AppState {
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
sourceItem: GridCharacter | GridWeapon | GridSummon | undefined
|
sourceItem: GridCharacter | GridWeapon | GridSummon | undefined
|
||||||
}
|
},
|
||||||
|
raids: Raid[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialAppState: AppState = {
|
export const initialAppState: AppState = {
|
||||||
party: {
|
party: {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
editable: false,
|
editable: false,
|
||||||
|
detailsVisible: false,
|
||||||
|
name: undefined,
|
||||||
|
description: undefined,
|
||||||
|
raid: undefined,
|
||||||
element: 0,
|
element: 0,
|
||||||
extra: false
|
extra: false
|
||||||
},
|
},
|
||||||
|
|
@ -47,7 +56,8 @@ export const initialAppState: AppState = {
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
sourceItem: undefined
|
sourceItem: undefined
|
||||||
}
|
},
|
||||||
|
raids: []
|
||||||
}
|
}
|
||||||
|
|
||||||
export const appState = proxy(initialAppState)
|
export const appState = proxy(initialAppState)
|
||||||
Loading…
Reference in a new issue