Implement EditPartyModal
EditPartyModal takes functionality that was in PartyHeader and puts it in a modal dialog. This lets us add fields and reduces the complexity of other components. Translations were also added.
This commit is contained in:
parent
d338459cf5
commit
47a867e39a
4 changed files with 594 additions and 0 deletions
56
components/party/EditPartyModal/index.scss
Normal file
56
components/party/EditPartyModal/index.scss
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
.EditTeam.DialogContent {
|
||||||
|
min-height: 80vh;
|
||||||
|
|
||||||
|
.Container.Scrollable {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: $unit-2x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Fields {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: $unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ExtraNotice {
|
||||||
|
background: var(--extra-purple-bg);
|
||||||
|
border-radius: $input-corner;
|
||||||
|
color: var(--extra-purple-text);
|
||||||
|
font-weight: $medium;
|
||||||
|
padding: $unit-2x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DescriptionField {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: inherit;
|
||||||
|
gap: $unit;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.Left {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea.Input {
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.Image {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
476
components/party/EditPartyModal/index.tsx
Normal file
476
components/party/EditPartyModal/index.tsx
Normal file
|
|
@ -0,0 +1,476 @@
|
||||||
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogTrigger,
|
||||||
|
DialogClose,
|
||||||
|
DialogTitle,
|
||||||
|
} from '~components/common/Dialog'
|
||||||
|
import DialogContent from '~components/common/DialogContent'
|
||||||
|
import Button from '~components/common/Button'
|
||||||
|
import CharLimitedFieldset from '~components/common/CharLimitedFieldset'
|
||||||
|
import DurationInput from '~components/common/DurationInput'
|
||||||
|
import InputTableField from '~components/common/InputTableField'
|
||||||
|
import RaidCombobox from '~components/raids/RaidCombobox'
|
||||||
|
import SegmentedControl from '~components/common/SegmentedControl'
|
||||||
|
import Segment from '~components/common/Segment'
|
||||||
|
import SwitchTableField from '~components/common/SwitchTableField'
|
||||||
|
import TableField from '~components/common/TableField'
|
||||||
|
|
||||||
|
import type { DetailsObject } from 'types'
|
||||||
|
import type { DialogProps } from '@radix-ui/react-dialog'
|
||||||
|
|
||||||
|
import CheckIcon from '~public/icons/Check.svg'
|
||||||
|
import CrossIcon from '~public/icons/Cross.svg'
|
||||||
|
import './index.scss'
|
||||||
|
|
||||||
|
interface Props extends DialogProps {
|
||||||
|
party?: Party
|
||||||
|
updateCallback: (details: DetailsObject) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const EditPartyModal = ({ party, updateCallback, ...props }: Props) => {
|
||||||
|
// Set up router
|
||||||
|
const router = useRouter()
|
||||||
|
const locale = router.locale
|
||||||
|
|
||||||
|
// Set up translation
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
|
// Refs
|
||||||
|
const headerRef = React.createRef<HTMLDivElement>()
|
||||||
|
const footerRef = React.createRef<HTMLDivElement>()
|
||||||
|
const descriptionInput = useRef<HTMLTextAreaElement>(null)
|
||||||
|
|
||||||
|
// States: Component
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const [errors, setErrors] = useState<{ [key: string]: string }>({
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
})
|
||||||
|
const [currentSegment, setCurrentSegment] = useState(0)
|
||||||
|
|
||||||
|
// States: Data
|
||||||
|
const [name, setName] = useState('')
|
||||||
|
const [raid, setRaid] = useState<Raid>()
|
||||||
|
const [extra, setExtra] = useState(false)
|
||||||
|
const [chargeAttack, setChargeAttack] = useState(true)
|
||||||
|
const [fullAuto, setFullAuto] = useState(false)
|
||||||
|
const [autoGuard, setAutoGuard] = useState(false)
|
||||||
|
const [autoSummon, setAutoSummon] = useState(false)
|
||||||
|
|
||||||
|
const [buttonCount, setButtonCount] = useState<number | undefined>(undefined)
|
||||||
|
const [chainCount, setChainCount] = useState<number | undefined>(undefined)
|
||||||
|
const [turnCount, setTurnCount] = useState<number | undefined>(undefined)
|
||||||
|
const [clearTime, setClearTime] = useState(0)
|
||||||
|
|
||||||
|
// Hooks
|
||||||
|
useEffect(() => {
|
||||||
|
if (!party) return
|
||||||
|
|
||||||
|
setName(party.name)
|
||||||
|
setRaid(party.raid)
|
||||||
|
setAutoGuard(party.auto_guard)
|
||||||
|
setAutoSummon(party.auto_summon)
|
||||||
|
setFullAuto(party.full_auto)
|
||||||
|
setChargeAttack(party.charge_attack)
|
||||||
|
setClearTime(party.clear_time)
|
||||||
|
if (party.turn_count) setTurnCount(party.turn_count)
|
||||||
|
if (party.button_count) setButtonCount(party.button_count)
|
||||||
|
if (party.chain_count) setChainCount(party.chain_count)
|
||||||
|
}, [party])
|
||||||
|
|
||||||
|
// Methods: Event handlers (Dialog)
|
||||||
|
function openChange() {
|
||||||
|
if (open) {
|
||||||
|
setOpen(false)
|
||||||
|
if (props.onOpenChange) props.onOpenChange(false)
|
||||||
|
} else {
|
||||||
|
setOpen(true)
|
||||||
|
if (props.onOpenChange) props.onOpenChange(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEscapeKeyDown(event: KeyboardEvent) {
|
||||||
|
event.preventDefault()
|
||||||
|
openChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOpenAutoFocus(event: Event) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Event handlers (Fields)
|
||||||
|
function handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
const { name, value } = event.target
|
||||||
|
setName(value)
|
||||||
|
|
||||||
|
let newErrors = errors
|
||||||
|
setErrors(newErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChargeAttackChanged(checked: boolean) {
|
||||||
|
setChargeAttack(checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFullAutoChanged(checked: boolean) {
|
||||||
|
setFullAuto(checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAutoGuardChanged(checked: boolean) {
|
||||||
|
setAutoGuard(checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAutoSummonChanged(checked: boolean) {
|
||||||
|
setAutoSummon(checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleExtraChanged(checked: boolean) {
|
||||||
|
setExtra(checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClearTimeChanged(value: number) {
|
||||||
|
if (!isNaN(value)) setClearTime(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTurnCountChanged(value?: string) {
|
||||||
|
if (!value) return
|
||||||
|
const numericalValue = parseInt(value)
|
||||||
|
if (!isNaN(numericalValue)) setTurnCount(numericalValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleButtonCountChanged(value?: string) {
|
||||||
|
if (!value) return
|
||||||
|
const numericalValue = parseInt(value)
|
||||||
|
if (!isNaN(numericalValue)) setButtonCount(numericalValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChainCountChanged(value?: string) {
|
||||||
|
if (!value) return
|
||||||
|
const numericalValue = parseInt(value)
|
||||||
|
if (!isNaN(numericalValue)) setChainCount(numericalValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTextAreaChanged(
|
||||||
|
event: React.ChangeEvent<HTMLTextAreaElement>
|
||||||
|
) {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
const { name, value } = event.target
|
||||||
|
let newErrors = errors
|
||||||
|
|
||||||
|
setErrors(newErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
function receiveRaid(raid?: Raid) {
|
||||||
|
if (raid) {
|
||||||
|
setRaid(raid)
|
||||||
|
|
||||||
|
if (raid.group.extra) setExtra(true)
|
||||||
|
else setExtra(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Data methods
|
||||||
|
function updateDetails(event: React.MouseEvent) {
|
||||||
|
const descriptionValue = descriptionInput.current?.value
|
||||||
|
const details: DetailsObject = {
|
||||||
|
fullAuto: fullAuto,
|
||||||
|
autoGuard: autoGuard,
|
||||||
|
autoSummon: autoSummon,
|
||||||
|
chargeAttack: chargeAttack,
|
||||||
|
clearTime: clearTime,
|
||||||
|
buttonCount: buttonCount,
|
||||||
|
turnCount: turnCount,
|
||||||
|
chainCount: chainCount,
|
||||||
|
name: name,
|
||||||
|
description: descriptionValue,
|
||||||
|
raid: raid,
|
||||||
|
extra: extra,
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCallback(details)
|
||||||
|
openChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Rendering methods
|
||||||
|
const segmentedControl = () => {
|
||||||
|
return (
|
||||||
|
<SegmentedControl blended={true}>
|
||||||
|
<Segment
|
||||||
|
groupName="edit_nav"
|
||||||
|
name="core"
|
||||||
|
selected={currentSegment === 0}
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => setCurrentSegment(0)}
|
||||||
|
>
|
||||||
|
{t('modals.edit_team.segments.basic_info')}
|
||||||
|
</Segment>
|
||||||
|
<Segment
|
||||||
|
groupName="edit_nav"
|
||||||
|
name="properties"
|
||||||
|
selected={currentSegment === 1}
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => setCurrentSegment(1)}
|
||||||
|
>
|
||||||
|
{t('modals.edit_team.segments.properties')}
|
||||||
|
</Segment>
|
||||||
|
</SegmentedControl>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const nameField = () => {
|
||||||
|
return (
|
||||||
|
<CharLimitedFieldset
|
||||||
|
className="Bound"
|
||||||
|
fieldName="name"
|
||||||
|
placeholder="Name your team"
|
||||||
|
value={name}
|
||||||
|
limit={50}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
error={errors.name}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const raidField = () => {
|
||||||
|
return (
|
||||||
|
<RaidCombobox
|
||||||
|
showAllRaidsOption={false}
|
||||||
|
currentRaid={raid}
|
||||||
|
onChange={receiveRaid}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const extraNotice = () => {
|
||||||
|
if (extra) {
|
||||||
|
return (
|
||||||
|
<div className="ExtraNotice">
|
||||||
|
<span className="ExtraNoticeText">
|
||||||
|
{raid && raid.group.guidebooks
|
||||||
|
? t('modals.edit_team.extra_notice_guidebooks')
|
||||||
|
: t('modals.edit_team.extra_notice')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const descriptionField = () => {
|
||||||
|
return (
|
||||||
|
<div className="DescriptionField">
|
||||||
|
<textarea
|
||||||
|
className="Input Bound"
|
||||||
|
name="description"
|
||||||
|
placeholder={
|
||||||
|
'Write your notes here\n\n\nWatch out for the 50% trigger!\nMake sure to click Fediel’s 3 first\nGood luck with RNG!'
|
||||||
|
}
|
||||||
|
value={party?.description}
|
||||||
|
onChange={handleTextAreaChanged}
|
||||||
|
ref={descriptionInput}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const chargeAttackField = () => {
|
||||||
|
return (
|
||||||
|
<SwitchTableField
|
||||||
|
name="charge_attack"
|
||||||
|
label={t('modals.edit_team.labels.charge_attack')}
|
||||||
|
value={chargeAttack}
|
||||||
|
onValueChange={handleChargeAttackChanged}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullAutoField = () => {
|
||||||
|
return (
|
||||||
|
<SwitchTableField
|
||||||
|
name="full_auto"
|
||||||
|
label={t('modals.edit_team.labels.full_auto')}
|
||||||
|
value={fullAuto}
|
||||||
|
onValueChange={handleFullAutoChanged}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const autoGuardField = () => {
|
||||||
|
return (
|
||||||
|
<SwitchTableField
|
||||||
|
name="auto_guard"
|
||||||
|
label={t('modals.edit_team.labels.auto_guard')}
|
||||||
|
value={autoGuard}
|
||||||
|
onValueChange={handleAutoGuardChanged}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const autoSummonField = () => {
|
||||||
|
return (
|
||||||
|
<SwitchTableField
|
||||||
|
name="auto_summon"
|
||||||
|
label={t('modals.edit_team.labels.auto_summon')}
|
||||||
|
value={autoSummon}
|
||||||
|
onValueChange={handleAutoSummonChanged}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const extraField = () => {
|
||||||
|
return (
|
||||||
|
<SwitchTableField
|
||||||
|
name="extra"
|
||||||
|
className="Extra"
|
||||||
|
label={t('modals.edit_team.labels.extra')}
|
||||||
|
description={t('modals.edit_team.descriptions.extra')}
|
||||||
|
value={extra}
|
||||||
|
disabled={true}
|
||||||
|
onValueChange={handleExtraChanged}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearTimeField = () => {
|
||||||
|
return (
|
||||||
|
<TableField
|
||||||
|
className="Numeric"
|
||||||
|
name="clear_time"
|
||||||
|
label={t('modals.edit_team.labels.clear_time')}
|
||||||
|
>
|
||||||
|
<DurationInput
|
||||||
|
name="clear_time"
|
||||||
|
className="Bound"
|
||||||
|
value={clearTime}
|
||||||
|
onValueChange={(value: number) => handleClearTimeChanged(value)}
|
||||||
|
/>
|
||||||
|
</TableField>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const turnCountField = () => {
|
||||||
|
return (
|
||||||
|
<InputTableField
|
||||||
|
name="turn_count"
|
||||||
|
className="Numeric"
|
||||||
|
label={t('modals.edit_team.labels.turn_count')}
|
||||||
|
placeholder="0"
|
||||||
|
type="number"
|
||||||
|
value={turnCount}
|
||||||
|
onValueChange={handleTurnCountChanged}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonCountField = () => {
|
||||||
|
return (
|
||||||
|
<InputTableField
|
||||||
|
name="button_count"
|
||||||
|
className="Numeric"
|
||||||
|
label={t('modals.edit_team.labels.button_count')}
|
||||||
|
placeholder="0"
|
||||||
|
type="number"
|
||||||
|
value={buttonCount}
|
||||||
|
onValueChange={handleButtonCountChanged}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const chainCountField = () => {
|
||||||
|
return (
|
||||||
|
<InputTableField
|
||||||
|
name="chain_count"
|
||||||
|
className="Numeric"
|
||||||
|
label={t('modals.edit_team.labels.chain_count')}
|
||||||
|
placeholder="0"
|
||||||
|
type="number"
|
||||||
|
value={chainCount}
|
||||||
|
onValueChange={handleChainCountChanged}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const infoPage = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{nameField()}
|
||||||
|
{raidField()}
|
||||||
|
{extraNotice()}
|
||||||
|
{descriptionField()}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const propertiesPage = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{chargeAttackField()}
|
||||||
|
{fullAutoField()}
|
||||||
|
{autoSummonField()}
|
||||||
|
{autoGuardField()}
|
||||||
|
{extraField()}
|
||||||
|
{clearTimeField()}
|
||||||
|
{turnCountField()}
|
||||||
|
{buttonCountField()}
|
||||||
|
{chainCountField()}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={openChange}>
|
||||||
|
<DialogTrigger asChild>{props.children}</DialogTrigger>
|
||||||
|
<DialogContent
|
||||||
|
className="EditTeam"
|
||||||
|
headerref={headerRef}
|
||||||
|
footerref={footerRef}
|
||||||
|
onEscapeKeyDown={onEscapeKeyDown}
|
||||||
|
onOpenAutoFocus={onOpenAutoFocus}
|
||||||
|
>
|
||||||
|
<div className="DialogHeader" ref={headerRef}>
|
||||||
|
<div className="DialogTop">
|
||||||
|
<DialogTitle className="DialogTitle">
|
||||||
|
{t('modals.edit_team.title')}
|
||||||
|
</DialogTitle>
|
||||||
|
</div>
|
||||||
|
<DialogClose className="DialogClose" asChild>
|
||||||
|
<span>
|
||||||
|
<CrossIcon />
|
||||||
|
</span>
|
||||||
|
</DialogClose>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="Content">
|
||||||
|
{segmentedControl()}
|
||||||
|
<div className="Fields">
|
||||||
|
{currentSegment === 0 && infoPage()}
|
||||||
|
{currentSegment === 1 && propertiesPage()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="DialogFooter" ref={footerRef}>
|
||||||
|
<div className="Left"></div>
|
||||||
|
<div className="Right Buttons Spaced">
|
||||||
|
<Button
|
||||||
|
contained={true}
|
||||||
|
text={t('buttons.cancel')}
|
||||||
|
onClick={openChange}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
contained={true}
|
||||||
|
rightAccessoryIcon={<CheckIcon />}
|
||||||
|
text={t('modals.edit_team.buttons.confirm')}
|
||||||
|
onClick={updateDetails}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditPartyModal
|
||||||
|
|
@ -169,6 +169,39 @@
|
||||||
"confirm": "Confirm"
|
"confirm": "Confirm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"edit_team": {
|
||||||
|
"title": "Edit team details",
|
||||||
|
"segments": {
|
||||||
|
"basic_info": "Basic info",
|
||||||
|
"properties": "Battle settings"
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"add_field": "Add field",
|
||||||
|
"confirm": "Save details"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"name": "Name",
|
||||||
|
"description": "Description",
|
||||||
|
"raid": "Battle",
|
||||||
|
"extra": "Additional weapons",
|
||||||
|
"charge_attack": "Charge Attack",
|
||||||
|
"full_auto": "Full Auto",
|
||||||
|
"auto_guard": "Auto Guard",
|
||||||
|
"auto_summon": "Auto Summon",
|
||||||
|
"turn_count": "Number of turns",
|
||||||
|
"button_count": "Number of buttons pressed",
|
||||||
|
"chain_count": "Number of chains",
|
||||||
|
"clear_time": "Clear time"
|
||||||
|
},
|
||||||
|
"descriptions": {
|
||||||
|
"extra": "Additional weapons are controlled by the selected battle"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"name": "Name your team"
|
||||||
|
},
|
||||||
|
"extra_notice": "You can add additional weapons to this team",
|
||||||
|
"extra_notice_guidebooks": "You can add additional weapons and Sephira Guidebooks to this team"
|
||||||
|
},
|
||||||
"delete_team": {
|
"delete_team": {
|
||||||
"title": "Delete team",
|
"title": "Delete team",
|
||||||
"description": "Are you sure you want to permanently delete this team?",
|
"description": "Are you sure you want to permanently delete this team?",
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,35 @@
|
||||||
"confirm": "入れ替える"
|
"confirm": "入れ替える"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"edit_team": {
|
||||||
|
"title": "編成の詳細を編集",
|
||||||
|
"segments": {
|
||||||
|
"basic_info": "基本情報",
|
||||||
|
"properties": "バトル設定・結果"
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"add_field": "フィールドを追加",
|
||||||
|
"confirm": "詳細を保存する"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"name": "編成名",
|
||||||
|
"description": "説明",
|
||||||
|
"raid": "バトル",
|
||||||
|
"charge_attack": "奥義",
|
||||||
|
"full_auto": "フルオート",
|
||||||
|
"auto_guard": "オートガード",
|
||||||
|
"auto_summon": "オート召喚",
|
||||||
|
"turn_count": "経過ターン",
|
||||||
|
"button_count": "ポチ数",
|
||||||
|
"chain_count": "チェイン数",
|
||||||
|
"clear_time": "討伐時間"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"name": "編成に名前を付ける"
|
||||||
|
},
|
||||||
|
"extra_notice": "Additional Weapons枠に武器を装備することはできます",
|
||||||
|
"extra_notice_guidebooks": "Additional Weaponsまたはセフィラ導本を装備することはできます"
|
||||||
|
},
|
||||||
"delete_team": {
|
"delete_team": {
|
||||||
"title": "編成を削除しますか",
|
"title": "編成を削除しますか",
|
||||||
"description": "編成を削除する操作は取り消せません。",
|
"description": "編成を削除する操作は取り消せません。",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue