From 2b2b4e9b6ec0eeb5ec4517c8d65395a4261b53e4 Mon Sep 17 00:00:00 2001 From: Cedric Wiese Date: Mon, 9 Mar 2026 10:59:33 +0100 Subject: [PATCH 1/3] v1: only move 2 backup functionalities to a separate tab --- frontends/web/src/app.tsx | 1 + .../src/routes/device/bitbox02/bitbox02.tsx | 14 +++- frontends/web/src/routes/router.tsx | 3 + .../web/src/routes/settings/bb02-settings.tsx | 68 +++++++++++++++---- .../src/routes/settings/components/tabs.tsx | 37 +++++++--- 5 files changed, 98 insertions(+), 25 deletions(-) diff --git a/frontends/web/src/app.tsx b/frontends/web/src/app.tsx index 283286f890..51bd86849e 100644 --- a/frontends/web/src/app.tsx +++ b/frontends/web/src/app.tsx @@ -84,6 +84,7 @@ export const App = () => { deviceIDs.length === 0 && ( currentURL.startsWith('/settings/device-settings/') + || currentURL.startsWith('/settings/backup-functionality/') || currentURL.startsWith('/manage-backups/') ) ) { diff --git a/frontends/web/src/routes/device/bitbox02/bitbox02.tsx b/frontends/web/src/routes/device/bitbox02/bitbox02.tsx index ac1aa3ed09..e07c1b2309 100644 --- a/frontends/web/src/routes/device/bitbox02/bitbox02.tsx +++ b/frontends/web/src/routes/device/bitbox02/bitbox02.tsx @@ -3,7 +3,7 @@ import { getStatus, statusChanged } from '@/api/bitbox02'; import type { TDevices } from '@/api/devices'; import { useSync } from '@/hooks/api'; -import { BB02Settings } from '@/routes/settings/bb02-settings'; +import { BB02BackupSettings, BB02Settings } from '@/routes/settings/bb02-settings'; type TProps = { deviceID: string; @@ -21,3 +21,15 @@ export const BitBox02 = ({ deviceID, devices, hasAccounts }: TProps) => { } return ; }; + +export const BitBox02Backup = ({ deviceID, devices, hasAccounts }: TProps) => { + const isBitBox02 = devices[deviceID] === 'bitbox02'; + const status = useSync( + isBitBox02 ? () => getStatus(deviceID) : async () => 'connected' as const, + isBitBox02 ? cb => statusChanged(deviceID, cb) : () => () => undefined + ); + if (!isBitBox02 || status !== 'initialized') { + return null; + } + return ; +}; diff --git a/frontends/web/src/routes/router.tsx b/frontends/web/src/routes/router.tsx index 45e71f3b89..c55eed1383 100644 --- a/frontends/web/src/routes/router.tsx +++ b/frontends/web/src/routes/router.tsx @@ -30,6 +30,7 @@ import { General } from './settings/general'; import { MobileSettings } from './settings/mobile-settings'; import { About } from './settings/about'; import { AdvancedSettings } from './settings/advanced-settings'; +import { BitBox02Backup } from './device/bitbox02/bitbox02'; import { Bitsurance } from './bitsurance/bitsurance'; import { BitsuranceAccount } from './bitsurance/account'; import { BitsuranceWidget } from './bitsurance/widget'; @@ -197,6 +198,7 @@ export const AppRouter = ({ devices, devicesKey, accounts, activeAccounts }: TAp const PassphraseEl = ; const RecoveryWordsEl = ; const Bip85El = ; + const BitBox02BackupEl = ; const ManageBackupsEl = ( + diff --git a/frontends/web/src/routes/settings/bb02-settings.tsx b/frontends/web/src/routes/settings/bb02-settings.tsx index 81e1c9d0a5..7d88eae43e 100644 --- a/frontends/web/src/routes/settings/bb02-settings.tsx +++ b/frontends/web/src/routes/settings/bb02-settings.tsx @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -import { useState, useEffect } from 'react'; +import { useState, useEffect, ReactNode } from 'react'; import { useLoad } from '@/hooks/api'; import { useTranslation } from 'react-i18next'; import { runningInIOS } from '@/utils/env'; @@ -37,6 +37,10 @@ type TProps = { }; type TWrapperProps = TProps & TPagePropsWithSettingsTabs; +type TLayoutProps = TPagePropsWithSettingsTabs & { + children: ReactNode; + mobileHeaderTitle: string; +}; export const StyledSkeleton = () => { return ( @@ -46,7 +50,12 @@ export const StyledSkeleton = () => { ); }; -const BB02Settings = ({ deviceID, devices, hasAccounts }: TWrapperProps) => { +const BB02SettingsLayout = ({ + devices, + hasAccounts, + children, + mobileHeaderTitle, +}: TLayoutProps) => { const { t } = useTranslation(); return (
@@ -60,7 +69,7 @@ const BB02Settings = ({ deviceID, devices, hasAccounts }: TWrapperProps) => { title={ <>

{t('sidebar.settings')}

- + }/> @@ -70,7 +79,7 @@ const BB02Settings = ({ deviceID, devices, hasAccounts }: TWrapperProps) => { hideMobileMenu hasAccounts={hasAccounts} > - + {children} @@ -81,7 +90,19 @@ const BB02Settings = ({ deviceID, devices, hasAccounts }: TWrapperProps) => { ); }; -const Content = ({ deviceID }: TProps) => { +const BackupContent = ({ deviceID }: TProps) => { + const { t } = useTranslation(); + + return ( +
+ {t('deviceSettings.backups.title')} + + +
+ ); +}; + +const ManageDeviceContent = ({ deviceID }: TProps) => { const { t } = useTranslation(); const [deviceInfo, setDeviceInfo] = useState(); @@ -102,13 +123,6 @@ const Content = ({ deviceID }: TProps) => { return ( <> - {/*"Backups" section*/} -
- {t('deviceSettings.backups.title')} - - -
- {/*"Device settings" section*/}
{t('deviceSettings.deviceSettings.title')} @@ -200,4 +214,32 @@ const Content = ({ deviceID }: TProps) => { ); }; -export { BB02Settings }; +const BB02Settings = ({ deviceID, devices, hasAccounts }: TWrapperProps) => { + const { t } = useTranslation(); + + return ( + + + + ); +}; + +const BB02BackupSettings = ({ deviceID, devices, hasAccounts }: TWrapperProps) => { + const { t } = useTranslation(); + + return ( + + + + ); +}; + +export { BB02Settings, BB02BackupSettings }; diff --git a/frontends/web/src/routes/settings/components/tabs.tsx b/frontends/web/src/routes/settings/components/tabs.tsx index 0daad0926a..026622fada 100644 --- a/frontends/web/src/routes/settings/components/tabs.tsx +++ b/frontends/web/src/routes/settings/components/tabs.tsx @@ -163,17 +163,32 @@ export const Tabs = ({ devices, hideMobileMenu, hasAccounts }: TTabs) => { url="/settings/no-accounts" /> )} - {deviceIDs.length ? deviceIDs.map(id => ( - : } - key={`device-${id}`} - deviceID={id} - device={devices[id] as TPlatformName} - hideMobileMenu={hideMobileMenu} - name={t('sidebar.device')} - url={`/settings/device-settings/${id}`} - /> - )) : ( + {deviceIDs.length ? deviceIDs.flatMap(id => { + const device = devices[id] as TPlatformName; + const tabs = [ + : } + key={`device-${id}`} + deviceID={id} + device={device} + hideMobileMenu={hideMobileMenu} + name={t('sidebar.device')} + url={`/settings/device-settings/${id}`} + /> + ]; + if (device === 'bitbox02') { + tabs.push( + : } + key={`backup-functionality-${id}`} + hideMobileMenu={hideMobileMenu} + name={t('deviceSettings.backups.title')} + url={`/settings/backup-functionality/${id}`} + /> + ); + } + return tabs; + }) : ( : } key="no-device" From 6f013c8845c63bb79e0e6d17134af11c928841fe Mon Sep 17 00:00:00 2001 From: Cedric Wiese Date: Mon, 9 Mar 2026 11:11:23 +0100 Subject: [PATCH 2/3] v2: Additionally split "Manage backups" into 3 different items --- .../src/routes/device/bitbox01/backups.tsx | 4 +- .../src/routes/device/bitbox02/backups.tsx | 4 +- .../device/manage-backups/manage-backups.tsx | 43 ++++++++++-- .../web/src/routes/settings/bb02-settings.tsx | 10 ++- .../device-settings/manage-backup-setting.tsx | 66 +++++++++++++++++-- 5 files changed, 113 insertions(+), 14 deletions(-) diff --git a/frontends/web/src/routes/device/bitbox01/backups.tsx b/frontends/web/src/routes/device/bitbox01/backups.tsx index da9c6e1ea3..b954a3563e 100644 --- a/frontends/web/src/routes/device/bitbox01/backups.tsx +++ b/frontends/web/src/routes/device/bitbox01/backups.tsx @@ -17,6 +17,7 @@ import { Restore } from './restore'; type BackupsProps = { deviceID: string; showCreate?: boolean; + showCheck?: boolean; showRestore?: boolean; requireConfirmation?: boolean; onRestore?: () => void; @@ -89,6 +90,7 @@ class Backups extends Component { t, children, showCreate = false, + showCheck = showCreate, showRestore = true, deviceID, requireConfirmation = true, @@ -146,7 +148,7 @@ class Backups extends Component { ) } { - showCreate && ( + showCheck && ( diff --git a/frontends/web/src/routes/device/bitbox02/backups.tsx b/frontends/web/src/routes/device/bitbox02/backups.tsx index 5c5daf1502..ea5fbf6ea1 100644 --- a/frontends/web/src/routes/device/bitbox02/backups.tsx +++ b/frontends/web/src/routes/device/bitbox02/backups.tsx @@ -20,6 +20,7 @@ type TProps = { deviceID: string; showRestore?: boolean; showCreate?: boolean; + showCheck?: boolean; showRadio: boolean; onSelectBackup?: (backup: Backup) => void; onRestoreBackup?: (success: boolean) => void; @@ -30,6 +31,7 @@ export const BackupsV2 = ({ deviceID, showRestore, showCreate, + showCheck, showRadio, onSelectBackup, onRestoreBackup, @@ -148,7 +150,7 @@ export const BackupsV2 = ({ ) } { - showCreate && ( + showCheck && ( { + return mode === 'create' || mode === 'check' || mode === 'list'; +}; + +const getBackupMode = (search: string): TBackupMode | undefined => { + const mode = new URLSearchParams(search).get('mode'); + return isBackupMode(mode) ? mode : undefined; +}; + +const getTitle = (mode: TBackupMode | undefined, t: (input: string) => string) => { + switch (mode) { + case 'create': + return t('backup.create.title'); + case 'check': + return t('backup.check.title'); + case 'list': + return t('backup.list'); + default: + return t('backup.title'); + } +}; + export const ManageBackups = ({ deviceID, devices, }: TProps) => { const { t } = useTranslation(); + const location = useLocation(); + const mode = getBackupMode(location.search); if (!deviceID || !devices[deviceID]) { return null; @@ -31,12 +58,13 @@ export const ManageBackups = ({
{t('backup.title')}} + title={

{getTitle(mode, t)}

} />
@@ -52,11 +80,16 @@ export const ManageBackups = ({ const BackupsList = ({ deviceID, devices, -}: TProps) => { + mode, +}: TProps & { mode?: TBackupMode }) => { const { t } = useTranslation(); if (!deviceID) { return null; } + + const showCreate = mode === undefined || mode === 'create'; + const showCheck = mode === undefined || mode === 'check'; + switch (devices[deviceID]) { case 'bitbox': @@ -65,7 +98,8 @@ const BackupsList = ({ {t('backup.list')} {t('button.back')} @@ -78,7 +112,8 @@ const BackupsList = ({ diff --git a/frontends/web/src/routes/settings/bb02-settings.tsx b/frontends/web/src/routes/settings/bb02-settings.tsx index 7d88eae43e..e07e86d003 100644 --- a/frontends/web/src/routes/settings/bb02-settings.tsx +++ b/frontends/web/src/routes/settings/bb02-settings.tsx @@ -8,7 +8,11 @@ import { GuideWrapper, GuidedContent, Header, Main } from '@/components/layout'; import { ViewContent, View } from '@/components/view/view'; import { WithSettingsTabs } from './components/tabs'; import { TPagePropsWithSettingsTabs } from './types'; -import { ManageBackupSetting } from './components/device-settings/manage-backup-setting'; +import { + CheckBackupSetting, + CreateBackupSetting, + ListBackupsSetting, +} from './components/device-settings/manage-backup-setting'; import { ShowRecoveryWordsSetting } from './components/device-settings/show-recovery-words-setting'; import { GoToStartupSettings } from './components/device-settings/go-to-startup-settings'; import { PassphraseSetting } from './components/device-settings/passphrase-setting'; @@ -96,7 +100,9 @@ const BackupContent = ({ deviceID }: TProps) => { return (
{t('deviceSettings.backups.title')} - + + +
); diff --git a/frontends/web/src/routes/settings/components/device-settings/manage-backup-setting.tsx b/frontends/web/src/routes/settings/components/device-settings/manage-backup-setting.tsx index ea629c7f47..829a0f2ed2 100644 --- a/frontends/web/src/routes/settings/components/device-settings/manage-backup-setting.tsx +++ b/frontends/web/src/routes/settings/components/device-settings/manage-backup-setting.tsx @@ -8,17 +8,71 @@ type TProps = { deviceID: string; }; -const ManageBackupSetting = ({ deviceID }: TProps) => { +type TBackupMode = 'create' | 'check' | 'list'; + +type TBackupSettingsItemProps = TProps & { + mode: TBackupMode; + settingName: string; + secondaryText: string; +}; + +const BackupSettingsItem = ({ + deviceID, + mode, + settingName, + secondaryText, +}: TBackupSettingsItemProps) => { const navigate = useNavigate(); - const { t } = useTranslation(); + return ( navigate(`/manage-backups/${deviceID}`)} - settingName={t('backup.title')} - secondaryText={t('deviceSettings.backups.manageBackups.description')} + onClick={() => navigate(`/manage-backups/${deviceID}?mode=${mode}`)} + settingName={settingName} + secondaryText={secondaryText} + /> + ); +}; + +const CreateBackupSetting = ({ deviceID }: TProps) => { + const { t } = useTranslation(); + return ( + ); }; +const CheckBackupSetting = ({ deviceID }: TProps) => { + const { t } = useTranslation(); + return ( + + ); +}; + +const ListBackupsSetting = ({ deviceID }: TProps) => { + const { t } = useTranslation(); + return ( + + ); +}; -export { ManageBackupSetting }; \ No newline at end of file +export { CreateBackupSetting, CheckBackupSetting, ListBackupsSetting }; From 34e6ea71f3ea3c84b6d8a955ede7e604adbe4e3a Mon Sep 17 00:00:00 2001 From: Cedric Wiese Date: Mon, 9 Mar 2026 11:23:35 +0100 Subject: [PATCH 3/3] v3: "Check backup" and "Create backup" do not show the backup list anymore --- .../src/routes/device/bitbox02/backups.tsx | 16 ++++- .../routes/device/bitbox02/checkbackup.tsx | 57 +++++++++++---- .../routes/device/bitbox02/createbackup.tsx | 42 ++++++++--- .../device/manage-backups/manage-backups.tsx | 70 ++++++++++++++++++- .../web/src/routes/settings/bb02-settings.tsx | 43 +++++++++++- .../device-settings/manage-backup-setting.tsx | 13 ++-- 6 files changed, 212 insertions(+), 29 deletions(-) diff --git a/frontends/web/src/routes/device/bitbox02/backups.tsx b/frontends/web/src/routes/device/bitbox02/backups.tsx index ea5fbf6ea1..46d1e64529 100644 --- a/frontends/web/src/routes/device/bitbox02/backups.tsx +++ b/frontends/web/src/routes/device/bitbox02/backups.tsx @@ -21,6 +21,9 @@ type TProps = { showRestore?: boolean; showCreate?: boolean; showCheck?: boolean; + autoStartCreate?: boolean; + autoStartCheck?: boolean; + autoStartID?: string; showRadio: boolean; onSelectBackup?: (backup: Backup) => void; onRestoreBackup?: (success: boolean) => void; @@ -32,6 +35,9 @@ export const BackupsV2 = ({ showRestore, showCreate, showCheck, + autoStartCreate, + autoStartCheck, + autoStartID, showRadio, onSelectBackup, onRestoreBackup, @@ -146,7 +152,12 @@ export const BackupsV2 = ({ } { showCreate && ( - + ) } { @@ -155,6 +166,9 @@ export const BackupsV2 = ({ deviceID={deviceID} backups={backups.backups ? backups.backups : []} disabled={backups.backups.length === 0} + autoStart={autoStartCheck} + autoStartID={autoStartCheck ? autoStartID : undefined} + showButton={!autoStartCheck} /> ) } diff --git a/frontends/web/src/routes/device/bitbox02/checkbackup.tsx b/frontends/web/src/routes/device/bitbox02/checkbackup.tsx index f121367234..721ad81ade 100644 --- a/frontends/web/src/routes/device/bitbox02/checkbackup.tsx +++ b/frontends/web/src/routes/device/bitbox02/checkbackup.tsx @@ -1,37 +1,53 @@ // SPDX-License-Identifier: Apache-2.0 -import { useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import * as bitbox02API from '@/api/bitbox02'; import { BackupsListItem } from '@/routes/device/components/backup'; -import { Backup } from '@/api/backup'; -import { alertUser } from '@/components/alert/Alert'; +import { Backup, getBackupList } from '@/api/backup'; import { Dialog, DialogButtons } from '@/components/dialog/dialog'; import { Button } from '@/components/forms'; import { useTranslation } from 'react-i18next'; +const startedCheckBackupFlows = new Set(); + type TProps = { deviceID: string; backups: Backup[]; disabled: boolean; + autoStart?: boolean; + autoStartID?: string; + showButton?: boolean; }; -export const Check = ({ deviceID, backups, disabled }: TProps) => { +export const Check = ({ + deviceID, + backups, + disabled, + autoStart = false, + autoStartID, + showButton = true, +}: TProps) => { const [activeDialog, setActiveDialog] = useState(false); const [message, setMessage] = useState(''); const [foundBackup, setFoundBackup] = useState(); const [userVerified, setUserVerified] = useState(false); + const checkBackupRef = useRef<() => Promise>(); const { t } = useTranslation(); const checkBackup = async () => { setMessage(''); + setFoundBackup(undefined); + setUserVerified(false); try { const result = await bitbox02API.checkBackup(deviceID, true); if (result.success) { const { backupID } = result; - const foundBackup = backups.find((backup: Backup) => backup.id === backupID); + let foundBackup = backups.find((backup: Backup) => backup.id === backupID); if (!foundBackup) { - alertUser(t('unknownError', { errorMessage: 'Not found' })); - return; + const backupListResult = await getBackupList(deviceID); + if (backupListResult.success) { + foundBackup = backupListResult.backups.find((backup: Backup) => backup.id === backupID); + } } setActiveDialog(true); setFoundBackup(foundBackup); @@ -54,15 +70,30 @@ export const Check = ({ deviceID, backups, disabled }: TProps) => { console.error(error); } }; + checkBackupRef.current = checkBackup; + + useEffect(() => { + if (!autoStart || disabled) { + return; + } + const id = autoStartID || `check-${deviceID}`; + if (startedCheckBackupFlows.has(id)) { + return; + } + startedCheckBackupFlows.add(id); + void checkBackupRef.current?.(); + }, [autoStart, disabled, autoStartID, deviceID]); return ( <> - + {showButton && ( + + )} diff --git a/frontends/web/src/routes/device/bitbox02/createbackup.tsx b/frontends/web/src/routes/device/bitbox02/createbackup.tsx index 092e2e8a2e..7a90e7a6a5 100644 --- a/frontends/web/src/routes/device/bitbox02/createbackup.tsx +++ b/frontends/web/src/routes/device/bitbox02/createbackup.tsx @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -import { useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { checkBackup, createBackup as createBackupAPI } from '@/api/bitbox02'; import { alertUser } from '@/components/alert/Alert'; import { confirmation } from '@/components/confirm/Confirm'; @@ -8,13 +8,24 @@ import { Button } from '@/components/forms'; import { WaitDialog } from '@/components/wait-dialog/wait-dialog'; import { useTranslation } from 'react-i18next'; +const startedCreateBackupFlows = new Set(); + type TProps = { deviceID: string; + autoStart?: boolean; + autoStartID?: string; + showButton?: boolean; }; -export const Create = ({ deviceID }: TProps) => { +export const Create = ({ + deviceID, + autoStart = false, + autoStartID, + showButton = true, +}: TProps) => { const [creatingBackup, setCreatingBackup] = useState(false); const [disabled, setDisabled] = useState(false); + const maybeCreateBackupRef = useRef<() => Promise>(); const { t } = useTranslation(); const createBackup = () => { @@ -49,15 +60,30 @@ export const Create = ({ deviceID }: TProps) => { console.error(error); } }; + maybeCreateBackupRef.current = maybeCreateBackup; + + useEffect(() => { + if (!autoStart) { + return; + } + const id = autoStartID || `create-${deviceID}`; + if (startedCreateBackupFlows.has(id)) { + return; + } + startedCreateBackupFlows.add(id); + void maybeCreateBackupRef.current?.(); + }, [autoStart, autoStartID, deviceID]); return ( <> - + {showButton && ( + + )} { creatingBackup && ( {t('bitbox02Interact.followInstructions')} diff --git a/frontends/web/src/routes/device/manage-backups/manage-backups.tsx b/frontends/web/src/routes/device/manage-backups/manage-backups.tsx index c89a31b8f7..7643772ad7 100644 --- a/frontends/web/src/routes/device/manage-backups/manage-backups.tsx +++ b/frontends/web/src/routes/device/manage-backups/manage-backups.tsx @@ -10,7 +10,10 @@ import { Entry } from '@/components/guide/entry'; import { Header } from '@/components/layout'; import { Backups } from '@/routes/device/bitbox01/backups'; import { BackupsV2 } from '@/routes/device/bitbox02/backups'; +import { Create as CreateBackupV2 } from '@/routes/device/bitbox02/createbackup'; +import { Check as CheckBackupV2 } from '@/routes/device/bitbox02/checkbackup'; import { SDCardCheck } from '@/routes/device/bitbox02/sdcardcheck'; +import { HorizontallyCenteredSpinner } from '@/components/spinner/SpinnerAnimation'; type TProps = { deviceID: string | null; @@ -48,6 +51,7 @@ export const ManageBackups = ({ const { t } = useTranslation(); const location = useLocation(); const mode = getBackupMode(location.search); + const autoStartID = mode ? `${location.key}-${mode}` : undefined; if (!deviceID || !devices[deviceID]) { return null; @@ -65,6 +69,7 @@ export const ManageBackups = ({ deviceID={deviceID} devices={devices} mode={mode} + autoStartID={autoStartID} />
@@ -81,7 +86,8 @@ const BackupsList = ({ deviceID, devices, mode, -}: TProps & { mode?: TBackupMode }) => { + autoStartID, +}: TProps & { mode?: TBackupMode; autoStartID?: string }) => { const { t } = useTranslation(); if (!deviceID) { return null; @@ -108,6 +114,26 @@ const BackupsList = ({ ); case 'bitbox02': + if (mode === 'create') { + return ( + + + + ); + } + if (mode === 'check') { + return ( + + + + ); + } return ( { + const { t } = useTranslation(); + return ( +
+ + +
+ + {t('button.back')} + +
+
+ ); +}; + +const AutoStartCheckBackup = ({ deviceID, autoStartID }: { deviceID: string; autoStartID?: string }) => { + const { t } = useTranslation(); + return ( +
+ + +
+ + {t('button.back')} + +
+
+ ); +}; + const ManageBackupGuide = ({ deviceID, devices, diff --git a/frontends/web/src/routes/settings/bb02-settings.tsx b/frontends/web/src/routes/settings/bb02-settings.tsx index e07e86d003..7f95bd72fd 100644 --- a/frontends/web/src/routes/settings/bb02-settings.tsx +++ b/frontends/web/src/routes/settings/bb02-settings.tsx @@ -34,6 +34,8 @@ import { MobileHeader } from './components/mobile-header'; import { ContentWrapper } from '@/components/contentwrapper/contentwrapper'; import { GlobalBanners } from '@/components/banners'; import { SubTitle } from '@/components/title'; +import { Create as CreateBackupFlow } from '@/routes/device/bitbox02/createbackup'; +import { Check as CheckBackupFlow } from '@/routes/device/bitbox02/checkbackup'; import styles from './bb02-settings.module.css'; type TProps = { @@ -96,14 +98,51 @@ const BB02SettingsLayout = ({ const BackupContent = ({ deviceID }: TProps) => { const { t } = useTranslation(); + const [activeBackupFlow, setActiveBackupFlow] = useState<'create' | 'check'>(); + const [backupFlowCounter, setBackupFlowCounter] = useState(0); + + const startFlow = (flow: 'create' | 'check') => { + setActiveBackupFlow(flow); + setBackupFlowCounter(current => current + 1); + }; + + const flowID = activeBackupFlow ? `${deviceID}-${activeBackupFlow}-${backupFlowCounter}` : undefined; return (
{t('deviceSettings.backups.title')} - - + startFlow('create')} + /> + startFlow('check')} + /> + { + activeBackupFlow === 'create' ? ( + + ) : null + } + { + activeBackupFlow === 'check' ? ( + + ) : null + }
); }; diff --git a/frontends/web/src/routes/settings/components/device-settings/manage-backup-setting.tsx b/frontends/web/src/routes/settings/components/device-settings/manage-backup-setting.tsx index 829a0f2ed2..0464715563 100644 --- a/frontends/web/src/routes/settings/components/device-settings/manage-backup-setting.tsx +++ b/frontends/web/src/routes/settings/components/device-settings/manage-backup-setting.tsx @@ -6,6 +6,7 @@ import { SettingsItem } from '@/routes/settings/components/settingsItem/settings type TProps = { deviceID: string; + onClick?: () => void; }; type TBackupMode = 'create' | 'check' | 'list'; @@ -18,6 +19,7 @@ type TBackupSettingsItemProps = TProps & { const BackupSettingsItem = ({ deviceID, + onClick, mode, settingName, secondaryText, @@ -26,18 +28,19 @@ const BackupSettingsItem = ({ return ( navigate(`/manage-backups/${deviceID}?mode=${mode}`)} + onClick={onClick || (() => navigate(`/manage-backups/${deviceID}?mode=${mode}`))} settingName={settingName} secondaryText={secondaryText} /> ); }; -const CreateBackupSetting = ({ deviceID }: TProps) => { +const CreateBackupSetting = ({ deviceID, onClick }: TProps) => { const { t } = useTranslation(); return ( { ); }; -const CheckBackupSetting = ({ deviceID }: TProps) => { +const CheckBackupSetting = ({ deviceID, onClick }: TProps) => { const { t } = useTranslation(); return ( { ); }; -const ListBackupsSetting = ({ deviceID }: TProps) => { +const ListBackupsSetting = ({ deviceID, onClick }: TProps) => { const { t } = useTranslation(); return (