fix: رفع مشکلات نمایش جزئیات محصول
- اصلاح نمایش دستهبندیها با fallback به product_categories - رفع خطای React hooks order با جابجایی useState - حل مشکلات TypeScript و نمایش صحیح تمام اطلاعات محصول
This commit is contained in:
parent
25429f9745
commit
5bf157219e
|
|
@ -14,6 +14,9 @@ const ProductDetailPage = () => {
|
||||||
|
|
||||||
const { data: product, isLoading, error } = useProduct(id);
|
const { data: product, isLoading, error } = useProduct(id);
|
||||||
|
|
||||||
|
// State for image preview – must be defined before any early returns to keep hook order stable
|
||||||
|
const [previewImage, setPreviewImage] = useState<string | null>(null);
|
||||||
|
|
||||||
if (isLoading) return <LoadingSpinner />;
|
if (isLoading) return <LoadingSpinner />;
|
||||||
if (error) return <div className="text-red-600">خطا در بارگذاری اطلاعات محصول</div>;
|
if (error) return <div className="text-red-600">خطا در بارگذاری اطلاعات محصول</div>;
|
||||||
if (!product) return <div>محصول یافت نشد</div>;
|
if (!product) return <div>محصول یافت نشد</div>;
|
||||||
|
|
@ -22,8 +25,6 @@ const ProductDetailPage = () => {
|
||||||
return new Intl.NumberFormat('fa-IR').format(price) + ' تومان';
|
return new Intl.NumberFormat('fa-IR').format(price) + ' تومان';
|
||||||
};
|
};
|
||||||
|
|
||||||
const [previewImage, setPreviewImage] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const formatNumber = (num: number) => {
|
const formatNumber = (num: number) => {
|
||||||
return new Intl.NumberFormat('fa-IR').format(num);
|
return new Intl.NumberFormat('fa-IR').format(num);
|
||||||
};
|
};
|
||||||
|
|
@ -31,8 +32,12 @@ const ProductDetailPage = () => {
|
||||||
// تصاویر محصول (حاصل تجمیع دو فیلد مختلف از API)
|
// تصاویر محصول (حاصل تجمیع دو فیلد مختلف از API)
|
||||||
const images = (product.file_ids && product.file_ids.length > 0) ? product.file_ids : ((product as any).files || []);
|
const images = (product.file_ids && product.file_ids.length > 0) ? product.file_ids : ((product as any).files || []);
|
||||||
|
|
||||||
|
// نسخههای محصول
|
||||||
const variants = (product.variants && product.variants.length > 0) ? product.variants : ((product as any).product_variants || []);
|
const variants = (product.variants && product.variants.length > 0) ? product.variants : ((product as any).product_variants || []);
|
||||||
|
|
||||||
|
// دستهبندیهای محصول
|
||||||
|
const categoriesData = (product.categories && product.categories.length > 0) ? product.categories : ((product as any).product_categories || []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageContainer>
|
<PageContainer>
|
||||||
|
|
@ -225,7 +230,7 @@ const ProductDetailPage = () => {
|
||||||
نسخههای محصول
|
نسخههای محصول
|
||||||
</SectionTitle>
|
</SectionTitle>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{variants.map((variant, index) => (
|
{variants.map((variant: any, index: number) => (
|
||||||
<div key={variant.id || index} className="border border-gray-200 dark:border-gray-600 rounded-lg p-4">
|
<div key={variant.id || index} className="border border-gray-200 dark:border-gray-600 rounded-lg p-4">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<h4 className="font-medium text-gray-900 dark:text-gray-100">
|
<h4 className="font-medium text-gray-900 dark:text-gray-100">
|
||||||
|
|
@ -299,11 +304,11 @@ const ProductDetailPage = () => {
|
||||||
ویژگیهای نسخه
|
ویژگیهای نسخه
|
||||||
</h5>
|
</h5>
|
||||||
<div className="grid grid-cols-2 gap-2">
|
<div className="grid grid-cols-2 gap-2">
|
||||||
{Object.entries(variant.attributes).map(([key, value]) => (
|
{Object.entries(variant.attributes).map(([key, value]: [string, any]) => (
|
||||||
<div key={key} className="p-2 bg-blue-50 dark:bg-blue-900/20 rounded text-sm">
|
<div key={key} className="p-2 bg-blue-50 dark:bg-blue-900/20 rounded text-sm">
|
||||||
<span className="font-medium text-gray-700 dark:text-gray-300">{key}:</span>
|
<span className="font-medium text-gray-700 dark:text-gray-300">{key}:</span>
|
||||||
<span className="ml-1 text-gray-900 dark:text-gray-100">
|
<span className="ml-1 text-gray-900 dark:text-gray-100">
|
||||||
{typeof value === 'object' ? JSON.stringify(value) : value}
|
{typeof value === 'object' ? JSON.stringify(value) : String(value)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
@ -318,11 +323,11 @@ const ProductDetailPage = () => {
|
||||||
اطلاعات تکمیلی
|
اطلاعات تکمیلی
|
||||||
</h5>
|
</h5>
|
||||||
<div className="grid grid-cols-2 gap-2">
|
<div className="grid grid-cols-2 gap-2">
|
||||||
{Object.entries(variant.meta).map(([key, value]) => (
|
{Object.entries(variant.meta).map(([key, value]: [string, any]) => (
|
||||||
<div key={key} className="p-2 bg-gray-50 dark:bg-gray-700 rounded text-sm">
|
<div key={key} className="p-2 bg-gray-50 dark:bg-gray-700 rounded text-sm">
|
||||||
<span className="font-medium text-gray-700 dark:text-gray-300">{key}:</span>
|
<span className="font-medium text-gray-700 dark:text-gray-300">{key}:</span>
|
||||||
<span className="ml-1 text-gray-900 dark:text-gray-100">
|
<span className="ml-1 text-gray-900 dark:text-gray-100">
|
||||||
{typeof value === 'object' ? JSON.stringify(value) : value}
|
{typeof value === 'object' ? JSON.stringify(value) : String(value)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
@ -416,7 +421,7 @@ const ProductDetailPage = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{product.categories && product.categories.length > 0 && (
|
{categoriesData.length > 0 && (
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Tag className="h-4 w-4 text-orange-500" />
|
<Tag className="h-4 w-4 text-orange-500" />
|
||||||
|
|
@ -425,7 +430,7 @@ const ProductDetailPage = () => {
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="font-semibold text-gray-900 dark:text-gray-100">
|
<span className="font-semibold text-gray-900 dark:text-gray-100">
|
||||||
{formatNumber(product.categories.length)}
|
{formatNumber(categoriesData.length)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -433,14 +438,14 @@ const ProductDetailPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* دستهبندیها */}
|
{/* دستهبندیها */}
|
||||||
{product.categories && product.categories.length > 0 && (
|
{categoriesData.length > 0 && (
|
||||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
|
||||||
<SectionTitle className="flex items-center gap-2 mb-4">
|
<SectionTitle className="flex items-center gap-2 mb-4">
|
||||||
<Tag className="h-5 w-5" />
|
<Tag className="h-5 w-5" />
|
||||||
دستهبندیها
|
دستهبندیها
|
||||||
</SectionTitle>
|
</SectionTitle>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{product.categories.map((category) => (
|
{categoriesData.map((category: any) => (
|
||||||
<div
|
<div
|
||||||
key={category.id}
|
key={category.id}
|
||||||
className="flex items-center gap-2 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg"
|
className="flex items-center gap-2 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue