diff --git a/.gitignore b/.gitignore index 496ee2ca6..c92743d55 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,12 @@ -.DS_Store \ No newline at end of file +.DS_Store +node_modules +coverage +.env +*.log +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? \ No newline at end of file diff --git a/includes/Coupon.php b/includes/Coupon.php index d05938e8b..0cc410d27 100644 --- a/includes/Coupon.php +++ b/includes/Coupon.php @@ -612,6 +612,9 @@ class Coupon { $args['s'] = sanitize_text_field( wp_unslash($_REQUEST['search']) ); } + // Handle status filtering (active/inactive) + $status_filter = isset($_REQUEST['status']) ? sanitize_text_field($_REQUEST['status']) : 'all'; + $get_coupons = get_posts($args); $global_currencies = get_global_currency_array(); @@ -619,13 +622,19 @@ class Coupon { if(!empty($get_coupons)){ foreach($get_coupons as $key => $coupon){ - $active = true; + $is_active = formipay_get_post_meta($coupon->ID, 'active') == 'on'; + + // Apply status filter + if ($status_filter !== 'all') { + if ($status_filter === 'active' && !$is_active) continue; + if ($status_filter === 'inactive' && $is_active) continue; + } $date_limit = formipay_get_post_meta($coupon->ID, 'date_limit'); $type = formipay_get_post_meta($coupon->ID, 'type'); $amount_meta_key = "amount_$type"; - + if($type == 'fixed'){ $amount_value = []; foreach($global_currencies as $currency){ @@ -646,23 +655,21 @@ class Coupon { $amount_value = floatval(formipay_get_post_meta($coupon->ID, $amount_meta_key)); } - - if($active){ - $coupons[] = [ - 'ID' => $coupon->ID, - 'code' => get_the_title($coupon->ID), - 'value' => $amount_value, - 'type' => ucfirst(formipay_get_post_meta($coupon->ID, 'type')), - 'case_sensitive' => formipay_get_post_meta($coupon->ID, 'case_sensitive'), - 'usages' => [ - 'used' => $this->count_order_by_coupon_code(get_the_title($coupon->ID)), - 'limit' => (intval(formipay_get_post_meta($coupon->ID, 'use_limit')) > 0) ? formipay_get_post_meta($coupon->ID, 'use_limit') : '∞' - ], - 'date_limit' => false !== $date_limit ? formipay_date('Y-m-d', intval(formipay_get_post_meta($coupon->ID, 'date_limit')) / 1000) : 'none', - 'status' => (formipay_get_post_meta($coupon->ID, 'active') == 'on') ? 'Active' : 'Inactive' - ]; - } + + $coupons[] = [ + 'ID' => $coupon->ID, + 'code' => get_the_title($coupon->ID), + 'amount' => $amount_value, + 'type' => ucfirst(formipay_get_post_meta($coupon->ID, 'type')), + 'case_sensitive' => formipay_get_post_meta($coupon->ID, 'case_sensitive'), + 'usage_count' => $this->count_order_by_coupon_code(get_the_title($coupon->ID)), + 'usages' => $this->count_order_by_coupon_code(get_the_title($coupon->ID)), + 'date_limit' => false !== $date_limit ? formipay_date('Y-m-d', intval(formipay_get_post_meta($coupon->ID, 'date_limit')) / 1000) : 'none', + 'active' => $is_active ? 'on' : 'off', + 'post_status' => $is_active ? 'active' : 'inactive', + 'status' => $is_active ? 'active' : 'inactive' + ]; } } diff --git a/includes/Order.php b/includes/Order.php index a3cfb2e52..2976aeddc 100644 --- a/includes/Order.php +++ b/includes/Order.php @@ -646,7 +646,7 @@ class Order { // React admin printf( - '
', + '
', esc_attr($page) ); @@ -933,21 +933,31 @@ class Order { // Process filtered orders if (!empty($get_filtered_orders)) { - foreach ($get_filtered_orders as $key => $order) { + foreach ($get_filtered_orders as $key => $order) { $currency = explode(':::', formipay_get_post_meta($order->form_id, 'product_currency')); - $code = !empty($currency[0]) ? $currency[0] : ''; - // Prepare order data + $code = !empty($currency[0]) ? $currency[0] : ''; + + // Keep status as-is (with hyphens) to match STATUS_COLORS keys + $status = $order->status; + + // Transform form_data to the structure expected by OrderListItem + $raw_form_data = maybe_unserialize($order->form_data); + $transformed_form_data = []; + if (is_array($raw_form_data)) { + foreach ($raw_form_data as $field_key => $field_value) { + $transformed_form_data[] = [ + 'name' => $field_key, + 'value' => is_array($field_value) && isset($field_value['value']) ? $field_value['value'] : $field_value, + ]; + } + } + $orders[] = [ - 'ID' => $order->id, - 'form' => get_the_title($order->form_id), - 'date' => $order->created_date, - 'payment_gateway' => ucwords(str_replace('_', ' ', $order->payment_gateway)), - 'status' => ucwords(str_replace('-', ' ', $order->status)), - 'total' => [ - 'flag' => formipay_get_flag_by_currency($code), - 'name' => $code, - 'value' => formipay_price_format($order->total, $order->form_id), - ] + 'id' => $order->id, + 'created_date' => $order->created_date, + 'form_data' => $transformed_form_data, + 'total_formatted' => formipay_price_format($order->total, $order->form_id), + 'status' => $status, ]; } } diff --git a/includes/Product.php b/includes/Product.php index d232e9756..c10b20ba5 100644 --- a/includes/Product.php +++ b/includes/Product.php @@ -161,7 +161,7 @@ class Product { 'confirmButton' => esc_html__( 'Confirm', 'formipay' ) ], ], - 'nonce' => wp_create_nonce('formipay-admin-product-page') + 'nonce' => wp_create_nonce('formipay-admin') ] ); } @@ -590,7 +590,7 @@ class Product { public function formipay_tabledata_products() { - check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' ); + check_ajax_referer( 'formipay-admin', '_wpnonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => 'Unauthorized' ] ); @@ -668,26 +668,66 @@ class Product { $total_products = $query->found_posts; // Process results + $global_currencies = get_global_currency_array(); $products = []; foreach ($product_ids as $product_id) { $product = get_post($product_id); - + $currency = explode(':::', get_post_meta($product_id, 'product_currency', true)); $categories = wp_get_post_terms($product_id, 'formipay-product-category', ['fields' => 'names']); - + + // Build multi-currency prices array + $prices = []; + foreach ($global_currencies as $curr) { + $curr_raw = $curr['currency']; + $curr_parts = explode(':::', $curr_raw); + $curr_code = $curr_parts[0] ?? ''; + $symbol = formipay_get_currency_data_by_value($curr_raw, 'symbol'); + + $regular_price = get_post_meta($product_id, 'setting_product_price_regular_' . $symbol, true); + $sale_price = get_post_meta($product_id, 'setting_product_price_sale_' . $symbol, true); + + // Only add if we have at least a regular price + if (!empty($regular_price)) { + // Format price using this currency's own formatting rules + $decimal_digits = intval($curr['decimal_digits'] ?? 2); + $decimal_symbol = $curr['decimal_symbol'] ?? '.'; + $thousand_separator = $curr['thousand_separator'] ?? ','; + + $formatted_regular = $symbol . ' ' . number_format(floatval($regular_price), $decimal_digits, $decimal_symbol, $thousand_separator); + $formatted_sale = !empty($sale_price) ? $symbol . ' ' . number_format(floatval($sale_price), $decimal_digits, $decimal_symbol, $thousand_separator) : ''; + + $prices[] = [ + 'currency' => $curr_code, + 'symbol' => $symbol, + 'flag' => formipay_get_flag_by_currency($curr_raw), + 'regular_price' => $formatted_regular, + 'sale_price' => $formatted_sale, + 'has_sale' => !empty($sale_price), + ]; + } + } + + // Fallback to single price if no multi-currency prices set + if (empty($prices)) { + $fallback_price = get_post_meta($product_id, 'price', true); + $prices[] = [ + 'currency' => $currency[0] ?? 'USD', + 'symbol' => $currency[2] ?? '$', + 'flag' => formipay_get_flag_by_currency($currency[0] ?? ''), + 'regular_price' => formipay_price_format($fallback_price, $product_id), + 'sale_price' => '', + 'has_sale' => false, + ]; + } + $products[] = [ 'ID' => $product_id, 'title' => $product->post_title, 'category' => implode(', ', $categories), 'type' => formipay_get_post_meta($product_id, 'product_type'), 'stock' => formipay_get_post_meta($product_id, 'stock') ?: '∞', - 'price' => [ - 'flag' => formipay_get_flag_by_currency($currency[0] ?? ''), - 'name' => formipay_price_format( - get_post_meta($product_id, 'price', true), - $product_id - ) - ], + 'prices' => $prices, 'status' => $product->post_status, ]; } @@ -710,7 +750,7 @@ class Product { public function formipay_create_product_post() { - check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' ); + check_ajax_referer( 'formipay-admin', '_wpnonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => 'Unauthorized' ] ); @@ -745,7 +785,7 @@ class Product { public function formipay_product_get_currencies() { - check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' ); + check_ajax_referer( 'formipay-admin', '_wpnonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => 'Unauthorized' ] ); @@ -773,7 +813,7 @@ class Product { public function formipay_delete_product() { - check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' ); + check_ajax_referer( 'formipay-admin', '_wpnonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => 'Unauthorized' ] ); @@ -801,7 +841,7 @@ class Product { public function formipay_bulk_delete_product() { - check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' ); + check_ajax_referer( 'formipay-admin', '_wpnonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => 'Unauthorized' ] ); @@ -847,7 +887,7 @@ class Product { public function formipay_duplicate_product() { - check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' ); + check_ajax_referer( 'formipay-admin', '_wpnonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => 'Unauthorized' ] ); diff --git a/src/admin/api/client.js b/src/admin/api/client.js index 82e8dba3e..edb36bd91 100644 --- a/src/admin/api/client.js +++ b/src/admin/api/client.js @@ -103,8 +103,8 @@ export const customersApi = { * Products API */ export const productsApi = { - list: (params = {}) => ajaxRequest('formipay_tabledata_products', params), - get: (productId) => ajaxRequest('formipay_get_product', { post_id: productId }), + list: (params = {}) => ajaxRequest('formipay-tabledata-products', params), + get: (productId) => ajaxRequest('formipay-get-product', { post_id: productId }), getVariables: (productId) => ajaxRequest('get_product_variables', { post_id: productId }), }; diff --git a/src/admin/components/orders/OrderList.js b/src/admin/components/orders/OrderList.js index c35eff601..0bf0bd7f7 100644 --- a/src/admin/components/orders/OrderList.js +++ b/src/admin/components/orders/OrderList.js @@ -6,7 +6,7 @@ import { __ } from '@wordpress/i18n'; import { useState, useCallback, useEffect } from '@wordpress/element'; import { SearchControl, SelectControl, Button } from '@wordpress/components'; import { Icon } from '@wordpress/icons'; -import list from '@wordpress/icons/build/list'; +import * as Icons from '@wordpress/icons'; import { ordersApi } from '../../api/client'; import OrderListItem from './OrderListItem'; import './OrderList.css'; @@ -37,9 +37,14 @@ export default function OrderList({ onSelectOrder }) { offset: pagination.offset, }) .then(result => { - if (result.data) { - setOrders(result.data.results || []); - setTotal(result.data.total || 0); + console.log('Orders API response:', result); + // Handle both response formats: with or without data wrapper + const data = result.data || result; + if (data) { + setOrders(data.results || []); + setTotal(data.total || 0); + } else { + console.error('Unexpected response structure:', result); } }) .catch(error => { @@ -86,7 +91,7 @@ export default function OrderList({ onSelectOrder }) {

- + { __('Orders', 'formipay') }

diff --git a/src/admin/components/orders/OrderListItem.js b/src/admin/components/orders/OrderListItem.js index 835c3c456..55d6eb2e5 100644 --- a/src/admin/components/orders/OrderListItem.js +++ b/src/admin/components/orders/OrderListItem.js @@ -4,7 +4,7 @@ import { __ } from '@wordpress/i18n'; import { Icon } from '@wordpress/icons'; -import seen from '@wordpress/icons/build/visible'; +import * as Icons from '@wordpress/icons'; import './OrderListItem.css'; const STATUS_COLORS = { @@ -79,7 +79,7 @@ export default function OrderListItem({ order, onSelect }) { className="button button-small" onClick={onSelect} > - + { __('View', 'formipay') }