mirror of
https://github.com/System-End/theseus.git
synced 2026-04-20 00:35:18 +00:00
232 lines
No EOL
6.1 KiB
Text
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> |