Added functionality in Attribute step of product creation configuration
This commit is contained in:
@@ -32,6 +32,7 @@ interface DynamicAttributesSectionProps {
|
||||
errors?: Record<string, any>;
|
||||
touched?: Record<string, any>;
|
||||
onAttributeChange: (code: string, value: any) => void;
|
||||
onAddAttributeClick?: (group: any) => void;
|
||||
readOnly?: boolean;
|
||||
}
|
||||
|
||||
@@ -42,6 +43,7 @@ export const DynamicAttributesSection: React.FC<DynamicAttributesSectionProps> =
|
||||
errors = {},
|
||||
touched = {},
|
||||
onAttributeChange,
|
||||
onAddAttributeClick,
|
||||
readOnly,
|
||||
}) => {
|
||||
if (!hasAttributeSet) {
|
||||
@@ -89,6 +91,7 @@ export const DynamicAttributesSection: React.FC<DynamicAttributesSectionProps> =
|
||||
errors={errors}
|
||||
touched={touched}
|
||||
onAttributeChange={onAttributeChange}
|
||||
onAddAttributeClick={onAddAttributeClick}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { assetsService, type AssetMapping } from '../../assets/services/assets.s
|
||||
import type { Asset } from '../../assets/types/assets.types';
|
||||
import {
|
||||
Upload, Image as ImageIcon, Video, FileText, Trash2,
|
||||
Check, Loader2, Search, Info, Shield, ArrowUp, ArrowDown
|
||||
Check, Loader2, Search, Info, Shield, ArrowUp, ArrowDown, Plus
|
||||
} from 'lucide-react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Loader } from '../../../components/customs/Loader';
|
||||
@@ -87,6 +87,36 @@ export const ProductAssetsTab: React.FC<ProductAssetsTabProps> = ({
|
||||
|
||||
// Handle new file upload
|
||||
const handleFileUpload = async (file: File) => {
|
||||
// 1. Validate size (Max 10MB)
|
||||
const MAX_SIZE = 10 * 1024 * 1024;
|
||||
if (file.size > MAX_SIZE) {
|
||||
toast.error('File size exceeds the 10MB limit.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Validate type
|
||||
const allowedExtensions = [
|
||||
'jpg', 'jpeg', 'png', 'webp', 'gif', 'svg', 'avif', 'bmp',
|
||||
'mp4', 'webm', 'mov', 'pdf', 'csv', 'xlsx', 'xls', 'doc', 'docx'
|
||||
];
|
||||
const fileExtension = file.name.split('.').pop()?.toLowerCase();
|
||||
|
||||
const isAllowedType =
|
||||
file.type.startsWith('image/') ||
|
||||
file.type.startsWith('video/') ||
|
||||
[
|
||||
'application/pdf', 'text/csv',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/vnd.ms-excel', 'application/msword',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
||||
].includes(file.type) ||
|
||||
allowedExtensions.includes(fileExtension || '');
|
||||
|
||||
if (!isAllowedType) {
|
||||
toast.error('Unsupported file format. Please upload images, videos, PDFs, CSVs, or Word/Excel documents.');
|
||||
return;
|
||||
}
|
||||
|
||||
setUploading(true);
|
||||
try {
|
||||
// 1. Upload to PIM media server
|
||||
@@ -306,21 +336,31 @@ export const ProductAssetsTab: React.FC<ProductAssetsTabProps> = ({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="bg-surface border border-border rounded-xl p-6 flex flex-col justify-between">
|
||||
<div className="bg-surface border border-border rounded-xl p-6 flex flex-col justify-between gap-4">
|
||||
<div>
|
||||
<h4 className="font-semibold text-foreground text-xs">Asset Library</h4>
|
||||
<h4 className="font-semibold text-foreground text-xs">Asset Actions</h4>
|
||||
<p className="text-[11px] text-muted-foreground mt-1">
|
||||
Select existing images, catalogs or spec documents from the central Asset library.
|
||||
Upload new files directly or select existing files from the central Asset library.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPicker(true)}
|
||||
className="w-full inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-surface border border-border hover:bg-background text-foreground rounded-lg text-xs font-semibold shadow-2xs"
|
||||
>
|
||||
<Search className="w-3.5 h-3.5" />
|
||||
Browse Asset Library
|
||||
</button>
|
||||
<div className="space-y-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
className="w-full inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-primary hover:bg-primary-hover text-white rounded-lg text-xs font-semibold shadow-2xs cursor-pointer"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5" />
|
||||
+ Add Asset
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPicker(true)}
|
||||
className="w-full inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-surface border border-border hover:bg-background text-foreground rounded-lg text-xs font-semibold shadow-2xs cursor-pointer"
|
||||
>
|
||||
<Search className="w-3.5 h-3.5" />
|
||||
Browse Library
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { ChevronDown, ChevronUp } from 'lucide-react';
|
||||
import { ChevronDown, ChevronUp, Plus } from 'lucide-react';
|
||||
import { DynamicAttributeRenderer } from './DynamicAttributeRenderer';
|
||||
|
||||
interface AttributeOption {
|
||||
@@ -33,6 +33,7 @@ interface ProductAttributeGroupProps {
|
||||
errors?: Record<string, any>;
|
||||
touched?: Record<string, any>;
|
||||
onAttributeChange: (code: string, value: any) => void;
|
||||
onAddAttributeClick?: (group: AttributeGroup) => void;
|
||||
readOnly?: boolean;
|
||||
}
|
||||
|
||||
@@ -42,6 +43,7 @@ export const ProductAttributeGroup: React.FC<ProductAttributeGroupProps> = ({
|
||||
errors = {},
|
||||
touched = {},
|
||||
onAttributeChange,
|
||||
onAddAttributeClick,
|
||||
readOnly,
|
||||
}) => {
|
||||
const [isExpanded, setIsExpanded] = useState(true);
|
||||
@@ -50,7 +52,22 @@ export const ProductAttributeGroup: React.FC<ProductAttributeGroupProps> = ({
|
||||
if (attributes.length === 0) {
|
||||
return (
|
||||
<div className="bg-surface rounded-xl border border-border shadow-xs p-6">
|
||||
<h3 className="font-semibold text-foreground mb-4">{group.name}</h3>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="font-semibold text-foreground text-xs uppercase tracking-wider">{group.name}</h3>
|
||||
{!readOnly && onAddAttributeClick && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onAddAttributeClick(group);
|
||||
}}
|
||||
className="px-3 py-2 bg-primary hover:bg-primary-hover text-white rounded-lg text-sm font-semibold transition-colors flex items-center justify-center shrink-0 h-[42px] w-[42px]"
|
||||
title={`Add attribute to ${group.name}`}
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground italic">No Attributes available.</div>
|
||||
</div>
|
||||
);
|
||||
@@ -58,14 +75,28 @@ export const ProductAttributeGroup: React.FC<ProductAttributeGroupProps> = ({
|
||||
|
||||
return (
|
||||
<div className="bg-surface rounded-xl border border-border shadow-xs overflow-hidden">
|
||||
<button
|
||||
type="button"
|
||||
<div
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
className="w-full flex items-center justify-between px-6 py-4 bg-background/50 border-b border-border/65 hover:bg-background transition-colors"
|
||||
className="w-full flex items-center justify-between px-6 py-4 bg-background/50 border-b border-border/65 hover:bg-background transition-colors cursor-pointer"
|
||||
>
|
||||
<h3 className="font-semibold text-foreground text-xs uppercase tracking-wider">{group.name}</h3>
|
||||
{isExpanded ? <ChevronUp className="w-4 h-4 text-muted-foreground" /> : <ChevronDown className="w-4 h-4 text-muted-foreground" />}
|
||||
</button>
|
||||
<div className="flex items-center gap-3">
|
||||
{!readOnly && onAddAttributeClick && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onAddAttributeClick(group);
|
||||
}}
|
||||
className="px-3 py-2 bg-primary hover:bg-primary-hover text-white rounded-lg text-sm font-semibold transition-colors flex items-center justify-center shrink-0 h-[42px] w-[42px]"
|
||||
title={`Add attribute to ${group.name}`}
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
{isExpanded ? <ChevronUp className="w-4 h-4 text-muted-foreground" /> : <ChevronDown className="w-4 h-4 text-muted-foreground" />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isExpanded && (
|
||||
<div className="p-6 grid grid-cols-2 gap-6">
|
||||
|
||||
+1627
-1567
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user