fix: Major UX improvements and API error handling
Fixed Issues: 1. ✅ API error handling - Added try-catch and validation 2. ✅ Pipe separator UX - Now accepts comma OR pipe naturally 3. ✅ Tab restructuring - Merged pricing into General tab Changes: 🔧 API (ProductsController.php): - Added try-catch error handling in create_product - Validate required fields (name) - Better empty field checks (use !empty instead of ??) - Support virtual, downloadable, featured flags - Array validation for categories/tags/variations - Return proper WP_Error on exceptions 🎨 UX Improvements: 1. Attribute Options Input (VariationsTab.tsx): ❌ Old: Pipe only, spaces rejected ✅ New: Comma OR pipe, spaces allowed - Split by /[,|]/ regex - Display as comma-separated (more natural) - Help text: "Type naturally: Red, Blue, Green" - No more cursor gymnastics! 2. Tab Restructuring (ProductFormTabbed.tsx): ❌ Old: 5 tabs (General, Pricing, Inventory, Variations, Organization) ✅ New: 3-4 tabs (General+Pricing, Inventory, Variations*, Organization) - Pricing merged into General tab - Variable products: 4 tabs (Variations shown) - Simple products: 3 tabs (Variations hidden) - Dynamic grid: grid-cols-3 or grid-cols-4 - Less tab switching! 3. GeneralTab.tsx Enhancement: - Added pricing fields section - SKU, Regular Price, Sale Price - Savings calculator ("Customers save X%") - Context-aware help text: * Simple: "Base price before discounts" * Variable: "Base price (can override per variation)" - All in one place! 📊 Result: - Simpler navigation (3-4 tabs vs 5) - Natural typing (comma works!) - Better context (pricing with product info) - Less cognitive load - Faster product creation
This commit is contained in:
@@ -183,70 +183,108 @@ class ProductsController {
|
||||
* Create new product
|
||||
*/
|
||||
public static function create_product(WP_REST_Request $request) {
|
||||
$data = $request->get_json_params();
|
||||
|
||||
// Determine product type
|
||||
$type = $data['type'] ?? 'simple';
|
||||
|
||||
if ($type === 'variable') {
|
||||
$product = new WC_Product_Variable();
|
||||
} else {
|
||||
$product = new WC_Product_Simple();
|
||||
}
|
||||
|
||||
// Set basic data
|
||||
$product->set_name($data['name'] ?? '');
|
||||
$product->set_slug($data['slug'] ?? '');
|
||||
$product->set_status($data['status'] ?? 'publish');
|
||||
$product->set_description($data['description'] ?? '');
|
||||
$product->set_short_description($data['short_description'] ?? '');
|
||||
$product->set_sku($data['sku'] ?? '');
|
||||
$product->set_regular_price($data['regular_price'] ?? '');
|
||||
$product->set_sale_price($data['sale_price'] ?? '');
|
||||
$product->set_manage_stock($data['manage_stock'] ?? false);
|
||||
|
||||
if ($data['manage_stock']) {
|
||||
$product->set_stock_quantity($data['stock_quantity'] ?? 0);
|
||||
$product->set_stock_status($data['stock_status'] ?? 'instock');
|
||||
} else {
|
||||
$product->set_stock_status($data['stock_status'] ?? 'instock');
|
||||
}
|
||||
|
||||
$product->set_weight($data['weight'] ?? '');
|
||||
$product->set_length($data['length'] ?? '');
|
||||
$product->set_width($data['width'] ?? '');
|
||||
$product->set_height($data['height'] ?? '');
|
||||
|
||||
// Categories
|
||||
if (!empty($data['categories'])) {
|
||||
$product->set_category_ids($data['categories']);
|
||||
}
|
||||
|
||||
// Tags
|
||||
if (!empty($data['tags'])) {
|
||||
$product->set_tag_ids($data['tags']);
|
||||
}
|
||||
|
||||
// Images
|
||||
if (!empty($data['image_id'])) {
|
||||
$product->set_image_id($data['image_id']);
|
||||
}
|
||||
if (!empty($data['gallery_image_ids'])) {
|
||||
$product->set_gallery_image_ids($data['gallery_image_ids']);
|
||||
}
|
||||
|
||||
$product->save();
|
||||
|
||||
// Handle variations for variable products
|
||||
if ($type === 'variable' && !empty($data['attributes'])) {
|
||||
self::save_product_attributes($product, $data['attributes']);
|
||||
try {
|
||||
$data = $request->get_json_params();
|
||||
|
||||
if (!empty($data['variations'])) {
|
||||
self::save_product_variations($product, $data['variations']);
|
||||
// Validate required fields
|
||||
if (empty($data['name'])) {
|
||||
return new WP_Error('missing_name', __('Product name is required', 'woonoow'), ['status' => 400]);
|
||||
}
|
||||
|
||||
// Determine product type
|
||||
$type = $data['type'] ?? 'simple';
|
||||
|
||||
if ($type === 'variable') {
|
||||
$product = new WC_Product_Variable();
|
||||
} else {
|
||||
$product = new WC_Product_Simple();
|
||||
}
|
||||
|
||||
// Set basic data
|
||||
$product->set_name($data['name']);
|
||||
if (!empty($data['slug'])) {
|
||||
$product->set_slug($data['slug']);
|
||||
}
|
||||
$product->set_status($data['status'] ?? 'publish');
|
||||
$product->set_description($data['description'] ?? '');
|
||||
$product->set_short_description($data['short_description'] ?? '');
|
||||
|
||||
if (!empty($data['sku'])) {
|
||||
$product->set_sku($data['sku']);
|
||||
}
|
||||
|
||||
if (!empty($data['regular_price'])) {
|
||||
$product->set_regular_price($data['regular_price']);
|
||||
}
|
||||
if (!empty($data['sale_price'])) {
|
||||
$product->set_sale_price($data['sale_price']);
|
||||
}
|
||||
|
||||
$product->set_manage_stock($data['manage_stock'] ?? false);
|
||||
|
||||
if (!empty($data['manage_stock'])) {
|
||||
$product->set_stock_quantity($data['stock_quantity'] ?? 0);
|
||||
}
|
||||
$product->set_stock_status($data['stock_status'] ?? 'instock');
|
||||
|
||||
// Optional fields
|
||||
if (!empty($data['weight'])) {
|
||||
$product->set_weight($data['weight']);
|
||||
}
|
||||
if (!empty($data['length'])) {
|
||||
$product->set_length($data['length']);
|
||||
}
|
||||
if (!empty($data['width'])) {
|
||||
$product->set_width($data['width']);
|
||||
}
|
||||
if (!empty($data['height'])) {
|
||||
$product->set_height($data['height']);
|
||||
}
|
||||
|
||||
// Virtual and downloadable
|
||||
if (!empty($data['virtual'])) {
|
||||
$product->set_virtual(true);
|
||||
}
|
||||
if (!empty($data['downloadable'])) {
|
||||
$product->set_downloadable(true);
|
||||
}
|
||||
if (!empty($data['featured'])) {
|
||||
$product->set_featured(true);
|
||||
}
|
||||
|
||||
// Categories
|
||||
if (!empty($data['categories']) && is_array($data['categories'])) {
|
||||
$product->set_category_ids($data['categories']);
|
||||
}
|
||||
|
||||
// Tags
|
||||
if (!empty($data['tags']) && is_array($data['tags'])) {
|
||||
$product->set_tag_ids($data['tags']);
|
||||
}
|
||||
|
||||
// Images
|
||||
if (!empty($data['image_id'])) {
|
||||
$product->set_image_id($data['image_id']);
|
||||
}
|
||||
if (!empty($data['gallery_image_ids']) && is_array($data['gallery_image_ids'])) {
|
||||
$product->set_gallery_image_ids($data['gallery_image_ids']);
|
||||
}
|
||||
|
||||
$product->save();
|
||||
|
||||
// Handle variations for variable products
|
||||
if ($type === 'variable' && !empty($data['attributes']) && is_array($data['attributes'])) {
|
||||
self::save_product_attributes($product, $data['attributes']);
|
||||
|
||||
if (!empty($data['variations']) && is_array($data['variations'])) {
|
||||
self::save_product_variations($product, $data['variations']);
|
||||
}
|
||||
}
|
||||
|
||||
return new WP_REST_Response(self::format_product_full($product), 201);
|
||||
} catch (Exception $e) {
|
||||
return new WP_Error('create_failed', $e->getMessage(), ['status' => 500]);
|
||||
}
|
||||
|
||||
return new WP_REST_Response(self::format_product_full($product), 201);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user