order.tpl 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <div class="container">
  2. <div class="store-order-container mb-5">
  3. <form method="post" action="{routePath('cart-order-addtocart')}" id="frmAddToCart">
  4. <input type="hidden" name="pid" value="{$product->id}">
  5. <input type="hidden" name="domain_type" value="" id="inputDomainType">
  6. <h2>{$product->name}</h2>
  7. <p class="desc">{$product->description}</p>
  8. <h4{if $themesettings.orderform.orderopc == '1'} class="d-none"{/if}>{lang key='store.choosePaymentTerm'}</h4>
  9. <div class="TM-card{if $themesettings.orderform.orderopc == '1'} d-none{/if}">
  10. <div class="payment-term">
  11. <select name="billingcycle" class="form-control">
  12. {foreach $product->pricing()->allAvailableCycles() as $pricing}
  13. <option value="{$pricing->cycle()}"{if $requestedCycle == $pricing->cycle()} selected{/if}>
  14. {if $pricing->isRecurring()}
  15. {if $pricing->isYearly()}
  16. {$pricing->cycleInYears()} - {$pricing->yearlyPrice()}
  17. {else}
  18. {$pricing->cycleInMonths()} - {$pricing->monthlyPrice()}
  19. {/if}
  20. {else}
  21. {$pricing->toFullString()}
  22. {/if}
  23. </option>
  24. {/foreach}
  25. </select>
  26. </div>
  27. </div>
  28. <h4>{lang key='store.chooseDomain'}</h4>
  29. <ul class="nav nav-tabs store-domain-tabs responsive-tabs-sm" role="tablist">
  30. {if $requireDomain}
  31. {if (count($domains) > 0 && $loggedin)}
  32. <li class="nav-item active" role="presentation">
  33. <a class="nav-link" href="#existing-domain" aria-controls="existing-domain" role="tab" data-toggle="tab">
  34. {lang key='store.chooseExistingDomain'}
  35. </a>
  36. </li>
  37. {/if}
  38. {if $allowSubdomains}
  39. <li class="nav-item" role="presentation">
  40. <a class="nav-link" href="#sub-domain" aria-controls="sub-domain" role="tab" data-toggle="tab">
  41. {lang key='store.subOfExisting'}
  42. </a>
  43. </li>
  44. {/if}
  45. <li class="nav-item" role="presentation">
  46. <a class="nav-link" id="tabCustomDomainControl" href="#custom-domain" aria-controls="custom-domain" role="tab" data-toggle="tab">
  47. {lang key='store.domainAlreadyOwned'}
  48. </a>
  49. </li>
  50. {else}
  51. <li class="nav-item" role="presentation" class="active">
  52. <a class="nav-link" id="tabNoDomain" href="#no-domain" role="tab" data-toggle="tab">
  53. {lang key='store.noDomain'}
  54. </a>
  55. </li>
  56. {/if}
  57. </ul>
  58. <div class="tab-content store-domain-tab-content">
  59. {if $requireDomain}
  60. {if count($domains) > 0}
  61. <div role="tabpanel" class="tab-pane active" id="existing-domain">
  62. {if $loggedin}
  63. <div class="row">
  64. <div class="col-sm-8">
  65. <select class="form-control" name="existing_domain">
  66. {foreach $domains as $domain}
  67. <option value="{$domain}"{if $domain == $selectedDomain} selected="selected"{/if}>
  68. {$domain}
  69. </option>
  70. {/foreach}
  71. </select>
  72. </div>
  73. <div class="col-sm-4">
  74. <span class="domain-validation ok">
  75. <i class="fas fa-check"></i>
  76. {lang key='store.eligible'}
  77. </span>
  78. </div>
  79. </div>
  80. {else}
  81. <a href="{routePath('cart-order-login')}">{lang key='store.login'}</a> {lang key='store.addToExistingPackage'}
  82. {/if}
  83. </div>
  84. {/if}
  85. {if $allowSubdomains}
  86. <div role="tabpanel" class="tab-pane" id="sub-domain">
  87. <div class="row">
  88. <div class="col-sm-8">
  89. <div style="display:inline-block;width:47%;">
  90. <input type="text" class="form-control subdomain-input" name="sub_domain" placeholder="Your desired subdomain"></div>
  91. <div style="display:inline-block;width:2%;text-align:center;">
  92. .
  93. </div>
  94. <div style="display:inline-block;width:47%;">
  95. <select class="form-control" name="existing_sld_for_subdomain" id="existing_sld_for_subdomain">
  96. {foreach $domains as $domain}
  97. <option value="{$domain}">{$domain}</option>
  98. {/foreach}
  99. </select>
  100. </div>
  101. </div>
  102. <div class="col-sm-4">
  103. <span class="domain-validation subdomain-validation"></span>
  104. </div>
  105. </div>
  106. </div>
  107. {/if}
  108. <div role="tabpanel" class="tab-pane" id="custom-domain">
  109. <div class="row">
  110. <div class="col-sm-8">
  111. <input type="text" class="form-control domain-input" placeholder="example.com" name="custom_domain" value="{$customDomain}">
  112. </div>
  113. <div class="col-sm-4">
  114. <span class="domain-validation domain-input-validation"></span>
  115. </div>
  116. </div>
  117. </div>
  118. {else}
  119. <div role="tabpanel" class="tab-pane" id="no-domain">
  120. {lang key='store.noDomainRequired'}
  121. </div>
  122. {/if}
  123. </div>
  124. <div class="row">
  125. <div class="col-sm-5">
  126. <a href="javascript:history.go(-1)" class="btn btn-default">
  127. <i class="fas fa-arrow-left"></i>
  128. {lang key='back'}
  129. </a>
  130. </div>
  131. <div class="col-sm-7 text-right">
  132. <button type="submit" name="continue" value="1" class="btn btn-default">
  133. {lang key='orderForm.continueShopping'}
  134. </button>
  135. <button type="submit" name="checkout" value="1" class="btn btn-primary">
  136. {lang key='orderForm.checkout'}
  137. <i class="fas fa-shopping-cart"></i>
  138. </button>
  139. </div>
  140. </div>
  141. </form>
  142. {if $upsellProduct && $promotion}
  143. <div class="store-promoted-product card p-0 promo-banner bg-checkered upsell-{$upsellProduct->productKey}">
  144. <div class="card-body p-5">
  145. <div class="d-flex align-items-center flex-column flex-md-row">
  146. <div class="icon-left">
  147. <img src="{$promotion->getImagePath()}">
  148. </div>
  149. <div class="content w-100 ml-md-5">
  150. <h3 class="h4 bolder">{$promotion->getHeadline()}</h3>
  151. <h4>{$promotion->getTagline()}</h4>
  152. {if $promotion->getDescription()}
  153. <p>{$promotion->getDescription()}</p>
  154. {/if}
  155. {if $promotion->hasFeatures()}
  156. <ul>
  157. {foreach $promotion->getFeatures() as $highlight}
  158. <li class="w-100"><i class="far fa-check-circle"></i> {$highlight}</li>
  159. {/foreach}
  160. </ul>
  161. {/if}
  162. </div>
  163. </div>
  164. </div>
  165. <div class="card-footer">
  166. <form method="post" action="{routePath('cart-order')}">
  167. <input type="hidden" name="pid" value="{$upsellProduct->id}">
  168. <button type="submit" class="btn btn-primary btn-block">
  169. {foreach $product->pricing()->allAvailableCycles() as $pricing}
  170. <span class="span-upsell span-upsell-{$pricing->cycle()}">
  171. {if is_null($upsellComparison->diff({$pricing->cycle()}))}
  172. {$promotion->getCta()} {$upsellProduct->name} from just {$upsellProduct->pricing()->best()->breakdownPrice()}
  173. {else}
  174. {$promotion->getCta()} {$upsellProduct->name} for just {$upsellComparison->diff({$pricing->cycle()})->breakdownPrice()} more
  175. {/if}
  176. </span>
  177. {/foreach}
  178. </button>
  179. </form>
  180. </div>
  181. </div>
  182. {/if}
  183. </div>
  184. </div>
  185. <script>
  186. jQuery(document).ready(function(){
  187. var delay = (function(){
  188. var timer = 0;
  189. return function(callback, ms){
  190. clearTimeout (timer);
  191. timer = setTimeout(callback, ms);
  192. };
  193. })();
  194. jQuery('.store-order-container .subdomain-input').keyup(function() {
  195. delay(function(){
  196. jQuery('.subdomain-validation').html('<i class="fas fa-spinner fa-spin"></i> Validating...').removeClass('ok');
  197. jQuery('#frmAddToCart button[type="submit"]').prop('disabled', true);
  198. var domainName = jQuery('.subdomain-input').val() + '.' + jQuery('#existing_sld_for_subdomain').val();
  199. WHMCS.http.jqClient.post('{routePath('cart-order-validate')}', 'domain=' + domainName, function(data) {
  200. if (data.valid) {
  201. jQuery('.subdomain-validation').html('<i class="fas fa-check"></i> Valid').addClass('ok');
  202. jQuery('#frmAddToCart button[type="submit"]').removeProp('disabled');
  203. } else {
  204. jQuery('.subdomain-validation').html('<i class="fas fa-times"></i> Invalid domain');
  205. }
  206. }, 'json');
  207. }, 1000 );
  208. });
  209. var delay2 = (function(){
  210. var timer = 0;
  211. return function(callback, ms){
  212. clearTimeout (timer);
  213. timer = setTimeout(callback, ms);
  214. };
  215. })();
  216. jQuery('.store-order-container .domain-input').keyup(function() {
  217. delay2(function(){
  218. jQuery('.domain-input-validation').html('<i class="fas fa-spinner fa-spin"></i> Validating...').removeClass('ok');
  219. jQuery('#frmAddToCart button[type="submit"]').prop('disabled', true);
  220. WHMCS.http.jqClient.post('{routePath('cart-order-validate')}', 'domain=' + jQuery('.domain-input').val(), function(data) {
  221. if (data.valid) {
  222. jQuery('.domain-input-validation').html('<i class="fas fa-check"></i> Valid').addClass('ok');
  223. jQuery('#frmAddToCart button[type="submit"]').removeProp('disabled');
  224. } else {
  225. jQuery('.domain-input-validation').html('<i class="fas fa-times"></i> Invalid domain');
  226. }
  227. }, 'json');
  228. }, 1000 );
  229. });
  230. {if $requireDomain}
  231. jQuery('.store-domain-tabs a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
  232. var tab = jQuery(e.target).attr('aria-controls');
  233. jQuery('#inputDomainType').val(tab);
  234. if (tab == 'custom-domain' || tab == 'sub-domain') {
  235. var validationBlockSelector = tab == 'custom-domain' ? '.domain-input-validation' : '.subdomain-validation';
  236. var validationHtml = jQuery(validationBlockSelector).html();
  237. if (validationHtml == '<i class="fas fa-check"></i> Valid') {
  238. jQuery('#frmAddToCart button[type="submit"]').removeProp('disabled');
  239. } else {
  240. jQuery('#frmAddToCart button[type="submit"]').prop('disabled', true);
  241. }
  242. } else {
  243. {if $loggedin}
  244. jQuery('#frmAddToCart button[type="submit"]').removeProp('disabled');
  245. {else}
  246. jQuery('#frmAddToCart button[type="submit"]').prop('disabled', true);
  247. {/if}
  248. }
  249. });
  250. {/if}
  251. jQuery('.store-domain-tabs li').removeClass('active');
  252. jQuery('.store-domain-tabs li:first-child a').click();
  253. {if !$loggedin && $requireDomain}
  254. jQuery('#frmAddToCart button[type="submit"]').prop('disabled', true);
  255. {/if}
  256. jQuery('.payment-term').find('select').change(function() {
  257. var cycle = jQuery('.payment-term').find('option:selected').val();
  258. updateUpsellDetailsOnBillingCycleChange(cycle);
  259. });
  260. updateUpsellDetailsOnBillingCycleChange(jQuery('.payment-term').find('option:selected').val());
  261. {if $customDomain}
  262. jQuery('#tabCustomDomainControl').click();
  263. jQuery('.store-order-container .domain-input').trigger('keyup');
  264. {/if}
  265. });
  266. function updateUpsellDetailsOnBillingCycleChange(cycle) {
  267. jQuery('.span-upsell').hide();
  268. jQuery('.span-upsell-' + cycle).show();
  269. }
  270. </script>