diff --git a/src/components/send/SendCoinjoinPreconditionAlert.tsx b/src/components/send/SendCoinjoinPreconditionAlert.tsx
index e02e8f92..3a470de9 100644
--- a/src/components/send/SendCoinjoinPreconditionAlert.tsx
+++ b/src/components/send/SendCoinjoinPreconditionAlert.tsx
@@ -1,97 +1,10 @@
-import { AlertTriangleIcon } from 'lucide-react'
-import { Trans, useTranslation } from 'react-i18next'
-import { Link } from 'react-router-dom'
import type { SweepPreconditionSummary } from '@/components/sweep/preconditions'
-import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
-import { Balance } from '@/components/ui/jam/Balance'
-import { JAM_JM_RETRIES_DOCS_URL } from '@/constants/jam'
-import { routes } from '@/constants/routes'
-import { shortenStringMiddle } from '@/lib/utils'
-import { JarBadge } from '../earn/fidelity-bond/FidelityBondDialogParts'
+import { PreconditionAlert } from '@/components/ui/jam/PreconditionAlert'
interface SendCoinjoinPreconditionAlertProps {
summary: SweepPreconditionSummary
}
-const RetryLockedUtxoList = ({ summary }: SendCoinjoinPreconditionAlertProps) => {
- const { t } = useTranslation()
-
- return (
- <>
-
- ),
- }}
- />
-
-
{t('global.utxos')}
-
- {summary.retryLockedUtxos.map((utxo) => (
- -
-
-
-
- {shortenStringMiddle(utxo.utxo, 26)}
-
-
- ))}
-
-
- >
- )
-}
-
export const SendCoinjoinPreconditionAlert = ({ summary }: SendCoinjoinPreconditionAlertProps) => {
- const { t } = useTranslation()
-
- if (summary.isFulfilled) {
- return null
- }
-
- return (
-
-
- {t('send.coinjoin_precondition.title')}
-
-
- {summary.numberOfNonFrozenFidelityBondOutputs === 0 ? null : (
- -
- ,
- }}
- />
-
- )}
- {summary.numberOfMissingUtxos === 0 ? null : (
- -
- {t('send.coinjoin_precondition.hint_missing_utxos', {
- minConfirmations: summary.options.minConfirmations,
- })}
-
- )}
- {summary.numberOfMissingConfirmations === 0 ? null : (
- -
- {t('send.coinjoin_precondition.hint_missing_confirmations', {
- minConfirmations: summary.options.minConfirmations,
- amountOfMissingConfirmations: summary.numberOfMissingConfirmations,
- })}
-
- )}
- {summary.retryLockedUtxos.length === 0 ? null : - {}
}
-
-
-
- )
+ return
}
diff --git a/src/components/sweep/SweepPreconditionAlert.tsx b/src/components/sweep/SweepPreconditionAlert.tsx
index afb1440e..fc5c6eb5 100644
--- a/src/components/sweep/SweepPreconditionAlert.tsx
+++ b/src/components/sweep/SweepPreconditionAlert.tsx
@@ -1,97 +1,10 @@
-import { AlertTriangleIcon } from 'lucide-react'
-import { Trans, useTranslation } from 'react-i18next'
-import { Link } from 'react-router-dom'
import type { SweepPreconditionSummary } from '@/components/sweep/preconditions'
-import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
-import { Balance } from '@/components/ui/jam/Balance'
-import { JAM_JM_RETRIES_DOCS_URL } from '@/constants/jam'
-import { routes } from '@/constants/routes'
-import { shortenStringMiddle } from '@/lib/utils'
-import { JarBadge } from '../earn/fidelity-bond/FidelityBondDialogParts'
+import { PreconditionAlert } from '@/components/ui/jam/PreconditionAlert'
interface SweepPreconditionAlertProps {
summary: SweepPreconditionSummary
}
-const RetryLockedUtxoList = ({ summary }: SweepPreconditionAlertProps) => {
- const { t } = useTranslation()
-
- return (
- <>
-
- ),
- }}
- />
-
-
{t('global.utxos')}
-
- {summary.retryLockedUtxos.map((utxo) => (
- -
-
-
-
- {shortenStringMiddle(utxo.utxo, 26)}
-
-
- ))}
-
-
- >
- )
-}
-
export const SweepPreconditionAlert = ({ summary }: SweepPreconditionAlertProps) => {
- const { t } = useTranslation()
-
- if (summary.isFulfilled) {
- return null
- }
-
- return (
-
-
- {t('scheduler.precondition.title')}
-
-
- {summary.numberOfNonFrozenFidelityBondOutputs === 0 ? null : (
- -
- ,
- }}
- />
-
- )}
- {summary.numberOfMissingUtxos === 0 ? null : (
- -
- {t('scheduler.precondition.hint_missing_utxos', {
- minConfirmations: summary.options.minConfirmations,
- })}
-
- )}
- {summary.numberOfMissingConfirmations === 0 ? null : (
- -
- {t('scheduler.precondition.hint_missing_confirmations', {
- minConfirmations: summary.options.minConfirmations,
- amountOfMissingConfirmations: summary.numberOfMissingConfirmations,
- })}
-
- )}
- {summary.retryLockedUtxos.length === 0 ? null : - {}
}
-
-
-
- )
+ return
}
diff --git a/src/components/ui/jam/PreconditionAlert.tsx b/src/components/ui/jam/PreconditionAlert.tsx
new file mode 100644
index 00000000..ce42d921
--- /dev/null
+++ b/src/components/ui/jam/PreconditionAlert.tsx
@@ -0,0 +1,102 @@
+import { AlertTriangleIcon } from 'lucide-react'
+import { Trans, useTranslation } from 'react-i18next'
+import { Link } from 'react-router-dom'
+import { JarBadge } from '@/components/earn/fidelity-bond/FidelityBondDialogParts'
+import type { SweepPreconditionSummary } from '@/components/sweep/preconditions'
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { Balance } from '@/components/ui/jam/Balance'
+import { JAM_JM_RETRIES_DOCS_URL } from '@/constants/jam'
+import { routes } from '@/constants/routes'
+import { shortenStringMiddle } from '@/lib/utils'
+
+export interface PreconditionAlertProps {
+ summary: SweepPreconditionSummary
+ i18nPrefix: 'send.coinjoin_precondition' | 'scheduler.precondition'
+}
+
+const RetryLockedUtxoList = ({ summary, i18nPrefix }: PreconditionAlertProps) => {
+ const { t } = useTranslation()
+
+ return (
+ <>
+
+ ),
+ }}
+ />
+
+
{t('global.utxos')}
+
+ {summary.retryLockedUtxos.map((utxo) => (
+ -
+
+
+
+ {shortenStringMiddle(utxo.utxo, 26)}
+
+
+ ))}
+
+
+ >
+ )
+}
+
+export const PreconditionAlert = ({ summary, i18nPrefix }: PreconditionAlertProps) => {
+ const { t } = useTranslation()
+
+ if (summary.isFulfilled) {
+ return null
+ }
+
+ return (
+
+
+ {t(`${i18nPrefix}.title`)}
+
+
+ {summary.numberOfNonFrozenFidelityBondOutputs === 0 ? null : (
+ -
+ ,
+ }}
+ />
+
+ )}
+ {summary.numberOfMissingUtxos === 0 ? null : (
+ -
+ {t(`${i18nPrefix}.hint_missing_utxos`, {
+ minConfirmations: summary.options.minConfirmations,
+ })}
+
+ )}
+ {summary.numberOfMissingConfirmations === 0 ? null : (
+ -
+ {t(`${i18nPrefix}.hint_missing_confirmations`, {
+ minConfirmations: summary.options.minConfirmations,
+ amountOfMissingConfirmations: summary.numberOfMissingConfirmations,
+ })}
+
+ )}
+ {summary.retryLockedUtxos.length === 0 ? null : (
+ -
+
+
+ )}
+
+
+
+ )
+}
diff --git a/src/stories/jam/PreconditionAlert.stories.tsx b/src/stories/jam/PreconditionAlert.stories.tsx
new file mode 100644
index 00000000..45b2d11c
--- /dev/null
+++ b/src/stories/jam/PreconditionAlert.stories.tsx
@@ -0,0 +1,179 @@
+import type { Meta, StoryObj } from '@storybook/react-vite'
+import { SWEEP_PRECONDITION_DEFAULT_OPTIONS } from '@/components/sweep/preconditions'
+import { PreconditionAlert } from '@/components/ui/jam/PreconditionAlert'
+import type { Utxo } from '@/hooks/useQueryUtxos'
+
+const DEFAULT_SUMMARY = Object.freeze({
+ isFulfilled: false,
+ options: SWEEP_PRECONDITION_DEFAULT_OPTIONS,
+ numberOfMissingUtxos: 0,
+ numberOfMissingConfirmations: 0,
+ numberOfNonFrozenFidelityBondOutputs: 0,
+ retryLockedUtxos: [],
+})
+
+const makeUtxo = (overrides: Partial = {}): Utxo =>
+ ({
+ address: 'bc1qsource',
+ confirmations: 6,
+ frozen: false,
+ label: '',
+ locktime: undefined,
+ mixdepth: 0,
+ path: '',
+ tries_remaining: 3,
+ utxo: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0',
+ value: 100_000,
+ ...overrides,
+ }) as Utxo
+
+const meta: Meta = {
+ title: 'Jam/PreconditionAlert',
+ component: PreconditionAlert,
+ tags: ['autodocs'],
+ args: {
+ summary: DEFAULT_SUMMARY,
+ i18nPrefix: 'send.coinjoin_precondition',
+ },
+}
+export default meta
+
+type Story = StoryObj
+
+// --- Send Flow Stories ---
+
+export const SendDefault: Story = {
+ args: {
+ i18nPrefix: 'send.coinjoin_precondition',
+ },
+}
+
+export const SendMissingUtxos: Story = {
+ args: {
+ i18nPrefix: 'send.coinjoin_precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ numberOfMissingUtxos: 3,
+ },
+ },
+}
+
+export const SendMissingConfirmations: Story = {
+ args: {
+ i18nPrefix: 'send.coinjoin_precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ numberOfMissingConfirmations: 3,
+ },
+ },
+}
+
+export const SendNonFrozenFidelityBondsPresent: Story = {
+ args: {
+ i18nPrefix: 'send.coinjoin_precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ numberOfNonFrozenFidelityBondOutputs: 3,
+ },
+ },
+}
+
+export const SendRetryLockedUtxos: Story = {
+ args: {
+ i18nPrefix: 'send.coinjoin_precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ retryLockedUtxos: [
+ makeUtxo({ mixdepth: 0, value: 21 }),
+ makeUtxo({ mixdepth: 1, value: 21_000 }),
+ makeUtxo({ mixdepth: 2, value: 21_000_000 }),
+ ],
+ },
+ },
+}
+
+export const SendMultiple: Story = {
+ args: {
+ i18nPrefix: 'send.coinjoin_precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ numberOfMissingUtxos: 3,
+ numberOfMissingConfirmations: 3,
+ numberOfNonFrozenFidelityBondOutputs: 3,
+ retryLockedUtxos: [
+ makeUtxo({ mixdepth: 0, value: 21 }),
+ makeUtxo({ mixdepth: 1, value: 21_000 }),
+ makeUtxo({ mixdepth: 2, value: 21_000_000 }),
+ ],
+ },
+ },
+}
+
+// --- Sweep Flow Stories ---
+
+export const SweepDefault: Story = {
+ args: {
+ i18nPrefix: 'scheduler.precondition',
+ },
+}
+
+export const SweepMissingUtxos: Story = {
+ args: {
+ i18nPrefix: 'scheduler.precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ numberOfMissingUtxos: 3,
+ },
+ },
+}
+
+export const SweepMissingConfirmations: Story = {
+ args: {
+ i18nPrefix: 'scheduler.precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ numberOfMissingConfirmations: 3,
+ },
+ },
+}
+
+export const SweepNonFrozenFidelityBondsPresent: Story = {
+ args: {
+ i18nPrefix: 'scheduler.precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ numberOfNonFrozenFidelityBondOutputs: 3,
+ },
+ },
+}
+
+export const SweepRetryLockedUtxos: Story = {
+ args: {
+ i18nPrefix: 'scheduler.precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ retryLockedUtxos: [
+ makeUtxo({ mixdepth: 0, value: 21 }),
+ makeUtxo({ mixdepth: 1, value: 21_000 }),
+ makeUtxo({ mixdepth: 2, value: 21_000_000 }),
+ ],
+ },
+ },
+}
+
+export const SweepMultiple: Story = {
+ args: {
+ i18nPrefix: 'scheduler.precondition',
+ summary: {
+ ...DEFAULT_SUMMARY,
+ numberOfMissingUtxos: 3,
+ numberOfMissingConfirmations: 3,
+ numberOfNonFrozenFidelityBondOutputs: 3,
+ retryLockedUtxos: [
+ makeUtxo({ mixdepth: 0, value: 21 }),
+ makeUtxo({ mixdepth: 1, value: 21_000 }),
+ makeUtxo({ mixdepth: 2, value: 21_000_000 }),
+ ],
+ },
+ },
+}
diff --git a/src/stories/jam/SendCoinJoinPreconditionAlert.stories.tsx b/src/stories/jam/SendCoinJoinPreconditionAlert.stories.tsx
deleted file mode 100644
index cca58e5c..00000000
--- a/src/stories/jam/SendCoinJoinPreconditionAlert.stories.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import type { Meta, StoryObj } from '@storybook/react-vite'
-import { SendCoinjoinPreconditionAlert } from '@/components/send/SendCoinjoinPreconditionAlert'
-import { SWEEP_PRECONDITION_DEFAULT_OPTIONS } from '@/components/sweep/preconditions'
-import type { Utxo } from '@/hooks/useQueryUtxos'
-
-const DEFAULT_SUMMARY = Object.freeze({
- isFulfilled: false,
- options: SWEEP_PRECONDITION_DEFAULT_OPTIONS,
- numberOfMissingUtxos: 0,
- numberOfMissingConfirmations: 0,
- numberOfNonFrozenFidelityBondOutputs: 0,
- retryLockedUtxos: [],
-})
-
-const makeUtxo = (overrides: Partial = {}): Utxo =>
- ({
- address: 'bc1qsource',
- confirmations: 6,
- frozen: false,
- label: '',
- locktime: undefined,
- mixdepth: 0,
- path: '',
- tries_remaining: 3,
- utxo: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0',
- value: 100_000,
- ...overrides,
- }) as Utxo
-
-const meta: Meta = {
- title: 'Jam/SendCoinjoinPreconditionAlert',
- component: SendCoinjoinPreconditionAlert,
- tags: ['autodocs'],
- args: {
- summary: DEFAULT_SUMMARY,
- },
-}
-export default meta
-
-type Story = StoryObj
-
-export const Default: Story = {}
-
-export const MissingUtxos: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- numberOfMissingUtxos: 3,
- },
- },
-}
-
-export const MissingConfirmations: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- numberOfMissingConfirmations: 3,
- },
- },
-}
-
-export const NonFrozenFidelityBondsPresent: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- numberOfNonFrozenFidelityBondOutputs: 3,
- },
- },
-}
-
-export const RetryLockedUtxos: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- retryLockedUtxos: [
- makeUtxo({
- mixdepth: 0,
- value: 21,
- }),
- makeUtxo({
- mixdepth: 1,
- value: 21_000,
- }),
- makeUtxo({
- mixdepth: 2,
- value: 21_000_000,
- }),
- ],
- },
- },
-}
-
-export const Multiple: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- numberOfMissingUtxos: 3,
- numberOfMissingConfirmations: 3,
- numberOfNonFrozenFidelityBondOutputs: 3,
- retryLockedUtxos: [
- makeUtxo({
- mixdepth: 0,
- value: 21,
- }),
- makeUtxo({
- mixdepth: 1,
- value: 21_000,
- }),
- makeUtxo({
- mixdepth: 2,
- value: 21_000_000,
- }),
- ],
- },
- },
-}
diff --git a/src/stories/jam/SweepPreconditionAlert.stories.tsx b/src/stories/jam/SweepPreconditionAlert.stories.tsx
deleted file mode 100644
index 9e8cbef5..00000000
--- a/src/stories/jam/SweepPreconditionAlert.stories.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import type { Meta, StoryObj } from '@storybook/react-vite'
-import { SweepPreconditionAlert } from '@/components/sweep/SweepPreconditionAlert'
-import { SWEEP_PRECONDITION_DEFAULT_OPTIONS } from '@/components/sweep/preconditions'
-import type { Utxo } from '@/hooks/useQueryUtxos'
-
-const DEFAULT_SUMMARY = Object.freeze({
- isFulfilled: false,
- options: SWEEP_PRECONDITION_DEFAULT_OPTIONS,
- numberOfMissingUtxos: 0,
- numberOfMissingConfirmations: 0,
- numberOfNonFrozenFidelityBondOutputs: 0,
- retryLockedUtxos: [],
-})
-
-const makeUtxo = (overrides: Partial = {}): Utxo =>
- ({
- address: 'bc1qsource',
- confirmations: 6,
- frozen: false,
- label: '',
- locktime: undefined,
- mixdepth: 0,
- path: '',
- tries_remaining: 3,
- utxo: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0',
- value: 100_000,
- ...overrides,
- }) as Utxo
-
-const meta: Meta = {
- title: 'Jam/SweepPreconditionAlert',
- component: SweepPreconditionAlert,
- tags: ['autodocs'],
- args: {
- summary: DEFAULT_SUMMARY,
- },
-}
-export default meta
-
-type Story = StoryObj
-
-export const Default: Story = {}
-
-export const MissingUtxos: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- numberOfMissingUtxos: 3,
- },
- },
-}
-
-export const MissingConfirmations: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- numberOfMissingConfirmations: 3,
- },
- },
-}
-
-export const NonFrozenFidelityBondsPresent: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- numberOfNonFrozenFidelityBondOutputs: 3,
- },
- },
-}
-
-export const RetryLockedUtxos: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- retryLockedUtxos: [
- makeUtxo({
- mixdepth: 0,
- value: 21,
- }),
- makeUtxo({
- mixdepth: 1,
- value: 21_000,
- }),
- makeUtxo({
- mixdepth: 2,
- value: 21_000_000,
- }),
- ],
- },
- },
-}
-
-export const Multiple: Story = {
- args: {
- summary: {
- ...DEFAULT_SUMMARY,
- numberOfMissingUtxos: 3,
- numberOfMissingConfirmations: 3,
- numberOfNonFrozenFidelityBondOutputs: 3,
- retryLockedUtxos: [
- makeUtxo({
- mixdepth: 0,
- value: 21,
- }),
- makeUtxo({
- mixdepth: 1,
- value: 21_000,
- }),
- makeUtxo({
- mixdepth: 2,
- value: 21_000_000,
- }),
- ],
- },
- },
-}