| | |
| | | <?php |
| | | namespace JVBase\ui; |
| | | |
| | | use JVBase\base\Site; |
| | | use JVBase\integrations\Integrations; |
| | | use JVBase\meta\Form; |
| | | use JVBase\meta\Meta; |
| | | |
| | | if (!defined('ABSPATH')) { |
| | | exit; |
| | |
| | | */ |
| | | class Checkout |
| | | { |
| | | public static function getProvider():Integrations|false |
| | | { |
| | | foreach (Site::getIntegrations() as $integration => $active) { |
| | | if (in_array($integration, ['square', 'helcim']) && $active) { |
| | | return JVB()->connect($integration); |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | /** |
| | | * Render the checkout aside and append to actions. |
| | | * |
| | |
| | | return $actions; |
| | | } |
| | | |
| | | $provider = jvbGetPaymentProvider(); |
| | | $provider = self::getProvider(); |
| | | if (!$provider || !$provider->isSetUp()) { |
| | | return $actions; |
| | | } |
| | | |
| | | $providerName = strtolower($provider->getServiceName()); |
| | | |
| | | $form = '<aside id="cart" class="right main"> |
| | | <form id="checkout" data-form-id="checkout" data-save="checkout" data-provider="' . esc_attr($providerName) . '">'; |
| | | $aside = '<aside id="cart" class="right main"><div class="wrap">'; |
| | | $tabs = new Tabs(); |
| | | $tabs->addTab('cartItems') |
| | | ->title('Your Cart') |
| | | ->icon('shopping-cart-simple') |
| | | ->description('Here\'s your order. You can change quantities, remove items, or clear your cart. To checkout, click the checkout tab.') |
| | | ->content(self::cartContent($providerName)); |
| | | |
| | | $tabs = [ |
| | | 'cartItems' => [ |
| | | 'title' => 'Your Order', |
| | | 'icon' => 'cart', |
| | | 'description' => 'Here\'s your order. You can change quantities, remove items, or clear your cart.', |
| | | 'content' => self::cartContent(), |
| | | ], |
| | | 'checkout' => [ |
| | | 'title' => 'Checkout', |
| | | 'icon' => 'checkout', |
| | | 'description' => apply_filters('jvb_checkout_description', |
| | | 'Securely checkout with your name, email, and payment.', |
| | | $providerName |
| | | ), |
| | | 'content' => self::checkoutContent($providerName), |
| | | ], |
| | | 'order' => [ |
| | | 'title' => 'Your Order', |
| | | 'icon' => 'truck', |
| | | 'hidden' => true, |
| | | 'description' => '', |
| | | 'content' => self::orderStatus(), |
| | | ], |
| | | ]; |
| | | if (!is_user_logged_in()) { |
| | | $tabs->addTab('thelogin') |
| | | ->title('Login') |
| | | ->description('Login to see past orders and access your saved cards') |
| | | ->content(JVB()->magicLink()->renderForm()); |
| | | } else { |
| | | $tabs->addTab('account') |
| | | ->title('Account') |
| | | ->description('Manage your contact information, saved cards, and see past orders') |
| | | ->content(self::renderAccount()); |
| | | } |
| | | |
| | | $form .= jvbRenderTabs($tabs, true); |
| | | $tabs->addTab('checkout') |
| | | ->title('Checkout') |
| | | ->icon('hand-coins') |
| | | ->description(apply_filters('jvb_checkout_description', |
| | | 'Securely checkout with your name, email, and payment.', $providerName)) |
| | | ->content(self::checkoutContent($providerName)); |
| | | |
| | | $form .= '<div class="cart-total row end"> |
| | | <p class="tax">Tax: <span></span></p> |
| | | <p class="total">GRAND TOTAL: <span></span></p> |
| | | </div> |
| | | </form> |
| | | $tabs->addTab('order') |
| | | ->title('Your Order') |
| | | ->icon('truck') |
| | | ->hidden() |
| | | ->content(self::orderStatus()); |
| | | |
| | | $aside .= $tabs->render(); |
| | | |
| | | |
| | | |
| | | $aside .= '</div> |
| | | </aside>'; |
| | | |
| | | $form .= self::templates($providerName); |
| | | $aside .= self::templates($providerName); |
| | | |
| | | $actions[] = [ |
| | | 'button' => self::toggleButton(), |
| | | 'content' => $form, |
| | | 'content' => $aside, |
| | | ]; |
| | | |
| | | return $actions; |
| | |
| | | */ |
| | | private static function checkoutContent(string $provider): string |
| | | { |
| | | $fields = '<div class="checkout-section"> |
| | | <h3>Customer Information</h3>' |
| | | . Form::render('cart_name', null, [ |
| | | $name = $email = $phone = ''; |
| | | if (is_user_logged_in()) { |
| | | $meta = Meta::forUser(get_current_user_id()); |
| | | if ($meta) { |
| | | $name = $meta->get('display_name'); |
| | | $email = $meta->get('user_email'); |
| | | $phone = $meta->get('phone'); |
| | | } |
| | | |
| | | } |
| | | $form = sprintf( |
| | | '<form id="checkout" data-handled> |
| | | <h3>Your Information</h3> |
| | | %s%s%s', |
| | | Form::render('cart_name', $name, [ |
| | | 'type' => 'text', |
| | | 'label' => 'Your Name', |
| | | 'required' => true, |
| | | 'autocomplete' => 'name', |
| | | ]) |
| | | . Form::render('cart_email', null, [ |
| | | ]), |
| | | Form::render('cart_email', $email, [ |
| | | 'type' => 'email', |
| | | 'label' => 'Your Email', |
| | | 'required' => true, |
| | | 'autocomplete' => 'email', |
| | | ]) |
| | | . Form::render('cart_phone', null, [ |
| | | ]), |
| | | Form::render('cart_phone', $phone, [ |
| | | 'type' => 'tel', |
| | | 'label' => 'Your Phone', |
| | | 'required' => true, |
| | | 'autocomplete' => 'phone', |
| | | ]); |
| | | ]) |
| | | ); |
| | | |
| | | |
| | | // Optional sections — integrations can add pickup, scheduling, etc. |
| | | $fields .= apply_filters('jvb_checkout_fields', '', $provider); |
| | | $form .= apply_filters('jvb_checkout_fields', '', $provider); |
| | | |
| | | $fields .= '</div>'; |
| | | |
| | | |
| | | // Payment section — provider JS mounts its own UI inside #payment-container |
| | | $fields .= '<div class="checkout-section"> |
| | | $form .= '<div class="checkout-section"> |
| | | <h3>Payment Information</h3> |
| | | <div id="saved-cards"></div> |
| | | <div id="payment-container" data-provider="' . esc_attr($provider) . '"></div> |
| | | </div>'; |
| | | </div> |
| | | </form>'; |
| | | |
| | | return $fields; |
| | | return $form; |
| | | } |
| | | |
| | | /** |
| | | * Cart items tab: table + account details |
| | | */ |
| | | private static function cartContent(): string |
| | | private static function cartContent(string $provider): string |
| | | { |
| | | ob_start(); |
| | | ?> |
| | | <div class="cart-items"> |
| | | $content = sprintf('<form id="checkout" data-form-id="checkout" data-save="checkout" data-provider="%s">', |
| | | esc_attr($provider) |
| | | ); |
| | | $content.= '<div class="cart-items"> |
| | | <table> |
| | | <thead> |
| | | <tr> |
| | | <th scope="col">Item</th> |
| | | <th scope="col">Price</th> |
| | | <th scope="col">Total</th> |
| | | <th scope="col"></th> |
| | | </tr> |
| | | </thead> |
| | | <tbody></tbody> |
| | | <tfoot> |
| | | <tr> |
| | | <th scope="col"></th> |
| | | <th scope="col">TAX</th> |
| | | <td class="tax"></td> |
| | | <th scope="col"></th> |
| | | </tr> |
| | | <tr> |
| | | <th scope="col"></th> |
| | | <th scope="col">Net:</th> |
| | | <td class="total"></td> |
| | | <th scope="col"></th> |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | | |
| | | <details class="account"> |
| | | <summary> |
| | | <?php |
| | | if (is_user_logged_in()) { |
| | | echo 'Your Favourites and Order History'; |
| | | } else { |
| | | echo '<a href="' . wp_login_url(get_the_permalink()) . '">Log in</a> to save your favourites and view order history.'; |
| | | } |
| | | ?> |
| | | </summary> |
| | | <?php |
| | | if (is_user_logged_in()) { |
| | | $tabs = [ |
| | | 'history' => [ |
| | | 'title' => 'Order History', |
| | | 'icon' => 'checkout', |
| | | 'description' => 'View your past orders and quickly reorder', |
| | | 'content' => apply_filters('jvb_checkout_order_history', ''), |
| | | ], |
| | | 'favourites' => [ |
| | | 'title' => 'Favourites', |
| | | 'icon' => 'heart', |
| | | 'description' => 'View your favourites', |
| | | 'content' => apply_filters('jvb_checkout_favourites', ''), |
| | | ], |
| | | ]; |
| | | jvbRenderTabs($tabs); |
| | | } |
| | | ?> |
| | | </details> |
| | | <?php |
| | | return ob_get_clean(); |
| | | </form>'; |
| | | return $content; |
| | | } |
| | | |
| | | /** |
| | |
| | | return ob_get_clean(); |
| | | } |
| | | |
| | | private static function renderAccount():string |
| | | { |
| | | return ''; |
| | | } |
| | | |
| | | /***************************************************************** |
| | | * TEMPLATES — cloned by JS at runtime |
| | | *****************************************************************/ |
| | |
| | | $browseText = apply_filters('jvb_checkout_browse_text', 'browse our products'); |
| | | |
| | | return '<template class="restoredCart"> |
| | | <div class="restored"> |
| | | <div class="fstatus restored"> |
| | | <h3>Looks like we left things hanging</h3> |
| | | <p>We\'ve restored your cart from your last session below.</p> |
| | | <p>If you\'d rather start over, click the button below.</p> |
| | | <div class="row btw"> |
| | | <div class="row x-btw"> |
| | | <button type="button" data-clear-cart>' . jvbIcon('trash') . 'Clear Cart</button> |
| | | <button type="button" data-dismiss>' . jvbIcon('x') . 'Dismiss</button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template class="cartItem"> |
| | | <template class="mainCartItem"> |
| | | <tbody> |
| | | <tr class="header"><th></th></tr> |
| | | </tbody> |
| | | </template> |
| | | <template class="childCartItem"> |
| | | <tr class="item"> |
| | | <td class="item"> |
| | | <label for="quantity"></label> |
| | |
| | | */ |
| | | private static function toggleButton(): string |
| | | { |
| | | return '<button type="button" class="toggle-cart row" title="Your Cart" |
| | | return '<button type="button" class="toggle-cart row empty" title="Your Cart" |
| | | data-action="toggle-cart" aria-label="Open Cart" |
| | | aria-controls="checkout" aria-expanded="false">' |
| | | . jvbIcon('shopping-cart') |
| | | . '<span class="abs"></span><span class="abs count"></span> |
| | | . '<span class="abs close"></span><span class="abs count"></span> |
| | | </button>'; |
| | | } |
| | | } |