feat: implement multiple saved addresses with modal selector in checkout
- Add AddressController with full CRUD API for saved addresses - Implement address management UI in My Account > Addresses - Add modal-based address selector in checkout (Tokopedia-style) - Hide checkout forms when saved address is selected - Add search functionality in address modal - Auto-select default addresses on page load - Fix variable products to show 'Select Options' instead of 'Add to Cart' - Add admin toggle for multiple addresses feature - Clean up debug logs and fix TypeScript errors
This commit is contained in:
@@ -158,6 +158,37 @@ class CheckoutController {
|
||||
return ['error' => $order->get_error_message()];
|
||||
}
|
||||
|
||||
// Set customer ID if user is logged in
|
||||
if (is_user_logged_in()) {
|
||||
$user_id = get_current_user_id();
|
||||
$order->set_customer_id($user_id);
|
||||
|
||||
// Update user's billing information from checkout data
|
||||
if (!empty($payload['billing'])) {
|
||||
$billing = $payload['billing'];
|
||||
|
||||
// Update first name and last name
|
||||
if (!empty($billing['first_name'])) {
|
||||
update_user_meta($user_id, 'first_name', sanitize_text_field($billing['first_name']));
|
||||
update_user_meta($user_id, 'billing_first_name', sanitize_text_field($billing['first_name']));
|
||||
}
|
||||
if (!empty($billing['last_name'])) {
|
||||
update_user_meta($user_id, 'last_name', sanitize_text_field($billing['last_name']));
|
||||
update_user_meta($user_id, 'billing_last_name', sanitize_text_field($billing['last_name']));
|
||||
}
|
||||
|
||||
// Update billing phone
|
||||
if (!empty($billing['phone'])) {
|
||||
update_user_meta($user_id, 'billing_phone', sanitize_text_field($billing['phone']));
|
||||
}
|
||||
|
||||
// Update billing email
|
||||
if (!empty($billing['email'])) {
|
||||
update_user_meta($user_id, 'billing_email', sanitize_email($billing['email']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add items
|
||||
foreach ($payload['items'] as $line) {
|
||||
$product = $this->load_product($line);
|
||||
@@ -352,7 +383,7 @@ class CheckoutController {
|
||||
if (!WC()->customer) { WC()->customer = new \WC_Customer(get_current_user_id(), true); }
|
||||
if (!WC()->cart) { WC()->cart = new \WC_Cart(); }
|
||||
|
||||
// Address context for taxes/shipping rules
|
||||
// Address context for taxes/shipping rules - set temporarily without saving to user profile
|
||||
$ship = !empty($payload['shipping']) ? $payload['shipping'] : $payload['billing'];
|
||||
if (!empty($payload['billing'])) {
|
||||
foreach (['country','state','postcode','city','address_1','address_2'] as $k) {
|
||||
@@ -370,7 +401,8 @@ class CheckoutController {
|
||||
}
|
||||
}
|
||||
}
|
||||
WC()->customer->save();
|
||||
// DO NOT save customer data - only use for quote calculation
|
||||
// WC()->customer->save(); // REMOVED - should not update user profile during checkout
|
||||
|
||||
WC()->cart->empty_cart(true);
|
||||
foreach ($payload['items'] as $line) {
|
||||
|
||||
@@ -24,6 +24,7 @@ use WooNooW\Api\NewsletterController;
|
||||
use WooNooW\Frontend\ShopController;
|
||||
use WooNooW\Frontend\CartController as FrontendCartController;
|
||||
use WooNooW\Frontend\AccountController;
|
||||
use WooNooW\Frontend\AddressController;
|
||||
use WooNooW\Frontend\HookBridge;
|
||||
use WooNooW\Api\Controllers\SettingsController;
|
||||
use WooNooW\Api\Controllers\CartController as ApiCartController;
|
||||
@@ -38,20 +39,7 @@ class Routes {
|
||||
// Initialize CartController auth bypass (must be before rest_api_init)
|
||||
FrontendCartController::init();
|
||||
|
||||
// Log ALL REST API requests to debug routing
|
||||
add_filter('rest_pre_dispatch', function($result, $server, $request) {
|
||||
$route = $request->get_route();
|
||||
$method = $request->get_method();
|
||||
$result_type = is_null($result) ? 'NULL (will call handler)' : 'NON-NULL (handler bypassed!)';
|
||||
error_log("WooNooW REST: {$method} {$route} - Result: {$result_type}");
|
||||
if (!is_null($result)) {
|
||||
error_log("WooNooW REST: BYPASSED! Result type: " . gettype($result));
|
||||
}
|
||||
return $result;
|
||||
}, 10, 3);
|
||||
|
||||
add_action('rest_api_init', function () {
|
||||
error_log('WooNooW Routes: rest_api_init hook fired');
|
||||
$namespace = 'woonoow/v1';
|
||||
|
||||
// Auth endpoints (public - no permission check)
|
||||
@@ -82,10 +70,6 @@ class Routes {
|
||||
$settings_controller = new SettingsController();
|
||||
$settings_controller->register_routes();
|
||||
|
||||
// Cart controller (API) - DISABLED: Using Frontend CartController instead to avoid route conflicts
|
||||
// $api_cart_controller = new ApiCartController();
|
||||
// $api_cart_controller->register_routes();
|
||||
|
||||
// Payments controller
|
||||
$payments_controller = new PaymentsController();
|
||||
$payments_controller->register_routes();
|
||||
@@ -127,9 +111,7 @@ class Routes {
|
||||
$activity_log_controller->register_routes();
|
||||
|
||||
// Products controller
|
||||
error_log('WooNooW Routes: Registering ProductsController routes');
|
||||
ProductsController::register_routes();
|
||||
error_log('WooNooW Routes: ProductsController routes registered');
|
||||
|
||||
// Coupons controller
|
||||
CouponsController::register_routes();
|
||||
@@ -141,12 +123,11 @@ class Routes {
|
||||
NewsletterController::register_routes();
|
||||
|
||||
// Frontend controllers (customer-facing)
|
||||
error_log('WooNooW Routes: Registering Frontend controllers');
|
||||
ShopController::register_routes();
|
||||
FrontendCartController::register_routes();
|
||||
AccountController::register_routes();
|
||||
AddressController::register_routes();
|
||||
HookBridge::register_routes();
|
||||
error_log('WooNooW Routes: Frontend controllers registered');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user