social networks

This commit is contained in:
hamid zarghami
2025-07-31 10:47:14 +03:30
parent f40a6ecee3
commit 0b79f870ee
6 changed files with 358 additions and 164 deletions
+128 -29
View File
@@ -8,7 +8,17 @@ import {
ButtonType,
ImageType,
SectionType,
SocialType,
SocialNetworkType,
SocialIconSize,
SocialIconStyle,
} from "../types/Types";
import {
getSocialIconPath,
hasPngIcon,
getSocialColor,
getSocialSvgIcon,
} from "./socialIcons";
export const exportPersonalityToHTML = async (
data: PersonalityDataType
@@ -233,6 +243,80 @@ export const exportPersonalityToHTML = async (
.join("");
};
// Render SocialRenderer equivalent
const renderSocials = (socials: SocialType[]) => {
if (!socials || socials.length === 0) return "";
const getIconSize = (size: SocialIconSize) => {
switch (size) {
case SocialIconSize.SMALL:
return "24px";
case SocialIconSize.MEDIUM:
return "32px";
case SocialIconSize.LARGE:
return "40px";
default:
return "32px";
}
};
const getIconStyle = (social: SocialType) => {
const size = getIconSize(social.size);
const baseStyle = `width: ${size}; height: ${size}; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; color: ${
social.color || getSocialColor(social.networkType)
}; margin: 2px;`;
switch (social.style) {
case SocialIconStyle.CIRCLE:
return `${baseStyle} border-radius: 50%;`;
case SocialIconStyle.SQUARE:
return `${baseStyle} border-radius: 0;`;
case SocialIconStyle.ROUNDED:
return `${baseStyle} border-radius: 8px;`;
default:
return baseStyle;
}
};
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%; object-fit: contain; display: block;" />`;
}
// Use shared SVG function
return getSocialSvgIcon(networkType, false) as string;
};
return `<table width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
<tbody>
<tr>
<td align="${getHorizontalAlign(
socials[0]?.alignment
)}" valign="${getVerticalAlign(
socials[0]?.verticalAlignment
)}" style="padding: 4px 0;">
<div style="display: flex; justify-content: ${getHorizontalAlign(
socials[0]?.alignment
)}; gap: 4px; flex-wrap: wrap;">
${socials
.map(
(social) =>
`<a href="${social.link || "#"}" style="${getIconStyle(
social
)} text-decoration: none;">
${getSocialIcon(social.networkType)}
</a>`
)
.join("")}
</div>
</td>
</tr>
</tbody>
</table>`;
};
// Helper functions for button alignment (same as in React components)
const getButtonHorizontalAlign = (button?: {
alignment?: HorizontalAlignment;
@@ -289,6 +373,10 @@ export const exportPersonalityToHTML = async (
item?.buttons && item.buttons.length > 0;
const hasTexts =
item?.texts && item.texts.length > 0;
const hasImages =
item?.images && item.images.length > 0;
const hasSocials =
item?.socials && item.socials.length > 0;
let result = `<td style="width: ${
100 / section.columnsCount
@@ -310,35 +398,45 @@ export const exportPersonalityToHTML = async (
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; height: ${sectionHeight};">
<tbody>`;
// اگر فقط دکمه داریم و متن نداریم
if (!hasTexts && hasButtons) {
result += `<tr>
<td width="100%" height="${sectionHeight}" align="${getButtonHorizontalAlign(
item.buttons[0]
)}" valign="${getButtonVerticalAlign(
item.buttons[0]
)}" style="padding: 8px;">
${renderButtons(item.buttons)}
</td>
</tr>`;
} else {
// ردیف اصلی برای متن و تصاویر
const mainHeight = hasButtons
? sectionHeight === "123px"
? "60"
// اگر محتوایی وجود دارد (متن، دکمه، تصویر، یا شبکه اجتماعی)
if (
hasTexts ||
hasButtons ||
hasImages ||
hasSocials
) {
// اگر فقط دکمه داریم و متن نداریم
if (!hasTexts && hasButtons) {
result += `<tr>
<td width="100%" height="${sectionHeight}" align="${getButtonHorizontalAlign(
item.buttons[0]
)}" valign="${getButtonVerticalAlign(
item.buttons[0]
)}" style="padding: 8px;">
${renderImages(item?.images || [])}
${renderSocials(item?.socials || [])}
${renderButtons(item.buttons)}
</td>
</tr>`;
} else {
// ردیف اصلی برای متن و تصاویر
const mainHeight = hasButtons
? sectionHeight === "123px"
? "60"
: sectionHeight === "246px"
? "203"
: "40"
: sectionHeight === "123px"
? "87"
: sectionHeight === "246px"
? "203"
: "40"
: sectionHeight === "123px"
? "87"
: sectionHeight === "246px"
? "230"
: "67";
? "230"
: "67";
result += `<tr>
result += `<tr>
<td width="100%" height="${mainHeight}" style="padding: 20px; vertical-align: top; font-size: 15px; line-height: 1.8;">
${renderTexts(item?.texts || [])}
${renderImages(item?.images || [])}
${renderSocials(item?.socials || [])}
${
isContentSection
? '<div style="margin: 0; text-align: right;">{{content}}</div>'
@@ -347,17 +445,18 @@ export const exportPersonalityToHTML = async (
</td>
</tr>`;
// ردیف دکمه‌ها
if (hasButtons) {
result += `<tr>
// ردیف دکمه‌ها
if (hasButtons) {
result += `<tr>
<td width="100%" height="27" align="${getButtonHorizontalAlign(
item.buttons[0]
)}" valign="${getButtonVerticalAlign(
item.buttons[0]
)}" style="padding: 0 8px 8px 8px;">
item.buttons[0]
)}" style="padding: 0 8px 8px 8px;">
${renderButtons(item.buttons)}
</td>
</tr>`;
}
}
}