recurrence_ui 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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +208 -0
- data/Rakefile +8 -0
- data/app/assets/config/recurrence_ui_manifest.js +1 -0
- data/app/assets/stylesheets/recurrence_ui/application.css +15 -0
- data/app/assets/stylesheets/recurrence_ui/components.css +295 -0
- data/app/assets/stylesheets/recurrence_ui/tokens.css +102 -0
- data/app/components/recurrence_ui/recurrence_picker_component.html.erb +234 -0
- data/app/components/recurrence_ui/recurrence_picker_component.rb +204 -0
- data/app/controllers/recurrence_ui/application_controller.rb +32 -0
- data/app/helpers/recurrence_ui/application_helper.rb +23 -0
- data/app/javascript/recurrence_ui/index.js +22 -0
- data/app/javascript/recurrence_ui/recurrence_ui_controller.js +954 -0
- data/app/jobs/recurrence_ui/application_job.rb +4 -0
- data/app/mailers/recurrence_ui/application_mailer.rb +6 -0
- data/app/models/concerns/recurrence_ui/has_recurrence.rb +351 -0
- data/app/models/recurrence_ui/application_record.rb +5 -0
- data/app/services/recurrence_ui/recurrence_formatter_service.rb +536 -0
- data/app/views/layouts/recurrence_ui/application.html.erb +15 -0
- data/app/views/recurrence_ui/_daily.html.erb +22 -0
- data/app/views/recurrence_ui/_exceptions.html.erb +50 -0
- data/app/views/recurrence_ui/_footer_actions.html.erb +17 -0
- data/app/views/recurrence_ui/_monthly_by_day_of_month.html.erb +47 -0
- data/app/views/recurrence_ui/_monthly_by_weekday.html.erb +55 -0
- data/app/views/recurrence_ui/_rdates.html.erb +50 -0
- data/app/views/recurrence_ui/_rule_card.html.erb +61 -0
- data/app/views/recurrence_ui/_summary_link.html.erb +25 -0
- data/app/views/recurrence_ui/_termination.html.erb +44 -0
- data/app/views/recurrence_ui/_weekly.html.erb +44 -0
- data/app/views/recurrence_ui/_yearly_by_day_of_month.html.erb +63 -0
- data/app/views/recurrence_ui/_yearly_by_weekday.html.erb +72 -0
- data/config/i18n-tasks.yml +212 -0
- data/config/importmap.rb +3 -0
- data/config/locales/recurrence_ui.be.yml +245 -0
- data/config/locales/recurrence_ui.en.yml +210 -0
- data/config/locales/recurrence_ui.ja.yml +201 -0
- data/config/locales/recurrence_ui.ru.yml +245 -0
- data/config/locales/recurrence_ui.uk.yml +245 -0
- data/config/routes.rb +5 -0
- data/lib/generators/recurrence_ui/views_generator.rb +26 -0
- data/lib/recurrence_ui/configuration.rb +116 -0
- data/lib/recurrence_ui/engine.rb +57 -0
- data/lib/recurrence_ui/version.rb +3 -0
- data/lib/recurrence_ui.rb +25 -0
- data/lib/tasks/recurrence_ui_tasks.rake +4 -0
- metadata +195 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_monthly_by_day_of_month.html.erb %>
|
|
2
|
+
<%# Monthly Recurrence Rule Options (By Day of Month) %>
|
|
3
|
+
<% selected_days_for_monthly = local_assigns.fetch(:selected_days_for_monthly, {}) %>
|
|
4
|
+
|
|
5
|
+
<div class="space-y-3" data-item="specificFields" data-rule="monthly_by_day_of_month">
|
|
6
|
+
<%# Interval Input Header %>
|
|
7
|
+
<div class="flex items-center space-x-2">
|
|
8
|
+
<span class="rui-inline-label">
|
|
9
|
+
<%= t("recurrence_ui.labels.every", default: "Every") %>
|
|
10
|
+
</span>
|
|
11
|
+
|
|
12
|
+
<%= number_field_tag nil, rec_ui.initial_interval,
|
|
13
|
+
value: 1,
|
|
14
|
+
min: 1,
|
|
15
|
+
class: "rui-input w-16 text-center",
|
|
16
|
+
data: {
|
|
17
|
+
item: "interval",
|
|
18
|
+
action: "input->#{identifier}#onCardInputChanged"
|
|
19
|
+
} %>
|
|
20
|
+
|
|
21
|
+
<span class="rui-inline-label">
|
|
22
|
+
<%= t("recurrence_ui.labels.month", count: rec_ui.initial_interval, default: "month(s)") %>
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<%# Month Days Selection Section %>
|
|
27
|
+
<div data-<%= identifier %>-target="monthlyDays">
|
|
28
|
+
<label class="rui-label mb-2">
|
|
29
|
+
<%= t("recurrence_ui.labels.select_dates", default: "Select dates") %>:
|
|
30
|
+
</label>
|
|
31
|
+
|
|
32
|
+
<div class="grid grid-cols-7 gap-1">
|
|
33
|
+
<% (1..31).each do |day| %>
|
|
34
|
+
<% is_selected = selected_days_for_monthly.to_a.include?(day) %>
|
|
35
|
+
|
|
36
|
+
<button type="button"
|
|
37
|
+
class="rui-day-btn"
|
|
38
|
+
data-day="<%= day %>"
|
|
39
|
+
data-<%= identifier %>-target="dayButton"
|
|
40
|
+
data-selected="<%= is_selected %>"
|
|
41
|
+
data-action="click-><%= identifier %>#toggleDay">
|
|
42
|
+
<%= day %>
|
|
43
|
+
</button>
|
|
44
|
+
<% end %>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_monthly_by_weekday.html.erb %>
|
|
2
|
+
<%# Monthly Recurrence Rule Options (By Weekday / Nth Day) %>
|
|
3
|
+
<% selected_nth_days = local_assigns.fetch(:selected_nth_days, {}) %>
|
|
4
|
+
|
|
5
|
+
<div class="space-y-3" data-item="specificFields" data-rule="monthly_by_weekday">
|
|
6
|
+
<%# Interval Input Header %>
|
|
7
|
+
<div class="flex items-center space-x-2">
|
|
8
|
+
<span class="rui-inline-label">
|
|
9
|
+
<%= t("recurrence_ui.labels.every", default: "Every") %>
|
|
10
|
+
</span>
|
|
11
|
+
|
|
12
|
+
<%= number_field_tag nil, rec_ui.initial_interval,
|
|
13
|
+
value: 1,
|
|
14
|
+
min: 1,
|
|
15
|
+
class: "rui-input w-16 text-center",
|
|
16
|
+
data: {
|
|
17
|
+
item: "interval",
|
|
18
|
+
action: "input->#{identifier}#onCardInputChanged"
|
|
19
|
+
} %>
|
|
20
|
+
|
|
21
|
+
<span class="rui-inline-label">
|
|
22
|
+
<%= t("recurrence_ui.labels.month", count: rec_ui.initial_interval, default: "month(s)") %>
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<%# Grid of Nth Days (1st, 2nd, 3rd, 4th, 5th, Last) %>
|
|
27
|
+
<div class="space-y-1">
|
|
28
|
+
<% %w[1 2 3 4 5 -1].each do |val| %>
|
|
29
|
+
<div class="grid grid-cols-8 gap-1 items-center">
|
|
30
|
+
<%# Row Label (Ordinal Name) %>
|
|
31
|
+
<div class="col-span-1 text-[10px] text-right pr-1">
|
|
32
|
+
<span class="rui-label mb-0 text-[10px] font-bold">
|
|
33
|
+
<%= t("recurrence_ui.nth_names.#{val}") %>
|
|
34
|
+
</span>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<%# Day Buttons Grid %>
|
|
38
|
+
<div class="col-span-7 grid grid-cols-7 gap-1">
|
|
39
|
+
<% days_for_ui.each do |day_idx| %>
|
|
40
|
+
<% is_selected = selected_nth_days[val.to_s]&.include?(day_idx) %>
|
|
41
|
+
<button type="button"
|
|
42
|
+
class="rui-day-btn"
|
|
43
|
+
data-nth="<%= val %>"
|
|
44
|
+
data-day="<%= day_idx %>"
|
|
45
|
+
data-<%= identifier %>-target="nthDayBtn"
|
|
46
|
+
data-selected="<%= !!is_selected %>"
|
|
47
|
+
data-action="click-><%= identifier %>#toggleDay">
|
|
48
|
+
<%= t('recurrence_ui.date.abbr_day_names', locale: I18n.locale)[day_idx] %>
|
|
49
|
+
</button>
|
|
50
|
+
<% end %>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<% end %>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_rdates.html.erb %>
|
|
2
|
+
<%# Additional Dates (RDATES) Section %>
|
|
3
|
+
<div class="space-y-1.5">
|
|
4
|
+
<%# 1. Section Label %>
|
|
5
|
+
<label class="rui-label flex items-center gap-1">
|
|
6
|
+
<%= t("recurrence_ui.labels.rdates", locale: locale, default: "Additional Dates") %>
|
|
7
|
+
</label>
|
|
8
|
+
|
|
9
|
+
<%# 2. Container for RDATE Chips %>
|
|
10
|
+
<div data-<%= identifier %>-target="rdatesContainer" class="flex flex-wrap gap-1">
|
|
11
|
+
<% rdates.each do |rdate| %>
|
|
12
|
+
<% date_str = rdate.is_a?(Date) || rdate.is_a?(Time) ? rdate.strftime("%Y-%m-%d") : rdate.to_s %>
|
|
13
|
+
<span class="rui-chip rui-chip--rdate" data-rdate-value="<%= date_str %>">
|
|
14
|
+
<button type="button"
|
|
15
|
+
data-action="click-><%= identifier %>#removeRdate"
|
|
16
|
+
class="rui-chip__remove-btn"
|
|
17
|
+
title="<%= t('recurrence_ui.actions.remove', default: 'Delete') %>">✕</button>
|
|
18
|
+
<span><%= rec_ui._formatDate(date_str) rescue date_str %></span>
|
|
19
|
+
</span>
|
|
20
|
+
<% end %>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<%# 3. Date Input and Add Button %>
|
|
24
|
+
<div class="flex items-center gap-1.5 pt-1">
|
|
25
|
+
<input type="date"
|
|
26
|
+
data-<%= identifier %>-target="rdateInput"
|
|
27
|
+
data-action="input-><%= identifier %>#onDateInputChange"
|
|
28
|
+
class="rui-input w-full text-xs py-1 px-2">
|
|
29
|
+
|
|
30
|
+
<button type="button"
|
|
31
|
+
data-<%= identifier %>-target="addRdateBtn"
|
|
32
|
+
data-action="click-><%= identifier %>#addRdate"
|
|
33
|
+
disabled
|
|
34
|
+
title="<%= t('recurrence_ui.actions.add_rdate', default: 'Add date') %>"
|
|
35
|
+
class="rui-btn rui-btn-primary px-2 py-1 text-xs font-bold">
|
|
36
|
+
+
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<%# 4. Template for Dynamically Generated RDATE Chips via JS %>
|
|
42
|
+
<template data-<%= identifier %>-target="rdateTemplate">
|
|
43
|
+
<span class="rui-chip rui-chip--rdate" data-rdate-value="VALUE">
|
|
44
|
+
<button type="button"
|
|
45
|
+
data-action="click-><%= identifier %>#removeRdate"
|
|
46
|
+
class="rui-chip__remove-btn"
|
|
47
|
+
title="<%= t('recurrence_ui.actions.remove', default: 'Delete') %>">✕</button>
|
|
48
|
+
<span>LABEL</span>
|
|
49
|
+
</span>
|
|
50
|
+
</template>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_rule_card.html.erb %>
|
|
2
|
+
<div data-<%= identifier %>-target="ruleCard" class="group rui-card-container w-full">
|
|
3
|
+
|
|
4
|
+
<%# 1. Rule Header: Card border & Clickable Area %>
|
|
5
|
+
<div class="rui-card-header" data-action="click-><%= identifier %>#toggleCardAccordion">
|
|
6
|
+
|
|
7
|
+
<%# Full Rule Text Summary %>
|
|
8
|
+
<span data-item="cardSummary" class="rui-accordion-link">
|
|
9
|
+
<%= t('recurrence_ui.labels.new_rule', default: 'New rule') %>
|
|
10
|
+
</span>
|
|
11
|
+
|
|
12
|
+
<%# Delete Button (Positioned on the Right) %>
|
|
13
|
+
<button type="button"
|
|
14
|
+
data-action="click-><%= identifier %>#removeRule"
|
|
15
|
+
title="<%= t('recurrence_ui.actions.remove', default: 'Delete') %>"
|
|
16
|
+
class="rui-btn-remove-card">
|
|
17
|
+
✕
|
|
18
|
+
</button>
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<%# 2. Rule Accordion Body %>
|
|
23
|
+
<div data-<%= identifier %>-target="cardBody" class="hidden rui-card-body">
|
|
24
|
+
|
|
25
|
+
<%# Frequency Selector Block %>
|
|
26
|
+
<div>
|
|
27
|
+
<label class="rui-label">
|
|
28
|
+
<%= t('recurrence_ui.labels.frequency', default: 'Частота') %>
|
|
29
|
+
</label>
|
|
30
|
+
<select data-item="ruleType"
|
|
31
|
+
data-action="change-><%= identifier %>#toggleCardFields"
|
|
32
|
+
class="rui-select w-full">
|
|
33
|
+
<% rule_options.each do |label, value| %>
|
|
34
|
+
<option value="<%= value %>"><%= label %></option>
|
|
35
|
+
<% end %>
|
|
36
|
+
</select>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<%# Dynamic Specific Rule Fields %>
|
|
40
|
+
<% rule_options.map(&:last).each do |rule| %>
|
|
41
|
+
<div data-item="specificFields" data-rule="<%= rule %>" class="hidden">
|
|
42
|
+
<%= render "recurrence_ui/#{rule}", form: form, identifier: identifier, days_for_ui: days_for_ui, rec_ui: rec_ui %>
|
|
43
|
+
</div>
|
|
44
|
+
<% end %>
|
|
45
|
+
|
|
46
|
+
<%# Termination Settings Section %>
|
|
47
|
+
<div data-item="terminationBlock">
|
|
48
|
+
<%= render "recurrence_ui/termination", form: form, identifier: identifier, rec_ui: rec_ui %>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<%# Accordion Close Action (Positioned on the Right) %>
|
|
52
|
+
<div class="pt-1 text-right">
|
|
53
|
+
<button type="button"
|
|
54
|
+
data-action="click-><%= identifier %>#toggleCardAccordion"
|
|
55
|
+
class="rui-btn-secondary">
|
|
56
|
+
<%= t('recurrence_ui.actions.done', default: 'Done') %>
|
|
57
|
+
</button>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_summary_link.html.erb %>
|
|
2
|
+
<%# Summary Link (Display Mode) %>
|
|
3
|
+
<div data-<%= identifier %>-target="displayMode" class="group cursor-pointer py-0.5">
|
|
4
|
+
<div class="flex items-center gap-2">
|
|
5
|
+
|
|
6
|
+
<%# Interactive Summary Text with full dotted/dashed underline %>
|
|
7
|
+
<div class="flex-1 min-w-0">
|
|
8
|
+
<span
|
|
9
|
+
data-<%= identifier %>-target="summaryText"
|
|
10
|
+
data-action="click-><%= identifier %>#editRule"
|
|
11
|
+
class="rui-summary-link"
|
|
12
|
+
>
|
|
13
|
+
<%= t("recurrence_ui.one_time", default: "Does not repeat") %>
|
|
14
|
+
</span>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<%# Pencil Icon - visible on hover %>
|
|
18
|
+
<div class="rui-summary-icon">
|
|
19
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
|
20
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
|
|
21
|
+
</svg>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_termination.html.erb %>
|
|
2
|
+
<%# Termination / End Condition Section for Recurrence Rules %>
|
|
3
|
+
<div class="rui-divider pt-3" data-item="termination">
|
|
4
|
+
<label class="rui-label mb-2">
|
|
5
|
+
<%= t("recurrence_ui.labels.termination", default: "Ends") %>
|
|
6
|
+
</label>
|
|
7
|
+
|
|
8
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
9
|
+
<%# Termination Type Selector %>
|
|
10
|
+
<%= select_tag :end_type,
|
|
11
|
+
options_for_select([
|
|
12
|
+
[t("recurrence_ui.termination_types.never", default: "Never"), 'never'],
|
|
13
|
+
[t("recurrence_ui.termination_types.until", default: "On date"), 'until'],
|
|
14
|
+
[t("recurrence_ui.termination_types.count", default: "After number of times"), 'count']
|
|
15
|
+
]),
|
|
16
|
+
class: "rui-select",
|
|
17
|
+
data: {
|
|
18
|
+
item: "endType",
|
|
19
|
+
"#{identifier}_target": "endType",
|
|
20
|
+
action: "change->#{identifier}#toggleEndFields change->#{identifier}#onCardInputChanged"
|
|
21
|
+
}
|
|
22
|
+
%>
|
|
23
|
+
|
|
24
|
+
<%# Specific End Date Input %>
|
|
25
|
+
<input type="date"
|
|
26
|
+
class="rui-input hidden text-xs"
|
|
27
|
+
data-item="endDateInput"
|
|
28
|
+
data-<%= identifier %>-target="endDate"
|
|
29
|
+
data-action="change-><%= identifier %>#onCardInputChanged">
|
|
30
|
+
|
|
31
|
+
<%# Count Input Field %>
|
|
32
|
+
<div data-item="endCount" data-<%= identifier %>-target="endCount" class="hidden flex items-center gap-2">
|
|
33
|
+
<input type="number" min="1" placeholder="10"
|
|
34
|
+
class="rui-input w-20 text-xs"
|
|
35
|
+
data-item="endCountInput"
|
|
36
|
+
data-<%= identifier %>-target="endCountInput"
|
|
37
|
+
data-action="input-><%= identifier %>#onCardInputChanged">
|
|
38
|
+
|
|
39
|
+
<span class="rui-inline-label text-xs uppercase font-semibold">
|
|
40
|
+
<%= t("recurrence_ui.labels.times", default: "times") %>
|
|
41
|
+
</span>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_weekly.html.erb %>
|
|
2
|
+
<%# Weekly Recurrence Rule Options %>
|
|
3
|
+
<% selected_days = local_assigns[:selected_weekly_days] || rec_ui.selected_weekly_days %>
|
|
4
|
+
|
|
5
|
+
<div class="space-y-3" data-item="specificFields" data-rule="weekly">
|
|
6
|
+
<%# Interval Input Header %>
|
|
7
|
+
<div class="flex items-center space-x-2">
|
|
8
|
+
<span class="rui-inline-label">
|
|
9
|
+
<%= t("recurrence_ui.every_week", default: "Every") %>
|
|
10
|
+
</span>
|
|
11
|
+
|
|
12
|
+
<%= number_field_tag nil, rec_ui.initial_interval,
|
|
13
|
+
value: 1,
|
|
14
|
+
min: 1,
|
|
15
|
+
class: "rui-input w-16 text-center",
|
|
16
|
+
data: {
|
|
17
|
+
item: "interval",
|
|
18
|
+
action: "input->#{identifier}#onCardInputChanged"
|
|
19
|
+
} %>
|
|
20
|
+
|
|
21
|
+
<span class="rui-inline-label">
|
|
22
|
+
<%= t("recurrence_ui.labels.week", count: rec_ui.initial_interval, default: "week(s)") %>
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<%# Days of Week Selection Grid %>
|
|
27
|
+
<div>
|
|
28
|
+
<div class="grid grid-cols-7 gap-1">
|
|
29
|
+
<% days_for_ui.each do |day_idx| %>
|
|
30
|
+
<%# Abbreviated day name based on current locale %>
|
|
31
|
+
<% day_name = t('recurrence_ui.date.abbr_day_names', locale: I18n.locale)[day_idx] %>
|
|
32
|
+
|
|
33
|
+
<button type="button"
|
|
34
|
+
class="rui-day-btn"
|
|
35
|
+
data-value="<%= day_idx %>"
|
|
36
|
+
data-selected="<%= selected_days.include?(day_idx) %>"
|
|
37
|
+
data-action="click-><%= identifier %>#toggleDay"
|
|
38
|
+
data-<%= identifier %>-target="dayButton">
|
|
39
|
+
<%= day_name %>
|
|
40
|
+
</button>
|
|
41
|
+
<% end %>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_yearly_by_day_of_month.html.erb %>
|
|
2
|
+
<%# Yearly Recurrence Rule Options (By Day of Month) %>
|
|
3
|
+
<% selected_days_for_yearly = local_assigns.fetch(:selected_days_for_yearly, {}) %>
|
|
4
|
+
|
|
5
|
+
<div class="space-y-3" data-item="specificFields" data-rule="yearly_by_day_of_month">
|
|
6
|
+
<%# Interval Input Header %>
|
|
7
|
+
<div class="flex items-center space-x-2">
|
|
8
|
+
<span class="rui-inline-label">
|
|
9
|
+
<%= t("recurrence_ui.labels.every", default: "Every") %>
|
|
10
|
+
</span>
|
|
11
|
+
|
|
12
|
+
<%= number_field_tag nil, rec_ui.initial_interval,
|
|
13
|
+
value: 1,
|
|
14
|
+
min: 1,
|
|
15
|
+
class: "rui-input w-16 text-center",
|
|
16
|
+
data: {
|
|
17
|
+
item: "interval",
|
|
18
|
+
action: "input->#{identifier}#onCardInputChanged"
|
|
19
|
+
} %>
|
|
20
|
+
|
|
21
|
+
<span class="rui-inline-label">
|
|
22
|
+
<%= t("recurrence_ui.labels.year", count: rec_ui.initial_interval, default: "year(s)") %>
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<%# Month Selector %>
|
|
27
|
+
<div data-<%= identifier %>-target="monthSelector" class="flex items-center gap-3">
|
|
28
|
+
<label class="rui-inline-label whitespace-nowrap">
|
|
29
|
+
<%= t("recurrence_ui.labels.choose_month", default: "Choose month") %>:
|
|
30
|
+
</label>
|
|
31
|
+
|
|
32
|
+
<select data-<%= identifier %>-target="monthInput"
|
|
33
|
+
data-item="month"
|
|
34
|
+
data-action="change-><%= identifier %>#onCardInputChanged"
|
|
35
|
+
class="rui-select w-full sm:w-auto">
|
|
36
|
+
<% (1..12).each do |m| %>
|
|
37
|
+
<% month_name = I18n.t("recurrence_ui.date.standalone_month_names", default: I18n.t("recurrence_ui.date.month_names"))[m] %>
|
|
38
|
+
<option value="<%= m %>"><%= month_name %></option>
|
|
39
|
+
<% end %>
|
|
40
|
+
</select>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<%# Month Days Selection Section %>
|
|
44
|
+
<div data-<%= identifier %>-target="monthlyDays">
|
|
45
|
+
<label class="rui-label mb-2">
|
|
46
|
+
<%= t("recurrence_ui.labels.select_dates", default: "Select dates") %>:
|
|
47
|
+
</label>
|
|
48
|
+
|
|
49
|
+
<div class="grid grid-cols-7 gap-1">
|
|
50
|
+
<% (1..31).each do |day| %>
|
|
51
|
+
<% is_selected = selected_days_for_yearly.to_a.include?(day) %>
|
|
52
|
+
<button type="button"
|
|
53
|
+
class="rui-day-btn"
|
|
54
|
+
data-day="<%= day %>"
|
|
55
|
+
data-<%= identifier %>-target="dayButton"
|
|
56
|
+
data-selected="<%= is_selected %>"
|
|
57
|
+
data-action="click-><%= identifier %>#toggleDay">
|
|
58
|
+
<%= day %>
|
|
59
|
+
</button>
|
|
60
|
+
<% end %>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<%# app/views/recurrence_ui/_yearly_by_weekday.html.erb %>
|
|
2
|
+
<%# Yearly Recurrence Rule Options (By Weekday / Nth Day) %>
|
|
3
|
+
<% selected_nth_days = local_assigns.fetch(:selected_nth_days, {}) %>
|
|
4
|
+
|
|
5
|
+
<div class="space-y-3" data-item="specificFields" data-rule="yearly_by_weekday">
|
|
6
|
+
<%# Interval Input Header %>
|
|
7
|
+
<div class="flex items-center space-x-2">
|
|
8
|
+
<span class="rui-inline-label">
|
|
9
|
+
<%= t("recurrence_ui.labels.every", default: "Every") %>
|
|
10
|
+
</span>
|
|
11
|
+
|
|
12
|
+
<%= number_field_tag nil, rec_ui.initial_interval,
|
|
13
|
+
value: 1,
|
|
14
|
+
min: 1,
|
|
15
|
+
class: "rui-input w-16 text-center",
|
|
16
|
+
data: {
|
|
17
|
+
item: "interval",
|
|
18
|
+
action: "input->#{identifier}#onCardInputChanged"
|
|
19
|
+
} %>
|
|
20
|
+
|
|
21
|
+
<span class="rui-inline-label">
|
|
22
|
+
<%= t("recurrence_ui.labels.year", count: rec_ui.initial_interval, default: "year(s)") %>
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<%# Month Selector %>
|
|
27
|
+
<div data-<%= identifier %>-target="monthSelector" class="flex items-center gap-3">
|
|
28
|
+
<label class="rui-inline-label whitespace-nowrap">
|
|
29
|
+
<%= t("recurrence_ui.labels.choose_month", default: "Choose month") %>:
|
|
30
|
+
</label>
|
|
31
|
+
|
|
32
|
+
<select data-<%= identifier %>-target="monthInput"
|
|
33
|
+
data-item="month"
|
|
34
|
+
data-action="change-><%= identifier %>#onCardInputChanged"
|
|
35
|
+
class="rui-select w-full sm:w-auto">
|
|
36
|
+
<% (1..12).each do |m| %>
|
|
37
|
+
<% month_name = I18n.t("recurrence_ui.date.standalone_month_names", default: t("recurrence_ui.date.month_names"))[m] %>
|
|
38
|
+
<option value="<%= m %>"><%= month_name %></option>
|
|
39
|
+
<% end %>
|
|
40
|
+
</select>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<%# Grid of Nth Days (1st, 2nd, 3rd, 4th, 5th, Last) %>
|
|
44
|
+
<div class="space-y-1">
|
|
45
|
+
<% %w[1 2 3 4 5 -1].each do |val| %>
|
|
46
|
+
<div class="grid grid-cols-8 gap-1 items-center">
|
|
47
|
+
<%# Row Label (Ordinal Name) %>
|
|
48
|
+
<div class="col-span-1 text-[10px] text-right pr-1">
|
|
49
|
+
<span class="rui-label mb-0 text-[10px] font-bold">
|
|
50
|
+
<%= t("recurrence_ui.nth_names.#{val}") %>
|
|
51
|
+
</span>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<%# Day Buttons Grid %>
|
|
55
|
+
<div class="col-span-7 grid grid-cols-7 gap-1">
|
|
56
|
+
<% days_for_ui.each do |day_idx| %>
|
|
57
|
+
<% is_selected = selected_nth_days[val.to_s]&.include?(day_idx) %>
|
|
58
|
+
<button type="button"
|
|
59
|
+
class="rui-day-btn"
|
|
60
|
+
data-nth="<%= val %>"
|
|
61
|
+
data-day="<%= day_idx %>"
|
|
62
|
+
data-<%= identifier %>-target="nthDayBtn"
|
|
63
|
+
data-selected="<%= !!is_selected %>"
|
|
64
|
+
data-action="click-><%= identifier %>#toggleDay">
|
|
65
|
+
<%= t('recurrence_ui.date.abbr_day_names', locale: I18n.locale)[day_idx] %>
|
|
66
|
+
</button>
|
|
67
|
+
<% end %>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
<% end %>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|