hoesman LiteCart Fan Fra Croatia Member since jun. 2024 hoesman 11 apr. 2025 17:59 How would I easiest make the required Customer Details change based on selected Shipping module? Like if a local pickup is selected there is only Name, Email and Phone inputs or only those become required, I guess I would use update() to trigger something in box_checkout_customer.inc?
tim Founder Fra Sweden Member since maj 2013 tim 11 apr. 2025 23:43 There are two validations taking place. One is for the customer details before storing them. https://github.com/litecart/litecart/blob/dev/public_html/pages/ajax/checkout_customer.inc.php#L34-L54 The other is before we are creating an order. https://github.com/litecart/litecart/blob/dev/public_html/includes/entities/ent_order.inc.php#L569-L644 During the first part we have a "hen and the egg" dilemma. We are collecting customer details for passing them to shipping and payment. Meaning you don't really have a choice of shipping to rely on at this early stage.
hoesman LiteCart Fan Fra Croatia Member since jun. 2024 hoesman 12 apr. 2025 20:36 So what you are saying is its not really possible, maybe another approach, selecting a shipping module say local pickup, or one which doesnt require as much customer details just fills the customer details with "-" ?
tim Founder Fra Sweden Member since maj 2013 tim 12 apr. 2025 23:37 I think you can remove all validations in checkout_customer, then use a condition for ent_order that checks if ($this->data['shipping_option']['id'] == 'sm_module:option').
jackmaessen LiteCart Fan Fra Netherlands Member since dec. 2022 jackmaessen 13 apr. 2025 14:13 possible solution: file: includes/templates/default.catalog/views/box_checkout_shipping.inc.php At the very end add this js: <script> $("label.option").on('click', function(e) { // this is the label with class option e.preventDefault(); var url = '?shipping-method=' + $(this).find('input').val(); // add string to url like: ?shipping-method=sm_pickup:pickup window.location = url; }); </script> file: includes/templates/default.catalog/pages/checkout.inc.php Add this at the very top of the file: <?php if( !empty($_GET['shipping-method']) && $_GET['shipping-method'] == 'sm_pickup:pickup') { // read $_GET from url; local pickup is chosen $_SESSION["local-pickup"] = true; // create a session } else { unset($_SESSION['local-pickup']); // if not sm_pickup:pickup in url; unset the session for local-pickup } ?> Now the client side validation: file: includes/templates/default.catalog/views/box_checkout_customer.inc.php Check the fields which are required and you dont want them to be required when local pickup e.g. <div class="row"> <div class="form-group col-sm-6"> <label><?php echo language::translate('title_address1', 'Address 1'); ?></label> <?php if(!isset($_SESSION["local-pickup"])) { echo functions::form_draw_text_field('address1', true, 'required'); } else { echo functions::form_draw_text_field('address1', true); // delete required } ?> </div> Finally the server-side validation: File: includes/entities/ent_order.inc.php Look for public function validate($shipping = null, $payment = null) { Below add the session check public function validate($shipping = null, $payment = null) { // check if is a local-pickup if(isset($_SESSION["local-pickup"])) { $localPickup = true; } else { $localPickup = false; } and later in // Validate customer details try { ... you can bypass the validation: try { if (empty($this->data['customer']['firstname'])) throw new Exception(language::translate('error_missing_firstname', 'You must enter a first name.')); if (empty($this->data['customer']['lastname'])) throw new Exception(language::translate('error_missing_lastname', 'You must enter a last name.')); if (!$localPickup && empty($this->data['customer']['address1'])) throw new Exception(language::translate('error_missing_address1', 'You must enter an address.')); if (!$localPickup && empty($this->data['customer']['city'])) throw new Exception(language::translate('error_missing_city', 'You must enter a city.')); ...
hoesman LiteCart Fan Fra Croatia Member since jun. 2024 hoesman 13 apr. 2025 15:51 Thanks for detailed instructions, that could be a possible solution I may try next, however something with less change I added did this in https://github.com/litecart/litecart/blob/dev/public_html/includes/templates/default.catalog/pages/checkout.inc.php#L363 // Check if the selected shipping option is sm_pickup var isPickup = $(this).find('input[name="shipping[option_id]"]').val() === 'sm_pickup:pickup'; var fields = { firstname: $('input[name="firstname"]'), lastname: $('input[name="lastname"]'), address1: $('input[name="address1"]'), city: $('input[name="city"]'), postcode: $('input[name="postcode"]') }; var isPickupMode = !isPickup && (fields.firstname.val() === '-' || fields.lastname.val() === '-' || fields.address1.val() === '-' || fields.city.val() === '-'); $.each(fields, function(key, field) { if (!field.length) return; field.prop('disabled', false); var val = field.val(); if (isPickup && !val) { field.val(key === 'postcode' ? '10000' : '-'); } else if (!isPickup && (val === '-' || (key === 'postcode' && val === '10000' && isPickupMode))) { field.val(''); } }); var customerData = ($('#box-checkout-customer').length ? $('#box-checkout-customer :input') : $('input[name="firstname"]').closest('form :input')).serialize(); queueUpdateTask('customer', customerData, true); Seems to work fine, keeps real data if entered and if pickup option and no data adds "-" to the fields and "10000" to postcode to pass validation and leaves email and phone, any issues I am missing here?
jackmaessen LiteCart Fan Fra Netherlands Member since dec. 2022 jackmaessen 13 apr. 2025 22:22 Yes this also works fine. Personally, it's not my favorite to place hyphens and postal code 10000 to bypass the validation. I shortened the code a bit: File: includes/templates/default.catalog/pages/checkout.inc.php $('#box-checkout .shipping.wrapper').on('click', '.option:not(.active):not(.disabled)', function(){ $('#box-checkout-shipping .option').removeClass('active'); $(this).find('input[name="shipping[option_id]"]').prop('checked', true).trigger('change'); $(this).addClass('active'); $('#box-checkout-shipping .option.active .fields :input').prop('disabled', false); $('#box-checkout-shipping .option:not(.active) .fields :input').prop('disabled', true); /************************ADDED*******************************************/ var selectedOption = $(this).find('input[name="shipping[option_id]"]').val(); $.ajax({ url: '<?php echo document::ilink('ajax/checkout_customer'); ?>', type: 'post', cache: true, async: true, data: { selectedOption: selectedOption }, dataType: 'json', success: function(data) { if(data.required == 0) { $('input[name="address1"]').removeAttr('required'); // remove required } else { $('input[name="address1"]').prop('required',true); // add required } } }); /******************************************************************/ var data = $('#box-checkout-shipping .option.active :input').serialize(); queueUpdateTask('shipping', data, false); queueUpdateTask('payment', true, true); queueUpdateTask('summary', null, true); }); File: pages/ajax/checkoutcustomer.inc.php /************ADDED**************/ // check shipping option = local pickup if(isset($_POST['selectedOption'])) { $result = []; $selectedOption = $_POST['selectedOption']; if($selectedOption == 'sm_pickup:pickup') { $_SESSION["local-pickup"] = true; $result['required'] = 0; // send back for skipping required from inputs } else { unset($_SESSION['local-pickup']); $result['required'] = 1; } echo json_encode($result); exit; } /*****************************/ if (!empty($_POST['customer_details'])) { ... File: includes/entities/entorder.inc.php // Validate customer details try { if (empty($this->data['customer']['firstname'])) throw new Exception(language::translate('error_missing_firstname', 'You must enter a first name.')); if (empty($this->data['customer']['lastname'])) throw new Exception(language::translate('error_missing_lastname', 'You must enter a last name.')); // bypass address1 and city if local pickup if (!isset($_SESSION["local-pickup"]) && empty($this->data['customer']['address1'])) throw new Exception(language::translate('error_missing_address1', 'You must enter an address.')); if (!isset($_SESSION["local-pickup"]) && empty($this->data['customer']['city'])) throw new Exception(language::translate('error_missing_city', 'You must enter a city.')); ...
hoesman LiteCart Fan Fra Croatia Member since jun. 2024 hoesman 14 apr. 2025 10:46 Thanks, I tried your solution and it works as expected, will save it as a backup. I will keep the simpler one for now as I actually want to insert the postcode and city as the "Most Popular Cities" stats still works this way, and it gives some visual to the user that the fields are clearly not required vs just empty fields.