Skip to content

Commit f539c04

Browse files
authored
Merge pull request #2 from tgaeta/fix-overlooked-issues
Fix Overlooked Issues
2 parents 9cf1d11 + 3b7c97f commit f539c04

18 files changed

+290
-175
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ gem "phlex-rails", "~> 1.2"
1616
gem "devise", "~> 4.9"
1717
gem "will_paginate", "~> 4.0"
1818
gem "validate_url", "~> 1.0"
19+
gem "rexml", ">= 3.3.2"
1920

2021
group :development, :test do
2122
gem "debug", "~> 1.9", ">= 1.9.2", platforms: %i[mri windows]

Gemfile.lock

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ GEM
261261
responders (3.1.1)
262262
actionpack (>= 5.2)
263263
railties (>= 5.2)
264-
rexml (3.2.8)
265-
strscan (>= 3.0.9)
264+
rexml (3.3.2)
265+
strscan
266266
rubocop (1.64.0)
267267
json (~> 2.3)
268268
language_server-protocol (>= 3.17.0)
@@ -366,6 +366,7 @@ DEPENDENCIES
366366
phlex-rails (~> 1.2)
367367
puma (~> 6.4, >= 6.4.2)
368368
rails (~> 7.1, >= 7.1.3.4)
369+
rexml (>= 3.3.2)
369370
rubocop (~> 1.63, >= 1.63.5)
370371
rubocop-factory_bot (~> 2.25, >= 2.25.1)
371372
rubocop-minitest (~> 0.35.0)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
Job Tracker is a simple, powerful, and user-friendly web application designed to help job seekers efficiently manage their job search process. Built with Ruby on Rails and enhanced with modern web technologies, this tool streamlines the often overwhelming task of tracking multiple job applications.
2222

23-
<img alt="UI Screenshot" src="https://github.com/user-attachments/assets/1b4ec900-a670-4220-bf01-1df1cfba5914"/>
23+
<img alt="UI Screenshot" src="https://github.com/user-attachments/assets/ab65ca79-4530-4730-b6b3-d839cfdf6398"/>
2424

2525
## Key Features
2626

app/controllers/job_applications_controller.rb

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
class JobApplicationsController < ApplicationController
2-
before_action :set_job_application, only: [:create, :update, :destroy]
2+
include ActionView::RecordIdentifier
3+
before_action :set_job_application, only: [:edit, :update, :destroy]
34

45
def index
56
@job_applications = filter_and_sort_job_applications
@@ -22,53 +23,61 @@ def index
2223

2324
def new
2425
@job_application = JobApplication.new
26+
respond_to do |format|
27+
format.html
28+
format.turbo_stream { render turbo_stream: turbo_stream.replace("new_job_application", partial: "form", locals: {job_application: @job_application, title: "New"}) }
29+
end
30+
end
31+
32+
def edit
33+
respond_to do |format|
34+
format.html
35+
format.turbo_stream { render turbo_stream: turbo_stream.replace(dom_id(@job_application), partial: "form", locals: {job_application: @job_application, title: "Edit"}) }
36+
end
2537
end
2638

2739
def create
2840
@job_application = JobApplication.new(job_application_params)
2941

3042
respond_to do |format|
3143
if @job_application.save
32-
format.html { redirect_to job_applications_path, notice: "Job application was successfully created." }
33-
format.turbo_stream {
34-
flash.now[:notice] = "Job application was successfully created."
35-
render turbo_stream: [
36-
turbo_stream.prepend("job_applications", partial: "job_application", locals: {job_application: @job_application}),
37-
turbo_stream.update("flash_messages", partial: "flash_messages"),
38-
turbo_stream.replace("new_job_application", partial: "form", locals: {job_application: JobApplication.new})
39-
]
40-
}
44+
format.html { redirect_to root_path, success: "Job application was successfully created." }
45+
format.turbo_stream do
46+
render turbo_stream: turbo_stream.redirect_advanced(root_path)
47+
flash[:success] = "Job application was successfully created."
48+
end
4149
else
4250
format.html { render :new, status: :unprocessable_entity }
43-
format.turbo_stream { render turbo_stream: turbo_stream.replace(@job_application, partial: "form", locals: {job_application: @job_application}) }
51+
format.turbo_stream do
52+
render turbo_stream: [
53+
turbo_stream.replace("new_job_application", partial: "form", locals: {job_application: @job_application, title: "New"}),
54+
turbo_stream.update("flash_messages", partial: "flash_messages")
55+
]
56+
end
4457
end
4558
end
4659
end
4760

4861
def update
4962
respond_to do |format|
5063
if @job_application.update(job_application_params)
51-
format.html { redirect_to job_applications_path, notice: "Job application was successfully updated." }
52-
format.turbo_stream {
53-
flash.now[:notice] = "Job application was successfully updated."
54-
render turbo_stream: [
55-
turbo_stream.replace(@job_application, partial: "job_application", locals: {job_application: @job_application}),
56-
turbo_stream.update("flash_messages", partial: "flash_messages")
57-
]
58-
}
64+
format.html { redirect_to root_path, success: "Job application was successfully updated." }
65+
format.turbo_stream do
66+
render turbo_stream: turbo_stream.redirect_advanced(root_path)
67+
flash[:success] = "Job application was successfully updated."
68+
end
5969
else
6070
format.html { render :edit, status: :unprocessable_entity }
61-
format.turbo_stream { render turbo_stream: turbo_stream.replace(@job_application, partial: "form", locals: {job_application: @job_application}) }
6271
end
6372
end
6473
end
6574

6675
def destroy
6776
@job_application.destroy
6877
respond_to do |format|
69-
format.html { redirect_to job_applications_url, notice: "Job application was successfully deleted." }
78+
format.html { redirect_to root_path, success: "Job application was successfully deleted." }
7079
format.turbo_stream {
71-
flash.now[:notice] = "Job application was successfully deleted."
80+
flash.now[:success] = "Job application was successfully deleted."
7281
render turbo_stream: [
7382
turbo_stream.remove(@job_application),
7483
turbo_stream.update("job_application_count", JobApplication.count),
@@ -82,6 +91,8 @@ def destroy
8291

8392
def set_job_application
8493
@job_application = JobApplication.find(params[:id])
94+
rescue ActiveRecord::RecordNotFound
95+
redirect_to root_path, alert: "Job application not found."
8596
end
8697

8798
def job_application_params
@@ -97,11 +108,18 @@ def filter_and_sort_job_applications
97108

98109
sort_column = sort_column(params[:sort])
99110
sort_direction = sort_direction(params[:direction])
100-
job_applications.order(sort_column => sort_direction)
111+
112+
if sort_column == "created_at" || params[:sort].blank?
113+
# If sorting by created_at or no sorting specified, always use desc order
114+
job_applications.order(created_at: :desc)
115+
else
116+
# For other columns, use the specified sort direction
117+
job_applications.order(sort_column => sort_direction)
118+
end
101119
end
102120

103121
def sort_column(column)
104-
%w[date_applied company_name position_title].include?(column) ? column : "date_applied"
122+
%w[date_applied company_name position_title created_at].include?(column) ? column : "created_at"
105123
end
106124

107125
def sort_direction(direction)

app/frontend/controllers/flash_message_controller.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,17 @@ export default class extends Controller {
1010
show() {
1111
this.element.classList.remove('hidden');
1212
setTimeout(() => {
13-
this.element.classList.add('hidden');
14-
}, 5000);
13+
this.fadeOut();
14+
}, 2000);
15+
}
16+
17+
fadeOut() {
18+
const flashMessage = this.element.querySelector('.flash-message');
19+
if (flashMessage) {
20+
flashMessage.classList.add('fade-out');
21+
setTimeout(() => {
22+
this.element.classList.add('hidden');
23+
}, 500);
24+
}
1525
}
1626
}

app/frontend/entrypoints/application.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import "~/controllers";
2-
import "@hotwired/turbo-rails";
2+
import { Turbo } from "@hotwired/turbo-rails"
33
// To see this message, add the following to the `<head>` section in your
44
// views/layouts/application.html.erb
55
//
@@ -20,7 +20,7 @@ console.log('Visit the guide for more information: ', 'https://vite-ruby.netlify
2020

2121
Turbo.start();
2222

23-
document.addEventListener("turbo:load", function () {
23+
document.addEventListener("turbo:load", () => {
2424
console.log("turbo:load");
2525
});
2626
//
@@ -32,3 +32,9 @@ document.addEventListener("turbo:load", function () {
3232

3333
// Example: Import a stylesheet in app/frontend/index.css
3434
// import '~/index.css'
35+
36+
Turbo.StreamActions.redirect_advanced = function () {
37+
const url = this.getAttribute('url') || '/'
38+
// Turbo.visit(url, { frame: '_top', action: 'advance' })
39+
Turbo.visit(url)
40+
}

app/frontend/stylesheets/index.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,11 @@ body {
2424
background-position: center;
2525
background-attachment: fixed;
2626
}
27+
28+
td {
29+
font-size: 12px !important;
30+
}
31+
32+
th {
33+
font-size: 12px !important;
34+
}

app/helpers/application_helper.rb

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,34 @@
11
module ApplicationHelper
22
def flash_class(type)
3+
base_class = "border-l-4 p-4 mb-4 rounded-md"
34
case type.to_sym
4-
when :notice then "bg-blue-100 border-blue-500 text-blue-700"
5-
when :success then "bg-green-100 border-green-500 text-green-700"
6-
when :error then "bg-red-100 border-red-500 text-red-700"
7-
when :alert then "bg-yellow-100 border-yellow-500 text-yellow-700"
8-
else "bg-gray-100 border-gray-500 text-gray-700"
9-
end + " border-l-4 p-4 mb-4"
5+
when :notice
6+
"bg-blue-100 border-blue-500 text-blue-700 #{base_class}"
7+
when :success
8+
"bg-green-100 border-green-500 text-green-700 #{base_class}"
9+
when :error
10+
"bg-red-100 border-red-500 text-red-700 #{base_class}"
11+
when :alert
12+
"bg-yellow-100 border-yellow-500 text-yellow-700 #{base_class}"
13+
else
14+
"bg-gray-100 border-gray-500 text-gray-700 #{base_class}"
15+
end
16+
end
17+
18+
def progress_bar_class(type)
19+
base_class = "rounded-md"
20+
case type.to_sym
21+
when :notice
22+
"bg-blue-500 #{base_class}"
23+
when :success
24+
"bg-green-500 #{base_class}"
25+
when :error
26+
"bg-red-500 #{base_class}"
27+
when :alert
28+
"bg-yellow-500 #{base_class}"
29+
else
30+
"bg-gray-500 #{base_class}"
31+
end
1032
end
1133

1234
def sort_link_to(name, column)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module TurboStreamActionsHelper
2+
# render turbo_stream: turbo_stream.redirect_advanced(projects_path)
3+
def redirect_advanced(url)
4+
turbo_stream_action_tag :redirect_advanced, url: url
5+
end
6+
end
7+
8+
Turbo::Streams::TagBuilder.prepend(TurboStreamActionsHelper)

app/views/application/_flash_messages.html.erb

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,36 @@
1-
<div data-controller="flash-message" class="hidden">
1+
<style>
2+
@keyframes flash-progress {
3+
from {
4+
width: 100%;
5+
left: 0;
6+
}
7+
to {
8+
width: 0;
9+
left: 0;
10+
}
11+
}
12+
13+
@keyframes fade-out {
14+
from {
15+
opacity: 1;
16+
}
17+
to {
18+
opacity: 0;
19+
}
20+
}
21+
22+
.flash-progress-bar {
23+
animation: flash-progress 2s linear forwards;
24+
}
25+
26+
.flash-message.fade-out {
27+
animation: fade-out 0.5s forwards;
28+
}
29+
</style>
30+
<div data-controller="flash-message" class="hidden relative">
231
<% flash.each do |type, message| %>
3-
<div class="<%= flash_class(type) %>" role="alert">
32+
<div class="<%= flash_class(type) %> flash-message relative" role="alert">
33+
<div class="flash-progress-bar absolute top-0 left-0 h-1 w-full <%= progress_bar_class(type) %>"></div>
434
<%= message %>
535
</div>
636
<% end %>

0 commit comments

Comments
 (0)