Skip to content

Commit 0ff874b

Browse files
committed
sidecar: add a wizard to register a Sidecar Channel ticket
1 parent 07421df commit 0ff874b

File tree

14 files changed

+455
-8
lines changed

14 files changed

+455
-8
lines changed
Lines changed: 5 additions & 0 deletions
Loading

app/src/components/base/icons.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ReactComponent as ChevronsRightIcon } from 'assets/icons/chevrons-right
1515
import { ReactComponent as ChevronsIcon } from 'assets/icons/chevrons.svg';
1616
import { ReactComponent as ClockIcon } from 'assets/icons/clock.svg';
1717
import { ReactComponent as CloseIcon } from 'assets/icons/close.svg';
18+
import { ReactComponent as CloudLightningIcon } from 'assets/icons/cloud-lightning.svg';
1819
import { ReactComponent as CopyIcon } from 'assets/icons/copy.svg';
1920
import { ReactComponent as DotIcon } from 'assets/icons/dot.svg';
2021
import { ReactComponent as DownloadIcon } from 'assets/icons/download.svg';
@@ -99,6 +100,7 @@ export const Chevrons = Icon.withComponent(ChevronsIcon);
99100
export const ChevronsLeft = Icon.withComponent(ChevronsLeftIcon);
100101
export const ChevronsRight = Icon.withComponent(ChevronsRightIcon);
101102
export const Close = Icon.withComponent(CloseIcon);
103+
export const CloudLightning = Icon.withComponent(CloudLightningIcon);
102104
export const Copy = Icon.withComponent(CopyIcon);
103105
export const Dot = Icon.withComponent(DotIcon);
104106
export const HelpCircle = Icon.withComponent(HelpCircleIcon);

app/src/components/base/shared.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,28 @@ export const Input = styled.input`
192192
}
193193
`;
194194

195+
export const TextArea = styled.textarea`
196+
font-family: ${props => props.theme.fonts.work.light};
197+
font-weight: 300;
198+
font-size: ${props => props.theme.sizes.m};
199+
color: ${props => props.theme.colors.offWhite};
200+
background-color: ${props => props.theme.colors.overlay};
201+
border-width: 0;
202+
border-bottom: 3px solid ${props => props.theme.colors.offWhite};
203+
padding: 5px;
204+
205+
&:active,
206+
&:focus {
207+
outline: none;
208+
background-color: ${props => props.theme.colors.overlay};
209+
border-bottom-color: ${props => props.theme.colors.white};
210+
}
211+
212+
&::placeholder {
213+
color: ${props => props.theme.colors.gray};
214+
}
215+
`;
216+
195217
//
196218
// Radio Button
197219
//

app/src/components/common/Wizard.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React from 'react';
2+
import { observer } from 'mobx-react-lite';
3+
import { usePrefixedTranslation } from 'hooks';
4+
import { ArrowLeft } from 'components/base';
5+
import Tip from 'components/common/Tip';
6+
import { styled } from 'components/theme';
7+
8+
const Styled = {
9+
Wrapper: styled.section<{ sidebar?: boolean }>`
10+
display: flex;
11+
min-height: 360px;
12+
padding: 30px;
13+
background-color: ${props => props.theme.colors.darkBlue};
14+
border-radius: 35px;
15+
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.5);
16+
margin-left: ${props => (props.sidebar ? '0' : '40px')};
17+
`,
18+
Nav: styled.div`
19+
width: 36px;
20+
`,
21+
Content: styled.div`
22+
flex-grow: 1;
23+
display: flex;
24+
align-items: stretch;
25+
flex-direction: row;
26+
`,
27+
};
28+
29+
interface Props {
30+
sidebar?: boolean;
31+
onBackClick?: () => void;
32+
}
33+
34+
const Wizard: React.FC<Props> = ({ sidebar, onBackClick, children }) => {
35+
const { l } = usePrefixedTranslation('cmps.common.Wizard');
36+
37+
const { Wrapper, Nav, Content } = Styled;
38+
return (
39+
<Wrapper sidebar={sidebar}>
40+
<Nav>
41+
<Tip overlay={l('backTip')}>
42+
<ArrowLeft onClick={onBackClick} />
43+
</Tip>
44+
</Nav>
45+
<Content>{children}</Content>
46+
</Wrapper>
47+
);
48+
};
49+
50+
export default observer(Wizard);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import styled from '@emotion/styled';
3+
import { usePrefixedTranslation } from 'hooks';
4+
import { Button } from 'components/base';
5+
6+
const Styled = {
7+
Wrapper: styled.div`
8+
display: flex;
9+
justify-content: flex-end;
10+
`,
11+
ExtraContent: styled.div`
12+
flex: 1;
13+
`,
14+
};
15+
16+
interface Props {
17+
onCancel: () => void;
18+
onNext: () => void;
19+
nextLabel?: string;
20+
extra?: React.ReactNode;
21+
}
22+
23+
const WizardButtons: React.FC<Props> = ({ onCancel, onNext, nextLabel, extra }) => {
24+
const { l } = usePrefixedTranslation('cmps.common.WizardButtons');
25+
26+
const { Wrapper, ExtraContent } = Styled;
27+
return (
28+
<Wrapper>
29+
<ExtraContent>{extra}</ExtraContent>
30+
<Button ghost borderless onClick={onCancel}>
31+
{l('common.cancel')}
32+
</Button>
33+
<Button primary ghost onClick={onNext}>
34+
{nextLabel || l('common.next')}
35+
</Button>
36+
</Wrapper>
37+
);
38+
};
39+
40+
export default WizardButtons;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React, { ReactNode } from 'react';
2+
import { HeaderFive, HeaderFour, Small } from 'components/base';
3+
import { styled } from 'components/theme';
4+
5+
const Styled = {
6+
Wrapper: styled.div`
7+
height: 100%;
8+
display: flex;
9+
flex-direction: column;
10+
justify-content: space-between;
11+
max-width: 300px;
12+
`,
13+
Description: styled(Small)`
14+
opacity: 0.5;
15+
`,
16+
Channels: styled.div`
17+
line-height: 40px;
18+
`,
19+
};
20+
21+
interface Props {
22+
title: string;
23+
heading: string;
24+
description?: string;
25+
extra?: ReactNode;
26+
}
27+
28+
const WizardSummary: React.FC<Props> = ({ title, heading, description, extra }) => {
29+
const { Wrapper, Description } = Styled;
30+
return (
31+
<Wrapper>
32+
<div>
33+
<HeaderFour>{title}</HeaderFour>
34+
<HeaderFive>{heading}</HeaderFive>
35+
{description && <Description>{description}</Description>}
36+
</div>
37+
<div>{extra}</div>
38+
</Wrapper>
39+
);
40+
};
41+
42+
export default WizardSummary;

app/src/components/loop/LoopActions.tsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { SwapDirection } from 'types/state';
44
import { usePrefixedTranslation } from 'hooks';
55
import { formatSats } from 'util/formatters';
66
import { useStore } from 'store';
7-
import { Button, Close, Refresh } from 'components/base';
7+
import { Button, Close, CloudLightning, Refresh } from 'components/base';
88
import { styled } from 'components/theme';
99
import SelectedChannels from './SelectedChannels';
1010

@@ -43,11 +43,16 @@ const Styled = {
4343
font-size: ${props => props.theme.sizes.s};
4444
color: ${props => props.theme.colors.gray};
4545
`,
46+
Buttons: styled.span`
47+
button:last-of-type {
48+
margin-left: 10px;
49+
}
50+
`,
4651
};
4752

4853
const LoopActions: React.FC = () => {
4954
const { l } = usePrefixedTranslation('cmps.loop.LoopActions');
50-
const { buildSwapView } = useStore();
55+
const { buildSwapView, registerSidecarView } = useStore();
5156
const {
5257
setDirection,
5358
inferredDirection,
@@ -69,7 +74,7 @@ const LoopActions: React.FC = () => {
6974
note = l('loopInNote');
7075
}
7176

72-
const { Wrapper, Actions, ActionBar, CloseIcon, Selected, Note } = Styled;
77+
const { Wrapper, Actions, ActionBar, CloseIcon, Selected, Note, Buttons } = Styled;
7378
return (
7479
<Wrapper data-tour="loop-actions">
7580
{buildSwapView.showActions ? (
@@ -102,10 +107,16 @@ const LoopActions: React.FC = () => {
102107
{note && <Note>{note}</Note>}
103108
</Actions>
104109
) : (
105-
<Button data-tour="loop" onClick={buildSwapView.startSwap}>
106-
<Refresh />
107-
{l('common.loop')}
108-
</Button>
110+
<Buttons>
111+
<Button data-tour="loop" onClick={buildSwapView.startSwap}>
112+
<Refresh />
113+
{l('common.loop')}
114+
</Button>
115+
<Button borderless onClick={registerSidecarView.startRegister}>
116+
<CloudLightning />
117+
{l('registerSidecar')}
118+
</Button>
119+
</Buttons>
109120
)}
110121
</Wrapper>
111122
);

app/src/components/loop/LoopPage.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import ChannelList from './ChannelList';
99
import LoopActions from './LoopActions';
1010
import LoopTiles from './LoopTiles';
1111
import ProcessingSwaps from './processing/ProcessingSwaps';
12+
import SidecarWizard from './sidecar/SidecarWizard';
1213
import SwapWizard from './swap/SwapWizard';
1314

1415
const Styled = {
@@ -19,7 +20,13 @@ const Styled = {
1920

2021
const LoopPage: React.FC = () => {
2122
const { l } = usePrefixedTranslation('cmps.loop.LoopPage');
22-
const { appView, buildSwapView, channelStore, nodeStore } = useStore();
23+
const {
24+
appView,
25+
buildSwapView,
26+
registerSidecarView,
27+
channelStore,
28+
nodeStore,
29+
} = useStore();
2330

2431
const title = (
2532
<>
@@ -39,6 +46,8 @@ const LoopPage: React.FC = () => {
3946
<ProcessingSwaps />
4047
) : buildSwapView.showWizard ? (
4148
<SwapWizard />
49+
) : registerSidecarView.showWizard ? (
50+
<SidecarWizard />
4251
) : (
4352
<>
4453
<PageHeader
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React from 'react';
2+
import { observer } from 'mobx-react-lite';
3+
import { usePrefixedTranslation } from 'hooks';
4+
import { useStore } from 'store';
5+
import WizardButtons from 'components/common/WizardButtons';
6+
import WizardSummary from 'components/common/WizardSummary';
7+
import { styled } from 'components/theme';
8+
9+
const Styled = {
10+
Wrapper: styled.div`
11+
flex-grow: 1;
12+
display: flex;
13+
justify-content: space-between;
14+
padding-top: 5px;
15+
`,
16+
Summary: styled.div`
17+
flex-grow: 1;
18+
display: flex;
19+
flex-direction: column;
20+
justify-content: space-between;
21+
`,
22+
Fields: styled.div`
23+
display: flex;
24+
flex-direction: column;
25+
justify-content: space-between;
26+
max-width: 50%;
27+
`,
28+
Input: styled.div`
29+
flex-grow: 1;
30+
display: flex;
31+
flex-direction: column;
32+
padding-bottom: 15px;
33+
34+
code {
35+
margin-top: 15px;
36+
word-break: break-all;
37+
background-color: ${props => props.theme.colors.overlay};
38+
padding: 15px;
39+
border-radius: 4px;
40+
}
41+
`,
42+
};
43+
44+
const ConfirmTicketStep: React.FC = () => {
45+
const { l } = usePrefixedTranslation('cmps.loop.sidecar.ConfirmTicketStep');
46+
const { registerSidecarView } = useStore();
47+
48+
const { Wrapper, Summary, Fields, Input } = Styled;
49+
return (
50+
<Wrapper>
51+
<Summary>
52+
<WizardSummary
53+
title={l('title')}
54+
heading={l('heading')}
55+
description={l('description')}
56+
/>
57+
</Summary>
58+
<Fields>
59+
<Input>
60+
<code>{registerSidecarView.ticket}</code>
61+
</Input>
62+
<WizardButtons
63+
onCancel={registerSidecarView.cancel}
64+
onNext={registerSidecarView.goToNextStep}
65+
nextLabel={l('common.confirm')}
66+
/>
67+
</Fields>
68+
</Wrapper>
69+
);
70+
};
71+
72+
export default observer(ConfirmTicketStep);

0 commit comments

Comments
 (0)