Skip to content
Draft
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
56 changes: 56 additions & 0 deletions spec/commands/clock_in/manual_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require "../../spec_helper"

describe TandaCLI::Commands::ClockIn::Manual do
it "Handles clocked out state asking for a time to clock in with" do
stub_shifts

travel_to(Time.local(2024, 12, 28, 9))

stdin = build_stdin(
"9:00am",
"y"
)
context = run(stdin)

output = context.stdout.to_s
output.should contain("You are currently clocked out, what do you want to set as the clock in time?\n")
output.should contain("Is this correct?\n")
output.should contain("Success: Set clock in time to 2024-12-28 09:00:00 +00:00\n")
end

it "Handles blank time input" do
stub_shifts

stdin = build_stdin(" ")
context = run(stdin)

output = context.stdout.to_s
output.should contain("You are currently clocked out, what do you want to set as the clock in time?\n")
output.should contain("Error: Input can't be blank!")
end

it "Handles invalid time input" do
stub_shifts

time_string = "invalid time"
stdin = build_stdin(time_string)
context = run(stdin)

output = context.stdout.to_s
output.should contain("You are currently clocked out, what do you want to set as the clock in time?\n")
output.should contain("Error: \"#{time_string}\" is not a valid time!\n")
end
end

private def run(stdin)
Command.run(["clockin", "manual"], stdin: stdin)
end

private def stub_shifts(shifts = Array(NamedTuple()).new)
WebMock
.stub(:get, endpoint(Regex.new("/shifts")))
.to_return(
status: 200,
body: shifts.to_json,
)
end
10 changes: 10 additions & 0 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,13 @@ end
def endpoint(regex : Regex)
Regex.new("#{DEFAULT_BASE_URI}#{regex}")
end

def build_stdin(*lines : String) : IO
IO::Memory.new.tap do |stdin|
lines.each do |line|
stdin.puts line
end

stdin.rewind
end
end
1 change: 1 addition & 0 deletions src/tanda_cli/commands/clock_in.cr
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module TandaCLI
add_commands(
ClockIn::Start,
ClockIn::Finish,
ClockIn::Manual,
ClockIn::Break,
ClockIn::Photo,
ClockIn::Status,
Expand Down
66 changes: 66 additions & 0 deletions src/tanda_cli/commands/clock_in/manual.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require "../../models/clock_in_status"

module TandaCLI
module Commands
class ClockIn
class Manual < Commands::Base
required_scopes :timesheet

def setup_
@name = "manual"
@summary = @description = "Manually set shift time for clockin"
end

def run_(arguments : Cling::Arguments, options : Cling::Options) : Nil
shifts = client.shifts(current.user.id, Utils::Time.now).or { |error| display.error!(error) }
status = Models::ClockInStatus.new(shifts).determine_status

case status
in .clocked_out?
handle_clocked_out!
in .clocked_in?
puts "Clocked in"
in .break_started?
puts "Break started"
end
end

private def handle_clocked_out!
message = "You are currently clocked out, what do you want to set as the clock in time?"
time = ask_for_and_parse_time!(message)

# TODO: Actually create shift and set time
display.success("Set clock in time to #{time}")
end

private def ask_for_and_parse_time!(message) : Time
time_string = input.request(message)
display.error!("Input can't be blank!") if time_string.nil?

time = Utils::Time.parse?(time_string).try(&->time_to_day_time(Time))
display.error!("\"#{time_string}\" is not a valid time!") if time.nil?

input.request_and(message: "Is this correct?") do |user_input|
display.error!("Command aborted. Please try again.") if user_input != "y"
end

time
end

private def time_to_day_time(time : Time) : Time
now = Utils::Time.now

Time.local(
now.year,
now.month,
now.day,
time.hour,
time.minute,
time.second,
location: now.location
)
end
end
end
end
end
19 changes: 3 additions & 16 deletions src/tanda_cli/executors/clock_in.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require "../models/clock_in_status"
require "../models/photo_path_parser"

module TandaCLI
Expand Down Expand Up @@ -106,22 +107,8 @@ module TandaCLI
BreakStarted
end

private def determine_status : ClockInStatus
if break_started?
ClockInStatus::BreakStarted
elsif clocked_in?
ClockInStatus::ClockedIn
else
ClockInStatus::ClockedOut
end
end

private def break_started? : Bool
@shifts.any?(&.ongoing_break?)
end

private def clocked_in? : Bool
@shifts.any? { |shift| shift.start_time && shift.finish_time.nil? }
private def determine_status : Models::ClockInStatus::Status
Models::ClockInStatus.new(@shifts).determine_status
end

private def validate_clockin_start!
Expand Down
7 changes: 5 additions & 2 deletions src/tanda_cli/input.cr
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module TandaCLI
end

retrieve_input(sensitive) do
gets.try(&.chomp).presence
@stdin.gets(chomp: true).presence
end
end

Expand All @@ -36,7 +36,10 @@ module TandaCLI
private def retrieve_input(sensitive : Bool, & : -> String?) : String?
return yield unless sensitive

STDIN.noecho do
stdin = @stdin
return yield unless stdin.is_a?(IO::FileDescriptor)

stdin.noecho do
yield
end
end
Expand Down
31 changes: 31 additions & 0 deletions src/tanda_cli/models/clock_in_status.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module TandaCLI
module Models
struct ClockInStatus
enum Status
ClockedIn
ClockedOut
BreakStarted
end

def initialize(@shifts : Array(Types::Shift)); end

def determine_status : Status
if break_started?
Status::BreakStarted
elsif clocked_in?
Status::ClockedIn
else
Status::ClockedOut
end
end

private def break_started? : Bool
@shifts.any?(&.ongoing_break?)
end

private def clocked_in? : Bool
@shifts.any? { |shift| shift.start_time && shift.finish_time.nil? }
end
end
end
end
15 changes: 15 additions & 0 deletions src/tanda_cli/utils/time.cr
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ module TandaCLI
def location : ::Time::Location
::Time::Location.local
end

def parse?(time_string : String) : ::Time?
formats = {
"%l%P", # "9am", "12pm"
"%l:%M%P", # "1:30pm"
}

formats
.each
.map do |format|
::Time.parse(time_string, format, location)
rescue ::Time::Format::Error
end
.find(&.itself)
end
end
end
end