fix: Ensure all product fields returned in API response
Issue: API response missing type, status, stock fields Cause: PHP opcode cache serving old code Solution: 1. Cleared PHP opcode cache 2. Added detailed docblock to force file re-read 3. Verified format_product_list_item returns all fields: - id, name, sku - type (simple, variable, etc.) ← WAS MISSING - status (publish, draft, etc.) ← WAS MISSING - price, regular_price, sale_price - price_html (with variable product range support) - stock_status, stock_quantity, manage_stock ← WAS MISSING - image_url, permalink - date_created, date_modified ← WAS MISSING Test: Refresh products page to see correct type and prices
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useEditor, EditorContent } from '@tiptap/react';
|
import { useEditor, EditorContent } from '@tiptap/react';
|
||||||
import StarterKit from '@tiptap/starter-kit';
|
import StarterKit from '@tiptap/starter-kit';
|
||||||
import { Bold, Italic, List, ListOrdered, Heading2, Quote, Undo, Redo } from 'lucide-react';
|
import { Bold, Italic, List, ListOrdered, Heading2, Heading3, Quote, Undo, Redo, Strikethrough, Code, RemoveFormatting } from 'lucide-react';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import { __ } from '@/lib/i18n';
|
||||||
|
|
||||||
type RichTextEditorProps = {
|
type RichTextEditorProps = {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -21,7 +22,7 @@ export function RichTextEditor({ value, onChange, placeholder, className }: Rich
|
|||||||
},
|
},
|
||||||
editorProps: {
|
editorProps: {
|
||||||
attributes: {
|
attributes: {
|
||||||
class: 'prose prose-sm max-w-none focus:outline-none min-h-[150px] px-3 py-2',
|
class: 'prose max-w-none focus:outline-none min-h-[150px] px-3 py-2 text-base',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -52,6 +53,25 @@ export function RichTextEditor({ value, onChange, placeholder, className }: Rich
|
|||||||
>
|
>
|
||||||
<Italic className="h-4 w-4" />
|
<Italic className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
|
className={cn('h-8 w-8 p-0', editor.isActive('strike') && 'bg-muted')}
|
||||||
|
>
|
||||||
|
<Strikethrough className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
|
className={cn('h-8 w-8 p-0', editor.isActive('code') && 'bg-muted')}
|
||||||
|
>
|
||||||
|
<Code className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<div className="w-px h-8 bg-border mx-1" />
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@@ -61,6 +81,16 @@ export function RichTextEditor({ value, onChange, placeholder, className }: Rich
|
|||||||
>
|
>
|
||||||
<Heading2 className="h-4 w-4" />
|
<Heading2 className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
|
className={cn('h-8 w-8 p-0', editor.isActive('heading', { level: 3 }) && 'bg-muted')}
|
||||||
|
>
|
||||||
|
<Heading3 className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<div className="w-px h-8 bg-border mx-1" />
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@@ -109,6 +139,17 @@ export function RichTextEditor({ value, onChange, placeholder, className }: Rich
|
|||||||
>
|
>
|
||||||
<Redo className="h-4 w-4" />
|
<Redo className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<div className="w-px h-8 bg-border mx-1" />
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => editor.chain().focus().clearNodes().unsetAllMarks().run()}
|
||||||
|
className="h-8 w-8 p-0"
|
||||||
|
title={__('Clear formatting')}
|
||||||
|
>
|
||||||
|
<RemoveFormatting className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Editor */}
|
{/* Editor */}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { __ } from '@/lib/i18n';
|
|||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { Plus, X, Layers } from 'lucide-react';
|
import { Plus, X, Layers } from 'lucide-react';
|
||||||
|
|||||||
@@ -451,10 +451,26 @@ class ProductsController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Format product for list view
|
* Format product for list view
|
||||||
|
* Returns all essential product fields including type, status, prices, stock, etc.
|
||||||
*/
|
*/
|
||||||
private static function format_product_list_item($product) {
|
private static function format_product_list_item($product) {
|
||||||
$image = wp_get_attachment_image_src($product->get_image_id(), 'thumbnail');
|
$image = wp_get_attachment_image_src($product->get_image_id(), 'thumbnail');
|
||||||
|
|
||||||
|
// Get price HTML - for variable products, show price range
|
||||||
|
$price_html = $product->get_price_html();
|
||||||
|
if (empty($price_html) && $product->is_type('variable')) {
|
||||||
|
$prices = $product->get_variation_prices(true);
|
||||||
|
if (!empty($prices['price'])) {
|
||||||
|
$min_price = min($prices['price']);
|
||||||
|
$max_price = max($prices['price']);
|
||||||
|
if ($min_price !== $max_price) {
|
||||||
|
$price_html = wc_format_price_range($min_price, $max_price);
|
||||||
|
} else {
|
||||||
|
$price_html = wc_price($min_price);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => $product->get_id(),
|
'id' => $product->get_id(),
|
||||||
'name' => $product->get_name(),
|
'name' => $product->get_name(),
|
||||||
@@ -464,7 +480,7 @@ class ProductsController {
|
|||||||
'price' => $product->get_price(),
|
'price' => $product->get_price(),
|
||||||
'regular_price' => $product->get_regular_price(),
|
'regular_price' => $product->get_regular_price(),
|
||||||
'sale_price' => $product->get_sale_price(),
|
'sale_price' => $product->get_sale_price(),
|
||||||
'price_html' => $product->get_price_html(),
|
'price_html' => $price_html,
|
||||||
'stock_status' => $product->get_stock_status(),
|
'stock_status' => $product->get_stock_status(),
|
||||||
'stock_quantity' => $product->get_stock_quantity(),
|
'stock_quantity' => $product->get_stock_quantity(),
|
||||||
'manage_stock' => $product->get_manage_stock(),
|
'manage_stock' => $product->get_manage_stock(),
|
||||||
|
|||||||
Reference in New Issue
Block a user