mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-22 06:21:37 +01:00
chore: 🔧 remove hodlhodl (#113)
* chore: 🔧 remove hodlhodl * chore: 🔧 cleanup package json
This commit is contained in:
parent
581185e6b0
commit
c8a9869062
28 changed files with 9 additions and 1858 deletions
2
.env
2
.env
|
@ -10,7 +10,6 @@
|
|||
# Server Configs
|
||||
# -----------
|
||||
# LOG_LEVEL='info'
|
||||
# HODL_KEY='HODL_HODL_API_KEY'
|
||||
# BASE_PATH='/basePath'
|
||||
|
||||
# -----------
|
||||
|
@ -24,7 +23,6 @@
|
|||
# -----------
|
||||
# FETCH_PRICES=false
|
||||
# FETCH_FEES=false
|
||||
# HODL_HODL=false
|
||||
# DISABLE_LINKS=true
|
||||
# NO_CLIENT_ACCOUNTS=true
|
||||
# NO_VERSION_CHECK=true
|
||||
|
|
|
@ -14,9 +14,6 @@ COPY package.json .
|
|||
COPY package-lock.json .
|
||||
RUN npm install --production --silent
|
||||
|
||||
# Install dependencies necessary for build and start
|
||||
RUN npm install -D cross-env typescript @types/react @next/bundle-analyzer
|
||||
|
||||
# ---------------
|
||||
# Build App
|
||||
# ---------------
|
||||
|
|
24
README.md
24
README.md
|
@ -102,22 +102,7 @@ This repository consists of a **NextJS** server that handles both the backend **
|
|||
## **Requirements**
|
||||
|
||||
- Yarn/npm installed
|
||||
- Node installed (Version 12.16.0 or higher)
|
||||
|
||||
**Older Versions of Node**
|
||||
Earlier versions of Node can be used if you replace the following commands:
|
||||
|
||||
```js
|
||||
//Yarn
|
||||
yarn start -> yarn start:compatible
|
||||
yarn dev -> yarn dev:compatible
|
||||
|
||||
//NPM
|
||||
npm start -> npm start:compatible
|
||||
npm run dev -> npm run dev:compatible
|
||||
```
|
||||
|
||||
**HodlHodl integration will not work with older versions of Node!**
|
||||
- Node installed (Version 10 or higher)
|
||||
|
||||
---
|
||||
|
||||
|
@ -132,7 +117,6 @@ You can define some environment variables that ThunderHub can start with. To do
|
|||
# Server Configs
|
||||
# -----------
|
||||
LOG_LEVEL = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly' # Default: 'info'
|
||||
HODL_KEY = '[Key provided by HodlHodl]' # Default: ''
|
||||
BASE_PATH = '[Base path where you want to have thunderhub running i.e. '/btcpay']' # Default: ''
|
||||
|
||||
# -----------
|
||||
|
@ -146,7 +130,6 @@ CURRENCY = 'sat' | 'btc' | 'fiat' # Default: 'sat'
|
|||
# -----------
|
||||
FETCH_PRICES = true | false # Default: true
|
||||
FETCH_FEES = true | false # Default: true
|
||||
HODL_HODL = true | false # Default: true
|
||||
DISABLE_LINKS = true | false # Default: false
|
||||
NO_CLIENT_ACCOUNTS = true | false # Default: false
|
||||
NO_VERSION_CHECK = true | false # Default: false
|
||||
|
@ -252,11 +235,6 @@ ThunderHub shows you links for quick viewing of nodes by public key on [1ml.com]
|
|||
|
||||
If you don't want to show these links, you can set `DISABLE_LINKS=true` in your `.env` file.
|
||||
|
||||
**HodlHodl**
|
||||
ThunderHub has a HodlHodl integration to view offers from this platform.
|
||||
|
||||
If you want to disable this integration, you can set `HODL_HODL=false` in your `.env` file.
|
||||
|
||||
**Client Accounts**
|
||||
ThunderHub allows you to create accounts on the browser which are also encrypted and stored in the same browser.
|
||||
|
||||
|
|
|
@ -14,9 +14,6 @@ COPY package.json .
|
|||
COPY package-lock.json .
|
||||
RUN npm install --production --silent
|
||||
|
||||
# Install dependencies necessary for build and start
|
||||
RUN npm install -D cross-env typescript @types/react @next/bundle-analyzer
|
||||
|
||||
# ---------------
|
||||
# Build App
|
||||
# ---------------
|
||||
|
|
|
@ -14,9 +14,6 @@ COPY package.json .
|
|||
COPY package-lock.json .
|
||||
RUN npm install --production --silent
|
||||
|
||||
# Install dependencies necessary for build and start
|
||||
RUN npm install -D cross-env typescript @types/react @next/bundle-analyzer
|
||||
|
||||
# ---------------
|
||||
# Build App
|
||||
# ---------------
|
||||
|
|
|
@ -9,7 +9,6 @@ module.exports = withBundleAnalyzer({
|
|||
serverRuntimeConfig: {
|
||||
nodeEnv: process.env.NODE_ENV || 'development',
|
||||
logLevel: process.env.LOG_LEVEL || 'info',
|
||||
hodlKey: process.env.HODL_KEY || '',
|
||||
cookiePath: process.env.COOKIE_PATH || '',
|
||||
lnServerUrl: process.env.SSO_SERVER_URL || '',
|
||||
lnCertPath: process.env.SSO_CERT_PATH || '',
|
||||
|
@ -26,7 +25,6 @@ module.exports = withBundleAnalyzer({
|
|||
defaultCurrency: process.env.CURRENCY || 'sat',
|
||||
fetchPrices: process.env.FETCH_PRICES === 'false' ? false : true,
|
||||
fetchFees: process.env.FETCH_FEES === 'false' ? false : true,
|
||||
hodlhodl: process.env.HODL_HODL === 'false' ? false : true,
|
||||
disableLinks: process.env.DISABLE_LINKS === 'true' ? true : false,
|
||||
noVersionCheck: process.env.NO_VERSION_CHECK === 'true' ? true : false,
|
||||
},
|
||||
|
|
52
package-lock.json
generated
52
package-lock.json
generated
|
@ -9919,58 +9919,6 @@
|
|||
"sha.js": "^2.4.8"
|
||||
}
|
||||
},
|
||||
"cross-env": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz",
|
||||
"integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cross-fetch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.4.tgz",
|
||||
|
|
14
package.json
14
package.json
|
@ -6,12 +6,9 @@
|
|||
"scripts": {
|
||||
"bs": "yarn build && yarn start",
|
||||
"dev": "next",
|
||||
"dev:compatible": "next",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"start:two": "next start -p 3001",
|
||||
"start:compatible": "next start",
|
||||
"start:compatible:two": "next start -p 3001",
|
||||
"start:cookie": "sh ./scripts/initCookie.sh",
|
||||
"lint": "eslint . --ext ts --ext tsx --ext js",
|
||||
"format": "prettier --write \"**/*.{js,ts,tsx}\"",
|
||||
|
@ -19,7 +16,7 @@
|
|||
"release:push": "standard-version --sign && git push --follow-tags origin master",
|
||||
"release:test": "standard-version --sign --dry-run",
|
||||
"release:minor": "standard-version --sign --release-as minor && git push --follow-tags origin master",
|
||||
"analyze": "cross-env ANALYZE=true next build",
|
||||
"analyze": "npx cross-env ANALYZE=true next build",
|
||||
"generate": "graphql-codegen --config codegen.yml && yarn format",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
|
@ -38,6 +35,8 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.1.1",
|
||||
"@next/bundle-analyzer": "^9.4.4",
|
||||
"@types/react": "^16.9.43",
|
||||
"apollo-server-micro": "^2.15.1",
|
||||
"balanceofsatoshis": "^5.40.2",
|
||||
"bcryptjs": "^2.4.3",
|
||||
|
@ -71,6 +70,7 @@
|
|||
"styled-components": "^5.1.1",
|
||||
"styled-react-modal": "^2.0.1",
|
||||
"styled-theming": "^2.2.0",
|
||||
"typescript": "^3.9.6",
|
||||
"underscore": "^1.10.2",
|
||||
"uuid": "^8.2.0",
|
||||
"victory": "^35.0.3",
|
||||
|
@ -88,7 +88,6 @@
|
|||
"@graphql-codegen/typescript-operations": "^1.17.0",
|
||||
"@graphql-codegen/typescript-react-apollo": "^1.17.0",
|
||||
"@graphql-codegen/typescript-resolvers": "^1.17.0",
|
||||
"@next/bundle-analyzer": "^9.4.4",
|
||||
"@testing-library/jest-dom": "^5.11.0",
|
||||
"@testing-library/react": "^10.4.5",
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
|
@ -104,7 +103,6 @@
|
|||
"@types/node": "^14.0.22",
|
||||
"@types/numeral": "0.0.28",
|
||||
"@types/qrcode.react": "^1.0.1",
|
||||
"@types/react": "^16.9.43",
|
||||
"@types/react-copy-to-clipboard": "^4.3.0",
|
||||
"@types/styled-components": "^5.1.1",
|
||||
"@types/styled-react-modal": "^1.2.0",
|
||||
|
@ -120,7 +118,6 @@
|
|||
"babel-plugin-inline-react-svg": "^1.1.1",
|
||||
"babel-plugin-styled-components": "^1.10.7",
|
||||
"babel-preset-react-app": "^9.1.2",
|
||||
"cross-env": "^7.0.2",
|
||||
"devmoji": "^2.1.9",
|
||||
"eslint": "^7.4.0",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
|
@ -135,8 +132,7 @@
|
|||
"jest-fetch-mock": "^3.0.3",
|
||||
"lint-staged": "^10.2.11",
|
||||
"prettier": "^2.0.5",
|
||||
"standard-version": "^8.0.2",
|
||||
"typescript": "^3.9.6"
|
||||
"standard-version": "^8.0.2"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
import React, { useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useGetOffersQuery } from 'src/graphql/hodlhodl/__generated__/query.generated';
|
||||
import { GridWrapper } from 'src/components/gridWrapper/GridWrapper';
|
||||
import getConfig from 'next/config';
|
||||
import { HodlOfferType } from 'src/graphql/types';
|
||||
import { NextPageContext } from 'next';
|
||||
import { getProps } from 'src/utils/ssr';
|
||||
import {
|
||||
CardWithTitle,
|
||||
SubTitle,
|
||||
Card,
|
||||
DarkSubTitle,
|
||||
ResponsiveLine,
|
||||
} from '../src/components/generic/Styled';
|
||||
import { LoadingCard } from '../src/components/loading/LoadingCard';
|
||||
import { OfferCard } from '../src/views/trading/OfferCard';
|
||||
import { OfferFilters } from '../src/views/trading/OfferFilters';
|
||||
import { Link } from '../src/components/link/Link';
|
||||
import { ColorButton } from '../src/components/buttons/colorButton/ColorButton';
|
||||
import { decode } from '../src/utils/helpers';
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
const { hodlhodl } = publicRuntimeConfig;
|
||||
|
||||
export interface QueryProps {
|
||||
pagination: {
|
||||
limit: number;
|
||||
offset: number;
|
||||
};
|
||||
filters: { [key: string]: string };
|
||||
sort: {
|
||||
by: string;
|
||||
direction: string;
|
||||
};
|
||||
}
|
||||
|
||||
const defaultQuery: QueryProps = {
|
||||
pagination: {
|
||||
limit: 25,
|
||||
offset: 0,
|
||||
},
|
||||
filters: {},
|
||||
sort: {
|
||||
by: '',
|
||||
direction: '',
|
||||
},
|
||||
};
|
||||
|
||||
const TradingView = () => {
|
||||
const { query } = useRouter();
|
||||
|
||||
let decoded: QueryProps = defaultQuery;
|
||||
if (query?.filter) {
|
||||
const { filter } = query;
|
||||
try {
|
||||
if (typeof filter === 'string') {
|
||||
decoded = JSON.parse(decode(filter));
|
||||
} else {
|
||||
decoded = JSON.parse(decode(filter[0]));
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('Incorrect url.');
|
||||
}
|
||||
}
|
||||
|
||||
const queryObject = {
|
||||
...defaultQuery,
|
||||
...decoded,
|
||||
};
|
||||
|
||||
const [indexOpen, setIndexOpen] = useState(0);
|
||||
const [page, setPage] = useState(1);
|
||||
const [fetching, setFetching] = useState(false);
|
||||
|
||||
const { data, loading, fetchMore, error } = useGetOffersQuery({
|
||||
skip: !hodlhodl,
|
||||
variables: { filter: JSON.stringify(queryObject) },
|
||||
});
|
||||
|
||||
if (!hodlhodl) {
|
||||
return (
|
||||
<CardWithTitle>
|
||||
<SubTitle>P2P Trading</SubTitle>
|
||||
<Card bottom={'16px'}>
|
||||
HodlHodl integration is disabled from the server.
|
||||
</Card>
|
||||
</CardWithTitle>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<CardWithTitle>
|
||||
<SubTitle>P2P Trading</SubTitle>
|
||||
<Card bottom={'16px'}>Failed to connect with HodlHodl.</Card>
|
||||
</CardWithTitle>
|
||||
);
|
||||
}
|
||||
|
||||
if (loading || !data || !data.getOffers) {
|
||||
return <LoadingCard title={'P2P Trading'} />;
|
||||
}
|
||||
|
||||
const amountOfOffers = data.getOffers.length;
|
||||
const {
|
||||
pagination: { limit },
|
||||
} = queryObject;
|
||||
|
||||
return (
|
||||
<CardWithTitle>
|
||||
<ResponsiveLine>
|
||||
<SubTitle>P2P Trading</SubTitle>
|
||||
<DarkSubTitle>
|
||||
Powered by <Link href={'https://hodlhodl.com/'}>HodlHodl</Link>
|
||||
</DarkSubTitle>
|
||||
</ResponsiveLine>
|
||||
<Card bottom={'16px'}>
|
||||
<OfferFilters offerFilters={queryObject} />
|
||||
</Card>
|
||||
<Card bottom={'8px'} mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||
{amountOfOffers <= 0 && <DarkSubTitle>No Offers Found</DarkSubTitle>}
|
||||
{data.getOffers.map((offer, index) => (
|
||||
<OfferCard
|
||||
offer={offer as HodlOfferType}
|
||||
index={index + 1}
|
||||
setIndexOpen={setIndexOpen}
|
||||
indexOpen={indexOpen}
|
||||
key={`${index}-${offer?.id}`}
|
||||
/>
|
||||
))}
|
||||
</Card>
|
||||
{amountOfOffers > 0 && amountOfOffers === limit * page && (
|
||||
<ColorButton
|
||||
loading={fetching}
|
||||
disabled={fetching}
|
||||
onClick={() => {
|
||||
setFetching(true);
|
||||
|
||||
fetchMore({
|
||||
variables: {
|
||||
filter: JSON.stringify({
|
||||
...queryObject,
|
||||
pagination: { limit, offset: limit * page },
|
||||
}),
|
||||
},
|
||||
updateQuery: (prev, { fetchMoreResult: result }) => {
|
||||
if (!result) return prev;
|
||||
|
||||
setFetching(false);
|
||||
setPage(prev => prev + 1);
|
||||
return {
|
||||
getOffers: [...prev.getOffers, ...result.getOffers],
|
||||
};
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
Show More
|
||||
</ColorButton>
|
||||
)}
|
||||
</CardWithTitle>
|
||||
);
|
||||
};
|
||||
|
||||
const Wrapped = () => (
|
||||
<GridWrapper>
|
||||
<TradingView />
|
||||
</GridWrapper>
|
||||
);
|
||||
|
||||
export default Wrapped;
|
||||
|
||||
export async function getServerSideProps(context: NextPageContext) {
|
||||
return await getProps(context);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
export const getHodlParams = (params: any): string => {
|
||||
let paramString = '?';
|
||||
|
||||
for (const key in params) {
|
||||
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
||||
const element = params[key];
|
||||
|
||||
for (const subKey in element) {
|
||||
if (Object.prototype.hasOwnProperty.call(element, subKey)) {
|
||||
const subElement = element[subKey];
|
||||
paramString = `${paramString}&${key}[${subKey}]=${subElement}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paramString;
|
||||
};
|
|
@ -1,103 +0,0 @@
|
|||
import getConfig from 'next/config';
|
||||
import { ContextType } from 'server/types/apiTypes';
|
||||
import { requestLimiter } from 'server/helpers/rateLimiter';
|
||||
import { logger } from 'server/helpers/logger';
|
||||
import { appUrls } from 'server/utils/appUrls';
|
||||
import { getHodlParams } from 'server/helpers/hodlHelpers';
|
||||
|
||||
const { serverRuntimeConfig } = getConfig() || {};
|
||||
const { hodlKey } = serverRuntimeConfig || {};
|
||||
|
||||
const defaultQuery = {
|
||||
filters: {},
|
||||
sort: {
|
||||
by: '',
|
||||
direction: '',
|
||||
},
|
||||
};
|
||||
|
||||
export const hodlResolvers = {
|
||||
Query: {
|
||||
getCountries: async (_: undefined, params: any, context: ContextType) => {
|
||||
await requestLimiter(context.ip, 'getCountries');
|
||||
|
||||
const headers = {
|
||||
Authorization: `Bearer ${hodlKey}`,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(`${appUrls.hodlhodl}/v1/countries`, {
|
||||
headers,
|
||||
});
|
||||
const json = await response.json();
|
||||
|
||||
if (json) {
|
||||
const { countries } = json;
|
||||
return countries;
|
||||
}
|
||||
throw new Error('Problem getting HodlHodl countries.');
|
||||
} catch (error) {
|
||||
logger.error('Error getting HodlHodl countries: %o', error);
|
||||
throw new Error('Problem getting HodlHodl countries.');
|
||||
}
|
||||
},
|
||||
getCurrencies: async (_: undefined, params: any, context: ContextType) => {
|
||||
await requestLimiter(context.ip, 'getCurrencies');
|
||||
|
||||
const headers = {
|
||||
Authorization: `Bearer ${hodlKey}`,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(`${appUrls.hodlhodl}/v1/currencies`, {
|
||||
headers,
|
||||
});
|
||||
const json = await response.json();
|
||||
|
||||
if (json) {
|
||||
const { currencies } = json;
|
||||
return currencies;
|
||||
}
|
||||
throw new Error('Problem getting HodlHodl currencies.');
|
||||
} catch (error) {
|
||||
logger.error('Error getting HodlHodl currencies: %o', error);
|
||||
throw new Error('Problem getting HodlHodl currencies.');
|
||||
}
|
||||
},
|
||||
getOffers: async (_: undefined, params: any, context: ContextType) => {
|
||||
await requestLimiter(context.ip, 'getOffers');
|
||||
|
||||
let queryParams = defaultQuery;
|
||||
|
||||
if (params.filter) {
|
||||
try {
|
||||
queryParams = JSON.parse(params.filter);
|
||||
} catch (error) {
|
||||
queryParams = defaultQuery;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const fullParams = {
|
||||
...queryParams,
|
||||
};
|
||||
|
||||
const paramString = getHodlParams(fullParams);
|
||||
|
||||
const response = await fetch(
|
||||
`${appUrls.hodlhodl}/v1/offers${paramString}`
|
||||
);
|
||||
const json = await response.json();
|
||||
|
||||
if (json) {
|
||||
const { offers } = json;
|
||||
return offers;
|
||||
}
|
||||
throw new Error('Problem getting HodlHodl offers.');
|
||||
} catch (error) {
|
||||
logger.error('Error getting HodlHodl offers: %o', error);
|
||||
throw new Error('Problem getting HodlHodl offers.');
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,69 +0,0 @@
|
|||
import { gql } from 'apollo-server-micro';
|
||||
|
||||
export const hodlTypes = gql`
|
||||
type hodlCountryType {
|
||||
code: String
|
||||
name: String
|
||||
native_name: String
|
||||
currency_code: String
|
||||
currency_name: String
|
||||
}
|
||||
|
||||
type hodlCurrencyType {
|
||||
code: String
|
||||
name: String
|
||||
type: String
|
||||
}
|
||||
|
||||
type hodlOfferFeeType {
|
||||
author_fee_rate: String
|
||||
}
|
||||
|
||||
type hodlOfferPaymentType {
|
||||
id: String
|
||||
version: String
|
||||
payment_method_id: String
|
||||
payment_method_type: String
|
||||
payment_method_name: String
|
||||
}
|
||||
|
||||
type hodlOfferTraderType {
|
||||
login: String
|
||||
online_status: String
|
||||
rating: String
|
||||
trades_count: Int
|
||||
url: String
|
||||
verified: Boolean
|
||||
verified_by: String
|
||||
strong_hodler: Boolean
|
||||
country: String
|
||||
country_code: String
|
||||
average_payment_time_minutes: Int
|
||||
average_release_time_minutes: Int
|
||||
days_since_last_trade: Int
|
||||
}
|
||||
|
||||
type hodlOfferType {
|
||||
id: String
|
||||
version: String
|
||||
asset_code: String
|
||||
searchable: Boolean
|
||||
country: String
|
||||
country_code: String
|
||||
working_now: Boolean
|
||||
side: String
|
||||
title: String
|
||||
description: String
|
||||
currency_code: String
|
||||
price: String
|
||||
min_amount: String
|
||||
max_amount: String
|
||||
first_trade_limit: String
|
||||
fee: hodlOfferFeeType
|
||||
balance: String
|
||||
payment_window_minutes: Int
|
||||
confirmations: Int
|
||||
payment_method_instructions: [hodlOfferPaymentType]
|
||||
trader: hodlOfferTraderType
|
||||
}
|
||||
`;
|
|
@ -6,8 +6,6 @@ import { authResolvers } from './auth/resolvers';
|
|||
import { generalTypes, queryTypes, mutationTypes } from './types';
|
||||
import { accountResolvers } from './account/resolvers';
|
||||
import { accountTypes } from './account/types';
|
||||
import { hodlTypes } from './hodlhodl/types';
|
||||
import { hodlResolvers } from './hodlhodl/resolvers';
|
||||
import { lnpayResolvers } from './lnpay/resolvers';
|
||||
import { lnpayTypes } from './lnpay/types';
|
||||
import { bitcoinResolvers } from './bitcoin/resolvers';
|
||||
|
@ -49,7 +47,6 @@ const typeDefs = [
|
|||
mutationTypes,
|
||||
nodeTypes,
|
||||
accountTypes,
|
||||
hodlTypes,
|
||||
lnpayTypes,
|
||||
bitcoinTypes,
|
||||
peerTypes,
|
||||
|
@ -72,7 +69,6 @@ const resolvers = merge(
|
|||
nodeResolvers,
|
||||
authResolvers,
|
||||
accountResolvers,
|
||||
hodlResolvers,
|
||||
lnpayResolvers,
|
||||
bitcoinResolvers,
|
||||
peerResolvers,
|
||||
|
|
|
@ -74,9 +74,6 @@ export const queryTypes = gql`
|
|||
getPendingChainBalance: Int
|
||||
getChainTransactions: [getTransactionsType]
|
||||
getUtxos: [getUtxosType]
|
||||
getOffers(filter: String): [hodlOfferType]
|
||||
getCountries: [hodlCountryType]
|
||||
getCurrencies: [hodlCurrencyType]
|
||||
getMessages(
|
||||
token: String
|
||||
initialize: Boolean
|
||||
|
|
|
@ -15,7 +15,6 @@ export const appUrls = {
|
|||
blockchain: 'https://www.blockchain.com/btc/tx/',
|
||||
fees: 'https://mempool.space/api/v1/fees/recommended',
|
||||
ticker: 'https://blockchain.info/ticker',
|
||||
hodlhodl: 'https://hodlhodl.com/api',
|
||||
github: 'https://api.github.com/repos/apotdevin/thunderhub/releases/latest',
|
||||
update: 'https://github.com/apotdevin/thunderhub#updating',
|
||||
};
|
||||
|
|
312
src/graphql/hodlhodl/__generated__/query.generated.tsx
generated
312
src/graphql/hodlhodl/__generated__/query.generated.tsx
generated
|
@ -1,312 +0,0 @@
|
|||
import {
|
||||
gql,
|
||||
QueryHookOptions,
|
||||
useQuery,
|
||||
useLazyQuery,
|
||||
QueryResult,
|
||||
LazyQueryHookOptions,
|
||||
} from '@apollo/client';
|
||||
import * as Types from '../../types';
|
||||
|
||||
export type GetCountriesQueryVariables = Types.Exact<{ [key: string]: never }>;
|
||||
|
||||
export type GetCountriesQuery = { __typename?: 'Query' } & {
|
||||
getCountries?: Types.Maybe<
|
||||
Array<
|
||||
Types.Maybe<
|
||||
{ __typename?: 'hodlCountryType' } & Pick<
|
||||
Types.HodlCountryType,
|
||||
'code' | 'name' | 'native_name' | 'currency_code' | 'currency_name'
|
||||
>
|
||||
>
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
export type GetCurrenciesQueryVariables = Types.Exact<{ [key: string]: never }>;
|
||||
|
||||
export type GetCurrenciesQuery = { __typename?: 'Query' } & {
|
||||
getCurrencies?: Types.Maybe<
|
||||
Array<
|
||||
Types.Maybe<
|
||||
{ __typename?: 'hodlCurrencyType' } & Pick<
|
||||
Types.HodlCurrencyType,
|
||||
'code' | 'name' | 'type'
|
||||
>
|
||||
>
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
export type GetOffersQueryVariables = Types.Exact<{
|
||||
filter?: Types.Maybe<Types.Scalars['String']>;
|
||||
}>;
|
||||
|
||||
export type GetOffersQuery = { __typename?: 'Query' } & {
|
||||
getOffers?: Types.Maybe<
|
||||
Array<
|
||||
Types.Maybe<
|
||||
{ __typename?: 'hodlOfferType' } & Pick<
|
||||
Types.HodlOfferType,
|
||||
| 'id'
|
||||
| 'asset_code'
|
||||
| 'country'
|
||||
| 'country_code'
|
||||
| 'working_now'
|
||||
| 'side'
|
||||
| 'title'
|
||||
| 'description'
|
||||
| 'currency_code'
|
||||
| 'price'
|
||||
| 'min_amount'
|
||||
| 'max_amount'
|
||||
| 'first_trade_limit'
|
||||
| 'balance'
|
||||
| 'payment_window_minutes'
|
||||
| 'confirmations'
|
||||
> & {
|
||||
fee?: Types.Maybe<
|
||||
{ __typename?: 'hodlOfferFeeType' } & Pick<
|
||||
Types.HodlOfferFeeType,
|
||||
'author_fee_rate'
|
||||
>
|
||||
>;
|
||||
payment_method_instructions?: Types.Maybe<
|
||||
Array<
|
||||
Types.Maybe<
|
||||
{ __typename?: 'hodlOfferPaymentType' } & Pick<
|
||||
Types.HodlOfferPaymentType,
|
||||
| 'id'
|
||||
| 'version'
|
||||
| 'payment_method_id'
|
||||
| 'payment_method_type'
|
||||
| 'payment_method_name'
|
||||
>
|
||||
>
|
||||
>
|
||||
>;
|
||||
trader?: Types.Maybe<
|
||||
{ __typename?: 'hodlOfferTraderType' } & Pick<
|
||||
Types.HodlOfferTraderType,
|
||||
| 'login'
|
||||
| 'online_status'
|
||||
| 'rating'
|
||||
| 'trades_count'
|
||||
| 'url'
|
||||
| 'verified'
|
||||
| 'verified_by'
|
||||
| 'strong_hodler'
|
||||
| 'country'
|
||||
| 'country_code'
|
||||
| 'average_payment_time_minutes'
|
||||
| 'average_release_time_minutes'
|
||||
| 'days_since_last_trade'
|
||||
>
|
||||
>;
|
||||
}
|
||||
>
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
export const GetCountriesDocument = gql`
|
||||
query GetCountries {
|
||||
getCountries {
|
||||
code
|
||||
name
|
||||
native_name
|
||||
currency_code
|
||||
currency_name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useGetCountriesQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useGetCountriesQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useGetCountriesQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useGetCountriesQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useGetCountriesQuery(
|
||||
baseOptions?: QueryHookOptions<GetCountriesQuery, GetCountriesQueryVariables>
|
||||
) {
|
||||
return useQuery<GetCountriesQuery, GetCountriesQueryVariables>(
|
||||
GetCountriesDocument,
|
||||
baseOptions
|
||||
);
|
||||
}
|
||||
export function useGetCountriesLazyQuery(
|
||||
baseOptions?: LazyQueryHookOptions<
|
||||
GetCountriesQuery,
|
||||
GetCountriesQueryVariables
|
||||
>
|
||||
) {
|
||||
return useLazyQuery<GetCountriesQuery, GetCountriesQueryVariables>(
|
||||
GetCountriesDocument,
|
||||
baseOptions
|
||||
);
|
||||
}
|
||||
export type GetCountriesQueryHookResult = ReturnType<
|
||||
typeof useGetCountriesQuery
|
||||
>;
|
||||
export type GetCountriesLazyQueryHookResult = ReturnType<
|
||||
typeof useGetCountriesLazyQuery
|
||||
>;
|
||||
export type GetCountriesQueryResult = QueryResult<
|
||||
GetCountriesQuery,
|
||||
GetCountriesQueryVariables
|
||||
>;
|
||||
export const GetCurrenciesDocument = gql`
|
||||
query GetCurrencies {
|
||||
getCurrencies {
|
||||
code
|
||||
name
|
||||
type
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useGetCurrenciesQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useGetCurrenciesQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useGetCurrenciesQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useGetCurrenciesQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useGetCurrenciesQuery(
|
||||
baseOptions?: QueryHookOptions<
|
||||
GetCurrenciesQuery,
|
||||
GetCurrenciesQueryVariables
|
||||
>
|
||||
) {
|
||||
return useQuery<GetCurrenciesQuery, GetCurrenciesQueryVariables>(
|
||||
GetCurrenciesDocument,
|
||||
baseOptions
|
||||
);
|
||||
}
|
||||
export function useGetCurrenciesLazyQuery(
|
||||
baseOptions?: LazyQueryHookOptions<
|
||||
GetCurrenciesQuery,
|
||||
GetCurrenciesQueryVariables
|
||||
>
|
||||
) {
|
||||
return useLazyQuery<GetCurrenciesQuery, GetCurrenciesQueryVariables>(
|
||||
GetCurrenciesDocument,
|
||||
baseOptions
|
||||
);
|
||||
}
|
||||
export type GetCurrenciesQueryHookResult = ReturnType<
|
||||
typeof useGetCurrenciesQuery
|
||||
>;
|
||||
export type GetCurrenciesLazyQueryHookResult = ReturnType<
|
||||
typeof useGetCurrenciesLazyQuery
|
||||
>;
|
||||
export type GetCurrenciesQueryResult = QueryResult<
|
||||
GetCurrenciesQuery,
|
||||
GetCurrenciesQueryVariables
|
||||
>;
|
||||
export const GetOffersDocument = gql`
|
||||
query GetOffers($filter: String) {
|
||||
getOffers(filter: $filter) {
|
||||
id
|
||||
asset_code
|
||||
country
|
||||
country_code
|
||||
working_now
|
||||
side
|
||||
title
|
||||
description
|
||||
currency_code
|
||||
price
|
||||
min_amount
|
||||
max_amount
|
||||
first_trade_limit
|
||||
fee {
|
||||
author_fee_rate
|
||||
}
|
||||
balance
|
||||
payment_window_minutes
|
||||
confirmations
|
||||
payment_method_instructions {
|
||||
id
|
||||
version
|
||||
payment_method_id
|
||||
payment_method_type
|
||||
payment_method_name
|
||||
}
|
||||
trader {
|
||||
login
|
||||
online_status
|
||||
rating
|
||||
trades_count
|
||||
url
|
||||
verified
|
||||
verified_by
|
||||
strong_hodler
|
||||
country
|
||||
country_code
|
||||
average_payment_time_minutes
|
||||
average_release_time_minutes
|
||||
days_since_last_trade
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useGetOffersQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useGetOffersQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useGetOffersQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useGetOffersQuery({
|
||||
* variables: {
|
||||
* filter: // value for 'filter'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useGetOffersQuery(
|
||||
baseOptions?: QueryHookOptions<GetOffersQuery, GetOffersQueryVariables>
|
||||
) {
|
||||
return useQuery<GetOffersQuery, GetOffersQueryVariables>(
|
||||
GetOffersDocument,
|
||||
baseOptions
|
||||
);
|
||||
}
|
||||
export function useGetOffersLazyQuery(
|
||||
baseOptions?: LazyQueryHookOptions<GetOffersQuery, GetOffersQueryVariables>
|
||||
) {
|
||||
return useLazyQuery<GetOffersQuery, GetOffersQueryVariables>(
|
||||
GetOffersDocument,
|
||||
baseOptions
|
||||
);
|
||||
}
|
||||
export type GetOffersQueryHookResult = ReturnType<typeof useGetOffersQuery>;
|
||||
export type GetOffersLazyQueryHookResult = ReturnType<
|
||||
typeof useGetOffersLazyQuery
|
||||
>;
|
||||
export type GetOffersQueryResult = QueryResult<
|
||||
GetOffersQuery,
|
||||
GetOffersQueryVariables
|
||||
>;
|
|
@ -1,71 +0,0 @@
|
|||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_HODL_COUNTRIES = gql`
|
||||
query GetCountries {
|
||||
getCountries {
|
||||
code
|
||||
name
|
||||
native_name
|
||||
currency_code
|
||||
currency_name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const GET_HODL_CURRENCIES = gql`
|
||||
query GetCurrencies {
|
||||
getCurrencies {
|
||||
code
|
||||
name
|
||||
type
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const GET_HODL_OFFERS = gql`
|
||||
query GetOffers($filter: String) {
|
||||
getOffers(filter: $filter) {
|
||||
id
|
||||
asset_code
|
||||
country
|
||||
country_code
|
||||
working_now
|
||||
side
|
||||
title
|
||||
description
|
||||
currency_code
|
||||
price
|
||||
min_amount
|
||||
max_amount
|
||||
first_trade_limit
|
||||
fee {
|
||||
author_fee_rate
|
||||
}
|
||||
balance
|
||||
payment_window_minutes
|
||||
confirmations
|
||||
payment_method_instructions {
|
||||
id
|
||||
version
|
||||
payment_method_id
|
||||
payment_method_type
|
||||
payment_method_name
|
||||
}
|
||||
trader {
|
||||
login
|
||||
online_status
|
||||
rating
|
||||
trades_count
|
||||
url
|
||||
verified
|
||||
verified_by
|
||||
strong_hodler
|
||||
country
|
||||
country_code
|
||||
average_payment_time_minutes
|
||||
average_release_time_minutes
|
||||
days_since_last_trade
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -72,9 +72,6 @@ export type Query = {
|
|||
getPendingChainBalance?: Maybe<Scalars['Int']>;
|
||||
getChainTransactions?: Maybe<Array<Maybe<GetTransactionsType>>>;
|
||||
getUtxos?: Maybe<Array<Maybe<GetUtxosType>>>;
|
||||
getOffers?: Maybe<Array<Maybe<HodlOfferType>>>;
|
||||
getCountries?: Maybe<Array<Maybe<HodlCountryType>>>;
|
||||
getCurrencies?: Maybe<Array<Maybe<HodlCurrencyType>>>;
|
||||
getMessages?: Maybe<GetMessagesType>;
|
||||
getAuthToken?: Maybe<Scalars['Boolean']>;
|
||||
getSessionToken?: Maybe<Scalars['Boolean']>;
|
||||
|
@ -343,78 +340,6 @@ export type ServerAccountType = {
|
|||
loggedIn: Scalars['Boolean'];
|
||||
};
|
||||
|
||||
export type HodlCountryType = {
|
||||
__typename?: 'hodlCountryType';
|
||||
code?: Maybe<Scalars['String']>;
|
||||
name?: Maybe<Scalars['String']>;
|
||||
native_name?: Maybe<Scalars['String']>;
|
||||
currency_code?: Maybe<Scalars['String']>;
|
||||
currency_name?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type HodlCurrencyType = {
|
||||
__typename?: 'hodlCurrencyType';
|
||||
code?: Maybe<Scalars['String']>;
|
||||
name?: Maybe<Scalars['String']>;
|
||||
type?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type HodlOfferFeeType = {
|
||||
__typename?: 'hodlOfferFeeType';
|
||||
author_fee_rate?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type HodlOfferPaymentType = {
|
||||
__typename?: 'hodlOfferPaymentType';
|
||||
id?: Maybe<Scalars['String']>;
|
||||
version?: Maybe<Scalars['String']>;
|
||||
payment_method_id?: Maybe<Scalars['String']>;
|
||||
payment_method_type?: Maybe<Scalars['String']>;
|
||||
payment_method_name?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type HodlOfferTraderType = {
|
||||
__typename?: 'hodlOfferTraderType';
|
||||
login?: Maybe<Scalars['String']>;
|
||||
online_status?: Maybe<Scalars['String']>;
|
||||
rating?: Maybe<Scalars['String']>;
|
||||
trades_count?: Maybe<Scalars['Int']>;
|
||||
url?: Maybe<Scalars['String']>;
|
||||
verified?: Maybe<Scalars['Boolean']>;
|
||||
verified_by?: Maybe<Scalars['String']>;
|
||||
strong_hodler?: Maybe<Scalars['Boolean']>;
|
||||
country?: Maybe<Scalars['String']>;
|
||||
country_code?: Maybe<Scalars['String']>;
|
||||
average_payment_time_minutes?: Maybe<Scalars['Int']>;
|
||||
average_release_time_minutes?: Maybe<Scalars['Int']>;
|
||||
days_since_last_trade?: Maybe<Scalars['Int']>;
|
||||
};
|
||||
|
||||
export type HodlOfferType = {
|
||||
__typename?: 'hodlOfferType';
|
||||
id?: Maybe<Scalars['String']>;
|
||||
version?: Maybe<Scalars['String']>;
|
||||
asset_code?: Maybe<Scalars['String']>;
|
||||
searchable?: Maybe<Scalars['Boolean']>;
|
||||
country?: Maybe<Scalars['String']>;
|
||||
country_code?: Maybe<Scalars['String']>;
|
||||
working_now?: Maybe<Scalars['Boolean']>;
|
||||
side?: Maybe<Scalars['String']>;
|
||||
title?: Maybe<Scalars['String']>;
|
||||
description?: Maybe<Scalars['String']>;
|
||||
currency_code?: Maybe<Scalars['String']>;
|
||||
price?: Maybe<Scalars['String']>;
|
||||
min_amount?: Maybe<Scalars['String']>;
|
||||
max_amount?: Maybe<Scalars['String']>;
|
||||
first_trade_limit?: Maybe<Scalars['String']>;
|
||||
fee?: Maybe<HodlOfferFeeType>;
|
||||
balance?: Maybe<Scalars['String']>;
|
||||
payment_window_minutes?: Maybe<Scalars['Int']>;
|
||||
confirmations?: Maybe<Scalars['Int']>;
|
||||
payment_method_instructions?: Maybe<Array<Maybe<HodlOfferPaymentType>>>;
|
||||
trader?: Maybe<HodlOfferTraderType>;
|
||||
};
|
||||
|
||||
export type LnPayInfoType = {
|
||||
__typename?: 'lnPayInfoType';
|
||||
max?: Maybe<Scalars['Int']>;
|
||||
|
|
|
@ -3,7 +3,6 @@ import {
|
|||
Cpu,
|
||||
Menu,
|
||||
X,
|
||||
CreditCard,
|
||||
MessageCircle,
|
||||
Settings,
|
||||
Home,
|
||||
|
@ -11,7 +10,6 @@ import {
|
|||
} from 'react-feather';
|
||||
import { useTransition, animated } from 'react-spring';
|
||||
import { useRouter } from 'next/router';
|
||||
import getConfig from 'next/config';
|
||||
import { headerColor, headerTextColor } from '../../styles/Themes';
|
||||
import { SingleLine } from '../../components/generic/Styled';
|
||||
import { BurgerMenu } from '../../components/burgerMenu/BurgerMenu';
|
||||
|
@ -30,13 +28,9 @@ import {
|
|||
|
||||
const MAIN = '/';
|
||||
const HOME = '/home';
|
||||
const TRADER = '/trading';
|
||||
const CHAT = '/chat';
|
||||
const SETTINGS = '/settings';
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
const { hodlhodl } = publicRuntimeConfig;
|
||||
|
||||
export const Header = () => {
|
||||
const { pathname } = useRouter();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
@ -44,7 +38,7 @@ export const Header = () => {
|
|||
const isRoot = pathname === '/';
|
||||
|
||||
const showHomeButton = (): boolean =>
|
||||
pathname === TRADER || pathname === CHAT || pathname === SETTINGS;
|
||||
pathname === CHAT || pathname === SETTINGS;
|
||||
|
||||
const transitions = useTransition(open, null, {
|
||||
from: { position: 'absolute', opacity: 0 },
|
||||
|
@ -80,7 +74,6 @@ export const Header = () => {
|
|||
<ViewSwitch hideMobile={true}>
|
||||
<HeaderButtons>
|
||||
{showHomeButton() && renderNavButton(HOME, Home)}
|
||||
{hodlhodl && renderNavButton(TRADER, CreditCard)}
|
||||
{renderNavButton(CHAT, MessageCircle)}
|
||||
{renderNavButton(SETTINGS, Settings)}
|
||||
</HeaderButtons>
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
Link as LinkIcon,
|
||||
Repeat,
|
||||
Users,
|
||||
CreditCard,
|
||||
MessageCircle,
|
||||
BarChart2,
|
||||
Icon,
|
||||
|
@ -122,7 +121,6 @@ const CHAIN_TRANS = '/chain';
|
|||
const TOOLS = '/tools';
|
||||
const DETAILS = '/details';
|
||||
const STATS = '/stats';
|
||||
const TRADER = '/trading';
|
||||
const CHAT = '/chat';
|
||||
const SETTINGS = '/settings';
|
||||
|
||||
|
@ -190,7 +188,6 @@ export const Navigation = ({ isBurger, setOpen }: NavigationProps) => {
|
|||
{renderBurgerNav('Chain', CHAIN_TRANS, LinkIcon)}
|
||||
{renderBurgerNav('Tools', TOOLS, Shield)}
|
||||
{renderBurgerNav('Stats', STATS, BarChart2)}
|
||||
{renderBurgerNav('Trading', TRADER, CreditCard)}
|
||||
{renderBurgerNav('Chat', CHAT, MessageCircle)}
|
||||
{renderBurgerNav('Settings', SETTINGS, Settings)}
|
||||
</BurgerRow>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { ModalType } from 'src/views/trading/Modal/FilterModal';
|
||||
import {
|
||||
Sub4Title,
|
||||
ResponsiveLine,
|
||||
|
@ -14,6 +13,8 @@ import { isLightningInvoice } from '../../../../utils/helpers';
|
|||
import { RequestModal } from './RequestModal';
|
||||
import { KeysendModal } from './KeysendModal';
|
||||
|
||||
type ModalType = 'keysend' | 'request' | 'none';
|
||||
|
||||
export const PayCard = ({ setOpen }: { setOpen: () => void }) => {
|
||||
const [request, setRequest] = useState<string>('');
|
||||
const [modalType, setModalType] = useState<ModalType>('none');
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { HodlOfferPaymentType } from 'src/graphql/types';
|
||||
import { themeColors, subCardColor } from '../../styles/Themes';
|
||||
|
||||
interface MethodProps {
|
||||
id: string;
|
||||
payment_method_type: string;
|
||||
payment_method_name: string;
|
||||
}
|
||||
|
||||
interface MethodBoxesProps {
|
||||
methods?: HodlOfferPaymentType[] | null;
|
||||
}
|
||||
|
||||
const StyledMethodBoxes = styled.div`
|
||||
width: 100%;
|
||||
position: relative;
|
||||
right: -16px;
|
||||
top: -26px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin: 0 0 -24px 0;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
height: 23px;
|
||||
`;
|
||||
|
||||
const StyledMethod = styled.div`
|
||||
font-size: 12px;
|
||||
margin: 0 0 0 8px;
|
||||
border: 1px solid ${themeColors.blue2};
|
||||
border-radius: 4px;
|
||||
padding: 2px 4px;
|
||||
background: ${subCardColor};
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
export const MethodBoxes = ({ methods }: MethodBoxesProps) => {
|
||||
if (!methods?.length) return null;
|
||||
|
||||
return (
|
||||
<StyledMethodBoxes>
|
||||
{methods.map((method, index) => (
|
||||
<StyledMethod key={`${method.payment_method_name}/${index}`}>
|
||||
{method.payment_method_name}
|
||||
</StyledMethod>
|
||||
))}
|
||||
</StyledMethodBoxes>
|
||||
);
|
||||
};
|
|
@ -1,163 +0,0 @@
|
|||
import React, { useState, useEffect, Dispatch } from 'react';
|
||||
import ScaleLoader from 'react-spinners/ScaleLoader';
|
||||
import { toast } from 'react-toastify';
|
||||
import {
|
||||
useGetCountriesQuery,
|
||||
useGetCurrenciesQuery,
|
||||
GetCountriesQuery,
|
||||
GetCurrenciesQuery,
|
||||
} from 'src/graphql/hodlhodl/__generated__/query.generated';
|
||||
import { HodlCountryType, HodlCurrencyType } from 'src/graphql/types';
|
||||
import { SubTitle } from '../../../components/generic/Styled';
|
||||
import { SortOptions, NewOptions } from '../OfferConfigs';
|
||||
import { FilterType, FilterActionType } from '../OfferFilters';
|
||||
import { themeColors } from '../../../styles/Themes';
|
||||
import { OptionsLoading } from '../OfferCard.styled';
|
||||
import { FilteredList, FilteredOptionsProps } from './FilteredList';
|
||||
|
||||
export type ModalType = 'keysend' | 'request' | 'none' | 'new' | 'sort';
|
||||
interface FilterProps {
|
||||
type: string;
|
||||
dispatch: Dispatch<FilterActionType>;
|
||||
final?: { title: string; name: string; searchable?: boolean };
|
||||
newOptions?: FilterType[];
|
||||
setModalType: (type: ModalType) => void;
|
||||
}
|
||||
|
||||
interface CountryType {
|
||||
code: string;
|
||||
name: string;
|
||||
native_name: string;
|
||||
currency_code: string;
|
||||
currency_name: string;
|
||||
}
|
||||
|
||||
interface CurrencyType {
|
||||
code: string;
|
||||
name: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export const FilterModal = ({
|
||||
type,
|
||||
dispatch,
|
||||
final,
|
||||
newOptions,
|
||||
setModalType,
|
||||
}: FilterProps) => {
|
||||
const searchable: boolean = final?.searchable ?? false;
|
||||
const skipable: boolean = type !== 'Country' && type !== 'Currency';
|
||||
|
||||
const [selected, setSelected] = useState<FilteredOptionsProps>();
|
||||
|
||||
const [options, setOptions] = useState(newOptions ?? []);
|
||||
const [title, setTitle] = useState(final?.title ?? '');
|
||||
|
||||
const useQuery =
|
||||
type === 'Country' ? useGetCountriesQuery : useGetCurrenciesQuery;
|
||||
|
||||
const { loading, data, error } = useQuery({
|
||||
skip: skipable,
|
||||
onError: () => toast.error('Error Loading Options. Please try again.'),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
switch (type) {
|
||||
case 'sort':
|
||||
setTitle('Sort Offers by:');
|
||||
setOptions(SortOptions);
|
||||
break;
|
||||
case 'new':
|
||||
setTitle('Add New Filter:');
|
||||
setOptions(NewOptions);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}, [type]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && data && (data as GetCountriesQuery).getCountries) {
|
||||
const countryOptions =
|
||||
(data as GetCountriesQuery).getCountries?.map(country => {
|
||||
const { code, name, native_name } = country as HodlCountryType;
|
||||
return { name: code || '', title: `${name} (${native_name})` };
|
||||
}) || [];
|
||||
|
||||
setOptions(countryOptions);
|
||||
}
|
||||
if (!loading && data && (data as GetCurrenciesQuery).getCurrencies) {
|
||||
const filtered =
|
||||
(data as GetCurrenciesQuery).getCurrencies?.filter(
|
||||
currency => currency?.type === 'fiat'
|
||||
) || [];
|
||||
|
||||
const currencyOptions = filtered.map(currency => {
|
||||
const { code, name } = currency as HodlCurrencyType;
|
||||
return { name: code || '', title: name || '' };
|
||||
});
|
||||
|
||||
setOptions(currencyOptions);
|
||||
}
|
||||
}, [data, loading]);
|
||||
|
||||
const handleClick = (name: string, option: FilteredOptionsProps) => () => {
|
||||
if (final) {
|
||||
dispatch({
|
||||
type: 'addFilter',
|
||||
newItem: { [final.name]: name },
|
||||
});
|
||||
setModalType('none');
|
||||
}
|
||||
switch (type) {
|
||||
case 'sort':
|
||||
if (name === 'none') {
|
||||
dispatch({
|
||||
type: 'removeSort',
|
||||
});
|
||||
} else {
|
||||
dispatch({
|
||||
type: 'addSort',
|
||||
newItem: { by: name },
|
||||
});
|
||||
}
|
||||
setModalType('none');
|
||||
break;
|
||||
case 'new':
|
||||
setSelected(option);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
return (
|
||||
<FilterModal
|
||||
type={selected.title}
|
||||
dispatch={dispatch}
|
||||
final={selected}
|
||||
newOptions={selected.options}
|
||||
setModalType={setModalType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SubTitle>{title}</SubTitle>
|
||||
<FilteredList
|
||||
searchable={searchable}
|
||||
options={options}
|
||||
handleClick={handleClick}
|
||||
/>
|
||||
<OptionsLoading>
|
||||
{loading && <ScaleLoader height={20} color={themeColors.blue3} />}
|
||||
</OptionsLoading>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,78 +0,0 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { ColorButton } from '../../../components/buttons/colorButton/ColorButton';
|
||||
import { OfferModalBox } from '../OfferCard.styled';
|
||||
import { Input } from '../../../components/input/Input';
|
||||
import { Sub4Title } from '../../../components/generic/Styled';
|
||||
import { FilterType } from '../OfferFilters';
|
||||
|
||||
interface FilteredProps {
|
||||
searchable: boolean;
|
||||
options: FilterType[];
|
||||
handleClick: (name: string, option: FilteredOptionsProps) => () => void;
|
||||
}
|
||||
|
||||
export interface FilteredOptionsProps {
|
||||
name: string;
|
||||
title: string;
|
||||
options?: FilterType[];
|
||||
}
|
||||
|
||||
export const FilteredList = ({
|
||||
searchable,
|
||||
options,
|
||||
handleClick,
|
||||
}: FilteredProps) => {
|
||||
const [searchTerm, setSearchTerm] = useState<string>('');
|
||||
const [filteredOptions, setOptions] = useState<FilteredOptionsProps[]>(
|
||||
options
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const filtered = options.filter(
|
||||
(option: { name: string; title: string }) => {
|
||||
const inName = option.name
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase());
|
||||
const inTitle = option.title
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase());
|
||||
|
||||
return inName || inTitle;
|
||||
}
|
||||
);
|
||||
setOptions(filtered);
|
||||
}, [searchTerm, options]);
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchTerm(event.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{searchable && (
|
||||
<Input
|
||||
placeholder={'Search'}
|
||||
fullWidth={true}
|
||||
onChange={handleChange}
|
||||
withMargin={'0 0 8px 0'}
|
||||
/>
|
||||
)}
|
||||
<OfferModalBox>
|
||||
{filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((option, index) => (
|
||||
<ColorButton
|
||||
key={`${index}-${option.name}`}
|
||||
fullWidth={true}
|
||||
withMargin={'0 0 2px 0'}
|
||||
onClick={handleClick(option.name, option)}
|
||||
>
|
||||
{option.title}
|
||||
</ColorButton>
|
||||
))
|
||||
) : (
|
||||
<Sub4Title>No results</Sub4Title>
|
||||
)}
|
||||
</OfferModalBox>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,54 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
import { ChevronRight } from 'react-feather';
|
||||
import { unSelectedNavButton, mediaWidths } from '../../styles/Themes';
|
||||
|
||||
export const TradesAmount = styled.div`
|
||||
font-size: 14px;
|
||||
color: ${unSelectedNavButton};
|
||||
margin: 0 4px;
|
||||
`;
|
||||
|
||||
export const StyleArrow = styled(ChevronRight)`
|
||||
margin-bottom: -3px;
|
||||
`;
|
||||
|
||||
export const OfferModalBox = styled.div`
|
||||
overflow-y: auto;
|
||||
max-height: 640px;
|
||||
min-height: 240px;
|
||||
@media (${mediaWidths.mobile}) {
|
||||
max-height: 240px;
|
||||
min-height: 120px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledTitle = styled.div`
|
||||
font-size: 14px;
|
||||
margin: 16px 0;
|
||||
|
||||
@media (${mediaWidths.mobile}) {
|
||||
text-align: center;
|
||||
margin-top: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledLogin = styled.div`
|
||||
max-width: 160px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
|
||||
export const StyledDescription = styled(StyledLogin)`
|
||||
max-width: unset;
|
||||
overflow-y: auto;
|
||||
font-size: 14px;
|
||||
max-height: 160px;
|
||||
`;
|
||||
|
||||
export const OptionsLoading = styled.div`
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
|
@ -1,192 +0,0 @@
|
|||
import React from 'react';
|
||||
import numeral from 'numeral';
|
||||
import { HodlOfferType, HodlOfferPaymentType } from 'src/graphql/types';
|
||||
import {
|
||||
SubCard,
|
||||
Sub4Title,
|
||||
SubTitle,
|
||||
SingleLine,
|
||||
ResponsiveLine,
|
||||
Separation,
|
||||
} from '../../components/generic/Styled';
|
||||
import { Rating } from '../../components/rating/Rating';
|
||||
import { MainInfo } from '../../components/generic/CardGeneric';
|
||||
import { themeColors } from '../../styles/Themes';
|
||||
import { renderLine } from '../../components/generic/helpers';
|
||||
import { Link } from '../../components/link/Link';
|
||||
import { ColorButton } from '../../components/buttons/colorButton/ColorButton';
|
||||
import { MethodBoxes } from './MethodBoxes';
|
||||
import {
|
||||
TradesAmount,
|
||||
StyleArrow,
|
||||
StyledTitle,
|
||||
StyledLogin,
|
||||
StyledDescription,
|
||||
} from './OfferCard.styled';
|
||||
|
||||
const format = (value: number | string | null | undefined, format = '0,0.00') =>
|
||||
value ? numeral(value).format(format) : null;
|
||||
|
||||
interface OfferCardProps {
|
||||
offer: HodlOfferType;
|
||||
index: number;
|
||||
setIndexOpen: (index: number) => void;
|
||||
indexOpen: number;
|
||||
}
|
||||
|
||||
export const OfferCard = ({
|
||||
offer,
|
||||
index,
|
||||
setIndexOpen,
|
||||
indexOpen,
|
||||
}: OfferCardProps) => {
|
||||
const {
|
||||
id,
|
||||
asset_code,
|
||||
country,
|
||||
country_code,
|
||||
working_now,
|
||||
side,
|
||||
title,
|
||||
description,
|
||||
currency_code,
|
||||
price,
|
||||
min_amount,
|
||||
max_amount,
|
||||
first_trade_limit,
|
||||
fee,
|
||||
balance,
|
||||
payment_window_minutes,
|
||||
confirmations,
|
||||
payment_method_instructions,
|
||||
trader,
|
||||
} = offer;
|
||||
|
||||
const { author_fee_rate } = fee || {};
|
||||
|
||||
const {
|
||||
login,
|
||||
online_status,
|
||||
rating,
|
||||
trades_count = 0,
|
||||
url,
|
||||
verified,
|
||||
verified_by,
|
||||
strong_hodler,
|
||||
country: traderCountry,
|
||||
country_code: traderCode,
|
||||
average_payment_time_minutes,
|
||||
average_release_time_minutes,
|
||||
days_since_last_trade,
|
||||
} = trader || {};
|
||||
|
||||
const handleClick = () => {
|
||||
if (indexOpen === index) {
|
||||
setIndexOpen(0);
|
||||
} else {
|
||||
setIndexOpen(index);
|
||||
}
|
||||
};
|
||||
|
||||
const renderPayments = (): string => {
|
||||
if (payment_method_instructions) {
|
||||
const methods = payment_method_instructions.map(method =>
|
||||
method
|
||||
? `${method.payment_method_name} (${method.payment_method_type})`
|
||||
: ''
|
||||
);
|
||||
|
||||
return methods.join(', ');
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
const renderDetails = () => (
|
||||
<>
|
||||
<Separation />
|
||||
<StyledDescription>{description}</StyledDescription>
|
||||
<Separation />
|
||||
{renderLine('Price', format(price))}
|
||||
{renderLine('Min Amount:', format(min_amount))}
|
||||
{renderLine('Max Amount:', format(max_amount))}
|
||||
{renderLine('First Trade Limit:', format(first_trade_limit))}
|
||||
{renderLine('Payment Options:', renderPayments())}
|
||||
{renderLine('Country:', `${country} (${country_code})`)}
|
||||
{renderLine('Available Now:', working_now ? 'Yes' : 'No')}
|
||||
{renderLine('Balance:', format(balance))}
|
||||
{renderLine('Payment Window (min):', payment_window_minutes)}
|
||||
{renderLine('Confirmations:', confirmations)}
|
||||
{renderLine('Fee Rate:', `${format(Number(author_fee_rate) * 100)}%`)}
|
||||
<Separation />
|
||||
<Sub4Title>Trader</Sub4Title>
|
||||
{renderLine('User:', login)}
|
||||
{renderLine('Online:', online_status)}
|
||||
{renderLine('Rating:', rating)}
|
||||
{renderLine('Amount of Trades:', trades_count)}
|
||||
{renderLine('Verified:', verified ? 'True' : 'False')}
|
||||
{renderLine('Verified By:', verified_by)}
|
||||
{renderLine('Strong Hodler:', strong_hodler ? 'True' : 'False')}
|
||||
{renderLine('Country:', `${traderCountry} (${traderCode})`)}
|
||||
{renderLine('Average Payment Time (min):', average_payment_time_minutes)}
|
||||
{renderLine('Average Release Time (min):', average_release_time_minutes)}
|
||||
{renderLine('Days since last trade:', days_since_last_trade)}
|
||||
<SingleLine>
|
||||
<Link
|
||||
href={`https://hodlhodl.com/offers/${id}`}
|
||||
underline={'transparent'}
|
||||
fullWidth={true}
|
||||
>
|
||||
<ColorButton
|
||||
withBorder={true}
|
||||
withMargin={'16px 8px 0 0'}
|
||||
fullWidth={true}
|
||||
>
|
||||
View Offer
|
||||
</ColorButton>
|
||||
</Link>
|
||||
{url && (
|
||||
<Link href={url} underline={'transparent'} fullWidth={true}>
|
||||
<ColorButton
|
||||
withBorder={true}
|
||||
withMargin={'16px 0 0 8px'}
|
||||
fullWidth={true}
|
||||
>
|
||||
View trader
|
||||
</ColorButton>
|
||||
</Link>
|
||||
)}
|
||||
</SingleLine>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<SubCard withMargin={'16px 0 24px'} key={`${index}-${id}`}>
|
||||
<MainInfo onClick={() => handleClick()}>
|
||||
<MethodBoxes
|
||||
methods={payment_method_instructions as HodlOfferPaymentType[]}
|
||||
/>
|
||||
<ResponsiveLine>
|
||||
<SubTitle>
|
||||
{side !== 'buy' ? asset_code : currency_code}
|
||||
<StyleArrow size={18} color={themeColors.blue3} />
|
||||
{side !== 'buy' ? currency_code : asset_code}
|
||||
</SubTitle>
|
||||
<SingleLine>
|
||||
<StyledLogin>{login}</StyledLogin>
|
||||
{(trades_count || 0) > 0 && (
|
||||
<TradesAmount>{`(${trades_count}) `}</TradesAmount>
|
||||
)}
|
||||
<Rating rating={Number(rating)} />
|
||||
</SingleLine>
|
||||
</ResponsiveLine>
|
||||
<StyledTitle>{title}</StyledTitle>
|
||||
{renderLine('Price:', format(price))}
|
||||
{renderLine(
|
||||
'Min/Max amount:',
|
||||
`${format(min_amount, '0a')}/${format(max_amount, '0a')}`
|
||||
)}
|
||||
</MainInfo>
|
||||
{index === indexOpen && renderDetails()}
|
||||
</SubCard>
|
||||
);
|
||||
};
|
|
@ -1,141 +0,0 @@
|
|||
export const SortOptions = [
|
||||
{
|
||||
name: 'none',
|
||||
title: 'None',
|
||||
},
|
||||
{
|
||||
name: 'price',
|
||||
title: 'Price',
|
||||
},
|
||||
{
|
||||
name: 'payment_window_minutes',
|
||||
title: 'Payment Window',
|
||||
},
|
||||
{
|
||||
name: 'user_average_payment_time_minutes',
|
||||
title: 'Average Payment Time',
|
||||
},
|
||||
{
|
||||
name: 'user_average_release_time_minutes',
|
||||
title: 'Average Release Time',
|
||||
},
|
||||
{
|
||||
name: 'rating',
|
||||
title: 'Rating',
|
||||
},
|
||||
];
|
||||
|
||||
export const NewOptions = [
|
||||
{
|
||||
name: 'asset_code',
|
||||
title: 'Asset Code',
|
||||
options: [
|
||||
{
|
||||
name: 'BTC',
|
||||
title: 'Bitcoin',
|
||||
},
|
||||
{
|
||||
name: 'BTCLN',
|
||||
title: 'Lightning Bitcoin',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'side',
|
||||
title: 'Side',
|
||||
options: [
|
||||
{
|
||||
name: 'buy',
|
||||
title: 'I want to sell Bitcoin',
|
||||
},
|
||||
{
|
||||
name: 'sell',
|
||||
title: 'I want to buy Bitcoin',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'include_global',
|
||||
title: 'Include Global Offers',
|
||||
options: [
|
||||
{
|
||||
name: 'true',
|
||||
title: 'Yes',
|
||||
},
|
||||
{
|
||||
name: 'false',
|
||||
title: 'No',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'only_working_now',
|
||||
title: 'Only Working Now Offers',
|
||||
options: [
|
||||
{
|
||||
name: 'true',
|
||||
title: 'Yes',
|
||||
},
|
||||
{
|
||||
name: 'false',
|
||||
title: 'No',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'country',
|
||||
title: 'Country',
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
name: 'currency_code',
|
||||
title: 'Currency',
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
name: 'payment_method_type',
|
||||
title: 'Payment Type',
|
||||
options: [
|
||||
{
|
||||
name: 'Bank wire',
|
||||
title: 'Bank wire',
|
||||
},
|
||||
{
|
||||
name: 'Cash',
|
||||
title: 'Cash',
|
||||
},
|
||||
{
|
||||
name: 'Cryptocurrency',
|
||||
title: 'Cryptocurrency',
|
||||
},
|
||||
{
|
||||
name: 'Online payment system',
|
||||
title: 'Online payment system',
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// name: 'payment_method_id',
|
||||
// title: 'Payment Id',
|
||||
// },
|
||||
// {
|
||||
// name: 'payment_method_name',
|
||||
// title: 'Payment Name',
|
||||
// },
|
||||
// {
|
||||
// name: 'volume',
|
||||
// title: 'Volume',
|
||||
// },
|
||||
// {
|
||||
// name: 'payment_window_minutes_max',
|
||||
// title: 'Max Payment Window',
|
||||
// },
|
||||
// {
|
||||
// name: 'user_average_payment_time_minutes_max',
|
||||
// title: 'Max User Payment Time',
|
||||
// },
|
||||
// {
|
||||
// name: 'user_average_release_time_minutes_max',
|
||||
// title: 'Max User Release Time',
|
||||
// },
|
||||
];
|
|
@ -1,237 +0,0 @@
|
|||
import React, { useState, useReducer } from 'react';
|
||||
import { X } from 'react-feather';
|
||||
import { useRouter } from 'next/router';
|
||||
import {
|
||||
SingleLine,
|
||||
Separation,
|
||||
ResponsiveLine,
|
||||
NoWrapTitle,
|
||||
} from '../../components/generic/Styled';
|
||||
import { ColorButton } from '../../components/buttons/colorButton/ColorButton';
|
||||
import {
|
||||
MultiButton,
|
||||
SingleButton,
|
||||
} from '../../components/buttons/multiButton/MultiButton';
|
||||
import Modal from '../../components/modal/ReactModal';
|
||||
import { QueryProps } from '../../../pages/trading';
|
||||
import { renderLine } from '../../components/generic/helpers';
|
||||
import { chartColors } from '../../styles/Themes';
|
||||
import { encode } from '../../utils/helpers';
|
||||
import { appendBasePath } from '../../utils/basePath';
|
||||
import { SortOptions } from './OfferConfigs';
|
||||
import { FilterModal, ModalType } from './Modal/FilterModal';
|
||||
|
||||
export type FilterActionType = {
|
||||
type: 'addFilter' | 'addSort' | 'removeSort' | 'removeFilter' | 'changeLimit';
|
||||
state?: QueryProps;
|
||||
newItem?: {};
|
||||
removeKey?: string;
|
||||
changeLimit?: number;
|
||||
};
|
||||
|
||||
const reducer = (state: QueryProps, action: FilterActionType): QueryProps => {
|
||||
const { sort, filters } = state;
|
||||
switch (action.type) {
|
||||
case 'addSort': {
|
||||
let direction = {};
|
||||
if (sort && !sort.direction) {
|
||||
direction = { direction: 'desc' };
|
||||
}
|
||||
const newSort = { ...sort, ...direction, ...action.newItem };
|
||||
return { ...state, sort: newSort };
|
||||
}
|
||||
case 'removeSort':
|
||||
return { ...state, sort: { by: '', direction: '' } };
|
||||
case 'addFilter': {
|
||||
const newFilters = { ...filters, ...action.newItem };
|
||||
return { ...state, filters: newFilters };
|
||||
}
|
||||
case 'removeFilter':
|
||||
if (action.removeKey) {
|
||||
const remaining = { ...filters };
|
||||
delete remaining[action.removeKey];
|
||||
return { ...state, filters: remaining };
|
||||
}
|
||||
return state;
|
||||
case 'changeLimit':
|
||||
if (action.changeLimit) {
|
||||
return {
|
||||
...state,
|
||||
pagination: { limit: action.changeLimit, offset: 0 },
|
||||
};
|
||||
}
|
||||
return state;
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
};
|
||||
|
||||
interface FilterProps {
|
||||
offerFilters: QueryProps;
|
||||
}
|
||||
|
||||
export interface FilterType {
|
||||
name: string;
|
||||
title: string;
|
||||
optionOne?: string;
|
||||
optionTwo?: string;
|
||||
}
|
||||
|
||||
export const OfferFilters = ({ offerFilters }: FilterProps) => {
|
||||
const { push } = useRouter();
|
||||
|
||||
const [filterState, dispatch] = useReducer(reducer, offerFilters);
|
||||
|
||||
const [modalType, setModalType] = useState<ModalType>('none');
|
||||
const [willApply, setWillApply] = useState<boolean>(false);
|
||||
|
||||
const renderButton = (
|
||||
onClick: () => void,
|
||||
text: string,
|
||||
selected: boolean
|
||||
) => (
|
||||
<SingleButton selected={selected} onClick={onClick}>
|
||||
{text}
|
||||
</SingleButton>
|
||||
);
|
||||
|
||||
const handleSave = () => {
|
||||
const stringFormat = JSON.stringify(filterState);
|
||||
const encoded = encode(stringFormat);
|
||||
push(appendBasePath(`/trading?filter=${encoded}`));
|
||||
};
|
||||
|
||||
const handleRemoveAll = () => push(appendBasePath('/trading'));
|
||||
|
||||
const handleRemove = (removeKey: string) => {
|
||||
dispatch({ type: 'removeFilter', removeKey });
|
||||
};
|
||||
|
||||
const renderAppliedFilters = () => {
|
||||
const currentFilters = filterState.filters;
|
||||
const activeFilters = Object.entries(currentFilters).map(([key, element]) =>
|
||||
renderLine(key, element, `${key}-${element}`, () => handleRemove(key))
|
||||
);
|
||||
return <>{activeFilters}</>;
|
||||
};
|
||||
|
||||
const renderLimitOptions = () => {
|
||||
const currentLimit = filterState.pagination.limit;
|
||||
|
||||
const renderButton = (value: number, margin?: string) => (
|
||||
<ColorButton
|
||||
onClick={() => dispatch({ type: 'changeLimit', changeLimit: value })}
|
||||
selected={currentLimit === value}
|
||||
withMargin={margin}
|
||||
>
|
||||
{value}
|
||||
</ColorButton>
|
||||
);
|
||||
|
||||
return (
|
||||
<SingleLine>
|
||||
{renderButton(25)}
|
||||
{renderButton(50, '0 4px 0')}
|
||||
{renderButton(100)}
|
||||
</SingleLine>
|
||||
);
|
||||
};
|
||||
|
||||
const renderFilters = () => {
|
||||
return (
|
||||
<>
|
||||
<Separation />
|
||||
<ResponsiveLine>
|
||||
<NoWrapTitle>Results:</NoWrapTitle>
|
||||
{renderLimitOptions()}
|
||||
</ResponsiveLine>
|
||||
<Separation />
|
||||
<ResponsiveLine>
|
||||
<NoWrapTitle>Filters</NoWrapTitle>
|
||||
<ColorButton arrow={true} onClick={() => setModalType('new')}>
|
||||
New Filter
|
||||
</ColorButton>
|
||||
</ResponsiveLine>
|
||||
{Object.keys(filterState.filters).length > 0 && renderAppliedFilters()}
|
||||
<Separation />
|
||||
<ResponsiveLine>
|
||||
<NoWrapTitle>Sort By:</NoWrapTitle>
|
||||
<ColorButton arrow={true} onClick={() => setModalType('sort')}>
|
||||
{SortOptions.find(option => option.name === filterState.sort.by)
|
||||
?.title ?? 'None'}
|
||||
</ColorButton>
|
||||
</ResponsiveLine>
|
||||
{!!filterState.sort.by && (
|
||||
<ResponsiveLine>
|
||||
<NoWrapTitle>Sort Direction:</NoWrapTitle>
|
||||
<MultiButton>
|
||||
{renderButton(
|
||||
() => {
|
||||
dispatch({
|
||||
type: 'addSort',
|
||||
newItem: { direction: 'asc' },
|
||||
});
|
||||
},
|
||||
'Asc',
|
||||
filterState.sort.direction === 'asc'
|
||||
)}
|
||||
{renderButton(
|
||||
() => {
|
||||
dispatch({
|
||||
type: 'addSort',
|
||||
newItem: { direction: 'desc' },
|
||||
});
|
||||
},
|
||||
'Desc',
|
||||
filterState.sort.direction !== 'asc'
|
||||
)}
|
||||
</MultiButton>
|
||||
</ResponsiveLine>
|
||||
)}
|
||||
<Separation />
|
||||
<SingleLine>
|
||||
<ColorButton
|
||||
fullWidth={true}
|
||||
withMargin={'16px 4px 0 0'}
|
||||
onClick={handleSave}
|
||||
>
|
||||
Filter
|
||||
</ColorButton>
|
||||
<ColorButton
|
||||
color={chartColors.orange2}
|
||||
fullWidth={true}
|
||||
withMargin={'16px 0 0 4px'}
|
||||
onClick={handleRemoveAll}
|
||||
>
|
||||
Remove All
|
||||
</ColorButton>
|
||||
</SingleLine>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SingleLine>
|
||||
Filters
|
||||
<ColorButton
|
||||
arrow={!willApply}
|
||||
onClick={() => setWillApply(prev => !prev)}
|
||||
>
|
||||
{willApply ? <X size={18} /> : 'Apply'}
|
||||
</ColorButton>
|
||||
</SingleLine>
|
||||
{willApply && renderFilters()}
|
||||
<Modal
|
||||
isOpen={modalType !== 'none'}
|
||||
closeCallback={() => setModalType('none')}
|
||||
>
|
||||
<FilterModal
|
||||
type={modalType}
|
||||
dispatch={dispatch}
|
||||
setModalType={setModalType}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
Loading…
Add table
Reference in a new issue