diff --git a/package.json b/package.json index 0c7ef06..351d9e6 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@storybook/react": "^6.4.22", "@storybook/testing-library": "^0.0.10", "@testing-library/react": "^12", + "@types/lodash": "^4.14.182", "@types/react": "<18.0.0", "@types/react-dom": "<18.0.0", "@typescript-eslint/eslint-plugin": "5.12.1", @@ -74,12 +75,15 @@ "dependencies": { "@mantine/core": "^4.1.2", "@mantine/dates": "^4.1.2", + "@mantine/form": "^4.2.2", "@mantine/hooks": "^4.1.2", "@mantine/modals": "^4.1.2", "@mantine/notifications": "^4.1.2", "dayjs": "^1.11.0", "electron-store": "^8.0.1", "electron-updater": "4.6.5", + "joi": "^17.6.0", + "lodash": "^4.17.21", "react": "<18.0.0", "react-dom": "<18.0.0", "react-intl": "^5.24.8", diff --git a/packages/renderer/assets/btc.svg b/packages/renderer/assets/btc.svg new file mode 100644 index 0000000..3ecff05 --- /dev/null +++ b/packages/renderer/assets/btc.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/renderer/assets/circle-plus.svg b/packages/renderer/assets/circle-plus.svg new file mode 100644 index 0000000..654dca5 --- /dev/null +++ b/packages/renderer/assets/circle-plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/renderer/assets/ellipsis.svg b/packages/renderer/assets/ellipsis.svg new file mode 100644 index 0000000..97a560a --- /dev/null +++ b/packages/renderer/assets/ellipsis.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/renderer/assets/eth.svg b/packages/renderer/assets/eth.svg new file mode 100644 index 0000000..20ac7d5 --- /dev/null +++ b/packages/renderer/assets/eth.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/renderer/assets/eur.svg b/packages/renderer/assets/eur.svg new file mode 100644 index 0000000..e8a9a4b --- /dev/null +++ b/packages/renderer/assets/eur.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/renderer/src/Routes.tsx b/packages/renderer/src/Routes.tsx index 105d5ca..f9d2a73 100644 --- a/packages/renderer/src/Routes.tsx +++ b/packages/renderer/src/Routes.tsx @@ -17,6 +17,7 @@ import { Routes, Route } from "react-router-dom"; import { Home, Welcome } from "@pages/Onboarding"; import { Wallet } from "@pages/Wallet"; +import { PaymentMethods, AddPaymentMethod } from "@pages/Account"; export const ROUTES = { Home: "/", @@ -24,6 +25,8 @@ export const ROUTES = { RestoreBackup: "/onboarding/restore-backup", SetupAccount: "/onboarding/setup", Wallet: "/wallet", + AccountPaymentMethods: "/account/payment-methods", + AccountAddPaymentMethod: "/account/payment-methods/add", }; export function AppRoutes() { @@ -32,6 +35,11 @@ export function AppRoutes() { } /> } /> } /> + } /> + } + /> ); } diff --git a/packages/renderer/src/components/atoms/ConnectionProgress/ConnectionProgress.tsx b/packages/renderer/src/components/atoms/ConnectionProgress/ConnectionProgress.tsx index 5fb06d7..93213b5 100644 --- a/packages/renderer/src/components/atoms/ConnectionProgress/ConnectionProgress.tsx +++ b/packages/renderer/src/components/atoms/ConnectionProgress/ConnectionProgress.tsx @@ -14,20 +14,17 @@ // limitations under the License. // ============================================================================= -import { Box, createStyles, keyframes, Stack, Text } from "@mantine/core"; -import { FormattedMessage } from "react-intl"; +import { Box, createStyles, keyframes, Stack } from "@mantine/core"; import { LangKeys } from "@constants/lang/LangKeys"; +import { BodyText } from "@atoms/Typography"; export function ConnectionProgress() { const { classes } = useStyles(); return ( - - - + + Connecting to Monero Network + diff --git a/packages/renderer/src/components/atoms/ConnectionProgress/__snapshots__/ConnectionProgress.test.tsx.snap b/packages/renderer/src/components/atoms/ConnectionProgress/__snapshots__/ConnectionProgress.test.tsx.snap index 4317a79..414953b 100644 --- a/packages/renderer/src/components/atoms/ConnectionProgress/__snapshots__/ConnectionProgress.test.tsx.snap +++ b/packages/renderer/src/components/atoms/ConnectionProgress/__snapshots__/ConnectionProgress.test.tsx.snap @@ -6,7 +6,7 @@ exports[`atoms::ConnectionProgress > renders without exploding 1`] = ` class="mantine-Stack-root mantine-njf2rt" >
Connecting to Monero Network
diff --git a/packages/renderer/src/components/atoms/Select/Select.stories.tsx b/packages/renderer/src/components/atoms/Select/Select.stories.tsx new file mode 100644 index 0000000..0dea878 --- /dev/null +++ b/packages/renderer/src/components/atoms/Select/Select.stories.tsx @@ -0,0 +1,68 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { Stack } from "@mantine/core"; +import type { ComponentStory, ComponentMeta } from "@storybook/react"; +import { Select } from "."; + +export default { + title: "atoms/Select", + component: Select, +} as ComponentMeta; + +const Template: ComponentStory = (args) => { + return ( + + + ); + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/packages/renderer/src/components/atoms/Select/Select.tsx b/packages/renderer/src/components/atoms/Select/Select.tsx new file mode 100644 index 0000000..4d047ee --- /dev/null +++ b/packages/renderer/src/components/atoms/Select/Select.tsx @@ -0,0 +1,84 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { useState, useMemo } from "react"; +import type { SelectProps as MSelectProps } from "@mantine/core"; +import { createStyles, Select as MSelect } from "@mantine/core"; +import { ReactComponent as ArrowIcon } from "@assets/arrow-down.svg"; + +interface SelectProps extends MSelectProps { + id: string; +} + +export function Select(props: SelectProps) { + const { clearable, value, onChange } = props; + const [isEmpty, setEmpty] = useState(!value); + const showClearButton = useMemo( + () => clearable === true && !isEmpty, + [clearable, isEmpty] + ); + const { classes } = useStyles({ showClearButton }); + + const handleChange = (value: string) => { + setEmpty(!value); + if (onChange) { + onChange(value); + } + }; + + return ( + + ) + } + withinPortal={false} + /> + ); +} + +const useStyles = createStyles( + (theme, params) => ({ + label: { + fontSize: "0.875rem", + fontWeight: 600, + marginBottom: theme.spacing.sm, + }, + input: { + fontSize: "0.875rem", + fontWeight: 700, + height: "3rem", + padding: "1rem", + }, + item: { + fontSize: "0.875rem", + fontWeight: 500, + padding: "1rem", + }, + ...(params.showClearButton + ? null + : { + rightSection: { pointerEvents: "none" }, + }), + arrowIcon: { + width: "0.5rem", + }, + }) +); diff --git a/packages/renderer/src/components/atoms/Select/__snapshots__/Select.test.tsx.snap b/packages/renderer/src/components/atoms/Select/__snapshots__/Select.test.tsx.snap new file mode 100644 index 0000000..fb182bf --- /dev/null +++ b/packages/renderer/src/components/atoms/Select/__snapshots__/Select.test.tsx.snap @@ -0,0 +1,65 @@ +// Vitest Snapshot v1 + +exports[`atoms::Select > renders without exploding 1`] = ` + +
+ + +
+
+`; diff --git a/packages/renderer/src/components/atoms/Select/index.ts b/packages/renderer/src/components/atoms/Select/index.ts new file mode 100644 index 0000000..f2e1fec --- /dev/null +++ b/packages/renderer/src/components/atoms/Select/index.ts @@ -0,0 +1,17 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +export * from "./Select"; diff --git a/packages/renderer/src/components/atoms/TextInput/TextInput.stories.tsx b/packages/renderer/src/components/atoms/TextInput/TextInput.stories.tsx new file mode 100644 index 0000000..1e7840b --- /dev/null +++ b/packages/renderer/src/components/atoms/TextInput/TextInput.stories.tsx @@ -0,0 +1,39 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { Stack } from "@mantine/core"; +import type { ComponentStory, ComponentMeta } from "@storybook/react"; +import { TextInput } from "."; + +export default { + title: "atoms/TextInput", + component: TextInput, +} as ComponentMeta; + +const Template: ComponentStory = (args) => { + return ( + + + + ); +}; + +export const Default = Template.bind({}); +Default.args = { + id: "email", + label: "Your email", + placeholder: "johndoe@gmail.com", +}; diff --git a/packages/renderer/src/components/atoms/TextInput/TextInput.test.tsx b/packages/renderer/src/components/atoms/TextInput/TextInput.test.tsx new file mode 100644 index 0000000..9a60f98 --- /dev/null +++ b/packages/renderer/src/components/atoms/TextInput/TextInput.test.tsx @@ -0,0 +1,33 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { describe, expect, it } from "vitest"; +import { render } from "@testing-library/react"; +import { TextInput } from "."; + +describe("atoms::TextInput", () => { + it("renders without exploding", () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/packages/renderer/src/components/atoms/TextInput/TextInput.tsx b/packages/renderer/src/components/atoms/TextInput/TextInput.tsx new file mode 100644 index 0000000..742f970 --- /dev/null +++ b/packages/renderer/src/components/atoms/TextInput/TextInput.tsx @@ -0,0 +1,42 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import type { TextInputProps as MTextInputProps } from "@mantine/core"; +import { createStyles, TextInput as MTextInput } from "@mantine/core"; + +interface TextInputProps extends MTextInputProps { + id: string; +} + +export function TextInput(props: TextInputProps) { + const { id, ...rest } = props; + const { classes } = useStyles(); + return ; +} + +const useStyles = createStyles((theme) => ({ + label: { + fontSize: "0.875rem", + fontWeight: 600, + marginBottom: theme.spacing.sm, + }, + input: { + fontSize: "0.875rem", + fontWeight: 700, + height: "3rem", + padding: "1rem", + }, +})); diff --git a/packages/renderer/src/components/atoms/TextInput/__snapshots__/TextInput.test.tsx.snap b/packages/renderer/src/components/atoms/TextInput/__snapshots__/TextInput.test.tsx.snap new file mode 100644 index 0000000..898d7b0 --- /dev/null +++ b/packages/renderer/src/components/atoms/TextInput/__snapshots__/TextInput.test.tsx.snap @@ -0,0 +1,28 @@ +// Vitest Snapshot v1 + +exports[`atoms::TextInput > renders without exploding 1`] = ` + +
+ +
+ +
+
+
+`; diff --git a/packages/renderer/src/components/atoms/TextInput/index.ts b/packages/renderer/src/components/atoms/TextInput/index.ts new file mode 100644 index 0000000..0825f80 --- /dev/null +++ b/packages/renderer/src/components/atoms/TextInput/index.ts @@ -0,0 +1,17 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +export * from "./TextInput"; diff --git a/packages/renderer/src/components/atoms/Typography/BodyText.stories.tsx b/packages/renderer/src/components/atoms/Typography/BodyText.stories.tsx new file mode 100644 index 0000000..bc70aeb --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/BodyText.stories.tsx @@ -0,0 +1,37 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { Stack } from "@mantine/core"; +import type { ComponentStory, ComponentMeta } from "@storybook/react"; +import { BodyText } from "."; + +export default { + title: "atoms/Typography/ BodyText", + component: BodyText, +} as ComponentMeta; + +const Template: ComponentStory = (args) => { + return ( + + Body Text + + ); +}; + +export const Default = Template.bind({}); +Default.args = { + heavy: false, +}; diff --git a/packages/renderer/src/components/atoms/Typography/Heading.stories.tsx b/packages/renderer/src/components/atoms/Typography/Heading.stories.tsx new file mode 100644 index 0000000..d71c5a8 --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/Heading.stories.tsx @@ -0,0 +1,46 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { Stack } from "@mantine/core"; +import type { ComponentStory, ComponentMeta } from "@storybook/react"; +import { Heading } from "."; + +export default { + title: "atoms/Typography/Heading", + component: Heading, + argTypes: { + order: { + options: [1, 2, 3, 4, 5], + control: { + type: "radio", + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => { + return ( + + + + ); +}; + +export const Default = Template.bind({}); +Default.args = { + order: 1, + children: "This is a heading", +}; diff --git a/packages/renderer/src/components/atoms/Typography/Heading.tsx b/packages/renderer/src/components/atoms/Typography/Heading.tsx new file mode 100644 index 0000000..d0e2cbf --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/Heading.tsx @@ -0,0 +1,40 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import type { ReactText } from "react"; +import { FormattedMessage } from "react-intl"; +import type { TitleProps } from "@mantine/core"; +import { Title } from "@mantine/core"; +import type { LangKeys } from "@constants/lang"; + +interface HeadingProps extends TitleProps { + children: ReactText; + stringId?: LangKeys; +} + +export function Heading(props: HeadingProps) { + const { children, stringId, ...rest } = props; + + return ( + + {stringId ? ( + <FormattedMessage id={stringId} defaultMessage={children.toString()} /> + ) : ( + children + )} + + ); +} diff --git a/packages/renderer/src/components/atoms/Typography/InfoText.stories.tsx b/packages/renderer/src/components/atoms/Typography/InfoText.stories.tsx new file mode 100644 index 0000000..b9c6285 --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/InfoText.stories.tsx @@ -0,0 +1,35 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { Stack } from "@mantine/core"; +import type { ComponentStory, ComponentMeta } from "@storybook/react"; +import { InfoText } from "."; + +export default { + title: "atoms/Typography/InfoText", + component: InfoText, +} as ComponentMeta; + +const Template: ComponentStory = (args) => { + return ( + + Info Text + + ); +}; + +export const Default = Template.bind({}); +Default.args = {}; diff --git a/packages/renderer/src/components/atoms/Typography/LabelText.stories.tsx b/packages/renderer/src/components/atoms/Typography/LabelText.stories.tsx new file mode 100644 index 0000000..3e8a324 --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/LabelText.stories.tsx @@ -0,0 +1,35 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { Stack } from "@mantine/core"; +import type { ComponentStory, ComponentMeta } from "@storybook/react"; +import { LabelText } from "."; + +export default { + title: "atoms/Typography/LabelText", + component: LabelText, +} as ComponentMeta; + +const Template: ComponentStory = (args) => { + return ( + + Label Text + + ); +}; + +export const Default = Template.bind({}); +Default.args = {}; diff --git a/packages/renderer/src/components/atoms/Typography/Text.tsx b/packages/renderer/src/components/atoms/Typography/Text.tsx new file mode 100644 index 0000000..966d6e3 --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/Text.tsx @@ -0,0 +1,101 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import type { ReactText } from "react"; +import { FormattedMessage } from "react-intl"; +import type { TextProps as MTextProps } from "@mantine/core"; +import { Text as MText, createStyles } from "@mantine/core"; +import type { LangKeys } from "@constants/lang"; + +type TextProps = MTextProps & { + children: ReactText; + stringId?: LangKeys; +}; + +type BodyTextProps = TextProps & { + heavy?: boolean; +}; + +export function BodyText(props: BodyTextProps) { + const { children, className, heavy, size, stringId, ...rest } = props; + const { classes, cx } = useStyles(); + + return ( + + {stringId ? ( + + ) : ( + children + )} + + ); +} + +export function InfoText(props: TextProps) { + const { children, className, stringId, ...rest } = props; + const { classes, cx } = useStyles(); + + return ( + + {stringId ? ( + + ) : ( + children + )} + + ); +} + +export function LabelText(props: TextProps<"label">) { + const { children, className, stringId, ...rest } = props; + const { classes, cx } = useStyles(); + + return ( + + {stringId ? ( + + ) : ( + children + )} + + ); +} + +const useStyles = createStyles((theme) => ({ + info: { + color: theme.colors.gray[6], + fontSize: "0.875rem", + }, + body: { + fontSize: "0.8125rem", + }, + bodyHeavy: { + fontWeight: 500, + }, + bodyLg: { + fontSize: "1rem", + fontWeight: 500, + }, + label: {}, +})); diff --git a/packages/renderer/src/components/atoms/Typography/Typography.test.tsx b/packages/renderer/src/components/atoms/Typography/Typography.test.tsx new file mode 100644 index 0000000..1939253 --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/Typography.test.tsx @@ -0,0 +1,57 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { describe, expect, it } from "vitest"; +import { render } from "@testing-library/react"; +import { BodyText, Heading, InfoText, LabelText } from "."; + +describe("atoms::Typography", () => { + describe("::BodyText", () => { + it("renders without exploding", () => { + const { asFragment } = render(body text); + expect(asFragment()).toMatchSnapshot(); + }); + it("renders heavy variant exploding", () => { + const { asFragment } = render(body text); + expect(asFragment()).toMatchSnapshot(); + }); + }); + + describe("::Heading", () => { + it("renders h1 by default", () => { + const { asFragment } = render(heading text); + expect(asFragment()).toMatchSnapshot(); + }); + it("renders h2", () => { + const { asFragment } = render(heading text); + expect(asFragment()).toMatchSnapshot(); + }); + }); + + describe("::InfoText", () => { + it("renders without exploding", () => { + const { asFragment } = render(Info text); + expect(asFragment()).toMatchSnapshot(); + }); + }); + + describe("::LabelText", () => { + it("renders without exploding", () => { + const { asFragment } = render(Label text); + expect(asFragment()).toMatchSnapshot(); + }); + }); +}); diff --git a/packages/renderer/src/components/atoms/Typography/__snapshots__/Typography.test.tsx.snap b/packages/renderer/src/components/atoms/Typography/__snapshots__/Typography.test.tsx.snap new file mode 100644 index 0000000..077f65e --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/__snapshots__/Typography.test.tsx.snap @@ -0,0 +1,71 @@ +// Vitest Snapshot v1 + +exports[`atoms::Typography > ::BodyText > renders heavy variant exploding 1`] = ` + +
+ body text +
+
+`; + +exports[`atoms::Typography > ::BodyText > renders without exploding 1`] = ` + +
+ body text +
+
+`; + +exports[`atoms::Typography > ::Heading > renders h1 1`] = ` + +

+ heading text +

+
+`; + +exports[`atoms::Typography > ::Heading > renders h1 by default 1`] = ` + +

+ heading text +

+
+`; + +exports[`atoms::Typography > ::Heading > renders h2 1`] = ` + +

+ heading text +

+
+`; + +exports[`atoms::Typography > ::InfoText > renders without exploding 1`] = ` + +
+ Info text +
+
+`; + +exports[`atoms::Typography > ::LabelText > renders without exploding 1`] = ` + + + +`; diff --git a/packages/renderer/src/components/atoms/Typography/index.ts b/packages/renderer/src/components/atoms/Typography/index.ts new file mode 100644 index 0000000..3c45e15 --- /dev/null +++ b/packages/renderer/src/components/atoms/Typography/index.ts @@ -0,0 +1,18 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +export * from "./Heading"; +export * from "./Text"; diff --git a/packages/renderer/src/components/molecules/PaymentMethodCard/AddPaymentMethodButton.tsx b/packages/renderer/src/components/molecules/PaymentMethodCard/AddPaymentMethodButton.tsx new file mode 100644 index 0000000..d524651 --- /dev/null +++ b/packages/renderer/src/components/molecules/PaymentMethodCard/AddPaymentMethodButton.tsx @@ -0,0 +1,55 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { createStyles, UnstyledButton } from "@mantine/core"; +import { ReactComponent as AddIcon } from "@assets/circle-plus.svg"; +import { HEIGHT, WIDTH } from "./_constants"; + +interface AddCardProps { + onClick: () => void; +} + +export function AddPaymentMethodButton({ onClick }: AddCardProps) { + const { classes } = useStyles(); + + return ( + + + + ); +} + +const useStyles = createStyles((theme) => ({ + card: { + background: theme.colors.gray[2], + borderRadius: "0.625rem", + display: "grid", + height: HEIGHT, + opacity: 0.75, + placeContent: "center", + transition: "opacity 0.2s", + width: WIDTH, + + "&:hover": { + opacity: 1, + }, + + "& svg": { + height: "1.75rem", + width: "1.75rem", + }, + }, +})); diff --git a/packages/renderer/src/components/molecules/PaymentMethodCard/PaymentMethodCard.tsx b/packages/renderer/src/components/molecules/PaymentMethodCard/PaymentMethodCard.tsx new file mode 100644 index 0000000..95aa1c6 --- /dev/null +++ b/packages/renderer/src/components/molecules/PaymentMethodCard/PaymentMethodCard.tsx @@ -0,0 +1,81 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { + Box, + createStyles, + Group, + Stack, + Text, + UnstyledButton, +} from "@mantine/core"; +import { ReactComponent as MenuIcon } from "@assets/ellipsis.svg"; +import { HEIGHT, WIDTH, CurrencyLogos } from "./_constants"; +import type { SupportedCurrencies } from "./_types"; +import { BodyText } from "@atoms/Typography"; +import { useMemo } from "react"; + +interface PaymentMethodCardProps { + currency: SupportedCurrencies; + accountId: string; +} + +export function PaymentMethodCard(props: PaymentMethodCardProps) { + const { accountId, currency } = props; + const { classes } = useStyles(); + + const Logo = useMemo(() => CurrencyLogos[currency].Logo, [currency]); + + return ( + + + + + + {CurrencyLogos[currency].name} + + + + + + + {accountId} + + + + ); +} + +const useStyles = createStyles((theme) => ({ + card: { + background: theme.colors.white[0], + border: `solid 1px ${theme.colors.gray[2]}`, + borderRadius: "0.625rem", + height: HEIGHT, + padding: "1.25rem", + width: WIDTH, + }, + logo: { + height: "1.75rem", + width: "1.75rem", + }, + name: { + color: theme.colors.gray[6], + }, + menuIcon: { + width: "1rem", + }, +})); diff --git a/packages/renderer/src/components/molecules/PaymentMethodCard/_constants.ts b/packages/renderer/src/components/molecules/PaymentMethodCard/_constants.ts new file mode 100644 index 0000000..3d6c808 --- /dev/null +++ b/packages/renderer/src/components/molecules/PaymentMethodCard/_constants.ts @@ -0,0 +1,44 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import type { FC } from "react"; +import { ReactComponent as BtcLogo } from "@assets/btc.svg"; +import { ReactComponent as EthLogo } from "@assets/eth.svg"; +import { ReactComponent as EurLogo } from "@assets/eur.svg"; +import type { SupportedCurrencies } from "./_types"; + +export const WIDTH = "17rem"; +export const HEIGHT = "7.25rem"; + +interface CurrencyDetails { + Logo: FC; // eslint-disable-line @typescript-eslint/no-explicit-any + name: string; +} + +export const CurrencyLogos: Record = { + BTC: { + Logo: BtcLogo, + name: "Bitcoin", + }, + ETH: { + Logo: EthLogo, + name: "Ethereum", + }, + EUR: { + Logo: EurLogo, + name: "Euro", + }, +}; diff --git a/packages/renderer/src/components/molecules/PaymentMethodCard/_types.ts b/packages/renderer/src/components/molecules/PaymentMethodCard/_types.ts new file mode 100644 index 0000000..20ae83d --- /dev/null +++ b/packages/renderer/src/components/molecules/PaymentMethodCard/_types.ts @@ -0,0 +1,17 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +export type SupportedCurrencies = "BTC" | "ETH" | "EUR"; diff --git a/packages/renderer/src/components/molecules/PaymentMethodCard/index.ts b/packages/renderer/src/components/molecules/PaymentMethodCard/index.ts new file mode 100644 index 0000000..1238451 --- /dev/null +++ b/packages/renderer/src/components/molecules/PaymentMethodCard/index.ts @@ -0,0 +1,18 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +export * from "./AddPaymentMethodButton"; +export * from "./PaymentMethodCard"; diff --git a/packages/renderer/src/components/molecules/WalletBalance/__snapshots__/WalletBalance.test.tsx.snap b/packages/renderer/src/components/molecules/WalletBalance/__snapshots__/WalletBalance.test.tsx.snap index f7a0e97..ce4ebdd 100644 --- a/packages/renderer/src/components/molecules/WalletBalance/__snapshots__/WalletBalance.test.tsx.snap +++ b/packages/renderer/src/components/molecules/WalletBalance/__snapshots__/WalletBalance.test.tsx.snap @@ -3,7 +3,7 @@ exports[`molecules::WalletBalance > renders without exploding 1`] = ` + +
+ + + +
+ ); +} + +const schema = Joi.object({ + currency: Joi.string().required(), + paymentMethod: Joi.string().required(), + accountNumber: Joi.string().required(), +}); + +const Currencies = SupportedCurrencies.map((curr) => ({ + value: curr.id, + label: curr.name, +})); diff --git a/packages/renderer/src/components/organisms/AddPaymentMethod/__snapshots__/AddPaymentMethod.test.tsx.snap b/packages/renderer/src/components/organisms/AddPaymentMethod/__snapshots__/AddPaymentMethod.test.tsx.snap new file mode 100644 index 0000000..b5cc09c --- /dev/null +++ b/packages/renderer/src/components/organisms/AddPaymentMethod/__snapshots__/AddPaymentMethod.test.tsx.snap @@ -0,0 +1,199 @@ +// Vitest Snapshot v1 + +exports[`organisms::AddPaymentMethod > renders without exploding 1`] = ` + +
+
+
+
+ + +
+ + +
+ +
+
+
+
+
+
+ +`; diff --git a/packages/renderer/src/components/organisms/AddPaymentMethod/index.ts b/packages/renderer/src/components/organisms/AddPaymentMethod/index.ts new file mode 100644 index 0000000..2c2e99a --- /dev/null +++ b/packages/renderer/src/components/organisms/AddPaymentMethod/index.ts @@ -0,0 +1,17 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +export * from "./AddPaymentMethod"; diff --git a/packages/renderer/src/components/organisms/PaymentMethodList/PaymentMethodList.stories.tsx b/packages/renderer/src/components/organisms/PaymentMethodList/PaymentMethodList.stories.tsx new file mode 100644 index 0000000..ef87737 --- /dev/null +++ b/packages/renderer/src/components/organisms/PaymentMethodList/PaymentMethodList.stories.tsx @@ -0,0 +1,32 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import type { ComponentStory, ComponentMeta } from "@storybook/react"; +import { PaymentMethodList } from "."; + +export default { + title: "organisms/Payment Method List", + component: PaymentMethodList, +} as ComponentMeta; + +const Template: ComponentStory = (args) => { + return ; +}; + +export const Default = Template.bind({}); +Default.args = { + onAdd: () => console.log("onAdd called"), +}; diff --git a/packages/renderer/src/components/organisms/PaymentMethodList/PaymentMethodList.tsx b/packages/renderer/src/components/organisms/PaymentMethodList/PaymentMethodList.tsx new file mode 100644 index 0000000..6bf6ad0 --- /dev/null +++ b/packages/renderer/src/components/organisms/PaymentMethodList/PaymentMethodList.tsx @@ -0,0 +1,51 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +import { Group, Space, Stack } from "@mantine/core"; +import { Heading, BodyText } from "@atoms/Typography"; +import { + AddPaymentMethodButton, + PaymentMethodCard, +} from "@molecules/PaymentMethodCard"; + +interface PaymentMethodsProps { + onAdd: () => void; +} + +export function PaymentMethodList({ onAdd }: PaymentMethodsProps) { + return ( + + + Your available payment accounts + + To engage in trades you need payment methods to support these trades. + The payment methods are stored locally on your device and details are + only shown to counter parties in trades when needed. + + + + + + + + + + + ); +} diff --git a/packages/renderer/src/components/organisms/PaymentMethodList/index.ts b/packages/renderer/src/components/organisms/PaymentMethodList/index.ts new file mode 100644 index 0000000..4e04db4 --- /dev/null +++ b/packages/renderer/src/components/organisms/PaymentMethodList/index.ts @@ -0,0 +1,17 @@ +// ============================================================================= +// Copyright 2022 Haveno +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +export * from "./PaymentMethodList"; diff --git a/packages/renderer/src/components/molecules/Sidebar/Sidebar.stories.tsx b/packages/renderer/src/components/organisms/Sidebar/Sidebar.stories.tsx similarity index 97% rename from packages/renderer/src/components/molecules/Sidebar/Sidebar.stories.tsx rename to packages/renderer/src/components/organisms/Sidebar/Sidebar.stories.tsx index 44d13c6..c28e6d1 100644 --- a/packages/renderer/src/components/molecules/Sidebar/Sidebar.stories.tsx +++ b/packages/renderer/src/components/organisms/Sidebar/Sidebar.stories.tsx @@ -19,7 +19,7 @@ import type { ComponentStory, ComponentMeta } from "@storybook/react"; import { Sidebar } from "."; export default { - title: "molecules/Sidebar", + title: "organisms/Sidebar", component: Sidebar, } as ComponentMeta; diff --git a/packages/renderer/src/components/molecules/Sidebar/Sidebar.test.tsx b/packages/renderer/src/components/organisms/Sidebar/Sidebar.test.tsx similarity index 100% rename from packages/renderer/src/components/molecules/Sidebar/Sidebar.test.tsx rename to packages/renderer/src/components/organisms/Sidebar/Sidebar.test.tsx diff --git a/packages/renderer/src/components/molecules/Sidebar/Sidebar.tsx b/packages/renderer/src/components/organisms/Sidebar/Sidebar.tsx similarity index 96% rename from packages/renderer/src/components/molecules/Sidebar/Sidebar.tsx rename to packages/renderer/src/components/organisms/Sidebar/Sidebar.tsx index 8c7f2cf..3ee1c0b 100644 --- a/packages/renderer/src/components/molecules/Sidebar/Sidebar.tsx +++ b/packages/renderer/src/components/organisms/Sidebar/Sidebar.tsx @@ -24,7 +24,7 @@ export function Sidebar() { const { classes } = useStyles(); return ( - + diff --git a/packages/renderer/src/components/molecules/Sidebar/_NavLink.tsx b/packages/renderer/src/components/organisms/Sidebar/_NavLink.tsx similarity index 97% rename from packages/renderer/src/components/molecules/Sidebar/_NavLink.tsx rename to packages/renderer/src/components/organisms/Sidebar/_NavLink.tsx index 86b6fba..70e23f4 100644 --- a/packages/renderer/src/components/molecules/Sidebar/_NavLink.tsx +++ b/packages/renderer/src/components/organisms/Sidebar/_NavLink.tsx @@ -34,7 +34,6 @@ export function NavLink({ icon, isActive = false, label }: NavLinkProps) { color="gray" size="xs" transform="uppercase" - weight={700} > {label} @@ -81,7 +80,8 @@ const useStyles = createStyles( theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.dark[8], - + fontSize: "0.6875rem", + fontWeight: 700, transition: "opacity 0.2s", }, }) diff --git a/packages/renderer/src/components/molecules/Sidebar/__snapshots__/Sidebar.test.tsx.snap b/packages/renderer/src/components/organisms/Sidebar/__snapshots__/Sidebar.test.tsx.snap similarity index 93% rename from packages/renderer/src/components/molecules/Sidebar/__snapshots__/Sidebar.test.tsx.snap rename to packages/renderer/src/components/organisms/Sidebar/__snapshots__/Sidebar.test.tsx.snap index d9cabeb..105e07a 100644 --- a/packages/renderer/src/components/molecules/Sidebar/__snapshots__/Sidebar.test.tsx.snap +++ b/packages/renderer/src/components/organisms/Sidebar/__snapshots__/Sidebar.test.tsx.snap @@ -6,7 +6,7 @@ exports[`molecules::Sidebar > renders without exploding 1`] = ` class="mantine-Stack-root mantine-dczm8e" >