wallet screen

This commit is contained in:
João Geonizeli
2021-08-11 20:51:42 -03:00
parent 38b60ca0fa
commit a057931c51
19 changed files with 656 additions and 20 deletions

View File

@@ -1,5 +1,8 @@
# frozen_string_literal: true
module Admin
class BalancesController < Admin::ApplicationController
def valid_action?(name, resource = resource_class)
["destroy"].exclude?(name.to_s) && super
end
end
end

View File

@@ -1,7 +1,5 @@
# frozen_string_literal: true
class ApplicationController < ActionController::Base
include Pundit
before_action :configure_devise_permitted_parameters, if: :devise_controller?
protected

View File

@@ -1,5 +1,7 @@
# frozen_string_literal: true
class GraphqlController < ApplicationController
# protect_from_forgery with: :null_session
def execute
variables = prepare_variables(params[:variables])
query = params[:query]

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
module Types
class BalanceType < Types::BaseObject
implements GraphQL::Types::Relay::Node
global_id_field :id
graphql_name "Balance"
field :id, ID, null: false
field :currency, CurrencyType, null: false
field :amount, String, null: false
end
end

View File

@@ -0,0 +1,12 @@
# frozen_string_literal: true
module Types
class CurrencyType < Types::BaseObject
implements GraphQL::Types::Relay::Node
global_id_field :id
graphql_name "Currency"
field :id, ID, null: false
field :name, String, null: false
end
end

View File

@@ -8,5 +8,10 @@ module Types
def current_user
context[:current_user]
end
field :balances, BalanceType.connection_type, null: false
def balances
Pundit.policy_scope(current_user, Balance)
end
end
end

View File

@@ -2,9 +2,10 @@
module Types
class UserType < Types::BaseObject
# implements GraphQL::Types::Relay::Node
global_id_field :id
graphql_name "User"
field :id, ID, null: false
field :first_name, String, null: false
field :last_name, String, null: false

View File

@@ -4,15 +4,22 @@ class XStakeSchema < GraphQL::Schema
query(Types::QueryType)
def self.resolve_type(abstract_type, obj, ctx)
raise(GraphQL::RequiredImplementationMissingError)
case obj
when Currency
Types::CurrencyType
when Balance
Types::BalanceType
else
raise(GraphQL::RequiredImplementationMissingError, "Unexpected object: #{obj}")
end
end
def self.id_from_object(object, type_definition, query_ctx)
def self.id_from_object(object, type_definition, ctx)
GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
end
def self.object_from_id(id, query_ctx)
def self.object_from_id(id, ctx)
type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
type_name.constantize.find(item_id)
Pundit.policy_scope(ctx[:current_user], type_name.constantize).find(item_id)
end
end

View File

@@ -1,5 +1,127 @@
type Balance implements Node {
amount: Float!
currency: Currency!
id: ID!
}
"""
The connection type for Balance.
"""
type BalanceConnection {
"""
A list of edges.
"""
edges: [BalanceEdge]
"""
A list of nodes.
"""
nodes: [Balance]
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
}
"""
An edge in a connection.
"""
type BalanceEdge {
"""
A cursor for use in pagination.
"""
cursor: String!
"""
The item at the end of the edge.
"""
node: Balance
}
type Currency implements Node {
id: ID!
name: String!
}
"""
An object with an ID.
"""
interface Node {
"""
ID of the object.
"""
id: ID!
}
"""
Information about pagination in a connection.
"""
type PageInfo {
"""
When paginating forwards, the cursor to continue.
"""
endCursor: String
"""
When paginating forwards, are there more items?
"""
hasNextPage: Boolean!
"""
When paginating backwards, are there more items?
"""
hasPreviousPage: Boolean!
"""
When paginating backwards, the cursor to continue.
"""
startCursor: String
}
type Query {
balances(
"""
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
): BalanceConnection!
currentUser: User
"""
Fetches an object given its ID.
"""
node(
"""
ID of the object.
"""
id: ID!
): Node
"""
Fetches a list of objects given a list of IDs.
"""
nodes(
"""
IDs of the objects.
"""
ids: [ID!]!
): [Node]!
}
type User {

View File

@@ -2,14 +2,17 @@ import type { FC } from "react";
import React from "react";
import { Switch, Route } from "react-router-dom";
import { Home } from "./pages";
import { Home, Wallet } from "./pages";
export const Routes: FC = () => {
return (
<Switch>
<Route path="/">
<Route exact path="/">
<Home />
</Route>
<Route exact path="/wallet">
<Wallet />
</Route>
</Switch>
);
};

View File

@@ -14,10 +14,6 @@ const MenuItems: MenuItem[] = [
label: "Início",
path: "/",
},
{
label: "Stake",
path: "/stake",
},
{
label: "Carteira",
path: "/wallet",

View File

@@ -0,0 +1,94 @@
import { graphql } from "babel-plugin-relay/macro";
import type { FC } from "react";
import React from "react";
import { useLazyLoadQuery } from "react-relay";
import { tokens } from "../../constants/pancake/Tokens";
import type { WalletQuery } from "./__generated__/WalletQuery.graphql";
export const Wallet: FC = () => {
const { balances } = useLazyLoadQuery<WalletQuery>(
graphql`
query WalletQuery {
balances {
nodes {
id
amount
currency {
name
}
}
}
}
`,
{}
);
const tokensList = Object.values(tokens);
return (
<div className="flex flex-col h-full w-full overflow-x-hidden mt-16">
<div className="container mx-auto px-4 sm:px-8 max-w-3xl">
<div className="py-8">
<div className="-mx-4 sm:-mx-8 px-4 sm:px-8 py-4 overflow-x-auto">
<div className="inline-block min-w-full shadow rounded-lg overflow-hidden">
<table className="min-w-full leading-normal">
<thead>
<tr>
<th
scope="col"
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
>
Moeda
</th>
<th
scope="col"
className="px-5 py-3 bg-white border-b border-gray-200 text-gray-800 text-left text-sm uppercase font-normal"
>
Saldo
</th>
</tr>
</thead>
<tbody>
{balances.nodes?.map((balance) => {
const token = tokensList.find(
({ symbol }) => symbol === balance?.currency.name
);
return (
<tr key={balance?.id}>
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
<div className="flex items-center">
<div className="flex-shrink-0">
<a href="/" className="block relative">
<img
alt="profil"
src={`https://pancakeswap.finance/images/tokens/${token?.address["56"]}.svg`}
className="mx-auto object-cover rounded-full h-10 w-10 "
/>
</a>
</div>
<div className="ml-3">
<p className="text-gray-900 whitespace-no-wrap">
{balance?.currency.name}
</p>
</div>
</div>
</td>
<td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
<p className="text-gray-900 whitespace-no-wrap">
{balance?.amount}
</p>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,165 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from "relay-runtime";
export type WalletQueryVariables = {};
export type WalletQueryResponse = {
readonly balances: {
readonly nodes: ReadonlyArray<{
readonly id: string;
readonly amount: number;
readonly currency: {
readonly name: string;
};
} | null> | null;
};
};
export type WalletQuery = {
readonly response: WalletQueryResponse;
readonly variables: WalletQueryVariables;
};
/*
query WalletQuery {
balances {
nodes {
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,
"kind": "ScalarField",
"name": "amount",
"storageKey": null
},
v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "WalletQuery",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "BalanceConnection",
"kind": "LinkedField",
"name": "balances",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Balance",
"kind": "LinkedField",
"name": "nodes",
"plural": true,
"selections": [
(v0/*: any*/),
(v1/*: any*/),
{
"alias": null,
"args": null,
"concreteType": "Currency",
"kind": "LinkedField",
"name": "currency",
"plural": false,
"selections": [
(v2/*: any*/)
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [],
"kind": "Operation",
"name": "WalletQuery",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "BalanceConnection",
"kind": "LinkedField",
"name": "balances",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Balance",
"kind": "LinkedField",
"name": "nodes",
"plural": true,
"selections": [
(v0/*: any*/),
(v1/*: any*/),
{
"alias": null,
"args": null,
"concreteType": "Currency",
"kind": "LinkedField",
"name": "currency",
"plural": false,
"selections": [
(v2/*: any*/),
(v0/*: any*/)
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "6b8d0c664bd2d9df4d323c19c4a823a5",
"id": null,
"metadata": {},
"name": "WalletQuery",
"operationKind": "query",
"text": "query WalletQuery {\n balances {\n nodes {\n id\n amount\n currency {\n name\n id\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = '428f4f1ab769f9056dd38ec641a30733';
export default node;

View File

@@ -0,0 +1 @@
export * from "./Wallet";

View File

@@ -1 +1,2 @@
export * from "./Home";
export * from "./Wallet";

View File

@@ -1 +0,0 @@
export * from "./Home";

View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
class BalancePolicy < ApplicationPolicy
class Scope < Scope
def resolve
return scope.none if user.nil?
scope.where(user_id: user.id)
end
end
end