Class: Www::FloorHeatingCalculatorComponent
- Inherits:
-
ApplicationComponent
- Object
- ViewComponent::Base
- ApplicationComponent
- Www::FloorHeatingCalculatorComponent
- Includes:
- ActionView::Helpers::TagHelper, ActionView::Helpers::UrlHelper
- Defined in:
- app/components/www/floor_heating_calculator_component.rb
Overview
Floor Heating Operating Cost Calculator
Calculates estimated operating costs based on square footage, usage hours, and electricity rates
Usage:
<%# Basic usage %>
<%= render Www::FloorHeatingCalculatorComponent.new %>
<%# Spanish locale %>
<%= render Www::FloorHeatingCalculatorComponent.new(locale: :es) %>
<%# Custom defaults %>
<%= render Www::FloorHeatingCalculatorComponent.new(default_sqft: 100, default_hours: 8) %>
<%# With integrated SmartPlan CTA %>
<%= render Www::FloorHeatingCalculatorComponent.new(layout: :horizontal,
smartplan: { product_type: :floor_heating, area_name: 'laminate floor', project_link: '/showcases' }
) %>
Constant Summary collapse
- IMAGEKIT_BASE =
ImageKit base URL for product images
'https://ik.warmlyyours.com'- TRANSLATIONS =
Translations.
{ en: { title: 'Operating Cost Calculator for Floor Heating', location: 'Location', location_description: 'Your location is used to find the energy rate in your area.', my_location: 'My Location', zip_postal_code: 'Zip/Postal Code', cents_per_kwh: 'Rate', current_rate: 'Current rate', square_footage: 'Square Footage', sq_ft: 'sq. ft.', usage: 'Usage', estimated_cost: 'Estimated Cost', per_hour: 'per hour', per_day: 'per day', per_month: 'per month', per_year: 'per year', daily_usage: 'Daily Usage', hours_day: 'hours/day', hour: 'hour', hours: 'hours', surface_type: 'What surface are you heating?', room_size: 'Room Size', energy_rates: 'Energy Rates', energy_rates_description: 'Your location helps us find the average energy rate in your area to ensure our calculation is accurate.', consider_usage: 'Consider your room type and if this will be a supplemental or primary heat source.', bathroom: 'Bathroom', kitchen: 'Kitchen', basement: 'Basement', custom: 'Square Footage', calculator_settings: 'Calculator Settings', rae_quote: "Most homeowners are surprised how affordable radiant floor heating is to operate—often just pennies a day for a bathroom. It's the kind of everyday luxury that pays for itself in comfort!" }, es: { title: 'Calculadora de Costos Operativos para Calefacción de Piso', location: 'Ubicación', location_description: 'Tu ubicación nos ayuda a encontrar la tasa de energía promedio en el área.', my_location: 'Mi ubicación actual', zip_postal_code: 'Código Postal', cents_per_kwh: 'Tarifa', current_rate: 'Tasa actual', square_footage: 'Pies Cuadrados', sq_ft: 'pies²', usage: 'Uso diario', estimated_cost: 'Costo estimado', per_hour: 'por hora', per_day: 'por día', per_month: 'por mes', per_year: 'por año', daily_usage: 'Uso diario', hours_day: 'horas por día', hour: 'hora', hours: 'horas', surface_type: '¿Qué superficie está calentando?', room_size: 'Tamaño de la Habitación', energy_rates: 'Tarifas de energía', energy_rates_description: 'Tu ubicación nos ayuda a encontrar la tasa de energía promedio en el área.', consider_usage: 'Considera tu tipo de habitación y si esta será una fuente de calor suplementaria o primaria.', bathroom: 'Baño', kitchen: 'Cocina', basement: 'Sótano', custom: 'Pies Cuadrados', calculator_settings: 'Configuración del Calculador', rae_quote: 'La mayoría de los propietarios se sorprenden de lo económico que es operar la calefacción por piso radiante—a menudo solo centavos al día para un baño. ¡Es el tipo de lujo cotidiano que se paga solo en comodidad!' } }.freeze
- SURFACE_TYPES =
Surface types map to heating systems
Surface type drives the product recommendation [ { id: 'tile_stone', name: 'Tile or Stone', product: 'TempZone™', wattage: 15 }, { id: 'laminate_floating', name: 'Laminate, Floating Wood, or Carpet', product: 'Environ™', wattage: 12 }, { id: 'concrete_embedded', name: 'Concrete Slab (New Pour)', product: 'Embedded Slab Heat Cable or Mat', wattage: 20 } ].freeze
- ROOM_TYPES =
Room types with typical square footage for dropdown
[ { id: 'bathroom', name: 'Bathroom', sqft: 35 }, { id: 'master_bath', name: 'Master Bathroom', sqft: 80 }, { id: 'powder_room', name: 'Powder Room', sqft: 25 }, { id: 'kitchen', name: 'Kitchen', sqft: 150 }, { id: 'entryway', name: 'Entryway/Foyer', sqft: 40 }, { id: 'mudroom', name: 'Mudroom', sqft: 50 }, { id: 'laundry', name: 'Laundry Room', sqft: 60 }, { id: 'bedroom', name: 'Bedroom', sqft: 150 }, { id: 'master_bed', name: 'Master Bedroom', sqft: 250 }, { id: 'living_room', name: 'Living Room', sqft: 300 }, { id: 'family_room', name: 'Family Room', sqft: 350 }, { id: 'dining_room', name: 'Dining Room', sqft: 180 }, { id: 'basement', name: 'Basement', sqft: 400 }, { id: 'sunroom', name: 'Sunroom', sqft: 200 }, { id: 'garage', name: 'Garage', sqft: 400 }, { id: 'office', name: 'Home Office', sqft: 120 }, { id: 'custom', name: 'Custom Size', sqft: nil } ].freeze
- DEFAULT_KWH_CENTS =
Default electricity rate in cents/kWh (US average ~16.26 cents)
16.26
Instance Attribute Summary collapse
-
#sp_area_name ⇒ String
readonly
Display name of the heated area (e.g. 'laminate floor').
-
#sp_project_link ⇒ Object
readonly
Returns the value of attribute sp_project_link.
Instance Method Summary collapse
-
#calculate_default_kwh ⇒ Float
Default electricity rate in cents per kWh for the component locale.
-
#currency_symbol ⇒ ActiveSupport::SafeBuffer
Currency symbol wrapped in a superscript-style span.
-
#horizontal? ⇒ Boolean
Whether the component renders the side-by-side layout.
-
#initial_daily_cost ⇒ Float
Initial daily cost for the configured defaults.
-
#initial_hourly_cost ⇒ Float
Initial hourly cost for server-side rendering.
-
#initial_monthly_cost ⇒ Float
Initial monthly cost (30 days of the daily cost).
-
#initialize(locale: :en, default_sqft: 35, default_hours: 4, default_kwh: nil, default_wattage: nil, default_surface_type: 'tile_stone', default_room_type: 'bathroom', layout: :vertical, smartplan: nil) ⇒ FloorHeatingCalculatorComponent
constructor
A new instance of FloorHeatingCalculatorComponent.
-
#room_types ⇒ Array<Hash>
Room types for the dropdown.
-
#smartplan? ⇒ Boolean
Whether a SmartPlan CTA section was configured.
-
#sp_app_type ⇒ String?
SmartPlan application type.
-
#sp_carousel_options ⇒ Hash
Splide options for the SmartPlan slide carousel.
-
#sp_icon ⇒ String?
SmartPlan icon name.
-
#sp_link ⇒ String?
SmartPlan request link URL.
-
#sp_rae_avatar ⇒ String?
Rae avatar image URL.
-
#sp_rae_quote ⇒ String?
Rae testimonial quote.
-
#sp_slides ⇒ Array<Hash>
SmartPlan carousel slide configs.
-
#sp_title ⇒ String?
SmartPlan section title.
-
#surface_types ⇒ Array<Hash>
Surface types for the dropdown.
-
#t(key) ⇒ String
Translate a key in the component locale, falling back to English.
-
#wattage_for_surface(surface_id) ⇒ Integer
Wattage per square foot for a surface type.
Methods inherited from ApplicationComponent
#cms_link, #fetch_or_fallback, #image_asset_tag, #image_tag, #number_to_currency, #number_with_delimiter, #post_path, #post_url, #strip_tags
Constructor Details
#initialize(locale: :en, default_sqft: 35, default_hours: 4, default_kwh: nil, default_wattage: nil, default_surface_type: 'tile_stone', default_room_type: 'bathroom', layout: :vertical, smartplan: nil) ⇒ FloorHeatingCalculatorComponent
Returns a new instance of FloorHeatingCalculatorComponent.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 139 def initialize(locale: :en, default_sqft: 35, default_hours: 4, default_kwh: nil, default_wattage: nil, default_surface_type: 'tile_stone', default_room_type: 'bathroom', layout: :vertical, smartplan: nil) super() @locale = locale.to_sym @default_surface_type = default_surface_type.to_s @default_room_type = default_room_type.to_s @default_sqft = default_sqft @default_hours = default_hours @default_kwh = default_kwh || calculate_default_kwh @default_wattage = default_wattage || wattage_for_surface(@default_surface_type) @layout = layout.to_sym @smartplan = smartplan resolve_smartplan_config if @smartplan end |
Instance Attribute Details
#sp_area_name ⇒ String (readonly)
Returns display name of the heated area (e.g. 'laminate floor').
185 186 187 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 185 def sp_area_name @sp_area_name end |
#sp_project_link ⇒ Object (readonly)
Returns the value of attribute sp_project_link.
185 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 185 attr_reader :sp_area_name, :sp_project_link |
Instance Method Details
#calculate_default_kwh ⇒ Float
Default electricity rate in cents per kWh for the component locale.
204 205 206 207 208 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 204 def calculate_default_kwh # ElectricityRate returns rate in dollars, we need cents rate = ElectricityRate.get_average_rate_for_locale(@locale) rate ? (rate * 100).round(2) : DEFAULT_KWH_CENTS end |
#currency_symbol ⇒ ActiveSupport::SafeBuffer
Currency symbol wrapped in a superscript-style span.
249 250 251 252 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 249 def currency_symbol symbol = helpers.canada? ? 'C$' : '$' %(<span style="font-size:.55em;vertical-align:baseline;position:relative;top:-.45em;font-weight:500;color:#6c757d">#{symbol}</span>).html_safe end |
#horizontal? ⇒ Boolean
Whether the component renders the side-by-side layout.
157 158 159 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 157 def horizontal? @layout == :horizontal end |
#initial_daily_cost ⇒ Float
Initial daily cost for the configured defaults.
237 238 239 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 237 def initial_daily_cost calculate_cost(@default_sqft, @default_hours, @default_kwh, @default_wattage) end |
#initial_hourly_cost ⇒ Float
Initial hourly cost for server-side rendering.
231 232 233 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 231 def initial_hourly_cost initial_daily_cost / @default_hours end |
#initial_monthly_cost ⇒ Float
Initial monthly cost (30 days of the daily cost).
243 244 245 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 243 def initial_monthly_cost initial_daily_cost * 30 end |
#room_types ⇒ Array<Hash>
Room types for the dropdown.
225 226 227 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 225 def room_types ROOM_TYPES.dup end |
#smartplan? ⇒ Boolean
Whether a SmartPlan CTA section was configured.
163 164 165 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 163 def smartplan? @smartplan.present? end |
#sp_app_type ⇒ String?
Returns SmartPlan application type.
172 173 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 172 def sp_app_type = @sp_config&.dig(:application_type) # @return [String, nil] SmartPlan request link URL |
#sp_carousel_options ⇒ Hash
Splide options for the SmartPlan slide carousel.
189 190 191 192 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 189 def { type: 'fade', perPage: 1, perMove: 1, arrows: true, pagination: true, autoplay: true, interval: 4000, pauseOnHover: true, rewind: true, speed: 600 } end |
#sp_icon ⇒ String?
Returns SmartPlan icon name.
170 171 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 170 def sp_icon = @sp_config&.dig(:icon) # @return [String, nil] SmartPlan application type |
#sp_link ⇒ String?
Returns SmartPlan request link URL.
174 175 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 174 def sp_link = @sp_config&.dig(:smartplan_link) # @return [String, nil] Rae avatar image URL |
#sp_rae_avatar ⇒ String?
Returns Rae avatar image URL.
176 177 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 176 def sp_rae_avatar = @sp_config&.dig(:rae_avatar) # @return [String, nil] Rae testimonial quote |
#sp_rae_quote ⇒ String?
Returns Rae testimonial quote.
178 179 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 178 def sp_rae_quote = @sp_config&.dig(:rae_quote) # @return [Array<Hash>] SmartPlan carousel slide configs |
#sp_slides ⇒ Array<Hash>
Returns SmartPlan carousel slide configs.
180 181 182 183 184 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 180 def = @sp_config&.dig(:carousel_slides) || [] # @!attribute [r] sp_area_name # @return [String] display name of the heated area (e.g. 'laminate floor') # @!attribute [r] sp_project_link # @return [String, nil] URL of a related project showcase |
#sp_title ⇒ String?
Returns SmartPlan section title.
168 169 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 168 def sp_title = @sp_config&.dig(:title) # @return [String, nil] SmartPlan icon name |
#surface_types ⇒ Array<Hash>
Surface types for the dropdown.
219 220 221 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 219 def surface_types SURFACE_TYPES.dup end |
#t(key) ⇒ String
Translate a key in the component locale, falling back to English.
213 214 215 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 213 def t(key) TRANSLATIONS[@locale][key] || TRANSLATIONS[:en][key] || key.to_s.humanize end |
#wattage_for_surface(surface_id) ⇒ Integer
Wattage per square foot for a surface type.
197 198 199 200 |
# File 'app/components/www/floor_heating_calculator_component.rb', line 197 def wattage_for_surface(surface_id) match = SURFACE_TYPES.find { |s| s[:id] == surface_id } match ? match[:wattage] : 15 end |