Files
dmail-admin/src/pages/setting/personality/components/SocialRenderer.tsx
T
2025-08-04 12:18:23 +03:30

164 lines
5.9 KiB
TypeScript

import React, { FC } from 'react'
import { SocialType, SocialNetworkType, SocialIconSize, SocialIconStyle, ElementType, PersonalityDataType, HorizontalAlignment, VerticalAlignment } from '../types/Types'
import { usePersonalityStore } from '../store/Store'
import { getSocialIconPath, hasPngIcon, getSocialColor as getSocialColorFromUtils, getSocialSvgIcon } from '../utils/socialIcons'
interface SocialRendererProps {
socials: SocialType[]
itemId: string
sectionKey: keyof PersonalityDataType
}
const SocialRenderer: FC<SocialRendererProps> = ({ socials, itemId, sectionKey }) => {
const { selectedElement, setSelectedElement } = usePersonalityStore()
if (!socials || socials.length === 0) return null
const handleSocialClick = (e: React.MouseEvent, socialId: string) => {
// جلوگیری از propagation به parent handlers
e.stopPropagation()
e.preventDefault()
setSelectedElement({
type: ElementType.SOCIAL,
elementId: socialId,
itemId,
sectionKey,
})
}
const getSocialIcon = (networkType: SocialNetworkType) => {
// Check if PNG icon is available, if so use it
if (hasPngIcon(networkType)) {
const iconPath = getSocialIconPath(networkType)
return (
<img
src={iconPath}
alt={`${networkType} icon`}
style={{
width: '100%',
height: '100%',
objectFit: 'contain',
display: 'block'
}}
/>
)
}
// Use shared SVG function
return getSocialSvgIcon(networkType, true) as React.ReactElement
}
const getSocialColor = getSocialColorFromUtils
const getIconSize = (size: SocialIconSize) => {
switch (size) {
case SocialIconSize.SMALL:
return { width: '24px', height: '24px', fontSize: '16px' }
case SocialIconSize.MEDIUM:
return { width: '32px', height: '32px', fontSize: '20px' }
case SocialIconSize.LARGE:
return { width: '40px', height: '40px', fontSize: '24px' }
default:
return { width: '32px', height: '32px', fontSize: '20px' }
}
}
const getIconStyle = (social: SocialType) => {
const size = getIconSize(social.size)
const baseStyle = {
...size,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
textDecoration: 'none',
color: social.color || getSocialColor(social.networkType),
transition: 'all 0.2s ease',
margin: '2px',
cursor: 'pointer',
pointerEvents: 'none' as const,
}
switch (social.style) {
case SocialIconStyle.CIRCLE:
return {
...baseStyle,
borderRadius: '50%',
}
case SocialIconStyle.SQUARE:
return {
...baseStyle,
borderRadius: '0',
}
case SocialIconStyle.ROUNDED:
return {
...baseStyle,
borderRadius: '8px',
}
default:
return baseStyle
}
}
const getHorizontalAlign = (alignment?: HorizontalAlignment) => {
switch (alignment) {
case HorizontalAlignment.LEFT:
return 'left'
case HorizontalAlignment.RIGHT:
return 'right'
case HorizontalAlignment.CENTER:
default:
return 'center'
}
}
const getVerticalAlign = (verticalAlignment?: VerticalAlignment) => {
switch (verticalAlignment) {
case VerticalAlignment.TOP:
return 'top'
case VerticalAlignment.BOTTOM:
return 'bottom'
case VerticalAlignment.MIDDLE:
default:
return 'middle'
}
}
return (
<table width="100%" cellPadding="0" cellSpacing="0" border={0}>
<tbody>
<tr>
<td
align={getHorizontalAlign(socials[0]?.alignment)}
valign={getVerticalAlign(socials[0]?.verticalAlignment)}
style={{ padding: '4px 0' }}
>
<div style={{ textAlign: getHorizontalAlign(socials[0]?.alignment) }}>
{socials.map((social) => (
<div
key={social.id}
data-element-type="social"
onClick={(e) => handleSocialClick(e, social.id)}
style={{
cursor: 'pointer',
outline: selectedElement?.elementId === social.id ? '2px dashed #0038FF' : 'none',
outlineOffset: '2px',
borderRadius: '4px',
padding: '2px',
display: 'inline-block',
margin: '2px'
}}
>
<div style={getIconStyle(social)}>
{getSocialIcon(social.networkType)}
</div>
</div>
))}
</div>
</td>
</tr>
</tbody>
</table>
)
}
export default SocialRenderer