diff --git a/app/graphql/mutations/create_deposit_order.rb b/app/graphql/mutations/create_deposit_order.rb index 8be66e6..cb6f988 100644 --- a/app/graphql/mutations/create_deposit_order.rb +++ b/app/graphql/mutations/create_deposit_order.rb @@ -3,14 +3,14 @@ module Mutations class CreateDepositOrder < BaseMutation field :order, Types::DepositOrderType, null: true - argument :order, Inputs::CreateStakeOrderAttributesInput, required: true + argument :order, Inputs::CreateDepositOrderAttributesInput, required: true def resolve(order:) ActiveRecord::Base.transaction do - record = BuildDepositOrder.new(paid_amount_cents: order[:amount_cents], user: current_user.id) + record = BuildDepositOrder.new(paid_amount_cents: order[:amount_cents], user_id: current_user.id).build record.save! - { order: record } + { order: record.reload } rescue ActiveRecord::RecordInvalid => e { errors: Resolvers::ModelErrors.from_active_record_model(e.record) } end diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index dd38274..ded7cbf 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -77,6 +77,13 @@ type CreateBuyCryptoOrderPayload { order: BuyCryptoOrder } +input CreateDepositOrderAttributesInput { + """ + Amount to be paid + """ + amountCents: Int! +} + """ Autogenerated input type of CreateDepositOrder """ @@ -85,7 +92,7 @@ input CreateDepositOrderInput { A unique identifier for the client performing the mutation. """ clientMutationId: String - order: CreateStakeOrderAttributesInput! + order: CreateDepositOrderAttributesInput! } """ diff --git a/app/javascript/src/messages/NoHistory.tsx b/app/javascript/src/messages/NoHistory.tsx index c829a13..afee0bb 100644 --- a/app/javascript/src/messages/NoHistory.tsx +++ b/app/javascript/src/messages/NoHistory.tsx @@ -7,7 +7,7 @@ type Props = { historyName: string; }; -export const NoHistory: FC = ({ historyName }) => { +export const NoHistory: FC = ({ historyName, children }) => { return (
@@ -21,6 +21,7 @@ export const NoHistory: FC = ({ historyName }) => { Você não possui históricos de {historyName}
+ {children}
); diff --git a/app/javascript/src/pages/Orders/Deposit/Create/Create.tsx b/app/javascript/src/pages/Orders/Deposit/Create/Create.tsx new file mode 100644 index 0000000..4710a9f --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Create/Create.tsx @@ -0,0 +1,41 @@ +import type { FC } from "react"; +import React, { useState } from "react"; +import { useRelayEnvironment } from "react-relay"; + +import { Button, Modal } from "../../../../components"; +import { useDepositContext } from "../DepositProvider"; +import { commitCreateDepositOrderMutation } from "./commitCreateDepositOrder"; +import { Form } from "./Form"; + +export const Create: FC = () => { + const environment = useRelayEnvironment(); + const { setOpenOrder } = useDepositContext(); + + const [isOpen, setIsOpen] = useState(false); + + const onFormSubmit = (amount: number) => { + commitCreateDepositOrderMutation( + environment, + { + amountCents: amount * 100, + }, + (res) => { + if (!res.createDepositOrder?.order) return; + + setIsOpen(false); + setOpenOrder(res.createDepositOrder?.order); + } + ); + }; + + return ( +
+
+ + +
+ +
+
+ ); +}; diff --git a/app/javascript/src/pages/Orders/Deposit/Create/Form.tsx b/app/javascript/src/pages/Orders/Deposit/Create/Form.tsx new file mode 100644 index 0000000..797a439 --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Create/Form.tsx @@ -0,0 +1,46 @@ +import type { FC } from "react"; +import React, { useState } from "react"; + +import { Button, Input } from "../../../../components"; + +type Props = { + submitCallback: (amount: number) => void; + className?: string; +}; + +export const Form: FC = ({ className, submitCallback }) => { + const [amountInput, setAmountInput] = useState(); + + const handleAmountChange = ({ + currentTarget: { value }, + }: React.ChangeEvent) => { + const newFiatAmount = parseInt(value, 10) || 0; + + if (newFiatAmount < 0) return; + setAmountInput(newFiatAmount); + }; + + const onSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + if (amountInput) { + submitCallback(amountInput); + } + }; + + const amount = amountInput ?? 0; + + return ( + +
+

Quantia em BRL

+ +
+
Você recebe: {amount + amount * 0.05} BRL
+
Taxa de transação: {amount * 0.05} BRL
+ + + ); +}; diff --git a/app/javascript/src/pages/Orders/Deposit/Create/__generated__/commitCreateDepositOrderMutation.graphql.ts b/app/javascript/src/pages/Orders/Deposit/Create/__generated__/commitCreateDepositOrderMutation.graphql.ts new file mode 100644 index 0000000..ec510ce --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Create/__generated__/commitCreateDepositOrderMutation.graphql.ts @@ -0,0 +1,197 @@ +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from "relay-runtime"; +import { FragmentRefs } from "relay-runtime"; +export type commitCreateDepositOrderMutationVariables = { + amountCents: number; +}; +export type commitCreateDepositOrderMutationResponse = { + readonly createDepositOrder: { + readonly order: { + readonly id: string; + readonly " $fragmentRefs": FragmentRefs<"Show_deposit_order">; + } | null; + } | null; +}; +export type commitCreateDepositOrderMutation = { + readonly response: commitCreateDepositOrderMutationResponse; + readonly variables: commitCreateDepositOrderMutationVariables; +}; + + + +/* +mutation commitCreateDepositOrderMutation( + $amountCents: Int! +) { + createDepositOrder(input: {order: {amountCents: $amountCents}}) { + order { + id + ...Show_deposit_order + } + } +} + +fragment Show_deposit_order on DepositOrder { + id + transactionId + paidAmountCents + receivedAmountCents + status + createdAt +} +*/ + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "amountCents" + } +], +v1 = [ + { + "fields": [ + { + "fields": [ + { + "kind": "Variable", + "name": "amountCents", + "variableName": "amountCents" + } + ], + "kind": "ObjectValue", + "name": "order" + } + ], + "kind": "ObjectValue", + "name": "input" + } +], +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "commitCreateDepositOrderMutation", + "selections": [ + { + "alias": null, + "args": (v1/*: any*/), + "concreteType": "CreateDepositOrderPayload", + "kind": "LinkedField", + "name": "createDepositOrder", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrder", + "kind": "LinkedField", + "name": "order", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "args": null, + "kind": "FragmentSpread", + "name": "Show_deposit_order" + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Mutation", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "commitCreateDepositOrderMutation", + "selections": [ + { + "alias": null, + "args": (v1/*: any*/), + "concreteType": "CreateDepositOrderPayload", + "kind": "LinkedField", + "name": "createDepositOrder", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DepositOrder", + "kind": "LinkedField", + "name": "order", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "transactionId", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "paidAmountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "receivedAmountCents", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "f83279e6438b80e14dbeb3efc1a20742", + "id": null, + "metadata": {}, + "name": "commitCreateDepositOrderMutation", + "operationKind": "mutation", + "text": "mutation commitCreateDepositOrderMutation(\n $amountCents: Int!\n) {\n createDepositOrder(input: {order: {amountCents: $amountCents}}) {\n order {\n id\n ...Show_deposit_order\n }\n }\n}\n\nfragment Show_deposit_order on DepositOrder {\n id\n transactionId\n paidAmountCents\n receivedAmountCents\n status\n createdAt\n}\n" + } +}; +})(); +(node as any).hash = '143549ad827756ac107c08e45b0bc525'; +export default node; diff --git a/app/javascript/src/pages/Orders/Deposit/Create/commitCreateDepositOrder.tsx b/app/javascript/src/pages/Orders/Deposit/Create/commitCreateDepositOrder.tsx new file mode 100644 index 0000000..989087f --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Create/commitCreateDepositOrder.tsx @@ -0,0 +1,33 @@ +import { graphql } from "babel-plugin-relay/macro"; +import type { Environment } from "react-relay"; +import { commitMutation } from "react-relay"; + +import type { + commitCreateDepositOrderMutation as commitCreateDepositOrderMutationType, + commitCreateDepositOrderMutationResponse, + commitCreateDepositOrderMutationVariables, +} from "./__generated__/commitCreateDepositOrderMutation.graphql"; + +export const commitCreateDepositOrderMutation = ( + environment: Environment, + variables: commitCreateDepositOrderMutationVariables, + callback: (response: commitCreateDepositOrderMutationResponse) => void +) => { + return commitMutation(environment, { + mutation: graphql` + mutation commitCreateDepositOrderMutation($amountCents: Int!) { + createDepositOrder(input: { order: { amountCents: $amountCents } }) { + order { + id + ...Show_deposit_order + } + } + } + `, + variables, + onCompleted: (response) => { + callback(response); + }, + onError: (_error) => {}, + }); +}; diff --git a/app/javascript/src/pages/Orders/Deposit/Create/index.ts b/app/javascript/src/pages/Orders/Deposit/Create/index.ts new file mode 100644 index 0000000..c65721e --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/Create/index.ts @@ -0,0 +1 @@ +export * from "./Create"; diff --git a/app/javascript/src/pages/Orders/Deposit/Deposit.tsx b/app/javascript/src/pages/Orders/Deposit/Deposit.tsx index b507458..99f18f9 100644 --- a/app/javascript/src/pages/Orders/Deposit/Deposit.tsx +++ b/app/javascript/src/pages/Orders/Deposit/Deposit.tsx @@ -6,8 +6,13 @@ import { useLazyLoadQuery } from "react-relay"; import type { DepositQuery } from "./__generated__/DepositQuery.graphql"; import { Messages } from "../../../messages"; import { History } from "./History"; +import { Create } from "./Create"; +import { DepositProvider, useDepositContext } from "./DepositProvider"; +import { Show } from "./Show"; + +const Component: FC = () => { + const { fetchKey } = useDepositContext(); -export const Deposit: FC = () => { const { depositOrders } = useLazyLoadQuery( graphql` query DepositQuery { @@ -17,21 +22,41 @@ export const Deposit: FC = () => { } } `, - {} + {}, + { + fetchKey, + fetchPolicy: "network-only", + } ); if (!depositOrders.totalCount) - return ; + return ( + + + + ); return ( -
-
-
-
+ <> +
+
+
+ +
+
-
+ + ); +}; + +export const Deposit: FC = () => { + return ( + + + + ); }; diff --git a/app/javascript/src/pages/Orders/Deposit/DepositProvider.tsx b/app/javascript/src/pages/Orders/Deposit/DepositProvider.tsx new file mode 100644 index 0000000..775eadd --- /dev/null +++ b/app/javascript/src/pages/Orders/Deposit/DepositProvider.tsx @@ -0,0 +1,43 @@ +import type { FC } from "react"; +import React, { useState, createContext, useContext } from "react"; + +import type { Show_deposit_order$key } from "./Show/__generated__/Show_deposit_order.graphql"; + +type Order = Show_deposit_order$key & { id: string }; + +type DepositContext = { + openOrder: Order | null; + setOpenOrder: React.Dispatch>; + fetchKey: string; + setFetchKey: React.Dispatch>; +}; + +const Context = createContext(null); + +export const useDepositContext = (): DepositContext => { + const context = useContext(Context); + + if (!context) { + throw new Error("You must wrap the component with "); + } + + return context; +}; + +export const DepositProvider: FC = ({ children }) => { + const [openOrder, setOpenOrder] = useState(null); + const [fetchKey, setFetchKey] = useState("empty"); + + return ( + + {children} + + ); +}; diff --git a/app/javascript/src/pages/Orders/Deposit/History/History.tsx b/app/javascript/src/pages/Orders/Deposit/History/History.tsx index a6882d9..dec4438 100644 --- a/app/javascript/src/pages/Orders/Deposit/History/History.tsx +++ b/app/javascript/src/pages/Orders/Deposit/History/History.tsx @@ -1,6 +1,7 @@ +/* eslint-disable relay/must-colocate-fragment-spreads */ import { graphql } from "babel-plugin-relay/macro"; import type { FC } from "react"; -import React, { useState } from "react"; +import React from "react"; import cs from "classnames"; import { useFragment } from "react-relay"; @@ -8,14 +9,14 @@ import { Table, TableRow } from "../../../../components"; import { getStatusTextAndColors } from "../../utils/processStatus"; import { centsToUnit } from "../../../../utils/fiatMoney"; import type { History_depositOrders$key } from "./__generated__/History_depositOrders.graphql"; -import { Show } from "../Show"; +import { useDepositContext } from "../DepositProvider"; type Props = { ordersRef: History_depositOrders$key; }; export const History: FC = ({ ordersRef }) => { - const [openOrderId, setOpenOrderId] = useState(null); + const { setOpenOrder } = useDepositContext(); const { edges } = useFragment( graphql` @@ -35,12 +36,8 @@ export const History: FC = ({ ordersRef }) => { ordersRef ); - const openOrder = edges.find(({ node }) => node.id === openOrderId); - const onClose = () => setOpenOrderId(null); - return ( - <> - {openOrder && } +
@@ -70,7 +67,7 @@ export const History: FC = ({ ordersRef }) => { return ( setOpenOrderId(orderId)} + onClick={() => setOpenOrder(node)} id={node.id} items={[ `${centsToUnit(node.paidAmountCents)} BRL`, @@ -82,6 +79,6 @@ export const History: FC = ({ ordersRef }) => { ); })}
- +
); }; diff --git a/app/javascript/src/pages/Orders/Deposit/Show/Show.tsx b/app/javascript/src/pages/Orders/Deposit/Show/Show.tsx index 5f61dae..308a036 100644 --- a/app/javascript/src/pages/Orders/Deposit/Show/Show.tsx +++ b/app/javascript/src/pages/Orders/Deposit/Show/Show.tsx @@ -9,16 +9,20 @@ import { usePixQr } from "./hooks/usePixQr"; import type { Show_deposit_order$key } from "./__generated__/Show_deposit_order.graphql"; import { centsToUnit } from "../../../../utils/fiatMoney"; import { getStatusTextAndColors } from "../../utils/processStatus"; +import { useDepositContext } from "../DepositProvider"; type Props = { orderRef: Show_deposit_order$key; onClose: () => void; }; -export const Show: FC = ({ orderRef, onClose }) => { +const ShowModal: FC = ({ orderRef, onClose }) => { + const { setFetchKey } = useDepositContext(); + const order = useFragment( graphql` fragment Show_deposit_order on DepositOrder { + id transactionId paidAmountCents receivedAmountCents @@ -36,6 +40,7 @@ export const Show: FC = ({ orderRef, onClose }) => { const handleClose = (_value: boolean) => { onClose(); + setFetchKey(order.id); }; const handleCopy = () => { @@ -92,3 +97,15 @@ export const Show: FC = ({ orderRef, onClose }) => { ); }; + +export const Show: FC = () => { + const { setOpenOrder, openOrder } = useDepositContext(); + + if (!openOrder) return null; + + const handleClose = () => { + setOpenOrder(null); + }; + + return ; +}; diff --git a/app/javascript/src/pages/Orders/Deposit/Show/__generated__/Show_deposit_order.graphql.ts b/app/javascript/src/pages/Orders/Deposit/Show/__generated__/Show_deposit_order.graphql.ts index 8ffbd48..8848485 100644 --- a/app/javascript/src/pages/Orders/Deposit/Show/__generated__/Show_deposit_order.graphql.ts +++ b/app/javascript/src/pages/Orders/Deposit/Show/__generated__/Show_deposit_order.graphql.ts @@ -6,6 +6,7 @@ import { ReaderFragment } from "relay-runtime"; import { FragmentRefs } from "relay-runtime"; export type ProcessStatus = "CANCELED" | "COMPLETED" | "PROCESSING" | "%future added value"; export type Show_deposit_order = { + readonly id: string; readonly transactionId: string; readonly paidAmountCents: number; readonly receivedAmountCents: number; @@ -27,6 +28,13 @@ const node: ReaderFragment = { "metadata": null, "name": "Show_deposit_order", "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, { "alias": null, "args": null, @@ -66,5 +74,5 @@ const node: ReaderFragment = { "type": "DepositOrder", "abstractKey": null }; -(node as any).hash = '73e84cef63c17faa3087f19ba2c73e69'; +(node as any).hash = '7bda3158834b0532ddabf9da61984049'; export default node; diff --git a/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts b/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts index 0bcf7ef..36e3284 100644 --- a/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts +++ b/app/javascript/src/pages/Orders/Deposit/__generated__/DepositQuery.graphql.ts @@ -40,6 +40,7 @@ fragment History_depositOrders on DepositOrderConnection { } fragment Show_deposit_order on DepositOrder { + id transactionId paidAmountCents receivedAmountCents @@ -169,12 +170,12 @@ return { ] }, "params": { - "cacheID": "99f3fbbd023ef8a38b0490275cb58aa6", + "cacheID": "c89f24bbd553272fc712f18bb6da0886", "id": null, "metadata": {}, "name": "DepositQuery", "operationKind": "query", - "text": "query DepositQuery {\n depositOrders {\n totalCount\n ...History_depositOrders\n }\n}\n\nfragment History_depositOrders on DepositOrderConnection {\n edges {\n node {\n id\n status\n createdAt\n paidAmountCents\n receivedAmountCents\n ...Show_deposit_order\n }\n }\n}\n\nfragment Show_deposit_order on DepositOrder {\n transactionId\n paidAmountCents\n receivedAmountCents\n status\n createdAt\n}\n" + "text": "query DepositQuery {\n depositOrders {\n totalCount\n ...History_depositOrders\n }\n}\n\nfragment History_depositOrders on DepositOrderConnection {\n edges {\n node {\n id\n status\n createdAt\n paidAmountCents\n receivedAmountCents\n ...Show_deposit_order\n }\n }\n}\n\nfragment Show_deposit_order on DepositOrder {\n id\n transactionId\n paidAmountCents\n receivedAmountCents\n status\n createdAt\n}\n" } }; })(); diff --git a/app/services/build_deposit_order.rb b/app/services/build_deposit_order.rb index 9f19023..c756f43 100644 --- a/app/services/build_deposit_order.rb +++ b/app/services/build_deposit_order.rb @@ -4,7 +4,7 @@ class BuildDepositOrder attr_reader :paid_amount_cents, :user_id - def initilize(paid_amount_cents:, user_id:) + def initialize(paid_amount_cents:, user_id:) @paid_amount_cents = paid_amount_cents @user_id = user_id end diff --git a/package.json b/package.json index e14c7ad..ac26888 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "webpack-cli": "^3.3.12" }, "devDependencies": { + "@types/qrcode": "^1.4.1", "@types/ramda": "^0.27.44", "@types/react-relay": "^11.0.2", "@types/react-router-dom": "^5.1.8", diff --git a/yarn.lock b/yarn.lock index 7df691a..88f8d74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1669,6 +1669,13 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ== +"@types/qrcode@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@types/qrcode/-/qrcode-1.4.1.tgz#0689f400c3a95d2db040c99c99834faa09ee9dc1" + integrity sha512-vxMyr7JM7tYPxu8vUE83NiosWX5DZieCyYeJRoOIg0pAkyofCBzknJ2ycUZkPGDFis2RS8GN/BeJLnRnAPxeCA== + dependencies: + "@types/node" "*" + "@types/ramda@^0.27.44": version "0.27.44" resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.27.44.tgz#ba2283d67fcff366f7e68bd5124a0466e467967f"