diff --git a/app/controllers/chips_controller.rb b/app/controllers/chips_controller.rb index b19e27a..950d937 100644 --- a/app/controllers/chips_controller.rb +++ b/app/controllers/chips_controller.rb @@ -1,6 +1,29 @@ class ChipsController < ApplicationController def index - json_response Chip.where(enabled: true).order(:name).to_json(include: :base_chip_values) + all_chips = [ + { + id: 1, + name: 'US Dollar', + symbol: '$', + code: 'USD', + prefixed: true + }, + { + id: 2, + name: 'Bosnian Convertible Mark', + symbol: 'KM', + code: 'BAM', + prefixed: false + }, + { + id: 3, + name: 'Euro', + symbol: '€', + code: 'EUR', + prefixed: false + } + ] + json_response all_chips end def create diff --git a/app/controllers/homies_controller.rb b/app/controllers/homies_controller.rb index 014751e..ee187fc 100644 --- a/app/controllers/homies_controller.rb +++ b/app/controllers/homies_controller.rb @@ -45,8 +45,7 @@ class HomiesController < ApplicationController params.require(:homie).permit( :name, :importance, - :about, - :chip_id + :about ) end end diff --git a/app/controllers/ogs_controller.rb b/app/controllers/ogs_controller.rb new file mode 100644 index 0000000..f96700b --- /dev/null +++ b/app/controllers/ogs_controller.rb @@ -0,0 +1,28 @@ +class OgsController < ApplicationController + def show + if Og.count.zero? + Og.create.save + end + + json_response Og.first + end + + def update + if og_params[:chip_scale].to_i.positive? + Og.update(og_params) + json_response onboarded: true + else + error_response :bad_request + end + end + + private + + def og_params + params.require(:og).permit :chip_name, + :chip_code, + :chip_symbol, + :chip_scale, + :chip_prefixed + end +end \ No newline at end of file diff --git a/app/models/homie.rb b/app/models/homie.rb index 9d5d5f6..1c67391 100644 --- a/app/models/homie.rb +++ b/app/models/homie.rb @@ -1,7 +1,6 @@ class Homie < ApplicationRecord has_many :money_moves has_many :work - belongs_to :chip def self.cash(importance) totals = Homie.all.joins(:money_moves).group(:id).order(:id).sum(:amount) diff --git a/app/models/og.rb b/app/models/og.rb new file mode 100644 index 0000000..c190614 --- /dev/null +++ b/app/models/og.rb @@ -0,0 +1,3 @@ +class Og < ApplicationRecord + +end \ No newline at end of file diff --git a/client/src/App.css b/client/src/App.css index 4a6d56e..d5bdbce 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -48,4 +48,10 @@ .required:before { color: red; content: "* "; +} + +.preloader-circle { + position: absolute; + height: 90%; + margin-left: 40%; } \ No newline at end of file diff --git a/client/src/App.js b/client/src/App.js index e831832..fa11d1a 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,24 +1,75 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import './App.css'; import { Navbar } from 'react-materialize'; import MakeMoneyMove from './cash/MakeMoneyMove'; import Flow from "./homies/Flow"; import Cash from './cash/Cash'; -import Chips from './chips/Chips'; import Homies from './homies/Homies'; import { BrowserRouter as Router, Route } from "react-router-dom"; import RoutableNavItem from './common/RoutableNavItem'; +import axios from 'axios'; import { CRIB, - CHIPS, MAKE_MONEY_MOVE, HOMIE_FLOW, HOMIES, PUT_IN_WORK } from './RouteNames'; import PutInWork from "./cash/PutInWork"; +import ChipSelection from "./ogOnboarding/ChipSelection"; +import {errorToast} from "./common/errorHelpers"; -function App() { +const App = (props) => { + const [loading, setLoading] = useState(true); + const [og, setOg] = useState({}); + + useEffect(() => { + (async() => { + try { + setLoading(true); + const response = await axios.get(`/api/og`); + if (response.status === 200 && response.data){ + setOg(response.data); + }else{ + errorToast(); + } + } catch (e) { + errorToast(); + } + setLoading(false); + })(); + }, []); + + const routes = ([ + } />, + } />, + } />, + } /> + ] + ); + + const onboarded = () => og.chip_name && og.chip_name.length > 0; + + const preloaderCircle = ( +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ); + return (
@@ -31,10 +82,6 @@ function App() { Homies - - Chips - - Make Money Move @@ -49,9 +96,11 @@ function App() { - + { loading && preloaderCircle } + { !loading && !onboarded() && } + { !loading && onboarded() && routes }
); diff --git a/client/src/RouteNames.js b/client/src/RouteNames.js index ae706c3..446919b 100644 --- a/client/src/RouteNames.js +++ b/client/src/RouteNames.js @@ -1,6 +1,5 @@ export const CRIB = '/'; export const HOMIES = '/homies'; -export const CHIPS = '/chips'; export const MAKE_MONEY_MOVE = '/make-money-move'; export const PUT_IN_WORK = '/put-in-work'; export const HOMIE_FLOW = '/homie/:homie_id/flow'; diff --git a/client/src/cash/Cash.js b/client/src/cash/Cash.js index 6f22627..9df9502 100644 --- a/client/src/cash/Cash.js +++ b/client/src/cash/Cash.js @@ -13,6 +13,7 @@ const Cash = (props) => { const [homiesCash, setHomiesCash] = useState([]); const [, forceUpdate] = useReducer(x => x + 1, 0); //const [importance, setImportance] = useState(10); + const og = props.og; useEffect( () => { const getCashForHomies = async () => { @@ -47,7 +48,7 @@ const Cash = (props) => { { homieLine.homie.name } - { formatMoney(homieLine.amount) } + { formatMoney(homieLine.amount, og) } [ diff --git a/client/src/cash/MakeMoneyMove.js b/client/src/cash/MakeMoneyMove.js index ac8f499..31a9fd7 100644 --- a/client/src/cash/MakeMoneyMove.js +++ b/client/src/cash/MakeMoneyMove.js @@ -9,7 +9,7 @@ const MakeMoneyMove = (props) => { const [selectedFrom, setSelectedFrom] = useState(""); const [selectedTo, setSelectedTo] = useState(""); const [homiesCash, setHomiesCash] = useState([]); - const [amountToMove, setAmountToMove] = useState(null); + const [amountToMove, setAmountToMove] = useState(''); const [moveDescription, setMoveDescription] = useState(""); const [submitInProgress, setSubmitInProgress] = useState(false); diff --git a/client/src/common/formatting.js b/client/src/common/formatting.js index 1f64e6c..ca600ee 100644 --- a/client/src/common/formatting.js +++ b/client/src/common/formatting.js @@ -1,6 +1,10 @@ -const formatMoney = (amount) => { - const formatted = Number.parseFloat(amount).toFixed(2); - return `${formatted} KM`; +const formatMoney = (amount, og) => { + const decimalPlaces = parseInt(og['chip_scale']); + const symbol = og['chip_symbol']; + const prefixed = og['chip_prefixed']; + + const formatted = Number.parseFloat(amount).toFixed(decimalPlaces); + return prefixed ? `${symbol} ${formatted}` : `${formatted} ${symbol}`; } const formatTime = (amount) => { diff --git a/client/src/homies/Flow.js b/client/src/homies/Flow.js index 87a82d9..edfa015 100644 --- a/client/src/homies/Flow.js +++ b/client/src/homies/Flow.js @@ -16,13 +16,58 @@ const Flow = (props) => { onChange={(e) => setFlowType(e.target.checked === true ? 'work' : 'cash')} onLabel="Work" /> + const [flow, setFlow] = useState([]); + + const og = props.og; + + useEffect( () => { + (async () => { + try { + const response = await axios.get(`/api/money_moves?homie_id=${parseInt(homie_id)}`); + if (response.status === 200 && response.data){ + setFlow(response.data); + } + } catch (e) { + M.toast({ html: "Yo! It ain't workin'" }); + } + })(); + }, [homie_id]); + + const dateBlock = (timestamp) => { timestampToDate(timestamp) } + + + const flowData = flow.map( (singleFlowData, index) => ( +
  • +
    +
    +
    +
    { singleFlowData.description }
    +
    { dateBlock(singleFlowData['created_at']) }
    +
    + +
    0 ? 'amount-green' : ''}`}>{ formatMoney(singleFlowData.amount, og) }
    +
    { flowType === 'cash' && } { flowType === 'work' && } + return ( +
    +
    +
    +
    + {`${totalCount} Records`}{` • ${fromDate} - ${toDate}`} +
    +
    + Total flow: {formatMoney(totalFlow, og)} +
    +
    +
    + ) + }
  • ); } -export default withRouter(Flow); \ No newline at end of file +export default withRouter(Flow); diff --git a/client/src/homies/NewHomieForm.js b/client/src/homies/NewHomieForm.js index 2e9d9f9..04fcec3 100644 --- a/client/src/homies/NewHomieForm.js +++ b/client/src/homies/NewHomieForm.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import { Button, Collapsible, CollapsibleItem, Select, TextInput } from 'react-materialize'; import axios from 'axios'; import { errorToast } from "../common/errorHelpers"; @@ -8,31 +8,11 @@ const NewHomieForm = (props) => { const [homieName, setHomieName] = useState(""); const [aboutHomie, setAboutHomie] = useState(""); const [homieImportance, setHomieImportance] = useState(""); - const [homieDefaultChip, setHomieDefaultChip] = useState(""); - const [chips, setChips] = useState([]); const [busy, setBusy] = useState(false); - useEffect(() => { - (async () => { - try { - const response = await axios.get('/api/chips'); - if (response.status === 200 && response.data) { - setChips(response.data); - }else { - errorToast(); - } - }catch (e) { - errorToast(); - } - })(); - }, []); - - const chipOptions = chips.map((chip, index) => ); - const disableAddButton = () => { return homieName.length === 0 || homieImportance === "" || - homieDefaultChip === "" || busy; } @@ -40,7 +20,6 @@ const NewHomieForm = (props) => { setHomieName(""); setAboutHomie(""); setHomieImportance(""); - setHomieDefaultChip(""); const collapsible = document.getElementById('new-homie-form-container'); const collapsibleInstance = M.Collapsible.getInstance(collapsible); @@ -54,8 +33,7 @@ const NewHomieForm = (props) => { homie: { name: homieName, about: aboutHomie, - importance: parseInt(homieImportance), - chip_id: parseInt(homieDefaultChip) + importance: parseInt(homieImportance) } } @@ -103,12 +81,6 @@ const NewHomieForm = (props) => { - - -
    diff --git a/client/src/ogOnboarding/ChipSelection.js b/client/src/ogOnboarding/ChipSelection.js new file mode 100644 index 0000000..4810b0d --- /dev/null +++ b/client/src/ogOnboarding/ChipSelection.js @@ -0,0 +1,79 @@ +import React, { useState, useEffect } from 'react'; +import axios from "axios"; +import { errorToast } from "../common/errorHelpers"; +import {Button, Select, TextInput} from "react-materialize"; + +const ChipSelection = (props) => { + const [chips, setChips] = useState([]); + const [selectedChip, setSelectedChip] = useState('1'); + const [chipScale, setChipScale] = useState('2'); + + useEffect(() => { + (async() => { + try { + const response = await axios.get(`/api/chips`); + if (response.status === 200 && response.data){ + setChips(response.data); + }else{ + errorToast(); + } + } catch (e) { + errorToast(); + } + })(); + }, []); + + const chipsToOptions = chips.map( (chip, index) => ); + + const disableSubmit = () => { + return !((parseInt(selectedChip) > 0) && (parseInt(chipScale) > 0)); + } + + const handleSubmit = async () => { + const chipData = chips.find(chip => chip.id === parseInt(selectedChip)); + if (chipData){ + const og = { + chip_name: chipData.name, + chip_code: chipData.code, + chip_symbol: chipData.symbol, + chip_prefixed: chipData.prefixed, + chip_scale: parseInt(chipScale) + } + + try{ + const response = await axios.put('/api/og', { og }); + if (response.status === 200 && response.data && response.data.onboarded) { + window.location.reload(); + }else{ + errorToast(); + } + }catch (e) { + errorToast(); + } + }else{ + errorToast(); + } + } + + return ( +
    + + + setChipScale(e.target.value)} + /> + + +
    + ) +} + +export default ChipSelection; \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index e3f2417..d722171 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ Rails.application.routes.draw do constraints format: :json do scope :api do + resource :og, only: [:show, :update] resources :money_moves resources :work resources :chips, only: %i[index create destroy] diff --git a/db/migrate/20200918012614_remove_default_chip_from_homies.rb b/db/migrate/20200918012614_remove_default_chip_from_homies.rb new file mode 100644 index 0000000..17ffb40 --- /dev/null +++ b/db/migrate/20200918012614_remove_default_chip_from_homies.rb @@ -0,0 +1,5 @@ +class RemoveDefaultChipFromHomies < ActiveRecord::Migration[5.2] + def change + remove_reference :homies, :chip + end +end diff --git a/db/migrate/20200918032033_create_ogs.rb b/db/migrate/20200918032033_create_ogs.rb new file mode 100644 index 0000000..041a859 --- /dev/null +++ b/db/migrate/20200918032033_create_ogs.rb @@ -0,0 +1,13 @@ +class CreateOgs < ActiveRecord::Migration[5.2] + def change + create_table :ogs do |t| + t.text :chip_name + t.text :chip_code + t.text :chip_symbol + t.boolean :chip_prefixed + t.integer :chip_scale + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 41dcfe5..ee86e7b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -41,8 +41,6 @@ ActiveRecord::Schema.define(version: 2020_09_19_023237) do t.text "about" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.bigint "chip_id" - t.index ["chip_id"], name: "index_homies_on_chip_id" end create_table "money_moves", force: :cascade do |t| @@ -61,6 +59,16 @@ ActiveRecord::Schema.define(version: 2020_09_19_023237) do t.datetime "updated_at", null: false end + create_table "ogs", force: :cascade do |t| + t.text "chip_name" + t.text "chip_code" + t.text "chip_symbol" + t.boolean "chip_prefixed" + t.integer "chip_scale" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + add_foreign_key "chip_values", "chips", column: "base_chip_id" add_foreign_key "chip_values", "chips", column: "secondary_chip_id" end