diff --git a/app/controllers/frontend_controller.rb b/app/controllers/frontend_controller.rb index 1c6dbfe..50ab280 100644 --- a/app/controllers/frontend_controller.rb +++ b/app/controllers/frontend_controller.rb @@ -1,5 +1,6 @@ class FrontendController < ApplicationController def index - render html: File.read(Rails.root.join("public/index.html")).html_safe + path = Rails.env.production? ? "public/index.html" : "web/build/index.html" + render html: File.read(Rails.root.join(path)).html_safe end end diff --git a/app/models/category_budget.rb b/app/models/category_budget.rb index e4ab6fe..3059c64 100644 --- a/app/models/category_budget.rb +++ b/app/models/category_budget.rb @@ -7,7 +7,10 @@ class CategoryBudget < ApplicationRecord validates :budget_cents, numericality: { greater_than_or_equal_to: 0 } scope :for_date_scope, ->(date) { order(date_from: :asc).where("date_from <= :date AND (date_to >= :date OR date_to IS NULL)", date: date) } - scope :for_date, ->(date) { for_date_scope(date).first } + + def self.for_date(date) + for_date_scope(date).first + end def budget Money.new(amount_cents: budget_cents, currency:) diff --git a/app/services/exchange_rates/convert_money.rb b/app/services/exchange_rates/convert_money.rb index 713e543..e9896b7 100644 --- a/app/services/exchange_rates/convert_money.rb +++ b/app/services/exchange_rates/convert_money.rb @@ -24,26 +24,27 @@ def call private def exchange_rates - @exchange_rates ||= existing_exchange_rates + sync_exchange_rates + @exchange_rates ||= existing_exchange_rates.merge(sync_exchange_rates) end def sync_exchange_rates - (needed_exchange_rates - existing_exchange_rates.keys).map do |date, from_currency| - ExchangeRates::Fetch.call(from_currency, date).find do |rate| + index_rates((needed_exchange_rates - existing_exchange_rates.keys).map do |date, from_currency| + ExchangeRates::Fetch.new(from_currency, date).call.find do |rate| rate.to_currency == to_currency end - end + end) end def existing_exchange_rates - @existing_exchange_rates ||= ExchangeRateValue. + @existing_exchange_rates ||= index_rates(ExchangeRateValue. includes(:from_currency, :to_currency). - where(to_currency:, date: money_on_dates.compact.map(&:date).uniq). - flat_map do |rate| - rate.exchange_rate_values.map do |value| - { [rate.date, value.from_currency] => value.rate } - end - end + where(to_currency:, date: money_on_dates.compact.map(&:date).uniq)) + end + + def index_rates(rates) + rates.to_h do |rate| + [[rate.date, rate.from_currency], rate.rate] + end end def needed_exchange_rates diff --git a/app/services/exchange_rates/fetch.rb b/app/services/exchange_rates/fetch.rb index c81d724..6a02ffc 100644 --- a/app/services/exchange_rates/fetch.rb +++ b/app/services/exchange_rates/fetch.rb @@ -9,7 +9,7 @@ def initialize(from_currency, date) end def call - response = fetch_exchange_rate(date) || fetch_exchange_rate("latest") || raise(FetchFailedError, "Failed to fetch exchange rate") + response = fetch_exchange_rate(formatted_date) || fetch_exchange_rate("latest") || raise(FetchFailedError, "Failed to fetch exchange rate") return if response.nil? save_exchange_rates(response) @@ -17,21 +17,23 @@ def call private + def formatted_date + date.strftime("%Y.%-m.%-d") + end + def save_exchange_rates(response) Currency.all.map do |currency| - next if currency == from_currency - ExchangeRateValue.create!( from_currency:, to_currency: currency, date:, - rate: response[from_currency.code.downcase][currency.code.downcase] + rate: currency == from_currency ? 1 : response[from_currency.code.downcase][currency.code.downcase] ) end end def fetch_exchange_rate(date) - response = Faraday.get("https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/#{date}/currencies/#{from_currency.code.downcase}.json") + response = Faraday.get("https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@#{date}/v1/currencies/#{from_currency.code.downcase}.json") return if response.status != 200 JSON.parse(response.body) diff --git a/config/environments/development.rb b/config/environments/development.rb index f962d9f..3ea8886 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -68,4 +68,10 @@ # Raise error when a before_action's only/except options reference missing actions config.action_controller.raise_on_missing_callback_actions = true + + Rails.application.config.middleware.insert_after( + ActionDispatch::Static, + ActionDispatch::Static, + Rails.root.join("web/build").to_s + ) end diff --git a/db/seeds.rb b/db/seeds.rb index 97a4155..df932a5 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -15,6 +15,13 @@ decimal_digits: 2 ) +gbp = Currency.find_by(code: "GBP") || Currency.create!( + code: "GBP", + name: "Pounds Sterling", + symbol: "£", + decimal_digits: 2 +) + Category.find_by(name: "First") || Category.create!( name: "First", color: "red", @@ -31,11 +38,9 @@ account = Account.find_by(name: "Test") || Account.create!(name: "Test", currency: usd) -(ENV["USER_EMAILS"]&.split(",") || []).each do |email| - User.find_or_initialize_by(email:) || User.create!( - email:, - password: "changeme", - default_currency: usd, - default_account: account - ) -end +User.find_by(email: "test@example.com") || User.create!( + email: "test@example.com", + password: "changeme", + default_currency: usd, + default_account: account +) diff --git a/package.json b/package.json index 32c8c2c..79c2969 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "prettier-plugin-tailwindcss": "^0.1.13" }, "scripts": { - "dev": "concurrently -n api,web,api-codegen,web-codegen -c blue,magenta,green,yellow 'cd api && bun run --watch bin/dev.ts' 'cd web && bun run watch' 'cd api && bun graphql-codegen --watch' 'cd web && bun graphql-codegen --watch'", + "dev": "concurrently -n api,web,codegen -c blue,magenta,yellow 'rails s' 'cd web && bun run watch' 'cd web && bun graphql-codegen --watch'", "dev:test": "cd api && ENV_TYPE=test PORT=4445 bun run bin/dev-test.ts", "deploy": "bun run deploy.js", "typecheck": "web && bun typecheck", diff --git a/web/src/components/transactions/NewTransactionModal.tsx b/web/src/components/transactions/NewTransactionModal.tsx index 40f4066..393d9cc 100644 --- a/web/src/components/transactions/NewTransactionModal.tsx +++ b/web/src/components/transactions/NewTransactionModal.tsx @@ -68,11 +68,11 @@ export const NewTransactionModal: Component<{ } }) - let memoInput: HTMLInputElement | undefined + let shopInput: HTMLInputElement | undefined createEffect(() => { if (isDateSelected()) { - memoInput?.focus() + shopInput?.focus() } }) @@ -99,8 +99,7 @@ export const NewTransactionModal: Component<{ : amountType === "expense" ? -integerAmount : integerAmount, - date: stripTime(new Date(date)), - includeInReports: Boolean(data.includeInReports) + date: stripTime(new Date(date)) } if (shopCurrencyId && shopAmount) { @@ -149,7 +148,7 @@ export const NewTransactionModal: Component<{ <> - + New Transaction @@ -170,7 +169,7 @@ export const NewTransactionModal: Component<{ { @@ -189,13 +188,7 @@ export const NewTransactionModal: Component<{ }} /> - + + onClick={() => { updateTransaction({ id: props.transaction.id, input: { includeInReports: !props.transaction.includeInReports } }) - } + onToggle(false) + }} > {props.transaction.includeInReports ? ( <> diff --git a/web/src/utils/graphqlClient/requestGraphql.ts b/web/src/utils/graphqlClient/requestGraphql.ts index 8bbbe7a..76d1b69 100644 --- a/web/src/utils/graphqlClient/requestGraphql.ts +++ b/web/src/utils/graphqlClient/requestGraphql.ts @@ -37,7 +37,7 @@ export const requestGraphql = async ( return data } -const maxRetries = 10 +const maxRetries = 2 const fetchWithRetry = async (fetch: () => Promise, retries = 0): Promise => { const response = await fetch() @@ -51,8 +51,10 @@ const fetchWithRetry = async (fetch: () => Promise, retries = 0): Prom } if (retries < maxRetries) { - return fetchWithRetry(fetch, retries + 1) + return new Promise((resolve) => setTimeout(resolve, 2000)).then(() => + fetchWithRetry(fetch, retries + 1) + ) } - throw new Error("Still getting 50x errors after max retries exceeded. Plesae try again later.") + throw new Error("Still getting 50x errors after max retries exceeded. Please try again later.") }