hr_lite 0.21.3 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +75 -0
- data/README.md +54 -2
- data/app/assets/javascripts/hr_lite/confirm.js +18 -3
- data/app/assets/javascripts/hr_lite/geo_punch.js +65 -10
- data/app/assets/javascripts/hr_lite/nav.js +17 -0
- data/app/assets/javascripts/hr_lite/select_filter.js +46 -0
- data/app/assets/stylesheets/hr_lite/hr_lite.css +219 -79
- data/app/controllers/hr_lite/admin/assets_controller.rb +1 -1
- data/app/controllers/hr_lite/admin/attendances_controller.rb +31 -0
- data/app/controllers/hr_lite/approvals_controller.rb +1 -12
- data/app/controllers/hr_lite/attendance_controller.rb +7 -0
- data/app/controllers/hr_lite/holidays_controller.rb +1 -0
- data/app/controllers/hr_lite/home_controller.rb +40 -3
- data/app/controllers/hr_lite/hr_requests_controller.rb +1 -1
- data/app/controllers/hr_lite/leave_requests_controller.rb +13 -2
- data/app/controllers/hr_lite/regularization_requests_controller.rb +10 -2
- data/app/controllers/hr_lite/tax_declarations_controller.rb +4 -0
- data/app/helpers/hr_lite/application_helper.rb +43 -30
- data/app/jobs/hr_lite/attendance_close_job.rb +6 -1
- data/app/models/hr_lite/approval.rb +5 -0
- data/app/models/hr_lite/attendance_record.rb +26 -0
- data/app/models/hr_lite/employee_profile.rb +1 -0
- data/app/models/hr_lite/hr_request.rb +2 -1
- data/app/models/hr_lite/office_location.rb +12 -0
- data/app/models/hr_lite/regularization_request.rb +10 -4
- data/app/services/hr_lite/attendance_puncher.rb +8 -3
- data/app/views/hr_lite/admin/assets/index.html.erb +3 -2
- data/app/views/hr_lite/admin/assets/new.html.erb +6 -2
- data/app/views/hr_lite/admin/attendances/index.html.erb +37 -6
- data/app/views/hr_lite/admin/attendances/show.html.erb +11 -7
- data/app/views/hr_lite/admin/attendances/week.html.erb +42 -0
- data/app/views/hr_lite/admin/checklists/index.html.erb +1 -1
- data/app/views/hr_lite/admin/comp_off_requests/index.html.erb +2 -2
- data/app/views/hr_lite/admin/comp_off_requests/show.html.erb +2 -2
- data/app/views/hr_lite/admin/documents/index.html.erb +1 -1
- data/app/views/hr_lite/admin/employees/_form.html.erb +15 -7
- data/app/views/hr_lite/admin/employees/show.html.erb +5 -5
- data/app/views/hr_lite/admin/expenses/index.html.erb +2 -2
- data/app/views/hr_lite/admin/leave_balances/index.html.erb +3 -3
- data/app/views/hr_lite/admin/leave_requests/index.html.erb +2 -2
- data/app/views/hr_lite/admin/leave_requests/show.html.erb +4 -6
- data/app/views/hr_lite/admin/loans/new.html.erb +2 -1
- data/app/views/hr_lite/admin/overview/index.html.erb +3 -3
- data/app/views/hr_lite/admin/regularization_requests/index.html.erb +1 -1
- data/app/views/hr_lite/admin/shared/_approvals_tabs.html.erb +6 -5
- data/app/views/hr_lite/appraisals/show.html.erb +1 -1
- data/app/views/hr_lite/approvals/index.html.erb +1 -1
- data/app/views/hr_lite/attendance/_month_grid.html.erb +21 -26
- data/app/views/hr_lite/attendance/_punch_card.html.erb +32 -10
- data/app/views/hr_lite/attendance/show.html.erb +36 -7
- data/app/views/hr_lite/benefits/index.html.erb +1 -1
- data/app/views/hr_lite/calendar/show.html.erb +29 -22
- data/app/views/hr_lite/comp_off_requests/index.html.erb +3 -3
- data/app/views/hr_lite/comp_off_requests/new.html.erb +3 -2
- data/app/views/hr_lite/documents/index.html.erb +32 -30
- data/app/views/hr_lite/employee_profiles/show.html.erb +2 -2
- data/app/views/hr_lite/expenses/index.html.erb +17 -35
- data/app/views/hr_lite/expenses/new.html.erb +11 -6
- data/app/views/hr_lite/holidays/_next_holiday.html.erb +11 -8
- data/app/views/hr_lite/holidays/index.html.erb +6 -6
- data/app/views/hr_lite/home/index.html.erb +29 -19
- data/app/views/hr_lite/hr_requests/index.html.erb +7 -24
- data/app/views/hr_lite/hr_requests/new.html.erb +7 -5
- data/app/views/hr_lite/hr_requests/show.html.erb +4 -0
- data/app/views/hr_lite/kudos/index.html.erb +4 -3
- data/app/views/hr_lite/leave_balances/index.html.erb +14 -5
- data/app/views/hr_lite/leave_requests/_balance_chips.html.erb +5 -3
- data/app/views/hr_lite/leave_requests/_out_list.html.erb +16 -0
- data/app/views/hr_lite/leave_requests/index.html.erb +8 -21
- data/app/views/hr_lite/leave_requests/new.html.erb +22 -9
- data/app/views/hr_lite/leave_requests/show.html.erb +3 -5
- data/app/views/hr_lite/loans/index.html.erb +18 -20
- data/app/views/hr_lite/policies/index.html.erb +1 -1
- data/app/views/hr_lite/regularization_requests/index.html.erb +2 -2
- data/app/views/hr_lite/regularization_requests/new.html.erb +11 -8
- data/app/views/hr_lite/resignations/show.html.erb +1 -1
- data/app/views/hr_lite/salary_slips/_slip_detail.html.erb +9 -3
- data/app/views/hr_lite/salary_slips/index.html.erb +48 -44
- data/app/views/hr_lite/shared/_bell.html.erb +1 -1
- data/app/views/hr_lite/shared/_form_errors.html.erb +1 -1
- data/app/views/hr_lite/tax_declarations/show.html.erb +24 -19
- data/app/views/hr_lite/team/show.html.erb +2 -2
- data/app/views/layouts/hr_lite/application.html.erb +24 -8
- data/config/routes.rb +3 -1
- data/lib/hr_lite/configuration.rb +16 -2
- data/lib/hr_lite/notifications.rb +1 -0
- data/lib/hr_lite/version.rb +1 -1
- metadata +4 -1
|
@@ -1,45 +1,52 @@
|
|
|
1
1
|
<% content_for(:page_title) { "Calendar" } %>
|
|
2
2
|
<div class="hrl-page__head">
|
|
3
3
|
<h1 class="hrl-page__title">Company calendar</h1>
|
|
4
|
+
<div class="hrl-page__actions">
|
|
5
|
+
<a class="hrl-btn" href="<%= hr_lite.holidays_path %>">Holiday list</a>
|
|
6
|
+
</div>
|
|
4
7
|
</div>
|
|
5
8
|
|
|
6
9
|
<section class="hrl-card">
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
<% prev_m, next_m = @month - 1.month, @month + 1.month %>
|
|
11
|
+
<div class="hrl-row hrl-row--mb">
|
|
12
|
+
<a class="hrl-btn" href="<%= hr_lite.calendar_path(month: prev_m.strftime("%Y-%m")) %>" aria-label="Previous month, <%= prev_m.strftime("%B %Y") %>"><span aria-hidden="true">‹</span> <%= prev_m.strftime("%b") %></a>
|
|
9
13
|
<strong><%= @month.strftime("%B %Y") %></strong>
|
|
10
|
-
<a class="hrl-btn" href="<%= hr_lite.calendar_path(month: (
|
|
11
|
-
<a class="hrl-btn hrl-right" href="<%= hr_lite.holidays_path %>">Holiday list</a>
|
|
14
|
+
<a class="hrl-btn" href="<%= hr_lite.calendar_path(month: next_m.strftime("%Y-%m")) %>" aria-label="Next month, <%= next_m.strftime("%B %Y") %>"><%= next_m.strftime("%b") %> <span aria-hidden="true">›</span></a>
|
|
12
15
|
</div>
|
|
13
16
|
|
|
14
17
|
<% first = @month.beginning_of_month %>
|
|
15
|
-
<div class="hrl-mgrid">
|
|
18
|
+
<div class="hrl-mgrid hrl-mgrid--cal">
|
|
16
19
|
<% %w[Mo Tu We Th Fr Sa Su].each do |d| %><div class="hrl-mgrid__head"><%= d %></div><% end %>
|
|
17
20
|
<% (first.cwday - 1).times do %><div></div><% end %>
|
|
18
21
|
<% (first..@month.end_of_month).each do |date| %>
|
|
19
|
-
<% cell_class =
|
|
20
|
-
if @holidays[date] then "hrl-mgrid__day--holiday"
|
|
22
|
+
<% cell_class, code =
|
|
23
|
+
if @holidays[date] then [ "hrl-mgrid__day--holiday", "H" ]
|
|
21
24
|
elsif @calendar.weekend?(date) then "hrl-mgrid__day--weekend"
|
|
22
|
-
elsif @leaves[date].any? then "hrl-mgrid__day--leave"
|
|
25
|
+
elsif @leaves[date].any? then [ "hrl-mgrid__day--leave", "#{@leaves[date].size} off" ]
|
|
23
26
|
end %>
|
|
24
|
-
<div class="hrl-mgrid__day
|
|
27
|
+
<div class="<%= class_names("hrl-mgrid__day", cell_class, "hrl-mgrid__day--today": date == Date.current) %>">
|
|
25
28
|
<span class="hrl-mgrid__num"><%= date.day %></span>
|
|
26
|
-
<%
|
|
27
|
-
<span class="hrl-mgrid__tag" title="<%= holiday.name %>"><%= holiday.name %></span>
|
|
28
|
-
<% end %>
|
|
29
|
-
<% @leaves[date].first(2).each do |request| %>
|
|
30
|
-
<span class="hrl-mgrid__tag" style="color: <%= request.leave_type.color %>;"
|
|
31
|
-
title="<%= hr_display_name(request.user) %> — <%= request.leave_type.name %>">
|
|
32
|
-
<%= hr_display_name(request.user).split.first %> · <%= request.leave_type.code %>
|
|
33
|
-
</span>
|
|
34
|
-
<% end %>
|
|
35
|
-
<% if @leaves[date].size > 2 %><span class="hrl-mgrid__tag">+<%= @leaves[date].size - 2 %> more</span><% end %>
|
|
29
|
+
<% if code %><span class="hrl-mgrid__tag"><%= code %></span><% end %>
|
|
36
30
|
</div>
|
|
37
31
|
<% end %>
|
|
38
32
|
</div>
|
|
39
33
|
|
|
40
34
|
<div class="hrl-legend hrl-small">
|
|
41
|
-
<span class="hrl-badge hrl-badge--warn">Holiday</span>
|
|
42
|
-
<span class="hrl-badge">On leave</span>
|
|
43
|
-
<span class="hrl-badge hrl-badge--muted">
|
|
35
|
+
<span class="hrl-badge hrl-badge--warn">H Holiday</span>
|
|
36
|
+
<span class="hrl-badge">N off On leave</span>
|
|
37
|
+
<span class="hrl-badge hrl-badge--muted">Weekly off</span>
|
|
38
|
+
<span class="hrl-badge hrl-mgrid__key hrl-mgrid__day--today">Today</span>
|
|
44
39
|
</div>
|
|
40
|
+
|
|
41
|
+
<%# Names only — the leave type is the employee's own business. Leave keeps its label's "(first half)" note. %>
|
|
42
|
+
<% day = ->(d) { d.strftime("%a %-d %b") }
|
|
43
|
+
agenda = @holidays.values.flatten.map { |h| [ h.date, "#{day.(h.date)}: #{h.name} (holiday)" ] } +
|
|
44
|
+
@leaves.values.flatten.uniq.map { |r| [ [ r.start_date, first ].max, "#{[ r.start_date, r.end_date ].uniq.map(&day).join(' – ')}#{r.date_range_label[/ \(.+\)/]}: #{hr_display_name(r.user)}, on leave" ] } %>
|
|
45
|
+
<% if agenda.any? %>
|
|
46
|
+
<ul class="hrl-feed hrl-small hrl-mt">
|
|
47
|
+
<% agenda.sort_by(&:first).each do |_, line| %><li class="hrl-feed__item"><%= line %></li><% end %>
|
|
48
|
+
</ul>
|
|
49
|
+
<% else %>
|
|
50
|
+
<p class="hrl-muted hrl-small hrl-mt">No holidays or leave this month.</p>
|
|
51
|
+
<% end %>
|
|
45
52
|
</section>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<% content_for(:page_title) { "Comp-off" } %>
|
|
2
|
+
<% content_for(:back, "Leaves") %>
|
|
2
3
|
<div class="hrl-page__head">
|
|
3
4
|
<h1 class="hrl-page__title">My comp-off</h1>
|
|
4
5
|
<div class="hrl-page__actions">
|
|
5
|
-
<a class="hrl-btn" href="<%= hr_lite.leave_requests_path %>">My leaves</a>
|
|
6
6
|
<a class="hrl-btn hrl-btn--primary" href="<%= hr_lite.new_comp_off_request_path %>">Request comp-off</a>
|
|
7
7
|
</div>
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
10
|
<section class="hrl-card">
|
|
11
|
-
<p class="hrl-small hrl-muted"
|
|
11
|
+
<p class="hrl-small hrl-muted">
|
|
12
12
|
Worked on a weekend or holiday? Request a comp-off — once an admin approves,
|
|
13
13
|
<%= @comp_off_type ? "your #{@comp_off_type.name} balance is credited" : "a day is credited to your balance" %>
|
|
14
14
|
and you spend it through the normal leave flow.
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<% @requests.each do |request| %>
|
|
22
22
|
<tr>
|
|
23
23
|
<td data-label="Day worked"><%= request.date_worked.strftime("%a, %d %b %Y") %></td>
|
|
24
|
-
<td data-label="Credit" class="hrl-num"><%= request.credit_days
|
|
24
|
+
<td data-label="Credit" class="hrl-num"><%= hrl_days(request.credit_days) %></td>
|
|
25
25
|
<td data-label="Status"><%= hrl_request_status_badge(request.status) %></td>
|
|
26
26
|
<td data-label="Note" class="hrl-small hrl-muted"><%= request.decision_note.presence || "—" %></td>
|
|
27
27
|
<td data-label="" class="<%= 'hrl-cell--void' unless request.pending? %>">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<% content_for(:page_title) { "Request comp-off" } %>
|
|
2
|
+
<% content_for(:back, "Leaves") %>
|
|
2
3
|
<div class="hrl-page__head">
|
|
3
4
|
<h1 class="hrl-page__title">Request comp-off</h1>
|
|
4
5
|
</div>
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
<%= render "hr_lite/shared/form_errors", record: @request %>
|
|
9
10
|
<div class="hrl-field">
|
|
10
11
|
<%= f.label :date_worked, "Which day did you work?" %>
|
|
11
|
-
<%= f.date_field :date_worked, max: Date.current %>
|
|
12
|
+
<%= f.date_field :date_worked, max: Date.current, required: true %>
|
|
12
13
|
<p class="hrl-hint">Must be a weekend or holiday you actually worked — extra hours on a
|
|
13
14
|
normal working day are not comp-off under the policy.</p>
|
|
14
15
|
</div>
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
</div>
|
|
19
20
|
<div class="hrl-field">
|
|
20
21
|
<%= f.label :reason, "What did you work on? (required)" %>
|
|
21
|
-
<%= f.text_area :reason %>
|
|
22
|
+
<%= f.text_area :reason, required: true %>
|
|
22
23
|
</div>
|
|
23
24
|
<div class="hrl-form-actions">
|
|
24
25
|
<%= f.submit "Send for approval", class: "hrl-btn hrl-btn--primary" %>
|
|
@@ -13,34 +13,6 @@
|
|
|
13
13
|
</section>
|
|
14
14
|
<% end %>
|
|
15
15
|
|
|
16
|
-
<section class="hrl-card">
|
|
17
|
-
<h2 class="hrl-card__title">Upload a document</h2>
|
|
18
|
-
<%= form_with model: @document, url: hr_lite.documents_path, method: :post, local: true do |f| %>
|
|
19
|
-
<%= render "hr_lite/shared/form_errors", record: @document %>
|
|
20
|
-
<div class="hrl-field">
|
|
21
|
-
<%= f.label :category %>
|
|
22
|
-
<%= f.select :category,
|
|
23
|
-
options_for_select(HrLite::Document::SENSITIVE_CATEGORIES.map { |c| [ c.humanize, c ] } +
|
|
24
|
-
[ [ "Offer letter", "offer_letter" ], [ "Certificate", "certificate" ],
|
|
25
|
-
[ "Other", "other" ] ], @document.category) %>
|
|
26
|
-
</div>
|
|
27
|
-
<div class="hrl-field"><%= f.label :title %><%= f.text_field :title %></div>
|
|
28
|
-
<div class="hrl-field">
|
|
29
|
-
<%= f.label :reference_number, "Document number (optional)" %>
|
|
30
|
-
<%= f.text_field :reference_number %>
|
|
31
|
-
</div>
|
|
32
|
-
<div class="hrl-field">
|
|
33
|
-
<%= f.label :expires_on, "Expires on (optional — we will remind you)" %>
|
|
34
|
-
<%= f.date_field :expires_on %>
|
|
35
|
-
</div>
|
|
36
|
-
<div class="hrl-field">
|
|
37
|
-
<%= f.label :file, "File (PDF or image, up to 10 MB)" %>
|
|
38
|
-
<%= f.file_field :file %>
|
|
39
|
-
</div>
|
|
40
|
-
<div class="hrl-form-actions"><%= f.submit "Upload", class: "hrl-btn hrl-btn--primary" %></div>
|
|
41
|
-
<% end %>
|
|
42
|
-
</section>
|
|
43
|
-
|
|
44
16
|
<section class="hrl-card">
|
|
45
17
|
<h2 class="hrl-card__title">On file</h2>
|
|
46
18
|
<% if @documents.empty? %>
|
|
@@ -54,7 +26,7 @@
|
|
|
54
26
|
<tr>
|
|
55
27
|
<td data-label="Document">
|
|
56
28
|
<strong><%= doc.title %></strong>
|
|
57
|
-
<div class="hrl-small hrl-muted"><%= doc.category.humanize %></div>
|
|
29
|
+
<div class="hrl-small hrl-muted"><%= doc.category.humanize.sub(/\APan\z/, "PAN") %></div>
|
|
58
30
|
</td>
|
|
59
31
|
<td data-label="Expires">
|
|
60
32
|
<%= doc.expires_on ? doc.expires_on.strftime("%d %b %Y") : "—" %>
|
|
@@ -67,7 +39,7 @@
|
|
|
67
39
|
</td>
|
|
68
40
|
<td data-label="">
|
|
69
41
|
<% if doc.file.attached? %>
|
|
70
|
-
<a class="hrl-
|
|
42
|
+
<a class="hrl-btn" href="<%= hr_lite.download_document_path(doc) %>">Open</a>
|
|
71
43
|
<% end %>
|
|
72
44
|
<% unless doc.verified? %>
|
|
73
45
|
<%= button_to "Remove", hr_lite.document_path(doc), method: :delete,
|
|
@@ -82,3 +54,33 @@
|
|
|
82
54
|
</div>
|
|
83
55
|
<% end %>
|
|
84
56
|
</section>
|
|
57
|
+
|
|
58
|
+
<details class="hrl-card" <%= "open" if @documents.empty? || @document.errors.any? %>>
|
|
59
|
+
<summary class="hrl-btn hrl-btn--primary">Upload a document</summary>
|
|
60
|
+
<%= form_with model: @document, url: hr_lite.documents_path, method: :post, local: true, class: "hrl-mt" do |f| %>
|
|
61
|
+
<%= render "hr_lite/shared/form_errors", record: @document %>
|
|
62
|
+
<div class="hrl-field">
|
|
63
|
+
<%= f.label :category, id: "hrl-doc-category", for: nil %>
|
|
64
|
+
<div class="hrl-chiprow" role="radiogroup" aria-labelledby="hrl-doc-category">
|
|
65
|
+
<% (HrLite::Document::SENSITIVE_CATEGORIES.map { |c| [ c.humanize.sub(/\APan\z/, "PAN"), c ] } +
|
|
66
|
+
[ [ "Offer letter", "offer_letter" ], [ "Certificate", "certificate" ], [ "Other", "other" ] ]).each do |label, value| %>
|
|
67
|
+
<label><%= f.radio_button :category, value, required: true %><span><%= label %></span></label>
|
|
68
|
+
<% end %>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="hrl-field"><%= f.label :title %><%= f.text_field :title, required: true %></div>
|
|
72
|
+
<div class="hrl-field">
|
|
73
|
+
<%= f.label :reference_number, "Document number (optional)" %>
|
|
74
|
+
<%= f.text_field :reference_number %>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="hrl-field">
|
|
77
|
+
<%= f.label :expires_on, "Expires on (optional — we will remind you)" %>
|
|
78
|
+
<%= f.date_field :expires_on %>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="hrl-field">
|
|
81
|
+
<%= f.label :file, "File (PDF or image, up to 10 MB)" %>
|
|
82
|
+
<%= f.file_field :file, required: true, accept: "application/pdf,image/*" %>
|
|
83
|
+
</div>
|
|
84
|
+
<div class="hrl-form-actions"><%= f.submit "Upload", class: "hrl-btn hrl-btn--primary" %></div>
|
|
85
|
+
<% end %>
|
|
86
|
+
</details>
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
<dt>Employee code</dt><dd><%= @profile.employee_code %></dd>
|
|
10
10
|
<dt>Designation</dt><dd><%= @profile.designation.presence || "—" %></dd>
|
|
11
11
|
<dt>Reports to</dt>
|
|
12
|
-
<dd><%= (boss = @profile.active_manager) ? "#{hr_display_name(boss)} (your L1)" : "—"
|
|
13
|
-
· <a href="<%= hr_lite.org_path %>">Org chart</a></dd>
|
|
12
|
+
<dd><%= (boss = @profile.active_manager) ? "#{hr_display_name(boss)} (your L1)" : "—" %></dd>
|
|
14
13
|
<dt>Department</dt><dd><%= @profile.department.presence || "—" %></dd>
|
|
15
14
|
<dt>Joined</dt><dd><%= @profile.date_of_joining.strftime("%d %B %Y") %>
|
|
16
15
|
<% if @profile.on_probation? %><span class="hrl-badge hrl-badge--warn">Probation</span><% end %></dd>
|
|
@@ -19,6 +18,7 @@
|
|
|
19
18
|
<dt>PF UAN</dt><dd><%= @profile.masked_uan || "—" %></dd>
|
|
20
19
|
<dt>Bank</dt><dd><%= [ @profile.bank_name, @profile.masked_account ].compact.join(" ").presence || "—" %></dd>
|
|
21
20
|
</dl>
|
|
21
|
+
<a class="hrl-btn hrl-mt" href="<%= hr_lite.org_path %>">Org chart</a>
|
|
22
22
|
<p class="hrl-small hrl-muted hrl-mt">Something wrong? Ask leadership to correct it — changes are audited.</p>
|
|
23
23
|
<a class="hrl-btn hrl-mt" href="<%= hr_lite.resignation_path %>">Resignation</a>
|
|
24
24
|
</section>
|
|
@@ -28,41 +28,23 @@
|
|
|
28
28
|
<% if @expenses.empty? %>
|
|
29
29
|
<p class="hrl-muted">No claims yet.</p>
|
|
30
30
|
<% else %>
|
|
31
|
-
|
|
32
|
-
<
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
</div>
|
|
49
|
-
<% end %>
|
|
50
|
-
<% if expense.decision_note.present? %>
|
|
51
|
-
<div class="hrl-small hrl-muted"><%= expense.decision_note %></div>
|
|
52
|
-
<% end %>
|
|
53
|
-
</td>
|
|
54
|
-
<td data-label="">
|
|
55
|
-
<% if expense.draft? || expense.submitted? %>
|
|
56
|
-
<%= button_to "Withdraw", hr_lite.cancel_expense_path(expense),
|
|
57
|
-
class: "hrl-btn",
|
|
58
|
-
form: { data: { turbo_confirm: "Withdraw this claim?" } } %>
|
|
59
|
-
<% end %>
|
|
60
|
-
</td>
|
|
61
|
-
</tr>
|
|
62
|
-
<% end %>
|
|
63
|
-
</tbody>
|
|
64
|
-
</table>
|
|
65
|
-
</div>
|
|
31
|
+
<% @expenses.each do |expense| %>
|
|
32
|
+
<div class="hrl-listrow">
|
|
33
|
+
<span><%= expense.description %></span>
|
|
34
|
+
<span><%= hrl_money(expense.amount) %></span>
|
|
35
|
+
<span class="hrl-small hrl-muted">
|
|
36
|
+
<%= expense.spent_on.strftime("%d %b %Y") %> · <%= expense.category.name %>
|
|
37
|
+
<%= hrl_request_status_badge(expense.status) %>
|
|
38
|
+
<%= "· with #{expense.reimbursed_in.strftime('%B %Y')} payroll" if expense.reimbursed_in %>
|
|
39
|
+
<%= "· #{expense.decision_note}" if expense.decision_note.present? %>
|
|
40
|
+
</span>
|
|
41
|
+
<% if expense.draft? || expense.submitted? %>
|
|
42
|
+
<%= button_to "Withdraw", hr_lite.cancel_expense_path(expense),
|
|
43
|
+
class: "hrl-btn",
|
|
44
|
+
form: { data: { turbo_confirm: "Withdraw this claim?" } } %>
|
|
45
|
+
<% end %>
|
|
46
|
+
</div>
|
|
47
|
+
<% end %>
|
|
66
48
|
<%= hrl_pagination %>
|
|
67
49
|
<% end %>
|
|
68
50
|
</section>
|
|
@@ -7,26 +7,31 @@
|
|
|
7
7
|
|
|
8
8
|
<div class="hrl-field">
|
|
9
9
|
<%= f.label :category_id, "What kind of expense" %>
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
<% options = @categories.map do |c|
|
|
11
|
+
remaining = c.remaining_for(hr_current_user)
|
|
12
|
+
notes = [ ("receipt needed" if c.receipt_required),
|
|
13
|
+
("#{hrl_money(remaining)} left this month" if remaining) ].compact
|
|
14
|
+
[ notes.any? ? "#{c.name} (#{notes.join(', ')})" : c.name, c.id ]
|
|
15
|
+
end %>
|
|
16
|
+
<%= f.select :category_id, options, { include_blank: "Choose one" }, { required: true } %>
|
|
12
17
|
</div>
|
|
13
18
|
<div class="hrl-field">
|
|
14
19
|
<%= f.label :amount, "Amount (₹)" %>
|
|
15
|
-
<%= f.text_field :amount, inputmode: "decimal" %>
|
|
20
|
+
<%= f.text_field :amount, inputmode: "decimal", required: true %>
|
|
16
21
|
</div>
|
|
17
22
|
<div class="hrl-field">
|
|
18
23
|
<%= f.label :spent_on, "When you spent it" %>
|
|
19
|
-
<%= f.date_field :spent_on, max: Date.current.to_s %>
|
|
24
|
+
<%= f.date_field :spent_on, max: Date.current.to_s, required: true %>
|
|
20
25
|
</div>
|
|
21
26
|
<div class="hrl-field">
|
|
22
27
|
<%= f.label :description, "What it was for" %>
|
|
23
|
-
<%= f.text_field :description %>
|
|
28
|
+
<%= f.text_field :description, required: true %>
|
|
24
29
|
</div>
|
|
25
30
|
<div class="hrl-field">
|
|
26
31
|
<%= f.label :receipt, "Receipt (PDF or photo)" %>
|
|
27
32
|
<%= f.file_field :receipt, accept: "application/pdf,image/*" %>
|
|
28
33
|
<span class="hrl-small hrl-muted">
|
|
29
|
-
|
|
34
|
+
Needed when the category says "receipt needed".
|
|
30
35
|
</span>
|
|
31
36
|
</div>
|
|
32
37
|
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
<section class="hrl-card">
|
|
2
|
-
<h2 class="hrl-card__title">
|
|
3
|
-
<%
|
|
4
|
-
<% if
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
<h2 class="hrl-card__title">Upcoming holidays</h2>
|
|
3
|
+
<% holidays = HrLite::Holiday.company_wide.upcoming.where(date: ..Date.current + 60).limit(3).to_a %>
|
|
4
|
+
<% if holidays.any? %>
|
|
5
|
+
<div class="hrl-feed">
|
|
6
|
+
<% holidays.each do |holiday| %>
|
|
7
|
+
<% days = (holiday.date - Date.current).to_i %>
|
|
8
|
+
<div class="hrl-feed__item"><div class="hrl-feed__body"><%= holiday.date.strftime("%a %-d %b") %> · <%= holiday.name %> · <%= days.zero? ? "today" : "in #{pluralize(days, "day")}" %></div></div>
|
|
9
|
+
<% end %>
|
|
10
|
+
</div>
|
|
8
11
|
<% else %>
|
|
9
|
-
<p class="hrl-muted hrl-small">No
|
|
12
|
+
<p class="hrl-muted hrl-small">No holidays in the next 2 months.</p>
|
|
10
13
|
<% end %>
|
|
11
|
-
<a class="hrl-
|
|
14
|
+
<a class="hrl-card__link" href="<%= hr_lite.holidays_path %>">All holidays</a>
|
|
12
15
|
</section>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<% content_for(:page_title) { "Holidays" } %>
|
|
2
|
+
<% content_for(:back, "Calendar") %>
|
|
2
3
|
<div class="hrl-page__head">
|
|
3
4
|
<h1 class="hrl-page__title">Holidays <%= @year %></h1>
|
|
4
5
|
<div class="hrl-page__actions">
|
|
5
6
|
<a class="hrl-btn" href="<%= hr_lite.holidays_path(year: @year - 1) %>"><%= @year - 1 %></a>
|
|
6
7
|
<a class="hrl-btn" href="<%= hr_lite.holidays_path(year: @year + 1) %>"><%= @year + 1 %></a>
|
|
7
|
-
<a class="hrl-btn" href="<%= hr_lite.calendar_path %>">Calendar</a>
|
|
8
8
|
</div>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
<% if @holidays.any? %>
|
|
13
13
|
<div class="hrl-table-wrap">
|
|
14
14
|
<table class="hrl-table hrl-table--stack">
|
|
15
|
-
<thead><tr><th>Date</th><th>Holiday</th
|
|
15
|
+
<thead><tr><th>Date</th><th>Holiday</th></tr></thead>
|
|
16
16
|
<tbody>
|
|
17
17
|
<% @holidays.each do |holiday| %>
|
|
18
|
-
|
|
18
|
+
<% next_up = holiday.id == @next_holiday_id %>
|
|
19
|
+
<%= tag.tr class: ("hrl-muted" if holiday.date < Date.current) do %>
|
|
19
20
|
<td data-label="Date"><%= holiday.date.strftime("%a, %d %b") %></td>
|
|
20
|
-
<td data-label="Holiday"><%= holiday.name %></td>
|
|
21
|
-
|
|
22
|
-
</tr>
|
|
21
|
+
<td data-label="Holiday"><span class="hrl-row"><%= holiday.name %><% if next_up %> <span class="hrl-badge">Next</span><% end %><% if holiday.optional %> <span class="hrl-badge hrl-badge--muted">Optional</span><% end %></span></td>
|
|
22
|
+
<% end %>
|
|
23
23
|
<% end %>
|
|
24
24
|
</tbody>
|
|
25
25
|
</table>
|
|
@@ -2,30 +2,40 @@
|
|
|
2
2
|
<h1 class="hrl-page__title">Hello, <%= hr_display_name(hr_current_user) %></h1>
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
|
+
<% if (@waiting + @queue).positive? %>
|
|
6
|
+
<section class="hrl-card">
|
|
7
|
+
<h2 class="hrl-card__title"><%= pluralize(@waiting + @queue, "request") %> waiting on you</h2>
|
|
8
|
+
<a class="hrl-btn hrl-btn--primary hrl-mt" href="<%= @waiting.positive? ? hr_lite.approvals_path : hr_lite.admin_leave_requests_path %>">Review requests</a>
|
|
9
|
+
</section>
|
|
10
|
+
<% end %>
|
|
11
|
+
|
|
5
12
|
<div class="hrl-grid hrl-grid--2">
|
|
6
|
-
<%= render "hr_lite/attendance/punch_card" %>
|
|
13
|
+
<%= render "hr_lite/attendance/punch_card", attention: @attention %>
|
|
7
14
|
<%= render "hr_lite/leave_requests/balance_chips" %>
|
|
15
|
+
|
|
16
|
+
<% if @mine_pending.any? %>
|
|
17
|
+
<section class="hrl-card">
|
|
18
|
+
<h2 class="hrl-card__title">My requests</h2>
|
|
19
|
+
<% @mine_pending.each do |req| %>
|
|
20
|
+
<% title, detail, href = case req
|
|
21
|
+
when HrLite::LeaveRequest then [ req.leave_type.name, "#{req.date_range_label} · #{pluralize(hrl_days(req.days_count), 'day')}", hr_lite.leave_request_path(req) ]
|
|
22
|
+
when HrLite::RegularizationRequest then [ "Attendance fix", "#{req.date.strftime('%a %-d %b')} · #{req.times_label}", hr_lite.regularization_requests_path ]
|
|
23
|
+
else [ "Comp-off", "Worked #{req.date_worked.strftime('%a %-d %b')}", hr_lite.comp_off_requests_path ]
|
|
24
|
+
end %>
|
|
25
|
+
<a class="hrl-listrow" href="<%= href %>">
|
|
26
|
+
<span><%= title %></span>
|
|
27
|
+
<%= hrl_request_status_badge(req.status) %>
|
|
28
|
+
<span class="hrl-small hrl-muted"><%= detail %></span>
|
|
29
|
+
</a>
|
|
30
|
+
<% end %>
|
|
31
|
+
</section>
|
|
32
|
+
<% end %>
|
|
8
33
|
<%= render "hr_lite/holidays/next_holiday" %>
|
|
9
34
|
|
|
10
35
|
<section class="hrl-card">
|
|
11
|
-
<h2 class="hrl-card__title">
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<div class="hrl-feed">
|
|
15
|
-
<% @out_today.first(10).each do |leave| %>
|
|
16
|
-
<div class="hrl-feed__item">
|
|
17
|
-
<div class="hrl-feed__body"><%= tag.strong hr_display_name(leave.user), title: "On leave: #{leave.date_range_label}" %>
|
|
18
|
-
<div class="hrl-feed__meta"><%= leave.date_range_label %></div></div>
|
|
19
|
-
</div>
|
|
20
|
-
<% end %>
|
|
21
|
-
</div>
|
|
22
|
-
<% if @out_today.size > 10 %>
|
|
23
|
-
<p class="hrl-muted hrl-small">+<%= @out_today.size - 10 %> more</p>
|
|
24
|
-
<% end %>
|
|
25
|
-
<% else %>
|
|
26
|
-
<p class="hrl-muted hrl-small">Everyone's in today.</p>
|
|
27
|
-
<% end %>
|
|
28
|
-
<a class="hrl-small" href="<%= hr_lite.team_path %>">Team board</a>
|
|
36
|
+
<h2 class="hrl-card__title">On leave this week</h2>
|
|
37
|
+
<%= render "hr_lite/leave_requests/out_list", leaves: @out_week, empty: "Nobody is on leave this week." %>
|
|
38
|
+
<a class="hrl-card__link" href="<%= hr_lite.team_path %>">Team board</a>
|
|
29
39
|
</section>
|
|
30
40
|
|
|
31
41
|
<section class="hrl-card">
|
|
@@ -10,30 +10,13 @@
|
|
|
10
10
|
<% if @requests.empty? %>
|
|
11
11
|
<p class="hrl-muted">Nothing raised yet.</p>
|
|
12
12
|
<% else %>
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<a href="<%= hr_lite.hr_request_path(request) %>"><%= request.subject %></a>
|
|
21
|
-
<div class="hrl-small hrl-muted"><%= request.category_label %></div>
|
|
22
|
-
</td>
|
|
23
|
-
<td data-label="Raised"><%= request.created_at.to_date.strftime("%d %b %Y") %></td>
|
|
24
|
-
<td data-label="Status"><%= hrl_request_status_badge(request.status) %></td>
|
|
25
|
-
<td data-label="">
|
|
26
|
-
<% if request.open? || request.in_progress? %>
|
|
27
|
-
<%= button_to "Withdraw", hr_lite.cancel_hr_request_path(request),
|
|
28
|
-
class: "hrl-btn",
|
|
29
|
-
form: { data: { turbo_confirm: "Withdraw this request?" } } %>
|
|
30
|
-
<% end %>
|
|
31
|
-
</td>
|
|
32
|
-
</tr>
|
|
33
|
-
<% end %>
|
|
34
|
-
</tbody>
|
|
35
|
-
</table>
|
|
36
|
-
</div>
|
|
13
|
+
<% @requests.each do |request| %>
|
|
14
|
+
<a class="hrl-listrow" href="<%= hr_lite.hr_request_path(request) %>">
|
|
15
|
+
<span><%= request.subject %></span>
|
|
16
|
+
<%= hrl_request_status_badge(request.status) %>
|
|
17
|
+
<span class="hrl-small hrl-muted"><%= request.category_label %> · <%= request.created_at.to_date.strftime("%d %b %Y") %></span>
|
|
18
|
+
</a>
|
|
19
|
+
<% end %>
|
|
37
20
|
<%= hrl_pagination %>
|
|
38
21
|
<% end %>
|
|
39
22
|
</section>
|
|
@@ -6,14 +6,16 @@
|
|
|
6
6
|
<%= render "hr_lite/shared/form_errors", record: @request %>
|
|
7
7
|
|
|
8
8
|
<div class="hrl-field">
|
|
9
|
-
<%= f.label :category, "What is this about" %>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
<%= f.label :category, "What is this about", id: "hrl-request-category", for: nil %>
|
|
10
|
+
<div class="hrl-chiprow" role="radiogroup" aria-labelledby="hrl-request-category">
|
|
11
|
+
<% HrLite::HrRequest::CATEGORIES.each do |c| %>
|
|
12
|
+
<label><%= f.radio_button :category, c, required: true %><span><%= HrLite::HrRequest.category_label(c) %></span></label>
|
|
13
|
+
<% end %>
|
|
14
|
+
</div>
|
|
13
15
|
</div>
|
|
14
16
|
<div class="hrl-field">
|
|
15
17
|
<%= f.label :subject, "In one line" %>
|
|
16
|
-
<%= f.text_field :subject %>
|
|
18
|
+
<%= f.text_field :subject, required: true %>
|
|
17
19
|
</div>
|
|
18
20
|
<div class="hrl-field">
|
|
19
21
|
<%= f.label :body, "Anything else HR should know" %>
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
<% if @request.body.present? %>
|
|
13
13
|
<div class="hrl-prose"><%= simple_format(@request.body) %></div>
|
|
14
14
|
<% end %>
|
|
15
|
+
<% if @request.open? || @request.in_progress? %>
|
|
16
|
+
<%= button_to "Withdraw", hr_lite.cancel_hr_request_path(@request), class: "hrl-btn hrl-mt",
|
|
17
|
+
form: { data: { turbo_confirm: "Withdraw this request?" } } %>
|
|
18
|
+
<% end %>
|
|
15
19
|
</section>
|
|
16
20
|
|
|
17
21
|
<% if @request.resolution.present? %>
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
<p class="hrl-page__sub">Appreciate teammates publicly. Mention people with @ — they get notified.</p>
|
|
4
4
|
</div>
|
|
5
5
|
|
|
6
|
-
<
|
|
7
|
-
|
|
6
|
+
<details class="hrl-card" <%= "open" if @kudo.errors.any? %>>
|
|
7
|
+
<summary class="hrl-btn hrl-btn--primary hrl-btn--block">Give kudos</summary>
|
|
8
|
+
<%= form_with model: @kudo, url: hr_lite.kudos_path, local: true, class: "hrl-mt" do |f| %>
|
|
8
9
|
<%= render "hr_lite/shared/form_errors", record: @kudo %>
|
|
9
10
|
<div class="hrl-field">
|
|
10
11
|
<%= f.label :message, "Say something nice" %>
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
<%= f.submit "Post kudos", class: "hrl-btn hrl-btn--primary" %>
|
|
25
26
|
</div>
|
|
26
27
|
<% end %>
|
|
27
|
-
</
|
|
28
|
+
</details>
|
|
28
29
|
|
|
29
30
|
<section class="hrl-card">
|
|
30
31
|
<% if @kudos.any? %>
|
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
<% content_for(:page_title) { "Leave balances" } %>
|
|
2
|
+
<% content_for(:back, "Leaves") %>
|
|
2
3
|
<div class="hrl-page__head">
|
|
3
4
|
<h1 class="hrl-page__title">Leave balances <%= HrLite::LeaveYear.label(@year) %></h1>
|
|
5
|
+
<div class="hrl-page__actions">
|
|
6
|
+
<a class="hrl-btn hrl-btn--primary" href="<%= hr_lite.new_leave_request_path %>">Apply</a>
|
|
7
|
+
</div>
|
|
4
8
|
</div>
|
|
5
9
|
|
|
10
|
+
<% if @balances.any? %>
|
|
6
11
|
<div class="hrl-grid hrl-grid--2">
|
|
7
12
|
<% @balances.each do |balance| %>
|
|
8
13
|
<section class="hrl-card">
|
|
9
14
|
<h2 class="hrl-card__title"><%= balance.leave_type.name %></h2>
|
|
10
15
|
<dl class="hrl-deflist">
|
|
11
|
-
<dt
|
|
12
|
-
<dt>Used</dt><dd><%= balance.used
|
|
13
|
-
<dt>Available</dt><dd><strong><%= balance.available
|
|
14
|
-
<% if balance.carried_forward.positive? %><dt>Carried forward</dt><dd><%= balance.carried_forward
|
|
15
|
-
<% if balance.adjustment.nonzero? %><dt>Adjustments</dt><dd><%= balance.adjustment
|
|
16
|
+
<dt><%= balance.leave_type.comp_off ? "Credited" : "Entitled" %></dt><dd><%= hrl_days(balance.entitled) %></dd>
|
|
17
|
+
<dt>Used</dt><dd><%= hrl_days(balance.used) %></dd>
|
|
18
|
+
<dt>Available</dt><dd><strong><%= hrl_days(balance.available) %></strong></dd>
|
|
19
|
+
<% if balance.carried_forward.positive? %><dt>Carried forward</dt><dd><%= hrl_days(balance.carried_forward) %></dd><% end %>
|
|
20
|
+
<% if balance.adjustment.nonzero? %><dt>Adjustments</dt><dd><%= hrl_days(balance.adjustment) %> <span class="hrl-muted hrl-small"><%= balance.adjustment_note %></span></dd><% end %>
|
|
16
21
|
</dl>
|
|
22
|
+
<a class="hrl-card__link" href="<%= hr_lite.new_leave_request_path(leave_type_id: balance.leave_type_id) %>">Apply</a>
|
|
17
23
|
</section>
|
|
18
24
|
<% end %>
|
|
19
25
|
</div>
|
|
26
|
+
<% else %>
|
|
27
|
+
<p class="hrl-card hrl-card--empty">No leave types set up yet. Ask HR.</p>
|
|
28
|
+
<% end %>
|
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
<div class="hrl-row">
|
|
6
6
|
<% types.each do |type| %>
|
|
7
7
|
<% balance = HrLite::LeaveBalance.for(hr_current_user, type, HrLite::LeaveYear.current_key) %>
|
|
8
|
-
<span class="hrl-badge" style="
|
|
9
|
-
<%= type.
|
|
8
|
+
<span class="hrl-badge hrl-badge--type" style="--hrl-type: <%= type.color %>">
|
|
9
|
+
<%= type.name %> · <%= hrl_days(balance.available) %> of <%= hrl_days(balance.entitled) %> left
|
|
10
10
|
</span>
|
|
11
11
|
<% end %>
|
|
12
12
|
</div>
|
|
13
|
-
|
|
13
|
+
<% unless local_assigns[:compact] %>
|
|
14
|
+
<a class="hrl-btn hrl-mt" href="<%= hr_lite.new_leave_request_path %>">Apply for leave</a>
|
|
15
|
+
<% end %>
|
|
14
16
|
<% else %>
|
|
15
17
|
<p class="hrl-muted hrl-small">No leave types configured yet.</p>
|
|
16
18
|
<% end %>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<%# Name and dates only — the leave type (sick leave) is the employee's own business. %>
|
|
2
|
+
<% if leaves.any? %>
|
|
3
|
+
<div class="hrl-feed">
|
|
4
|
+
<% leaves.first(10).each do |leave| %>
|
|
5
|
+
<div class="hrl-feed__item">
|
|
6
|
+
<div class="hrl-feed__body"><%= tag.strong hr_display_name(leave.user), title: "On leave: #{leave.date_range_label}" %>
|
|
7
|
+
<div class="hrl-feed__meta"><%= leave.date_range_label %></div></div>
|
|
8
|
+
</div>
|
|
9
|
+
<% end %>
|
|
10
|
+
</div>
|
|
11
|
+
<% if leaves.size > 10 %>
|
|
12
|
+
<p class="hrl-muted hrl-small">+<%= leaves.size - 10 %> more</p>
|
|
13
|
+
<% end %>
|
|
14
|
+
<% else %>
|
|
15
|
+
<p class="hrl-muted hrl-small"><%= empty %></p>
|
|
16
|
+
<% end %>
|