theseus/app/views/batches/map_fields.html.erb
2025-05-31 23:25:41 -04:00

232 lines
No EOL
6.1 KiB
Text

<h1>Map CSV Fields to Address Fields</h1>
<div class="mapping-form">
<%= form_with(model: @batch, url: set_mapping_batch_path(@batch), method: :post) do |f| %>
<%# Define default_mapping outside of the loop %>
<%
default_mapping = {
# loops defaults
'email' => 'email',
'firstName' => 'first_name',
'lastName' => 'last_name',
'addressLine1' => 'line_1',
'addressLine2' => 'line_2',
'addressCity' => 'city',
'addressState' => 'state',
'addressZipCode' => 'postal_code',
'addressCountry' => 'country',
# hcb promotions
'Address (zip/postal code)' => 'postal_code',
'Address (city)' => 'city',
'Address (state/province)' => 'state',
'Address (country)' => 'country',
'Address (line 1)' => 'line_1',
'Address (line 2)' => 'line_2',
'Recipient Name' => 'first_name',
'Login Email' => 'email',
}
%>
<div class="mapping-container">
<% @csv_headers.each do |header| %>
<div class="mapping-row">
<div class="csv-field">
<div class="field-name"><%= header %></div>
<div class="field-preview">
<% if @csv_preview.first %>
<%= @csv_preview.first[@csv_headers.index(header)] %>
<% end %>
</div>
</div>
<div class="field-mapping">
<%
default_value = default_mapping[header]
%>
<%= select_tag "mapping[#{header}]",
options_for_select(@address_fields, default_value),
prompt: "Select address field...",
class: "form-select",
data: { csv_field: header } %>
</div>
</div>
<% end %>
</div>
<%# Add hidden fields for required fields if they're not already mapped %>
<%
mapped_fields = @csv_headers.map { |header| default_mapping[header] }.compact
missing_required = BatchesController::REQUIRED_FIELDS - mapped_fields
if missing_required.any?
# Find a suitable CSV header for each missing required field
missing_required.each do |field|
# Try to find a suitable header based on field name
suitable_header = case field
when 'first_name'
@csv_headers.find { |h| h.downcase.include?('name') || h.downcase.include?('recipient') }
when 'state'
@csv_headers.find { |h| h.downcase.include?('state') || h.downcase.include?('province') }
when 'line_1'
@csv_headers.find { |h| h.downcase.include?('address') || h.downcase.include?('street') }
when 'city'
@csv_headers.find { |h| h.downcase.include?('city') || h.downcase.include?('town') }
when 'postal_code'
@csv_headers.find { |h| h.downcase.include?('zip') || h.downcase.include?('postal') || h.downcase.include?('code') }
when 'country'
@csv_headers.find { |h| h.downcase.include?('country') || h.downcase.include?('nation') }
end
if suitable_header
# Add a hidden field to map this header to the required field
hidden_field_tag "mapping[#{suitable_header}]", field
end
end
end
%>
<div class="actions">
<%= f.submit "Save Mapping", class: "btn btn-primary" %>
</div>
<% end %>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Get all select elements
const selects = document.querySelectorAll('.form-select');
// Function to update the disabled state of options
function updateSelects() {
// Get all currently selected values (excluding empty selections)
const selectedValues = Array.from(selects)
.map(select => select.value)
.filter(value => value !== '');
// For each select element
selects.forEach(select => {
const currentValue = select.value;
// First, enable all options
for (let i = 0; i < select.options.length; i++) {
select.options[i].disabled = false;
}
// Then disable options that are selected in other dropdowns
selectedValues.forEach(value => {
if (value !== currentValue) {
// Find the option with this value in the current select
for (let i = 0; i < select.options.length; i++) {
if (select.options[i].value === value) {
select.options[i].disabled = true;
break;
}
}
}
});
});
}
// Run the update function immediately
updateSelects();
// Add change event listeners to all selects
selects.forEach(select => {
select.addEventListener('change', updateSelects);
});
});
</script>
<style>
.mapping-container {
display: grid;
gap: 1rem;
margin-bottom: 2rem;
}
.mapping-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
align-items: center;
}
.csv-field {
padding: 0.75rem;
background: #2d2d2d;
border-radius: 4px;
border: 1px solid #404040;
}
.field-name {
font-weight: 500;
margin-bottom: 0.25rem;
color: #e0e0e0;
}
.field-preview {
font-size: 0.875rem;
color: #a0a0a0;
}
.field-mapping {
padding: 0.5rem;
}
.form-select {
width: 100%;
padding: 0.375rem;
background: #1a1a1a;
border: 1px solid #404040;
border-radius: 4px;
color: #e0e0e0;
}
.form-select option {
background: #2d2d2d;
color: #e0e0e0;
}
.form-select option:disabled {
color: #666;
background-color: #1a1a1a;
}
.form-select:focus {
outline: none;
border-color: #4a9eff;
box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.2);
}
.actions {
display: flex;
justify-content: flex-end;
margin-top: 1rem;
}
.btn-primary {
padding: 0.5rem 1rem;
background: #4a9eff;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s;
}
.btn-primary:hover {
background: #357abd;
}
.alert {
padding: 1rem;
margin-bottom: 1rem;
border-radius: 4px;
}
.alert-danger {
background-color: #2d1a1a;
border: 1px solid #4a1a1a;
color: #ff6b6b;
}
</style>