From 2043daae397b38f263ffe2328e749a12446eee03 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Wed, 16 Jul 2025 13:03:30 +0330 Subject: [PATCH] set select fix + screen shot fix --- src/components/Radio.tsx | 2 +- src/pages/setting/personality/List.tsx | 21 ++++++++++++++++--- .../personality/components/Templete.tsx | 16 ++++++++++++-- .../personality/hooks/usePersonalityData.ts | 5 +++++ src/pages/setting/personality/types/Types.ts | 1 + .../personality/utils/screenshotHelper.ts | 1 - 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/components/Radio.tsx b/src/components/Radio.tsx index 4f7dcdc..8b62541 100644 --- a/src/components/Radio.tsx +++ b/src/components/Radio.tsx @@ -8,7 +8,7 @@ type Props = { const Radio: FC = (props: Props) => { return ( -
props.onChange(props.value)} className='size-4 cursor-pointer rounded-full bg-[#EAEDF5] flex justify-center items-center'> +
props.onChange(props.value)} className='size-4 min-w-4 cursor-pointer rounded-full bg-[#EAEDF5] flex justify-center items-center'> { props.isActive &&
diff --git a/src/pages/setting/personality/List.tsx b/src/pages/setting/personality/List.tsx index a7ddd62..a2cf118 100644 --- a/src/pages/setting/personality/List.tsx +++ b/src/pages/setting/personality/List.tsx @@ -1,6 +1,6 @@ import Button from '@/components/Button' import { AddCircle } from 'iconsax-react' -import { FC } from 'react' +import { FC, useState, useEffect } from 'react' import { useGetTemplates } from './hooks/usePersonalityData' import { Link } from 'react-router-dom' import { Paths } from '@/utils/Paths' @@ -9,12 +9,23 @@ import Templete from './components/Templete' const List: FC = () => { const { data } = useGetTemplates() + const [optimisticSelectedId, setOptimisticSelectedId] = useState(null) - // پیدا کردن template انتخاب شده - const selectedTemplateId = data?.data?.templates?.find( + // پیدا کردن template انتخاب شده از سرور + const serverSelectedTemplateId = data?.data?.templates?.find( (template: TemplateResponseType) => template.selected )?.id + // استفاده از optimistic state یا server state + const selectedTemplateId = optimisticSelectedId || serverSelectedTemplateId + + // وقتی داده‌های جدید از سرور می‌آید، optimistic state را پاک کن + useEffect(() => { + if (data?.data?.templates) { + setOptimisticSelectedId(null) + } + }, [data]) + return (
@@ -41,10 +52,14 @@ const List: FC = () => { key={item.id} item={item} selectedTemplateId={selectedTemplateId} + onOptimisticSelect={setOptimisticSelectedId} /> ) }) } +
+
+
diff --git a/src/pages/setting/personality/components/Templete.tsx b/src/pages/setting/personality/components/Templete.tsx index 53aec19..dbf4c01 100644 --- a/src/pages/setting/personality/components/Templete.tsx +++ b/src/pages/setting/personality/components/Templete.tsx @@ -10,7 +10,8 @@ import ModalConfrim from '@/components/ModalConfrim' const Templete: FC<{ item: TemplateResponseType selectedTemplateId?: string -}> = ({ item, selectedTemplateId }) => { + onOptimisticSelect?: (id: string | null) => void +}> = ({ item, selectedTemplateId, onOptimisticSelect }) => { const [isActive, setIsActive] = useState(item.selected) const [isShowDeleteModal, setIsShowDeleteModal] = useState(false) @@ -19,7 +20,16 @@ const Templete: FC<{ const { mutate: deleteTemplate, isPending: isDeleting } = useDeleteTemplate() const handleChangeSelectedTemplate = (id: string) => { + // Optimistic update - بلافاصله UI را به‌روزرسانی کن + setIsActive(true) + onOptimisticSelect?.(id) + setSelectedTemplate(id, { + onError: () => { + // اگر خطا رخ داد، state را به حالت قبلی برگردان + setIsActive(item.selected) + onOptimisticSelect?.(null) + } }) } @@ -42,7 +52,9 @@ const Templete: FC<{ return ( <>
-
+
+ {item.name} +
diff --git a/src/pages/setting/personality/hooks/usePersonalityData.ts b/src/pages/setting/personality/hooks/usePersonalityData.ts index fd05bae..69da699 100644 --- a/src/pages/setting/personality/hooks/usePersonalityData.ts +++ b/src/pages/setting/personality/hooks/usePersonalityData.ts @@ -20,8 +20,13 @@ export const useGetTemplates = () => { }; export const useSetSelectedTemplate = () => { + const queryClient = useQueryClient(); + return useMutation({ mutationFn: (id: string) => api.setSelectedTemplate(id), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["templates"] }); + }, }); }; diff --git a/src/pages/setting/personality/types/Types.ts b/src/pages/setting/personality/types/Types.ts index dcdd4fa..5e13e06 100644 --- a/src/pages/setting/personality/types/Types.ts +++ b/src/pages/setting/personality/types/Types.ts @@ -316,6 +316,7 @@ export type TemplateResponseType = { currentVersion: string; selected: boolean; business: BusinessType; + thumbnailUrl: string; }; export type PagerType = { diff --git a/src/pages/setting/personality/utils/screenshotHelper.ts b/src/pages/setting/personality/utils/screenshotHelper.ts index 9052758..11a517a 100644 --- a/src/pages/setting/personality/utils/screenshotHelper.ts +++ b/src/pages/setting/personality/utils/screenshotHelper.ts @@ -38,7 +38,6 @@ export const captureScreenshotAsFile = async ( }; const dataUrl = await domtoimage.toPng(element, options); - // بازگردانی استایل‌های اصلی htmlElement.style.transform = originalTransform; htmlElement.style.position = originalPosition;