fix problem font in detail email + refetch inbox when open detail email + ...

This commit is contained in:
hamid zarghami
2025-07-17 12:46:16 +03:30
parent a8b203f324
commit 1139df424f
5 changed files with 102 additions and 9 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
VITE_TOKEN_NAME = 'dmail_token' VITE_TOKEN_NAME = 'dmail_token'
VITE_REFRESH_TOKEN_NAME = 'dmail_refresh_token' VITE_REFRESH_TOKEN_NAME = 'dmail_refresh_token'
VITE_DANAK_BASE_URL ='https://api.danakcorp.com' VITE_DANAK_BASE_URL ='https://api.danakcorp.com'
# VITE_BASE_URL = 'http://192.168.1.134:4000' # VITE_BASE_URL = 'http://192.168.1.113:4000'
VITE_BASE_URL = 'https://dmail-api.danakcorp.com' VITE_BASE_URL = 'https://dmail-api.danakcorp.com'
VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e' VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e'
+19 -3
View File
@@ -1,3 +1,19 @@
<svg width="85" height="72" viewBox="0 0 85 72" fill="none" xmlns="http://www.w3.org/2000/svg"> <?xml version="1.0" encoding="UTF-8"?>
<path d="M47.97 0C39.21 0 20.6 0.0500073 20.18 0.0700073C28.87 8.77001 45.47 25.11 55.3 34.9C54.27 35.93 53.22 36.98 52.11 38.09C49.1 41.1 47.07 41.82 44.03 38.78C31.57 26.32 5.38 0.07 5.28 0H0V71.79C0 71.79 11.97 71.77 12.57 71.77V24.82C12.63 24.6 16.87 28.77 22.08 33.96L21.63 71.81C22.28 71.81 39.72 71.83 47.28 71.8C49.16 71.8 51.06 71.69 52.93 71.49C69.23 69.67 82.67 55.87 84.14 39.48C86.07 17.95 69.62 0 47.98 0H47.97ZM46.3 11.58C55.58 10.72 63.99 15.5 67.84 22.39C66.04 24.19 64.36 25.86 62.72 27.49C57.77 22.69 49.24 14.43 46.3 11.58ZM48.3 60.07C45.38 60.12 42.46 60.12 39.54 60.11H31.86V43.77C33.94 45.85 35.86 47.78 37.43 49.33C43.64 55.49 53.12 52.88 59.33 46.75C63.62 42.51 71.94 34.1 72.57 33.51C73.5 47.57 62.46 59.84 48.29 60.09L48.3 60.07Z" fill="black"/> <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 55.27 39.19">
</svg> <!-- Generator: Adobe Illustrator 29.5.1, SVG Export Plug-In . SVG Version: 2.1.0 Build 141) -->
<defs>
<style>
.st0 {
fill: #231f20;
}
</style>
</defs>
<path class="st0" d="M22.83,18.01l.1,19.39c2.24,0,8.63.01,11.79-.01.94,0,1.87-.06,2.76-.16,7.85-.91,14.3-7.82,15-16.07.45-5.23-1.13-10.19-4.44-13.97s-7.92-5.86-12.96-5.86h0c-3.41,0-9.15.01-12.09.02,2.27,2.36,5.2,5.38,8.13,8.41,2.98,3.07,5.95,6.14,8.21,8.49l.56.58-2.16,2.25c-.81.85-1.71,1.63-2.8,1.63-.79,0-1.55-.4-2.37-1.26l-10.4-10.87C17.98,6.21,14.23,2.3,13.3,1.33h-1.55v36.05h4.75l.05-25.25,6.3,5.87h-.02ZM32.46,5.95l1.7-.17c4.75-.43,9.4,1.99,11.59,6.09l.29.54-3.55,3.68-10.04-10.15h0ZM26.18,21.52l4.14,4.32c2.81,2.91,7.12,1.52,9.91-1.36,1.26-1.3,3.22-3.35,4.69-4.89,1.05-1.1,1.85-1.94,1.99-2.07l1.21-1.2.11,1.74c.24,3.78-1.04,7.55-3.51,10.36-2.48,2.81-5.84,4.4-9.47,4.46-.98.02-1.97.02-2.95.02h-6.12v-11.38h0Z"/>
<path class="st0" d="M7.35,37.41H2.26v-1.67c0-.55.11-.97.34-1.25s.57-.42,1.01-.42c.24,0,.45.07.63.2.18.14.32.32.43.55.08-.28.22-.49.44-.65s.47-.24.77-.24c.46,0,.82.15,1.08.44s.39.72.39,1.26v1.77h0ZM4.43,36.74v-1.01c0-.29-.07-.53-.22-.7-.15-.18-.35-.26-.6-.26-.28,0-.48.08-.61.24-.13.16-.19.41-.19.75v.99h1.62ZM4.97,36.74h1.83v-1.11c0-.31-.08-.56-.24-.74s-.39-.27-.67-.27c-.61,0-.92.33-.92,1v1.12h0Z"/>
<path class="st0" d="M4.81,31.14l-2.56-1.33v-.76l3.19,1.76h1.9v.67h-1.9l-3.19,1.76v-.77l2.56-1.32h0Z"/>
<path class="st0" d="M7.23,25.95H2.12v-1.44c0-.44.1-.84.29-1.18.2-.34.48-.61.84-.79.36-.19.78-.28,1.25-.28h.33c.48,0,.9.09,1.27.28s.64.45.84.8c.19.34.29.75.3,1.2v1.41h0ZM2.67,25.27h4.01v-.71c0-.52-.16-.92-.48-1.21-.32-.29-.78-.43-1.38-.43h-.3c-.58,0-1.03.14-1.35.41s-.48.66-.49,1.16v.79h-.01Z"/>
<path class="st0" d="M7.23,11.86v.68l-3.94,2.57h3.94v.68H2.12v-.68l3.95-2.58h-3.95v-.67h5.11Z"/>
<path class="st0" d="M4.85,3.89l.65.62h1.73v.67H2.12v-.67h2.53l-2.53-2.27v-.81l2.26,2.01,2.85-2.17v.81l-2.37,1.81h-.01Z"/>
<polygon class="st0" points="2.95 19.13 7.23 17.57 7.23 16.89 2.12 18.84 2.12 19.43 7.23 21.38 7.23 20.68 2.95 19.13"/>
<polygon class="st0" points="2.95 8.57 7.23 7.01 7.23 6.32 2.12 8.27 2.12 8.86 7.23 10.81 7.23 10.12 2.95 8.57"/>
</svg>

Before

Width:  |  Height:  |  Size: 876 B

After

Width:  |  Height:  |  Size: 2.3 KiB

+31
View File
@@ -80,3 +80,34 @@ export const formatDate = (dateString: string) => {
minute: "2-digit", minute: "2-digit",
}).format(date); }).format(date);
}; };
export const sanitizeEmailHTML = (html: string): string => {
try {
// Remove style tags and their content
let sanitized = html.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "");
// Remove link tags (CSS files)
sanitized = sanitized.replace(/<link[^>]*>/gi, "");
// Remove all style attributes
sanitized = sanitized.replace(/\s*style\s*=\s*["'][^"']*["']/gi, "");
// Remove font-family and other font-related CSS properties
sanitized = sanitized
.replace(/font-family\s*:\s*[^;]*;?/gi, "")
.replace(/font-size\s*:\s*[^;]*;?/gi, "")
.replace(/font-weight\s*:\s*[^;]*;?/gi, "")
.replace(/color\s*:\s*[^;]*;?/gi, "");
// Remove script tags for security
sanitized = sanitized.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "");
// Remove potentially harmful attributes
sanitized = sanitized.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi, "");
return sanitized;
} catch (error) {
console.error("خطا در پاک‌سازی HTML:", error);
return "خطا در نمایش محتوای ایمیل";
}
};
+35
View File
@@ -261,3 +261,38 @@ textarea::placeholder {
.animate-spin-reverse { .animate-spin-reverse {
animation: spin-reverse 1s linear infinite; animation: spin-reverse 1s linear infinite;
} }
/* Email Content Isolation */
.email-content-container {
/* ایزوله کردن استایل‌های ایمیل از بقیه سایت */
isolation: isolate;
contain: layout style;
}
.email-content-container * {
/* اعمال فونت اصلی سایت به تمام عناصر داخل ایمیل */
font-family: irancell !important;
/* محدود کردن اندازه فونت */
font-size: inherit !important;
line-height: inherit !important;
/* جلوگیری از تغییر رنگ پس‌زمینه */
background-color: transparent !important;
}
.email-content-container p,
.email-content-container div,
.email-content-container span,
.email-content-container table,
.email-content-container td,
.email-content-container th {
/* حفظ فونت و اندازه اصلی */
font-family: irancell !important;
font-size: 13px !important;
line-height: 1.75 !important;
}
.email-content-container img {
/* محدود کردن اندازه تصاویر */
max-width: 100% !important;
height: auto !important;
}
+16 -5
View File
@@ -1,5 +1,5 @@
import Button from '@/components/Button' import Button from '@/components/Button'
import { FC, useState } from 'react' import { FC, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import AvatarImage from '@/assets/images/avatar.svg' import AvatarImage from '@/assets/images/avatar.svg'
@@ -9,16 +9,17 @@ import AnswerIcon from '@/assets/images/answer.svg'
import Header from './Components/Header' import Header from './Components/Header'
import ReactQuill from 'react-quill-new'; import ReactQuill from 'react-quill-new';
import Select from '@/components/Select' import Select from '@/components/Select'
import { useGetMessageDetail, useSendEmail } from './hooks/useEmailData' import { useGetInbox, useGetMessageDetail, useSendEmail } from './hooks/useEmailData'
import { useAuthStore } from '../auth/store/AuthStore' import { useAuthStore } from '../auth/store/AuthStore'
import { SendEmailDto } from './types/Types' import { SendEmailDto } from './types/Types'
import { toast } from '@/components/Toast' import { toast } from '@/components/Toast'
import { formatDate } from '@/config/func' import { formatDate, sanitizeEmailHTML } from '@/config/func'
import SkeletonDetail from './Components/SkeletonDetail' import SkeletonDetail from './Components/SkeletonDetail'
const DetailEmail: FC = () => { const DetailEmail: FC = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { refetch } = useGetInbox({ page: 1 })
const { id } = useParams<{ id: string }>() const { id } = useParams<{ id: string }>()
const { email: userEmail } = useAuthStore() const { email: userEmail } = useAuthStore()
const [showAnswer, setShowAnswer] = useState<boolean>(false) const [showAnswer, setShowAnswer] = useState<boolean>(false)
@@ -26,7 +27,7 @@ const DetailEmail: FC = () => {
const [priority, setPriority] = useState<string>('') const [priority, setPriority] = useState<string>('')
// API hooks // API hooks
const { data: messageDetail, isLoading, error } = useGetMessageDetail(id || '', !!id) const { data: messageDetail, isLoading, error, isSuccess } = useGetMessageDetail(id || '', !!id)
const sendEmailMutation = useSendEmail() const sendEmailMutation = useSendEmail()
// const saveDraftMutation = useSaveDraft() // const saveDraftMutation = useSaveDraft()
@@ -107,6 +108,12 @@ const DetailEmail: FC = () => {
toast('قابلیت ارسال به دیگران به زودی اضافه خواهد شد', 'info') toast('قابلیت ارسال به دیگران به زودی اضافه خواهد شد', 'info')
} }
useEffect(() => {
if (isSuccess) {
refetch()
}
}, [isSuccess])
if (isLoading) { if (isLoading) {
return ( return (
<SkeletonDetail /> <SkeletonDetail />
@@ -157,7 +164,11 @@ const DetailEmail: FC = () => {
<div className='xl:mt-8 mt-3 text-[13px] leading-7 font-light'> <div className='xl:mt-8 mt-3 text-[13px] leading-7 font-light'>
{messageDetail.html && messageDetail.html.length > 0 ? ( {messageDetail.html && messageDetail.html.length > 0 ? (
<div dangerouslySetInnerHTML={{ __html: messageDetail.html.join('') }} /> <div
className='email-content-container p-4 bg-gray-50 rounded-lg overflow-hidden'
dangerouslySetInnerHTML={{ __html: sanitizeEmailHTML(messageDetail.html.join('')) }}
/>
) : ( ) : (
<p>{messageDetail.text || 'محتوای پیام'}</p> <p>{messageDetail.text || 'محتوای پیام'}</p>
)} )}