More consistent api
This commit is contained in:
parent
af95c67110
commit
fbb11fbcd8
@ -1,14 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<section class="timer" v-bind:class="{ overtime: isOvertime }">
|
<section
|
||||||
{{ time }}
|
v-if="total_time"
|
||||||
|
class="timer"
|
||||||
|
v-bind:class="{ overtime: isOvertime }"
|
||||||
|
>
|
||||||
|
{{ total_time | str_time }}
|
||||||
</section>
|
</section>
|
||||||
<section class="actions">
|
<section class="actions">
|
||||||
<a v-if="started" v-on:click.prevent="finish" href="#">Закончить</a>
|
<a v-if="started" v-on:click.prevent="finish" href="#">Закончить</a>
|
||||||
<a v-else v-on:click.prevent="start" href="#">Начать</a>
|
<a v-else v-on:click.prevent="start" href="#">Начать</a>
|
||||||
</section>
|
</section>
|
||||||
<section class="today">
|
<section v-if="today_time" class="today">
|
||||||
Сегодня {{ today_time }}
|
Сегодня {{ today_time | str_time }}
|
||||||
</section>
|
</section>
|
||||||
<p class="profile-info">Профиль: {{ profileId }}</p>
|
<p class="profile-info">Профиль: {{ profileId }}</p>
|
||||||
</div>
|
</div>
|
||||||
@ -21,10 +25,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
profileId: null,
|
profileId: null,
|
||||||
started: false,
|
started: false,
|
||||||
status: '',
|
total_time: null,
|
||||||
hours: 0,
|
today_time: null,
|
||||||
minutes: 0,
|
|
||||||
today: null,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -33,26 +35,16 @@ export default {
|
|||||||
setInterval(() => this.get_status(), 60 * 1000);
|
setInterval(() => this.get_status(), 60 * 1000);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
time() {
|
|
||||||
const sign = this.isOvertime ? '+' : '';
|
|
||||||
return sign + this.hours + ':' + String(this.minutes).padStart(2, '0');
|
|
||||||
},
|
|
||||||
isOvertime() {
|
isOvertime() {
|
||||||
return this.status === 'overtime';
|
return this.total_time && this.total_time.status === 'overtime';
|
||||||
},
|
},
|
||||||
today_time() {
|
|
||||||
const sign = this.today.status === 'overtime' ? '+' : '';
|
|
||||||
return sign + this.today.hours + ':' + String(this.today.minutes).padStart(2, '0');
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
get_status() {
|
get_status() {
|
||||||
h.get_status(this.profileId).then(data => {
|
h.get_status(this.profileId).then(data => {
|
||||||
this.started = data.started;
|
this.started = data.started;
|
||||||
this.status = data.total.status;
|
this.total_time = data.total.time;
|
||||||
this.hours = data.total.hours;
|
this.today_time = data.today.time;
|
||||||
this.minutes = data.total.minutes;
|
|
||||||
this.today = data.today;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
start() {
|
start() {
|
||||||
@ -62,6 +54,12 @@ export default {
|
|||||||
h.finish(this.profileId).then(() => this.get_status());
|
h.finish(this.profileId).then(() => this.get_status());
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
filters: {
|
||||||
|
str_time(time) {
|
||||||
|
const sign = time.status === 'overtime' ? '+' : '';
|
||||||
|
return sign + time.hours + ':' + String(time.minutes).padStart(2, '0');
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ module Dayoff::Test
|
|||||||
|
|
||||||
it "can calc remaining time" do
|
it "can calc remaining time" do
|
||||||
prof = create_profile
|
prof = create_profile
|
||||||
span = prof.remaining_time t(3, 12)
|
span = prof.total_status t(3, 12)
|
||||||
expected = 8 * 3 - 10 * 2
|
expected = 8 * 3 - 10 * 2
|
||||||
expected.should eq span.total_hours
|
expected.should eq span.total_hours
|
||||||
end
|
end
|
||||||
|
@ -17,10 +17,8 @@ def now
|
|||||||
Time.local(Time::Location.load("Europe/Moscow"))
|
Time.local(Time::Location.load("Europe/Moscow"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def date_status(profile, date)
|
def serialize_span(span : Time::Span)
|
||||||
span = profile.date_status date
|
|
||||||
{
|
{
|
||||||
date: date.to_s("%Y-%m-%d"),
|
|
||||||
status: span < Time::Span.zero ? STATUS_OVERTIME : STATUS_UPTIME,
|
status: span < Time::Span.zero ? STATUS_OVERTIME : STATUS_UPTIME,
|
||||||
hours: span.abs.total_hours.to_i32,
|
hours: span.abs.total_hours.to_i32,
|
||||||
minutes: span.abs.minutes.to_i32,
|
minutes: span.abs.minutes.to_i32,
|
||||||
@ -41,15 +39,17 @@ end
|
|||||||
|
|
||||||
get "/api/status" do |env|
|
get "/api/status" do |env|
|
||||||
profile = app.profile Dayoff::ProfileId.new(env.get("profile_id").to_s)
|
profile = app.profile Dayoff::ProfileId.new(env.get("profile_id").to_s)
|
||||||
rem_span = profile.remaining_time now
|
total_span = profile.total_status now
|
||||||
|
today_span = profile.date_status now
|
||||||
data = {
|
data = {
|
||||||
started: profile.started?,
|
started: profile.started?,
|
||||||
total: {
|
total: {
|
||||||
status: rem_span < Time::Span.zero ? STATUS_OVERTIME : STATUS_UPTIME,
|
time: serialize_span total_span,
|
||||||
hours: rem_span.abs.total_hours.to_i32,
|
},
|
||||||
minutes: rem_span.abs.minutes.to_i32,
|
today: {
|
||||||
|
date: now.to_s("%Y-%m-%d"),
|
||||||
|
time: serialize_span today_span,
|
||||||
},
|
},
|
||||||
today: date_status(profile, now),
|
|
||||||
}
|
}
|
||||||
env.response.content_type = "application/json"
|
env.response.content_type = "application/json"
|
||||||
data.to_json
|
data.to_json
|
||||||
|
@ -70,7 +70,8 @@ module Dayoff
|
|||||||
end
|
end
|
||||||
|
|
||||||
private def in_range_finished(from_time : Time, to_time : Time) : Time::Span
|
private def in_range_finished(from_time : Time, to_time : Time) : Time::Span
|
||||||
if @start <= to_time && finish! >= from_time
|
crossed = Helpers.crossed? @start, finish!, from_time, to_time
|
||||||
|
if crossed
|
||||||
normalized_start = Math.max(@start, from_time)
|
normalized_start = Math.max(@start, from_time)
|
||||||
normalized_finish = Math.min(finish!, to_time)
|
normalized_finish = Math.min(finish!, to_time)
|
||||||
normalized_finish - normalized_start
|
normalized_finish - normalized_start
|
||||||
|
12
src/dayoff/helpers.cr
Normal file
12
src/dayoff/helpers.cr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
module Dayoff::Helpers
|
||||||
|
extend self
|
||||||
|
|
||||||
|
def zero_time : Time
|
||||||
|
location = Time::Location.load("Europe/Moscow")
|
||||||
|
Time.local(1, 1, 1, 0, 0, location: location)
|
||||||
|
end
|
||||||
|
|
||||||
|
def crossed?(s1 : Time, f1 : Time, s2 : Time, f2 : Time) : Bool
|
||||||
|
s1 <= f2 && f1 >= s2
|
||||||
|
end
|
||||||
|
end
|
@ -64,20 +64,15 @@ module Dayoff
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def zero_time : Time
|
def total_status(on_time : Time) : Time::Span
|
||||||
location = Time::Location.load("Europe/Moscow")
|
planned = get_planned Helpers.zero_time, on_time
|
||||||
Time.local(1, 1, 1, 0, 0, location: location)
|
worked = get_worked Helpers.zero_time, on_time
|
||||||
end
|
|
||||||
|
|
||||||
def remaining_time(on_time : Time) : Time::Span
|
|
||||||
planned = get_planned zero_time, on_time
|
|
||||||
worked = get_worked zero_time, on_time
|
|
||||||
planned - worked
|
planned - worked
|
||||||
end
|
end
|
||||||
|
|
||||||
def date_status(date : Time) : Time::Span
|
def date_status(on_time : Time) : Time::Span
|
||||||
planned = get_planned date.at_beginning_of_day, date.at_end_of_day
|
planned = get_planned on_time.at_beginning_of_day, on_time.at_end_of_day
|
||||||
worked = get_worked date.at_beginning_of_day, date
|
worked = get_worked on_time.at_beginning_of_day, on_time
|
||||||
planned - worked
|
planned - worked
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user