+ {/* Drag handle - hidden on mobile for better UX */}
+
-
@@ -102,22 +103,36 @@ export default function PaymentsPage() {
);
// Fetch all payment gateways
- const { data: gateways = [], isLoading, refetch } = useQuery({
+ const { data: gatewayData, isLoading, refetch } = useQuery({
queryKey: ['payment-gateways'],
queryFn: () => api.get('/payments/gateways'),
refetchOnWindowFocus: true,
staleTime: 5 * 60 * 1000, // 5 minutes
});
- // Initialize order from gateways
+ // Extract gateways and order from response
+ const gateways = gatewayData?.gateways || [];
+ const savedOrder = gatewayData?.order || { manual: [], online: [] };
+
+ // Initialize order from saved order or gateways
React.useEffect(() => {
if (gateways.length > 0 && manualOrder.length === 0 && onlineOrder.length === 0) {
- const manual = gateways.filter((g: PaymentGateway) => g.type === 'manual').map((g: PaymentGateway) => g.id);
- const online = gateways.filter((g: PaymentGateway) => g.type === 'provider' || g.type === 'other').map((g: PaymentGateway) => g.id);
- setManualOrder(manual);
- setOnlineOrder(online);
+ // Use saved order if available, otherwise use gateway order
+ if (savedOrder.manual.length > 0) {
+ setManualOrder(savedOrder.manual);
+ } else {
+ const manual = gateways.filter((g: PaymentGateway) => g.type === 'manual').map((g: PaymentGateway) => g.id);
+ setManualOrder(manual);
+ }
+
+ if (savedOrder.online.length > 0) {
+ setOnlineOrder(savedOrder.online);
+ } else {
+ const online = gateways.filter((g: PaymentGateway) => g.type === 'provider' || g.type === 'other').map((g: PaymentGateway) => g.id);
+ setOnlineOrder(online);
+ }
}
- }, [gateways, manualOrder.length, onlineOrder.length]);
+ }, [gateways, savedOrder, manualOrder.length, onlineOrder.length]);
// Toggle gateway mutation
const toggleMutation = useMutation({
@@ -162,7 +177,7 @@ export default function PaymentsPage() {
};
// Handle drag end for manual gateways
- const handleManualDragEnd = (event: DragEndEvent) => {
+ const handleManualDragEnd = async (event: DragEndEvent) => {
const { active, over } = event;
if (!over || active.id === over.id) return;
@@ -172,12 +187,23 @@ export default function PaymentsPage() {
const newOrder = arrayMove(manualOrder, oldIndex, newIndex);
setManualOrder(newOrder);
- // TODO: Save order to backend
- toast.success('Payment methods reordered');
+ // Save order to backend
+ try {
+ await api.post('/payments/gateways/order', {
+ category: 'manual',
+ order: newOrder,
+ });
+ toast.success('Payment methods reordered');
+ } catch (error) {
+ console.error('Failed to save order:', error);
+ toast.error('Failed to save order');
+ // Revert order on error
+ setManualOrder(manualOrder);
+ }
};
// Handle drag end for online gateways
- const handleOnlineDragEnd = (event: DragEndEvent) => {
+ const handleOnlineDragEnd = async (event: DragEndEvent) => {
const { active, over } = event;
if (!over || active.id === over.id) return;
@@ -187,8 +213,19 @@ export default function PaymentsPage() {
const newOrder = arrayMove(onlineOrder, oldIndex, newIndex);
setOnlineOrder(newOrder);
- // TODO: Save order to backend
- toast.success('Payment methods reordered');
+ // Save order to backend
+ try {
+ await api.post('/payments/gateways/order', {
+ category: 'online',
+ order: newOrder,
+ });
+ toast.success('Payment methods reordered');
+ } catch (error) {
+ console.error('Failed to save order:', error);
+ toast.error('Failed to save order');
+ // Revert order on error
+ setOnlineOrder(onlineOrder);
+ }
};
const handleSaveGateway = async (settings: Record
) => {
diff --git a/includes/Api/PaymentsController.php b/includes/Api/PaymentsController.php
index 823ea93..a4a507c 100644
--- a/includes/Api/PaymentsController.php
+++ b/includes/Api/PaymentsController.php
@@ -94,6 +94,31 @@ class PaymentsController extends WP_REST_Controller {
],
],
]);
+
+ // POST /woonoow/v1/payments/gateways/order
+ register_rest_route($this->namespace, '/' . $this->rest_base . '/gateways/order', [
+ [
+ 'methods' => WP_REST_Server::EDITABLE,
+ 'callback' => [$this, 'save_gateway_order'],
+ 'permission_callback' => [$this, 'check_permission'],
+ 'args' => [
+ 'category' => [
+ 'description' => 'Gateway category (manual or online)',
+ 'type' => 'string',
+ 'required' => true,
+ 'enum' => ['manual', 'online'],
+ ],
+ 'order' => [
+ 'description' => 'Array of gateway IDs in desired order',
+ 'type' => 'array',
+ 'required' => true,
+ 'items' => [
+ 'type' => 'string',
+ ],
+ ],
+ ],
+ ],
+ ]);
}
/**
@@ -106,7 +131,17 @@ class PaymentsController extends WP_REST_Controller {
try {
$gateways = PaymentGatewaysProvider::get_gateways();
- $response = rest_ensure_response($gateways);
+ // Get saved order
+ $manual_order = get_option('woonoow_payment_gateway_order_manual', []);
+ $online_order = get_option('woonoow_payment_gateway_order_online', []);
+
+ $response = rest_ensure_response([
+ 'gateways' => $gateways,
+ 'order' => [
+ 'manual' => $manual_order,
+ 'online' => $online_order,
+ ],
+ ]);
// Cache for 5 minutes
$response->header('Cache-Control', 'max-age=300');
@@ -265,6 +300,48 @@ class PaymentsController extends WP_REST_Controller {
}
}
+ /**
+ * Save gateway order
+ *
+ * @param WP_REST_Request $request Request object
+ * @return WP_REST_Response|WP_Error Response object or error
+ */
+ public function save_gateway_order(WP_REST_Request $request) {
+ $category = $request->get_param('category');
+ $order = $request->get_param('order');
+
+ // Validate category
+ if (!in_array($category, ['manual', 'online'], true)) {
+ return new WP_Error(
+ 'invalid_category',
+ 'Category must be either "manual" or "online"',
+ ['status' => 400]
+ );
+ }
+
+ // Validate order is array
+ if (!is_array($order)) {
+ return new WP_Error(
+ 'invalid_order',
+ 'Order must be an array of gateway IDs',
+ ['status' => 400]
+ );
+ }
+
+ // Save to WordPress options
+ $option_key = 'woonoow_payment_gateway_order_' . $category;
+ update_option($option_key, $order, false);
+
+ error_log(sprintf('[WooNooW] Saved %s gateway order: %s', $category, implode(', ', $order)));
+
+ return rest_ensure_response([
+ 'success' => true,
+ 'message' => 'Gateway order saved successfully',
+ 'category' => $category,
+ 'order' => $order,
+ ]);
+ }
+
/**
* Check permission
*