feat: Implement variable product handling in OrderForm (Tokopedia pattern)
Following PROJECT_SOP.md section 5.7 - Variable Product Handling: **Backend (OrdersController.php):** - Updated /products/search endpoint to return: - Product type (simple/variable) - Variations array with attributes, prices, stock - Formatted attribute names (Color, Size, etc.) **Frontend (OrderForm.tsx):** - Updated ProductSearchItem type to include variations - Updated LineItem type to support variation_id and variation_name - Added variation selector drawer (mobile + desktop) - Each variation = separate cart item row - Display variation name below product name - Fixed remove button to work with variations (by index) **UX Pattern:** 1. Search product → If variable, show variation drawer 2. Select variation → Add as separate line item 3. Can add same product with different variations 4. Each variation shown clearly: 'Product Name' + 'Color: Red' **Result:** ✅ Tokopedia/Shopee pattern implemented ✅ No auto-selection of first variation ✅ Each variation is independent cart item ✅ Works on mobile and desktop **Next:** Fix PageHeader max-w-5xl to only apply on settings pages
This commit is contained in:
@@ -1138,9 +1138,10 @@ class OrdersController {
|
||||
|
||||
$prods = wc_get_products( $args );
|
||||
$rows = array_map( function( $p ) {
|
||||
return [
|
||||
$data = [
|
||||
'id' => $p->get_id(),
|
||||
'name' => $p->get_name(),
|
||||
'type' => $p->get_type(),
|
||||
'price' => (float) $p->get_price(),
|
||||
'regular_price' => (float) $p->get_regular_price(),
|
||||
'sale_price' => $p->get_sale_price() ? (float) $p->get_sale_price() : null,
|
||||
@@ -1148,7 +1149,41 @@ class OrdersController {
|
||||
'stock' => $p->get_stock_quantity(),
|
||||
'virtual' => $p->is_virtual(),
|
||||
'downloadable' => $p->is_downloadable(),
|
||||
'variations' => [],
|
||||
];
|
||||
|
||||
// If variable product, include variations
|
||||
if ( $p->get_type() === 'variable' ) {
|
||||
$variation_ids = $p->get_children();
|
||||
foreach ( $variation_ids as $variation_id ) {
|
||||
$variation = wc_get_product( $variation_id );
|
||||
if ( ! $variation ) continue;
|
||||
|
||||
// Get variation attributes
|
||||
$attributes = [];
|
||||
foreach ( $variation->get_variation_attributes() as $attr_name => $attr_value ) {
|
||||
// Remove 'attribute_' prefix and format name
|
||||
$clean_name = str_replace( 'attribute_', '', $attr_name );
|
||||
$clean_name = str_replace( 'pa_', '', $clean_name ); // Remove taxonomy prefix if present
|
||||
$clean_name = ucfirst( str_replace( [ '-', '_' ], ' ', $clean_name ) );
|
||||
|
||||
$attributes[ $clean_name ] = $attr_value;
|
||||
}
|
||||
|
||||
$data['variations'][] = [
|
||||
'id' => $variation->get_id(),
|
||||
'attributes' => $attributes,
|
||||
'price' => (float) $variation->get_price(),
|
||||
'regular_price' => (float) $variation->get_regular_price(),
|
||||
'sale_price' => $variation->get_sale_price() ? (float) $variation->get_sale_price() : null,
|
||||
'sku' => $variation->get_sku(),
|
||||
'stock' => $variation->get_stock_quantity(),
|
||||
'in_stock' => $variation->is_in_stock(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}, $prods );
|
||||
|
||||
return new WP_REST_Response( [ 'rows' => $rows ], 200 );
|
||||
|
||||
Reference in New Issue
Block a user