Building Mortimer, day 5
"I hate Mondays" is what Garfield has been expressing for 46 years (it has an anniversary in two days from now 😄) or to put it somewhat more civic – I don't like Mondays
Suffice to say the first day of the week (at least since 1988) was never my favorite, but here we are on day 5 of Building Mortimer.
Day 5
I left Mortimer yesterday in a state of transition, from no UI framework moving towards a UI using TailwindCSS. So why not build on new strengths?
as a user I will see a dashboard with stats and a menu and my "punch in/out" button once logged in
I'll start with the button and add a test for it
test "should show punch button when logged in" do
sign_in users(:one)
get root_url
assert_response :success
assert_select "section" # where the stats will go
assert_select "a[href=?]", destroy_user_session_url # part of a menu
assert_select "button"
end
Phlex (& PhlexUI)
Seriously stabbing at the UI had me consider what component framework to go with: ViewComponent or Phlex were the "usual suspects" and I choose Phlex, among other reasons due to the speed with which Phlex renders! To complement it all I reached for the stars going with PhlexUI 🫃
bundle add phlex-rails
rails generate phlex:install
bundle add phlex_ui
I continued following the installation guide for Rails and then in the end I jumped ship and finalized it all with using the PhlexUI Rails with importmap installation guide. I must have timed my "full immersion" really bad 'cause I was not able to produce any output from the PhlexUI components - sadly! So, I reversed the entire thing (with git holding my hand that's as easy as tapping the 'discard changes' left circling arrow in the source control tab in Visual Studio Code) and then did it again but for the Phlex only.
Phlex has been a part of my toolbelt for quite some time and even though Joel Drapper and his League of Extraordinary Do-Good'ers seriously remodeled the little finca, I feverishly tagged along best I could.
So for this first use case I needed some stats and a menu and a punch button - so my first 3 components were exactly that.
First add a few helpers:
module PhlexUiHelper
def punch_button
render PunchButtonComponent.new
end
def menu
render MenuComponent.new
end
def stats_section
render StatsComponent.new
end
end
Then on to the components definition:
# frozen_string_literal: true
class MenuComponent < ApplicationComponent
include Phlex::Rails::Helpers::LinkTo
def initialize
end
def view_template
div do
h1 { "Menu" }
ul do
li { link_to("Home", "/") }
li { link_to("Sign out", destroy_user_session_url, data: { turbo_method: :delete }) }
end
end
end
end
With that out of the way I hurried to the next use case
as a user I will be able to see whether I'm 'punched in' or 'out' – and by merely tapping the punch button punch the right thing
That required me to
rails g migration add_state_to_user state:integer
and as for persisting the punches, now I could
# controllers/punches_controller.rb
...
# POST /punches or /punches.json
def create
@punch = Punch.new
@punch.user = current_user
@punch.state = current_user.in? ? "out" : "in"
@punch.punched_at = DateTime.now.utc
@punch.comment = punch_params[:comment] if params_good?
respond_to do |format|
if @punch.save
current_user.update state: @punch.state
format.html { redirect_to nexturl, allow_other_host: true, notice: "Punch was successfully created." }
format.json { render :show, status: :created, location: @punch }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @punch.errors, status: :unprocessable_entity }
end
end
end
I'm feeling a bit under the weather - will call it a day, and tag it as 0.4.0_menu