diff --git a/.env b/.env index 546c985..464ef2a 100644 --- a/.env +++ b/.env @@ -2,6 +2,7 @@ VITE_TOKEN_NAME = 'dmail_token' VITE_REFRESH_TOKEN_NAME = 'dmail_refresh_token' VITE_DANAK_BASE_URL ='https://api.danakcorp.com' +# VITE_DANAK_BASE_URL ='http://192.168.1.112:4001' VITE_SOCKET_URL = 'wss://dmail-api.danakcorp.com/email' # VITE_SOCKET_URL = 'ws://192.168.1.106:4000/email' @@ -9,6 +10,8 @@ VITE_SOCKET_URL = 'wss://dmail-api.danakcorp.com/email' VITE_BASE_URL = 'https://dmail-api.danakcorp.com' # VITE_BASE_URL = 'http://192.168.1.117:4000' +VITE_HELP_URL = 'https://help.danakcorp.com' + VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e' diff --git a/src/App.tsx b/src/App.tsx index e4aebcd..571e69f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,6 +20,7 @@ import { EmailWebSocketProvider } from './contexts/EmailWebSocketContext'; import SocketManagment from './lib/SocketManagment'; import NajvaToken from './components/NajvaToken'; import { ThemeProvider } from './contexts/ThemeContext'; +import ReportBug from '@/pages/guide/ReportBug'; declare global { interface Window { @@ -131,6 +132,7 @@ const App: FC = () => {
+ ) : isLogin === 'isNotLogin' ? ( diff --git a/src/assets/images/sad1.png b/src/assets/images/sad1.png new file mode 100644 index 0000000..dd56d28 Binary files /dev/null and b/src/assets/images/sad1.png differ diff --git a/src/assets/images/sad2.png b/src/assets/images/sad2.png new file mode 100644 index 0000000..b0d77c7 Binary files /dev/null and b/src/assets/images/sad2.png differ diff --git a/src/assets/images/sad3.png b/src/assets/images/sad3.png new file mode 100644 index 0000000..c9dc8f6 Binary files /dev/null and b/src/assets/images/sad3.png differ diff --git a/src/assets/images/smile.png b/src/assets/images/smile.png new file mode 100644 index 0000000..a1ce329 Binary files /dev/null and b/src/assets/images/smile.png differ diff --git a/src/assets/images/smile2.png b/src/assets/images/smile2.png new file mode 100644 index 0000000..542d1f1 Binary files /dev/null and b/src/assets/images/smile2.png differ diff --git a/src/assets/images/smile3.png b/src/assets/images/smile3.png new file mode 100644 index 0000000..5894654 Binary files /dev/null and b/src/assets/images/smile3.png differ diff --git a/src/components/DefaulModal.tsx b/src/components/DefaulModal.tsx index a9956f2..bfdd687 100644 --- a/src/components/DefaulModal.tsx +++ b/src/components/DefaulModal.tsx @@ -33,7 +33,7 @@ const DefaulModal: FC = (props: Props) => { { props.isHeader && props.title_header && -
+
diff --git a/src/components/RowActionsDropdown.tsx b/src/components/RowActionsDropdown.tsx index 43c6846..f4d253e 100644 --- a/src/components/RowActionsDropdown.tsx +++ b/src/components/RowActionsDropdown.tsx @@ -13,9 +13,10 @@ export interface RowActionItem { interface RowActionsDropdownProps { actions: RowActionItem[]; className?: string; + trigger?: React.ReactNode; } -const RowActionsDropdown: React.FC = ({ actions, className = '' }) => { +const RowActionsDropdown: React.FC = ({ actions, className = '', trigger }) => { const [isOpen, setIsOpen] = useState(false) const [position, setPosition] = useState({ top: 0, left: 0 }) const dropdownRef = useRef(null) @@ -102,8 +103,12 @@ const RowActionsDropdown: React.FC = ({ actions, classN ref={buttonRef} onClick={handleToggle} className="mt-2 hover:bg-gray-100 dark:hover:bg-[#2d2d30] rounded-full transition-colors" + aria-haspopup="menu" + aria-expanded={isOpen} > - + {trigger ? trigger : ( + + )} {renderDropdown()} diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx index 36e8956..1cbf691 100644 --- a/src/components/Switch.tsx +++ b/src/components/Switch.tsx @@ -19,20 +19,22 @@ const SwitchComponent = (props: Props) => { {({ checked }) => ( )} { props.label && -
+
: {props.label}
} diff --git a/src/index.css b/src/index.css index 25c8051..9c8543c 100644 --- a/src/index.css +++ b/src/index.css @@ -519,3 +519,8 @@ strong { filter: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(7416%) hue-rotate(296deg) brightness(109%) contrast(97%); } + +.filterBlue { + filter: brightness(0) saturate(100%) invert(9%) sepia(100%) saturate(7246%) + hue-rotate(236deg) brightness(111%) contrast(112%); +} diff --git a/src/pages/guide/ReportBug.tsx b/src/pages/guide/ReportBug.tsx new file mode 100644 index 0000000..ebfa583 --- /dev/null +++ b/src/pages/guide/ReportBug.tsx @@ -0,0 +1,128 @@ +import React, { useMemo, useState } from 'react' +import DefaulModal from '@/components/DefaulModal' +import Textarea from '@/components/Textarea' +import Button from '@/components/Button' +import { useSharedStore } from '@/shared/store/sharedStore' +import { useSendFeedback } from './hooks/useFeedbackData' +import { toast } from '@/components/Toast' +import { ErrorType } from '@/helpers/types' +import { useTheme } from '@/contexts/ThemeContext' + + +// Import images +import sad1 from '@/assets/images/sad1.png' +import sad2 from '@/assets/images/sad2.png' +import sad3 from '@/assets/images/sad3.png' +import smile from '@/assets/images/smile.png' +import smile2 from '@/assets/images/smile2.png' +import smile3 from '@/assets/images/smile3.png' +import { useGetProfile } from '../profile/hooks/useProfileData' + +const ReportBug: React.FC = () => { + const { openReportBug, setOpenReportBug } = useSharedStore() + const [description, setDescription] = useState('') + const [feeling, setFeeling] = useState(null) + const { data } = useGetProfile() + const { mutate: sendReportBug, isPending } = useSendFeedback() + const { theme } = useTheme() + + const isValid = useMemo(() => description.trim().length > 0, [description]) + + const getRatingFromFeeling = (feeling: string | null): number => { + if (!feeling) return 0 + + const feelingMap: Record = { + 'angry': 1, // sad1 + 'crying': 2, // sad2 + 'sad': 3, // sad3 + 'neutral': 4, // smile + 'smile': 5, // smile2 + 'love': 6, // smile3 + } + + return feelingMap[feeling] || 0 + } + + const handleSubmit = async () => { + if (!isValid) return + + sendReportBug({ + content: description, + rating: getRatingFromFeeling(feeling), + serviceId: import.meta.env.VITE_SERVICE_ID, + email: data?.data?.user?.emailAddress, + }, { + onSuccess: () => { + toast('گزارش با موفقیت ارسال شد', 'success') + setDescription('') + setFeeling(null) + setOpenReportBug(false) + }, + onError: (error: ErrorType) => { + toast(error.response?.data?.error?.message[0], 'error') + } + }) + } + + const feelings = [ + { id: 'angry', image: sad1, alt: 'ناراضی' }, + { id: 'crying', image: sad2, alt: 'ناراضی' }, + { id: 'sad', image: sad3, alt: 'ناراضی' }, + { id: 'neutral', image: smile, alt: 'خنثی' }, + { id: 'smile', image: smile2, alt: 'راضی' }, + { id: 'love', image: smile3, alt: 'راضی' }, + ] + + return ( + setOpenReportBug(false)} isHeader title_header='گزارش اشکالات' width={500}> +
+
+ لطفاً در صورت مشاهده هرگونه اشکال یا باگ در سایت، از طریق این فرم گزارش دهید. همچنین می‌توانید بازخورد، نظر یا پیشنهادات خود را درباره سایت با ما به اشتراک بگذارید. اطلاعات دقیق شما به ما کمک می‌کند مشکلات را سریع‌تر برطرف کنیم و کیفیت سایت را بهبود بخشیم. +
+ +