Update party footer
* Add segmented control to swap between remixes and description * Fix styles
This commit is contained in:
parent
05af1ac6aa
commit
5caca71931
4 changed files with 88 additions and 164 deletions
|
|
@ -1,4 +1,4 @@
|
|||
.FooterWrapper {
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit-2x;
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
max-width: $grid-width;
|
||||
|
||||
@include breakpoint(phone) {
|
||||
.Button:not(.IconButton) {
|
||||
.Button:not(.icon) {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
|
|
@ -16,7 +16,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
.PartyFooter {
|
||||
.description,
|
||||
.remixes {
|
||||
box-sizing: border-box;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
|
|
@ -30,150 +31,20 @@
|
|||
@include breakpoint(phone) {
|
||||
padding: 0 $unit;
|
||||
}
|
||||
&.Editable {
|
||||
gap: $unit;
|
||||
|
||||
&.Visible {
|
||||
display: grid;
|
||||
.noRemixes {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit-2x;
|
||||
margin: 0 auto;
|
||||
padding: $unit-4x 0;
|
||||
|
||||
h3 {
|
||||
font-size: $font-small;
|
||||
font-weight: $medium;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
textarea {
|
||||
min-height: $unit * 22;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.SelectTrigger {
|
||||
padding: $unit-2x;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.DetailToggleGroup {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: $unit;
|
||||
|
||||
@include breakpoint(phone) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.ToggleSection,
|
||||
.InputSection {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
background: var(--card-bg);
|
||||
border-radius: $input-corner;
|
||||
|
||||
& > label {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-size: $font-regular;
|
||||
gap: $unit;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
& > span {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ToggleSection {
|
||||
padding: ($unit * 1.5) $unit-2x;
|
||||
}
|
||||
|
||||
.InputSection {
|
||||
padding: $unit-half $unit-2x;
|
||||
padding-right: $unit-half;
|
||||
|
||||
.Input {
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
div.Input {
|
||||
align-items: center;
|
||||
border: 2px solid transparent;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
padding: $unit;
|
||||
|
||||
&:has(> input:focus) {
|
||||
border: 2px solid $blue;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
& > input {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: $unit 0;
|
||||
text-align: right;
|
||||
width: 2rem;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
span {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.Input {
|
||||
border-radius: 7px;
|
||||
max-width: 10rem;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: $unit-half;
|
||||
justify-content: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: $unit;
|
||||
|
||||
@include breakpoint(phone) {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.left {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: $unit;
|
||||
|
||||
@include breakpoint(phone) {
|
||||
.Button {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.Visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
|
|
|
|||
|
|
@ -2,13 +2,16 @@ 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 clonedeep from 'lodash.clonedeep'
|
||||
|
||||
import Linkify from 'react-linkify'
|
||||
import LiteYouTubeEmbed from 'react-lite-youtube-embed'
|
||||
import classNames from 'classnames'
|
||||
import reactStringReplace from 'react-string-replace'
|
||||
|
||||
import Button from '~components/common/Button'
|
||||
import SegmentedControl from '~components/common/SegmentedControl'
|
||||
import Segment from '~components/common/Segment'
|
||||
import GridRepCollection from '~components/GridRepCollection'
|
||||
import GridRep from '~components/GridRep'
|
||||
|
||||
|
|
@ -18,6 +21,7 @@ import { youtube } from '~utils/youtube'
|
|||
|
||||
import type { DetailsObject } from 'types'
|
||||
|
||||
import RemixIcon from '~public/icons/Remix.svg'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
// Props
|
||||
|
|
@ -38,6 +42,7 @@ const PartyFooter = (props: Props) => {
|
|||
/(?:https:\/\/www\.youtube\.com\/watch\?v=|https:\/\/youtu\.be\/)([\w-]+)/g
|
||||
|
||||
const [open, setOpen] = useState(false)
|
||||
const [currentSegment, setCurrentSegment] = useState(0)
|
||||
|
||||
const [remixes, setRemixes] = useState<Party[]>([])
|
||||
const [embeddedDescription, setEmbeddedDescription] =
|
||||
|
|
@ -147,6 +152,47 @@ const PartyFooter = (props: Props) => {
|
|||
})
|
||||
}
|
||||
|
||||
const segmentedControl = (
|
||||
<SegmentedControl className="background">
|
||||
<Segment
|
||||
name="description"
|
||||
groupName="footer"
|
||||
selected={currentSegment === 0}
|
||||
onClick={() => setCurrentSegment(0)}
|
||||
>
|
||||
{t('footer.description.label')}
|
||||
</Segment>
|
||||
<Segment
|
||||
name="remixes"
|
||||
groupName="footer"
|
||||
selected={currentSegment === 1}
|
||||
onClick={() => setCurrentSegment(1)}
|
||||
>
|
||||
{t('footer.remixes.label')}
|
||||
</Segment>
|
||||
</SegmentedControl>
|
||||
)
|
||||
|
||||
const descriptionSection = (
|
||||
<section className={styles.description}>
|
||||
<Linkify>{embeddedDescription}</Linkify>
|
||||
</section>
|
||||
)
|
||||
|
||||
const remixesSection = (
|
||||
<section className={styles.remixes}>
|
||||
{party?.remixes?.length > 0 && (
|
||||
<GridRepCollection>{renderRemixes()}</GridRepCollection>
|
||||
)}
|
||||
{party?.remixes?.length === 0 && (
|
||||
<div className={styles.noRemixes}>
|
||||
<h3>{t('footer.remixes.empty')}</h3>
|
||||
<Button leftAccessoryIcon={<RemixIcon />} text={t('buttons.remix')} />
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)
|
||||
|
||||
function renderRemixes() {
|
||||
return remixes.map((party, i) => {
|
||||
return (
|
||||
|
|
@ -162,7 +208,6 @@ const PartyFooter = (props: Props) => {
|
|||
fullAuto={party.full_auto}
|
||||
autoGuard={party.auto_guard}
|
||||
key={`party-${i}`}
|
||||
displayUser={true}
|
||||
onClick={goTo}
|
||||
onSave={toggleFavorite}
|
||||
/>
|
||||
|
|
@ -170,23 +215,13 @@ const PartyFooter = (props: Props) => {
|
|||
})
|
||||
}
|
||||
|
||||
const remixSection = () => {
|
||||
return (
|
||||
<section className="Remixes">
|
||||
<h3>{t('remixes')}</h3>
|
||||
{<GridRepCollection>{renderRemixes()}</GridRepCollection>}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="FooterWrapper">
|
||||
<section className="PartyFooter">
|
||||
<Linkify>{embeddedDescription}</Linkify>
|
||||
</section>
|
||||
</section>
|
||||
{remixes && remixes.length > 0 ? remixSection() : ''}
|
||||
<div className={styles.wrapper}>
|
||||
{segmentedControl}
|
||||
{currentSegment === 0 && descriptionSection}
|
||||
{currentSegment === 1 && remixesSection}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,16 @@
|
|||
"rarity": "Rarity"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"description": {
|
||||
"label": "Description",
|
||||
"empty": "This team doesn't have a description"
|
||||
},
|
||||
"remixes": {
|
||||
"label": "Remixes",
|
||||
"empty": "No one has remixed this team yet"
|
||||
}
|
||||
},
|
||||
"header": {
|
||||
"anonymous": "Anonymous",
|
||||
"untitled_team": "Untitled team by {{username}}",
|
||||
|
|
@ -540,6 +550,5 @@
|
|||
"no_user": "Anonymous",
|
||||
"no_job": "No class",
|
||||
"no_value": "No value",
|
||||
"remixes": "Remixes",
|
||||
"level": "Level"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,16 @@
|
|||
"rarity": "レアリティ"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"description": {
|
||||
"label": "説明",
|
||||
"empty": "この編成には説明がありません"
|
||||
},
|
||||
"remixes": {
|
||||
"label": "リミックス",
|
||||
"empty": "この編成はリミックスされていません"
|
||||
}
|
||||
},
|
||||
"header": {
|
||||
"anonymous": "無名",
|
||||
"untitled_team": "{{username}}さんからの無題編成",
|
||||
|
|
@ -537,6 +547,5 @@
|
|||
"no_user": "無名",
|
||||
"no_job": "ジョブなし",
|
||||
"no_value": "値なし",
|
||||
"remixes": "リミックスされた編成",
|
||||
"level": "レベル"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue