diff --git a/assets/App.vue b/assets/App.vue
index 69440fc..dde76a4 100644
--- a/assets/App.vue
+++ b/assets/App.vue
@@ -18,6 +18,16 @@
Профиль: {{ profileId }}
+ Статистика
+
+
+
+ {{ item.date }} |
+ {{ item.planned.total_minutes }} |
+ {{ item.worked.total_minutes }} |
+
+
+
@@ -31,11 +41,14 @@ export default {
started: false,
total_time: null,
today_time: null,
+ show_stat: false,
+ statistics: [],
};
},
created() {
this.profileId = h.extract_profile_id();
this.get_status();
+ this.get_statistics();
setInterval(() => this.get_status(), 60 * 1000);
},
methods: {
@@ -46,6 +59,11 @@ export default {
this.today_time = TimeSpan.fromObject(data.today.time);
});
},
+ get_statistics() {
+ h.get_statistics(this.profileId).then(data => {
+ this.statistics = data;
+ });
+ },
start() {
h.start(this.profileId).then(() => this.get_status());
},
@@ -85,4 +103,8 @@ export default {
.profile-info {
margin-top: 2em;
}
+
+.stat-table {
+ display: inline-table;
+}
diff --git a/assets/helpers.js b/assets/helpers.js
index 5f89bda..f686be9 100644
--- a/assets/helpers.js
+++ b/assets/helpers.js
@@ -32,4 +32,19 @@ async function finish(profileId) {
});
}
-export default { extract_profile_id, check_profile, get_status, start, finish };
+async function get_statistics(profileId) {
+ const response = await fetch('/api/statistics?profile_id=' + profileId, {
+ method: 'GET',
+ });
+ const data = await response.json();
+ return data;
+}
+
+export default {
+ extract_profile_id,
+ check_profile,
+ get_status,
+ start,
+ finish,
+ get_statistics,
+};
diff --git a/spec/profile_spec.cr b/spec/profile_spec.cr
index 9c779a6..4d31522 100644
--- a/spec/profile_spec.cr
+++ b/spec/profile_spec.cr
@@ -77,5 +77,11 @@ module Dayoff::Test
span = prof.date_status t(1, 15)
span.total_hours.should eq 3
end
+
+ it "can get statistics" do
+ prof = create_profile
+ stat = prof.statistics t(3, 12)
+ stat.size.should eq 3
+ end
end
end
diff --git a/src/dayoff.cr b/src/dayoff.cr
index 8b33b4f..7444988 100644
--- a/src/dayoff.cr
+++ b/src/dayoff.cr
@@ -19,9 +19,10 @@ end
def serialize_span(span : Time::Span)
{
- status: span < Time::Span.zero ? STATUS_OVERTIME : STATUS_UPTIME,
- hours: span.abs.total_hours.to_i32,
- minutes: span.abs.minutes.to_i32,
+ status: span < Time::Span.zero ? STATUS_OVERTIME : STATUS_UPTIME,
+ hours: span.abs.total_hours.to_i32,
+ minutes: span.abs.minutes.to_i32,
+ total_minutes: span.abs.total_minutes.to_i32,
}
end
@@ -55,6 +56,19 @@ get "/api/status" do |env|
data.to_json
end
+get "/api/statistics" do |env|
+ profile = app.profile Dayoff::ProfileId.new(env.get("profile_id").to_s)
+ data = profile.statistics now
+ mapped = data.map do |v|
+ {
+ date: v.date.to_s("%Y-%m-%d"),
+ planned: serialize_span(v.planned),
+ worked: serialize_span(v.worked),
+ }
+ end
+ mapped.to_json
+end
+
get "/" do
render "public/index.ecr"
end
diff --git a/src/dayoff/entities.cr b/src/dayoff/entities.cr
index 6b1ea86..b629d7f 100644
--- a/src/dayoff/entities.cr
+++ b/src/dayoff/entities.cr
@@ -23,9 +23,13 @@ module Dayoff
def initialize(@date : Time, @hours : Int32)
end
+ def hours_as_span : Time::Span
+ Time::Span.new(hours: @hours, minutes: 0, seconds: 0)
+ end
+
def in_range(from_time : Time, to_time : Time) : Time::Span
if @date >= from_time && @date < to_time
- Time::Span.new(hours: @hours, minutes: 0, seconds: 0)
+ hours_as_span
else
Time::Span.zero
end
@@ -61,6 +65,10 @@ module Dayoff
!@finish.nil?
end
+ def get_span(to_time : Time) : Time::Span
+ in_range @start, to_time
+ end
+
def in_range(from_time : Time, to_time : Time) : Time::Span
if finished?
in_range_finished from_time, to_time
diff --git a/src/dayoff/profile.cr b/src/dayoff/profile.cr
index bcd7141..3360735 100644
--- a/src/dayoff/profile.cr
+++ b/src/dayoff/profile.cr
@@ -12,6 +12,23 @@ module Dayoff
end
end
+ class DayStatRecord
+ getter date
+ getter planned
+ getter worked
+
+ def initialize(@date : Time, @planned : Time::Span, @worked : Time::Span)
+ end
+
+ def add_planned(v : Time::Span)
+ @planned += v
+ end
+
+ def add_worked(v : Time::Span)
+ @worked += v
+ end
+ end
+
class Profile
@pdates = [] of PlannedDate
@wrecords = [] of WorkRecord
@@ -75,5 +92,40 @@ module Dayoff
worked = get_worked on_time.at_beginning_of_day, on_time
planned - worked
end
+
+ def statistics(on_time : Time) : Array(DayStatRecord)
+ dates = {} of String => DayStatRecord
+
+ @pdates.each do |pd|
+ key = pd.date.to_s("%Y-%m-%d")
+ dates[key] = DayStatRecord.new(
+ pd.date,
+ pd.hours_as_span,
+ Time::Span.zero
+ )
+ end
+
+ @wrecords.each do |wr|
+ key = wr.start.to_s("%Y-%m-%d")
+ if dates.has_key? key
+ dates[key].add_worked wr.in_range(Helpers.zero_time, on_time)
+ else
+ dates[key] = DayStatRecord.new(
+ wr.start,
+ Time::Span.zero,
+ wr.in_range(Helpers.zero_time, on_time)
+ )
+ end
+ end
+
+ date_keys = dates.keys.sort!.reverse!
+
+ result = [] of DayStatRecord
+ date_keys.each do |k|
+ result.push dates[k]
+ end
+
+ result
+ end
end
end