diff --git a/Gemfile.lock b/Gemfile.lock index 883215e..4d41e8b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,29 @@ GEM remote: https://rubygems.org/ specs: - actioncable (8.0.3) - actionpack (= 8.0.3) - activesupport (= 8.0.3) + actioncable (8.0.4) + actionpack (= 8.0.4) + activesupport (= 8.0.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (8.0.3) - actionpack (= 8.0.3) - activejob (= 8.0.3) - activerecord (= 8.0.3) - activestorage (= 8.0.3) - activesupport (= 8.0.3) + actionmailbox (8.0.4) + actionpack (= 8.0.4) + activejob (= 8.0.4) + activerecord (= 8.0.4) + activestorage (= 8.0.4) + activesupport (= 8.0.4) mail (>= 2.8.0) - actionmailer (8.0.3) - actionpack (= 8.0.3) - actionview (= 8.0.3) - activejob (= 8.0.3) - activesupport (= 8.0.3) + actionmailer (8.0.4) + actionpack (= 8.0.4) + actionview (= 8.0.4) + activejob (= 8.0.4) + activesupport (= 8.0.4) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (8.0.3) - actionview (= 8.0.3) - activesupport (= 8.0.3) + actionpack (8.0.4) + actionview (= 8.0.4) + activesupport (= 8.0.4) nokogiri (>= 1.8.5) rack (>= 2.2.4) rack-session (>= 1.0.1) @@ -31,35 +31,35 @@ GEM rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (8.0.3) - actionpack (= 8.0.3) - activerecord (= 8.0.3) - activestorage (= 8.0.3) - activesupport (= 8.0.3) + actiontext (8.0.4) + actionpack (= 8.0.4) + activerecord (= 8.0.4) + activestorage (= 8.0.4) + activesupport (= 8.0.4) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (8.0.3) - activesupport (= 8.0.3) + actionview (8.0.4) + activesupport (= 8.0.4) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (8.0.3) - activesupport (= 8.0.3) + activejob (8.0.4) + activesupport (= 8.0.4) globalid (>= 0.3.6) - activemodel (8.0.3) - activesupport (= 8.0.3) - activerecord (8.0.3) - activemodel (= 8.0.3) - activesupport (= 8.0.3) + activemodel (8.0.4) + activesupport (= 8.0.4) + activerecord (8.0.4) + activemodel (= 8.0.4) + activesupport (= 8.0.4) timeout (>= 0.4.0) - activestorage (8.0.3) - actionpack (= 8.0.3) - activejob (= 8.0.3) - activerecord (= 8.0.3) - activesupport (= 8.0.3) + activestorage (8.0.4) + actionpack (= 8.0.4) + activejob (= 8.0.4) + activerecord (= 8.0.4) + activesupport (= 8.0.4) marcel (~> 1.0) - activesupport (8.0.3) + activesupport (8.0.4) base64 benchmark (>= 0.3) bigdecimal @@ -78,12 +78,14 @@ GEM base64 (0.3.0) bcrypt (3.1.20) bcrypt_pbkdf (1.1.1) - benchmark (0.4.1) - bigdecimal (3.2.3) + bcrypt_pbkdf (1.1.1-arm64-darwin) + bcrypt_pbkdf (1.1.1-x86_64-darwin) + benchmark (0.5.0) + bigdecimal (3.3.1) bindex (0.8.1) bootsnap (1.18.6) msgpack (~> 1.2) - brakeman (7.1.0) + brakeman (7.1.1) racc builder (3.3.0) capybara (3.40.0) @@ -98,7 +100,7 @@ GEM concurrent-ruby (1.3.5) connection_pool (2.5.4) crass (1.0.6) - date (3.4.1) + date (3.5.0) debug (1.11.0) irb (~> 1.10) reline (>= 0.3.8) @@ -111,15 +113,22 @@ GEM dotenv (3.1.8) drb (2.2.3) ed25519 (1.4.0) - erb (5.0.2) + erb (5.1.3) erubi (1.13.1) et-orbi (1.4.0) tzinfo + ffi (1.17.2-aarch64-linux-gnu) + ffi (1.17.2-aarch64-linux-musl) + ffi (1.17.2-arm-linux-gnu) + ffi (1.17.2-arm-linux-musl) + ffi (1.17.2-arm64-darwin) + ffi (1.17.2-x86_64-darwin) ffi (1.17.2-x86_64-linux-gnu) + ffi (1.17.2-x86_64-linux-musl) font-awesome-sass (5.15.1) sassc (>= 1.11) - fugit (1.11.2) - et-orbi (~> 1, >= 1.2.11) + fugit (1.12.1) + et-orbi (~> 1.4) raabro (~> 1.4) globalid (1.3.0) activesupport (>= 6.1) @@ -133,15 +142,15 @@ GEM activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.8.1) - irb (1.15.2) + irb (1.15.3) pp (>= 0.6.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jbuilder (2.14.1) actionview (>= 7.0.0) activesupport (>= 7.0.0) - json (2.15.0) - kamal (2.7.0) + json (2.15.2) + kamal (2.8.2) activesupport (>= 7.0) base64 (~> 0.2) bcrypt_pbkdf (~> 1.0) @@ -158,7 +167,8 @@ GEM loofah (2.24.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) - mail (2.8.1) + mail (2.9.0) + logger mini_mime (>= 0.1.1) net-imap net-pop @@ -168,9 +178,9 @@ GEM mini_magick (5.3.1) logger mini_mime (1.1.5) - minitest (5.25.5) + minitest (5.26.0) msgpack (1.8.0) - net-imap (0.5.10) + net-imap (0.5.12) date net-protocol net-pop (0.1.2) @@ -184,19 +194,33 @@ GEM net-smtp (0.5.1) net-protocol net-ssh (7.3.0) - nio4r (2.7.4) + nio4r (2.7.5) + nokogiri (1.18.10-aarch64-linux-gnu) + racc (~> 1.4) + nokogiri (1.18.10-aarch64-linux-musl) + racc (~> 1.4) + nokogiri (1.18.10-arm-linux-gnu) + racc (~> 1.4) + nokogiri (1.18.10-arm-linux-musl) + racc (~> 1.4) + nokogiri (1.18.10-arm64-darwin) + racc (~> 1.4) + nokogiri (1.18.10-x86_64-darwin) + racc (~> 1.4) nokogiri (1.18.10-x86_64-linux-gnu) racc (~> 1.4) + nokogiri (1.18.10-x86_64-linux-musl) + racc (~> 1.4) orm_adapter (0.5.0) ostruct (0.6.3) parallel (1.27.0) - parser (3.3.9.0) + parser (3.3.10.0) ast (~> 2.4.1) racc - pp (0.6.2) + pp (0.6.3) prettyprint prettyprint (0.2.0) - prism (1.5.1) + prism (1.6.0) propshaft (1.3.1) actionpack (>= 7.0.0) activesupport (>= 7.0.0) @@ -205,11 +229,11 @@ GEM date stringio public_suffix (6.0.2) - puma (7.0.4) + puma (7.1.0) nio4r (~> 2.0) raabro (1.4.0) racc (1.8.1) - rack (3.2.1) + rack (3.2.4) rack-session (2.1.1) base64 (>= 0.1.0) rack (>= 3.0.0) @@ -217,20 +241,20 @@ GEM rack (>= 1.3) rackup (2.2.1) rack (>= 3) - rails (8.0.3) - actioncable (= 8.0.3) - actionmailbox (= 8.0.3) - actionmailer (= 8.0.3) - actionpack (= 8.0.3) - actiontext (= 8.0.3) - actionview (= 8.0.3) - activejob (= 8.0.3) - activemodel (= 8.0.3) - activerecord (= 8.0.3) - activestorage (= 8.0.3) - activesupport (= 8.0.3) + rails (8.0.4) + actioncable (= 8.0.4) + actionmailbox (= 8.0.4) + actionmailer (= 8.0.4) + actionpack (= 8.0.4) + actiontext (= 8.0.4) + actionview (= 8.0.4) + activejob (= 8.0.4) + activemodel (= 8.0.4) + activerecord (= 8.0.4) + activestorage (= 8.0.4) + activesupport (= 8.0.4) bundler (>= 1.15.0) - railties (= 8.0.3) + railties (= 8.0.4) rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest @@ -238,9 +262,9 @@ GEM rails-html-sanitizer (1.6.2) loofah (~> 2.21) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) - railties (8.0.3) - actionpack (= 8.0.3) - activesupport (= 8.0.3) + railties (8.0.4) + actionpack (= 8.0.4) + activesupport (= 8.0.4) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) @@ -248,10 +272,11 @@ GEM tsort (>= 0.2) zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.3.0) - rdoc (6.14.2) + rake (13.3.1) + rdoc (6.15.1) erb psych (>= 4.0.0) + tsort regexp_parser (2.11.3) reline (0.6.2) io-console (~> 0.5) @@ -259,7 +284,7 @@ GEM actionpack (>= 7.0) railties (>= 7.0) rexml (3.4.4) - rubocop (1.81.1) + rubocop (1.81.7) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -273,10 +298,10 @@ GEM rubocop-ast (1.47.1) parser (>= 3.3.7.2) prism (~> 1.4) - rubocop-performance (1.26.0) + rubocop-performance (1.26.1) lint_roller (~> 1.1) rubocop (>= 1.75.0, < 2.0) - rubocop-ast (>= 1.44.0, < 2.0) + rubocop-ast (>= 1.47.1, < 2.0) rubocop-rails (2.33.4) activesupport (>= 4.2.0) lint_roller (~> 1.1) @@ -291,7 +316,7 @@ GEM ruby-vips (2.2.5) ffi (~> 1.12) logger - rubyzip (3.1.1) + rubyzip (3.2.2) sassc (2.4.0) ffi (~> 1.9) sassc-rails (2.1.2) @@ -301,7 +326,7 @@ GEM sprockets-rails tilt securerandom (0.4.1) - selenium-webdriver (4.35.0) + selenium-webdriver (4.38.0) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) @@ -312,15 +337,15 @@ GEM activejob (>= 7.2) activerecord (>= 7.2) railties (>= 7.2) - solid_cache (1.0.7) + solid_cache (1.0.8) activejob (>= 7.2) activerecord (>= 7.2) railties (>= 7.2) - solid_queue (1.2.1) + solid_queue (1.2.4) activejob (>= 7.1) activerecord (>= 7.1) concurrent-ruby (>= 1.3.1) - fugit (~> 1.11.0) + fugit (~> 1.11) railties (>= 7.1) thor (>= 1.3.1) sprockets (4.2.2) @@ -331,7 +356,14 @@ GEM actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - sqlite3 (2.7.4-x86_64-linux-gnu) + sqlite3 (2.8.0-aarch64-linux-gnu) + sqlite3 (2.8.0-aarch64-linux-musl) + sqlite3 (2.8.0-arm-linux-gnu) + sqlite3 (2.8.0-arm-linux-musl) + sqlite3 (2.8.0-arm64-darwin) + sqlite3 (2.8.0-x86_64-darwin) + sqlite3 (2.8.0-x86_64-linux-gnu) + sqlite3 (2.8.0-x86_64-linux-musl) sshkit (1.24.0) base64 logger @@ -343,11 +375,15 @@ GEM railties (>= 6.0.0) stringio (3.1.7) thor (1.4.0) - thruster (0.1.15-x86_64-linux) + thruster (0.1.16) + thruster (0.1.16-aarch64-linux) + thruster (0.1.16-arm64-darwin) + thruster (0.1.16-x86_64-darwin) + thruster (0.1.16-x86_64-linux) tilt (2.6.1) - timeout (0.4.3) + timeout (0.4.4) tsort (0.2.0) - turbo-rails (2.0.17) + turbo-rails (2.0.20) actionpack (>= 7.1.0) railties (>= 7.1.0) tzinfo (2.0.6) @@ -355,7 +391,7 @@ GEM unicode-display_width (3.2.0) unicode-emoji (~> 4.1) unicode-emoji (4.1.0) - uri (1.1.0) + uri (1.1.1) useragent (0.16.11) warden (1.2.9) rack (>= 2.0.9) @@ -374,7 +410,15 @@ GEM zeitwerk (2.7.3) PLATFORMS - x86_64-linux + aarch64-linux + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + x86_64-darwin + x86_64-linux-gnu + x86_64-linux-musl DEPENDENCIES bootsnap @@ -405,4 +449,4 @@ DEPENDENCIES web-console BUNDLED WITH - 2.4.20 + 2.5.7 diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index 3f31662..8024967 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -2,3 +2,6 @@ //= link_directory ../stylesheets .css //= link_tree ../video .mp4 //= link just.mp4 +// Include all JavaScript files from app/javascript so importmap-pinned modules +// (e.g. dropdown.js, flash_messages.js) are available to the asset pipeline. +//= link_tree ../../javascript .js diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/legacy_flash.js similarity index 100% rename from app/assets/javascripts/application.js rename to app/assets/javascripts/legacy_flash.js diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index d23eb91..b0aa92c 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -9,6 +9,8 @@ * Consider organizing styles into separate files for maintainability. */ @import "font-awesome"; +@import "trix/dist/trix.css"; + #flash-message { position: fixed; diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000..4ba4bcc --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,70 @@ +class CategoriesController < ApplicationController + before_action :set_category, only: %i[ show edit update destroy ] + + # GET /categories or /categories.json + def index + @categories = Category.all + end + + # GET /categories/1 or /categories/1.json + def show + end + + # GET /categories/new + def new + @category = Category.new + end + + # GET /categories/1/edit + def edit + end + + # POST /categories or /categories.json + def create + @category = Category.new(category_params) + + respond_to do |format| + if @category.save + format.html { redirect_to @category, notice: "Category was successfully created." } + format.json { render :show, status: :created, location: @category } + else + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @category.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /categories/1 or /categories/1.json + def update + respond_to do |format| + if @category.update(category_params) + format.html { redirect_to @category, notice: "Category was successfully updated.", status: :see_other } + format.json { render :show, status: :ok, location: @category } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @category.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /categories/1 or /categories/1.json + def destroy + @category.destroy! + + respond_to do |format| + format.html { redirect_to categories_path, notice: "Category was successfully destroyed.", status: :see_other } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_category + @category = Category.find(params.expect(:id)) + end + + # Only allow a list of trusted parameters through. + def category_params + params.require(:category).permit(:name, :description, :image) + end +end diff --git a/app/controllers/expenses_controller.rb b/app/controllers/expenses_controller.rb index 97a9aa6..4bed929 100644 --- a/app/controllers/expenses_controller.rb +++ b/app/controllers/expenses_controller.rb @@ -33,19 +33,24 @@ class ExpensesController < ApplicationController # GET /expenses/report def report - set_summary - render :report - @daily_expense_items = Expense.where(date: Date.today.all_day) + # Daily expenses + @daily_expense_items = Expense.where(date: Date.today) + @daily_expense = @daily_expense_items.sum(:amount) + + # Weekly expenses @weekly_expense_items = Expense.where(date: Date.today.beginning_of_week..Date.today.end_of_week) + @weekly_expense = @weekly_expense_items.sum(:amount) + + # Monthly expenses @monthly_expense_items = Expense.where(date: Date.today.beginning_of_month..Date.today.end_of_month) + @monthly_expense = @monthly_expense_items.sum(:amount) - @daily_expenses = @daily_expense_items.sum(:amount) - @weekly_expenses = @weekly_expense_items.sum(:amount) - @monthly_expenses = @monthly_expense_items.sum(:amount) - - # For chart - @chart_labels = @monthly_expense_items.pluck(:date).map { |d| d.strftime("%d %b") } - @chart_data = @monthly_expense_items.pluck(:amount) + # For chart - last 7 days + @chart_labels = (0..6).map { |i| (Date.today - i).strftime("%d %b") }.reverse + @chart_data = @chart_labels.map { |date_str| + date = Date.parse(date_str) + Expense.where(date: date).sum(:amount) + } end # GET /expenses/new diff --git a/app/helpers/categories_helper.rb b/app/helpers/categories_helper.rb new file mode 100644 index 0000000..e06f315 --- /dev/null +++ b/app/helpers/categories_helper.rb @@ -0,0 +1,2 @@ +module CategoriesHelper +end diff --git a/app/javascript/legacy_flash.js b/app/javascript/legacy_flash.js new file mode 100644 index 0000000..54b181c --- /dev/null +++ b/app/javascript/legacy_flash.js @@ -0,0 +1,11 @@ +// migrated from app/assets/javascripts/application.js +document.addEventListener("DOMContentLoaded", () => { + const flash = document.getElementById("flash-message"); + if (flash) { + setTimeout(() => { + flash.style.transition = "opacity 0.5s ease"; + flash.style.opacity = "0"; + setTimeout(() => flash.remove(), 500); + }, 3000); + } +}); diff --git a/app/models/category.rb b/app/models/category.rb new file mode 100644 index 0000000..d58b9f4 --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,4 @@ +class Category < ApplicationRecord + has_rich_text :description + has_one_attached :image +end diff --git a/app/views/categories/_category.html.erb b/app/views/categories/_category.html.erb new file mode 100644 index 0000000..17b84da --- /dev/null +++ b/app/views/categories/_category.html.erb @@ -0,0 +1,17 @@ +
+ Name: + <%= category.name %> +
+ ++ Description: + <%= category.description %> +
+ ++ Image: + <%= link_to category.image.filename, category.image if category.image.attached? %> +
+ +<%= notice %>
+ +<% content_for :title, "Categories" %> + ++ <%= link_to "Show this category", category %> +
+ <% end %> +<%= notice %>
+ +<%= render @category %> + +