Class: HakumiComponents::Calendar::Component

Inherits:
BaseComponent
  • Object
show all
Extended by:
T::Sig
Defined in:
app/components/hakumi_components/calendar/component.rb

Constant Summary collapse

DateInput =
T.type_alias { BaseComponent::DateInput }
DateRange =
T.type_alias { T.nilable([ T.nilable(Date), T.nilable(Date) ]) }
YearRangeValue =
T.type_alias { T.any(T::Range[Integer], T::Array[Integer]) }
YearRangeInput =
T.type_alias { T.nilable(YearRangeValue) }
DateCellRenderer =
T.type_alias { T.nilable(T.proc.params(date: Date).returns(Types::RenderedContent)) }
MonthCellRenderer =
T.type_alias { T.nilable(T.proc.params(month: Integer).returns(Types::RenderedContent)) }
HeaderRendererProc =
T.type_alias do
  T.nilable(T.proc.params(
    arg0: Date,
    arg1: Symbol,
    arg2: NilClass,
    arg3: NilClass
  ).returns(Types::RenderedContent))
end
HeaderRenderer =
T.type_alias { T.nilable(T.any(FalseClass, HeaderRendererProc)) }
DisabledDatePredicate =
T.type_alias { T.nilable(T.proc.params(date: Date).returns(T::Boolean)) }
ControllerLocalValue =
T.type_alias { T.nilable(T.any(Types::HtmlPrimitive, Types::StringOrSymbolArray)) }
EventInputKey =
T.type_alias { T.any(Date, Types::HtmlKey) }
EventInputMap =
T.type_alias { T::Hash[EventInputKey, T::Array[HakumiComponents::Calendar::EventEntry::InputAttributes]] }
EventsByDate =
T.type_alias { T::Hash[Date, T::Array[HakumiComponents::Calendar::EventEntry]] }
MODES =
T.let(%i[month year quarter decade].freeze, T::Array[Symbol])
LOCALES =
T.let({
  en: HakumiComponents::Calendar::LocalePack.new(
    days_short: %w[Su Mo Tu We Th Fr Sa],
    days_full: %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday],
    months_short: %w[Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec],
    months_full: %w[January February March April May June July August September October November December]
  ),
  es: HakumiComponents::Calendar::LocalePack.new(
    days_short: [ "Do", "Lu", "Ma", "Mi", "Ju", "Vi", "" ],
    days_full: [ "Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado" ],
    months_short: %w[Ene Feb Mar Abr May Jun Jul Ago Sep Oct Nov Dic],
    months_full: [ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" ]
  )
}.freeze, T::Hash[Symbol, HakumiComponents::Calendar::LocalePack])

Constants inherited from BaseComponent

BaseComponent::ControllerOptions, BaseComponent::DateLikeValue, BaseComponent::DimensionInput, BaseComponent::HtmlPayloadInput, BaseComponent::I18nOptionValue, BaseComponent::PresenceArray, BaseComponent::PresenceScalar, BaseComponent::PresenceValue, BaseComponent::RawHtmlInput, BaseComponent::SIZES, BaseComponent::SizeValue, BaseComponent::SymbolInput

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseComponent

#append_data_token, boolean_html_param, #build_inline_style, cast_boolean, #cast_boolean, #class_names, #component_classes, #data_attributes_from, #dimension_to_css, #ensure_dom_id!, float_html_param, #generate_id, #html_classes, html_param, html_primitive_param, #html_style, #i18n_scope, integer_html_param, #merge_attributes, #render_value, #size_to_pixels, #stimulus_attrs, string_html_param, string_or_symbol_array_html_param, symbol_html_param, #t_default, #translate_with_default, #validate_inclusion!, #validate_required!, #value_present?

Constructor Details

#initialize(value: nil, default_value: nil, mode: :month, fullscreen: true, show_week: false, locale: :en, valid_range: nil, year_range: nil, events: {}, date_cell_render: nil, month_cell_render: nil, header_render: nil, disabled_date: nil, static: nil, **html_options) ⇒ Component

Returns a new instance of Component.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'app/components/hakumi_components/calendar/component.rb', line 88

def initialize(
  value: nil,
  default_value: nil,
  mode: :month,
  fullscreen: true,
  show_week: false,
  locale: :en,
  valid_range: nil,
  year_range: nil,
  events: {},
  date_cell_render: nil,
  month_cell_render: nil,
  header_render: nil,
  disabled_date: nil,
  static: nil,
  **html_options
)
  @value = T.let(parse_date(value), T.nilable(Date))
  @default_value = T.let(parse_date(default_value), T.nilable(Date))
  @mode = T.let(normalize_symbol(mode, fallback: :month), Symbol)
  @fullscreen = T.let(fullscreen.nil? ? true : fullscreen, T::Boolean)
  @show_week = T.let(show_week, T::Boolean)
  @locale = T.let(normalize_symbol(locale, fallback: :en), Symbol)
  @valid_range = T.let(normalize_valid_range(valid_range), DateRange)
  @year_range = T.let(year_range, YearRangeInput)
  @events = T.let(normalize_events(events), EventsByDate)
  @date_cell_render = T.let(date_cell_render, DateCellRenderer)
  @month_cell_render = T.let(month_cell_render, MonthCellRenderer)
  @header_render = T.let(header_render, HeaderRenderer)
  @disabled_date = T.let(disabled_date, DisabledDatePredicate)
  @static = T.let(static.nil? ? custom_cell_render? : static, T::Boolean)
  @html_options = T.let(html_options, Types::HtmlAttributes)
  @display_model = T.let(nil, T.nilable(HakumiComponents::Calendar::DisplayModel))

  validate_props!
end

Class Method Details

.extract_controller_locals(params) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/components/hakumi_components/calendar/component.rb', line 51

def self.extract_controller_locals(params)
  value = html_param(params, :value)
  default_value = html_param(params, :default_value)
  mode = symbol_html_param(html_param(params, :mode))
  locale = symbol_html_param(html_param(params, :locale))
  valid_range_input = html_param(params, :valid_range)

  {
    value: value&.to_s,
    default_value: default_value&.to_s,
    mode: mode,
    fullscreen: boolean_html_param(html_param(params, :fullscreen)),
    show_week: boolean_html_param(html_param(params, :show_week)),
    locale: locale,
    valid_range: valid_range_input.is_a?(Array) ? valid_range_input : nil
  }
end

Instance Method Details

#calendar_classesObject



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'app/components/hakumi_components/calendar/component.rb', line 156

def calendar_classes
  component_classes(
    "calendar",
    {
      fullscreen: @fullscreen,
      card: !@fullscreen,
      "mode-month": month_mode?,
      "mode-year": year_mode?,
      "mode-quarter": quarter_mode?,
      "mode-decade": decade_mode?,
      "show-week": @show_week
    },
    @html_options
  )
end

#cell_classes(cell) ⇒ Object



386
387
388
# File 'app/components/hakumi_components/calendar/component.rb', line 386

def cell_classes(cell)
  display_model.cell_classes(cell)
end

#current_dateObject



136
137
138
# File 'app/components/hakumi_components/calendar/component.rb', line 136

def current_date
  @value || @default_value || Date.today
end

#current_monthObject



151
152
153
# File 'app/components/hakumi_components/calendar/component.rb', line 151

def current_month
  current_date.month
end

#current_yearObject



146
147
148
# File 'app/components/hakumi_components/calendar/component.rb', line 146

def current_year
  current_date.year
end

#custom_cell_render?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'app/components/hakumi_components/calendar/component.rb', line 126

def custom_cell_render?
  !@date_cell_render.nil? || !@month_cell_render.nil?
end

#custom_header?Boolean

Returns:

  • (Boolean)


265
266
267
# File 'app/components/hakumi_components/calendar/component.rb', line 265

def custom_header?
  @header_render.is_a?(Proc)
end

#data_attributesObject



184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'app/components/hakumi_components/calendar/component.rb', line 184

def data_attributes
  attrs = T.let({
    controller: "hakumi--calendar",
    "hakumi--calendar-mode-value": @mode,
    "hakumi--calendar-year-value": current_year,
    "hakumi--calendar-month-value": current_month,
    "hakumi--calendar-fullscreen-value": @fullscreen,
    "hakumi--calendar-locale-value": @locale,
    "hakumi--calendar-static-value": @static
  }, Types::DataAttributes)
  attrs["hakumi--calendar-events-value"] = events_to_json if events?
  attrs["hakumi--calendar-valid-range-value"] = valid_range_to_json if @valid_range
  attrs
end

#date_disabled?(date) ⇒ Boolean

Returns:

  • (Boolean)


342
343
344
# File 'app/components/hakumi_components/calendar/component.rb', line 342

def date_disabled?(date)
  display_model.date_disabled?(date)
end

#date_in_valid_range?(date) ⇒ Boolean

Returns:

  • (Boolean)


347
348
349
# File 'app/components/hakumi_components/calendar/component.rb', line 347

def date_in_valid_range?(date)
  display_model.date_in_valid_range?(date)
end

#decade_mode?Boolean

Returns:

  • (Boolean)


245
246
247
# File 'app/components/hakumi_components/calendar/component.rb', line 245

def decade_mode?
  @mode == :decade
end

#decade_range_labelObject



332
333
334
# File 'app/components/hakumi_components/calendar/component.rb', line 332

def decade_range_label
  display_model.decade_range_label
end

#events?Boolean

Returns:

  • (Boolean)


374
375
376
# File 'app/components/hakumi_components/calendar/component.rb', line 374

def events?
  @events.any?
end

#events_for_date(date) ⇒ Object



359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'app/components/hakumi_components/calendar/component.rb', line 359

def events_for_date(date)
  items = @events[date]
  return nil if items.blank?

  safe_join(items.map do |item|
    (:div, class: "hakumi-calendar-event hakumi-calendar-event-#{item.type}") do
      render HakumiComponents::Badge::Component.new(
        status: item.type,
        text: item.content
      )
    end
  end)
end

#events_to_jsonObject



206
207
208
209
210
211
212
213
214
215
216
217
# File 'app/components/hakumi_components/calendar/component.rb', line 206

def events_to_json
  @events.transform_keys(&:iso8601).transform_values do |events|
    events.map do |event|
      {
        id: event.id,
        type: event.type.to_s,
        content: event.content,
        html: render_event_badge(event)
      }
    end
  end.to_json
end

#fullscreen?Boolean

Returns:

  • (Boolean)


250
251
252
# File 'app/components/hakumi_components/calendar/component.rb', line 250

def fullscreen?
  @fullscreen
end

#locale_dataObject



292
293
294
# File 'app/components/hakumi_components/calendar/component.rb', line 292

def locale_data
  LOCALES.fetch(@locale, LOCALES.fetch(:en))
end

#month_cell_classes(entry) ⇒ Object



391
392
393
# File 'app/components/hakumi_components/calendar/component.rb', line 391

def month_cell_classes(entry)
  display_model.month_cell_classes(entry)
end

#month_mode?Boolean

Returns:

  • (Boolean)


230
231
232
# File 'app/components/hakumi_components/calendar/component.rb', line 230

def month_mode?
  @mode == :month
end

#month_namesObject



302
303
304
# File 'app/components/hakumi_components/calendar/component.rb', line 302

def month_names
  display_model.month_names
end

#month_names_shortObject



307
308
309
# File 'app/components/hakumi_components/calendar/component.rb', line 307

def month_names_short
  display_model.month_names_short
end

#months_in_yearObject



317
318
319
# File 'app/components/hakumi_components/calendar/component.rb', line 317

def months_in_year
  display_model.months_in_year
end

#quarter_cell_classes(entry) ⇒ Object



396
397
398
# File 'app/components/hakumi_components/calendar/component.rb', line 396

def quarter_cell_classes(entry)
  display_model.quarter_cell_classes(entry)
end

#quarter_mode?Boolean

Returns:

  • (Boolean)


240
241
242
# File 'app/components/hakumi_components/calendar/component.rb', line 240

def quarter_mode?
  @mode == :quarter
end

#quarters_in_yearObject



322
323
324
# File 'app/components/hakumi_components/calendar/component.rb', line 322

def quarters_in_year
  display_model.quarters_in_year
end

#render_custom_headerObject



285
286
287
288
289
# File 'app/components/hakumi_components/calendar/component.rb', line 285

def render_custom_header
  return nil unless @header_render.is_a?(Proc)

  @header_render.call(current_date, @mode, nil, nil)
end

#render_date_cell(date) ⇒ Object



352
353
354
355
356
# File 'app/components/hakumi_components/calendar/component.rb', line 352

def render_date_cell(date)
  return @date_cell_render.call(date) if @date_cell_render

  events_for_date(date)
end

#render_event_badge(event) ⇒ Object



220
221
222
223
224
225
226
227
# File 'app/components/hakumi_components/calendar/component.rb', line 220

def render_event_badge(event)
  helpers.render(
    HakumiComponents::Badge::Component.new(
      status: event.type,
      text: event.content
    )
  ).to_s
end

#render_month_cell(month) ⇒ Object



379
380
381
382
383
# File 'app/components/hakumi_components/calendar/component.rb', line 379

def render_month_cell(month)
  return nil unless @month_cell_render

  @month_cell_render.call(month)
end

#selected_valueObject



141
142
143
# File 'app/components/hakumi_components/calendar/component.rb', line 141

def selected_value
  @value || @default_value
end

#show_header?Boolean

Returns:

  • (Boolean)


260
261
262
# File 'app/components/hakumi_components/calendar/component.rb', line 260

def show_header?
  @header_render != false
end

#show_mode_switch?Boolean

Returns:

  • (Boolean)


280
281
282
# File 'app/components/hakumi_components/calendar/component.rb', line 280

def show_mode_switch?
  fullscreen? && !static?
end

#show_month_select?Boolean

Returns:

  • (Boolean)


275
276
277
# File 'app/components/hakumi_components/calendar/component.rb', line 275

def show_month_select?
  month_mode?
end

#show_week?Boolean

Returns:

  • (Boolean)


255
256
257
# File 'app/components/hakumi_components/calendar/component.rb', line 255

def show_week?
  @show_week
end

#show_year_select?Boolean

Returns:

  • (Boolean)


270
271
272
# File 'app/components/hakumi_components/calendar/component.rb', line 270

def show_year_select?
  month_mode? || year_mode? || quarter_mode?
end

#static?Boolean

Returns:

  • (Boolean)


131
132
133
# File 'app/components/hakumi_components/calendar/component.rb', line 131

def static?
  @static
end

#valid_range_to_jsonObject



200
201
202
203
# File 'app/components/hakumi_components/calendar/component.rb', line 200

def valid_range_to_json
  start_date, end_date = T.must(@valid_range)
  [ start_date&.iso8601, end_date&.iso8601 ].to_json
end

#week_number(date) ⇒ Object



406
407
408
# File 'app/components/hakumi_components/calendar/component.rb', line 406

def week_number(date)
  display_model.week_number(date)
end

#weekday_namesObject



297
298
299
# File 'app/components/hakumi_components/calendar/component.rb', line 297

def weekday_names
  display_model.weekday_names
end

#weeks_in_monthObject



312
313
314
# File 'app/components/hakumi_components/calendar/component.rb', line 312

def weeks_in_month
  display_model.weeks_in_month
end

#wrapper_attributesObject



173
174
175
176
177
178
179
180
181
# File 'app/components/hakumi_components/calendar/component.rb', line 173

def wrapper_attributes
  merge_attributes(
    {
      class: calendar_classes,
      data: data_attributes
    },
    @html_options.except(:class)
  )
end

#year_cell_classes(entry) ⇒ Object



401
402
403
# File 'app/components/hakumi_components/calendar/component.rb', line 401

def year_cell_classes(entry)
  display_model.year_cell_classes(entry)
end

#year_mode?Boolean

Returns:

  • (Boolean)


235
236
237
# File 'app/components/hakumi_components/calendar/component.rb', line 235

def year_mode?
  @mode == :year
end

#years_in_decadeObject



327
328
329
# File 'app/components/hakumi_components/calendar/component.rb', line 327

def years_in_decade
  display_model.years_in_decade
end

#years_rangeObject



337
338
339
# File 'app/components/hakumi_components/calendar/component.rb', line 337

def years_range
  display_model.years_range
end