Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rails budget app #2

Merged
merged 22 commits into from
Aug 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@
!/app/assets/builds/.keep

/node_modules

# Ignore application configuration
/config/application.yml
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ gem 'cssbundling-rails', '~> 1.1'

# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"
gem 'aws-sdk-s3', require: false

# Store encrypted credentials
gem 'figaro'

group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
Expand Down Expand Up @@ -82,3 +86,5 @@ group :test do
gem 'selenium-webdriver'
gem 'webdrivers'
end

gem 'pry-rails', group: :development
28 changes: 28 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ GEM
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
ast (2.4.2)
aws-eventstream (1.2.0)
aws-partitions (1.616.0)
aws-sdk-core (3.132.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.58.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.114.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.1)
aws-eventstream (~> 1, >= 1.0.2)
bcrypt (3.1.18)
bindex (0.8.1)
bootsnap (1.13.0)
Expand All @@ -84,6 +100,7 @@ GEM
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
childprocess (4.1.0)
coderay (1.1.3)
concurrent-ruby (1.1.10)
crass (1.0.6)
cssbundling-rails (1.1.1)
Expand All @@ -110,6 +127,8 @@ GEM
factory_bot (~> 6.2.0)
railties (>= 5.0.0)
ffi (1.15.5-x64-mingw-ucrt)
figaro (1.2.0)
thor (>= 0.14.0, < 2)
globalid (1.0.0)
activesupport (>= 5.0)
i18n (1.12.0)
Expand All @@ -123,6 +142,7 @@ GEM
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jmespath (1.6.1)
json (2.6.2)
loofah (2.18.0)
crass (~> 1.0.2)
Expand Down Expand Up @@ -157,6 +177,11 @@ GEM
parser (3.1.2.0)
ast (~> 2.4.1)
pg (1.4.2-x64-mingw-ucrt)
pry (0.14.1)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (4.0.7)
puma (5.6.4)
nio4r (~> 2.0)
Expand Down Expand Up @@ -283,6 +308,7 @@ PLATFORMS
x64-mingw-ucrt

DEPENDENCIES
aws-sdk-s3
bootsnap
capybara
cssbundling-rails (~> 1.1)
Expand All @@ -291,9 +317,11 @@ DEPENDENCIES
devise
factory_bot_rails
ffi (~> 1.15, >= 1.15.5)
figaro
importmap-rails
jbuilder
pg (~> 1.1)
pry-rails
puma (~> 5.0)
rails (~> 7.0.3, >= 7.0.3.1)
rails-controller-testing
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

A web application where you can manage your budget: you have a list of transactions associated with a category, so that you can see how much money you spent and on what.

![image](https://user-images.githubusercontent.com/55185309/184540699-4353c054-c3e5-49e9-9b55-ece9ea3f6721.png)



### Live demo: [Budgit](https://my-budgit-app.herokuapp.com/)

## Built With

Expand Down
2 changes: 2 additions & 0 deletions app/assets/javascript/activestorage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//= require activestorage

40 changes: 40 additions & 0 deletions app/assets/javascript/direct_uploads.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

// direct_uploads.js

addEventListener("direct-upload:initialize", event => {
const { target, detail } = event
const { id, file } = detail
target.insertAdjacentHTML("beforebegin", `
<div id="direct-upload-${id}" class="direct-upload direct-upload--pending">
<div id="direct-upload-progress-${id}" class="direct-upload__progress" style="width: 0%"></div>
<span class="direct-upload__filename"></span>
</div>
`)
target.previousElementSibling.querySelector(`.direct-upload__filename`).textContent = file.name
})

addEventListener("direct-upload:start", event => {
const { id } = event.detail
const element = document.getElementById(`direct-upload-${id}`)
element.classList.remove("direct-upload--pending")
})

addEventListener("direct-upload:progress", event => {
const { id, progress } = event.detail
const progressElement = document.getElementById(`direct-upload-progress-${id}`)
progressElement.style.width = `${progress}%`
})

addEventListener("direct-upload:error", event => {
event.preventDefault()
const { id, error } = event.detail
const element = document.getElementById(`direct-upload-${id}`)
element.classList.add("direct-upload--error")
element.setAttribute("title", error)
})

addEventListener("direct-upload:end", event => {
const { id } = event.detail
const element = document.getElementById(`direct-upload-${id}`)
element.classList.add("direct-upload--complete")
})
40 changes: 40 additions & 0 deletions app/assets/stylesheets/application.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,43 @@
*= require_tree .
*= require_self
*/

/* direct_uploads.css */

.direct-upload {
display: inline-block;
position: relative;
padding: 2px 4px;
margin: 0 3px 3px 0;
border: 1px solid rgba(0, 0, 0, 0.3);
border-radius: 3px;
font-size: 11px;
line-height: 13px;
}

.direct-upload--pending {
opacity: 0.6;
}

.direct-upload__progress {
position: absolute;
top: 0;
left: 0;
bottom: 0;
opacity: 0.2;
background: #0076ff;
transition: width 120ms ease-out, opacity 60ms 60ms ease-in;
transform: translate3d(0, 0, 0);
}

.direct-upload--complete .direct-upload__progress {
opacity: 0.4;
}

.direct-upload--error {
border-color: red;
}

input[type=file][data-direct-upload-url][disabled] {
display: none;
}
5 changes: 4 additions & 1 deletion app/assets/stylesheets/application.tailwind.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/* stylelint-disable */

@tailwind base;
@tailwind components;
@tailwind utilities;
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@300;700&display=swap');

@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@300;700&display=swap');
9 changes: 9 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :authenticate_user!

protected

def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:name, :email, :password, :password_confirmation) }
end
end
27 changes: 7 additions & 20 deletions app/controllers/categories_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,39 @@ class CategoriesController < ApplicationController

# GET /categories or /categories.json
def index
@categories = Category.all
@categories = Category.includes(:user).where(user: current_user)
end

# GET /categories/1 or /categories/1.json
def show; end
def show
@payments = @category.sorted_payments(current_user)
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)
@category.user = current_user

respond_to do |format|
if @category.save
format.html { redirect_to category_url(@category), notice: 'Category was successfully created.' }
format.html { redirect_to categories_path, notice: 'Category was successfully created.' }
else
format.html { render :new, 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_url(@category), notice: 'Category was successfully updated.' }
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_url, notice: 'Category was successfully deleted.' }
format.html { redirect_to categories_path, notice: 'Category was successfully deleted.' }
end
end

Expand Down
19 changes: 4 additions & 15 deletions app/controllers/payments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def show; end
# GET /payments/new
def new
@payment = Payment.new
@categories = Category.includes(:user).where(user: current_user)
end

# GET /payments/1/edit
Expand All @@ -20,25 +21,13 @@ def edit; end
# POST /payments or /payments.json
def create
@payment = Payment.new(payment_params)
@payment.user = current_user

respond_to do |format|
if @payment.save
format.html { redirect_to payment_url(@payment), notice: 'Payment was successfully created.' }
format.json { render :show, status: :created, location: @payment }
format.html { redirect_to category_path(@payment.category), notice: 'Payment was successfully created.' }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @payment.errors, status: :unprocessable_entity }
end
end
end

# PATCH/PUT /payments/1 or /payments/1.json
def update
respond_to do |format|
if @payment.update(payment_params)
format.html { redirect_to payment_url(@payment), notice: 'Payment was successfully updated.' }
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
Expand All @@ -62,6 +51,6 @@ def set_payment

# Only allow a list of trusted parameters through.
def payment_params
params.require(:payment).permit(:name, :amount)
params.require(:payment).permit(:name, :amount, :category_id)
end
end
4 changes: 1 addition & 3 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@ def create

respond_to do |format|
if @user.save
format.html { redirect_to user_url(@user), notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: @user }
format.html { redirect_to categories_path, notice: 'Account successfully created.' }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
Expand Down
1 change: 1 addition & 0 deletions app/controllers/welcome_controller.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
class WelcomeController < ApplicationController
skip_before_action :authenticate_user!
def index; end
end
13 changes: 13 additions & 0 deletions app/models/category.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
class Category < ApplicationRecord
has_one_attached :icon
has_many :payments, dependent: :destroy
belongs_to :user
validates :name, presence: true
validates :icon, presence: true
validates :user_id, presence: true

def total_amount(user)
payments.includes(:user).where(user:).sum(:amount)
end

def sorted_payments(user)
payments.includes(:user).where(user:).order(created_at: :desc)
end
end
10 changes: 10 additions & 0 deletions app/models/payment.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
class Payment < ApplicationRecord
belongs_to :user
belongs_to :category
validates :amount, presence: true
validates :amount, numericality: { greater_than: 0 }
validates :category_id, presence: true
validates :name, presence: true

def payment_date
created_at.strftime('%d %b %Y')
end
end
9 changes: 5 additions & 4 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :categories, dependent: :destroy
has_many :payments, dependent: :destroy
validates :name, presence: true, length: { minimum: 3, maximum: 25 }

devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable
end
Loading