hr_lite 0.1.0

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.
Files changed (176) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +33 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +166 -0
  5. data/Rakefile +3 -0
  6. data/app/assets/javascripts/hr_lite/geo_punch.js +61 -0
  7. data/app/assets/javascripts/hr_lite/mention.js +100 -0
  8. data/app/assets/stylesheets/hr_lite/application.css +15 -0
  9. data/app/assets/stylesheets/hr_lite/hr_lite.css +239 -0
  10. data/app/controllers/hr_lite/admin/appraisals_controller.rb +74 -0
  11. data/app/controllers/hr_lite/admin/attendances_controller.rb +79 -0
  12. data/app/controllers/hr_lite/admin/audit_logs_controller.rb +9 -0
  13. data/app/controllers/hr_lite/admin/base_controller.rb +16 -0
  14. data/app/controllers/hr_lite/admin/designation_changes_controller.rb +33 -0
  15. data/app/controllers/hr_lite/admin/employees_controller.rb +53 -0
  16. data/app/controllers/hr_lite/admin/holidays_controller.rb +70 -0
  17. data/app/controllers/hr_lite/admin/leadership_controller.rb +18 -0
  18. data/app/controllers/hr_lite/admin/leave_balances_controller.rb +41 -0
  19. data/app/controllers/hr_lite/admin/leave_requests_controller.rb +41 -0
  20. data/app/controllers/hr_lite/admin/leave_types_controller.rb +54 -0
  21. data/app/controllers/hr_lite/admin/office_locations_controller.rb +46 -0
  22. data/app/controllers/hr_lite/admin/overview_controller.rb +12 -0
  23. data/app/controllers/hr_lite/admin/payroll_runs_controller.rb +93 -0
  24. data/app/controllers/hr_lite/admin/salary_slips_controller.rb +44 -0
  25. data/app/controllers/hr_lite/admin/salary_structures_controller.rb +49 -0
  26. data/app/controllers/hr_lite/admin/settings_controller.rb +18 -0
  27. data/app/controllers/hr_lite/application_controller.rb +76 -0
  28. data/app/controllers/hr_lite/appraisals_controller.rb +18 -0
  29. data/app/controllers/hr_lite/attendance_controller.rb +37 -0
  30. data/app/controllers/hr_lite/calendar_controller.rb +20 -0
  31. data/app/controllers/hr_lite/career_controller.rb +9 -0
  32. data/app/controllers/hr_lite/employee_profiles_controller.rb +9 -0
  33. data/app/controllers/hr_lite/holidays_controller.rb +9 -0
  34. data/app/controllers/hr_lite/home_controller.rb +7 -0
  35. data/app/controllers/hr_lite/kudos_controller.rb +36 -0
  36. data/app/controllers/hr_lite/leave_balances_controller.rb +11 -0
  37. data/app/controllers/hr_lite/leave_requests_controller.rb +56 -0
  38. data/app/controllers/hr_lite/salary_slips_controller.rb +39 -0
  39. data/app/controllers/hr_lite/users_controller.rb +9 -0
  40. data/app/helpers/hr_lite/application_helper.rb +105 -0
  41. data/app/jobs/hr_lite/application_job.rb +4 -0
  42. data/app/jobs/hr_lite/daily_digest_job.rb +33 -0
  43. data/app/jobs/hr_lite/leave_year_rollover_job.rb +29 -0
  44. data/app/mailers/hr_lite/application_mailer.rb +5 -0
  45. data/app/mailers/hr_lite/event_mailer.rb +33 -0
  46. data/app/models/concerns/hr_lite/audited.rb +70 -0
  47. data/app/models/concerns/hr_lite/encrypted_money.rb +32 -0
  48. data/app/models/hr_lite/application_record.rb +5 -0
  49. data/app/models/hr_lite/appraisal.rb +89 -0
  50. data/app/models/hr_lite/attendance_record.rb +41 -0
  51. data/app/models/hr_lite/audit_log.rb +17 -0
  52. data/app/models/hr_lite/designation_change.rb +52 -0
  53. data/app/models/hr_lite/employee_profile.rb +72 -0
  54. data/app/models/hr_lite/holiday.rb +18 -0
  55. data/app/models/hr_lite/kudo.rb +54 -0
  56. data/app/models/hr_lite/kudo_mention.rb +8 -0
  57. data/app/models/hr_lite/leave_balance.rb +42 -0
  58. data/app/models/hr_lite/leave_request.rb +207 -0
  59. data/app/models/hr_lite/leave_type.rb +22 -0
  60. data/app/models/hr_lite/office_location.rb +21 -0
  61. data/app/models/hr_lite/payroll_run.rb +112 -0
  62. data/app/models/hr_lite/salary_slip.rb +78 -0
  63. data/app/models/hr_lite/salary_structure.rb +49 -0
  64. data/app/models/hr_lite/setting.rb +14 -0
  65. data/app/services/hr_lite/attendance_puncher.rb +103 -0
  66. data/app/services/hr_lite/attendance_summary.rb +98 -0
  67. data/app/services/hr_lite/calculators/esi.rb +25 -0
  68. data/app/services/hr_lite/calculators/pf.rb +32 -0
  69. data/app/services/hr_lite/calculators/professional_tax.rb +20 -0
  70. data/app/services/hr_lite/calculators/proration.rb +30 -0
  71. data/app/services/hr_lite/calculators/tds.rb +74 -0
  72. data/app/services/hr_lite/day_status.rb +49 -0
  73. data/app/services/hr_lite/leave_day_counter.rb +24 -0
  74. data/app/services/hr_lite/overview_query.rb +39 -0
  75. data/app/services/hr_lite/payroll_run_processor.rb +46 -0
  76. data/app/services/hr_lite/pdf_renderer.rb +23 -0
  77. data/app/services/hr_lite/slip_builder.rb +106 -0
  78. data/app/services/hr_lite/working_calendar.rb +41 -0
  79. data/app/views/hr_lite/admin/appraisals/_form.html.erb +29 -0
  80. data/app/views/hr_lite/admin/appraisals/edit.html.erb +6 -0
  81. data/app/views/hr_lite/admin/appraisals/new.html.erb +6 -0
  82. data/app/views/hr_lite/admin/attendances/index.html.erb +49 -0
  83. data/app/views/hr_lite/admin/attendances/show.html.erb +55 -0
  84. data/app/views/hr_lite/admin/audit_logs/index.html.erb +39 -0
  85. data/app/views/hr_lite/admin/designation_changes/new.html.erb +19 -0
  86. data/app/views/hr_lite/admin/employees/_form.html.erb +40 -0
  87. data/app/views/hr_lite/admin/employees/edit.html.erb +3 -0
  88. data/app/views/hr_lite/admin/employees/index.html.erb +40 -0
  89. data/app/views/hr_lite/admin/employees/new.html.erb +3 -0
  90. data/app/views/hr_lite/admin/employees/show.html.erb +75 -0
  91. data/app/views/hr_lite/admin/holidays/index.html.erb +59 -0
  92. data/app/views/hr_lite/admin/leave_balances/index.html.erb +58 -0
  93. data/app/views/hr_lite/admin/leave_requests/index.html.erb +35 -0
  94. data/app/views/hr_lite/admin/leave_requests/show.html.erb +39 -0
  95. data/app/views/hr_lite/admin/leave_types/_form.html.erb +27 -0
  96. data/app/views/hr_lite/admin/leave_types/edit.html.erb +10 -0
  97. data/app/views/hr_lite/admin/leave_types/index.html.erb +39 -0
  98. data/app/views/hr_lite/admin/leave_types/new.html.erb +3 -0
  99. data/app/views/hr_lite/admin/office_locations/_form.html.erb +18 -0
  100. data/app/views/hr_lite/admin/office_locations/edit.html.erb +10 -0
  101. data/app/views/hr_lite/admin/office_locations/index.html.erb +30 -0
  102. data/app/views/hr_lite/admin/office_locations/new.html.erb +3 -0
  103. data/app/views/hr_lite/admin/overview/index.html.erb +72 -0
  104. data/app/views/hr_lite/admin/payroll_runs/index.html.erb +33 -0
  105. data/app/views/hr_lite/admin/payroll_runs/new.html.erb +20 -0
  106. data/app/views/hr_lite/admin/payroll_runs/show.html.erb +76 -0
  107. data/app/views/hr_lite/admin/salary_slips/show.html.erb +42 -0
  108. data/app/views/hr_lite/admin/salary_structures/_form.html.erb +25 -0
  109. data/app/views/hr_lite/admin/salary_structures/edit.html.erb +6 -0
  110. data/app/views/hr_lite/admin/salary_structures/new.html.erb +6 -0
  111. data/app/views/hr_lite/admin/settings/edit.html.erb +18 -0
  112. data/app/views/hr_lite/appraisals/index.html.erb +22 -0
  113. data/app/views/hr_lite/appraisals/show.html.erb +32 -0
  114. data/app/views/hr_lite/attendance/_month_grid.html.erb +41 -0
  115. data/app/views/hr_lite/attendance/_punch_card.html.erb +41 -0
  116. data/app/views/hr_lite/attendance/show.html.erb +22 -0
  117. data/app/views/hr_lite/calendar/show.html.erb +45 -0
  118. data/app/views/hr_lite/career/show.html.erb +49 -0
  119. data/app/views/hr_lite/employee_profiles/show.html.erb +22 -0
  120. data/app/views/hr_lite/event_mailer/event.html.erb +10 -0
  121. data/app/views/hr_lite/event_mailer/event.text.erb +10 -0
  122. data/app/views/hr_lite/event_mailer/leadership.html.erb +27 -0
  123. data/app/views/hr_lite/event_mailer/leadership.text.erb +16 -0
  124. data/app/views/hr_lite/holidays/_next_holiday.html.erb +12 -0
  125. data/app/views/hr_lite/holidays/index.html.erb +30 -0
  126. data/app/views/hr_lite/home/index.html.erb +25 -0
  127. data/app/views/hr_lite/kudos/_kudo.html.erb +17 -0
  128. data/app/views/hr_lite/kudos/index.html.erb +39 -0
  129. data/app/views/hr_lite/leave_balances/index.html.erb +19 -0
  130. data/app/views/hr_lite/leave_requests/_balance_chips.html.erb +17 -0
  131. data/app/views/hr_lite/leave_requests/index.html.erb +37 -0
  132. data/app/views/hr_lite/leave_requests/new.html.erb +36 -0
  133. data/app/views/hr_lite/leave_requests/show.html.erb +25 -0
  134. data/app/views/hr_lite/salary_slips/_slip_detail.html.erb +48 -0
  135. data/app/views/hr_lite/salary_slips/index.html.erb +29 -0
  136. data/app/views/hr_lite/salary_slips/pdf.html.erb +72 -0
  137. data/app/views/hr_lite/salary_slips/show.html.erb +12 -0
  138. data/app/views/hr_lite/shared/_form_errors.html.erb +10 -0
  139. data/app/views/hr_lite/shared/_pagination.html.erb +11 -0
  140. data/app/views/layouts/hr_lite/application.html.erb +56 -0
  141. data/app/views/layouts/hr_lite/mailer.html.erb +30 -0
  142. data/app/views/layouts/hr_lite/mailer.text.erb +6 -0
  143. data/app/views/layouts/hr_lite/pdf.html.erb +26 -0
  144. data/config/routes.rb +57 -0
  145. data/db/migrate/20260718190726_create_hr_lite_kudos.rb +14 -0
  146. data/db/migrate/20260718190727_create_hr_lite_kudo_mentions.rb +12 -0
  147. data/db/migrate/20260718190728_create_hr_lite_audit_logs.rb +15 -0
  148. data/db/migrate/20260718192342_create_hr_lite_office_locations.rb +13 -0
  149. data/db/migrate/20260718192343_create_hr_lite_attendance_records.rb +27 -0
  150. data/db/migrate/20260718193045_create_hr_lite_holidays.rb +14 -0
  151. data/db/migrate/20260718193046_create_hr_lite_leave_types.rb +20 -0
  152. data/db/migrate/20260718193047_create_hr_lite_leave_balances.rb +17 -0
  153. data/db/migrate/20260718193048_create_hr_lite_leave_requests.rb +23 -0
  154. data/db/migrate/20260718193049_create_hr_lite_settings.rb +10 -0
  155. data/db/migrate/20260718194534_create_hr_lite_employee_profiles.rb +27 -0
  156. data/db/migrate/20260718194535_create_hr_lite_salary_structures.rb +23 -0
  157. data/db/migrate/20260718194536_create_hr_lite_payroll_runs.rb +20 -0
  158. data/db/migrate/20260718194537_create_hr_lite_salary_slips.rb +28 -0
  159. data/db/migrate/20260718195953_create_hr_lite_appraisals.rb +22 -0
  160. data/db/migrate/20260718195954_create_hr_lite_designation_changes.rb +17 -0
  161. data/lib/generators/hr_lite/install/install_generator.rb +29 -0
  162. data/lib/generators/hr_lite/install/templates/AFTER_INSTALL +35 -0
  163. data/lib/generators/hr_lite/install/templates/initializer.rb +45 -0
  164. data/lib/hr_lite/configuration.rb +60 -0
  165. data/lib/hr_lite/current.rb +7 -0
  166. data/lib/hr_lite/engine.rb +39 -0
  167. data/lib/hr_lite/geo.rb +22 -0
  168. data/lib/hr_lite/mention_parser.rb +18 -0
  169. data/lib/hr_lite/money.rb +33 -0
  170. data/lib/hr_lite/notifications.rb +99 -0
  171. data/lib/hr_lite/seeds.rb +42 -0
  172. data/lib/hr_lite/statutory_rate_card.rb +60 -0
  173. data/lib/hr_lite/version.rb +3 -0
  174. data/lib/hr_lite.rb +104 -0
  175. data/lib/tasks/hr_lite_tasks.rake +8 -0
  176. metadata +250 -0
@@ -0,0 +1,49 @@
1
+ <% content_for(:page_title) { "Team attendance" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title">Team attendance</h1>
4
+ </div>
5
+
6
+ <div class="hrl-row" style="margin-bottom:.8rem;">
7
+ <a class="hrl-btn" href="<%= hr_lite.admin_attendances_path(date: @date - 1) %>">&larr;</a>
8
+ <strong><%= @date.strftime("%A, %d %B %Y") %></strong>
9
+ <a class="hrl-btn" href="<%= hr_lite.admin_attendances_path(date: @date + 1) %>">&rarr;</a>
10
+ <% unless @date == Date.current %>
11
+ <a class="hrl-btn" href="<%= hr_lite.admin_attendances_path %>">Today</a>
12
+ <% end %>
13
+ </div>
14
+
15
+ <div class="hrl-kpis">
16
+ <div class="hrl-kpi"><div class="hrl-kpi__value"><%= @records.values.count { |r| r.check_in_at } %></div><div class="hrl-kpi__label">Checked in</div></div>
17
+ <div class="hrl-kpi"><div class="hrl-kpi__value"><%= @employees.size - @records.size %></div><div class="hrl-kpi__label">No punch</div></div>
18
+ <div class="hrl-kpi"><div class="hrl-kpi__value"><%= @flagged_count %></div><div class="hrl-kpi__label">Flagged</div></div>
19
+ <div class="hrl-kpi"><div class="hrl-kpi__value"><%= @records.values.count { |r| r.check_in_at && r.check_out_at.nil? } %></div><div class="hrl-kpi__label">Still in</div></div>
20
+ </div>
21
+
22
+ <div class="hrl-table-wrap">
23
+ <table class="hrl-table hrl-table--stack">
24
+ <thead><tr><th>Employee</th><th>In</th><th>Out</th><th>Status</th><th></th></tr></thead>
25
+ <tbody>
26
+ <% @employees.each do |employee| %>
27
+ <% record = @records[employee.id] %>
28
+ <tr>
29
+ <td data-label="Employee"><%= hr_display_name(employee) %></td>
30
+ <td data-label="In"><%= record&.check_in_at&.strftime("%H:%M") || "—" %></td>
31
+ <td data-label="Out"><%= record&.check_out_at&.strftime("%H:%M") || "—" %></td>
32
+ <td data-label="Status">
33
+ <% if record&.flagged? %>
34
+ <span class="hrl-badge hrl-badge--bad" title="<%= record.flag_note %>">Flagged</span>
35
+ <% elsif record&.check_in_at %>
36
+ <span class="hrl-badge hrl-badge--ok"><%= record.status.humanize %></span>
37
+ <% else %>
38
+ <span class="hrl-badge hrl-badge--muted">No punch</span>
39
+ <% end %>
40
+ <% if record&.regularized? %><span class="hrl-badge">Fixed</span><% end %>
41
+ </td>
42
+ <td data-label="">
43
+ <a class="hrl-small" href="<%= hr_lite.admin_attendance_path(employee.id, date: @date, month: @date.strftime("%Y-%m")) %>">Fix / month</a>
44
+ </td>
45
+ </tr>
46
+ <% end %>
47
+ </tbody>
48
+ </table>
49
+ </div>
@@ -0,0 +1,55 @@
1
+ <% content_for(:page_title) { "Attendance — #{hr_display_name(@employee)}" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title"><%= hr_display_name(@employee) %></h1>
4
+ <div class="hrl-page__actions">
5
+ <a class="hrl-btn" href="<%= hr_lite.admin_attendances_path %>">Team view</a>
6
+ </div>
7
+ </div>
8
+
9
+ <section class="hrl-card">
10
+ <div class="hrl-row" style="margin-bottom:.6rem;">
11
+ <a class="hrl-btn" href="<%= hr_lite.admin_attendance_path(@employee.id, month: (@month - 1.month).strftime("%Y-%m")) %>">&larr;</a>
12
+ <strong><%= @month.strftime("%B %Y") %></strong>
13
+ <a class="hrl-btn" href="<%= hr_lite.admin_attendance_path(@employee.id, month: (@month + 1.month).strftime("%Y-%m")) %>">&rarr;</a>
14
+ <span class="hrl-right hrl-small hrl-muted">
15
+ Present <%= @counts[:present] %> · Half <%= @counts[:half_day] %> · Absent <%= @counts[:absent] %>
16
+ </span>
17
+ </div>
18
+ <%= render "hr_lite/attendance/month_grid", month: @month, day_status: @day_status,
19
+ link_builder: ->(date) { hr_lite.admin_attendance_path(@employee.id, date: date, month: @month.strftime("%Y-%m")) } %>
20
+ <p class="hrl-small hrl-muted hrl-mt">Tap a date to fix its punches.</p>
21
+ </section>
22
+
23
+ <% if @edit_date %>
24
+ <section class="hrl-card" id="regularize">
25
+ <h2 class="hrl-card__title">Fix <%= @edit_date.strftime("%A, %d %B") %></h2>
26
+ <% if @edit_record.flagged? %>
27
+ <p class="hrl-small"><span class="hrl-badge hrl-badge--bad">Flagged</span> <%= @edit_record.flag_note %></p>
28
+ <% end %>
29
+ <%= form_with url: hr_lite.admin_attendance_path(@employee.id, date: @edit_date), method: :patch,
30
+ scope: :attendance_record, local: true do |f| %>
31
+ <div class="hrl-field">
32
+ <%= f.label :check_in_at, "Check-in" %>
33
+ <%= f.datetime_local_field :check_in_at, value: @edit_record.check_in_at&.strftime("%Y-%m-%dT%H:%M") %>
34
+ </div>
35
+ <div class="hrl-field">
36
+ <%= f.label :check_out_at, "Check-out" %>
37
+ <%= f.datetime_local_field :check_out_at, value: @edit_record.check_out_at&.strftime("%Y-%m-%dT%H:%M") %>
38
+ <p class="hrl-hint">Clear both times to remove the punch entirely.</p>
39
+ </div>
40
+ <div class="hrl-field">
41
+ <%= f.label :status %>
42
+ <%= f.select :status, HrLite::AttendanceRecord::STATUSES.map { |s| [ s.humanize, s ] },
43
+ selected: @edit_record.status %>
44
+ </div>
45
+ <div class="hrl-field">
46
+ <%= f.label :regularization_note, "Why is this being fixed? (required)" %>
47
+ <%= f.text_area :regularization_note %>
48
+ </div>
49
+ <div class="hrl-form-actions">
50
+ <%= f.submit "Save fix", class: "hrl-btn hrl-btn--primary" %>
51
+ <a class="hrl-btn" href="<%= hr_lite.admin_attendance_path(@employee.id, month: @month.strftime("%Y-%m")) %>">Cancel</a>
52
+ </div>
53
+ <% end %>
54
+ </section>
55
+ <% end %>
@@ -0,0 +1,39 @@
1
+ <div class="hrl-page__head">
2
+ <h1 class="hrl-page__title">Audit trail</h1>
3
+ <p class="hrl-page__sub">Every policy, settings and payroll change — append-only.</p>
4
+ </div>
5
+
6
+ <% if @audit_logs.any? %>
7
+ <div class="hrl-table-wrap">
8
+ <table class="hrl-table hrl-table--stack">
9
+ <thead>
10
+ <tr><th>When</th><th>Who</th><th>Action</th><th>Subject</th><th>Changes</th></tr>
11
+ </thead>
12
+ <tbody>
13
+ <% @audit_logs.each do |log| %>
14
+ <tr>
15
+ <td data-label="When"><%= log.created_at.strftime("%d %b %Y, %H:%M") %></td>
16
+ <td data-label="Who"><%= hr_display_name(log.actor) %></td>
17
+ <td data-label="Action"><span class="hrl-badge hrl-badge--muted"><%= log.action %></span></td>
18
+ <td data-label="Subject"><%= log.subject_type.demodulize.underscore.humanize %> #<%= log.subject_id %></td>
19
+ <td data-label="Changes">
20
+ <% log.audited_changes.each do |attr, change| %>
21
+ <div class="hrl-small">
22
+ <span class="hrl-muted"><%= attr.humanize %>:</span>
23
+ <% if change.is_a?(Array) %>
24
+ <%= change[0].inspect %> → <%= change[1].inspect %>
25
+ <% else %>
26
+ <%= change %>
27
+ <% end %>
28
+ </div>
29
+ <% end %>
30
+ </td>
31
+ </tr>
32
+ <% end %>
33
+ </tbody>
34
+ </table>
35
+ </div>
36
+ <%= hrl_pagination %>
37
+ <% else %>
38
+ <p class="hrl-card hrl-card--empty">No changes recorded yet.</p>
39
+ <% end %>
@@ -0,0 +1,19 @@
1
+ <% content_for(:page_title) { "Role change" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title">Role change — <%= hr_display_name(@profile.user) %></h1>
4
+ </div>
5
+
6
+ <section class="hrl-card">
7
+ <p class="hrl-small hrl-muted">Current: <strong><%= @profile.designation.presence || "not set" %></strong>. The employee is notified and the change is recorded on their career timeline.</p>
8
+ <%= form_with model: @change, url: hr_lite.admin_employee_designation_changes_path(@profile),
9
+ scope: :designation_change, local: true do |f| %>
10
+ <%= render "hr_lite/shared/form_errors", record: @change %>
11
+ <div class="hrl-field"><%= f.label :to_designation, "New designation" %><%= f.text_field :to_designation %></div>
12
+ <div class="hrl-field"><%= f.label :effective_date %><%= f.date_field :effective_date %></div>
13
+ <div class="hrl-field"><%= f.label :note, "Note (optional)" %><%= f.text_area :note %></div>
14
+ <div class="hrl-form-actions">
15
+ <%= f.submit "Record change", class: "hrl-btn hrl-btn--primary" %>
16
+ <a class="hrl-btn" href="<%= hr_lite.admin_employee_path(@profile) %>">Cancel</a>
17
+ </div>
18
+ <% end %>
19
+ </section>
@@ -0,0 +1,40 @@
1
+ <section class="hrl-card">
2
+ <%= form_with model: profile, url: url, method: method, scope: :employee_profile, local: true do |f| %>
3
+ <%= render "hr_lite/shared/form_errors", record: profile %>
4
+ <%= f.hidden_field :user_id %>
5
+ <% if profile.new_record? && profile.user_id.blank? %>
6
+ <div class="hrl-field">
7
+ <%= f.label :user_id, "Staff member" %>
8
+ <%= f.select :user_id, HrLite.employees.map { |u| [ HrLite.display_name(u), u.id ] } %>
9
+ </div>
10
+ <% end %>
11
+ <div class="hrl-field"><%= f.label :employee_code %><%= f.text_field :employee_code %></div>
12
+ <div class="hrl-field"><%= f.label :designation %><%= f.text_field :designation %></div>
13
+ <div class="hrl-field"><%= f.label :department %><%= f.text_field :department %></div>
14
+ <div class="hrl-field"><%= f.label :work_location %><%= f.text_field :work_location %></div>
15
+ <div class="hrl-field"><%= f.label :date_of_birth %><%= f.date_field :date_of_birth %></div>
16
+ <div class="hrl-field"><%= f.label :date_of_joining %><%= f.date_field :date_of_joining %></div>
17
+ <div class="hrl-field">
18
+ <%= f.label :date_of_exit, "Date of exit (leave blank while employed)" %>
19
+ <%= f.date_field :date_of_exit %>
20
+ </div>
21
+ <div class="hrl-field"><%= f.label :pan_number, "PAN" %><%= f.text_field :pan_number %></div>
22
+ <div class="hrl-field"><%= f.label :pf_uan, "PF UAN" %><%= f.text_field :pf_uan %></div>
23
+ <div class="hrl-field"><%= f.label :esi_number, "ESI number" %><%= f.text_field :esi_number %></div>
24
+ <div class="hrl-field"><%= f.label :bank_name %><%= f.text_field :bank_name %></div>
25
+ <div class="hrl-field"><%= f.label :bank_account_number %><%= f.text_field :bank_account_number %></div>
26
+ <div class="hrl-field"><%= f.label :bank_ifsc, "IFSC" %><%= f.text_field :bank_ifsc %></div>
27
+ <div class="hrl-field">
28
+ <%= f.label :tax_regime %>
29
+ <%= f.select :tax_regime, HrLite::EmployeeProfile::TAX_REGIMES.map { |r| [ "#{r.humanize} regime", r ] } %>
30
+ </div>
31
+ <div class="hrl-field">
32
+ <%= f.label :declared_annual_deductions, "Declared annual deductions (old regime only)" %>
33
+ <%= f.number_field :declared_annual_deductions, step: 0.01, value: profile.declared_annual_deductions&.to_s("F") %>
34
+ </div>
35
+ <div class="hrl-form-actions">
36
+ <%= f.submit "Save profile", class: "hrl-btn hrl-btn--primary" %>
37
+ <a class="hrl-btn" href="<%= hr_lite.admin_employees_path %>">Cancel</a>
38
+ </div>
39
+ <% end %>
40
+ </section>
@@ -0,0 +1,3 @@
1
+ <% content_for(:page_title) { "Edit employee profile" } %>
2
+ <div class="hrl-page__head"><h1 class="hrl-page__title">Edit <%= @profile.employee_code %></h1></div>
3
+ <%= render "form", profile: @profile, url: hr_lite.admin_employee_path(@profile), method: :patch %>
@@ -0,0 +1,40 @@
1
+ <% content_for(:page_title) { "Employees" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title">Employees</h1>
4
+ </div>
5
+
6
+ <section class="hrl-card">
7
+ <% if @profiles.any? %>
8
+ <div class="hrl-table-wrap">
9
+ <table class="hrl-table hrl-table--stack">
10
+ <thead><tr><th>Code</th><th>Name</th><th>Designation</th><th>Joined</th><th></th></tr></thead>
11
+ <tbody>
12
+ <% @profiles.each do |profile| %>
13
+ <tr>
14
+ <td data-label="Code"><%= profile.employee_code %></td>
15
+ <td data-label="Name"><%= hr_display_name(profile.user) %>
16
+ <% if profile.date_of_exit %><span class="hrl-badge hrl-badge--muted">Exited</span><% end %></td>
17
+ <td data-label="Designation"><%= profile.designation %></td>
18
+ <td data-label="Joined"><%= profile.date_of_joining.strftime("%d %b %Y") %></td>
19
+ <td data-label=""><a class="hrl-btn" href="<%= hr_lite.admin_employee_path(profile) %>">Open</a></td>
20
+ </tr>
21
+ <% end %>
22
+ </tbody>
23
+ </table>
24
+ </div>
25
+ <%= hrl_pagination %>
26
+ <% else %>
27
+ <p class="hrl-card--empty">No employee profiles yet.</p>
28
+ <% end %>
29
+ </section>
30
+
31
+ <% if @users_without_profile.any? %>
32
+ <section class="hrl-card">
33
+ <h2 class="hrl-card__title">Staff without an HR profile</h2>
34
+ <div class="hrl-row">
35
+ <% @users_without_profile.each do |user| %>
36
+ <a class="hrl-btn" href="<%= hr_lite.new_admin_employee_path(user_id: user.id) %>">+ <%= hr_display_name(user) %></a>
37
+ <% end %>
38
+ </div>
39
+ </section>
40
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <% content_for(:page_title) { "New employee profile" } %>
2
+ <div class="hrl-page__head"><h1 class="hrl-page__title">New employee profile</h1></div>
3
+ <%= render "form", profile: @profile, url: hr_lite.admin_employees_path, method: :post %>
@@ -0,0 +1,75 @@
1
+ <% content_for(:page_title) { @profile.employee_code } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title"><%= hr_display_name(@profile.user) %> <span class="hrl-muted">(<%= @profile.employee_code %>)</span></h1>
4
+ <div class="hrl-page__actions">
5
+ <a class="hrl-btn" href="<%= hr_lite.edit_admin_employee_path(@profile) %>">Edit</a>
6
+ <a class="hrl-btn" href="<%= hr_lite.new_admin_employee_appraisal_path(@profile) %>">New appraisal</a>
7
+ <a class="hrl-btn" href="<%= hr_lite.new_admin_employee_designation_change_path(@profile) %>">Role change</a>
8
+ <a class="hrl-btn hrl-btn--primary" href="<%= hr_lite.new_admin_employee_salary_structure_path(@profile) %>">New structure</a>
9
+ </div>
10
+ </div>
11
+
12
+ <div class="hrl-grid hrl-grid--2">
13
+ <section class="hrl-card">
14
+ <h2 class="hrl-card__title">Profile</h2>
15
+ <dl class="hrl-deflist">
16
+ <dt>Designation</dt><dd><%= @profile.designation.presence || "—" %></dd>
17
+ <dt>Department</dt><dd><%= @profile.department.presence || "—" %></dd>
18
+ <dt>Joined</dt><dd><%= @profile.date_of_joining.strftime("%d %b %Y") %></dd>
19
+ <% if @profile.date_of_exit %><dt>Exited</dt><dd><%= @profile.date_of_exit.strftime("%d %b %Y") %></dd><% end %>
20
+ <dt>Tax regime</dt><dd><%= @profile.tax_regime.humanize %></dd>
21
+ <dt>PAN</dt><dd><%= @profile.masked_pan || "—" %></dd>
22
+ <dt>UAN</dt><dd><%= @profile.masked_uan || "—" %></dd>
23
+ <dt>ESI</dt><dd><%= @profile.esi_number.present? ? "on file" : "—" %></dd>
24
+ <dt>Bank</dt><dd><%= [ @profile.bank_name, @profile.masked_account ].compact.join(" ").presence || "—" %></dd>
25
+ </dl>
26
+ </section>
27
+
28
+ <section class="hrl-card">
29
+ <h2 class="hrl-card__title">Salary structures</h2>
30
+ <% if @structures.any? %>
31
+ <div class="hrl-table-wrap">
32
+ <table class="hrl-table">
33
+ <thead><tr><th>Effective</th><th class="hrl-num">Basic</th><th class="hrl-num">Gross</th><th></th></tr></thead>
34
+ <tbody>
35
+ <% @structures.each do |structure| %>
36
+ <tr>
37
+ <td><%= structure.effective_from.strftime("%b %Y") %></td>
38
+ <td class="hrl-num"><%= hrl_money(structure.basic) %></td>
39
+ <td class="hrl-num"><%= hrl_money(structure.monthly_gross) %></td>
40
+ <td><a class="hrl-small" href="<%= hr_lite.edit_admin_employee_salary_structure_path(@profile, structure) %>">Edit</a></td>
41
+ </tr>
42
+ <% end %>
43
+ </tbody>
44
+ </table>
45
+ </div>
46
+ <% else %>
47
+ <p class="hrl-muted hrl-small">No structure yet — payroll will skip this employee.</p>
48
+ <% end %>
49
+ </section>
50
+ </div>
51
+
52
+ <section class="hrl-card">
53
+ <h2 class="hrl-card__title">Appraisals</h2>
54
+ <% appraisals = HrLite::Appraisal.where(user_id: @profile.user_id).recent_first %>
55
+ <% if appraisals.any? %>
56
+ <% appraisals.each do |appraisal| %>
57
+ <div class="hrl-feed__item">
58
+ <div class="hrl-feed__body">
59
+ <strong><%= appraisal.period_label %></strong>
60
+ <span class="hrl-badge <%= appraisal.shared? ? 'hrl-badge--ok' : 'hrl-badge--muted' %>"><%= appraisal.status.humanize %></span>
61
+ <% if appraisal.rating %><span class="hrl-badge"><%= appraisal.rating %>/5</span><% end %>
62
+ <% if appraisal.outcome != "none" %><span class="hrl-badge hrl-badge--warn"><%= appraisal.outcome.humanize %></span><% end %>
63
+ </div>
64
+ <% if appraisal.draft? %>
65
+ <a class="hrl-btn" href="<%= hr_lite.edit_admin_employee_appraisal_path(@profile, appraisal) %>">Edit</a>
66
+ <%= button_to "Share", hr_lite.share_admin_employee_appraisal_path(@profile, appraisal), method: :post,
67
+ class: "hrl-btn hrl-btn--primary",
68
+ form: { data: { turbo_confirm: "Share this appraisal with the employee? It becomes permanent." } } %>
69
+ <% end %>
70
+ </div>
71
+ <% end %>
72
+ <% else %>
73
+ <p class="hrl-muted hrl-small">No appraisals yet.</p>
74
+ <% end %>
75
+ </section>
@@ -0,0 +1,59 @@
1
+ <% content_for(:page_title) { "Manage holidays" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title">Holidays <%= @year %></h1>
4
+ <div class="hrl-page__actions">
5
+ <a class="hrl-btn" href="<%= hr_lite.admin_holidays_path(year: @year - 1) %>"><%= @year - 1 %></a>
6
+ <a class="hrl-btn" href="<%= hr_lite.admin_holidays_path(year: @year + 1) %>"><%= @year + 1 %></a>
7
+ </div>
8
+ </div>
9
+
10
+ <section class="hrl-card">
11
+ <% if @holidays.any? %>
12
+ <div class="hrl-table-wrap">
13
+ <table class="hrl-table hrl-table--stack">
14
+ <thead><tr><th>Date</th><th>Holiday</th><th>Optional</th><th></th></tr></thead>
15
+ <tbody>
16
+ <% @holidays.each do |holiday| %>
17
+ <tr>
18
+ <td data-label="Date"><%= holiday.date.strftime("%a, %d %b %Y") %></td>
19
+ <td data-label="Holiday"><%= holiday.name %></td>
20
+ <td data-label="Optional"><%= holiday.optional ? "Yes" : "No" %></td>
21
+ <td data-label="">
22
+ <%= button_to "Remove", hr_lite.admin_holiday_path(holiday), method: :delete,
23
+ class: "hrl-btn hrl-btn--danger hrl-small",
24
+ form: { data: { turbo_confirm: "Remove #{holiday.name}?" } } %>
25
+ </td>
26
+ </tr>
27
+ <% end %>
28
+ </tbody>
29
+ </table>
30
+ </div>
31
+ <% else %>
32
+ <p class="hrl-card--empty">No holidays for <%= @year %> yet.</p>
33
+ <% end %>
34
+ </section>
35
+
36
+ <div class="hrl-grid hrl-grid--2">
37
+ <section class="hrl-card">
38
+ <h2 class="hrl-card__title">Add one</h2>
39
+ <%= form_with model: @holiday, url: hr_lite.admin_holidays_path, local: true do |f| %>
40
+ <div class="hrl-field"><%= f.label :date %><%= f.date_field :date %></div>
41
+ <div class="hrl-field"><%= f.label :name %><%= f.text_field :name %></div>
42
+ <div class="hrl-field hrl-field--check"><%= f.check_box :optional %><%= f.label :optional, "Optional / restricted" %></div>
43
+ <div class="hrl-form-actions"><%= f.submit "Add holiday", class: "hrl-btn hrl-btn--primary" %></div>
44
+ <% end %>
45
+ </section>
46
+
47
+ <section class="hrl-card">
48
+ <h2 class="hrl-card__title">Bulk paste</h2>
49
+ <p class="hrl-small hrl-muted">One per line: <code>YYYY-MM-DD, Name</code> (append <code>, optional</code> for restricted holidays). Duplicates are skipped.</p>
50
+ <%= form_with url: hr_lite.bulk_create_admin_holidays_path, method: :post, local: true do %>
51
+ <div class="hrl-field">
52
+ <textarea name="lines" class="hrl-input" rows="6" placeholder="2026-11-09, Diwali&#10;2026-03-04, Holi"></textarea>
53
+ </div>
54
+ <div class="hrl-form-actions">
55
+ <button type="submit" class="hrl-btn hrl-btn--primary">Add all</button>
56
+ </div>
57
+ <% end %>
58
+ </section>
59
+ </div>
@@ -0,0 +1,58 @@
1
+ <% content_for(:page_title) { "Team balances" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title">Team leave balances <%= @year %></h1>
4
+ </div>
5
+
6
+ <section class="hrl-card">
7
+ <div class="hrl-table-wrap">
8
+ <table class="hrl-table">
9
+ <thead>
10
+ <tr><th>Employee</th><% @types.each do |type| %><th class="hrl-num"><%= type.code %></th><% end %></tr>
11
+ </thead>
12
+ <tbody>
13
+ <% @employees.each do |employee| %>
14
+ <tr>
15
+ <td><%= hr_display_name(employee) %></td>
16
+ <% @types.each do |type| %>
17
+ <% balance = HrLite::LeaveBalance.for(employee, type, @year) %>
18
+ <td class="hrl-num"><%= balance.available.to_f %></td>
19
+ <% end %>
20
+ </tr>
21
+ <% end %>
22
+ </tbody>
23
+ </table>
24
+ </div>
25
+ </section>
26
+
27
+ <section class="hrl-card">
28
+ <h2 class="hrl-card__title">Adjust a balance</h2>
29
+ <p class="hrl-small hrl-muted">Positive credits (comp-off), negative debits. Fully audited.</p>
30
+ <%= form_with url: hr_lite.adjust_admin_leave_balances_path, method: :post, local: true do %>
31
+ <div class="hrl-field">
32
+ <label for="adj_user">Employee</label>
33
+ <select name="user_id" id="adj_user" class="hrl-input">
34
+ <% @employees.each do |employee| %>
35
+ <option value="<%= employee.id %>"><%= hr_display_name(employee) %></option>
36
+ <% end %>
37
+ </select>
38
+ </div>
39
+ <div class="hrl-field">
40
+ <label for="adj_type">Leave type</label>
41
+ <select name="leave_type_id" id="adj_type" class="hrl-input">
42
+ <% @types.each do |type| %><option value="<%= type.id %>"><%= type.name %></option><% end %>
43
+ </select>
44
+ </div>
45
+ <input type="hidden" name="year" value="<%= @year %>">
46
+ <div class="hrl-field">
47
+ <label for="adj_delta">Days (+/-)</label>
48
+ <input type="number" step="0.5" name="delta" id="adj_delta" class="hrl-input" required>
49
+ </div>
50
+ <div class="hrl-field">
51
+ <label for="adj_note">Note (required)</label>
52
+ <input type="text" name="note" id="adj_note" class="hrl-input" required>
53
+ </div>
54
+ <div class="hrl-form-actions">
55
+ <button class="hrl-btn hrl-btn--primary" type="submit">Apply adjustment</button>
56
+ </div>
57
+ <% end %>
58
+ </section>
@@ -0,0 +1,35 @@
1
+ <% content_for(:page_title) { "Leave approvals" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title">Leave approvals</h1>
4
+ </div>
5
+
6
+ <div class="hrl-row" style="margin-bottom:.8rem;">
7
+ <% HrLite::LeaveRequest::STATUSES.each do |status| %>
8
+ <a class="hrl-btn <%= 'hrl-btn--primary' if @status == status %>"
9
+ href="<%= hr_lite.admin_leave_requests_path(status: status) %>"><%= status.humanize %></a>
10
+ <% end %>
11
+ </div>
12
+
13
+ <section class="hrl-card">
14
+ <% if @requests.any? %>
15
+ <div class="hrl-table-wrap">
16
+ <table class="hrl-table hrl-table--stack">
17
+ <thead><tr><th>Employee</th><th>Type</th><th>Dates</th><th>Days</th><th></th></tr></thead>
18
+ <tbody>
19
+ <% @requests.each do |request| %>
20
+ <tr>
21
+ <td data-label="Employee"><%= hr_display_name(request.user) %></td>
22
+ <td data-label="Type"><%= request.leave_type.name %></td>
23
+ <td data-label="Dates"><%= request.date_range_label %></td>
24
+ <td data-label="Days" class="hrl-num"><%= request.days_count.to_f %></td>
25
+ <td data-label=""><a class="hrl-btn" href="<%= hr_lite.admin_leave_request_path(request) %>">Open</a></td>
26
+ </tr>
27
+ <% end %>
28
+ </tbody>
29
+ </table>
30
+ </div>
31
+ <%= hrl_pagination %>
32
+ <% else %>
33
+ <p class="hrl-card--empty">No <%= @status %> requests.</p>
34
+ <% end %>
35
+ </section>
@@ -0,0 +1,39 @@
1
+ <% content_for(:page_title) { "Leave decision" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title"><%= hr_display_name(@request.user) %></h1>
4
+ <div class="hrl-page__actions">
5
+ <a class="hrl-btn" href="<%= hr_lite.admin_leave_requests_path %>">Back</a>
6
+ </div>
7
+ </div>
8
+
9
+ <section class="hrl-card">
10
+ <dl class="hrl-deflist">
11
+ <dt>Type</dt><dd><%= @request.leave_type.name %> (<%= @request.paid? ? "paid" : "unpaid" %>)</dd>
12
+ <dt>Dates</dt><dd><%= @request.date_range_label %></dd>
13
+ <dt>Working days</dt><dd><%= @request.days_count.to_f %></dd>
14
+ <dt>Status</dt><dd><span class="hrl-badge"><%= @request.status.humanize %></span></dd>
15
+ <% if @request.reason.present? %><dt>Reason</dt><dd><%= @request.reason %></dd><% end %>
16
+ <% unless @request.leave_type.unlimited? %>
17
+ <dt>Balance</dt>
18
+ <dd><%= @balance.available.to_f %> of <%= @balance.entitled.to_f %> available</dd>
19
+ <% end %>
20
+ <% if @request.decision_note.present? %><dt>Decision note</dt><dd><%= @request.decision_note %></dd><% end %>
21
+ </dl>
22
+ </section>
23
+
24
+ <% if @request.pending? %>
25
+ <section class="hrl-card">
26
+ <h2 class="hrl-card__title">Decide</h2>
27
+ <%= form_with url: hr_lite.approve_admin_leave_request_path(@request), method: :post, local: true do %>
28
+ <div class="hrl-field">
29
+ <label for="decision_note">Note (required to reject)</label>
30
+ <textarea name="decision_note" id="decision_note" class="hrl-input"></textarea>
31
+ </div>
32
+ <div class="hrl-form-actions">
33
+ <button class="hrl-btn hrl-btn--primary" type="submit">Approve</button>
34
+ <button class="hrl-btn hrl-btn--danger" type="submit"
35
+ formaction="<%= hr_lite.reject_admin_leave_request_path(@request) %>">Reject</button>
36
+ </div>
37
+ <% end %>
38
+ </section>
39
+ <% end %>
@@ -0,0 +1,27 @@
1
+ <section class="hrl-card">
2
+ <%= form_with model: leave_type, url: url, method: method, local: true do |f| %>
3
+ <%= render "hr_lite/shared/form_errors", record: leave_type %>
4
+ <div class="hrl-field"><%= f.label :name %><%= f.text_field :name %></div>
5
+ <div class="hrl-field"><%= f.label :code %><%= f.text_field :code %></div>
6
+ <div class="hrl-field"><%= f.label :color %><%= f.color_field :color %></div>
7
+ <div class="hrl-field">
8
+ <%= f.label :annual_quota, "Annual quota (blank = unlimited)" %>
9
+ <%= f.number_field :annual_quota, step: 0.5 %>
10
+ </div>
11
+ <div class="hrl-field">
12
+ <%= f.label :accrual %>
13
+ <%= f.select :accrual, HrLite::LeaveType::ACCRUALS.map { |a| [ a.humanize, a ] } %>
14
+ </div>
15
+ <div class="hrl-field">
16
+ <%= f.label :carry_forward_cap, "Carry-forward cap" %>
17
+ <%= f.number_field :carry_forward_cap, step: 0.5 %>
18
+ </div>
19
+ <div class="hrl-field"><%= f.label :position %><%= f.number_field :position %></div>
20
+ <div class="hrl-field hrl-field--check"><%= f.check_box :paid %><%= f.label :paid %></div>
21
+ <div class="hrl-field hrl-field--check"><%= f.check_box :active %><%= f.label :active %></div>
22
+ <div class="hrl-form-actions">
23
+ <%= f.submit "Save", class: "hrl-btn hrl-btn--primary" %>
24
+ <a class="hrl-btn" href="<%= hr_lite.admin_leave_types_path %>">Cancel</a>
25
+ </div>
26
+ <% end %>
27
+ </section>
@@ -0,0 +1,10 @@
1
+ <% content_for(:page_title) { "Edit leave type" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title">Edit <%= @leave_type.name %></h1>
4
+ <div class="hrl-page__actions">
5
+ <%= button_to "Delete", hr_lite.admin_leave_type_path(@leave_type), method: :delete,
6
+ class: "hrl-btn hrl-btn--danger",
7
+ form: { data: { turbo_confirm: "Delete this leave type?" } } %>
8
+ </div>
9
+ </div>
10
+ <%= render "form", leave_type: @leave_type, url: hr_lite.admin_leave_type_path(@leave_type), method: :patch %>
@@ -0,0 +1,39 @@
1
+ <% content_for(:page_title) { "Leave types" } %>
2
+ <div class="hrl-page__head">
3
+ <h1 class="hrl-page__title">Leave types &amp; policy</h1>
4
+ <div class="hrl-page__actions">
5
+ <a class="hrl-btn hrl-btn--primary" href="<%= hr_lite.new_admin_leave_type_path %>">Add type</a>
6
+ </div>
7
+ </div>
8
+
9
+ <section class="hrl-card">
10
+ <div class="hrl-table-wrap">
11
+ <table class="hrl-table hrl-table--stack">
12
+ <thead><tr><th>Type</th><th>Quota</th><th>Accrual</th><th>Carry cap</th><th>Paid</th><th></th></tr></thead>
13
+ <tbody>
14
+ <% @leave_types.each do |type| %>
15
+ <tr>
16
+ <td data-label="Type">
17
+ <span class="hrl-badge" style="background: <%= type.color %>1f; color: <%= type.color %>;"><%= type.code %></span>
18
+ <%= type.name %>
19
+ <% unless type.active %><span class="hrl-badge hrl-badge--muted">Inactive</span><% end %>
20
+ </td>
21
+ <td data-label="Quota" class="hrl-num"><%= type.unlimited? ? "Unlimited" : type.annual_quota.to_f %></td>
22
+ <td data-label="Accrual"><%= type.accrual.humanize %></td>
23
+ <td data-label="Carry cap" class="hrl-num"><%= type.carry_forward_cap.to_f %></td>
24
+ <td data-label="Paid"><%= type.paid ? "Yes" : "No" %></td>
25
+ <td data-label="">
26
+ <a class="hrl-small" href="<%= hr_lite.edit_admin_leave_type_path(type) %>">Edit</a>
27
+ </td>
28
+ </tr>
29
+ <% end %>
30
+ </tbody>
31
+ </table>
32
+ </div>
33
+ </section>
34
+
35
+ <div class="hrl-row">
36
+ <a class="hrl-btn" href="<%= hr_lite.admin_office_locations_path %>">Office locations</a>
37
+ <a class="hrl-btn" href="<%= hr_lite.admin_holidays_path %>">Holidays</a>
38
+ <a class="hrl-btn" href="<%= hr_lite.edit_admin_setting_path %>">Weekend policy</a>
39
+ </div>
@@ -0,0 +1,3 @@
1
+ <% content_for(:page_title) { "New leave type" } %>
2
+ <div class="hrl-page__head"><h1 class="hrl-page__title">New leave type</h1></div>
3
+ <%= render "form", leave_type: @leave_type, url: hr_lite.admin_leave_types_path, method: :post %>