more button remove + remove all logs

This commit is contained in:
hamid zarghami
2025-07-30 09:47:21 +03:30
parent ef26c63e33
commit e35634a0c2
17 changed files with 71 additions and 51 deletions
+2 -4
View File
@@ -19,8 +19,8 @@ export const EmailNotifications: React.FC<EmailNotificationsProps> = ({
const { socket, isConnected } = useEmailWebSocket({ const { socket, isConnected } = useEmailWebSocket({
token: userToken, token: userToken,
onConnect: () => console.log('نوتیفیکیشن‌های ایمیل متصل شد'), onConnect: () => null,
onError: (error) => console.error('خطای WebSocket:', error), onError: () => null,
}); });
// Sound settings state // Sound settings state
@@ -47,7 +47,6 @@ export const EmailNotifications: React.FC<EmailNotificationsProps> = ({
}); });
const handleNewEmail = useCallback((email: EmailPayload) => { const handleNewEmail = useCallback((email: EmailPayload) => {
console.log('📧 ایمیل جدید دریافت شد:', email);
// Add to notifications list // Add to notifications list
setNotifications(prev => [email, ...prev.slice(0, 9)]); // Keep only 10 latest setNotifications(prev => [email, ...prev.slice(0, 9)]); // Keep only 10 latest
@@ -97,7 +96,6 @@ export const EmailNotifications: React.FC<EmailNotificationsProps> = ({
{/* Test Sound Button */} {/* Test Sound Button */}
<button <button
onClick={() => { onClick={() => {
console.log("کلیک روی دکمه تست صدا");
playSound(); playSound();
}} }}
className="p-2 rounded-full hover:bg-gray-100 transition-colors" className="p-2 rounded-full hover:bg-gray-100 transition-colors"
+49 -3
View File
@@ -1,4 +1,4 @@
import { FC, useEffect, useState, ChangeEvent } from 'react'; import { FC, useEffect, useState, ChangeEvent, useRef } from 'react';
import { Filter } from 'iconsax-react'; import { Filter } from 'iconsax-react';
import DatePicker from './DatePicker'; import DatePicker from './DatePicker';
import Input from './Input'; import Input from './Input';
@@ -54,27 +54,72 @@ const Filters: FC<FiltersProps> = ({
}) => { }) => {
const [filters, setFilters] = useState<FilterValues>({}); const [filters, setFilters] = useState<FilterValues>({});
const [isFiltersOpen, setIsFiltersOpen] = useState(false); const [isFiltersOpen, setIsFiltersOpen] = useState(false);
const [inputValues, setInputValues] = useState<Record<string, string>>({});
const onChangeRef = useRef(onChange);
// آپدیت کردن ref وقتی onChange تغییر می‌کند
useEffect(() => {
onChangeRef.current = onChange;
}, [onChange]);
// تنظیم مقادیر اولیه // تنظیم مقادیر اولیه
useEffect(() => { useEffect(() => {
if (Object.keys(initialValues).length > 0) { if (Object.keys(initialValues).length > 0) {
setFilters(initialValues); setFilters(initialValues);
// تنظیم مقادیر input برای فیلدهای نوع input
const inputFields: Record<string, string> = {};
fields.forEach(field => {
if (field.type === 'input' && initialValues[field.name]) {
inputFields[field.name] = initialValues[field.name] as string;
}
});
setInputValues(inputFields);
} else { } else {
// تنظیم مقادیر پیش‌فرض از فیلدها // تنظیم مقادیر پیش‌فرض از فیلدها
const defaultValues: FilterValues = {}; const defaultValues: FilterValues = {};
const defaultInputs: Record<string, string> = {};
fields.forEach(field => { fields.forEach(field => {
if ('defaultValue' in field && field.defaultValue !== undefined) { if ('defaultValue' in field && field.defaultValue !== undefined) {
defaultValues[field.name] = field.defaultValue; defaultValues[field.name] = field.defaultValue;
if (field.type === 'input') {
defaultInputs[field.name] = field.defaultValue;
}
} }
}); });
if (Object.keys(defaultValues).length > 0) { if (Object.keys(defaultValues).length > 0) {
setFilters(defaultValues); setFilters(defaultValues);
setInputValues(defaultInputs);
onChange(defaultValues); onChange(defaultValues);
} }
} }
}, [fields, initialValues, onChange]); }, [fields, initialValues, onChange]);
// Debounce برای فیلدهای input
useEffect(() => {
const timeouts: Record<string, number> = {};
Object.keys(inputValues).forEach(fieldName => {
timeouts[fieldName] = setTimeout(() => {
setFilters(currentFilters => {
const currentFilter = currentFilters[fieldName];
const newValue = inputValues[fieldName];
if (currentFilter !== newValue) {
const newFilters = { ...currentFilters, [fieldName]: newValue || null };
onChangeRef.current(newFilters);
return newFilters;
}
return currentFilters;
});
}, 1000);
});
return () => {
Object.values(timeouts).forEach(timeout => clearTimeout(timeout));
};
}, [inputValues]);
const handleChange = (name: string, value: string | null) => { const handleChange = (name: string, value: string | null) => {
const newFilters = { ...filters, [name]: value }; const newFilters = { ...filters, [name]: value };
setFilters(newFilters); setFilters(newFilters);
@@ -82,11 +127,12 @@ const Filters: FC<FiltersProps> = ({
}; };
const handleInputChange = (name: string, event: ChangeEvent<HTMLInputElement>) => { const handleInputChange = (name: string, event: ChangeEvent<HTMLInputElement>) => {
handleChange(name, event.target.value); const value = event.target.value;
setInputValues(prev => ({ ...prev, [name]: value }));
}; };
const renderField = (field: FieldType) => { const renderField = (field: FieldType) => {
const currentValue = filters[field.name]; const currentValue = field.type === 'input' ? inputValues[field.name] : filters[field.name];
switch (field.type) { switch (field.type) {
case 'date': case 'date':
+1 -2
View File
@@ -35,8 +35,7 @@ const NajvaToken: FC = () => {
} else { } else {
return false return false
} }
} catch (error) { } catch {
console.log(error);
return false return false
} }
} }
+1 -1
View File
@@ -104,7 +104,7 @@ const RowActionsDropdown: React.FC<RowActionsDropdownProps> = ({ actions, classN
<button <button
ref={buttonRef} ref={buttonRef}
onClick={handleToggle} onClick={handleToggle}
className="p-1 hover:bg-gray-100 rounded-full transition-colors" className="mt-2 hover:bg-gray-100 rounded-full transition-colors"
> >
<More size={14} color="black" className="rotate-90" /> <More size={14} color="black" className="rotate-90" />
</button> </button>
+1 -2
View File
@@ -370,7 +370,7 @@ const Table = <T extends RowDataType>({
return ( return (
<div className="h-[64px] rounded-t-2xl md:rounded-t-3xl md:h-[74px] bg-white flex items-center px-3 md:px-6"> <div className="h-[64px] rounded-t-2xl md:rounded-t-3xl md:h-[74px] bg-white flex items-center px-3 md:px-6">
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
{actions} {actions}
{selectable && selectedRows.length > 0 && selectedActions && selectedActions} {selectable && selectedRows.length > 0 && selectedActions && selectedActions}
</div> </div>
@@ -471,7 +471,6 @@ const Table = <T extends RowDataType>({
</div> </div>
{pagination && (() => { {pagination && (() => {
console.log('Table component rendering pagination:', pagination);
return ( return (
<Pagination <Pagination
hasNext={pagination.hasNext} hasNext={pagination.hasNext}
-1
View File
@@ -57,7 +57,6 @@ const UploadBoxDraggble: FC<Props> = (props: Props) => {
if (props.preview && props.preview.length > 0 && !isFill) { if (props.preview && props.preview.length > 0 && !isFill) {
setPerviews(props.preview) setPerviews(props.preview)
console.log('preview', props.preview);
setIsFill(true) setIsFill(true)
} }
+1 -6
View File
@@ -28,23 +28,18 @@ export const useEmailWebSocket = ({
// Connection events // Connection events
newSocket.on("connect", () => { newSocket.on("connect", () => {
console.log("✅ اتصال به WebSocket ایمیل برقرار شد");
setIsConnected(true); setIsConnected(true);
onConnect?.(); onConnect?.();
}); });
newSocket.on("disconnect", () => { newSocket.on("disconnect", () => {
console.log("❌ اتصال به WebSocket ایمیل قطع شد");
setIsConnected(false); setIsConnected(false);
onDisconnect?.(); onDisconnect?.();
}); });
newSocket.on("connection_established", (data) => { newSocket.on("connection_established", () => {});
console.log("🎉 اتصال We bSocket ایمیل تأیید شد:", data);
});
newSocket.on("connection_error", (error) => { newSocket.on("connection_error", (error) => {
console.error("💥 خطای اتصال WebSocket ایمیل:", error);
onError?.(error.error); onError?.(error.error);
}); });
+3 -11
View File
@@ -15,13 +15,11 @@ export const useNotificationSound = ({
const playSound = useCallback(async () => { const playSound = useCallback(async () => {
if (!enabled || isPlaying) { if (!enabled || isPlaying) {
console.log("صدا غیرفعال است یا در حال پخش");
return; return;
} }
try { try {
setIsPlaying(true); setIsPlaying(true);
console.log("شروع پخش صدا...", { soundUrl, volume, enabled });
const audio = new Audio(); const audio = new Audio();
audio.preload = "auto"; audio.preload = "auto";
@@ -30,32 +28,26 @@ export const useNotificationSound = ({
// Add event listeners // Add event listeners
audio.addEventListener("ended", () => { audio.addEventListener("ended", () => {
console.log("پخش صدا تمام شد");
setIsPlaying(false); setIsPlaying(false);
}); });
audio.addEventListener("error", (e) => { audio.addEventListener("error", () => {
console.error("خطا در پخش صدا:", e);
setIsPlaying(false); setIsPlaying(false);
}); });
// Wait for audio to be ready // Wait for audio to be ready
if (audio.readyState >= 2) { if (audio.readyState >= 2) {
await audio.play(); await audio.play();
console.log("🔊 صدای نوتیفیکیشن پخش شد");
} else { } else {
audio.addEventListener("canplay", async () => { audio.addEventListener("canplay", async () => {
try { try {
await audio.play(); await audio.play();
console.log("🔊 صدای نوتیفیکیشن پخش شد"); } catch {
} catch (playError) {
console.error("خطا در پخش بعد از آماده شدن:", playError);
setIsPlaying(false); setIsPlaying(false);
} }
}); });
} }
} catch (error) { } catch {
console.error("خطا در ایجاد audio element:", error);
setIsPlaying(false); setIsPlaying(false);
} }
}, [enabled, isPlaying, soundUrl, volume]); }, [enabled, isPlaying, soundUrl, volume]);
+1 -1
View File
@@ -131,7 +131,7 @@ const List: FC = () => {
}; };
const tableActions = ( const tableActions = (
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox <Checkbox
checked={selectAll} checked={selectAll}
+2 -3
View File
@@ -2,7 +2,7 @@ import Filters, { FilterValues } from '../../components/Filters';
import { FC, useState } from 'react' import { FC, useState } from 'react'
import Table from '../../components/Table'; import Table from '../../components/Table';
import { ColumnType } from '../../components/types/TableTypes'; import { ColumnType } from '../../components/types/TableTypes';
import { InfoCircle, More, Refresh2, Trash, ArchiveSlash } from 'iconsax-react'; import { InfoCircle, Refresh2, Trash, ArchiveSlash } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown'; import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useGetArchiveMessages } from './hooks/useArchiveData'; import { useGetArchiveMessages } from './hooks/useArchiveData';
@@ -127,7 +127,7 @@ const List: FC = () => {
}; };
const tableActions = ( const tableActions = (
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox <Checkbox
checked={selectAll} checked={selectAll}
@@ -141,7 +141,6 @@ const List: FC = () => {
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`} className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
onClick={() => refetch()} onClick={() => refetch()}
/> />
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div> </div>
); );
+2 -5
View File
@@ -3,7 +3,7 @@ import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Table from '../../components/Table'; import Table from '../../components/Table';
import { ColumnType } from '../../components/types/TableTypes'; import { ColumnType } from '../../components/types/TableTypes';
import { InfoCircle, More, Refresh2, Trash, Edit, Send } from 'iconsax-react'; import { InfoCircle, Refresh2, Trash, Edit, Send } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown'; import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useGetDrafts } from './hooks/useDraftData'; import { useGetDrafts } from './hooks/useDraftData';
@@ -145,7 +145,7 @@ const List: FC = () => {
}; };
const tableActions = ( const tableActions = (
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox <Checkbox
checked={selectAll} checked={selectAll}
@@ -159,7 +159,6 @@ const List: FC = () => {
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`} className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
onClick={() => refetch()} onClick={() => refetch()}
/> />
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div> </div>
); );
@@ -218,8 +217,6 @@ const List: FC = () => {
const handleEditSelected = () => { const handleEditSelected = () => {
if (selectedMessages.length === 1) { if (selectedMessages.length === 1) {
navigate(`/draft/edit/${selectedMessages[0].id}`); navigate(`/draft/edit/${selectedMessages[0].id}`);
} else {
console.log('ویرایش چندین پیش‌نویس انتخاب شده:', selectedMessages.map(m => m.id));
} }
setSelectedMessages([]); setSelectedMessages([]);
setSelectAll(false); setSelectAll(false);
+2 -3
View File
@@ -2,7 +2,7 @@ import Filters, { FilterValues } from '../../components/Filters';
import { FC, useState } from 'react' import { FC, useState } from 'react'
import Table from '../../components/Table'; import Table from '../../components/Table';
import { ColumnType } from '../../components/types/TableTypes'; import { ColumnType } from '../../components/types/TableTypes';
import { InfoCircle, More, Refresh2, Trash, Archive, Star1 } from 'iconsax-react'; import { InfoCircle, Refresh2, Trash, Archive, Star1 } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown'; import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useGetFavoriteMessages } from './hooks/useFavoriteData'; import { useGetFavoriteMessages } from './hooks/useFavoriteData';
@@ -128,7 +128,7 @@ const List: FC = () => {
}; };
const tableActions = ( const tableActions = (
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox <Checkbox
checked={selectAll} checked={selectAll}
@@ -142,7 +142,6 @@ const List: FC = () => {
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`} className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
onClick={() => refetch()} onClick={() => refetch()}
/> />
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div> </div>
); );
-1
View File
@@ -118,7 +118,6 @@ const DetailEmail: FC = () => {
// Mark message as seen when it's loaded and not already seen // Mark message as seen when it's loaded and not already seen
useEffect(() => { useEffect(() => {
if (messageDetail && !messageDetail.seen && id) { if (messageDetail && !messageDetail.seen && id) {
console.log('Marking message as seen:', id, 'Current seen status:', messageDetail.seen)
emailActions.markAsSeen({ messageId: Number(id), mailbox: mailbox || '' }) emailActions.markAsSeen({ messageId: Number(id), mailbox: mailbox || '' })
} }
}, [messageDetail, emailActions, id]) }, [messageDetail, emailActions, id])
+1 -1
View File
@@ -149,7 +149,7 @@ const List: FC = () => {
}; };
const tableActions = ( const tableActions = (
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox <Checkbox
checked={selectAll} checked={selectAll}
+1 -1
View File
@@ -137,7 +137,7 @@ const List: FC = () => {
}; };
const tableActions = ( const tableActions = (
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox <Checkbox
checked={selectAll} checked={selectAll}
+2 -3
View File
@@ -2,7 +2,7 @@ import Filters, { FilterValues } from '../../components/Filters';
import { FC, useState } from 'react' import { FC, useState } from 'react'
import Table from '../../components/Table'; import Table from '../../components/Table';
import { ColumnType } from '../../components/types/TableTypes'; import { ColumnType } from '../../components/types/TableTypes';
import { InfoCircle, More, Refresh2, AttachSquare, Trash, Archive, Star } from 'iconsax-react'; import { InfoCircle, Refresh2, AttachSquare, Trash, Archive, Star } from 'iconsax-react';
import { useGetSentMessages } from './hooks/useSentData'; import { useGetSentMessages } from './hooks/useSentData';
import { InboxMessage } from './types/SentTypes'; import { InboxMessage } from './types/SentTypes';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@@ -142,7 +142,7 @@ const List: FC = () => {
}; };
const tableActions = ( const tableActions = (
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox <Checkbox
checked={selectAll} checked={selectAll}
@@ -156,7 +156,6 @@ const List: FC = () => {
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`} className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
onClick={() => refetch()} onClick={() => refetch()}
/> />
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div> </div>
); );
+2 -3
View File
@@ -127,7 +127,7 @@ const List: FC = () => {
}; };
const tableActions = ( const tableActions = (
<div className='flex items-center gap-2 md:gap-4'> <div className='flex items-center gap-4 md:gap-4'>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox <Checkbox
checked={selectAll} checked={selectAll}
@@ -179,7 +179,6 @@ const List: FC = () => {
const handleNotSpamSelected = () => { const handleNotSpamSelected = () => {
// TODO: پیاده‌سازی علامت‌گذاری به عنوان غیر اسپم - نیاز به API endpoint جداگانه // TODO: پیاده‌سازی علامت‌گذاری به عنوان غیر اسپم - نیاز به API endpoint جداگانه
console.log('علامت‌گذاری به عنوان غیر اسپم:', selectedMessages.map(m => m.id));
setSelectedMessages([]); setSelectedMessages([]);
setSelectAll(false); setSelectAll(false);
}; };
@@ -200,7 +199,7 @@ const List: FC = () => {
{ {
label: 'غیر اسپم', label: 'غیر اسپم',
icon: <RecoveryConvert size={16} color="black" />, icon: <RecoveryConvert size={16} color="black" />,
onClick: () => console.log('علامت‌گذاری به عنوان غیر اسپم', message.id), onClick: () => null,
}, },
{ {
label: 'حذف', label: 'حذف',