187 lines
6.4 KiB
TypeScript
187 lines
6.4 KiB
TypeScript
import { FC, useState } from 'react'
|
|
import { ImageBlock as ImageBlockType } from '../../types/blocks'
|
|
import Input from '@/components/Input'
|
|
import UploadBoxDraggble from '@/components/UploadBoxDraggble'
|
|
|
|
interface ImageBlockProps {
|
|
block: ImageBlockType
|
|
isSelected?: boolean
|
|
onUpdate: (updates: Partial<ImageBlockType>) => void
|
|
onSelect: () => void
|
|
isEditing?: boolean
|
|
}
|
|
|
|
const ImageBlock: FC<ImageBlockProps> = ({
|
|
block,
|
|
isSelected,
|
|
onUpdate,
|
|
onSelect,
|
|
isEditing = false
|
|
}) => {
|
|
const [localSrc, setLocalSrc] = useState(block.data.src)
|
|
const [localAlt, setLocalAlt] = useState(block.data.alt)
|
|
const [localUrl, setLocalUrl] = useState(block.data.url || '')
|
|
|
|
const handleSrcChange = (src: string) => {
|
|
setLocalSrc(src)
|
|
onUpdate({
|
|
data: {
|
|
...block.data,
|
|
src
|
|
}
|
|
})
|
|
}
|
|
|
|
const handleAltChange = (alt: string) => {
|
|
setLocalAlt(alt)
|
|
onUpdate({
|
|
data: {
|
|
...block.data,
|
|
alt
|
|
}
|
|
})
|
|
}
|
|
|
|
const handleUrlChange = (url: string) => {
|
|
setLocalUrl(url)
|
|
onUpdate({
|
|
data: {
|
|
...block.data,
|
|
url
|
|
}
|
|
})
|
|
}
|
|
|
|
const handleImageUpload = (files: File[]) => {
|
|
if (files.length > 0) {
|
|
const file = files[0]
|
|
const imageUrl = URL.createObjectURL(file)
|
|
handleSrcChange(imageUrl)
|
|
}
|
|
}
|
|
|
|
const imageStyle = {
|
|
width: typeof block.style.width === 'number' ? `${block.style.width}px` : block.style.width,
|
|
height: typeof block.style.height === 'number' ? `${block.style.height}px` : block.style.height,
|
|
objectFit: block.style.objectFit as 'cover' | 'contain' | 'fill',
|
|
borderRadius: block.style.borderRadius ? `${block.style.borderRadius}px` : '0',
|
|
maxWidth: '100%',
|
|
display: 'block',
|
|
margin: block.style.margin ?
|
|
`${block.style.margin.top}px ${block.style.margin.right}px ${block.style.margin.bottom}px ${block.style.margin.left}px` :
|
|
'8px 0'
|
|
}
|
|
|
|
const containerStyle = {
|
|
border: isSelected ? '2px dashed #0038FF' : '2px dashed transparent',
|
|
borderRadius: '8px',
|
|
padding: '4px',
|
|
textAlign: block.style.textAlign as 'left' | 'center' | 'right',
|
|
position: 'relative' as const,
|
|
display: 'inline-block',
|
|
minHeight: '60px',
|
|
minWidth: '80px'
|
|
}
|
|
|
|
// Process variables in src for preview
|
|
const processVariables = (content: string) => {
|
|
return content.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
const sampleData: Record<string, string> = {
|
|
userImage: 'https://via.placeholder.com/150x150?text=تصویر+کاربر',
|
|
companyLogo: 'https://via.placeholder.com/200x80?text=لوگو+شرکت',
|
|
productImage: 'https://via.placeholder.com/300x200?text=تصویر+محصول'
|
|
}
|
|
return sampleData[key] || match
|
|
})
|
|
}
|
|
|
|
const processedSrc = processVariables(localSrc)
|
|
|
|
return (
|
|
<div
|
|
style={containerStyle}
|
|
onClick={onSelect}
|
|
className="image-block-wrapper"
|
|
>
|
|
{isEditing ? (
|
|
<div className="space-y-3 p-2 bg-gray-50 rounded">
|
|
<UploadBoxDraggble
|
|
label="آپلود تصویر"
|
|
onChange={handleImageUpload}
|
|
/>
|
|
<Input
|
|
label="آدرس تصویر"
|
|
value={localSrc}
|
|
onChange={(e) => handleSrcChange(e.target.value)}
|
|
placeholder="https://example.com/image.jpg"
|
|
/>
|
|
<Input
|
|
label="متن جایگزین (Alt Text)"
|
|
value={localAlt}
|
|
onChange={(e) => handleAltChange(e.target.value)}
|
|
placeholder="توضیح تصویر"
|
|
/>
|
|
<Input
|
|
label="لینک تصویر (اختیاری)"
|
|
value={localUrl}
|
|
onChange={(e) => handleUrlChange(e.target.value)}
|
|
placeholder="https://example.com"
|
|
/>
|
|
</div>
|
|
) : (
|
|
<div>
|
|
{localUrl ? (
|
|
<a
|
|
href={localUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<img
|
|
src={processedSrc}
|
|
alt={localAlt}
|
|
style={imageStyle}
|
|
onError={(e) => {
|
|
const target = e.target as HTMLImageElement
|
|
target.src = 'https://via.placeholder.com/400x200?text=تصویر+یافت+نشد'
|
|
}}
|
|
/>
|
|
</a>
|
|
) : (
|
|
<img
|
|
src={processedSrc}
|
|
alt={localAlt}
|
|
style={imageStyle}
|
|
onError={(e) => {
|
|
const target = e.target as HTMLImageElement
|
|
target.src = 'https://via.placeholder.com/400x200?text=تصویر+یافت+نشد'
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{/* Block type indicator */}
|
|
{isSelected && (
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
top: '-8px',
|
|
right: '8px',
|
|
backgroundColor: '#0038FF',
|
|
color: 'white',
|
|
padding: '2px 6px',
|
|
fontSize: '10px',
|
|
borderRadius: '4px',
|
|
fontWeight: 'bold',
|
|
zIndex: 10
|
|
}}
|
|
>
|
|
تصویر
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default ImageBlock
|