From 2b9397b3401a1aa134a53434cc9e8a07e19564b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Tue, 10 Aug 2021 23:18:32 -0300 Subject: [PATCH 1/3] add currency entity --- .../admin/currencies_controller.rb | 5 ++ app/dashboards/currency_dashboard.rb | 52 +++++++++++++++++++ app/models/currency.rb | 14 +++++ config/routes.rb | 1 + .../20210811014107_create_currencies.rb | 10 ++++ db/schema.rb | 8 ++- spec/models/currency_spec.rb | 18 +++++++ 7 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 app/controllers/admin/currencies_controller.rb create mode 100644 app/dashboards/currency_dashboard.rb create mode 100644 app/models/currency.rb create mode 100644 db/migrate/20210811014107_create_currencies.rb create mode 100644 spec/models/currency_spec.rb diff --git a/app/controllers/admin/currencies_controller.rb b/app/controllers/admin/currencies_controller.rb new file mode 100644 index 0000000..95f67c7 --- /dev/null +++ b/app/controllers/admin/currencies_controller.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true +module Admin + class CurrenciesController < Admin::ApplicationController + end +end diff --git a/app/dashboards/currency_dashboard.rb b/app/dashboards/currency_dashboard.rb new file mode 100644 index 0000000..9364ffa --- /dev/null +++ b/app/dashboards/currency_dashboard.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true +require "administrate/base_dashboard" + +class CurrencyDashboard < Administrate::BaseDashboard + # ATTRIBUTE_TYPES + # a hash that describes the type of each of the model's fields. + # + # Each different type represents an Administrate::Field object, + # which determines how the attribute is displayed + # on pages throughout the dashboard. + ATTRIBUTE_TYPES = { + id: Field::Number, + name: Field::String, + created_at: Field::DateTime, + updated_at: Field::DateTime, + }.freeze + + # COLLECTION_ATTRIBUTES + # an array of attributes that will be displayed on the model's index page. + # + # By default, it's limited to four items to reduce clutter on index pages. + # Feel free to add, remove, or rearrange items. + COLLECTION_ATTRIBUTES = [:id, :name, :created_at, :updated_at].freeze + + # SHOW_PAGE_ATTRIBUTES + # an array of attributes that will be displayed on the model's show page. + SHOW_PAGE_ATTRIBUTES = [:id, :name, :created_at, :updated_at].freeze + + # FORM_ATTRIBUTES + # an array of attributes that will be displayed + # on the model's form (`new` and `edit`) pages. + FORM_ATTRIBUTES = [:name].freeze + + # COLLECTION_FILTERS + # a hash that defines filters that can be used while searching via the search + # field of the dashboard. + # + # For example to add an option to search for open resources by typing "open:" + # in the search field: + # + # COLLECTION_FILTERS = { + # open: ->(resources) { resources.where(open: true) } + # }.freeze + COLLECTION_FILTERS = {}.freeze + + # Overwrite this method to customize how currencies are displayed + # across all pages of the admin dashboard. + # + # def display_resource(currency) + # "Currency ##{currency.id}" + # end +end diff --git a/app/models/currency.rb b/app/models/currency.rb new file mode 100644 index 0000000..1b32a3a --- /dev/null +++ b/app/models/currency.rb @@ -0,0 +1,14 @@ +# 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 +# +class Currency < ApplicationRecord + validates :name, presence: true +end diff --git a/config/routes.rb b/config/routes.rb index 4fcf6a4..5eaa02c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,6 +6,7 @@ Rails.application.routes.draw do namespace :admin do resources :users resources :user_documents + resources :currencies resources :admin_users root to: "users#index" diff --git a/db/migrate/20210811014107_create_currencies.rb b/db/migrate/20210811014107_create_currencies.rb new file mode 100644 index 0000000..78d5c83 --- /dev/null +++ b/db/migrate/20210811014107_create_currencies.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +class CreateCurrencies < ActiveRecord::Migration[6.1] + def change + create_table(:currencies) do |t| + t.string(:name, null: false) + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index aba024e..8d91afe 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_08_08_153626) do +ActiveRecord::Schema.define(version: 2021_08_11_014107) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -55,6 +55,12 @@ ActiveRecord::Schema.define(version: 2021_08_08_153626) do t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true end + create_table "currencies", force: :cascade do |t| + t.string "name", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + create_table "user_documents", force: :cascade do |t| t.string "status", null: false t.bigint "user_id", null: false diff --git a/spec/models/currency_spec.rb b/spec/models/currency_spec.rb new file mode 100644 index 0000000..85691fd --- /dev/null +++ b/spec/models/currency_spec.rb @@ -0,0 +1,18 @@ +# 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 +# +require "rails_helper" + +RSpec.describe(Currency, type: :model) do + describe "validations" do + it { is_expected.to(validate_presence_of(:name)) } + end +end From 38b60ca0fa0ea81d52fcddc3b64ca03b81ba2702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Wed, 11 Aug 2021 09:28:42 -0300 Subject: [PATCH 2/3] add balance entity --- app/controllers/admin/balances_controller.rb | 5 ++ .../admin/currencies_controller.rb | 3 ++ app/dashboards/balance_dashboard.rb | 54 +++++++++++++++++++ app/dashboards/currency_dashboard.rb | 6 +-- app/models/balance.rb | 29 ++++++++++ app/models/user.rb | 1 + config/locales/activerecord.yml | 11 +++- config/routes.rb | 2 +- db/migrate/20210811121726_create_balances.rb | 13 +++++ db/schema.rb | 14 ++++- db/seeds.rb | 24 ++++++--- spec/models/balance_spec.rb | 35 ++++++++++++ spec/models/user_spec.rb | 1 + 13 files changed, 184 insertions(+), 14 deletions(-) create mode 100644 app/controllers/admin/balances_controller.rb create mode 100644 app/dashboards/balance_dashboard.rb create mode 100644 app/models/balance.rb create mode 100644 db/migrate/20210811121726_create_balances.rb create mode 100644 spec/models/balance_spec.rb diff --git a/app/controllers/admin/balances_controller.rb b/app/controllers/admin/balances_controller.rb new file mode 100644 index 0000000..ecad826 --- /dev/null +++ b/app/controllers/admin/balances_controller.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true +module Admin + class BalancesController < Admin::ApplicationController + end +end diff --git a/app/controllers/admin/currencies_controller.rb b/app/controllers/admin/currencies_controller.rb index 95f67c7..46afa63 100644 --- a/app/controllers/admin/currencies_controller.rb +++ b/app/controllers/admin/currencies_controller.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true module Admin class CurrenciesController < Admin::ApplicationController + def valid_action?(name, resource = resource_class) + ["new", "edit", "destroy"].exclude?(name.to_s) && super + end end end diff --git a/app/dashboards/balance_dashboard.rb b/app/dashboards/balance_dashboard.rb new file mode 100644 index 0000000..e7ffaa1 --- /dev/null +++ b/app/dashboards/balance_dashboard.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true +require "administrate/base_dashboard" + +class BalanceDashboard < Administrate::BaseDashboard + # ATTRIBUTE_TYPES + # a hash that describes the type of each of the model's fields. + # + # Each different type represents an Administrate::Field object, + # which determines how the attribute is displayed + # on pages throughout the dashboard. + ATTRIBUTE_TYPES = { + user: Field::BelongsTo, + currency: Field::BelongsTo, + id: Field::Number, + amount: Field::String.with_options(searchable: false), + created_at: Field::DateTime, + updated_at: Field::DateTime, + }.freeze + + # COLLECTION_ATTRIBUTES + # an array of attributes that will be displayed on the model's index page. + # + # By default, it's limited to four items to reduce clutter on index pages. + # Feel free to add, remove, or rearrange items. + COLLECTION_ATTRIBUTES = [:user, :currency, :id, :amount].freeze + + # SHOW_PAGE_ATTRIBUTES + # an array of attributes that will be displayed on the model's show page. + SHOW_PAGE_ATTRIBUTES = [:user, :currency, :id, :amount, :created_at, :updated_at].freeze + + # FORM_ATTRIBUTES + # an array of attributes that will be displayed + # on the model's form (`new` and `edit`) pages. + FORM_ATTRIBUTES = [:user, :currency, :amount].freeze + + # COLLECTION_FILTERS + # a hash that defines filters that can be used while searching via the search + # field of the dashboard. + # + # For example to add an option to search for open resources by typing "open:" + # in the search field: + # + # COLLECTION_FILTERS = { + # open: ->(resources) { resources.where(open: true) } + # }.freeze + COLLECTION_FILTERS = {}.freeze + + # Overwrite this method to customize how balances are displayed + # across all pages of the admin dashboard. + # + # def display_resource(balance) + # "Balance ##{balance.id}" + # end +end diff --git a/app/dashboards/currency_dashboard.rb b/app/dashboards/currency_dashboard.rb index 9364ffa..bbf9036 100644 --- a/app/dashboards/currency_dashboard.rb +++ b/app/dashboards/currency_dashboard.rb @@ -46,7 +46,7 @@ class CurrencyDashboard < Administrate::BaseDashboard # Overwrite this method to customize how currencies are displayed # across all pages of the admin dashboard. # - # def display_resource(currency) - # "Currency ##{currency.id}" - # end + def display_resource(currency) + currency.name + end end diff --git a/app/models/balance.rb b/app/models/balance.rb new file mode 100644 index 0000000..8dfc70b --- /dev/null +++ b/app/models/balance.rb @@ -0,0 +1,29 @@ +# 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) +# +class Balance < ApplicationRecord + belongs_to :user + belongs_to :currency + + validates :amount, presence: true +end diff --git a/app/models/user.rb b/app/models/user.rb index 29b0cfa..be95b3b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,6 +25,7 @@ class User < ApplicationRecord :recoverable, :rememberable, :validatable has_many :documents, class_name: "UserDocument", dependent: :destroy + has_many :balances, dependent: :restrict_with_error validates :first_name, :last_name, :email, presence: true validates :email, uniqueness: true diff --git a/config/locales/activerecord.yml b/config/locales/activerecord.yml index 803fcda..802053a 100644 --- a/config/locales/activerecord.yml +++ b/config/locales/activerecord.yml @@ -5,9 +5,16 @@ pt-BR: one: Documentos de Usuário other: Documentos de Usuários admin_user: - one: Usuário Administrador - other: Usuários Administradores + one: Administrador + other: Administradores + currency: + one: Moeda + other: Moedas + balance: + one: Saldo + other: Saldos attributes: user: first_name: Primeiro nome last_name: Último nome + full_name: Nome completo diff --git a/config/routes.rb b/config/routes.rb index 5eaa02c..6fb3107 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,7 +5,7 @@ Rails.application.routes.draw do namespace :admin do resources :users - resources :user_documents + resources :balances resources :currencies resources :admin_users diff --git a/db/migrate/20210811121726_create_balances.rb b/db/migrate/20210811121726_create_balances.rb new file mode 100644 index 0000000..8281e88 --- /dev/null +++ b/db/migrate/20210811121726_create_balances.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +class CreateBalances < ActiveRecord::Migration[6.1] + def change + create_table(:balances) do |t| + t.references(:user, null: false, foreign_key: true) + t.references(:currency, null: false, foreign_key: true) + + t.decimal(:amount, precision: 20, scale: 10, null: false, default: 0) + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 8d91afe..166df6e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_08_11_014107) do +ActiveRecord::Schema.define(version: 2021_08_11_121726) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -55,6 +55,16 @@ ActiveRecord::Schema.define(version: 2021_08_11_014107) do t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true end + create_table "balances", force: :cascade do |t| + t.bigint "user_id", null: false + t.bigint "currency_id", null: false + t.decimal "amount", precision: 20, scale: 10, default: "0.0", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["currency_id"], name: "index_balances_on_currency_id" + t.index ["user_id"], name: "index_balances_on_user_id" + end + create_table "currencies", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", precision: 6, null: false @@ -85,5 +95,7 @@ ActiveRecord::Schema.define(version: 2021_08_11_014107) do add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" + add_foreign_key "balances", "currencies" + add_foreign_key "balances", "users" add_foreign_key "user_documents", "users" end diff --git a/db/seeds.rb b/db/seeds.rb index c8c1b75..a60d211 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,8 +1,18 @@ # frozen_string_literal: true -# This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). -# -# Examples: -# -# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) -# Character.create(name: 'Luke', movie: movies.first) + +AdminUser.create(email: "admin@example.com", password: "password") + +user = User.create!( + first_name: "Test", + last_name: "User", + email: "user@example.com", + password: "password" +) + +currency = Currency.create!(name: "CAKE") + +Balance.create!( + user_id: user.id, + currency_id: currency.id, + amount: 153124.72088 +) diff --git a/spec/models/balance_spec.rb b/spec/models/balance_spec.rb new file mode 100644 index 0000000..67694fc --- /dev/null +++ b/spec/models/balance_spec.rb @@ -0,0 +1,35 @@ +# 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) +# +require "rails_helper" + +RSpec.describe(Balance, type: :model) do + describe "validations" do + it { is_expected.to(validate_presence_of(:amount)) } + end + + describe "associations" do + it { is_expected.to(belong_to(:user)) } + it { is_expected.to(belong_to(:currency)) } + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 19aa188..8845843 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -31,5 +31,6 @@ RSpec.describe(User, type: :model) do describe "associations" do it { is_expected.to(have_many(:documents)) } + it { is_expected.to(have_many(:balances)) } end end From a057931c51ddd3b28590068cbf912c201e34fbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Wed, 11 Aug 2021 20:51:42 -0300 Subject: [PATCH 3/3] wallet screen --- app/controllers/admin/balances_controller.rb | 3 + app/controllers/application_controller.rb | 2 - app/controllers/graphql_controller.rb | 2 + app/graphql/types/balance_type.rb | 13 ++ app/graphql/types/currency_type.rb | 12 + app/graphql/types/query_type.rb | 5 + app/graphql/types/user_type.rb | 3 +- app/graphql/x_stake_schema.rb | 15 +- app/javascript/__generated__/schema.graphql | 122 ++++++++++ app/javascript/src/Routes.tsx | 7 +- app/javascript/src/components/SideNav.tsx | 4 - app/javascript/src/pages/Wallet/Wallet.tsx | 94 ++++++++ .../__generated__/WalletQuery.graphql.ts | 165 ++++++++++++++ app/javascript/src/pages/Wallet/index.ts | 1 + app/javascript/src/pages/index.ts | 1 + app/javascript/src/pages/index.tsx | 1 - app/policies/balance_policy.rb | 10 + db/seeds.rb | 210 +++++++++++++++++- spec/policies/balance_policy_spec.rb | 6 + 19 files changed, 656 insertions(+), 20 deletions(-) create mode 100644 app/graphql/types/balance_type.rb create mode 100644 app/graphql/types/currency_type.rb create mode 100644 app/javascript/src/pages/Wallet/Wallet.tsx create mode 100644 app/javascript/src/pages/Wallet/__generated__/WalletQuery.graphql.ts create mode 100644 app/javascript/src/pages/Wallet/index.ts delete mode 100644 app/javascript/src/pages/index.tsx create mode 100644 app/policies/balance_policy.rb create mode 100644 spec/policies/balance_policy_spec.rb diff --git a/app/controllers/admin/balances_controller.rb b/app/controllers/admin/balances_controller.rb index ecad826..7ab3220 100644 --- a/app/controllers/admin/balances_controller.rb +++ b/app/controllers/admin/balances_controller.rb @@ -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 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b218fb5..d970904 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true class ApplicationController < ActionController::Base - include Pundit - before_action :configure_devise_permitted_parameters, if: :devise_controller? protected diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index a524f70..76fb005 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -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] diff --git a/app/graphql/types/balance_type.rb b/app/graphql/types/balance_type.rb new file mode 100644 index 0000000..f1a3e09 --- /dev/null +++ b/app/graphql/types/balance_type.rb @@ -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 diff --git a/app/graphql/types/currency_type.rb b/app/graphql/types/currency_type.rb new file mode 100644 index 0000000..6c35166 --- /dev/null +++ b/app/graphql/types/currency_type.rb @@ -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 diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index f662605..95b6fb0 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -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 diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb index 61bfec3..efd0c7b 100644 --- a/app/graphql/types/user_type.rb +++ b/app/graphql/types/user_type.rb @@ -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 diff --git a/app/graphql/x_stake_schema.rb b/app/graphql/x_stake_schema.rb index afef4fc..b89bdee 100644 --- a/app/graphql/x_stake_schema.rb +++ b/app/graphql/x_stake_schema.rb @@ -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 diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index 79516c9..1594f5e 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -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 { diff --git a/app/javascript/src/Routes.tsx b/app/javascript/src/Routes.tsx index 23528f3..b429084 100644 --- a/app/javascript/src/Routes.tsx +++ b/app/javascript/src/Routes.tsx @@ -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 ( - + + + + ); }; diff --git a/app/javascript/src/components/SideNav.tsx b/app/javascript/src/components/SideNav.tsx index 62099c0..71289fa 100644 --- a/app/javascript/src/components/SideNav.tsx +++ b/app/javascript/src/components/SideNav.tsx @@ -14,10 +14,6 @@ const MenuItems: MenuItem[] = [ label: "Início", path: "/", }, - { - label: "Stake", - path: "/stake", - }, { label: "Carteira", path: "/wallet", diff --git a/app/javascript/src/pages/Wallet/Wallet.tsx b/app/javascript/src/pages/Wallet/Wallet.tsx new file mode 100644 index 0000000..727cf17 --- /dev/null +++ b/app/javascript/src/pages/Wallet/Wallet.tsx @@ -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( + graphql` + query WalletQuery { + balances { + nodes { + id + amount + currency { + name + } + } + } + } + `, + {} + ); + + const tokensList = Object.values(tokens); + + return ( +
+
+
+
+
+ + + + + + + + + {balances.nodes?.map((balance) => { + const token = tokensList.find( + ({ symbol }) => symbol === balance?.currency.name + ); + + return ( + + + + + ); + })} + +
+ Moeda + + Saldo +
+
+
+ + profil + +
+
+

+ {balance?.currency.name} +

+
+
+
+

+ {balance?.amount} +

+
+
+
+
+
+
+ ); +}; diff --git a/app/javascript/src/pages/Wallet/__generated__/WalletQuery.graphql.ts b/app/javascript/src/pages/Wallet/__generated__/WalletQuery.graphql.ts new file mode 100644 index 0000000..2e49fb5 --- /dev/null +++ b/app/javascript/src/pages/Wallet/__generated__/WalletQuery.graphql.ts @@ -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; diff --git a/app/javascript/src/pages/Wallet/index.ts b/app/javascript/src/pages/Wallet/index.ts new file mode 100644 index 0000000..7397bec --- /dev/null +++ b/app/javascript/src/pages/Wallet/index.ts @@ -0,0 +1 @@ +export * from "./Wallet"; diff --git a/app/javascript/src/pages/index.ts b/app/javascript/src/pages/index.ts index 5d79295..f07c67e 100644 --- a/app/javascript/src/pages/index.ts +++ b/app/javascript/src/pages/index.ts @@ -1 +1,2 @@ export * from "./Home"; +export * from "./Wallet"; diff --git a/app/javascript/src/pages/index.tsx b/app/javascript/src/pages/index.tsx deleted file mode 100644 index 5d79295..0000000 --- a/app/javascript/src/pages/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from "./Home"; diff --git a/app/policies/balance_policy.rb b/app/policies/balance_policy.rb new file mode 100644 index 0000000..f867bb3 --- /dev/null +++ b/app/policies/balance_policy.rb @@ -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 diff --git a/db/seeds.rb b/db/seeds.rb index a60d211..3a1a6de 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -9,10 +9,208 @@ user = User.create!( password: "password" ) -currency = Currency.create!(name: "CAKE") +tokens = [ + "BNB", + "CAKE", + "CHESS", + "TITAN", + "ONE", + "MASK", + "DVI", + "ADX", + "BSCPAD", + "RABBIT", + "FORM", + "TXL", + "ORBS", + "COS", + "BUNNY", + "ALICE", + "FOR", + "BUX", + "NULS", + "BELT", + "RAMP", + "BFI", + "DEXE", + "BEL", + "TPT", + "WATCH", + "xMARK", + "bMXX", + "IOTX", + "BOR", + "bOPEN", + "DODO", + "SWINGBY", + "BRY", + "ZEE", + "SWGb", + "SWG", + "SFP", + "LINA", + "LIT", + "HGET", + "BDO", + "EGLD", + "UST", + "wSOTE", + "FRONT", + "Helmet", + "BTCST", + "BSCX", + "TEN", + "bALBT", + "ASR", + "ATM", + "OG", + "REEF", + "DITTO", + "JUV", + "PSG", + "VAI", + "wBNB", + "BLINK", + "UNFI", + "TWT", + "HARD", + "bROOBEE", + "STAX", + "NAR", + "NYA", + "CTK", + "INJ", + "SXP", + "ALPHA", + "XVS", + "SUSHI", + "COMP", + "SYRUP", + "BIFI", + "DUSK", + "BUSD", + "ETH", + "BETH", + "mAMZN", + "mGOOGL", + "mNFLX", + "mTSLA", + "LTC", + "USDC", + "DAI", + "ADA", + "BAND", + "DOT", + "EOS", + "LINK", + "USDT", + "BTCB", + "XRP", + "ATOM", + "YFII", + "XTZ", + "BCH", + "YFI", + "UNI", + "FIL", + "BAKE", + "BURGER", + "bDIGG", + "bBadger", + "TRADE", + "PNT", + "MIR", + "pBTC", + "LTO", + "pCWS", + "ZIL", + "LIEN", + "SWTH", + "DFT", + "GUM", + "DEGO", + "NRV", + "EASY", + "ODDZ", + "HOO", + "APYS", + "BONDLY", + "TKO", + "ITAM", + "ARPA", + "EPS", + "JGN", + "TLM", + "PERL", + "ALPA", + "HZN", + "SUTER", + "CGG", + "MIX", + "HAKKA", + "XED", + "τBTC", + "ALPACA", + "DFD", + "LMT", + "BTT", + "TRX", + "WIN", + "mCOIN", + "MATH", + "KUN", + "QSD", + "HYFI", + "OIN", + "DOGE", + "FINE", + "ONE", + "PMON", + "HOTCROSS", + "τDOGE", + "BTR", + "UBXT", + "WMASS", + "RFOX", + "XEND", + "CYC", + "CHR", + "KALM", + "DERI", + "WELL", + "WEX", + "WAULTx", + "pOPEN", + "EZ", + "VRT", + "TUSD", + "MTRG", + "KTN", + "QKC", + "bCFX", + "MX", + "ATA", + "MBOX", + "BORING", + "MARSH", + "AMPL", + "O3", + "HAI", + "HTB", + "WOO", + "$DG", +] -Balance.create!( - user_id: user.id, - currency_id: currency.id, - amount: 153124.72088 -) +currencies = tokens.map do |token| + Currency.create!(name: token) +end + +currencies.each do |currency| + random_floating_number = (rand * (10000 - 0) + 0) + + Balance.create!( + user_id: user.id, + currency_id: currency.id, + amount: random_floating_number + ) +end diff --git a/spec/policies/balance_policy_spec.rb b/spec/policies/balance_policy_spec.rb new file mode 100644 index 0000000..eb3c421 --- /dev/null +++ b/spec/policies/balance_policy_spec.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +require "rails_helper" + +RSpec.describe(BalancePolicy, type: :policy) do + pending "add some examples to (or delete) #{__FILE__}" +end