Files
WooNooW/admin-spa/src/routes/Products/Edit.tsx
Dwindi Ramadhana 82399d4ddf fix: WP-Admin CSS conflicts and add-to-cart redirect
- Fix CSS conflicts between WP-Admin and SPA (radio buttons, chart text)
- Add Tailwind important selector scoped to #woonoow-admin-app
- Remove overly aggressive inline SVG styles from Assets.php
- Add targeted WordPress admin CSS overrides in index.css
- Fix add-to-cart redirect to use woocommerce_add_to_cart_redirect filter
- Let WooCommerce handle cart operations natively for proper session management
- Remove duplicate tailwind.config.cjs
2025-12-31 14:06:04 +07:00

146 lines
4.4 KiB
TypeScript

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';
import { __ } from '@/lib/i18n';
import { toast } from 'sonner';
import { useFABConfig } from '@/hooks/useFABConfig';
import { usePageHeader } from '@/contexts/PageHeaderContext';
import { ProductFormTabbed as ProductForm, ProductFormData } from './partials/ProductFormTabbed';
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 }>();
const navigate = useNavigate();
const queryClient = useQueryClient();
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');
// Fetch product
const productQ = useQuery({
queryKey: ['products', id],
queryFn: () => api.get(`/products/${id}`),
enabled: !!id,
});
// Update mutation
const updateMutation = useMutation({
mutationFn: async (data: ProductFormData) => {
return api.put(`/products/${id}`, data);
},
onSuccess: (response: any) => {
toast.success(__('Product updated successfully'));
queryClient.invalidateQueries({ queryKey: ['products'] });
queryClient.invalidateQueries({ queryKey: ['products', id] });
// Navigate back to products list
navigate('/products');
},
onError: (error: any) => {
toast.error(error.message || __('Failed to update product'));
},
});
const handleSubmit = async (data: ProductFormData) => {
// Merge meta data with form data (Level 1 compatibility)
const payload = { ...data, meta: metaData };
await updateMutation.mutateAsync(payload);
};
// Sync meta data from product
useEffect(() => {
if (productQ.data?.meta) {
setMetaData(productQ.data.meta);
}
}, [productQ.data?.meta]);
// Smart back handler: go back in history if available, otherwise fallback to /products
const handleBack = () => {
if (window.history.state?.idx > 0) {
navigate(-1); // Go back in history
} else {
navigate('/products'); // Fallback to products index
}
};
// Set page header with back button and save button
useEffect(() => {
const actions = (
<div className="flex gap-2">
<Button size="sm" variant="ghost" onClick={handleBack}>
{__('Back')}
</Button>
<Button
size="sm"
onClick={() => formRef.current?.requestSubmit()}
disabled={updateMutation.isPending || productQ.isLoading}
>
{updateMutation.isPending ? __('Saving...') : __('Save')}
</Button>
</div>
);
setPageHeader(__('Edit Product'), actions);
return () => clearPageHeader();
}, [updateMutation.isPending, productQ.isLoading, setPageHeader, clearPageHeader, navigate]);
// Loading state
if (productQ.isLoading) {
return (
<div className="space-y-4">
<Skeleton className="h-12 w-full" />
<Skeleton className="h-64 w-full" />
<Skeleton className="h-32 w-full" />
</div>
);
}
// Error state
if (productQ.isError) {
return (
<ErrorCard
title={__('Failed to load product')}
message={getPageLoadErrorMessage(productQ.error)}
onRetry={() => productQ.refetch()}
/>
);
}
const product = productQ.data;
return (
<div className="space-y-4">
<ProductForm
mode="edit"
initial={product}
onSubmit={handleSubmit}
formRef={formRef}
hideSubmitButton={true}
productId={product.id}
/>
{/* 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>
);
}