Skip to content

Commit

Permalink
close #2174 dynamic kyc fields
Browse files Browse the repository at this point in the history
  • Loading branch information
panhachom committed Dec 19, 2024
1 parent 1d40c05 commit 4d3c2a8
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 22 deletions.
13 changes: 12 additions & 1 deletion app/controllers/spree/admin/kyc_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,19 @@ class KycController < Spree::Admin::ResourceController
# @overrided
def permitted_resource_params
kyc_result = calculate_kyc_value(params[:product])
params.require(:product).permit(:allowed_upload_later, dynamic_kyc: %i[key label attype]).merge(kyc: kyc_result)
end

def remove_field
key = params[:key]

@product.dynamic_kyc.reject! { |field| field['key'] == key }

params.require(:product).permit(:allowed_upload_later).merge(kyc: kyc_result)
if @product.save
render json: { success: true }
else
render json: { success: false, errors: @product.errors.full_messages }, status: :unprocessable_entity
end
end

def flash_error
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/spree/api/v2/storefront/guests_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def guest_params
:address,
:other_organization,
:expectation,
:upload_later
:upload_later,
:dynamic_field
)
end
end
Expand Down
14 changes: 14 additions & 0 deletions app/views/spree/admin/kyc/_dynamic_kyc_fields.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div class="d-flex align-items-center mb-2">

<input type="text" class="form-control mx-1 my-1" name="product[dynamic_kyc][][key]" value="<%= key %>" placeholder="Key">
<input type="text" class="form-control mx-1 my-1" name="product[dynamic_kyc][][label]" value="<%= label %>" placeholder="Label">
<select class="form-control mx-1 my-1" name="product[dynamic_kyc][][attype]">
<option value="string" <%= 'selected' if attype == 'string' %>>String</option>
<option value="integer" <%= 'selected' if attype == 'integer' %>>Integer</option>
<option value="float" <%= 'selected' if attype == 'float' %>>Float</option>
<option value="array" <%= 'selected' if attype == 'array' %>>Array</option>
<option value="datetime" <%= 'selected' if attype == 'datetime' %>>Datetime</option>
<option value="date" <%= 'selected' if attype == 'date' %>>Date</option>
</select>
<button type="button" class="btn btn-danger remove-field btn-sm">Remove</button>
</div>
90 changes: 90 additions & 0 deletions app/views/spree/admin/kyc/_dynamic_kyc_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<div class="d-flex align-items-center justify-content-between">
<h5 class="mx-1">Dynamic KYC Fields</h5>
<button type="button" id="add-dynamic-kyc-field" class="btn btn-primary mx-1">Add New Field</button>
</div>

<div id="dynamic-kyc-fields" class="my-2">
<div class="form-group">
<div class="d-flex flex-column">
<% if @product.dynamic_kyc.empty? %>
<%= render partial: 'dynamic_kyc_fields', locals: { key: '', label: '', attype: '' } %>
<% else %>
<% @product.dynamic_kyc.each_with_index do |item, index| %>
<%= render partial: 'dynamic_kyc_fields', locals: { key: item['key'], label: item['label'], attype: item['attype'] } %>
<% end %>
<% end %>
</div>
</div>
</div>



<script>

document.addEventListener('DOMContentLoaded', () => {
const $addFieldButton = document.getElementById('add-dynamic-kyc-field');
const $fieldsContainer = document.getElementById('dynamic-kyc-fields');
const $form = document.querySelector('form');

const generateNewFieldHTML = () => `
<div class="d-flex align-items-center mb-2">
<input type="text" class="form-control mx-1 my-1" name="product[dynamic_kyc][][key]" placeholder="Key">
<input type="text" class="form-control mx-1 my-1" name="product[dynamic_kyc][][label]" placeholder="Label">
<select class="form-control mx-1 my-1" name="product[dynamic_kyc][][attype]">
<option value="string">String</option>
<option value="integer">Integer</option>
<option value="float">Float</option>
<option value="array">Array</option>
<option value="datetime">Datetime</option>
<option value="date">Date</option>
</select>
<button type="button" class="btn btn-danger remove-field btn-sm">Remove</button>
</div>
`;

const getProductSlug = () => "<%= @product.slug %>";

const removeKycField = (key) => {
return fetch(`/admin/products/${getProductSlug()}/remove_field`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
},
body: JSON.stringify({ key })
});
};

const handleAddFieldClick = () => {
$fieldsContainer.querySelector('.form-group .d-flex').insertAdjacentHTML('beforeend', generateNewFieldHTML());
};

const handleRemoveFieldClick = (event) => {
if (event.target.classList.contains('remove-field')) {
const $fieldElement = event.target.closest('.d-flex');
const key = $fieldElement.querySelector('input[name*="[key]"]').value;

removeKycField(key)
.then(response => {
if (response.ok) $fieldElement.remove();
else alert('Failed to remove the field');
});
}
};

const handleSubmit = (event) => {
$fieldsContainer.querySelectorAll('.d-flex').forEach(field => {
const $keyField = field.querySelector('input[name*="[key]"]');
const $labelField = field.querySelector('input[name*="[label]"]');
if (!$keyField.value.trim() && !$labelField.value.trim()) field.remove();
});
};

$addFieldButton.addEventListener('click', handleAddFieldClick);
$fieldsContainer.addEventListener('click', handleRemoveFieldClick);
$form.addEventListener('submit', handleSubmit);
});



</script>
41 changes: 21 additions & 20 deletions app/views/spree/admin/kyc/edit.html.erb
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
<%= render partial: 'spree/admin/shared/product_tabs', locals: { current: :kyc } %>

<% content_for :page_actions do %>
<%= button_link_to Spree.t(:edit_icons),
admin_vectors_option_values_url,
{ icon: 'spree-icon.svg', id: 'admin-option-values-icons-index' }
%>
<% end %>

<%= form_with model: @product, url: update_kyc_admin_product_path(@product), method: :put do |form| %>
<small class="form-text text-muted">
<%= raw I18n.t('kyc.allowed_upload_later') %>
</small>
<div class="d-flex flex-column my-4">
<div class="form-check form-check-inline">
<%= form.field_container :allowed_upload_later do %>
<%= form.check_box :allowed_upload_later, class: 'form-check-input', checked: form.object.allowed_upload_later? %>
<%= form.label :allowed_upload_later, Spree.t(:allowed_upload_later), class: 'form-check-label' %>
<%= form.error_message_on :allowed_upload_later, class: 'text-danger' %>
<% end %>
</div>
<small class="form-text text-muted">
<%= raw I18n.t('kyc.allowed_upload_later') %>
</small>
<div class="d-flex flex-column my-4">
<div class="form-check form-check-inline">
<%= form.field_container :allowed_upload_later do %>
<%= form.check_box :allowed_upload_later, class: 'form-check-input', checked: form.object.allowed_upload_later? %>
<%= form.label :allowed_upload_later, Spree.t(:allowed_upload_later), class: 'form-check-label' %>
<%= form.error_message_on :allowed_upload_later, class: 'text-danger' %>
<% end %>
</div>
</div>
<small class="form-text text-muted">
<%= raw I18n.t('kyc.note') %>
</small>
<%= render partial: 'form', locals: { form: form } %>
<%= render partial: 'dynamic_kyc_form' %>

<small class="form-text text-muted">
<%= raw I18n.t('kyc.note') %>
</small>
<%= render partial: 'form', locals: { form: form } %>
<div class='form-actions' data-hook='buttons'>
<%= button Spree.t('actions.update'), 'save.svg', 'submit', { class: 'btn-success', data: { disable_with: "#{ Spree.t(:saving) }..." }} %>
</div>
<div class="form-actions" data-hook="buttons">
<%= button Spree.t('actions.update'), 'save.svg', 'submit', { class: 'btn-success', data: { disable_with: "#{ Spree.t(:saving) }..." }} %>
</div>
<% end %>


1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
delete 'remove_metafield', to: 'metafields#remove_metafield'
get 'edit_kyc', to: 'kyc#edit'
put 'update_kyc', to: 'kyc#update'
delete 'remove_field', to: 'kyc#remove_field'
end

resources :variant_guest_card_classes
Expand Down
7 changes: 7 additions & 0 deletions db/migrate/20241219025924_add_dynamic_kyc_to_spree_product.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddDynamicKycToSpreeProduct < ActiveRecord::Migration[7.0]
def change
unless column_exists?(:spree_products, :dynamic_kyc)
add_column :spree_products, :dynamic_kyc, :jsonb, default: {}
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddDynamicFieldToSpreeCmCommissionerGuest < ActiveRecord::Migration[7.0]
def change
unless column_exists?(:cm_guests, :dynamic_field)
add_column :cm_guests, :dynamic_field, :jsonb, default: {}
end
end
end

0 comments on commit 4d3c2a8

Please sign in to comment.