diff --git a/src/pages/setting/Setting.tsx b/src/pages/setting/Setting.tsx index ac93edd..c1e9b42 100644 --- a/src/pages/setting/Setting.tsx +++ b/src/pages/setting/Setting.tsx @@ -1,6 +1,6 @@ import { FC, useState, useEffect } from 'react' import { useTranslation } from 'react-i18next' -import { useLocation } from 'react-router-dom' +import { useLocation, useParams } from 'react-router-dom' import { SettingTabEnum } from './enum/SettingEnum' import Personality from './personality/Personality' import Domain from './domain/Domain' @@ -14,17 +14,30 @@ import { TickCircle } from 'iconsax-react' import { usePersonalityStore } from './personality/store/Store' import { exportPersonalityToHTML } from './personality/utils/ExportHTML' import Input from '@/components/Input' -import { useSaveTemplate } from './personality/hooks/usePersonalityData' +import { useSaveTemplate, useUpdateTemplate, useGetTemplate } from './personality/hooks/usePersonalityData' import { toast } from '@/components/Toast' const Setting: FC = () => { const { t } = useTranslation() + const { id } = useParams() const { data } = usePersonalityStore() const location = useLocation() const [activeTab, setActiveTab] = useState(SettingTabEnum.SETTING_DOMAIN) const [templateName, setTemplateName] = useState('') - const { mutate: saveTemplate, isPending } = useSaveTemplate() + const { mutate: saveTemplate, isPending: isSaving } = useSaveTemplate() + const { mutate: updateTemplate, isPending: isUpdating } = useUpdateTemplate() + const { data: template } = useGetTemplate(id || '') + + const isEditMode = !!id + const isLoading = isSaving || isUpdating + + // پر کردن نام قالب در حالت edit + useEffect(() => { + if (isEditMode && template?.data?.template?.name) { + setTemplateName(template.data.template.name) + } + }, [isEditMode, template]) const getTabFromPath = (pathname: string): SettingTabEnum => { switch (pathname) { @@ -39,6 +52,10 @@ const Setting: FC = () => { case Paths.settingSignature: return SettingTabEnum.SETTING_SIGNATURE default: + // بررسی personality با id + if (pathname.startsWith(Paths.settingPersonality + '/')) { + return SettingTabEnum.SETTING_PERSONALITY + } return SettingTabEnum.SETTING_DOMAIN } } @@ -84,15 +101,39 @@ const Setting: FC = () => { } const html = await exportPersonalityToHTML(data) - saveTemplate({ - name: templateName, - rawHtml: html, - structure: data - }, { - onSuccess: (data) => { - toast(data?.data?.message, 'success') - } - }) + + if (isEditMode) { + // حالت edit - استفاده از updateTemplate + updateTemplate({ + id: id!, + params: { + name: templateName, + rawHtml: html, + structure: data + } + }, { + onSuccess: (data) => { + toast(data?.data?.message || 'قالب با موفقیت بروزرسانی شد', 'success') + }, + onError: () => { + toast('خطا در بروزرسانی قالب', 'error') + } + }) + } else { + // حالت جدید - استفاده از saveTemplate + saveTemplate({ + name: templateName, + rawHtml: html, + structure: data + }, { + onSuccess: (data) => { + toast(data?.data?.message || 'قالب با موفقیت ایجاد شد', 'success') + }, + onError: () => { + toast('خطا در ایجاد قالب', 'error') + } + }) + } } // const handleExportHTML = async () => { @@ -124,11 +165,11 @@ const Setting: FC = () => { variant='secondary' className='border border-black w-fit px-7' onClick={handleSave} - loading={isPending} + loading={isLoading} >
- {t('save')} + {isEditMode ? 'بروزرسانی' : t('save')}
diff --git a/src/pages/setting/personality/Personality.tsx b/src/pages/setting/personality/Personality.tsx index 5f81164..c559113 100644 --- a/src/pages/setting/personality/Personality.tsx +++ b/src/pages/setting/personality/Personality.tsx @@ -1,9 +1,22 @@ -import { FC } from 'react' +import { FC, useEffect } from 'react' import HeaderSection from './components/HeaderSection' import ContentSection from './components/ContentSection' import FooterSection from './components/FooterSection' +import { useParams } from 'react-router-dom' +import { usePersonalityStore } from './store/Store' +import { useGetTemplate } from './hooks/usePersonalityData' const Personality: FC = () => { + const { id } = useParams() + const { setData } = usePersonalityStore() + const { data: template } = useGetTemplate(id || '') + + useEffect(() => { + if (id && template?.data?.template?.structure) { + setData(template.data.template.structure) + } + }, [id, template, setData]) + return (
diff --git a/src/pages/setting/personality/SideBar.tsx b/src/pages/setting/personality/SideBar.tsx index 7c7713f..e6099ff 100644 --- a/src/pages/setting/personality/SideBar.tsx +++ b/src/pages/setting/personality/SideBar.tsx @@ -98,28 +98,28 @@ const PersonalitySidebar: FC = () => { /> setActive(SideBarTab.TEXT)} className='cursor-pointer' /> setActive(SideBarTab.BUTTON)} className='cursor-pointer' /> setActive(SideBarTab.IMAGE)} className='cursor-pointer' /> setActive(SideBarTab.SOCIAL)} className='cursor-pointer' diff --git a/src/pages/setting/personality/components/ContentSection.tsx b/src/pages/setting/personality/components/ContentSection.tsx index b411b66..47d0cd4 100644 --- a/src/pages/setting/personality/components/ContentSection.tsx +++ b/src/pages/setting/personality/components/ContentSection.tsx @@ -13,80 +13,47 @@ const ContentSection: FC = () => { const { t } = useTranslation() const { activeSection, activeItemIndex, data, setActiveSection, setActiveItemIndex } = usePersonalityStore() - console.log('🟢 ContentSection - Current state:', { - activeSection, - activeItemIndex, - contentColumnsCount: data.content.columnsCount, - contentItemsLength: data.content.items.length - }); + // Early return if data is not available + if (!data || !data.content) { + return ( + + + + ) + } const handleSectionClick = (section: SectionName, e: React.MouseEvent) => { - console.log('🟢 ContentSection - handleSectionClick called:', { - section, - event: e, - target: e.target, - currentTarget: e.currentTarget - }); // اگر کلیک روی فضای خالی باشد (نه روی content elements) const target = e.target as HTMLElement; const isClickOnContent = target.closest('[data-element-type]') !== null; - console.log('🟢 ContentSection - Section click analysis:', { - isClickOnContent, - targetTagName: target.tagName, - targetClasses: target.className - }); - if (!isClickOnContent) { - console.log('🟢 ContentSection - Setting active section:', section); setActiveSection(section) - } else { - console.log('🟢 ContentSection - Click on content element, not setting section'); } } const handleItemClick = (index: number, e: React.MouseEvent) => { - console.log('🟢 ContentSection - handleItemClick called:', { - index, - event: e, - target: e.target, - currentTarget: e.currentTarget - }); // Check if click is on a content element (text, button, image, social) const target = e.target as HTMLElement; const isClickOnContent = target.closest('[data-element-type]') !== null; - console.log('🟢 ContentSection - Click analysis:', { - isClickOnContent, - targetTagName: target.tagName, - targetClasses: target.className, - closestDataElement: target.closest('[data-element-type]') - }); - // Only select column if not clicking on content elements if (!isClickOnContent) { - console.log('🟢 ContentSection - Selecting column:', { - index, - section: SectionName.CONTENT, - currentActiveSection: activeSection, - currentActiveItemIndex: activeItemIndex - }); + e.stopPropagation() // Only set active section if we're not already in content section if (activeSection !== SectionName.CONTENT) { - console.log('🟢 ContentSection - Switching to content section'); setActiveSection(SectionName.CONTENT) } // Always set the active item index - console.log('🟢 ContentSection - Setting active item index to:', index); setActiveItemIndex(index) - } else { - console.log('🟢 ContentSection - Click on content element, not selecting column'); } } diff --git a/src/pages/setting/personality/components/FooterSection.tsx b/src/pages/setting/personality/components/FooterSection.tsx index 6377fa9..555fa5f 100644 --- a/src/pages/setting/personality/components/FooterSection.tsx +++ b/src/pages/setting/personality/components/FooterSection.tsx @@ -13,6 +13,17 @@ const FooterSection: FC = () => { const { t } = useTranslation() const { activeSection, activeItemIndex, data, setActiveSection, setActiveItemIndex } = usePersonalityStore() + // Early return if data is not available + if (!data || !data.footer) { + return ( + + + + ) + } + console.log('🔴 FooterSection - Current state:', { activeSection, activeItemIndex, diff --git a/src/pages/setting/personality/components/HeaderSection.tsx b/src/pages/setting/personality/components/HeaderSection.tsx index eddcc4b..e7a00db 100644 --- a/src/pages/setting/personality/components/HeaderSection.tsx +++ b/src/pages/setting/personality/components/HeaderSection.tsx @@ -13,80 +13,50 @@ const HeaderSection: FC = () => { const { t } = useTranslation() const { activeSection, activeItemIndex, data, setActiveSection, setActiveItemIndex } = usePersonalityStore() - console.log('🔵 HeaderSection - Current state:', { - activeSection, - activeItemIndex, - headerColumnsCount: data.header.columnsCount, - headerItemsLength: data.header.items.length - }); + // Early return if data is not available + if (!data || !data.header) { + return ( + + + + ) + } + + const handleSectionClick = (section: SectionName, e: React.MouseEvent) => { - console.log('🔵 HeaderSection - handleSectionClick called:', { - section, - event: e, - target: e.target, - currentTarget: e.currentTarget - }); // اگر کلیک روی فضای خالی باشد (نه روی content elements) const target = e.target as HTMLElement; const isClickOnContent = target.closest('[data-element-type]') !== null; - console.log('🔵 HeaderSection - Section click analysis:', { - isClickOnContent, - targetTagName: target.tagName, - targetClasses: target.className - }); - if (!isClickOnContent) { - console.log('🔵 HeaderSection - Setting active section:', section); setActiveSection(section) - } else { - console.log('🔵 HeaderSection - Click on content element, not setting section'); } } const handleItemClick = (index: number, e: React.MouseEvent) => { - console.log('🔵 HeaderSection - handleItemClick called:', { - index, - event: e, - target: e.target, - currentTarget: e.currentTarget - }); // Check if click is on a content element (text, button, image, social) const target = e.target as HTMLElement; const isClickOnContent = target.closest('[data-element-type]') !== null; - console.log('🔵 HeaderSection - Click analysis:', { - isClickOnContent, - targetTagName: target.tagName, - targetClasses: target.className, - closestDataElement: target.closest('[data-element-type]') - }); // Only select column if not clicking on content elements if (!isClickOnContent) { - console.log('🔵 HeaderSection - Selecting column:', { - index, - section: SectionName.HEADER, - currentActiveSection: activeSection, - currentActiveItemIndex: activeItemIndex - }); e.stopPropagation() // Only set active section if we're not already in header section if (activeSection !== SectionName.HEADER) { - console.log('🔵 HeaderSection - Switching to header section'); + setActiveSection(SectionName.HEADER) } // Always set the active item index - console.log('🔵 HeaderSection - Setting active item index to:', index); setActiveItemIndex(index) - } else { - console.log('🔵 HeaderSection - Click on content element, not selecting column'); } } diff --git a/src/pages/setting/personality/components/Templete.tsx b/src/pages/setting/personality/components/Templete.tsx index fdee955..53aec19 100644 --- a/src/pages/setting/personality/components/Templete.tsx +++ b/src/pages/setting/personality/components/Templete.tsx @@ -2,7 +2,10 @@ import { FC, useEffect, useState } from 'react' import { TemplateResponseType } from '../types/Types' import Radio from '@/components/Radio' import { Brush2, Trash } from 'iconsax-react' -import { useSetSelectedTemplate } from '../hooks/usePersonalityData' +import { useSetSelectedTemplate, useDeleteTemplate } from '../hooks/usePersonalityData' +import { Link } from 'react-router-dom' +import { Paths } from '@/utils/Paths' +import ModalConfrim from '@/components/ModalConfrim' const Templete: FC<{ item: TemplateResponseType @@ -10,14 +13,24 @@ const Templete: FC<{ }> = ({ item, selectedTemplateId }) => { const [isActive, setIsActive] = useState(item.selected) + const [isShowDeleteModal, setIsShowDeleteModal] = useState(false) const { mutate: setSelectedTemplate } = useSetSelectedTemplate() + const { mutate: deleteTemplate, isPending: isDeleting } = useDeleteTemplate() const handleChangeSelectedTemplate = (id: string) => { setSelectedTemplate(id, { }) } + const handleDeleteTemplate = () => { + deleteTemplate(item.id, { + onSuccess: () => { + setIsShowDeleteModal(false) + } + }) + } + useEffect(() => { if (selectedTemplateId) { setIsActive(selectedTemplateId === item.id) @@ -27,19 +40,34 @@ const Templete: FC<{ }, [item.selected, selectedTemplateId, item.id]) return ( -
-
-
-
- -
{item.name}
-
-
- - + <> +
+
+
+
+ +
{item.name}
+
+
+ + + + +
-
+ + setIsShowDeleteModal(false)} + onConfrim={handleDeleteTemplate} + isLoading={isDeleting} + title="حذف قالب" + label={`آیا از حذف قالب "${item.name}" اطمینان دارید؟`} + /> + ) } diff --git a/src/pages/setting/personality/components/TextSidebar.tsx b/src/pages/setting/personality/components/TextSidebar.tsx index 9eba9bb..ae1ab24 100644 --- a/src/pages/setting/personality/components/TextSidebar.tsx +++ b/src/pages/setting/personality/components/TextSidebar.tsx @@ -228,7 +228,6 @@ const TextSidebar: FC = () => {
+
در حال بارگذاری...
+
+
در حال بارگذاری...
+
+
در حال بارگذاری...
+