Plugin Directory

Changeset 3758167


Ignore:
Timestamp:
10/21/2026 10:43:36 AM (9 days ago)
Author:
webtendhq
Message:

updated version

Location:
traceify/trunk
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • traceify/trunk/admin/class-trcfy-admin.php

    r3716662 r3758167  
    2828                add_action( 'add_meta_boxes', array( $this, 'add_order_meta_box' ) );
    2929
     30                // Order detail page — Estimated Delivery override meta box.
     31                // `woocommerce_process_shop_order_meta` fires for both HPOS and legacy order screens.
     32                add_action( 'add_meta_boxes',                    array( $this, 'add_edd_meta_box' ) );
     33                add_action( 'woocommerce_process_shop_order_meta', array( $this, 'save_edd_override' ), 20, 2 );
     34
    3035                // Settings link on plugins page.
    3136                add_filter( 'plugin_action_links_' . TRCFY_BASENAME, array( $this, 'add_plugin_action_links' ) );
    … …  
    3742                // Show a red dot badge on the menu item until the user visits settings.
    3843                $show_badge = ( '1' !== get_option( 'trcfy_settings_visited', '0' ) );
    39                 $menu_label = __( 'Traceify', 'traceify' );
     44                $menu_label = __( 'Traceify', 'traceify-for-woocommerce' );
    4045                if ( $show_badge ) {
    4146                        $menu_label .= ' <span class="trcfy-menu-badge"></span>';
    … …  
    4449                add_submenu_page(
    4550                        'woocommerce',
    46                         __( 'Traceify Settings', 'traceify' ),
     51                        __( 'Traceify Settings', 'traceify-for-woocommerce' ),
    4752                        $menu_label,
    4853                        'manage_woocommerce',
    … …  
    6974        public function render_settings_page() {
    7075                if ( ! current_user_can( 'manage_woocommerce' ) ) {
    71                         wp_die( esc_html__( 'You do not have permission to access this page.', 'traceify' ) );
     76                        wp_die( esc_html__( 'You do not have permission to access this page.', 'traceify-for-woocommerce' ) );
    7277                }
    7378                require_once TRCFY_PATH . 'admin/views/settings-page.php';
    … …  
    97102                        'trcfy_edd_max_ship_days',
    98103                        'trcfy_edd_exclude_weekends',
     104                        // Shipment tracking.
     105                        'trcfy_shipment_enabled',
     106                        'trcfy_shipment_auto_shipped',
     107                        'trcfy_custom_courier_name',
     108                        'trcfy_custom_courier_url',
    99109                        // Email notifications.
    100110                        'trcfy_email_enabled',
    … …  
    130140                        'trcfy_edd_enabled'           => array( $this, 'sanitize_checkbox' ),
    131141                        'trcfy_edd_exclude_weekends'  => array( $this, 'sanitize_checkbox' ),
     142                        // Shipment tracking.
     143                        'trcfy_shipment_enabled'           => array( $this, 'sanitize_checkbox' ),
     144                        'trcfy_shipment_auto_shipped'      => array( $this, 'sanitize_checkbox' ),
     145                        'trcfy_custom_courier_url'         => array( 'TRCFY_Shipment_Tracking', 'sanitize_url_template' ),
    132146                        // Email toggles.
    133147                        'trcfy_email_enabled'              => array( $this, 'sanitize_checkbox' ),
    … …  
    164178                                $this->get_badge_inline_css()
    165179                        );
     180                }
     181
     182                // Order-screen meta box styles (tiny; only on order edit screens).
     183                $screen = get_current_screen();
     184                if ( $screen && ( 'shop_order' === $screen->post_type || 'woocommerce_page_wc-orders' === $screen->id ) ) {
     185                        wp_add_inline_style( 'wp-admin', '.trcfy-edd-input{width:100%;margin-bottom:8px}' );
    166186                }
    167187
    … …  
    221241                        if ( 'order_status' === $key ) {
    222242                                $new['trcfy_whatsapp'] = '<span class="trcfy-col-icon" title="' .
    223                                         esc_attr__( 'WhatsApp', 'traceify' ) . '">💬</span>';
     243                                        esc_attr__( 'WhatsApp', 'traceify-for-woocommerce' ) . '">💬</span>';
    224244                        }
    225245                }
    … …  
    242262                $wa_number = get_option( 'trcfy_wa_number', '' );
    243263                if ( ! $wa_number ) {
    244                         echo '<span title="' . esc_attr__( 'Set your WhatsApp number in WooCommerce → Order Tracker.', 'traceify' ) . '">—</span>';
     264                        echo '<span title="' . esc_attr__( 'Set your WhatsApp number in WooCommerce → Traceify.', 'traceify-for-woocommerce' ) . '">—</span>';
    245265                        return;
    246266                }
    … …  
    254274                                '<a href="%s" target="_blank" rel="noopener noreferrer" class="trcfy-wa-btn" title="%s %s">📲</a>',
    255275                                esc_url( $wa_link ),
    256                                 esc_attr__( 'Send WhatsApp to', 'traceify' ),
     276                                esc_attr__( 'Send WhatsApp to', 'traceify-for-woocommerce' ),
    257277                                esc_attr( $customer_phone )
    258278                        );
    259279                } else {
    260                         echo '<span title="' . esc_attr__( 'No billing phone on this order.', 'traceify' ) . '">—</span>';
     280                        echo '<span title="' . esc_attr__( 'No billing phone on this order.', 'traceify-for-woocommerce' ) . '">—</span>';
    261281                }
    262282        }
    … …  
    269289                        add_meta_box(
    270290                                'trcfy-whatsapp-box',
    271                                 __( 'WhatsApp Update', 'traceify' ),
     291                                __( 'WhatsApp Update', 'traceify-for-woocommerce' ),
    272292                                array( $this, 'render_order_meta_box' ),
    273293                                $screen,
    … …  
    303323                                        printf(
    304324                                                /* translators: %s = link to settings */
    305                                                 esc_html__( 'Add your WhatsApp number in %s to enable this feature.', 'traceify' ),
     325                                                esc_html__( 'Add your WhatsApp number in %s to enable this feature.', 'traceify-for-woocommerce' ),
    306326                                                '<a href="' . esc_url( admin_url( 'admin.php?page=traceify-for-woocommerce' ) ) . '">' .
    307                                                         esc_html__( 'Traceify Settings', 'traceify' ) .
     327                                                        esc_html__( 'Traceify Settings', 'traceify-for-woocommerce' ) .
    308328                                                '</a>'
    309329                                        );
    … …  
    311331                                </p>
    312332                        <?php elseif ( ! $customer_phone ) : ?>
    313                                 <p class="trcfy-notice"><?php esc_html_e( 'No billing phone number on this order.', 'traceify' ); ?></p>
     333                                <p class="trcfy-notice"><?php esc_html_e( 'No billing phone number on this order.', 'traceify-for-woocommerce' ); ?></p>
    314334                        <?php else : ?>
    315                                 <p class="trcfy-label"><?php esc_html_e( 'Customer Phone:', 'traceify' ); ?>
     335                                <p class="trcfy-label"><?php esc_html_e( 'Customer Phone:', 'traceify-for-woocommerce' ); ?>
    316336                                        <strong><?php echo esc_html( $customer_phone ); ?></strong>
    317337                                </p>
    318                                 <p class="trcfy-label"><?php esc_html_e( 'Preview message:', 'traceify' ); ?></p>
     338                                <p class="trcfy-label"><?php esc_html_e( 'Preview message:', 'traceify-for-woocommerce' ); ?></p>
    319339                                <p class="trcfy-preview"><?php echo esc_html( $message ); ?></p>
    320340                                <a href="<?php echo esc_url( $wa_link ); ?>"
    … …  
    322342                                   rel="noopener noreferrer"
    323343                                   class="button button-primary trcfy-send-btn">
    324                                         📲 <?php esc_html_e( 'Send WhatsApp Update', 'traceify' ); ?>
     344                                        📲 <?php esc_html_e( 'Send WhatsApp Update', 'traceify-for-woocommerce' ); ?>
    325345                                </a>
    326346                                <p class="trcfy-help">
    327                                         <?php esc_html_e( 'Opens WhatsApp on your device with the message pre-filled.', 'traceify' ); ?>
     347                                        <?php esc_html_e( 'Opens WhatsApp on your device with the message pre-filled.', 'traceify-for-woocommerce' ); ?>
    328348                                </p>
    329349                        <?php endif; ?>
    … …  
    339359                        add_meta_box(
    340360                                'trcfy-edd-box',
    341                                 __( 'Estimated Delivery', 'traceify' ),
     361                                __( 'Estimated Delivery', 'traceify-for-woocommerce' ),
    342362                                array( $this, 'render_edd_meta_box' ),
    343363                                $screen,
    … …  
    357377                }
    358378
    359                 $min = esc_attr( $order->get_meta( '_trcfy_edd_min' ) );
    360                 $max = esc_attr( $order->get_meta( '_trcfy_edd_max' ) );
     379                $min = $order->get_meta( '_trcfy_edd_min' );
     380                $max = $order->get_meta( '_trcfy_edd_max' );
    361381                wp_nonce_field( 'trcfy_edd_override', 'trcfy_edd_override_nonce' );
    362382                ?>
    363383                <div class="trcfy-meta-box">
    364                         <p class="trcfy-label"><?php esc_html_e( 'Min delivery date:', 'traceify' ); ?></p>
    365                         <input type="date" name="trcfy_edd_min" value="<?php echo esc_attr( $min ); ?>" style="width:100%;margin-bottom:8px;">
    366                         <p class="trcfy-label"><?php esc_html_e( 'Max delivery date:', 'traceify' ); ?></p>
    367                         <input type="date" name="trcfy_edd_max" value="<?php echo esc_attr( $max ); ?>" style="width:100%;margin-bottom:8px;">
    368                         <p class="trcfy-help"><?php esc_html_e( 'Override the auto-calculated dates shown to the customer on the tracking page.', 'traceify' ); ?></p>
     384                        <p class="trcfy-label"><?php esc_html_e( 'Min delivery date:', 'traceify-for-woocommerce' ); ?></p>
     385                        <input type="date" name="trcfy_edd_min" class="trcfy-edd-input" value="<?php echo esc_attr( $min ); ?>">
     386                        <p class="trcfy-label"><?php esc_html_e( 'Max delivery date:', 'traceify-for-woocommerce' ); ?></p>
     387                        <input type="date" name="trcfy_edd_max" class="trcfy-edd-input" value="<?php echo esc_attr( $max ); ?>">
     388                        <p class="trcfy-help"><?php esc_html_e( 'Override the auto-calculated dates shown to the customer on the tracking page.', 'traceify-for-woocommerce' ); ?></p>
    369389                </div>
    370390                <?php
    … …  
    378398        }
    379399
    380         public function save_edd_override_hpos( $and_taxes, $order ) {
    381                 if ( $order instanceof WC_Order ) {
    382                         TRCFY_Delivery_Estimator::save_admin_override( $order->get_id(), $order );
    383                 }
    384         }
    385 
    386400        // ── Plugin action links ───────────────────────────────────────────────
    387401
    388402        public function add_plugin_action_links( $links ) {
    389403                $settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=traceify-for-woocommerce' ) ) . '">'
    390                         . esc_html__( 'Settings', 'traceify' ) . '</a>';
     404                        . esc_html__( 'Settings', 'traceify-for-woocommerce' ) . '</a>';
    391405                array_unshift( $links, $settings_link );
    392406                return $links;
  • traceify/trunk/admin/views/settings-page.php

    r3716662 r3758167  
    1515        'whatsapp' => array( 'label' => 'WhatsApp',             'group' => 'MESSAGING',      'desc' => 'WhatsApp number and message templates.',         'icon' => '<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413z"/><path d="M12 0C5.373 0 0 5.373 0 12c0 2.124.558 4.122 1.533 5.854L0 24l6.335-1.51A11.945 11.945 0 0012 24c6.627 0 12-5.373 12-12S18.627 0 12 0zm0 21.818a9.818 9.818 0 01-5.006-1.368l-.36-.213-3.76.896.951-3.657-.234-.376A9.817 9.817 0 012.182 12C2.182 6.582 6.582 2.182 12 2.182c5.418 0 9.818 4.4 9.818 9.818 0 5.418-4.4 9.818-9.818 9.818z"/>' ),
    1616        'tracking'  => array( 'label' => 'Tracking Page',       'group' => 'TRACKING',       'desc' => 'Configure the customer-facing tracking page.',   'icon' => '<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>' ),
     17        'shipment'  => array( 'label' => 'Shipment Tracking',   'group' => 'TRACKING',       'desc' => 'Courier and tracking number for each order.',    'icon' => '<path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/>' ),
    1718        'delivery'  => array( 'label' => 'Estimated Delivery',  'group' => 'TRACKING',       'desc' => 'Auto-calculate delivery date ranges.',          'icon' => '<path d="M19 4h-1V2h-2v2H8V2H6v2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V10h14v10zm0-12H5V6h14v2zM9 14H7v-2h2v2zm4 0h-2v-2h2v2zm4 0h-2v-2h2v2zm-8 4H7v-2h2v2zm4 4h-2v-2h2v2zm4 0h-2v-2h2v2z"/>' ),
    1819        'emails'    => array( 'label' => 'Email Notifications', 'group' => 'NOTIFICATIONS',  'desc' => 'Branded email alerts on order status changes.', 'icon' => '<path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/>' ),
    … …  
    7071    <div id="trcfy-saved-notice" style="display:none;align-items:center;gap:8px;background:#D1FAE5;border:1px solid #A7F3D0;color:#065F46;padding:10px 20px;font-size:13px;font-weight:500;">
    7172      <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
    72       <?php esc_html_e( 'Settings saved.', 'traceify' ); ?>
     73      <?php esc_html_e( 'Settings saved.', 'traceify-for-woocommerce' ); ?>
    7374    </div>
    7475
    … …  
    8081      </div>
    8182      <button type="submit" form="trcfy-settings-form" class="trcfy-save-btn">
    82         <?php esc_html_e( 'Save changes', 'traceify' ); ?>
     83        <?php esc_html_e( 'Save changes', 'traceify-for-woocommerce' ); ?>
    8384      </button>
    8485    </div>
    … …  
    9495          <div class="trcfy-card-header">
    9596            <div class="trcfy-card-dot"></div>
    96             <h3><?php esc_html_e( 'BRANDING', 'traceify' ); ?></h3>
    97           </div>
    98           <div class="trcfy-row">
    99             <div class="trcfy-row-label">
    100               <strong><?php esc_html_e( 'Store name', 'traceify' ); ?></strong>
    101               <span><?php esc_html_e( 'Used in WhatsApp and email message templates.', 'traceify' ); ?></span>
     97            <h3><?php esc_html_e( 'BRANDING', 'traceify-for-woocommerce' ); ?></h3>
     98          </div>
     99          <div class="trcfy-row">
     100            <div class="trcfy-row-label">
     101              <strong><?php esc_html_e( 'Store name', 'traceify-for-woocommerce' ); ?></strong>
     102              <span><?php esc_html_e( 'Used in WhatsApp and email message templates.', 'traceify-for-woocommerce' ); ?></span>
    102103            </div>
    103104            <div class="trcfy-row-control">
    … …  
    108109          <div class="trcfy-row">
    109110            <div class="trcfy-row-label">
    110               <strong><?php esc_html_e( 'Brand color', 'traceify' ); ?></strong>
    111               <span><?php esc_html_e( 'Applied to the tracking page timeline, buttons and focus states.', 'traceify' ); ?></span>
     111              <strong><?php esc_html_e( 'Brand color', 'traceify-for-woocommerce' ); ?></strong>
     112              <span><?php esc_html_e( 'Applied to the tracking page timeline, buttons and focus states.', 'traceify-for-woocommerce' ); ?></span>
    112113            </div>
    113114            <div class="trcfy-row-control">
    … …  
    126127          <div class="trcfy-row">
    127128            <div class="trcfy-row-label">
    128               <strong><?php esc_html_e( 'Logo URL', 'traceify' ); ?></strong>
    129               <span><?php esc_html_e( 'Shown at the top of the customer tracking page. Optional.', 'traceify' ); ?></span>
     129              <strong><?php esc_html_e( 'Logo URL', 'traceify-for-woocommerce' ); ?></strong>
     130              <span><?php esc_html_e( 'Shown at the top of the customer tracking page. Optional.', 'traceify-for-woocommerce' ); ?></span>
    130131            </div>
    131132            <div class="trcfy-row-control">
    … …  
    143144          <div class="trcfy-card-header">
    144145            <div class="trcfy-card-dot" style="background:#25D366"></div>
    145             <h3><?php esc_html_e( 'CONFIGURATION', 'traceify' ); ?></h3>
     146            <h3><?php esc_html_e( 'CONFIGURATION', 'traceify-for-woocommerce' ); ?></h3>
    146147          </div>
    147148          <div class="trcfy-info">
    148             <?php esc_html_e( 'Uses WhatsApp\'s free wa.me link — no API or monthly fee. Clicking opens WhatsApp on your device with the message pre-filled.', 'traceify' ); ?>
    149           </div>
    150           <div class="trcfy-row">
    151             <div class="trcfy-row-label">
    152               <strong><?php esc_html_e( 'Business number', 'traceify' ); ?></strong>
    153               <span><?php esc_html_e( 'Country code + digits only. e.g. 8801712345678', 'traceify' ); ?></span>
     149            <?php esc_html_e( 'Uses WhatsApp\'s free wa.me link — no API or monthly fee. Clicking opens WhatsApp on your device with the message pre-filled.', 'traceify-for-woocommerce' ); ?>
     150          </div>
     151          <div class="trcfy-row">
     152            <div class="trcfy-row-label">
     153              <strong><?php esc_html_e( 'Business number', 'traceify-for-woocommerce' ); ?></strong>
     154              <span><?php esc_html_e( 'Country code + digits only. e.g. 8801712345678', 'traceify-for-woocommerce' ); ?></span>
    154155            </div>
    155156            <div class="trcfy-row-control">
    … …  
    161162          <div class="trcfy-row">
    162163            <div class="trcfy-row-label">
    163               <strong><?php esc_html_e( 'Customer contact button', 'traceify' ); ?></strong>
    164               <span><?php esc_html_e( 'Show a "Chat on WhatsApp" button on the tracking page.', 'traceify' ); ?></span>
     164              <strong><?php esc_html_e( 'Customer contact button', 'traceify-for-woocommerce' ); ?></strong>
     165              <span><?php esc_html_e( 'Show a "Chat on WhatsApp" button on the tracking page.', 'traceify-for-woocommerce' ); ?></span>
    165166            </div>
    166167            <div class="trcfy-row-control">
    … …  
    174175          <div class="trcfy-row">
    175176            <div class="trcfy-row-label">
    176               <strong><?php esc_html_e( 'Button label', 'traceify' ); ?></strong>
    177               <span><?php esc_html_e( 'Text shown on the customer-facing WhatsApp button.', 'traceify' ); ?></span>
     177              <strong><?php esc_html_e( 'Button label', 'traceify-for-woocommerce' ); ?></strong>
     178              <span><?php esc_html_e( 'Text shown on the customer-facing WhatsApp button.', 'traceify-for-woocommerce' ); ?></span>
    178179            </div>
    179180            <div class="trcfy-row-control">
    180181              <input type="text" name="trcfy_wa_customer_btn_label" class="trcfy-input trcfy-input-wide"
    181                 value="<?php echo esc_attr( get_option( 'trcfy_wa_customer_btn_label', __( 'Chat with us on WhatsApp', 'traceify' ) ) ); ?>">
     182                value="<?php echo esc_attr( get_option( 'trcfy_wa_customer_btn_label', __( 'Chat with us on WhatsApp', 'traceify-for-woocommerce' ) ) ); ?>">
    182183            </div>
    183184          </div>
    … …  
    187188          <div class="trcfy-card-header">
    188189            <div class="trcfy-card-dot" style="background:#25D366"></div>
    189             <h3><?php esc_html_e( 'MESSAGE TEMPLATES', 'traceify' ); ?></h3>
     190            <h3><?php esc_html_e( 'MESSAGE TEMPLATES', 'traceify-for-woocommerce' ); ?></h3>
    190191          </div>
    191192          <div class="trcfy-placeholder">
    192             <?php esc_html_e( 'Placeholders:', 'traceify' ); ?>
    193             {customer_name} &nbsp; {order_number} &nbsp; {order_status} &nbsp; {order_total} &nbsp; {store_name} &nbsp; {tracking_url}
     193            <?php esc_html_e( 'Placeholders:', 'traceify-for-woocommerce' ); ?>
     194            {customer_name} &nbsp; {order_number} &nbsp; {order_status} &nbsp; {order_total} &nbsp; {store_name} &nbsp; {tracking_url} &nbsp; {tracking_number} &nbsp; {tracking_link} &nbsp; {courier_name}
    194195          </div>
    195196          <?php
    196197          $trcfy_wa_statuses = array(
    197             'pending'    => __( 'Pending Payment', 'traceify' ),
    198             'processing' => __( 'Processing', 'traceify' ),
    199             'on-hold'    => __( 'On Hold', 'traceify' ),
    200             'shipped'    => __( 'Shipped', 'traceify' ),
    201             'completed'  => __( 'Completed / Delivered', 'traceify' ),
    202             'cancelled'  => __( 'Cancelled', 'traceify' ),
     198            'pending'    => __( 'Pending Payment', 'traceify-for-woocommerce' ),
     199            'processing' => __( 'Processing', 'traceify-for-woocommerce' ),
     200            'on-hold'    => __( 'On Hold', 'traceify-for-woocommerce' ),
     201            'shipped'    => __( 'Shipped', 'traceify-for-woocommerce' ),
     202            'completed'  => __( 'Completed / Delivered', 'traceify-for-woocommerce' ),
     203            'cancelled'  => __( 'Cancelled', 'traceify-for-woocommerce' ),
    203204          );
    204205          foreach ( $trcfy_wa_statuses as $trcfy_s_key => $trcfy_s_label ) :
    … …  
    224225          <div class="trcfy-card-header">
    225226            <div class="trcfy-card-dot" style="background:#0EA5E9"></div>
    226             <h3><?php esc_html_e( 'PAGE SETUP', 'traceify' ); ?></h3>
    227           </div>
    228           <div class="trcfy-row">
    229             <div class="trcfy-row-label">
    230               <strong><?php esc_html_e( 'Tracking page', 'traceify' ); ?></strong>
    231               <span><?php esc_html_e( 'The page containing the [traceify_tracker] shortcode.', 'traceify' ); ?></span>
     227            <h3><?php esc_html_e( 'PAGE SETUP', 'traceify-for-woocommerce' ); ?></h3>
     228          </div>
     229          <div class="trcfy-row">
     230            <div class="trcfy-row-label">
     231              <strong><?php esc_html_e( 'Tracking page', 'traceify-for-woocommerce' ); ?></strong>
     232              <span><?php esc_html_e( 'The page containing the [traceify_tracker] shortcode.', 'traceify-for-woocommerce' ); ?></span>
    232233            </div>
    233234            <div class="trcfy-row-control" style="gap:10px;display:flex;align-items:center;">
    234235              <select name="trcfy_tracking_page_id" class="trcfy-select">
    235                 <option value=""><?php esc_html_e( '— Select —', 'traceify' ); ?></option>
     236                <option value=""><?php esc_html_e( '— Select —', 'traceify-for-woocommerce' ); ?></option>
    236237                <?php foreach ( $trcfy_pages as $trcfy_p ) : ?>
    237238                  <option value="<?php echo absint( $trcfy_p->ID ); ?>"
    … …  
    245246                   rel="noopener noreferrer"
    246247                   style="font-size:12px;color:#7C3AED;text-decoration:none;">
    247                   <?php esc_html_e( 'View ↗', 'traceify' ); ?>
     248                  <?php esc_html_e( 'View ↗', 'traceify-for-woocommerce' ); ?>
    248249                </a>
    249250              <?php endif; ?>
    … …  
    252253          <div class="trcfy-row">
    253254            <div class="trcfy-row-label">
    254               <strong><?php esc_html_e( 'Shortcode', 'traceify' ); ?></strong>
    255               <span><?php esc_html_e( 'Add to any page or post to embed the tracking form.', 'traceify' ); ?></span>
    256             </div>
    257             <div class="trcfy-row-control">
    258               <div class="trcfy-shortcode-pill" title="<?php esc_attr_e( 'Click to copy', 'traceify' ); ?>">
     255              <strong><?php esc_html_e( 'Shortcode', 'traceify-for-woocommerce' ); ?></strong>
     256              <span><?php esc_html_e( 'Add to any page or post to embed the tracking form.', 'traceify-for-woocommerce' ); ?></span>
     257            </div>
     258            <div class="trcfy-row-control">
     259              <div class="trcfy-shortcode-pill" title="<?php esc_attr_e( 'Click to copy', 'traceify-for-woocommerce' ); ?>">
    259260                <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>
    260261                <code>[traceify_tracker]</code>
    261                 <span class="trcfy-copied">✓ <?php esc_html_e( 'Copied', 'traceify' ); ?></span>
     262                <span class="trcfy-copied">✓ <?php esc_html_e( 'Copied', 'traceify-for-woocommerce' ); ?></span>
    262263              </div>
     264            </div>
     265          </div>
     266        </div>
     267      </div>
     268
     269      <!-- ══ SHIPMENT TRACKING ══ -->
     270      <div class="trcfy-section-body<?php echo ( 'shipment' === $trcfy_active ) ? ' active' : ''; ?>" id="section-shipment">
     271        <div class="trcfy-card">
     272          <div class="trcfy-card-header">
     273            <div class="trcfy-card-dot" style="background:#3B82F6"></div>
     274            <h3><?php esc_html_e( 'SHIPMENT TRACKING', 'traceify-for-woocommerce' ); ?></h3>
     275          </div>
     276          <div class="trcfy-row">
     277            <div class="trcfy-row-label">
     278              <strong><?php esc_html_e( 'Enable shipment tracking', 'traceify-for-woocommerce' ); ?></strong>
     279              <span><?php esc_html_e( 'Adds a courier + tracking number box to every order and shows it to customers.', 'traceify-for-woocommerce' ); ?></span>
     280            </div>
     281            <div class="trcfy-row-control">
     282              <label class="trcfy-toggle">
     283                <input type="checkbox" name="trcfy_shipment_enabled" value="yes"
     284                  <?php checked( 'yes', get_option( 'trcfy_shipment_enabled', 'yes' ) ); ?>>
     285                <span class="trcfy-toggle-track"></span>
     286              </label>
     287            </div>
     288          </div>
     289          <div class="trcfy-row">
     290            <div class="trcfy-row-label">
     291              <strong><?php esc_html_e( 'Auto-mark as Shipped', 'traceify-for-woocommerce' ); ?></strong>
     292              <span><?php esc_html_e( 'When a tracking number is first added to a Processing order, change its status to Shipped.', 'traceify-for-woocommerce' ); ?></span>
     293            </div>
     294            <div class="trcfy-row-control">
     295              <label class="trcfy-toggle">
     296                <input type="checkbox" name="trcfy_shipment_auto_shipped" value="yes"
     297                  <?php checked( 'yes', get_option( 'trcfy_shipment_auto_shipped', 'no' ) ); ?>>
     298                <span class="trcfy-toggle-track"></span>
     299              </label>
     300            </div>
     301          </div>
     302        </div>
     303        <div class="trcfy-card">
     304          <div class="trcfy-card-header">
     305            <div class="trcfy-card-dot" style="background:#8B5CF6"></div>
     306            <h3><?php esc_html_e( 'CUSTOM COURIER', 'traceify-for-woocommerce' ); ?></h3>
     307          </div>
     308          <div class="trcfy-placeholder">
     309            <?php esc_html_e( 'Use {tracking_number} in the URL where the number goes, e.g. https://example.com/track?id={tracking_number}', 'traceify-for-woocommerce' ); ?>
     310          </div>
     311          <div class="trcfy-row">
     312            <div class="trcfy-row-label">
     313              <strong><?php esc_html_e( 'Courier name', 'traceify-for-woocommerce' ); ?></strong>
     314            </div>
     315            <div class="trcfy-row-control">
     316              <input type="text" name="trcfy_custom_courier_name" class="trcfy-input trcfy-input-wide"
     317                value="<?php echo esc_attr( get_option( 'trcfy_custom_courier_name', '' ) ); ?>"
     318                placeholder="<?php esc_attr_e( 'e.g. Pathao', 'traceify-for-woocommerce' ); ?>">
     319            </div>
     320          </div>
     321          <div class="trcfy-row">
     322            <div class="trcfy-row-label">
     323              <strong><?php esc_html_e( 'Tracking URL', 'traceify-for-woocommerce' ); ?></strong>
     324              <span><?php esc_html_e( 'Must start with https://', 'traceify-for-woocommerce' ); ?></span>
     325            </div>
     326            <div class="trcfy-row-control">
     327              <input type="text" name="trcfy_custom_courier_url" class="trcfy-input trcfy-input-wide"
     328                value="<?php echo esc_attr( get_option( 'trcfy_custom_courier_url', '' ) ); ?>"
     329                placeholder="https://">
    263330            </div>
    264331          </div>
    … …  
    271338          <div class="trcfy-card-header">
    272339            <div class="trcfy-card-dot" style="background:#F59E0B"></div>
    273             <h3><?php esc_html_e( 'DELIVERY ESTIMATE', 'traceify' ); ?></h3>
    274           </div>
    275           <div class="trcfy-row">
    276             <div class="trcfy-row-label">
    277               <strong><?php esc_html_e( 'Enable estimated delivery', 'traceify' ); ?></strong>
    278               <span><?php esc_html_e( 'Auto-calculate and show delivery date range on the tracking page.', 'traceify' ); ?></span>
     340            <h3><?php esc_html_e( 'DELIVERY ESTIMATE', 'traceify-for-woocommerce' ); ?></h3>
     341          </div>
     342          <div class="trcfy-row">
     343            <div class="trcfy-row-label">
     344              <strong><?php esc_html_e( 'Enable estimated delivery', 'traceify-for-woocommerce' ); ?></strong>
     345              <span><?php esc_html_e( 'Auto-calculate and show delivery date range on the tracking page.', 'traceify-for-woocommerce' ); ?></span>
    279346            </div>
    280347            <div class="trcfy-row-control">
    … …  
    288355          <div class="trcfy-row">
    289356            <div class="trcfy-row-label">
    290               <strong><?php esc_html_e( 'Processing time', 'traceify' ); ?></strong>
    291               <span><?php esc_html_e( 'Days to prepare the order before dispatch.', 'traceify' ); ?></span>
     357              <strong><?php esc_html_e( 'Processing time', 'traceify-for-woocommerce' ); ?></strong>
     358              <span><?php esc_html_e( 'Days to prepare the order before dispatch.', 'traceify-for-woocommerce' ); ?></span>
    292359            </div>
    293360            <div class="trcfy-row-control">
    … …  
    295362                min="0" max="30"
    296363                value="<?php echo absint( get_option( 'trcfy_edd_processing_days', 1 ) ); ?>">
    297               <span style="font-size:12px;color:#94A3B8;margin-left:8px;"><?php esc_html_e( 'days', 'traceify' ); ?></span>
    298             </div>
    299           </div>
    300           <div class="trcfy-row">
    301             <div class="trcfy-row-label">
    302               <strong><?php esc_html_e( 'Shipping days range', 'traceify' ); ?></strong>
    303               <span><?php esc_html_e( 'Min and max days in transit after dispatch.', 'traceify' ); ?></span>
     364              <span style="font-size:12px;color:#94A3B8;margin-left:8px;"><?php esc_html_e( 'days', 'traceify-for-woocommerce' ); ?></span>
     365            </div>
     366          </div>
     367          <div class="trcfy-row">
     368            <div class="trcfy-row-label">
     369              <strong><?php esc_html_e( 'Shipping days range', 'traceify-for-woocommerce' ); ?></strong>
     370              <span><?php esc_html_e( 'Min and max days in transit after dispatch.', 'traceify-for-woocommerce' ); ?></span>
    304371            </div>
    305372            <div class="trcfy-row-control" style="gap:8px;display:flex;align-items:center;">
    … …  
    307374                min="1" max="60"
    308375                value="<?php echo absint( get_option( 'trcfy_edd_min_ship_days', 2 ) ); ?>">
    309               <span style="font-size:12px;color:#94A3B8;"><?php esc_html_e( 'to', 'traceify' ); ?></span>
     376              <span style="font-size:12px;color:#94A3B8;"><?php esc_html_e( 'to', 'traceify-for-woocommerce' ); ?></span>
    310377              <input type="number" name="trcfy_edd_max_ship_days" class="trcfy-number-input"
    311378                min="1" max="60"
    312379                value="<?php echo absint( get_option( 'trcfy_edd_max_ship_days', 5 ) ); ?>">
    313               <span style="font-size:12px;color:#94A3B8;"><?php esc_html_e( 'days', 'traceify' ); ?></span>
    314             </div>
    315           </div>
    316           <div class="trcfy-row">
    317             <div class="trcfy-row-label">
    318               <strong><?php esc_html_e( 'Exclude weekends', 'traceify' ); ?></strong>
    319               <span><?php esc_html_e( 'Skip Saturday and Sunday when counting delivery days.', 'traceify' ); ?></span>
     380              <span style="font-size:12px;color:#94A3B8;"><?php esc_html_e( 'days', 'traceify-for-woocommerce' ); ?></span>
     381            </div>
     382          </div>
     383          <div class="trcfy-row">
     384            <div class="trcfy-row-label">
     385              <strong><?php esc_html_e( 'Exclude weekends', 'traceify-for-woocommerce' ); ?></strong>
     386              <span><?php esc_html_e( 'Skip Saturday and Sunday when counting delivery days.', 'traceify-for-woocommerce' ); ?></span>
    320387            </div>
    321388            <div class="trcfy-row-control">
    … …  
    335402          <div class="trcfy-card-header">
    336403            <div class="trcfy-card-dot" style="background:#EC4899"></div>
    337             <h3><?php esc_html_e( 'EMAIL SETTINGS', 'traceify' ); ?></h3>
     404            <h3><?php esc_html_e( 'EMAIL SETTINGS', 'traceify-for-woocommerce' ); ?></h3>
    338405          </div>
    339406          <div class="trcfy-info">
    340             <?php esc_html_e( '"Shipped" is ON by default — WooCommerce has no built-in shipped email. Other statuses are OFF to avoid duplicating WC\'s default emails.', 'traceify' ); ?>
    341           </div>
    342           <div class="trcfy-row">
    343             <div class="trcfy-row-label">
    344               <strong><?php esc_html_e( 'Enable email notifications', 'traceify' ); ?></strong>
    345               <span><?php esc_html_e( 'Master toggle for all Traceify branded emails.', 'traceify' ); ?></span>
     407            <?php esc_html_e( '"Shipped" is ON by default — WooCommerce has no built-in shipped email. Other statuses are OFF to avoid duplicating WC\'s default emails.', 'traceify-for-woocommerce' ); ?>
     408          </div>
     409          <div class="trcfy-row">
     410            <div class="trcfy-row-label">
     411              <strong><?php esc_html_e( 'Enable email notifications', 'traceify-for-woocommerce' ); ?></strong>
     412              <span><?php esc_html_e( 'Master toggle for all Traceify branded emails.', 'traceify-for-woocommerce' ); ?></span>
    346413            </div>
    347414            <div class="trcfy-row-control">
    … …  
    357424        <?php
    358425        $trcfy_email_statuses = array(
    359           'shipped'    => array( 'label' => 'Shipped',    'on' => 'yes', 'note' => __( 'Recommended ON — no WC default.', 'traceify' ) ),
    360           'processing' => array( 'label' => 'Processing', 'on' => 'no',  'note' => __( 'WC already sends this.', 'traceify' ) ),
    361           'completed'  => array( 'label' => 'Completed',  'on' => 'no',  'note' => __( 'WC already sends this.', 'traceify' ) ),
    362           'on-hold'    => array( 'label' => 'On Hold',    'on' => 'no',  'note' => __( 'WC already sends this.', 'traceify' ) ),
    363           'cancelled'  => array( 'label' => 'Cancelled',  'on' => 'no',  'note' => __( 'WC already sends this.', 'traceify' ) ),
     426          'shipped'    => array( 'label' => 'Shipped',    'on' => 'yes', 'note' => __( 'Recommended ON — no WC default.', 'traceify-for-woocommerce' ) ),
     427          'processing' => array( 'label' => 'Processing', 'on' => 'no',  'note' => __( 'WC already sends this.', 'traceify-for-woocommerce' ) ),
     428          'completed'  => array( 'label' => 'Completed',  'on' => 'no',  'note' => __( 'WC already sends this.', 'traceify-for-woocommerce' ) ),
     429          'on-hold'    => array( 'label' => 'On Hold',    'on' => 'no',  'note' => __( 'WC already sends this.', 'traceify-for-woocommerce' ) ),
     430          'cancelled'  => array( 'label' => 'Cancelled',  'on' => 'no',  'note' => __( 'WC already sends this.', 'traceify-for-woocommerce' ) ),
    364431        );
    365432        $trcfy_default_subjects = TRCFY_Email_Notifier::default_subjects();
    … …  
    378445            </div>
    379446            <span class="trcfy-tag <?php echo ( 'yes' === $trcfy_is_enabled ) ? 'trcfy-tag-on' : 'trcfy-tag-off'; ?>">
    380               <?php echo ( 'yes' === $trcfy_is_enabled ) ? esc_html__( 'ON', 'traceify' ) : esc_html__( 'OFF', 'traceify' ); ?>
     447              <?php echo ( 'yes' === $trcfy_is_enabled ) ? esc_html__( 'ON', 'traceify-for-woocommerce' ) : esc_html__( 'OFF', 'traceify-for-woocommerce' ); ?>
    381448            </span>
    382449          </div>
    383450          <div class="trcfy-row">
    384451            <div class="trcfy-row-label">
    385               <strong><?php esc_html_e( 'Send email', 'traceify' ); ?></strong>
     452              <strong><?php esc_html_e( 'Send email', 'traceify-for-woocommerce' ); ?></strong>
    386453              <span><?php echo esc_html( $trcfy_s_info['note'] ); ?></span>
    387454            </div>
    … …  
    396463          <div class="trcfy-row trcfy-row-full">
    397464            <div class="trcfy-row-label">
    398               <strong><?php esc_html_e( 'Email subject', 'traceify' ); ?></strong>
     465              <strong><?php esc_html_e( 'Email subject', 'traceify-for-woocommerce' ); ?></strong>
    399466            </div>
    400467            <div class="trcfy-row-control">
  • traceify/trunk/assets/css/public.css

    r3716662 r3758167  
    1 /* WC Order Tracker — Public Styles */
     1/* Traceify — Public Styles */
    22:root {
    33  --trcfy-brand:       #7C3AED;
    … …  
    330330.trcfy-edd-date  { font-size: 17px; font-weight: 700; color: var(--trcfy-text); }
    331331.trcfy-edd-remaining { font-size: 12px; color: var(--trcfy-brand); font-weight: 500; }
     332
     333/* ── Shipment tracking ── */
     334.trcfy-ship-card { border-left: 4px solid var(--trcfy-brand); padding: 16px 20px; }
     335.trcfy-ship-card .trcfy-edd-inner { flex-wrap: wrap; }
     336.trcfy-ship-number { word-break: break-all; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
     337.trcfy-ship-btn { margin-left: auto; text-decoration: none; }
     338@media (max-width: 520px) {
     339  .trcfy-ship-btn { margin-left: 0; width: 100%; text-align: center; justify-content: center; }
     340}
  • traceify/trunk/assets/js/public.js

    r3716662 r3758167  
    1 /* WC Order Tracker — Frontend JS (vanilla, no dependencies) */
     1/* Traceify — Frontend JS (vanilla, no dependencies) */
    22(function () {
    33  'use strict';
  • traceify/trunk/includes/class-trcfy-core.php

    r3716662 r3758167  
    1414        public function init() {
    1515                // Init new feature classes (always, not just admin).
     16                TRCFY_Order_Status::init();
     17                TRCFY_Shipment_Tracking::init();
    1618                TRCFY_Delivery_Estimator::init();
    1719                TRCFY_Email_Notifier::init();
  • traceify/trunk/includes/class-trcfy-delivery-estimator.php

    r3716662 r3758167  
    156156                        if ( $diff > 0 ) {
    157157                                /* translators: %d = number of days */
    158                                 $days_remaining = sprintf( _n( '%d day remaining', '%d days remaining', $diff, 'traceify' ), $diff );
     158                                $days_remaining = sprintf( _n( '%d day remaining', '%d days remaining', $diff, 'traceify-for-woocommerce' ), $diff );
    159159                        } elseif ( 0 === $diff ) {
    160                                 $days_remaining = __( 'Expected today!', 'traceify' );
     160                                $days_remaining = __( 'Expected today!', 'traceify-for-woocommerce' );
    161161                        } else {
    162                                 $days_remaining = __( 'Expected to have arrived', 'traceify' );
     162                                $days_remaining = __( 'Expected to have arrived', 'traceify-for-woocommerce' );
    163163                        }
    164164                }
    … …  
    188188                }
    189189
    190                 if ( isset( $_POST['trcfy_edd_min'] ) ) {
    191                         $min = sanitize_text_field( wp_unslash( $_POST['trcfy_edd_min'] ) );
    192                         $order->update_meta_data( '_trcfy_edd_min', $min );
    193                 }
    194                 if ( isset( $_POST['trcfy_edd_max'] ) ) {
    195                         $max = sanitize_text_field( wp_unslash( $_POST['trcfy_edd_max'] ) );
    196                         $order->update_meta_data( '_trcfy_edd_max', $max );
    197                 }
    198                 $order->save();
     190                // Accept only empty or a valid Y-m-d date; anything else is ignored.
     191                $changed = false;
     192                foreach ( array( 'min', 'max' ) as $bound ) {
     193                        $field = 'trcfy_edd_' . $bound;
     194                        if ( ! isset( $_POST[ $field ] ) ) {
     195                                continue;
     196                        }
     197                        $value = sanitize_text_field( wp_unslash( $_POST[ $field ] ) );
     198                        if ( '' !== $value && ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $value ) ) {
     199                                continue;
     200                        }
     201                        $order->update_meta_data( '_trcfy_edd_' . $bound, $value );
     202                        $changed = true;
     203                }
     204                if ( $changed ) {
     205                        $order->save();
     206                }
    199207        }
    200208}
  • traceify/trunk/includes/class-trcfy-email-notifier.php

    r3716662 r3758167  
    8989        private static function get_subject( WC_Order $order, $status ) {
    9090                $defaults = array(
    91                         'processing' => __( 'Your order #{order_number} is being processed', 'traceify' ),
    92                         'on-hold'    => __( 'Your order #{order_number} is on hold', 'traceify' ),
    93                         'shipped'    => __( 'Great news! Your order #{order_number} has been shipped 🚚', 'traceify' ),
    94                         'completed'  => __( 'Your order #{order_number} has been delivered ✅', 'traceify' ),
    95                         'cancelled'  => __( 'Your order #{order_number} has been cancelled', 'traceify' ),
     91                        'processing' => __( 'Your order #{order_number} is being processed', 'traceify-for-woocommerce' ),
     92                        'on-hold'    => __( 'Your order #{order_number} is on hold', 'traceify-for-woocommerce' ),
     93                        'shipped'    => __( 'Great news! Your order #{order_number} has been shipped 🚚', 'traceify-for-woocommerce' ),
     94                        'completed'  => __( 'Your order #{order_number} has been delivered ✅', 'traceify-for-woocommerce' ),
     95                        'cancelled'  => __( 'Your order #{order_number} has been cancelled', 'traceify-for-woocommerce' ),
    9696                );
    9797                $template = get_option(
    9898                        'trcfy_email_subject_' . $status,
    99                         isset( $defaults[ $status ] ) ? $defaults[ $status ] : __( 'Your order has been updated', 'traceify' )
     99                        isset( $defaults[ $status ] ) ? $defaults[ $status ] : __( 'Your order has been updated', 'traceify-for-woocommerce' )
    100100                );
    101101                return TRCFY_WhatsApp::replace_placeholders( $template, $order );
    … …  
    135135                        $edd = TRCFY_Delivery_Estimator::get_formatted( $order );
    136136                        if ( $edd ) {
    137                                 $edd_line = '<p style="background:#F0FDF4;border-left:4px solid #22C55E;padding:10px 14px;border-radius:0 6px 6px 0;margin:20px 0;font-size:14px;color:#166534;">📅 <strong>' . esc_html__( 'Estimated Delivery:', 'traceify' ) . '</strong> ' . esc_html( $edd ) . '</p>';
     137                                $edd_line = '<p style="background:#F0FDF4;border-left:4px solid #22C55E;padding:10px 14px;border-radius:0 6px 6px 0;margin:20px 0;font-size:14px;color:#166534;">📅 <strong>' . esc_html__( 'Estimated Delivery:', 'traceify-for-woocommerce' ) . '</strong> ' . esc_html( $edd ) . '</p>';
    138138                        }
     139                }
     140
     141                // Shipment tracking line.
     142                $shipment_line = '';
     143                $shipment      = TRCFY_Shipment_Tracking::get_data( $order );
     144                if ( $shipment['available'] ) {
     145                        $shipment_line = '<p style="background:#F5F3FF;border-left:4px solid ' . esc_attr( $brand_color ) . ';padding:10px 14px;border-radius:0 6px 6px 0;margin:20px 0;font-size:14px;color:#374151;">🚚 <strong>'
     146                                . esc_html( $shipment['courier'] ? $shipment['courier'] : __( 'Tracking number', 'traceify-for-woocommerce' ) ) . ':</strong> '
     147                                . esc_html( $shipment['number'] );
     148                        if ( $shipment['url'] ) {
     149                                $shipment_line .= ' &nbsp;<a href="' . esc_url( $shipment['url'] ) . '" target="_blank" rel="noopener noreferrer" style="color:' . esc_attr( $brand_color ) . ';font-weight:600;">' . esc_html__( 'Track shipment', 'traceify-for-woocommerce' ) . ' →</a>';
     150                        }
     151                        $shipment_line .= '</p>';
    139152                }
    140153
    … …  
    167180        public static function default_subjects() {
    168181                return array(
    169                         'processing' => __( 'Your order #{order_number} is being processed', 'traceify' ),
    170                         'on-hold'    => __( 'Your order #{order_number} is on hold', 'traceify' ),
    171                         'shipped'    => __( 'Great news! Your order #{order_number} has been shipped 🚚', 'traceify' ),
    172                         'completed'  => __( 'Your order #{order_number} has been delivered ✅', 'traceify' ),
    173                         'cancelled'  => __( 'Your order #{order_number} has been cancelled', 'traceify' ),
     182                        'processing' => __( 'Your order #{order_number} is being processed', 'traceify-for-woocommerce' ),
     183                        'on-hold'    => __( 'Your order #{order_number} is on hold', 'traceify-for-woocommerce' ),
     184                        'shipped'    => __( 'Great news! Your order #{order_number} has been shipped 🚚', 'traceify-for-woocommerce' ),
     185                        'completed'  => __( 'Your order #{order_number} has been delivered ✅', 'traceify-for-woocommerce' ),
     186                        'cancelled'  => __( 'Your order #{order_number} has been cancelled', 'traceify-for-woocommerce' ),
    174187                );
    175188        }
  • traceify/trunk/includes/class-trcfy-installer.php

    r3716662 r3758167  
    3131
    3232                $page_id = wp_insert_post( array(
    33                         'post_title'     => __( 'Track Your Order', 'traceify' ),
     33                        'post_title'     => __( 'Track Your Order', 'traceify-for-woocommerce' ),
    3434                        'post_content'   => '<!-- wp:shortcode -->[traceify_tracker]<!-- /wp:shortcode -->',
    3535                        'post_status'    => 'publish',
    … …  
    5959                        'trcfy_wa_number'            => '',
    6060                        'trcfy_wa_show_customer_btn' => 'yes',
    61                         'trcfy_wa_customer_btn_label'=> __( 'Chat with us on WhatsApp', 'traceify' ),
    62                         'trcfy_wa_msg_pending'       => __( 'Hi {customer_name}, we received your order #{order_number}. We\'ll start processing it shortly. Thank you for shopping with {store_name}! 🛍️', 'traceify' ),
    63                         'trcfy_wa_msg_processing'    => __( 'Hi {customer_name}, great news! Your order #{order_number} is now being processed and will be dispatched soon. — {store_name}', 'traceify' ),
    64                         'trcfy_wa_msg_on-hold'       => __( 'Hi {customer_name}, your order #{order_number} is on hold. Please contact us for more details. — {store_name}', 'traceify' ),
    65                         'trcfy_wa_msg_shipped'       => __( 'Hi {customer_name}, your order #{order_number} has been shipped and is on its way! 🚚 — {store_name}', 'traceify' ),
    66                         'trcfy_wa_msg_completed'     => __( 'Hi {customer_name}, your order #{order_number} has been delivered. We hope you love it! 💜 — {store_name}', 'traceify' ),
    67                         'trcfy_wa_msg_cancelled'     => __( 'Hi {customer_name}, your order #{order_number} has been cancelled. Contact us if this was a mistake. — {store_name}', 'traceify' ),
     61                        'trcfy_wa_customer_btn_label'=> __( 'Chat with us on WhatsApp', 'traceify-for-woocommerce' ),
     62                        'trcfy_wa_msg_pending'       => __( 'Hi {customer_name}, we received your order #{order_number}. We\'ll start processing it shortly. Thank you for shopping with {store_name}! 🛍️', 'traceify-for-woocommerce' ),
     63                        'trcfy_wa_msg_processing'    => __( 'Hi {customer_name}, great news! Your order #{order_number} is now being processed and will be dispatched soon. — {store_name}', 'traceify-for-woocommerce' ),
     64                        'trcfy_wa_msg_on-hold'       => __( 'Hi {customer_name}, your order #{order_number} is on hold. Please contact us for more details. — {store_name}', 'traceify-for-woocommerce' ),
     65                        'trcfy_wa_msg_shipped'       => __( 'Hi {customer_name}, your order #{order_number} has been shipped and is on its way! 🚚 — {store_name}', 'traceify-for-woocommerce' ),
     66                        'trcfy_wa_msg_completed'     => __( 'Hi {customer_name}, your order #{order_number} has been delivered. We hope you love it! 💜 — {store_name}', 'traceify-for-woocommerce' ),
     67                        'trcfy_wa_msg_cancelled'     => __( 'Hi {customer_name}, your order #{order_number} has been cancelled. Contact us if this was a mistake. — {store_name}', 'traceify-for-woocommerce' ),
    6868                        // Estimated Delivery Date.
    6969                        'trcfy_edd_enabled'          => 'yes',
    … …  
    7272                        'trcfy_edd_max_ship_days'    => '5',
    7373                        'trcfy_edd_exclude_weekends' => 'yes',
     74                        // Shipment tracking.
     75                        'trcfy_shipment_enabled'      => 'yes',
     76                        'trcfy_shipment_auto_shipped' => 'no',
     77                        'trcfy_custom_courier_name'   => '',
     78                        'trcfy_custom_courier_url'    => '',
    7479                        // Email notifications.
    7580                        'trcfy_email_enabled'            => 'yes',
  • traceify/trunk/includes/class-trcfy-order-tracker.php

    r3716662 r3758167  
    5555
    5656                $steps = array(
    57                         array( 'key' => 'placed',     'label' => __( 'Order Placed',  'traceify' ), 'icon' => '🛍️' ),
    58                         array( 'key' => 'processing', 'label' => __( 'Processing',    'traceify' ), 'icon' => '⚙️' ),
    59                         array( 'key' => 'shipped',    'label' => __( 'Shipped',       'traceify' ), 'icon' => '🚚' ),
    60                         array( 'key' => 'delivered',  'label' => __( 'Delivered',     'traceify' ), 'icon' => '✅' ),
     57                        array( 'key' => 'placed',     'label' => __( 'Order Placed',  'traceify-for-woocommerce' ), 'icon' => '🛍️' ),
     58                        array( 'key' => 'processing', 'label' => __( 'Processing',    'traceify-for-woocommerce' ), 'icon' => '⚙️' ),
     59                        array( 'key' => 'shipped',    'label' => __( 'Shipped',       'traceify-for-woocommerce' ), 'icon' => '🚚' ),
     60                        array( 'key' => 'delivered',  'label' => __( 'Delivered',     'traceify-for-woocommerce' ), 'icon' => '✅' ),
    6161                );
    6262
    … …  
    100100        private static function get_special_status_timeline( $status ) {
    101101                $labels = array(
    102                         'cancelled' => array( 'label' => __( 'Order Cancelled', 'traceify' ), 'icon' => '❌' ),
    103                         'refunded'  => array( 'label' => __( 'Order Refunded',  'traceify' ), 'icon' => '↩️' ),
    104                         'failed'    => array( 'label' => __( 'Payment Failed',  'traceify' ), 'icon' => '⚠️' ),
     102                        'cancelled' => array( 'label' => __( 'Order Cancelled', 'traceify-for-woocommerce' ), 'icon' => '❌' ),
     103                        'refunded'  => array( 'label' => __( 'Order Refunded',  'traceify-for-woocommerce' ), 'icon' => '↩️' ),
     104                        'failed'    => array( 'label' => __( 'Payment Failed',  'traceify-for-woocommerce' ), 'icon' => '⚠️' ),
    105105                );
    106106                $info = $labels[ $status ];
    … …  
    152152                        'timeline'        => self::get_timeline( $order ),
    153153                        'edd'             => TRCFY_Delivery_Estimator::get_data( $order ),
     154                        'shipment'        => TRCFY_Shipment_Tracking::get_data( $order ),
    154155                );
    155156        }
  • traceify/trunk/includes/class-trcfy-whatsapp.php

    r3716662 r3758167  
    7878                        $message = sprintf(
    7979                                /* translators: %s = order number */
    80                                 __( 'Hi, I have a question about my order #%s', 'traceify' ),
     80                                __( 'Hi, I have a question about my order #%s', 'traceify-for-woocommerce' ),
    8181                                $order->get_order_number()
    8282                        );
    8383                } else {
    84                         $message = __( 'Hi, I need help with my order.', 'traceify' );
     84                        $message = __( 'Hi, I need help with my order.', 'traceify-for-woocommerce' );
    8585                }
    8686
    … …  
    9393         * Supported tags: {customer_name} {order_number} {order_status}
    9494         *                 {order_total} {store_name} {tracking_url}
     95         *                 {tracking_number} {tracking_link} {courier_name}
    9596         *
    9697         * @param string   $template
    … …  
    102103                $tracking_url     = $tracking_page_id ? get_permalink( $tracking_page_id ) : site_url();
    103104
     105                $shipment = TRCFY_Shipment_Tracking::get_data( $order );
     106
    104107                $search  = array(
     108                        '{tracking_number}',
     109                        '{tracking_link}',
     110                        '{courier_name}',
    105111                        '{customer_name}',
    106112                        '{order_number}',
    … …  
    111117                );
    112118                $replace = array(
     119                        sanitize_text_field( $shipment['number'] ),
     120                        $shipment['url'],
     121                        sanitize_text_field( $shipment['courier'] ),
    113122                        sanitize_text_field( $order->get_billing_first_name() ),
    114123                        sanitize_text_field( $order->get_order_number() ),
  • traceify/trunk/public/class-trcfy-public.php

    r3716662 r3758167  
    2323
    2424                // Only load on the tracking page (or wherever the shortcode is used).
    25                 if ( ! is_page( $tracking_page_id ) && ! $this->current_page_has_shortcode() ) {
     25                if ( ! ( $tracking_page_id && is_page( $tracking_page_id ) ) && ! $this->current_page_has_shortcode() ) {
    2626                        return;
    2727                }
    … …  
    7070                $submitted  = false;
    7171
    72                 // Process form submission (GET method, WooCommerce-style).
    73                 if ( isset( $_GET['trcfy_order_id'], $_GET['trcfy_billing_email'], $_GET['trcfy_nonce'] ) ) {
     72                // Process lookup (GET, WooCommerce-style). This is a read-only lookup that
     73                // requires order number + matching billing email, so no nonce is used —
     74                // a nonce here would break on cached pages and adds no protection.
     75                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only lookup, verified by order number + billing email.
     76                if ( isset( $_GET['trcfy_order_id'], $_GET['trcfy_billing_email'] ) ) {
    7477                        $submitted = true;
    7578
    76                         if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['trcfy_nonce'] ) ), 'trcfy_track_order' ) ) {
    77                                 $error = __( 'Security check failed. Please try again.', 'traceify' );
    78                         } else {
    79                                 $order_id = sanitize_text_field( wp_unslash( $_GET['trcfy_order_id'] ) );
    80                                 $email    = sanitize_email( wp_unslash( $_GET['trcfy_billing_email'] ) );
    81                                 $order    = TRCFY_Order_Tracker::get_order( $order_id, $email );
     79                        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     80                        $order_id = sanitize_text_field( wp_unslash( $_GET['trcfy_order_id'] ) );
     81                        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     82                        $email    = sanitize_email( wp_unslash( $_GET['trcfy_billing_email'] ) );
     83                        $order    = TRCFY_Order_Tracker::get_order( $order_id, $email );
    8284
    83                                 if ( ! $order ) {
    84                                         $error = __( 'No order found. Please check your order number and billing email and try again.', 'traceify' );
    85                                 }
     85                        if ( ! $order ) {
     86                                $error = __( 'No order found. Please check your order number and billing email and try again.', 'traceify-for-woocommerce' );
    8687                        }
    8788                }
    … …  
    9293                        'error'      => $error,
    9394                        'submitted'  => $submitted,
    94                         'nonce'      => wp_create_nonce( 'trcfy_track_order' ),
    9595                        'logo_url'   => esc_url( get_option( 'trcfy_brand_logo_url', '' ) ),
    9696                        'store_name' => esc_html( get_option( 'trcfy_store_name', get_bloginfo( 'name' ) ) ),
    9797                        'wa_number'  => get_option( 'trcfy_wa_number', '' ),
    9898                        'show_wa_btn'=> 'yes' === get_option( 'trcfy_wa_show_customer_btn', 'yes' ),
    99                         'wa_btn_label'=> esc_html( get_option( 'trcfy_wa_customer_btn_label', __( 'Chat with us on WhatsApp', 'traceify' ) ) ),
     99                        'wa_btn_label'=> esc_html( get_option( 'trcfy_wa_customer_btn_label', __( 'Chat with us on WhatsApp', 'traceify-for-woocommerce' ) ) ),
    100100                );
    101101
  • traceify/trunk/public/views/tracking-page.php

    r3716662 r3758167  
    66 * Receives $data array from TRCFY_Public::render_shortcode().
    77 * All dynamic values are already sanitized — escape on output only.
    8  * Nonce verification for the tracking form is handled in render_shortcode()
    9  * before this template is loaded; $_GET access here is read-only prefill.
     8 * $_GET access here is read-only prefill of the lookup form.
    109 */
    1110if ( ! defined( 'ABSPATH' ) ) { exit; }
    … …  
    2120                <?php endif; ?>
    2221                <h2 class="trcfy-title">
    23                         <?php esc_html_e( 'Track Your Order', 'traceify' ); ?>
     22                        <?php esc_html_e( 'Track Your Order', 'traceify-for-woocommerce' ); ?>
    2423                </h2>
    2524        </div>
    … …  
    3635
    3736                <p class="trcfy-search-intro">
    38                         <?php esc_html_e( 'Enter your order number and billing email address to check your order status.', 'traceify' ); ?>
     37                        <?php esc_html_e( 'Enter your order number and billing email address to check your order status.', 'traceify-for-woocommerce' ); ?>
    3938                </p>
    4039
    4140                <form method="GET" action="" class="trcfy-form" id="trcfy-tracking-form" novalidate>
    42                         <input type="hidden" name="trcfy_nonce" value="<?php echo esc_attr( $data['nonce'] ); ?>">
    4341
    4442                        <div class="trcfy-field">
    4543                                <label for="trcfy_order_id" class="trcfy-label">
    46                                         <?php esc_html_e( 'Order Number', 'traceify' ); ?>
     44                                        <?php esc_html_e( 'Order Number', 'traceify-for-woocommerce' ); ?>
    4745                                        <span class="trcfy-required" aria-hidden="true">*</span>
    4846                                </label>
    4947                                <?php
    50                                 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce verified in render_shortcode(); this is prefill only.
     48                                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only prefill of the lookup form.
    5149                                $trcfy_prefill_order_id = isset( $_GET['trcfy_order_id'] ) ? sanitize_text_field( wp_unslash( $_GET['trcfy_order_id'] ) ) : '';
    5250                                ?>
    … …  
    5654                                        class="trcfy-input"
    5755                                        inputmode="numeric"
    58                                         placeholder="<?php esc_attr_e( 'e.g. 1234', 'traceify' ); ?>"
     56                                        placeholder="<?php esc_attr_e( 'e.g. 1234', 'traceify-for-woocommerce' ); ?>"
    5957                                        value="<?php echo esc_attr( $trcfy_prefill_order_id ); ?>"
    6058                                        required
    … …  
    6462                        <div class="trcfy-field">
    6563                                <label for="trcfy_billing_email" class="trcfy-label">
    66                                         <?php esc_html_e( 'Billing Email Address', 'traceify' ); ?>
     64                                        <?php esc_html_e( 'Billing Email Address', 'traceify-for-woocommerce' ); ?>
    6765                                        <span class="trcfy-required" aria-hidden="true">*</span>
    6866                                </label>
    6967                                <?php
    70                                 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce verified in render_shortcode(); this is prefill only.
     68                                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only prefill of the lookup form.
    7169                                $trcfy_prefill_email = isset( $_GET['trcfy_billing_email'] ) ? sanitize_email( wp_unslash( $_GET['trcfy_billing_email'] ) ) : '';
    7270                                ?>
    … …  
    7573                                        name="trcfy_billing_email"
    7674                                        class="trcfy-input"
    77                                         placeholder="<?php esc_attr_e( 'you@example.com', 'traceify' ); ?>"
     75                                        placeholder="<?php esc_attr_e( 'you@example.com', 'traceify-for-woocommerce' ); ?>"
    7876                                        value="<?php echo esc_attr( $trcfy_prefill_email ); ?>"
    7977                                        required
    … …  
    8381                        <button type="submit" class="trcfy-btn trcfy-btn-primary">
    8482                                <span class="trcfy-btn-icon">🔍</span>
    85                                 <?php esc_html_e( 'Track Order', 'traceify' ); ?>
     83                                <?php esc_html_e( 'Track Order', 'traceify-for-woocommerce' ); ?>
    8684                        </button>
    8785                </form>
    … …  
    10098                <div class="trcfy-order-meta">
    10199                        <div>
    102                                 <span class="trcfy-meta-label"><?php esc_html_e( 'Order', 'traceify' ); ?></span>
     100                                <span class="trcfy-meta-label"><?php esc_html_e( 'Order', 'traceify-for-woocommerce' ); ?></span>
    103101                                <span class="trcfy-meta-value">#<?php echo esc_html( $trcfy_d['order_number'] ); ?></span>
    104102                        </div>
    105103                        <div>
    106                                 <span class="trcfy-meta-label"><?php esc_html_e( 'Placed on', 'traceify' ); ?></span>
     104                                <span class="trcfy-meta-label"><?php esc_html_e( 'Placed on', 'traceify-for-woocommerce' ); ?></span>
    107105                                <span class="trcfy-meta-value"><?php echo esc_html( $trcfy_d['date_created'] ); ?></span>
    108106                        </div>
    109107                        <div>
    110                                 <span class="trcfy-meta-label"><?php esc_html_e( 'Status', 'traceify' ); ?></span>
     108                                <span class="trcfy-meta-label"><?php esc_html_e( 'Status', 'traceify-for-woocommerce' ); ?></span>
    111109                                <span class="trcfy-status-badge trcfy-status-<?php echo esc_attr( $trcfy_status ); ?>">
    112110                                        <?php echo esc_html( $trcfy_d['status_label'] ); ?>
    … …  
    162160                        <span class="trcfy-edd-icon" aria-hidden="true">📅</span>
    163161                        <div class="trcfy-edd-content">
    164                                 <span class="trcfy-edd-label"><?php esc_html_e( 'Estimated Delivery', 'traceify' ); ?></span>
     162                                <span class="trcfy-edd-label"><?php esc_html_e( 'Estimated Delivery', 'traceify-for-woocommerce' ); ?></span>
    165163                                <span class="trcfy-edd-date"><?php echo esc_html( $trcfy_d['edd']['formatted'] ); ?></span>
    166164                                <?php if ( $trcfy_d['edd']['days_remaining'] ) : ?>
    … …  
    172170        <?php endif; ?>
    173171
     172        <!-- ── Shipment tracking ── -->
     173        <?php if ( ! $trcfy_is_special && ! empty( $trcfy_d['shipment']['available'] ) ) : ?>
     174        <div class="trcfy-card trcfy-ship-card">
     175                <div class="trcfy-edd-inner">
     176                        <span class="trcfy-edd-icon" aria-hidden="true">🚚</span>
     177                        <div class="trcfy-edd-content">
     178                                <span class="trcfy-edd-label">
     179                                        <?php
     180                                        echo esc_html(
     181                                                $trcfy_d['shipment']['courier']
     182                                                        ? sprintf(
     183                                                                /* translators: %s = courier name */
     184                                                                __( 'Shipped with %s', 'traceify-for-woocommerce' ),
     185                                                                $trcfy_d['shipment']['courier']
     186                                                        )
     187                                                        : __( 'Tracking number', 'traceify-for-woocommerce' )
     188                                        );
     189                                        ?>
     190                                </span>
     191                                <span class="trcfy-edd-date trcfy-ship-number"><?php echo esc_html( $trcfy_d['shipment']['number'] ); ?></span>
     192                        </div>
     193                        <?php if ( $trcfy_d['shipment']['url'] ) : ?>
     194                                <a href="<?php echo esc_url( $trcfy_d['shipment']['url'] ); ?>"
     195                                        target="_blank" rel="noopener noreferrer"
     196                                        class="trcfy-btn trcfy-btn-primary trcfy-ship-btn">
     197                                        <?php esc_html_e( 'Track shipment', 'traceify-for-woocommerce' ); ?> ↗
     198                                </a>
     199                        <?php endif; ?>
     200                </div>
     201        </div>
     202        <?php endif; ?>
     203
    174204        <!-- ── Order items ── -->
    175205        <div class="trcfy-card trcfy-items-card">
    176                 <h3 class="trcfy-card-title"><?php esc_html_e( 'Order Summary', 'traceify' ); ?></h3>
     206                <h3 class="trcfy-card-title"><?php esc_html_e( 'Order Summary', 'traceify-for-woocommerce' ); ?></h3>
    177207                <div class="trcfy-items-list">
    178208                        <?php foreach ( $trcfy_d['items'] as $trcfy_item ) : ?>
    … …  
    191221                                                printf(
    192222                                                        /* translators: %d = quantity */
    193                                                         esc_html__( 'Qty: %d', 'traceify' ),
     223                                                        esc_html__( 'Qty: %d', 'traceify-for-woocommerce' ),
    194224                                                        absint( $trcfy_item['qty'] )
    195225                                                );
    … …  
    204234                        <?php if ( $trcfy_d['shipping_method'] ) : ?>
    205235                        <div class="trcfy-total-row">
    206                                 <span><?php esc_html_e( 'Shipping', 'traceify' ); ?></span>
     236                                <span><?php esc_html_e( 'Shipping', 'traceify-for-woocommerce' ); ?></span>
    207237                                <span><?php echo esc_html( $trcfy_d['shipping_method'] ); ?></span>
    208238                        </div>
    209239                        <?php endif; ?>
    210240                        <div class="trcfy-total-row trcfy-total-grand">
    211                                 <span><?php esc_html_e( 'Total', 'traceify' ); ?></span>
     241                                <span><?php esc_html_e( 'Total', 'traceify-for-woocommerce' ); ?></span>
    212242                                <span><?php echo wp_kses_post( $trcfy_d['total'] ); ?></span>
    213243                        </div>
    … …  
    218248        <?php if ( ! empty( $trcfy_d['notes'] ) ) : ?>
    219249        <div class="trcfy-card trcfy-notes-card">
    220                 <h3 class="trcfy-card-title"><?php esc_html_e( 'Order Updates', 'traceify' ); ?></h3>
     250                <h3 class="trcfy-card-title"><?php esc_html_e( 'Order Updates', 'traceify-for-woocommerce' ); ?></h3>
    221251                <?php foreach ( $trcfy_d['notes'] as $trcfy_note ) : ?>
    222252                <div class="trcfy-note">
    … …  
    231261        <?php if ( $trcfy_d['shipping_address'] ) : ?>
    232262        <div class="trcfy-card trcfy-address-card">
    233                 <h3 class="trcfy-card-title"><?php esc_html_e( 'Shipping To', 'traceify' ); ?></h3>
     263                <h3 class="trcfy-card-title"><?php esc_html_e( 'Shipping To', 'traceify-for-woocommerce' ); ?></h3>
    234264                <address class="trcfy-address"><?php echo wp_kses_post( $trcfy_d['shipping_address'] ); ?></address>
    235265        </div>
    … …  
    251281        <!-- ── Track another ── -->
    252282        <div class="trcfy-track-another">
    253                 <a href="<?php echo esc_url( remove_query_arg( array( 'trcfy_order_id', 'trcfy_billing_email', 'trcfy_nonce' ) ) ); ?>"
     283                <a href="<?php echo esc_url( remove_query_arg( array( 'trcfy_order_id', 'trcfy_billing_email' ) ) ); ?>"
    254284                   class="trcfy-link">
    255                         ← <?php esc_html_e( 'Track another order', 'traceify' ); ?>
     285                        ← <?php esc_html_e( 'Track another order', 'traceify-for-woocommerce' ); ?>
    256286                </a>
    257287        </div>
  • traceify/trunk/readme.txt

    r3716662 r3758167  
    11=== Traceify – Order Tracking for WooCommerce ===
    22Contributors:      webtendhq,devhasib
    3 Tags:              woocommerce, order tracking, whatsapp, estimated delivery, order status
     3Tags:              woocommerce, order tracking, shipment tracking, whatsapp, estimated delivery
    44Requires at least: 6.0
    55Tested up to:      7.1
    66Requires PHP:      7.4
    7 Stable tag:        1.0.0
     7Stable tag:        1.0.1
    88License:           GPLv2 or later
    99License URI:       https://www.gnu.org/licenses/gpl-2.0.html
    1010
    11 Branded order tracking page for WooCommerce with WhatsApp updates, estimated delivery dates, and email notifications — no API or monthly fee.
     11Branded order tracking for WooCommerce with courier links, WhatsApp updates, delivery dates and email alerts — no API or monthly fee.
    1212
    1313== Description ==
    1414
    1515**Traceify** gives your WooCommerce store a professional, branded order-tracking experience — and the tools to proactively keep customers updated via WhatsApp and email.
     16
     17📖 **[Documentation](https://webtend.net/docs/traceify-doc.html)**
     18
    1619
    1720= Customer-Facing Features =
    … …  
    2023* **Visual progress timeline** — Order Placed → Processing → Shipped → Delivered
    2124* **Estimated Delivery Date** — auto-calculated date range shown prominently on the tracking page
     25* **Shipment tracking** — courier name, tracking number and a "Track shipment" button that opens the courier's site
    2226* **Order summary** — items with images, quantities, totals, and shipping address
    2327* **Customer order notes** — shows notes you have added to the order
    … …  
    2832* **WhatsApp column** on the WooCommerce orders list — one click to send a status update to any customer
    2933* **WhatsApp meta box** on every order detail page — preview the message then send
     34* **Shipment Tracking meta box** — pick a courier and enter the tracking number on any order
    3035* **Estimated Delivery Date meta box** — manually override the auto-calculated delivery date per order
    3136* **Branded HTML email notifications** — send beautiful order-status emails on status change
    3237* **Per-status message templates** for both WhatsApp and email
    33 * **Template placeholders**: `{customer_name}` `{order_number}` `{order_status}` `{order_total}` `{store_name}` `{tracking_url}`
     38* **Template placeholders**: `{customer_name}` `{order_number}` `{order_status}` `{order_total}` `{store_name}` `{tracking_url}` `{tracking_number}` `{tracking_link}` `{courier_name}`
     39
     40= Shipment Tracking =
     41
     42Add a courier and tracking number to any order. Built-in couriers: DHL, FedEx, UPS, USPS and Steadfast. Add your own courier (for example Pathao or RedX) under Traceify → Shipment Tracking with a URL such as `https://example.com/track?id={tracking_number}`. The tracking number and link appear on the customer's tracking page, in Traceify emails and in WhatsApp messages. Optionally mark the order as Shipped automatically when a tracking number is first added.
    3443
    3544= Estimated Delivery Date =
    … …  
    5059* **WhatsApp** — business number, show/hide customer contact button, per-status message templates
    5160* **Tracking Page** — page assignment, shortcode reference
     61* **Shipment Tracking** — enable/disable, auto-mark as Shipped, custom courier name and tracking URL
    5262* **Delivery EDD** — processing days, min/max shipping days, weekend exclusion toggle
    5363* **Email Notifications** — master toggle, per-status on/off, custom subject lines
    … …  
    8696No. By default, only the "Shipped" status email is enabled — WooCommerce has no built-in email for that status. Processing, Completed, Cancelled, and On Hold emails are off by default.
    8797
     98= Can I add a courier that is not in the list? =
     99
     100Yes. Go to Traceify → Shipment Tracking → Custom Courier and enter a name and a tracking URL containing `{tracking_number}`. Developers can also use the `trcfy_couriers` filter.
     101
     102= Where does the "Shipped" status come from? =
     103
     104WooCommerce has no Shipped status. Traceify registers one (`wc-shipped`) only if no other plugin has already done so.
     105
    88106= Is customer data secure? =
    89107
    90 Yes. Order lookup requires both the order number and the billing email address, preventing order enumeration. All inputs are sanitized, all outputs are escaped, and forms are nonce-protected.
     108Yes. Order lookup requires both the order number and the billing email address, preventing order enumeration. All inputs are sanitized and all outputs are escaped. Admin settings and order actions are capability-checked and nonce-protected.
    91109
    92110== Screenshots ==
    … …  
    104122== Changelog ==
    105123
     124= 1.0.1 =
     125* New: Shipment tracking — courier + tracking number per order with a "Track shipment" link.
     126* New: Built-in couriers (DHL, FedEx, UPS, USPS, Steadfast) plus a custom courier with your own tracking URL.
     127* New: Tracking details on the customer tracking page and in branded emails.
     128* New: WhatsApp placeholders `{tracking_number}`, `{tracking_link}` and `{courier_name}`.
     129* New: Optional "Auto-mark as Shipped" when a tracking number is first added.
     130* New: `trcfy_couriers` filter to add or change couriers in code.
     131
     132
     133
    106134= 1.0.0 — 2026-09-05 =
    107135* Initial release.
    … …  
    116144== Upgrade Notice ==
    117145
     146= 1.0.1 =
     147Adds shipment tracking (courier + tracking number). Review Traceify → Shipment Tracking after updating.
     148
     149
    118150= 1.0.0 =
    119151Initial release.
  • traceify/trunk/templates/email-notification.php

    r3716662 r3758167  
    4848        printf(
    4949          /* translators: %s = order number */
    50           esc_html__( 'Order #%s Update', 'traceify' ),
     50          esc_html__( 'Order #%s Update', 'traceify-for-woocommerce' ),
    5151          esc_html( $order->get_order_number() )
    5252        );
    … …  
    5757        printf(
    5858          /* translators: %s = customer first name */
    59           esc_html__( 'Hi %s, here\'s the latest on your order.', 'traceify' ),
     59          esc_html__( 'Hi %s, here\'s the latest on your order.', 'traceify-for-woocommerce' ),
    6060          esc_html( $order->get_billing_first_name() )
    6161        );
    … …  
    8585  <?php endif; ?>
    8686
     87  <!-- Shipment tracking block -->
     88  <?php if ( ! empty( $shipment_line ) ) : ?>
     89  <tr>
     90    <td style="padding:0 40px;">
     91      <?php echo wp_kses_post( $shipment_line ); ?>
     92    </td>
     93  </tr>
     94  <?php endif; ?>
     95
    8796  <!-- Order items -->
    8897  <tr>
    8998    <td style="padding:24px 40px 0;">
    9099      <p style="font-size:13px;font-weight:600;color:#6B7280;text-transform:uppercase;letter-spacing:0.06em;margin:0 0 10px;">
    91         <?php esc_html_e( 'Order Summary', 'traceify' ); ?>
     100        <?php esc_html_e( 'Order Summary', 'traceify-for-woocommerce' ); ?>
    92101      </p>
    93102      <table width="100%" cellpadding="0" cellspacing="0">
    94103        <thead>
    95104          <tr>
    96             <th style="font-size:12px;color:#9CA3AF;font-weight:500;text-align:left;padding-bottom:6px;"><?php esc_html_e( 'Product', 'traceify' ); ?></th>
    97             <th style="font-size:12px;color:#9CA3AF;font-weight:500;text-align:right;padding-bottom:6px;"><?php esc_html_e( 'Qty', 'traceify' ); ?></th>
    98             <th style="font-size:12px;color:#9CA3AF;font-weight:500;text-align:right;padding-bottom:6px;"><?php esc_html_e( 'Price', 'traceify' ); ?></th>
     105            <th style="font-size:12px;color:#9CA3AF;font-weight:500;text-align:left;padding-bottom:6px;"><?php esc_html_e( 'Product', 'traceify-for-woocommerce' ); ?></th>
     106            <th style="font-size:12px;color:#9CA3AF;font-weight:500;text-align:right;padding-bottom:6px;"><?php esc_html_e( 'Qty', 'traceify-for-woocommerce' ); ?></th>
     107            <th style="font-size:12px;color:#9CA3AF;font-weight:500;text-align:right;padding-bottom:6px;"><?php esc_html_e( 'Price', 'traceify-for-woocommerce' ); ?></th>
    99108          </tr>
    100109        </thead>
    … …  
    104113        <tfoot>
    105114          <tr>
    106             <td colspan="2" style="padding-top:10px;font-size:15px;font-weight:700;color:#111827;"><?php esc_html_e( 'Total', 'traceify' ); ?></td>
     115            <td colspan="2" style="padding-top:10px;font-size:15px;font-weight:700;color:#111827;"><?php esc_html_e( 'Total', 'traceify-for-woocommerce' ); ?></td>
    107116            <td style="padding-top:10px;font-size:15px;font-weight:700;color:#111827;text-align:right;"><?php echo wp_kses_post( $order->get_formatted_order_total() ); ?></td>
    108117          </tr>
    … …  
    118127      <a href="<?php echo esc_url( $tracking_url . '?trcfy_order_id=' . $order->get_order_number() ); ?>"
    119128         style="display:inline-block;background:<?php echo esc_attr( $brand_color ); ?>;color:#ffffff;text-decoration:none;font-size:15px;font-weight:600;padding:13px 28px;border-radius:8px;">
    120         <?php esc_html_e( 'Track Your Order →', 'traceify' ); ?>
     129        <?php esc_html_e( 'Track Your Order →', 'traceify-for-woocommerce' ); ?>
    121130      </a>
    122131    </td>
    … …  
    131140        printf(
    132141          /* translators: %s = store name */
    133           esc_html__( 'You received this email because you placed an order at %s.', 'traceify' ),
     142          esc_html__( 'You received this email because you placed an order at %s.', 'traceify-for-woocommerce' ),
    134143          esc_html( $store_name )
    135144        );
  • traceify/trunk/traceify-for-woocommerce.php

    r3716672 r3758167  
    33 * Plugin Name:       Traceify – Order Tracking for WooCommerce
    44 * Plugin URI:        https://webtend.net/
    5  * Description:       Replace WooCommerce's plain order tracking with a beautiful branded page. Send one-click WhatsApp status updates to customers — no API or monthly fee needed.
    6  * Version:           1.0.0
     5 * Description:       Branded order tracking and shipment tracking for WooCommerce. Add courier tracking numbers and send one-click WhatsApp status updates — no API or monthly fee needed.
     6 * Version:           1.0.1
    77 * Requires at least: 6.0
    88 * Requires PHP:      7.4
     9 * Requires Plugins:  woocommerce
    910 * Author:            WebTend
    1011 * Author URI:        https://webtend.net/
    1112 * License:           GPL v2 or later
    1213 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
    13  * Text Domain:       traceify
    14  * Domain Path:       /languages
     14 * Text Domain:       traceify-for-woocommerce
    1515 * WC requires at least: 7.0
    1616 * WC tested up to:   9.9
    … …  
    2626
    2727// ── Constants ──────────────────────────────────────────────────────────────
    28 define( 'TRCFY_VERSION',  '1.0.0' );
     28define( 'TRCFY_VERSION',  '1.0.1' );
    2929define( 'TRCFY_PATH',     plugin_dir_path( __FILE__ ) );
    3030define( 'TRCFY_URL',      plugin_dir_url( __FILE__ ) );
    … …  
    4242function trcfy_woocommerce_missing_notice() {
    4343        echo '<div class="notice notice-error"><p>' .
    44                 esc_html__( 'WC Order Tracker requires WooCommerce to be installed and activated.', 'traceify' ) .
     44                esc_html__( 'Traceify requires WooCommerce to be installed and activated.', 'traceify-for-woocommerce' ) .
    4545                '</p></div>';
    4646}
    … …  
    4848function trcfy_check_woocommerce() {
    4949        if ( ! class_exists( 'WooCommerce' ) ) {
     50                // Only show a notice. deactivate_plugins() is not loaded on the front end
     51                // and would cause a fatal error there.
    5052                add_action( 'admin_notices', 'trcfy_woocommerce_missing_notice' );
    51                 deactivate_plugins( TRCFY_BASENAME );
    5253                return false;
    5354        }
    … …  
    6061                deactivate_plugins( TRCFY_BASENAME );
    6162                wp_die(
    62                         esc_html__( 'WC Order Tracker requires WooCommerce. Please install WooCommerce first.', 'traceify' ),
    63                         esc_html__( 'Plugin Activation Error', 'traceify' ),
     63                        esc_html__( 'Traceify requires WooCommerce. Please install WooCommerce first.', 'traceify-for-woocommerce' ),
     64                        esc_html__( 'Plugin Activation Error', 'traceify-for-woocommerce' ),
    6465                        array( 'back_link' => true )
    6566                );
    … …  
    8384        require_once TRCFY_PATH . 'includes/class-trcfy-installer.php';
    8485        require_once TRCFY_PATH . 'includes/class-trcfy-order-tracker.php';
     86        require_once TRCFY_PATH . 'includes/class-trcfy-order-status.php';
     87        require_once TRCFY_PATH . 'includes/class-trcfy-shipment-tracking.php';
    8588        require_once TRCFY_PATH . 'includes/class-trcfy-whatsapp.php';
    8689        require_once TRCFY_PATH . 'includes/class-trcfy-delivery-estimator.php';
Note: See TracChangeset for help on using the changeset viewer.