border + height section
This commit is contained in:
@@ -11,7 +11,7 @@ import { toast } from '@/components/Toast'
|
|||||||
|
|
||||||
const Personality: FC = () => {
|
const Personality: FC = () => {
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
const { setData, data, addSection, getSortedSectionKeys } = usePersonalityStore()
|
const { setData, addSection, getSortedSectionKeys } = usePersonalityStore()
|
||||||
const { data: template } = useGetTemplate(id || '')
|
const { data: template } = useGetTemplate(id || '')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -63,8 +63,6 @@ const Personality: FC = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('data', data);
|
|
||||||
|
|
||||||
|
|
||||||
const sortedSectionKeys = getSortedSectionKeys();
|
const sortedSectionKeys = getSortedSectionKeys();
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,37 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
|
|
||||||
const { activeSection, activeItemIndex, data, setActiveSection, setActiveItemIndex } = usePersonalityStore()
|
const { activeSection, activeItemIndex, data, setActiveSection, setActiveItemIndex } = usePersonalityStore()
|
||||||
|
|
||||||
|
// Helper function to get numeric height
|
||||||
|
const getNumericHeight = (height?: string) => {
|
||||||
|
return parseInt(height?.replace(/px|em|rem|%/g, '') || "123")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to generate border style object based on selected sides
|
||||||
|
const generateBorderStyle = (border?: { width?: string; color?: string; style?: string; sides?: string[] }) => {
|
||||||
|
if (!border || border.style === 'none') {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { width = '0px', color = '#E5E7EB', style = 'solid', sides = [] } = border
|
||||||
|
|
||||||
|
// اگر width صفر باشد یا تعریف نشده باشد، border نمایش نده
|
||||||
|
if (!width || width === '0px') {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sides.length === 0 || sides.length === 4) {
|
||||||
|
return { border: `${width} ${style} ${color}` }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate individual border sides
|
||||||
|
const borderStyle: any = {}
|
||||||
|
sides.forEach(side => {
|
||||||
|
borderStyle[`border${side.charAt(0).toUpperCase() + side.slice(1)}`] = `${width} ${style} ${color}`
|
||||||
|
})
|
||||||
|
|
||||||
|
return borderStyle
|
||||||
|
}
|
||||||
|
|
||||||
// Early return if data is not available
|
// Early return if data is not available
|
||||||
if (!data || !data[sectionKey]) {
|
if (!data || !data[sectionKey]) {
|
||||||
return (
|
return (
|
||||||
@@ -95,9 +126,30 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
sectionData.columnsCount > 0 ?
|
sectionData.columnsCount > 0 ?
|
||||||
<td style={{
|
<td style={{
|
||||||
padding: '10px',
|
padding: '10px',
|
||||||
border: activeSection === sectionKey ? '1px dashed #0038FF' : '1px dashed #E5E7EB',
|
...(() => {
|
||||||
|
const borderStyle = generateBorderStyle(sectionData.border)
|
||||||
|
if (activeSection === sectionKey) {
|
||||||
|
// اگر سکشن انتخاب شده است، border آبی + border سکشن را نمایش بده
|
||||||
|
if (Object.keys(borderStyle).length === 0) {
|
||||||
|
return { border: '1px dashed #0038FF' }
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...borderStyle,
|
||||||
|
outline: '1px dashed #0038FF',
|
||||||
|
outlineOffset: '2px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// اگر سکشن انتخاب نشده، فقط border سکشن یا border پیشفرض
|
||||||
|
if (Object.keys(borderStyle).length === 0) {
|
||||||
|
return { border: '1px dashed #E5E7EB' }
|
||||||
|
}
|
||||||
|
return borderStyle
|
||||||
|
}
|
||||||
|
})(),
|
||||||
borderRadius: '24px',
|
borderRadius: '24px',
|
||||||
cursor: 'pointer'
|
cursor: 'pointer',
|
||||||
|
height: sectionData.height || '123px'
|
||||||
}}>
|
}}>
|
||||||
<table width="100%" cellPadding="0" cellSpacing="0" border={0} style={{ tableLayout: 'fixed' }}>
|
<table width="100%" cellPadding="0" cellSpacing="0" border={0} style={{ tableLayout: 'fixed' }}>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -114,7 +166,7 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
onClick={(e) => handleItemClick(index, e)}
|
onClick={(e) => handleItemClick(index, e)}
|
||||||
style={{
|
style={{
|
||||||
width: `${100 / sectionData.columnsCount}%`,
|
width: `${100 / sectionData.columnsCount}%`,
|
||||||
height: '123px',
|
height: sectionData.height || '123px',
|
||||||
border: isActive ? '1px dashed #0038FF' : '1px dashed #EAECF4',
|
border: isActive ? '1px dashed #0038FF' : '1px dashed #EAECF4',
|
||||||
backgroundColor: item?.backgroundColor || '#ffffff',
|
backgroundColor: item?.backgroundColor || '#ffffff',
|
||||||
backgroundImage: item?.backgroundImage ? `url(${item.backgroundImage})` : 'none',
|
backgroundImage: item?.backgroundImage ? `url(${item.backgroundImage})` : 'none',
|
||||||
@@ -130,7 +182,7 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
>
|
>
|
||||||
<table width="100%" cellPadding="0" cellSpacing="0" border={0} style={{
|
<table width="100%" cellPadding="0" cellSpacing="0" border={0} style={{
|
||||||
borderCollapse: 'collapse',
|
borderCollapse: 'collapse',
|
||||||
height: '123px'
|
height: sectionData.height || '123px'
|
||||||
}}>
|
}}>
|
||||||
<tbody>
|
<tbody>
|
||||||
{/* اگر column خالی است */}
|
{/* اگر column خالی است */}
|
||||||
@@ -141,7 +193,7 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
width="100%"
|
width="100%"
|
||||||
height="123"
|
height={getNumericHeight(sectionData.height).toString()}
|
||||||
style={{
|
style={{
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
cursor: 'pointer'
|
cursor: 'pointer'
|
||||||
@@ -158,7 +210,7 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
width="100%"
|
width="100%"
|
||||||
height="123"
|
height={getNumericHeight(sectionData.height).toString()}
|
||||||
align={getButtonHorizontalAlign(item.buttons[0])}
|
align={getButtonHorizontalAlign(item.buttons[0])}
|
||||||
valign={getButtonVerticalAlign(item.buttons[0])}
|
valign={getButtonVerticalAlign(item.buttons[0])}
|
||||||
style={{
|
style={{
|
||||||
@@ -178,7 +230,9 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
width="100%"
|
width="100%"
|
||||||
height={item?.buttons && item.buttons.length > 0 ? "60" : "87"}
|
height={item?.buttons && item.buttons.length > 0 ?
|
||||||
|
Math.floor(getNumericHeight(sectionData.height) * 0.6).toString() :
|
||||||
|
Math.floor(getNumericHeight(sectionData.height) * 0.8).toString()}
|
||||||
align={item?.texts?.[0]?.alignment || 'center'}
|
align={item?.texts?.[0]?.alignment || 'center'}
|
||||||
valign={item?.texts?.[0]?.verticalAlignment === VerticalAlignment.TOP ? 'top' :
|
valign={item?.texts?.[0]?.verticalAlignment === VerticalAlignment.TOP ? 'top' :
|
||||||
item?.texts?.[0]?.verticalAlignment === VerticalAlignment.BOTTOM ? 'bottom' : 'middle'}
|
item?.texts?.[0]?.verticalAlignment === VerticalAlignment.BOTTOM ? 'bottom' : 'middle'}
|
||||||
@@ -210,7 +264,7 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
width="100%"
|
width="100%"
|
||||||
height="27"
|
height={Math.floor(getNumericHeight(sectionData.height) * 0.2).toString()}
|
||||||
align={getButtonHorizontalAlign(item.buttons[0])}
|
align={getButtonHorizontalAlign(item.buttons[0])}
|
||||||
valign={getButtonVerticalAlign(item.buttons[0])}
|
valign={getButtonVerticalAlign(item.buttons[0])}
|
||||||
style={{
|
style={{
|
||||||
@@ -247,8 +301,28 @@ const GenericSection: FC<GenericSectionProps> = ({ sectionKey }) => {
|
|||||||
<td
|
<td
|
||||||
onClick={(e) => handleSectionClick(sectionKey, e)}
|
onClick={(e) => handleSectionClick(sectionKey, e)}
|
||||||
style={{
|
style={{
|
||||||
height: '123px',
|
height: sectionData.height || '123px',
|
||||||
border: activeSection === sectionKey ? '1px dashed #0038FF' : '1px dashed #E5E7EB',
|
...(() => {
|
||||||
|
const borderStyle = generateBorderStyle(sectionData.border)
|
||||||
|
if (activeSection === sectionKey) {
|
||||||
|
// اگر سکشن انتخاب شده است، border آبی + border سکشن را نمایش بده
|
||||||
|
if (Object.keys(borderStyle).length === 0) {
|
||||||
|
return { border: '1px dashed #0038FF' }
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...borderStyle,
|
||||||
|
outline: '1px dashed #0038FF',
|
||||||
|
outlineOffset: '2px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// اگر سکشن انتخاب نشده، فقط border سکشن یا border پیشفرض
|
||||||
|
if (Object.keys(borderStyle).length === 0) {
|
||||||
|
return { border: '1px dashed #E5E7EB' }
|
||||||
|
}
|
||||||
|
return borderStyle
|
||||||
|
}
|
||||||
|
})(),
|
||||||
borderRadius: '24px',
|
borderRadius: '24px',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
verticalAlign: 'middle',
|
verticalAlign: 'middle',
|
||||||
|
|||||||
@@ -82,13 +82,13 @@ const ImageSideBar: FC = () => {
|
|||||||
}, [selectedElement, isEditMode, data]);
|
}, [selectedElement, isEditMode, data]);
|
||||||
|
|
||||||
const sizeOptions = [
|
const sizeOptions = [
|
||||||
{ label: 'کاور - تمام فضا را پوشش دهد (Cover)', value: ImageSize.COVER },
|
{ label: 'کاور ', value: ImageSize.COVER },
|
||||||
{ label: 'در مقیاس - در فضا جا شود (Contain)', value: ImageSize.CONTAIN },
|
{ label: 'در مقیاس', value: ImageSize.CONTAIN },
|
||||||
{ label: 'تکرار - عکس تکرار شود (Repeat)', value: ImageSize.REPEAT },
|
{ label: 'تکرار', value: ImageSize.REPEAT },
|
||||||
{ label: 'تکرار افقی (Repeat-X)', value: ImageSize.REPEAT_X },
|
{ label: 'تکرار افقی', value: ImageSize.REPEAT_X },
|
||||||
{ label: 'تکرار عمودی (Repeat-Y)', value: ImageSize.REPEAT_Y },
|
{ label: 'تکرار عمودی', value: ImageSize.REPEAT_Y },
|
||||||
{ label: 'بدون تکرار (No-Repeat)', value: ImageSize.NO_REPEAT },
|
{ label: 'بدون تکرار', value: ImageSize.NO_REPEAT },
|
||||||
{ label: 'اندازه اصلی (Auto)', value: ImageSize.AUTO }
|
{ label: 'اندازه اصلی', value: ImageSize.AUTO }
|
||||||
]
|
]
|
||||||
|
|
||||||
const handleImageUpload = async (files: File[]) => {
|
const handleImageUpload = async (files: File[]) => {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import ColorPicker from '@/components/ColorPicker';
|
|||||||
import { usePersonalityStore } from '../store/Store';
|
import { usePersonalityStore } from '../store/Store';
|
||||||
import { SectionItemType, BackgroundSize, BackgroundPosition } from '../types/Types';
|
import { SectionItemType, BackgroundSize, BackgroundPosition } from '../types/Types';
|
||||||
import Select from '@/components/Select';
|
import Select from '@/components/Select';
|
||||||
|
import Input from '@/components/Input';
|
||||||
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import { useSingleUpload } from '../hooks/usePersonalityData';
|
import { useSingleUpload } from '../hooks/usePersonalityData';
|
||||||
import { toast } from '@/components/Toast';
|
import { toast } from '@/components/Toast';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
@@ -12,11 +14,16 @@ import { Trash } from 'iconsax-react';
|
|||||||
|
|
||||||
const SettingSideBar: FC = () => {
|
const SettingSideBar: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { activeSection, setColumnsCount, updateActiveItem, data, activeItemIndex, removeSection } = usePersonalityStore()
|
const { activeSection, setColumnsCount, updateActiveItem, data, activeItemIndex, removeSection, setSectionHeight, setSectionBorder } = usePersonalityStore()
|
||||||
const [color, setColor] = useState("#aabbcc");
|
const [color, setColor] = useState("#aabbcc");
|
||||||
const [backgroundSize, setBackgroundSize] = useState<BackgroundSize>(BackgroundSize.COVER)
|
const [backgroundSize, setBackgroundSize] = useState<BackgroundSize>(BackgroundSize.COVER)
|
||||||
const [backgroundPosition, setBackgroundPosition] = useState<BackgroundPosition>(BackgroundPosition.CENTER)
|
const [backgroundPosition, setBackgroundPosition] = useState<BackgroundPosition>(BackgroundPosition.CENTER)
|
||||||
const [isUploading, setIsUploading] = useState<boolean>(false)
|
const [isUploading, setIsUploading] = useState<boolean>(false)
|
||||||
|
const [sectionHeight, setSectionHeightState] = useState<string>('123px')
|
||||||
|
const [borderWidth, setBorderWidth] = useState<string>('0px')
|
||||||
|
const [borderColor, setBorderColor] = useState<string>('#E5E7EB')
|
||||||
|
const [borderStyle, setBorderStyle] = useState<'solid' | 'dashed' | 'dotted' | 'none'>('solid')
|
||||||
|
const [borderSides, setBorderSides] = useState<('top' | 'bottom' | 'left' | 'right')[]>(['top', 'bottom', 'left', 'right'])
|
||||||
|
|
||||||
const { mutateAsync: singleUpload } = useSingleUpload()
|
const { mutateAsync: singleUpload } = useSingleUpload()
|
||||||
|
|
||||||
@@ -44,13 +51,23 @@ const SettingSideBar: FC = () => {
|
|||||||
// بهروزرسانی state وقتی activeSection یا activeItem تغییر میکند
|
// بهروزرسانی state وقتی activeSection یا activeItem تغییر میکند
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeSection && data[activeSection as keyof typeof data]) {
|
if (activeSection && data[activeSection as keyof typeof data]) {
|
||||||
const currentItem = data[activeSection as keyof typeof data]?.items[activeItemIndex]
|
const currentSection = data[activeSection as keyof typeof data]
|
||||||
|
const currentItem = currentSection?.items[activeItemIndex]
|
||||||
|
|
||||||
|
// بروزرسانی background settings
|
||||||
if (currentItem?.style) {
|
if (currentItem?.style) {
|
||||||
const currentType = getCurrentBackgroundSizeType(currentItem.style)
|
const currentType = getCurrentBackgroundSizeType(currentItem.style)
|
||||||
const currentPosition = getCurrentBackgroundPosition(currentItem.style)
|
const currentPosition = getCurrentBackgroundPosition(currentItem.style)
|
||||||
setBackgroundSize(currentType)
|
setBackgroundSize(currentType)
|
||||||
setBackgroundPosition(currentPosition)
|
setBackgroundPosition(currentPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// بروزرسانی section height و border
|
||||||
|
setSectionHeightState(currentSection?.height || '123px')
|
||||||
|
setBorderWidth(currentSection?.border?.width || '0px')
|
||||||
|
setBorderColor(currentSection?.border?.color || '#E5E7EB')
|
||||||
|
setBorderStyle(currentSection?.border?.style || 'solid')
|
||||||
|
setBorderSides(currentSection?.border?.sides || ['top', 'bottom', 'left', 'right'])
|
||||||
}
|
}
|
||||||
}, [activeSection, activeItemIndex, data])
|
}, [activeSection, activeItemIndex, data])
|
||||||
|
|
||||||
@@ -80,6 +97,65 @@ const SettingSideBar: FC = () => {
|
|||||||
updateActiveItem({ backgroundColor: color })
|
updateActiveItem({ backgroundColor: color })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSectionHeightChange = (height: string) => {
|
||||||
|
if (activeSection) {
|
||||||
|
setSectionHeightState(height)
|
||||||
|
setSectionHeight(activeSection, height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleBorderWidthChange = (width: string) => {
|
||||||
|
if (activeSection) {
|
||||||
|
setBorderWidth(width)
|
||||||
|
setSectionBorder(activeSection, {
|
||||||
|
width,
|
||||||
|
color: borderColor,
|
||||||
|
style: borderStyle,
|
||||||
|
sides: borderSides
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleBorderColorChange = (color: string) => {
|
||||||
|
if (activeSection) {
|
||||||
|
setBorderColor(color)
|
||||||
|
setSectionBorder(activeSection, {
|
||||||
|
width: borderWidth,
|
||||||
|
color,
|
||||||
|
style: borderStyle,
|
||||||
|
sides: borderSides
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleBorderStyleChange = (style: 'solid' | 'dashed' | 'dotted' | 'none') => {
|
||||||
|
if (activeSection) {
|
||||||
|
setBorderStyle(style)
|
||||||
|
setSectionBorder(activeSection, {
|
||||||
|
width: borderWidth,
|
||||||
|
color: borderColor,
|
||||||
|
style,
|
||||||
|
sides: borderSides
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleBorderSidesChange = (side: 'top' | 'bottom' | 'left' | 'right') => {
|
||||||
|
if (activeSection) {
|
||||||
|
const newSides = borderSides.includes(side)
|
||||||
|
? borderSides.filter(s => s !== side)
|
||||||
|
: [...borderSides, side]
|
||||||
|
|
||||||
|
setBorderSides(newSides)
|
||||||
|
setSectionBorder(activeSection, {
|
||||||
|
width: borderWidth,
|
||||||
|
color: borderColor,
|
||||||
|
style: borderStyle,
|
||||||
|
sides: newSides
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleUploadBackground = async (file: File[]) => {
|
const handleUploadBackground = async (file: File[]) => {
|
||||||
if (activeSection && file.length > 0) {
|
if (activeSection && file.length > 0) {
|
||||||
setIsUploading(true)
|
setIsUploading(true)
|
||||||
@@ -166,6 +242,13 @@ const SettingSideBar: FC = () => {
|
|||||||
{ label: 'پایین راست', value: BackgroundPosition.BOTTOM_RIGHT }
|
{ label: 'پایین راست', value: BackgroundPosition.BOTTOM_RIGHT }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const borderStyleOptions = [
|
||||||
|
{ label: 'ساده', value: 'solid' },
|
||||||
|
{ label: 'خطچین', value: 'dashed' },
|
||||||
|
{ label: 'نقطهچین', value: 'dotted' },
|
||||||
|
{ label: 'بدون حاشیه', value: 'none' }
|
||||||
|
]
|
||||||
|
|
||||||
if (!activeSection) {
|
if (!activeSection) {
|
||||||
return (
|
return (
|
||||||
<div className='text-center text-gray-500 mt-8'>
|
<div className='text-center text-gray-500 mt-8'>
|
||||||
@@ -294,6 +377,73 @@ const SettingSideBar: FC = () => {
|
|||||||
disabled={isUploading}
|
disabled={isUploading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Section Height Control */}
|
||||||
|
<div className='mt-5'>
|
||||||
|
<Input
|
||||||
|
label="ارتفاع سکشن"
|
||||||
|
value={sectionHeight}
|
||||||
|
onChange={(e) => handleSectionHeightChange(e.target.value)}
|
||||||
|
placeholder="مثال: 123px"
|
||||||
|
disabled={isUploading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Border Controls */}
|
||||||
|
<div className='mt-5 border-t border-gray-200 pt-5'>
|
||||||
|
<div className='text-sm font-medium mb-3'>تنظیمات حاشیه</div>
|
||||||
|
|
||||||
|
<div className='mt-3'>
|
||||||
|
<Input
|
||||||
|
label="ضخامت حاشیه"
|
||||||
|
value={borderWidth}
|
||||||
|
onChange={(e) => handleBorderWidthChange(e.target.value)}
|
||||||
|
placeholder="مثال: 1px"
|
||||||
|
disabled={isUploading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-3'>
|
||||||
|
<ColorPicker
|
||||||
|
label="رنگ حاشیه"
|
||||||
|
defaultColor={borderColor}
|
||||||
|
changeColor={handleBorderColorChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-3'>
|
||||||
|
<Select
|
||||||
|
items={borderStyleOptions}
|
||||||
|
label="نوع حاشیه"
|
||||||
|
value={borderStyle}
|
||||||
|
onChange={(e) => handleBorderStyleChange(e.target.value as 'solid' | 'dashed' | 'dotted' | 'none')}
|
||||||
|
placeholder="انتخاب نوع حاشیه"
|
||||||
|
disabled={isUploading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-3'>
|
||||||
|
<div className='text-sm font-medium mb-2'>جهات حاشیه</div>
|
||||||
|
<div className='grid grid-cols-2 gap-2'>
|
||||||
|
{[
|
||||||
|
{ value: 'top', label: 'بالا' },
|
||||||
|
{ value: 'bottom', label: 'پایین' },
|
||||||
|
{ value: 'left', label: 'چپ' },
|
||||||
|
{ value: 'right', label: 'راست' }
|
||||||
|
].map(side => (
|
||||||
|
<div key={side.value} className='flex items-center space-x-2 rtl:space-x-reverse'>
|
||||||
|
<Checkbox
|
||||||
|
id={`border-${side.value}`}
|
||||||
|
checked={borderSides.includes(side.value as 'top' | 'bottom' | 'left' | 'right')}
|
||||||
|
onCheckedChange={() => handleBorderSidesChange(side.value as 'top' | 'bottom' | 'left' | 'right')}
|
||||||
|
disabled={isUploading}
|
||||||
|
/>
|
||||||
|
<label htmlFor={`border-${side.value}`} className='text-sm'>{side.label}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,6 +273,36 @@ export const usePersonalityStore = create<PersonalityStore>((set, get) => ({
|
|||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
setSectionHeight: (sectionKey: string, height: string) =>
|
||||||
|
set((state) => ({
|
||||||
|
data: {
|
||||||
|
...state.data,
|
||||||
|
[sectionKey]: {
|
||||||
|
...state.data[sectionKey],
|
||||||
|
height,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
|
||||||
|
setSectionBorder: (
|
||||||
|
sectionKey: string,
|
||||||
|
border: {
|
||||||
|
width?: string;
|
||||||
|
color?: string;
|
||||||
|
style?: "solid" | "dashed" | "dotted" | "none";
|
||||||
|
sides?: ("top" | "bottom" | "left" | "right")[];
|
||||||
|
}
|
||||||
|
) =>
|
||||||
|
set((state) => ({
|
||||||
|
data: {
|
||||||
|
...state.data,
|
||||||
|
[sectionKey]: {
|
||||||
|
...state.data[sectionKey],
|
||||||
|
border,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
|
||||||
setItems: (sectionKey: string, items: SectionItemType[]) =>
|
setItems: (sectionKey: string, items: SectionItemType[]) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -103,6 +103,13 @@ export type SectionType = {
|
|||||||
columnsCount: number;
|
columnsCount: number;
|
||||||
sortNumber: number;
|
sortNumber: number;
|
||||||
items: SectionItemType[];
|
items: SectionItemType[];
|
||||||
|
height?: string;
|
||||||
|
border?: {
|
||||||
|
width?: string;
|
||||||
|
color?: string;
|
||||||
|
style?: "solid" | "dashed" | "dotted" | "none";
|
||||||
|
sides?: ("top" | "bottom" | "left" | "right")[];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SectionItemType = {
|
export type SectionItemType = {
|
||||||
@@ -200,6 +207,16 @@ export type PersonalityStore = {
|
|||||||
updateActiveItem: (updates: Partial<SectionItemType>) => void;
|
updateActiveItem: (updates: Partial<SectionItemType>) => void;
|
||||||
removeItem: (sectionKey: string, id: string) => void;
|
removeItem: (sectionKey: string, id: string) => void;
|
||||||
setColumnsCount: (sectionKey: string, columnsCount: number) => void;
|
setColumnsCount: (sectionKey: string, columnsCount: number) => void;
|
||||||
|
setSectionHeight: (sectionKey: string, height: string) => void;
|
||||||
|
setSectionBorder: (
|
||||||
|
sectionKey: string,
|
||||||
|
border: {
|
||||||
|
width?: string;
|
||||||
|
color?: string;
|
||||||
|
style?: "solid" | "dashed" | "dotted" | "none";
|
||||||
|
sides?: ("top" | "bottom" | "left" | "right")[];
|
||||||
|
}
|
||||||
|
) => void;
|
||||||
addText: (
|
addText: (
|
||||||
sectionKey: string,
|
sectionKey: string,
|
||||||
itemId: string,
|
itemId: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user