mirror of
https://github.com/haveno-dex/haveno-ui.git
synced 2025-07-08 16:09:35 -04:00
chore(MarketOffers): Implement the market offers filter.
This commit is contained in:
parent
07a984bb52
commit
f1dad626aa
19 changed files with 539 additions and 1 deletions
|
@ -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 { ComponentStory, ComponentMeta } from "@storybook/react";
|
||||
import { MarketoffersSelectPaymentMethods } from ".";
|
||||
|
||||
export default {
|
||||
title: "molecules/MarketoffersSelectPaymentMethods",
|
||||
component: MarketoffersSelectPaymentMethods,
|
||||
} as ComponentMeta<typeof MarketoffersSelectPaymentMethods>;
|
||||
|
||||
const Template: ComponentStory<
|
||||
typeof MarketoffersSelectPaymentMethods
|
||||
> = () => {
|
||||
return <MarketoffersSelectPaymentMethods data={data} />;
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
||||
Default.args = {};
|
||||
|
||||
const data = [
|
||||
{
|
||||
method: "Celpay",
|
||||
rateTradeLimit: 20,
|
||||
rateTradeLimitCurrency: "XMR",
|
||||
info: "Global",
|
||||
},
|
||||
];
|
|
@ -0,0 +1,54 @@
|
|||
import { createTable } from "@tanstack/react-table";
|
||||
import { createStyles } from "@mantine/core";
|
||||
import { Table } from "@molecules/Table";
|
||||
|
||||
const table = createTable().setRowType<TMarketOfferPaymentMethod>();
|
||||
|
||||
interface MarketoffersSelectPaymentMethods {
|
||||
data: TMarketOfferPaymentMethod[];
|
||||
}
|
||||
|
||||
export function MarketoffersSelectPaymentMethods({
|
||||
data,
|
||||
}: MarketoffersSelectPaymentMethods) {
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<Table
|
||||
table={table}
|
||||
columns={columns}
|
||||
data={data}
|
||||
tableWrap={{
|
||||
verticalSpacing: "xs",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const columns = [
|
||||
table.createDataColumn("method", {
|
||||
id: "method",
|
||||
header: "Method",
|
||||
}),
|
||||
table.createDataColumn("rateTradeLimit", {
|
||||
id: "rateTradeLimit",
|
||||
header: "Per Trade Limit",
|
||||
size: 400,
|
||||
}),
|
||||
table.createDataColumn("info", {
|
||||
id: "info",
|
||||
header: "Info",
|
||||
size: 400,
|
||||
})
|
||||
];
|
||||
|
||||
export interface TMarketOfferPaymentMethod {
|
||||
method: string;
|
||||
rateTradeLimit: number;
|
||||
rateTradeLimitCurrency: string;
|
||||
info: string;
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
root: {},
|
||||
}));
|
|
@ -0,0 +1 @@
|
|||
export * from "./MarketOffersSelectPaymentMethods";
|
|
@ -0,0 +1,45 @@
|
|||
// =============================================================================
|
||||
// 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 {
|
||||
MarketOffersTradingPairTable,
|
||||
TMarketOffersTradingPair,
|
||||
} from "./MarketOffersTradingPairTable";
|
||||
|
||||
export default {
|
||||
title: "molecules/MarketOffersTradingPairTable",
|
||||
component: MarketOffersTradingPairTable,
|
||||
} as ComponentMeta<typeof MarketOffersTradingPairTable>;
|
||||
|
||||
const Template: ComponentStory<typeof MarketOffersTradingPairTable> = () => {
|
||||
return <MarketOffersTradingPairTable data={data} />;
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
||||
Default.args = {};
|
||||
|
||||
const data = [
|
||||
{
|
||||
fromPair: "EUR",
|
||||
toPair: "XMR",
|
||||
lastPrice: 101.122,
|
||||
lastPriceCurrency: "EUR",
|
||||
dayChangeRate: 12.12,
|
||||
dayChangeVolume: 1222.123,
|
||||
},
|
||||
] as TMarketOffersTradingPair;
|
|
@ -0,0 +1,61 @@
|
|||
import { createTable } from "@tanstack/react-table";
|
||||
import { createStyles } from "@mantine/core";
|
||||
import { Table } from "@molecules/Table";
|
||||
|
||||
const table = createTable().setRowType<TMarketOffersTradingPair>();
|
||||
|
||||
interface MarketOffersTradingPairTableProps {
|
||||
data: TMarketOffersTradingPair[];
|
||||
}
|
||||
|
||||
export function MarketOffersTradingPairTable({
|
||||
data,
|
||||
}: MarketOffersTradingPairTableProps) {
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<Table
|
||||
table={table}
|
||||
columns={columns}
|
||||
data={data}
|
||||
tableWrap={{
|
||||
verticalSpacing: "xs",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const columns = [
|
||||
table.createDataColumn("fromPair", {
|
||||
id: "pair",
|
||||
header: "Pair",
|
||||
}),
|
||||
table.createDataColumn("lastPrice", {
|
||||
id: "lastPrice",
|
||||
header: "Last Price",
|
||||
size: 400,
|
||||
}),
|
||||
table.createDataColumn("dayChangeRate", {
|
||||
id: "lastPrice",
|
||||
header: "24th Change",
|
||||
size: 400,
|
||||
}),
|
||||
table.createDataColumn("dayChangeVolume", {
|
||||
id: "lastPrice",
|
||||
header: "24h Vol",
|
||||
size: 400,
|
||||
}),
|
||||
];
|
||||
|
||||
export interface TMarketOffersTradingPair {
|
||||
fromPair: string;
|
||||
toPair: string;
|
||||
lastPrice: number;
|
||||
lastPriceCurrency: number;
|
||||
dayChangeRate: number;
|
||||
dayChangeVolume: number;
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
root: {},
|
||||
}));
|
|
@ -0,0 +1,30 @@
|
|||
// =============================================================================
|
||||
// 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 { MarketOffersFilterAmountForm } from "./MarketOffersFilterAmountForm";
|
||||
|
||||
export default {
|
||||
title: "organisms/MarketOffersFilterAmountForm",
|
||||
component: MarketOffersFilterAmountForm,
|
||||
} as ComponentMeta<typeof MarketOffersFilterAmountForm>;
|
||||
|
||||
const Template: ComponentStory<typeof MarketOffersFilterAmountForm> = () => {
|
||||
return <MarketOffersFilterAmountForm />;
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
|
@ -0,0 +1,87 @@
|
|||
import { TextInput } from "@atoms/TextInput";
|
||||
import { Box, Grid, Text } from "@mantine/core";
|
||||
import { useForm } from "@mantine/hooks";
|
||||
|
||||
export function MarketOffersFilterAmountForm() {
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
minAmountFrom: null,
|
||||
minAmountTo: null,
|
||||
maxAmountFrom: null,
|
||||
maxAmountTo: null,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={form.onSubmit((values: MarketOffersFilterAmountFormValues) =>
|
||||
console.log(values)
|
||||
)}
|
||||
>
|
||||
<Grid>
|
||||
<Grid.Col span={8}>
|
||||
<Text weight={500}>Minimum amount</Text>
|
||||
<Text color="gray">Set the minimum amount you want to buy.</Text>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={4}>
|
||||
<TextInput
|
||||
id={"minAmountFrom"}
|
||||
{...form.getInputProps("minAmountFrom")}
|
||||
rightSection={
|
||||
<Text mr="xl" color="gray">
|
||||
EUR
|
||||
</Text>
|
||||
}
|
||||
mb="lg"
|
||||
/>
|
||||
<TextInput
|
||||
id={"minAmountTo"}
|
||||
{...form.getInputProps("minAmountTo")}
|
||||
rightSection={
|
||||
<Text mr="xl" color="gray">
|
||||
XMR
|
||||
</Text>
|
||||
}
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
<Grid mt="xl">
|
||||
<Grid.Col span={8}>
|
||||
<Text weight={500}>Maximum amount</Text>
|
||||
<Text color="gray">Set the maximum amount you want to buy.</Text>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={4}>
|
||||
<TextInput
|
||||
id={"maxAmountFrom"}
|
||||
{...form.getInputProps("maxAmountFrom")}
|
||||
rightSection={
|
||||
<Text mr="xl" color="gray">
|
||||
XMR
|
||||
</Text>
|
||||
}
|
||||
mb="lg"
|
||||
/>
|
||||
<TextInput
|
||||
id={"maxAmountTo"}
|
||||
{...form.getInputProps("maxAmountTo")}
|
||||
rightSection={
|
||||
<Text mr="xl" color="gray">
|
||||
EUR
|
||||
</Text>
|
||||
}
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
interface MarketOffersFilterAmountFormValues {
|
||||
maxAmountTo: string;
|
||||
maxAmountFrom: string;
|
||||
minAmountTo: string;
|
||||
minAmountFrom: string;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// =============================================================================
|
||||
// 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 { MarketOffersFilterBar } from ".";
|
||||
|
||||
export default {
|
||||
title: "organisms/MarketOffersFilterBar",
|
||||
component: MarketOffersFilterBar,
|
||||
} as ComponentMeta<typeof MarketOffersFilterBar>;
|
||||
|
||||
const Template: ComponentStory<typeof MarketOffersFilterBar> = () => {
|
||||
return <MarketOffersFilterBar />;
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
|
@ -0,0 +1,123 @@
|
|||
import { LangKeys } from "@constants/lang";
|
||||
import { Divider, Group, Button, createStyles } from "@mantine/core";
|
||||
import { useModals } from "@mantine/modals";
|
||||
import { MarketOffersTradingPair } from "@organisms/MarketOffersTradingPair";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
export function MarketOffersFilterBar() {
|
||||
const { classes } = useStyles();
|
||||
const modals = useModals();
|
||||
|
||||
const handlePairsBtnClick = () => {
|
||||
modals.openConfirmModal({
|
||||
title: "Select trading pair",
|
||||
children: <MarketOffersTradingPair />,
|
||||
size: 570,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Group position="apart" className={classes.root}>
|
||||
<Group>
|
||||
<Button radius="md" size="md">
|
||||
XMR/EUR
|
||||
</Button>
|
||||
|
||||
<Divider className={classes.divider} orientation="vertical" />
|
||||
<Button
|
||||
color="gray"
|
||||
variant="outline"
|
||||
radius="md"
|
||||
size="md"
|
||||
classNames={{ root: classes.buttonBold, label: classes.buttonLabel }}
|
||||
onClick={handlePairsBtnClick}
|
||||
>
|
||||
XMR/EUR
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
color="gray"
|
||||
variant="outline"
|
||||
radius="md"
|
||||
size="md"
|
||||
classNames={{ root: classes.buttonBold, label: classes.buttonLabel }}
|
||||
>
|
||||
<FormattedMessage
|
||||
id={LangKeys.MarketOffersAmount}
|
||||
defaultMessage={"Amount"}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
color="gray"
|
||||
variant="outline"
|
||||
radius="md"
|
||||
size="md"
|
||||
classNames={{ label: classes.buttonLabel }}
|
||||
>
|
||||
<FormattedMessage
|
||||
id={LangKeys.MarketOffersAccountDetails}
|
||||
defaultMessage={"Payment method"}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
color="gray"
|
||||
variant="outline"
|
||||
radius="md"
|
||||
size="md"
|
||||
classNames={{ label: classes.buttonLabel }}
|
||||
>
|
||||
<FormattedMessage
|
||||
id={LangKeys.MarketOffersAccountDetails}
|
||||
defaultMessage={"Account details"}
|
||||
/>
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
<Button
|
||||
variant="outline"
|
||||
color="dark"
|
||||
radius="md"
|
||||
size="md"
|
||||
classNames={{
|
||||
root: classes.buttonBold,
|
||||
}}
|
||||
>
|
||||
Show market depth
|
||||
</Button>
|
||||
|
||||
<Button radius="md" size="md">
|
||||
<FormattedMessage
|
||||
id={LangKeys.MarketOffersCreateOffer}
|
||||
defaultMessage={"Create Offer"}
|
||||
/>
|
||||
</Button>
|
||||
</Group>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
root: {
|
||||
minHeight: 84,
|
||||
padding: 15,
|
||||
borderBottom: `1px solid ${theme.colors.gray[3]}`,
|
||||
},
|
||||
button: {
|
||||
borderColor: "#E8E7EC",
|
||||
},
|
||||
buttonLabel: {
|
||||
color: "#111",
|
||||
},
|
||||
buttonBold: {
|
||||
borderWidth: 2,
|
||||
borderColor: "#111",
|
||||
},
|
||||
divider: {
|
||||
marginTop: "auto",
|
||||
marginBottom: "auto",
|
||||
height: 28,
|
||||
},
|
||||
}));
|
|
@ -0,0 +1 @@
|
|||
export * from "./MarketoffersFilterBar";
|
|
@ -0,0 +1,17 @@
|
|||
import { FC } from "react";
|
||||
|
||||
export function MarketOffersTradingPair() {
|
||||
return (
|
||||
<MarketOffersTradingPairBoot>
|
||||
<MarketOffersTradingPairLoaded />
|
||||
</MarketOffersTradingPairBoot>
|
||||
);
|
||||
}
|
||||
|
||||
const MarketOffersTradingPairLoaded: FC = ({ children }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
const MarketOffersTradingPairBoot: FC = ({ children }) => {
|
||||
return <>{children}</>;
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export * from "./MarketOffersTradingPair";
|
|
@ -99,4 +99,10 @@ export enum LangKeys {
|
|||
AccountBackupRestoreBtn = "account.backup.restore.btn",
|
||||
AccountBackupDownloadSuccessNotif = "account.backup.download.successNotification",
|
||||
AccountBackupRestoreSuccessNotif = "account.backup.restore.successNotification",
|
||||
MarketOffersAmount = "marketOffers.filter.amount",
|
||||
MarketOffersPaymentMethod = "marketOffers.filter.amount",
|
||||
MarketOffersAccountDetails = "marketOffers.filter.accountDetails",
|
||||
MarketOffersShowMarketDepth = "marketOffers.filter.showMarketDepth",
|
||||
MarketOffersHideMarketDepth = "marketOffers.filter.hideMarketDepth",
|
||||
MarketOffersCreateOffer = "marketOffers.filter.createOffer",
|
||||
}
|
||||
|
|
|
@ -116,6 +116,13 @@ const LangPackEN: { [key in LangKeys]: string } = {
|
|||
"The backup has been downloaded successfully.",
|
||||
[LangKeys.AccountBackupRestoreSuccessNotif]:
|
||||
"The backup has been restored successfully.",
|
||||
};
|
||||
|
||||
[LangKeys.MarketOffersAmount]: 'Amount',
|
||||
[LangKeys.MarketOffersPaymentMethod]: 'Payment method',
|
||||
[LangKeys.MarketOffersAccountDetails]: 'Account details',
|
||||
[LangKeys.MarketOffersShowMarketDepth]: 'Show market depth',
|
||||
[LangKeys.MarketOffersHideMarketDepth]: 'Hide market depth',
|
||||
[LangKeys.MarketOffersCreateOffer]: 'Create offer',
|
||||
};
|
||||
|
||||
export default LangPackEN;
|
||||
|
|
|
@ -29,6 +29,7 @@ export enum QueryKeys {
|
|||
XmrSeed = "Haveno.XmrSeed",
|
||||
XmrPrimaryAddress = "Haveno.XmrPrimaryAddress",
|
||||
XmrTxs = "Haveno.XmrTransactions",
|
||||
PaymentMethods = "Haveno.PaymentMethods",
|
||||
|
||||
// Storage
|
||||
StorageAccountInfo = "Storage.AccountInfo",
|
||||
|
|
32
packages/renderer/src/hooks/haveno/usePaymentMethods.ts
Normal file
32
packages/renderer/src/hooks/haveno/usePaymentMethods.ts
Normal file
|
@ -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 { useQuery } from "react-query";
|
||||
import type { PaymentMethod } from "haveno-ts";
|
||||
import { useHavenoClient } from "./useHavenoClient";
|
||||
import { QueryKeys } from "@constants/query-keys";
|
||||
|
||||
interface PaymentMethodsQuery {
|
||||
assetCode: string;
|
||||
}
|
||||
|
||||
export function usePaymentMethods(query: PaymentMethodsQuery) {
|
||||
const client = useHavenoClient();
|
||||
|
||||
return useQuery<Array<PaymentMethod>, Error>(QueryKeys.PaymentAccounts, () =>
|
||||
client.getPaymentMethods(query.assetCode)
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue