From 4922994da6d380510342d76ac23c46ae414d8251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Fri, 13 Aug 2021 23:55:37 -0300 Subject: [PATCH 1/6] add exchange order screen --- app/javascript/__generated__/schema.graphql | 51 ++++ app/javascript/src/Routes.tsx | 5 +- app/javascript/src/components/SideNav.tsx | 4 + .../src/pages/Orders/Exchange/Exchange.tsx | 182 ++++++++++++ .../__generated__/ExchangeQuery.graphql.ts | 259 ++++++++++++++++++ .../src/pages/Orders/Exchange/index.ts | 1 + app/javascript/src/pages/Orders/index.ts | 5 + app/javascript/src/pages/index.ts | 1 + app/models/user.rb | 2 +- package.json | 1 + spec/models/user_spec.rb | 3 +- yarn.lock | 5 + 12 files changed, 516 insertions(+), 3 deletions(-) create mode 100644 app/javascript/src/pages/Orders/Exchange/Exchange.tsx create mode 100644 app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts create mode 100644 app/javascript/src/pages/Orders/Exchange/index.ts create mode 100644 app/javascript/src/pages/Orders/index.ts diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index daacf47..c945e2f 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -39,6 +39,36 @@ type Currency implements Node { name: String! } +""" +The connection type for Currency. +""" +type CurrencyConnection { + """ + A list of edges. + """ + edges: [CurrencyEdge!]! + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CurrencyEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: Currency! +} + type FiatBalance implements Node { amountCents: Int! amountCurrency: String! @@ -139,6 +169,27 @@ type Query { """ last: Int ): BalanceConnection! + currencies( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CurrencyConnection! currentUser: User fiatBalances( """ diff --git a/app/javascript/src/Routes.tsx b/app/javascript/src/Routes.tsx index b429084..de22071 100644 --- a/app/javascript/src/Routes.tsx +++ b/app/javascript/src/Routes.tsx @@ -2,7 +2,7 @@ import type { FC } from "react"; import React from "react"; import { Switch, Route } from "react-router-dom"; -import { Home, Wallet } from "./pages"; +import { Home, Orders, Wallet } from "./pages"; export const Routes: FC = () => { return ( @@ -13,6 +13,9 @@ export const Routes: FC = () => { + + + ); }; diff --git a/app/javascript/src/components/SideNav.tsx b/app/javascript/src/components/SideNav.tsx index 2cfc4b9..0917cb6 100644 --- a/app/javascript/src/components/SideNav.tsx +++ b/app/javascript/src/components/SideNav.tsx @@ -18,6 +18,10 @@ const MenuItems: MenuItem[] = [ label: "Carteira", path: "/wallet", }, + { + label: "Ordem de Troca", + path: "/orders/exchange", + }, ]; export const SideNav = () => { diff --git a/app/javascript/src/pages/Orders/Exchange/Exchange.tsx b/app/javascript/src/pages/Orders/Exchange/Exchange.tsx new file mode 100644 index 0000000..a607ad1 --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/Exchange.tsx @@ -0,0 +1,182 @@ +import React, { useState } from "react"; +import type { FC } from "react"; +import { graphql } from "babel-plugin-relay/macro"; +import { useLazyLoadQuery } from "react-relay"; +import { BigNumber } from "bignumber.js"; +import cx from "classnames"; + +import { useCurrentUser } from "../../../contexts/UserProvider"; +import { Unauthenticated } from "../../../messages/Unauthenticated"; +import type { ExchangeQuery } from "./__generated__/ExchangeQuery.graphql"; + +const tabBaseStyles = + "w-full text-base font-bold text-black px-4 py-2 focus:ring-blue-500"; + +const selectedTabStyles = + "bg-blue-600 hover:bg-blue-700 rounded-l-frounded-full text-white"; + +const inputBaseStyles = + "rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent mb-3"; + +export const Exchange: FC = () => { + const { isAuthenticated } = useCurrentUser(); + const [exchangeOption, setExchangeOption] = useState<"BUY" | "SELL">("BUY"); + const [cryptoDock, setCryptoDock] = useState("0"); + const [fiatDock, setFiatDock] = useState("0.00"); + + const { balances, fiatBalances } = useLazyLoadQuery( + graphql` + query ExchangeQuery { + fiatBalances { + edges { + node { + id + amountCents + amountCurrency + } + } + } + balances { + edges { + node { + id + amount + currency { + name + } + } + } + } + } + `, + {} + ); + + if (!isAuthenticated) return ; + const [crypto] = balances.edges; + const [fiat] = fiatBalances.edges; + + const avaliableCrypto = new BigNumber(crypto.node.amount); + const avaliableFiat = ( + fiat.node.amountCents ? fiat.node.amountCents / 100 : 0 + ).toFixed(2); + + const handleSellTabClick = () => { + setExchangeOption("SELL"); + setCryptoDock("0"); + }; + + const handleBuyTabClick = () => { + setExchangeOption("BUY"); + setCryptoDock("0"); + }; + + const handleCryptoAmountChange = ({ + currentTarget: { value }, + }: React.ChangeEvent) => { + const newCryptoAmount = new BigNumber(value); + + if (newCryptoAmount.isLessThanOrEqualTo(avaliableCrypto)) { + setCryptoDock(value); + } + }; + + const handleFiatAmountChange = ({ + currentTarget: { value }, + }: React.ChangeEvent) => { + const newFiatAmount = Number(value); + + if (Number(avaliableFiat) >= newFiatAmount) { + setFiatDock(value); + } + }; + + const handleMaxFiatDockButton = () => { + setFiatDock(avaliableFiat); + }; + + const handleMaxCryptoButton = () => { + setCryptoDock(avaliableCrypto.toString()); + }; + + return ( +
+
+
+ + +
+
+ + {exchangeOption === "SELL" ? "CAKE" : "BRL"} disponível:{" "} + {exchangeOption === "SELL" ? crypto.node.amount : avaliableFiat} + +
+ {exchangeOption === "BUY" ? ( + <> + + + + ) : ( + <> + + + + )} +
+ + +
+
+
+ ); +}; diff --git a/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts b/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts new file mode 100644 index 0000000..becd5d9 --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts @@ -0,0 +1,259 @@ +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from "relay-runtime"; +export type ExchangeQueryVariables = {}; +export type ExchangeQueryResponse = { + readonly fiatBalances: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly id: string; + readonly amountCents: number; + readonly amountCurrency: string; + }; + }>; + }; + readonly balances: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly id: string; + readonly amount: string; + readonly currency: { + readonly name: string; + }; + }; + }>; + }; +}; +export type ExchangeQuery = { + readonly response: ExchangeQueryResponse; + readonly variables: ExchangeQueryVariables; +}; + + + +/* +query ExchangeQuery { + fiatBalances { + edges { + node { + id + amountCents + amountCurrency + } + } + } + balances { + edges { + node { + id + amount + currency { + name + id + } + } + } + } +} +*/ + +const node: ConcreteRequest = (function(){ +var v0 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v1 = { + "alias": null, + "args": null, + "concreteType": "FiatBalanceConnection", + "kind": "LinkedField", + "name": "fiatBalances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v0/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "amountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "amountCurrency", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null +}, +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "amount", + "storageKey": null +}, +v3 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null +}; +return { + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "ExchangeQuery", + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "BalanceConnection", + "kind": "LinkedField", + "name": "balances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "BalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Balance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v0/*: any*/), + (v2/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "Currency", + "kind": "LinkedField", + "name": "currency", + "plural": false, + "selections": [ + (v3/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [], + "kind": "Operation", + "name": "ExchangeQuery", + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "BalanceConnection", + "kind": "LinkedField", + "name": "balances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "BalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Balance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v0/*: any*/), + (v2/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "Currency", + "kind": "LinkedField", + "name": "currency", + "plural": false, + "selections": [ + (v3/*: any*/), + (v0/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "7a42b2fc93f97505aaaf21867de36321", + "id": null, + "metadata": {}, + "name": "ExchangeQuery", + "operationKind": "query", + "text": "query ExchangeQuery {\n fiatBalances {\n edges {\n node {\n id\n amountCents\n amountCurrency\n }\n }\n }\n balances {\n edges {\n node {\n id\n amount\n currency {\n name\n id\n }\n }\n }\n }\n}\n" + } +}; +})(); +(node as any).hash = '80cac44f2e6288dfb573d0037b7d4148'; +export default node; diff --git a/app/javascript/src/pages/Orders/Exchange/index.ts b/app/javascript/src/pages/Orders/Exchange/index.ts new file mode 100644 index 0000000..9196238 --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/index.ts @@ -0,0 +1 @@ +export * from "./Exchange"; diff --git a/app/javascript/src/pages/Orders/index.ts b/app/javascript/src/pages/Orders/index.ts new file mode 100644 index 0000000..5824f1b --- /dev/null +++ b/app/javascript/src/pages/Orders/index.ts @@ -0,0 +1,5 @@ +import { Exchange } from "./Exchange"; + +export const Orders = { + Exchange, +}; diff --git a/app/javascript/src/pages/index.ts b/app/javascript/src/pages/index.ts index f07c67e..e00ff4d 100644 --- a/app/javascript/src/pages/index.ts +++ b/app/javascript/src/pages/index.ts @@ -1,2 +1,3 @@ export * from "./Home"; export * from "./Wallet"; +export * from "./Orders"; diff --git a/app/models/user.rb b/app/models/user.rb index 26d827a..cbc1d8d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,7 +25,7 @@ class User < ApplicationRecord :recoverable, :rememberable, :validatable has_many :documents, class_name: "UserDocument", dependent: :destroy - has_many :balances, dependent: :restrict_with_error + has_one :balance, dependent: :restrict_with_error has_one :fiat_balance, dependent: :restrict_with_error validates :first_name, :last_name, :email, presence: true diff --git a/package.json b/package.json index 6a22fd4..d2bb066 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "autoprefixer": "^9", "babel-plugin-macros": "^3.1.0", "babel-plugin-relay": "^11.0.2", + "bignumber.js": "^9.0.1", "classnames": "^2.3.1", "postcss": "^7", "ramda": "^0.27.1", diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 8845843..ce70b21 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -31,6 +31,7 @@ RSpec.describe(User, type: :model) do describe "associations" do it { is_expected.to(have_many(:documents)) } - it { is_expected.to(have_many(:balances)) } + it { is_expected.to(have_one(:balance)) } + it { is_expected.to(have_one(:fiat_balance)) } end end diff --git a/yarn.lock b/yarn.lock index 1c6891a..0fb4192 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2024,6 +2024,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +bignumber.js@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" + integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" From 249925e1765c51af0a9a26d688a7784cf7eb968c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sat, 14 Aug 2021 11:37:55 -0300 Subject: [PATCH 2/6] add relay eslint plugin --- .eslintrc | 8 +- .../src/pages/Orders/Exchange/Exchange.tsx | 6 - .../__generated__/ExchangeQuery.graphql.ts | 178 ++++++++---------- package.json | 1 + yarn.lock | 9 +- 5 files changed, 95 insertions(+), 107 deletions(-) diff --git a/.eslintrc b/.eslintrc index 7f775ba..bea5ba5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": ["vtex"], + "extends": ["vtex", "plugin:relay/recommended"], "ignorePatterns": [ "__mocks__/", "__generated__/" @@ -9,5 +9,9 @@ "files": ["**/*.tsx"], "extends": ["vtex-react"] } - ] + ], + "rules": { + "relay/generated-flow-types": "false" + }, + "plugins": ["relay"] } diff --git a/app/javascript/src/pages/Orders/Exchange/Exchange.tsx b/app/javascript/src/pages/Orders/Exchange/Exchange.tsx index a607ad1..296128b 100644 --- a/app/javascript/src/pages/Orders/Exchange/Exchange.tsx +++ b/app/javascript/src/pages/Orders/Exchange/Exchange.tsx @@ -30,20 +30,14 @@ export const Exchange: FC = () => { fiatBalances { edges { node { - id amountCents - amountCurrency } } } balances { edges { node { - id amount - currency { - name - } } } } diff --git a/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts b/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts index becd5d9..bab9853 100644 --- a/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts +++ b/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts @@ -8,20 +8,14 @@ export type ExchangeQueryResponse = { readonly fiatBalances: { readonly edges: ReadonlyArray<{ readonly node: { - readonly id: string; readonly amountCents: number; - readonly amountCurrency: string; }; }>; }; readonly balances: { readonly edges: ReadonlyArray<{ readonly node: { - readonly id: string; readonly amount: string; - readonly currency: { - readonly name: string; - }; }; }>; }; @@ -38,21 +32,16 @@ query ExchangeQuery { fiatBalances { edges { node { - id amountCents - amountCurrency + id } } } balances { edges { node { - id amount - currency { - name - id - } + id } } } @@ -64,69 +53,21 @@ var v0 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "id", + "name": "amountCents", "storageKey": null }, v1 = { - "alias": null, - "args": null, - "concreteType": "FiatBalanceConnection", - "kind": "LinkedField", - "name": "fiatBalances", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "FiatBalanceEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "FiatBalance", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v0/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "amountCents", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "amountCurrency", - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null -}, -v2 = { "alias": null, "args": null, "kind": "ScalarField", "name": "amount", "storageKey": null }, -v3 = { +v2 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "name", + "name": "id", "storageKey": null }; return { @@ -136,7 +77,40 @@ return { "metadata": null, "name": "ExchangeQuery", "selections": [ - (v1/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceConnection", + "kind": "LinkedField", + "name": "fiatBalances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v0/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + }, { "alias": null, "args": null, @@ -161,20 +135,7 @@ return { "name": "node", "plural": false, "selections": [ - (v0/*: any*/), - (v2/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Currency", - "kind": "LinkedField", - "name": "currency", - "plural": false, - "selections": [ - (v3/*: any*/) - ], - "storageKey": null - } + (v1/*: any*/) ], "storageKey": null } @@ -194,7 +155,41 @@ return { "kind": "Operation", "name": "ExchangeQuery", "selections": [ - (v1/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceConnection", + "kind": "LinkedField", + "name": "fiatBalances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v0/*: any*/), + (v2/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + }, { "alias": null, "args": null, @@ -219,21 +214,8 @@ return { "name": "node", "plural": false, "selections": [ - (v0/*: any*/), - (v2/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Currency", - "kind": "LinkedField", - "name": "currency", - "plural": false, - "selections": [ - (v3/*: any*/), - (v0/*: any*/) - ], - "storageKey": null - } + (v1/*: any*/), + (v2/*: any*/) ], "storageKey": null } @@ -246,14 +228,14 @@ return { ] }, "params": { - "cacheID": "7a42b2fc93f97505aaaf21867de36321", + "cacheID": "bb1b8283beba2daf38bacec716816383", "id": null, "metadata": {}, "name": "ExchangeQuery", "operationKind": "query", - "text": "query ExchangeQuery {\n fiatBalances {\n edges {\n node {\n id\n amountCents\n amountCurrency\n }\n }\n }\n balances {\n edges {\n node {\n id\n amount\n currency {\n name\n id\n }\n }\n }\n }\n}\n" + "text": "query ExchangeQuery {\n fiatBalances {\n edges {\n node {\n amountCents\n id\n }\n }\n }\n balances {\n edges {\n node {\n amount\n id\n }\n }\n }\n}\n" } }; })(); -(node as any).hash = '80cac44f2e6288dfb573d0037b7d4148'; +(node as any).hash = '517d3bf7bc6330021f8eb615e78417f5'; export default node; diff --git a/package.json b/package.json index d2bb066..11db0f0 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "eslint": "^7.32.0", "eslint-config-vtex": "^14.1.0", "eslint-config-vtex-react": "^8.1.0", + "eslint-plugin-relay": "^1.8.2", "graphql": "^15.5.1", "prettier": "^2.3.2", "relay-compiler": "^11.0.2", diff --git a/yarn.lock b/yarn.lock index 0fb4192..f412efe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3563,6 +3563,13 @@ eslint-plugin-react@^7.20.6: resolve "^2.0.0-next.3" string.prototype.matchall "^4.0.5" +eslint-plugin-relay@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-1.8.2.tgz#925f59231e39dfc076b3cbb39ef793c13381579e" + integrity sha512-bqIfXJnPMd6iHPitONSi8JqxrWQWaX4Rqk1shusKDlUu5vswUgoqOEGgqE8nDu6SmejBUZMz0vY+ROvq5wqOsw== + dependencies: + graphql "^14.0.0 || ^15.0.0" + eslint-plugin-vtex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-vtex/-/eslint-plugin-vtex-2.1.0.tgz#cb328b5d6f4bba400cf57d5dca679985ac768e2a" @@ -4256,7 +4263,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== -graphql@^15.5.1: +"graphql@^14.0.0 || ^15.0.0", graphql@^15.5.1: version "15.5.1" resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.1.tgz#f2f84415d8985e7b84731e7f3536f8bb9d383aad" integrity sha512-FeTRX67T3LoE3LWAxxOlW2K3Bz+rMYAC18rRguK4wgXaTZMiJwSUwDmPFo3UadAKbzirKIg5Qy+sNJXbpPRnQw== From 51a493b327b85673c680ec3a13e77369972bce3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sat, 14 Aug 2021 11:45:25 -0300 Subject: [PATCH 3/6] remove unused GraphQl input --- app/graphql/inputs/user_attributes_input.rb | 9 --------- spec/graphql/inputs/user_attributes_input_spec.rb | 11 ----------- 2 files changed, 20 deletions(-) delete mode 100644 app/graphql/inputs/user_attributes_input.rb delete mode 100644 spec/graphql/inputs/user_attributes_input_spec.rb diff --git a/app/graphql/inputs/user_attributes_input.rb b/app/graphql/inputs/user_attributes_input.rb deleted file mode 100644 index 61dc56a..0000000 --- a/app/graphql/inputs/user_attributes_input.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true -module Inputs - class UserAttributesInput < Types::BaseInputObject - graphql_name "UserAttributesInput" - - argument :first_name, String, required: true - argument :last_name, String, required: true - end -end diff --git a/spec/graphql/inputs/user_attributes_input_spec.rb b/spec/graphql/inputs/user_attributes_input_spec.rb deleted file mode 100644 index d3fe858..0000000 --- a/spec/graphql/inputs/user_attributes_input_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true -require "rails_helper" - -RSpec.describe(Inputs::UserAttributesInput) do - subject { described_class } - - describe "arguments" do - it { is_expected.to(accept_argument(:first_name).of_type("String!")) } - it { is_expected.to(accept_argument(:last_name).of_type("String!")) } - end -end From 97c6f28b03c710a0a1801db2efee87f298f90f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sat, 14 Aug 2021 11:58:51 -0300 Subject: [PATCH 4/6] improve test setup with factory bot --- Gemfile | 4 +++- Gemfile.lock | 23 ++++++++------------ spec/factories/admin_users.rb | 26 ++++++++++++++++++++++ spec/factories/balances.rb | 30 ++++++++++++++++++++++++++ spec/factories/currencies.rb | 16 ++++++++++++++ spec/factories/fiat_balances.rb | 28 ++++++++++++++++++++++++ spec/factories/user_documents.rb | 26 ++++++++++++++++++++++ spec/factories/users.rb | 30 ++++++++++++++++++++++++++ spec/rails_helper.rb | 3 +++ spec/views/home/index.html.erb_spec.rb | 6 +++++- 10 files changed, 176 insertions(+), 16 deletions(-) create mode 100644 spec/factories/admin_users.rb create mode 100644 spec/factories/balances.rb create mode 100644 spec/factories/currencies.rb create mode 100644 spec/factories/fiat_balances.rb create mode 100644 spec/factories/user_documents.rb create mode 100644 spec/factories/users.rb diff --git a/Gemfile b/Gemfile index 4801de5..3e49b10 100644 --- a/Gemfile +++ b/Gemfile @@ -28,8 +28,10 @@ gem "pundit" group :development, :test do gem "dotenv-rails" gem "pry-byebug", platforms: [:mri, :mingw, :x64_mingw] - gem "capybara" + gem "rspec-rails" + gem "faker", "~> 2.18" + gem "factory_bot_rails", "~> 6.2" gem "rubocop-rails", require: false gem "rubocop-rspec", require: false diff --git a/Gemfile.lock b/Gemfile.lock index 38f8401..b8c4546 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,8 +60,6 @@ GEM minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) administrate (0.16.0) actionpack (>= 5.0) actionview (>= 5.0) @@ -85,14 +83,6 @@ GEM msgpack (~> 1.0) builder (3.2.4) byebug (11.1.3) - capybara (3.35.3) - addressable - mini_mime (>= 0.1.3) - nokogiri (~> 1.8) - rack (>= 1.6.0) - rack-test (>= 0.6.3) - regexp_parser (>= 1.5, < 3.0) - xpath (~> 3.2) coderay (1.1.3) concurrent-ruby (1.1.9) crass (1.0.6) @@ -114,6 +104,13 @@ GEM enumerize (2.4.0) activesupport (>= 3.2) erubi (1.10.0) + factory_bot (6.2.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + faker (2.18.0) + i18n (>= 1.6, < 2) ffi (1.15.3) globalid (0.5.2) activesupport (>= 5.0) @@ -182,7 +179,6 @@ GEM pry-byebug (3.9.0) byebug (~> 11.0) pry (~> 0.13.0) - public_suffix (4.0.6) puma (5.4.0) nio4r (~> 2.0) pundit (2.1.0) @@ -318,8 +314,6 @@ GEM websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - xpath (3.2.0) - nokogiri (~> 1.8) zeitwerk (2.4.2) PLATFORMS @@ -330,11 +324,12 @@ DEPENDENCIES administrate-field-active_storage annotate bootsnap (>= 1.4.4) - capybara devise devise-i18n dotenv-rails enumerize + factory_bot_rails (~> 6.2) + faker (~> 2.18) graphql graphql_playground-rails image_processing (~> 1.12) diff --git a/spec/factories/admin_users.rb b/spec/factories/admin_users.rb new file mode 100644 index 0000000..10f906b --- /dev/null +++ b/spec/factories/admin_users.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: admin_users +# +# id :bigint not null, primary key +# email :string default(""), not null +# encrypted_password :string default(""), not null +# remember_created_at :datetime +# reset_password_sent_at :datetime +# reset_password_token :string +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_admin_users_on_email (email) UNIQUE +# index_admin_users_on_reset_password_token (reset_password_token) UNIQUE +# +FactoryBot.define do + factory :admin_user do + sequence(:email) { |n| "admin-#{n}@example.com" } + password { "password" } + end +end diff --git a/spec/factories/balances.rb b/spec/factories/balances.rb new file mode 100644 index 0000000..1aa9df3 --- /dev/null +++ b/spec/factories/balances.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: balances +# +# id :bigint not null, primary key +# amount :decimal(20, 10) default(0.0), not null +# created_at :datetime not null +# updated_at :datetime not null +# currency_id :bigint not null +# user_id :bigint not null +# +# Indexes +# +# index_balances_on_currency_id (currency_id) +# index_balances_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (currency_id => currencies.id) +# fk_rails_... (user_id => users.id) +# +FactoryBot.define do + factory :balance do + association :user + association :currency + amount { (rand * (10000 - 0) + 0) } + end +end diff --git a/spec/factories/currencies.rb b/spec/factories/currencies.rb new file mode 100644 index 0000000..e294e90 --- /dev/null +++ b/spec/factories/currencies.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: currencies +# +# id :bigint not null, primary key +# name :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +FactoryBot.define do + factory :currency do + name { "CAKE" } + end +end diff --git a/spec/factories/fiat_balances.rb b/spec/factories/fiat_balances.rb new file mode 100644 index 0000000..37ac2a4 --- /dev/null +++ b/spec/factories/fiat_balances.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: fiat_balances +# +# id :bigint not null, primary key +# amount_cents :integer default(0), not null +# amount_currency :string default("BRL"), not null +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_fiat_balances_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# +FactoryBot.define do + factory :fiat_balance do + association :user + amount_currency { "BRL" } + amount_cents { Faker::Number.number(digits: 10) } + end +end diff --git a/spec/factories/user_documents.rb b/spec/factories/user_documents.rb new file mode 100644 index 0000000..a12861e --- /dev/null +++ b/spec/factories/user_documents.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: user_documents +# +# id :bigint not null, primary key +# status :string not null +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_user_documents_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# +FactoryBot.define do + factory :user_document do + association :user + status { :pending_review } + end +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb new file mode 100644 index 0000000..fda8d14 --- /dev/null +++ b/spec/factories/users.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: users +# +# id :bigint not null, primary key +# email :string default(""), not null +# encrypted_password :string default(""), not null +# first_name :string not null +# last_name :string not null +# remember_created_at :datetime +# reset_password_sent_at :datetime +# reset_password_token :string +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_users_on_email (email) UNIQUE +# index_users_on_reset_password_token (reset_password_token) UNIQUE +# +FactoryBot.define do + factory :user do + first_name { Faker::Name.first_name } + last_name { Faker::Name.last_name } + email { Faker::Internet.email } + password { "password" } + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 990e786..edf45e1 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -66,6 +66,9 @@ RSpec.configure do |config| config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") + + # Add FactoryBot + config.include(FactoryBot::Syntax::Methods) end Shoulda::Matchers.configure do |config| diff --git a/spec/views/home/index.html.erb_spec.rb b/spec/views/home/index.html.erb_spec.rb index 5399492..c26ae9b 100644 --- a/spec/views/home/index.html.erb_spec.rb +++ b/spec/views/home/index.html.erb_spec.rb @@ -2,5 +2,9 @@ require "rails_helper" RSpec.describe("home/index.html.erb", type: :view) do - pending "add some examples to (or delete) #{__FILE__}" + it "render div with id root" do + render + + expect(rendered).to(eq("
")) + end end From 3813abdaf03a60d39853402338d99f00d54e98d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sat, 14 Aug 2021 12:11:00 -0300 Subject: [PATCH 5/6] add rails erd --- .erdconfig | 11 ++ Gemfile | 1 + Gemfile.lock | 9 ++ README.md | 4 +- erd.svg | 198 +++++++++++++++++++++++++++ lib/tasks/auto_generate_diagram.rake | 7 + 6 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 .erdconfig create mode 100644 erd.svg create mode 100644 lib/tasks/auto_generate_diagram.rake diff --git a/.erdconfig b/.erdconfig new file mode 100644 index 0000000..d6330e4 --- /dev/null +++ b/.erdconfig @@ -0,0 +1,11 @@ +filetype: svg +orientation: vertical +attributes: + - content + - foreign_key + - inheritance +exclude: + - ActiveRecord::InternalMetadata + - ActiveRecord::SchemaMigration + - primary::SchemaMigration + - Audited::Audit diff --git a/Gemfile b/Gemfile index 3e49b10..404f3e8 100644 --- a/Gemfile +++ b/Gemfile @@ -28,6 +28,7 @@ gem "pundit" group :development, :test do gem "dotenv-rails" gem "pry-byebug", platforms: [:mri, :mingw, :x64_mingw] + gem "rails-erd" gem "rspec-rails" gem "faker", "~> 2.18" diff --git a/Gemfile.lock b/Gemfile.lock index b8c4546..fc32f9f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -83,6 +83,7 @@ GEM msgpack (~> 1.0) builder (3.2.4) byebug (11.1.3) + choice (0.2.0) coderay (1.1.3) concurrent-ruby (1.1.9) crass (1.0.6) @@ -207,6 +208,11 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) + rails-erd (1.6.1) + activerecord (>= 4.2) + activesupport (>= 4.2) + choice (~> 0.2.0) + ruby-graphviz (~> 1.2) rails-html-sanitizer (1.3.0) loofah (~> 2.3) railties (6.1.4) @@ -264,6 +270,8 @@ GEM rubocop-ast (>= 1.1.0) rubocop-shopify (2.2.0) rubocop (~> 1.18) + ruby-graphviz (1.2.5) + rexml ruby-progressbar (1.11.0) ruby-vips (2.1.2) ffi (~> 1.12) @@ -340,6 +348,7 @@ DEPENDENCIES puma (~> 5.0) pundit rails (~> 6.1.4) + rails-erd rspec-graphql_matchers (~> 1.3) rspec-rails rubocop-rails diff --git a/README.md b/README.md index 12cdd6d..da28abd 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ * Postgres 13.x * [Watchman](https://github.com/facebook/watchman) (opcional) - ## 🚀 Instalando Comandos para a instalação: @@ -42,3 +41,6 @@ yarn relay ``` yarn relay:watch // requer a instalação do watchman ``` + +## ⛳ Modelo De Domínio +![](./erd.svg) diff --git a/erd.svg b/erd.svg new file mode 100644 index 0000000..309a8a3 --- /dev/null +++ b/erd.svg @@ -0,0 +1,198 @@ + + + + + + +XStake + +XStake domain model + + +m_ActiveStorage::Attachment + +ActiveStorage::Attachment + +blob_id +integer (8) ∗ FK +name +string ∗ +record_id +integer (8) ∗ FK +record_type +string ∗ + + + +m_ActiveStorage::Blob + +ActiveStorage::Blob + +byte_size +integer (8) ∗ +checksum +string ∗ +content_type +string +filename +string ∗ +key +string ∗ +metadata +text +service_name +string ∗ + + + +m_ActiveStorage::Blob->m_ActiveStorage::Attachment + + + + +m_ActiveStorage::Blob->m_ActiveStorage::Blob + + + + +m_ActiveStorage::VariantRecord + +ActiveStorage::VariantRecord + +blob_id +integer (8) ∗ FK +variation_digest +string ∗ + + + +m_ActiveStorage::Blob->m_ActiveStorage::VariantRecord + + + + + +m_ActiveStorage::VariantRecord->m_ActiveStorage::Attachment + + + + +m_AdminUser + +AdminUser + +email +string ∗ U +encrypted_password +string ∗ +remember_created_at +datetime +reset_password_sent_at +datetime +reset_password_token +string + + + +m_Balance + +Balance + +amount +decimal (20,10) ∗ +currency_id +integer (8) ∗ FK +user_id +integer (8) ∗ FK + + + +m_Currency + +Currency + +name +string ∗ + + + +m_Currency->m_Balance + + + + + +m_FiatBalance + +FiatBalance + +amount_cents +integer ∗ +amount_currency +string ∗ +user_id +integer (8) ∗ FK + + + +m_User + +User + +email +string ∗ U +encrypted_password +string ∗ +first_name +string ∗ +last_name +string ∗ +remember_created_at +datetime +reset_password_sent_at +datetime +reset_password_token +string + + + +m_User->m_Balance + + + + +m_User->m_FiatBalance + + + + +m_UserDocument + +UserDocument + +status +string ∗ +user_id +integer (8) ∗ FK + + + +m_User->m_UserDocument + + + + + +m_UserDocument->m_ActiveStorage::Attachment + + + + +m_UserDocument->m_ActiveStorage::Blob + + + + diff --git a/lib/tasks/auto_generate_diagram.rake b/lib/tasks/auto_generate_diagram.rake new file mode 100644 index 0000000..b7be980 --- /dev/null +++ b/lib/tasks/auto_generate_diagram.rake @@ -0,0 +1,7 @@ +# frozen_string_literal: true +# NOTE: only doing this in development as some production environments (Heroku) +# NOTE: are sensitive to local FS writes, and besides -- it's just not proper +# NOTE: to have a dev-mode tool do its thing in production. +if Rails.env.development? + RailsERD.load_tasks +end From de5e581f2130b3dd3b71c6bb79831d4c5c446b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Sat, 14 Aug 2021 13:51:00 -0300 Subject: [PATCH 6/6] remove monetize helper from CreateFiatBalances migration --- db/migrate/20210812011039_create_fiat_balances.rb | 4 +++- db/seeds.rb | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/db/migrate/20210812011039_create_fiat_balances.rb b/db/migrate/20210812011039_create_fiat_balances.rb index d139f0a..285df7c 100644 --- a/db/migrate/20210812011039_create_fiat_balances.rb +++ b/db/migrate/20210812011039_create_fiat_balances.rb @@ -3,7 +3,9 @@ class CreateFiatBalances < ActiveRecord::Migration[6.1] def change create_table(:fiat_balances) do |t| t.references(:user, null: false, foreign_key: true) - t.monetize(:amount) + + t.integer(:amount_cents, null: false, default: 0) + t.string(:amount_currency, null: false, default: "BRL") t.timestamps end diff --git a/db/seeds.rb b/db/seeds.rb index f04c278..092f13f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -17,4 +17,4 @@ Balance.create!( amount: (rand * (10000 - 0) + 0) ) -FiatBalance.create!(user_id: user.id) +FiatBalance.create!(user_id: user.id, amount_cents: 15000)