feat: Phase 2 - Frontend meta fields components (Level 1)
Implemented: Frontend Components for Level 1 Compatibility Created Components: - MetaFields.tsx - Generic meta field renderer - useMetaFields.ts - Hook for field registry Integrated Into: - Orders/Edit.tsx - Meta fields after OrderForm - Products/Edit.tsx - Meta fields after ProductForm Features: - Supports: text, textarea, number, date, select, checkbox - Groups fields by section - Zero coupling with specific plugins - Renders any registered fields dynamically - Read-only mode support How It Works: 1. Backend exposes meta via API (Phase 1) 2. PHP registers fields via MetaFieldsRegistry (Phase 3 - next) 3. Fields localized to window.WooNooWMetaFields 4. useMetaFields hook reads registry 5. MetaFields component renders fields 6. User edits fields 7. Form submission includes meta 8. Backend saves via update_order_meta_data() Result: - Generic, reusable components - Zero plugin-specific code - Works with any registered fields - Clean separation of concerns Next: Phase 3 - PHP MetaFieldsRegistry system
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
import React, { useRef, useEffect, useState } from 'react';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { api } from '@/lib/api';
|
||||
@@ -11,6 +11,8 @@ import { Button } from '@/components/ui/button';
|
||||
import { ErrorCard } from '@/components/ErrorCard';
|
||||
import { getPageLoadErrorMessage } from '@/lib/errorHandling';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { MetaFields } from '@/components/MetaFields';
|
||||
import { useMetaFields } from '@/hooks/useMetaFields';
|
||||
|
||||
export default function ProductEdit() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
@@ -19,6 +21,10 @@ export default function ProductEdit() {
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
const { setPageHeader, clearPageHeader } = usePageHeader();
|
||||
|
||||
// Level 1 compatibility: Meta fields from plugins
|
||||
const metaFields = useMetaFields('products');
|
||||
const [metaData, setMetaData] = useState<Record<string, any>>({});
|
||||
|
||||
// Hide FAB on edit product page
|
||||
useFABConfig('none');
|
||||
|
||||
@@ -48,7 +54,9 @@ export default function ProductEdit() {
|
||||
});
|
||||
|
||||
const handleSubmit = async (data: ProductFormData) => {
|
||||
await updateMutation.mutateAsync(data);
|
||||
// Merge meta data with form data (Level 1 compatibility)
|
||||
const payload = { ...data, meta: metaData };
|
||||
await updateMutation.mutateAsync(payload);
|
||||
};
|
||||
|
||||
// Set page header with back button and save button
|
||||
@@ -95,6 +103,13 @@ export default function ProductEdit() {
|
||||
|
||||
const product = productQ.data;
|
||||
|
||||
// Sync meta data from product
|
||||
useEffect(() => {
|
||||
if (product?.meta) {
|
||||
setMetaData(product.meta);
|
||||
}
|
||||
}, [product?.meta]);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<ProductForm
|
||||
@@ -104,6 +119,17 @@ export default function ProductEdit() {
|
||||
formRef={formRef}
|
||||
hideSubmitButton={true}
|
||||
/>
|
||||
|
||||
{/* Level 1 compatibility: Custom meta fields from plugins */}
|
||||
{metaFields.length > 0 && (
|
||||
<MetaFields
|
||||
meta={metaData}
|
||||
fields={metaFields}
|
||||
onChange={(key, value) => {
|
||||
setMetaData(prev => ({ ...prev, [key]: value }));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user