Update extra weapons section
* ExtraContainer split into ExtraContainerItem * Updated Guidebook result item, grid and unit * Updated extra weapons grid and weapon grid
This commit is contained in:
parent
c0392a1bab
commit
877cb4491e
13 changed files with 161 additions and 136 deletions
|
|
@ -1,50 +1,18 @@
|
||||||
.ExtraContainer {
|
.container {
|
||||||
background: var(--extra-purple-bg);
|
background: var(--extra-purple-bg);
|
||||||
border-radius: $card-corner;
|
border-radius: $card-corner;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin: $unit-4x auto 0;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: relative;
|
max-width: calc($grid-width + $unit-2x);
|
||||||
left: $unit;
|
|
||||||
margin: 20px auto;
|
|
||||||
max-width: calc($grid-width + 20px);
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
// gap: $unit;
|
||||||
|
|
||||||
.ContainerItem {
|
& > * {
|
||||||
display: grid;
|
border-bottom: 2px solid var(--background);
|
||||||
grid-template-columns: 1.19fr 3fr;
|
|
||||||
gap: $unit-2x;
|
|
||||||
padding: $unit-2x $unit-2x $unit-2x;
|
|
||||||
|
|
||||||
&.Disabled {
|
&:last-child {
|
||||||
grid-template-columns: 1fr;
|
border-bottom: none;
|
||||||
|
|
||||||
.Header {
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Header {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: $unit;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: $unit-4x;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
& > h3 {
|
|
||||||
color: var(--extra-purple-text);
|
|
||||||
font-size: $font-small;
|
|
||||||
font-weight: $medium;
|
|
||||||
line-height: 1.2;
|
|
||||||
font-weight: 500;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:first-child) {
|
|
||||||
border-top: 1px solid var(--extra-purple-card-bg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
import React, { PropsWithChildren } from 'react'
|
import React, { PropsWithChildren } from 'react'
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
|
|
||||||
// Props
|
|
||||||
interface Props {}
|
interface Props {}
|
||||||
|
|
||||||
const ExtraContainer = ({ children, ...props }: PropsWithChildren<Props>) => {
|
const ExtraContainer = (props: PropsWithChildren<Props>) => {
|
||||||
return <div className="ExtraContainer">{children}</div>
|
return <section className={styles.container}>{props.children}</section>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ExtraContainer
|
export default ExtraContainer
|
||||||
|
|
|
||||||
47
components/extra/ExtraContainerItem/index.module.scss
Normal file
47
components/extra/ExtraContainerItem/index.module.scss
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: $unit;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: $unit-4x;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
& > h3 {
|
||||||
|
color: var(--extra-purple-text);
|
||||||
|
font-size: $font-small;
|
||||||
|
font-weight: $medium;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.19fr 3fr;
|
||||||
|
gap: $unit-2x;
|
||||||
|
padding: $unit-2x $unit-2x $unit-2x;
|
||||||
|
|
||||||
|
@include breakpoint(phone) {
|
||||||
|
grid-template-columns: auto;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Disabled {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
|
.Header {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
border-top: 1px solid var(--extra-purple-card-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
components/extra/ExtraContainerItem/index.tsx
Normal file
35
components/extra/ExtraContainerItem/index.tsx
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React, { PropsWithChildren } from 'react'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import styles from './index.module.scss'
|
||||||
|
|
||||||
|
// Props
|
||||||
|
interface Props {
|
||||||
|
title: string
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const ExtraContainerItem = ({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: PropsWithChildren<Props>) => {
|
||||||
|
const classes = classNames(
|
||||||
|
{
|
||||||
|
[styles.item]: true,
|
||||||
|
},
|
||||||
|
props.className?.split(' ').map((c) => styles[c])
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<header className={styles.header}>
|
||||||
|
<h3>{title}</h3>
|
||||||
|
</header>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ExtraContainerItem
|
||||||
|
|
@ -1,26 +1,14 @@
|
||||||
.ExtraWeapons {
|
.grid {
|
||||||
#ExtraWeaponGrid {
|
display: grid;
|
||||||
display: grid;
|
gap: $unit-3x;
|
||||||
gap: $unit-3x;
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
||||||
|
|
||||||
@include breakpoint(tablet) {
|
@include breakpoint(tablet) {
|
||||||
gap: $unit-2x;
|
gap: $unit-2x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include breakpoint(phone) {
|
@include breakpoint(phone) {
|
||||||
gap: $unit;
|
gap: $unit;
|
||||||
}
|
|
||||||
|
|
||||||
.WeaponUnit {
|
|
||||||
.WeaponImage {
|
|
||||||
background: var(--extra-purple-card-bg);
|
|
||||||
|
|
||||||
.icon svg {
|
|
||||||
fill: var(--extra-purple-secondary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ExtraGrid.Weapons {
|
.ExtraGrid.Weapons {
|
||||||
|
|
|
||||||
|
|
@ -30,18 +30,11 @@ const ExtraWeaponsGrid = ({
|
||||||
updateObject,
|
updateObject,
|
||||||
updateUncap,
|
updateUncap,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { t } = useTranslation('common')
|
return (
|
||||||
|
<ul className={styles.grid}>
|
||||||
const classes = classNames({
|
|
||||||
ExtraWeapons: true,
|
|
||||||
ContainerItem: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
const extraWeapons = (
|
|
||||||
<ul id="ExtraWeaponGrid">
|
|
||||||
{Array.from(Array(EXTRA_WEAPONS_COUNT)).map((x, i) => {
|
{Array.from(Array(EXTRA_WEAPONS_COUNT)).map((x, i) => {
|
||||||
const itemClasses = classNames({
|
const itemClasses = classNames({
|
||||||
Empty: grid[offset + i] === undefined,
|
[styles.empty]: grid[offset + i] === undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -60,15 +53,6 @@ const ExtraWeaponsGrid = ({
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classes}>
|
|
||||||
<div className="Header">
|
|
||||||
<h3>{t('extra_weapons')}</h3>
|
|
||||||
</div>
|
|
||||||
{extraWeapons}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ExtraWeaponsGrid
|
export default ExtraWeaponsGrid
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
.GuidebookResult {
|
.result {
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: $unit;
|
gap: $unit;
|
||||||
padding: $unit * 1.5;
|
padding: $unit * 1.5;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--button-contained-bg);
|
background: var(--button-contained-bg);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.Info h5 {
|
.info h5 {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +22,7 @@
|
||||||
width: 90px;
|
width: 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Info {
|
.info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ const GuidebookResult = (props: Props) => {
|
||||||
const guidebook = props.data
|
const guidebook = props.data
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="GuidebookResult" onClick={props.onClick}>
|
<li className={styles.result} onClick={props.onClick}>
|
||||||
<img
|
<img
|
||||||
alt={guidebook.name[locale]}
|
alt={guidebook.name[locale]}
|
||||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/guidebooks/book_${guidebook.granblue_id}.png`}
|
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/guidebooks/book_${guidebook.granblue_id}.png`}
|
||||||
/>
|
/>
|
||||||
<div className="Info">
|
<div className={styles.info}>
|
||||||
<h5>{guidebook.name[locale]}</h5>
|
<h5>{guidebook.name[locale]}</h5>
|
||||||
<p>{guidebook.description[locale]}</p>
|
<p>{guidebook.description[locale]}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.GuidebookUnit {
|
.unit {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.editable .GuidebookImage:hover {
|
&.editable .guidebookImage:hover {
|
||||||
border: $hover-stroke;
|
border: $hover-stroke;
|
||||||
box-shadow: $hover-shadow;
|
box-shadow: $hover-shadow;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.GuidebookImage {
|
.guidebookImage {
|
||||||
background: var(--extra-purple-card-bg);
|
background: var(--extra-purple-card-bg);
|
||||||
border: 1px solid rgba(0, 0, 0, 0);
|
border: 1px solid rgba(0, 0, 0, 0);
|
||||||
border-radius: $unit;
|
border-radius: $unit;
|
||||||
|
|
@ -74,7 +74,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
&.Placeholder {
|
&.placeholder {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.GuidebookName {
|
.name {
|
||||||
font-size: $font-name;
|
font-size: $font-name;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.GuidebookDescription {
|
.guidebookDescription {
|
||||||
font-size: $font-small;
|
font-size: $font-small;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,11 @@ const GuidebookUnit = ({
|
||||||
|
|
||||||
// Classes
|
// Classes
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
GuidebookUnit: true,
|
unit: true,
|
||||||
editable: editable,
|
[styles.unit]: true,
|
||||||
filled: guidebook !== undefined,
|
[styles.editable]: editable,
|
||||||
empty: guidebook == undefined,
|
[styles.filled]: guidebook !== undefined,
|
||||||
|
[styles.empty]: guidebook == undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonClasses = classNames({
|
const buttonClasses = classNames({
|
||||||
|
|
@ -114,8 +115,10 @@ const GuidebookUnit = ({
|
||||||
<ContextMenu onOpenChange={handleContextMenuOpenChange}>
|
<ContextMenu onOpenChange={handleContextMenuOpenChange}>
|
||||||
<ContextMenuTrigger asChild>
|
<ContextMenuTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
|
active={contextMenuOpen}
|
||||||
|
floating={true}
|
||||||
leftAccessoryIcon={<SettingsIcon />}
|
leftAccessoryIcon={<SettingsIcon />}
|
||||||
className={buttonClasses}
|
className="options"
|
||||||
onClick={handleButtonClicked}
|
onClick={handleButtonClicked}
|
||||||
/>
|
/>
|
||||||
</ContextMenuTrigger>
|
</ContextMenuTrigger>
|
||||||
|
|
@ -165,17 +168,17 @@ const GuidebookUnit = ({
|
||||||
|
|
||||||
// Methods: Core element rendering
|
// Methods: Core element rendering
|
||||||
const imageElement = (
|
const imageElement = (
|
||||||
<div className="GuidebookImage" onClick={openSearchModal}>
|
<div className={styles.guidebookImage} onClick={openSearchModal}>
|
||||||
<img
|
<img
|
||||||
alt={guidebook?.name[locale]}
|
alt={guidebook?.name[locale]}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
GridImage: true,
|
[styles.image]: true,
|
||||||
Placeholder: imageUrl === '',
|
[styles.placeholder]: imageUrl === '',
|
||||||
})}
|
})}
|
||||||
src={imageUrl !== '' ? imageUrl : placeholderImageUrl}
|
src={imageUrl !== '' ? imageUrl : placeholderImageUrl}
|
||||||
/>
|
/>
|
||||||
{editable ? (
|
{editable ? (
|
||||||
<span className="icon">
|
<span className={styles.icon}>
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -189,7 +192,7 @@ const GuidebookUnit = ({
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
{contextMenu()}
|
{contextMenu()}
|
||||||
{imageElement}
|
{imageElement}
|
||||||
<h3 className="GuidebookName">{guidebook?.name[locale]}</h3>
|
<h3 className={styles.name}>{guidebook?.name[locale]}</h3>
|
||||||
</div>
|
</div>
|
||||||
{searchModal()}
|
{searchModal()}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
.Guidebooks {
|
.guidebooks {
|
||||||
#GuidebooksGrid {
|
.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: $unit-3x;
|
gap: $unit-3x;
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import Switch from '~components/common/Switch'
|
|
||||||
import GuidebookUnit from '../GuidebookUnit'
|
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import GuidebookUnit from '../GuidebookUnit'
|
||||||
|
|
||||||
import type { SearchableObject } from '~types'
|
import type { SearchableObject } from '~types'
|
||||||
|
|
||||||
|
|
@ -28,12 +27,12 @@ const GuidebooksGrid = ({
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
Guidebooks: true,
|
[styles.guidebooks]: true,
|
||||||
ContainerItem: true,
|
[styles.containerItem]: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const guidebooks = (
|
const guidebooks = (
|
||||||
<ul id="GuidebooksGrid">
|
<ul className={styles.grid}>
|
||||||
{Array.from(Array(EXTRA_WEAPONS_COUNT)).map((x, i) => {
|
{Array.from(Array(EXTRA_WEAPONS_COUNT)).map((x, i) => {
|
||||||
const itemClasses = classNames({
|
const itemClasses = classNames({
|
||||||
Empty: grid && grid[i] === undefined,
|
Empty: grid && grid[i] === undefined,
|
||||||
|
|
@ -54,14 +53,7 @@ const GuidebooksGrid = ({
|
||||||
</ul>
|
</ul>
|
||||||
)
|
)
|
||||||
|
|
||||||
const guidebookElement = (
|
const guidebookElement = <div className={classes}>{guidebooks}</div>
|
||||||
<div className={classes}>
|
|
||||||
<div className="Header">
|
|
||||||
<h3>{t('sephira_guidebooks')}</h3>
|
|
||||||
</div>
|
|
||||||
{guidebooks}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
return guidebookElement
|
return guidebookElement
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import Alert from '~components/common/Alert'
|
||||||
import WeaponUnit from '~components/weapon/WeaponUnit'
|
import WeaponUnit from '~components/weapon/WeaponUnit'
|
||||||
import ExtraWeaponsGrid from '~components/extra/ExtraWeaponsGrid'
|
import ExtraWeaponsGrid from '~components/extra/ExtraWeaponsGrid'
|
||||||
import ExtraContainer from '~components/extra/ExtraContainer'
|
import ExtraContainer from '~components/extra/ExtraContainer'
|
||||||
|
import ExtraContainerItem from '~components/extra/ExtraContainerItem'
|
||||||
import GuidebooksGrid from '~components/extra/GuidebooksGrid'
|
import GuidebooksGrid from '~components/extra/GuidebooksGrid'
|
||||||
import WeaponConflictModal from '~components/weapon/WeaponConflictModal'
|
import WeaponConflictModal from '~components/weapon/WeaponConflictModal'
|
||||||
|
|
||||||
|
|
@ -379,23 +380,30 @@ const WeaponGrid = (props: Props) => {
|
||||||
if (appState.party.raid && appState.party.raid.group.extra) {
|
if (appState.party.raid && appState.party.raid.group.extra) {
|
||||||
return (
|
return (
|
||||||
<ExtraContainer>
|
<ExtraContainer>
|
||||||
{appState.party.raid && appState.party.raid.group.extra && (
|
<ExtraContainerItem title={t('extra_weapons')} className="weapons">
|
||||||
<ExtraWeaponsGrid
|
{appState.party.raid && appState.party.raid.group.extra && (
|
||||||
grid={appState.grid.weapons.allWeapons}
|
<ExtraWeaponsGrid
|
||||||
editable={props.editable}
|
grid={appState.grid.weapons.allWeapons}
|
||||||
offset={numWeapons}
|
editable={props.editable}
|
||||||
removeWeapon={removeWeapon}
|
offset={numWeapons}
|
||||||
updateObject={receiveWeaponFromSearch}
|
removeWeapon={removeWeapon}
|
||||||
updateUncap={initiateUncapUpdate}
|
updateObject={receiveWeaponFromSearch}
|
||||||
/>
|
updateUncap={initiateUncapUpdate}
|
||||||
)}
|
/>
|
||||||
|
)}
|
||||||
|
</ExtraContainerItem>
|
||||||
{appState.party.raid && appState.party.raid.group.guidebooks && (
|
{appState.party.raid && appState.party.raid.group.guidebooks && (
|
||||||
<GuidebooksGrid
|
<ExtraContainerItem
|
||||||
grid={appState.party.guidebooks}
|
title={t('sephira_guidebooks')}
|
||||||
editable={props.editable}
|
className="guidebooks"
|
||||||
removeGuidebook={removeGuidebook}
|
>
|
||||||
updateObject={receiveGuidebookFromSearch}
|
<GuidebooksGrid
|
||||||
/>
|
grid={appState.party.guidebooks}
|
||||||
|
editable={props.editable}
|
||||||
|
removeGuidebook={removeGuidebook}
|
||||||
|
updateObject={receiveGuidebookFromSearch}
|
||||||
|
/>
|
||||||
|
</ExtraContainerItem>
|
||||||
)}
|
)}
|
||||||
</ExtraContainer>
|
</ExtraContainer>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue