diff --git a/src/components/emails/compose-modal.tsx b/src/components/emails/compose-modal.tsx
index bd93222..8862cc1 100644
--- a/src/components/emails/compose-modal.tsx
+++ b/src/components/emails/compose-modal.tsx
@@ -1,71 +1,63 @@
-import React, { Dispatch } from 'react';
+import React, { Dispatch } from 'react';
import { Select, Form, Input, Button } from 'antd';
-import {EmailCreation, User} from '../../types';
+import { EmailCreation, User } from '../../types';
import { connect } from 'react-redux';
-import {sendEmail} from '../../store/emails/actions';
-import {ActionTypes} from '../../store/emails/types';
-
+import { sendEmail } from '../../store/emails/actions';
+import { ActionTypes } from '../../store/emails/types';
interface ComposeModal {
- sendEmail : (data:EmailCreation) => void,
- modalInfo ?: any,
- emailSuccessMessage : string,
- currentUser : User
+ sendEmail: (data: EmailCreation) => void;
+ modalInfo?: any;
+ emailSuccessMessage: string;
+ currentUser: User;
}
-function ComposeModal({sendEmail, currentUser}:ComposeModal) {
- const {email} = currentUser;
-
- const onFinish = (values:EmailCreation) => {
- if(!values.body.trim()){
- if(!window.confirm("Do you want to proceed without body ?")){
+function ComposeModal({ sendEmail, currentUser }: ComposeModal) {
+ const { email } = currentUser;
+
+ const onFinish = (values: EmailCreation) => {
+ if (!values.body?.trim()) {
+ if (!window.confirm('Do you want to proceed without body ?')) {
return false;
}
}
- sendEmail({...values, sender : email});
+ sendEmail({ ...values, sender: email });
};
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
}
-
-const mapStateToProps = ({email, auth}:any) => {
-
+const mapStateToProps = ({ email, auth }: any) => {
return {
- currentUser : auth.currentUser,
- emailSuccessMessage : email.successMessage
- }
-}
+ currentUser: auth.currentUser,
+ emailSuccessMessage: email.successMessage,
+ };
+};
-const mapDispatchToProps = (dispatch:Dispatch) => {
+const mapDispatchToProps = (dispatch: Dispatch) => {
return {
- sendEmail : (data:EmailCreation) => dispatch(sendEmail(data)),
+ sendEmail: (data: EmailCreation) => dispatch(sendEmail(data)),
};
};
-
-export default connect(
- mapStateToProps,
- mapDispatchToProps
-)(ComposeModal);
\ No newline at end of file
+export default connect(mapStateToProps, mapDispatchToProps)(ComposeModal);
\ No newline at end of file
diff --git a/src/components/emails/list.tsx b/src/components/emails/list.tsx
index 944f5c7..603d334 100644
--- a/src/components/emails/list.tsx
+++ b/src/components/emails/list.tsx
@@ -1,68 +1,66 @@
-import React, { useState, Dispatch, useEffect } from 'react';
+import React, { useState, Dispatch } from 'react';
import { Table, Button } from 'antd';
-import { Redirect, useParams, useHistory } from 'react-router-dom';
+import { useParams, useNavigate } from 'react-router-dom';
import { connect } from 'react-redux';
-import {includes} from 'lodash';
+import { includes } from 'lodash';
import './list.css';
-import {ParamTypes} from '../../types';
-import {emailListColumns, emailListFirstColumn} from './config';
-import {deleteEmail} from '../../store/emails/actions';
-import {ActionTypes} from '../../store/emails/types';
+import { emailListColumns, emailListFirstColumn } from './config';
+import { deleteEmail } from '../../store/emails/actions';
+import { ActionTypes } from '../../store/emails/types';
-function EmailList({emails, deleteEmail}:any) {
- const rhist:any = useHistory();
- let { emailAction } = useParams();
- const firstColumn = emailListFirstColumn[emailAction] || {};
- const [selectedRowKeys, setSelectedRowKeys] = useState([]);
- const onSelectChange = (selectedRowKeys:any) => {
- setSelectedRowKeys(selectedRowKeys);
- }
+function EmailList({ emails, deleteEmail }: any) {
+ const navigate = useNavigate();
+ let { emailAction } = useParams<{ emailAction: string }>();
+ const firstColumn = emailListFirstColumn[emailAction!] || {};
+ const [selectedRowKeys, setSelectedRowKeys] = useState([]);
- const deleteAnEmail = () => {
- const emailList = emails
- .filter((email:any, index:number) => includes(selectedRowKeys, index))
- .map(({emailUuid}:any) => emailUuid)
- deleteEmail(emailList);
- setSelectedRowKeys([]);
- }
-
-
+ const onSelectChange = (selectedRowKeys: any) => {
+ setSelectedRowKeys(selectedRowKeys);
+ };
+ const deleteAnEmail = () => {
+ const emailList = emails
+ .filter((email: any, index: number) => includes(selectedRowKeys, index))
+ .map(({ emailUuid }: any) => emailUuid);
+ deleteEmail(emailList);
+ setSelectedRowKeys([]);
+ };
- return (
- <>
-
- (readClass || "")}
- rowKey={({index}) => index}
- onRow={({emailUuid}, rowIndex) => {
- return {
- onClick: event => rhist.push(`/dashboard/${emailAction}/view/${emailUuid}`)
- }
- }}
- columns={[firstColumn, ...emailListColumns]} dataSource={emails} />
- >
- );
+ return (
+ <>
+
+ readClass || ""}
+ rowKey={({ index }) => index}
+ onRow={({ emailUuid }, rowIndex) => ({
+ onClick: event => navigate(`/dashboard/${emailAction}/view/${emailUuid}`)
+ })}
+ columns={[firstColumn, ...emailListColumns]}
+ dataSource={emails}
+ />
+ >
+ );
}
+const mapDispatchToProps = (dispatch: Dispatch) => {
+ return {
+ deleteEmail: (emailUuids: string[]) => dispatch(deleteEmail(emailUuids)),
+ };
+};
-const mapDispatchToProps = (dispatch:Dispatch) => {
+const mapStateToProps = ({ email, auth }: any) => {
return {
- deleteEmail : (emailUuids:string[]) => dispatch(deleteEmail(emailUuids)),
+ currentUser: auth.currentUser,
+ emails: email.emails,
};
};
-const mapStateToProps = ({email, auth}:any) => {
- return {
- currentUser : auth.currentUser,
- emails : email.emails,
- }
-}
-export default connect(
- mapStateToProps,
- mapDispatchToProps
-)(EmailList);
+export default connect(mapStateToProps, mapDispatchToProps)(EmailList);
\ No newline at end of file
diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx
index e8f9948..d467fcd 100644
--- a/src/pages/dashboard/index.tsx
+++ b/src/pages/dashboard/index.tsx
@@ -1,6 +1,6 @@
import React, {useEffect, Dispatch, useState} from 'react';
import { connect } from 'react-redux';
-import { Redirect, useParams,Switch, Route } from 'react-router-dom';
+import { Navigate, useParams, Routes, Route } from 'react-router-dom';
import EmailList from '../../components/emails/list';
import EmailOps from '../../components/emails/ops';
import EmailView from '../../components/emails/view';
@@ -14,104 +14,105 @@ import * as AuthTypes from '../../store/auth/types';
import {isEmpty} from 'lodash';
import {getEmails} from '../../store/emails/actions';
import {ActionTypes} from '../../store/emails/types';
-import {User, ParamTypes} from '../../types';
-import { Button, Layout, Menu , message} from 'antd';
+import {User} from '../../types';
+import { Button, Layout, message } from 'antd';
import { MailOutlined } from '@ant-design/icons';
import './style.css';
const { Header, Content, Footer } = Layout;
interface dashboardProps {
- getEmailsUpdate : (email:string, emailAction?:string) => void,
- successMessage : string,
- errorMessage : string,
- reset : () => void,
- signOut: (currentUser:User) => void
-};
-
+ getEmailsUpdate: (email: string, emailAction?: string) => void,
+ successMessage: string,
+ errorMessage: string,
+ reset: () => void,
+ signOut: (currentUser: User) => void
+}
-function Dashboard({unreadCount, match, signOut, currentUser, emails, successMessage, errorMessage, reset, getEmailsUpdate}:any) {
+function Dashboard({unreadCount, signOut, currentUser, emails, successMessage, errorMessage, reset, getEmailsUpdate}: any) {
const [login, goToLogin] = useState(false);
- let { emailAction} = useParams();
- useEffect(()=>{
- if(successMessage){
+ let { emailAction } = useParams<{emailAction: string}>();
+
+ // ✅ Fix: extract emailAction from URL path if useParams returns undefined
+ const pathEmailAction = emailAction || window.location.pathname.split('/')[2];
+
+ useEffect(() => {
+ if (successMessage) {
message.success(successMessage);
- return reset()
+ reset();
}
- if(errorMessage){
- message.success(errorMessage);
- return reset()
+
+ if (errorMessage) {
+ message.error(errorMessage);
+ reset();
}
- if(!isEmpty(currentUser)){
- getEmailsUpdate(currentUser.email, emailAction);
- }else{
+ if (!isEmpty(currentUser)) {
+ // ✅ Fix: use pathEmailAction instead of emailAction
+ getEmailsUpdate(currentUser.email, pathEmailAction);
+ } else {
goToLogin(true);
}
- })
+ // ✅ Fix: use pathEmailAction in dependency array
+ }, [currentUser, pathEmailAction, successMessage, errorMessage]);
const getOut = () => {
signOut(currentUser);
}
- if(login){
- return
+ if (login) {
+ return ;
}
- console.log("match", match);
+
return (
-
-
- (
-
- {unreadCount}
-
)
-
+
+
+
+
+ {unreadCount}
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ {/* ✅ Fix: pass pathEmailAction instead of emailAction */}
+
+
+
+
+ } />
+ } />
+
+
-
);
}
-const mapStateToProps = ({email, notification, auth}:any) => {
+const mapStateToProps = ({email, notification, auth}: any) => {
return {
- currentUser : auth.currentUser,
- successMessage : notification.successMessage,
- errorMessage : notification.errorMessage,
- unreadCount : email.unreadCount
+ currentUser: auth.currentUser,
+ successMessage: notification.successMessage,
+ errorMessage: notification.errorMessage,
+ unreadCount: email.unreadCount
}
}
-const mapDispatchToProps = (dispatch:Dispatch) => {
+const mapDispatchToProps = (dispatch: Dispatch) => {
return {
- reset : () => dispatch(reset()),
- signOut : (data:User) => dispatch(signOut(data)),
- getEmailsUpdate: (email:string, emailAction?:string) => dispatch(getEmails(email, emailAction))
+ reset: () => dispatch(reset()),
+ signOut: (data: User) => dispatch(signOut(data)),
+ getEmailsUpdate: (email: string, emailAction?: string) => dispatch(getEmails(email, emailAction))
};
};
-
export default connect(
mapStateToProps,
mapDispatchToProps
-)(Dashboard);
+)(Dashboard);
\ No newline at end of file
diff --git a/src/sagas/auth.ts b/src/sagas/auth.ts
index 00483d3..6200ec1 100644
--- a/src/sagas/auth.ts
+++ b/src/sagas/auth.ts
@@ -1,27 +1,29 @@
import { put, call, take, takeLatest} from 'redux-saga/effects';
+import { SagaIterator } from 'redux-saga';
import {START_LOGIN, START_SIGNOUT} from '../store/auth/types';
import {signInSuccess, signOutSuccess} from '../store/auth/actions';
import {notifyError, notify} from '../store/notification/actions';
import {login, signout} from '../services/api';
import {Credentials, EmailCreation, User} from '../types'
+
const ANY_ERROR_TEXT = 'Something went wrong, please try again';
-function* loginUpdates({credentials}: any) {
+function* loginUpdates({credentials}: any): SagaIterator {
try{
- // console.log("payload", payload);
const currentUser = yield call(login, credentials)
yield put(signInSuccess(currentUser));
- }catch({message}){
+ }catch(e){
+ const message = (e as Error).message;
yield put(notifyError(message || ANY_ERROR_TEXT));
}
}
-function* signOutUpdates({currentUser}: any) {
+function* signOutUpdates({currentUser}: any): SagaIterator {
try{
- // console.log("payload", payload);
const response = yield call(signout, currentUser)
yield put(signOutSuccess());
- }catch({message}){
+ }catch(e){
+ const message = (e as Error).message;
yield put(notifyError(message || ANY_ERROR_TEXT));
}
}
@@ -30,5 +32,3 @@ export function* watchAuth() {
yield takeLatest(START_LOGIN, loginUpdates)
yield takeLatest(START_SIGNOUT, signOutUpdates)
}
-
-
diff --git a/src/sagas/email.ts b/src/sagas/email.ts
index 16eadab..b21dbb9 100644
--- a/src/sagas/email.ts
+++ b/src/sagas/email.ts
@@ -1,47 +1,42 @@
-import { put, call, take, takeLatest} from 'redux-saga/effects';
-
+import { put, call, takeLatest } from 'redux-saga/effects';
+import { SagaIterator } from 'redux-saga';
import {GET_EMAILS_START, SEND_EMAIL_START, DELETE_EMAIL, SET_EMAIL_READ} from '../store/emails/types';
-import {getEmailsSuccess, deleteEmailSuccess} from '../store/emails/actions';
+import {getEmailsSuccess, deleteEmailSuccess, sendEmailSuccess, getEmails} from '../store/emails/actions';
import {notify} from '../store/notification/actions';
import {getAccountEmails, sendAccountEmail, deleteEmails, setEmailRead} from '../services/api';
-import {EmailCreation} from '../types'
-function* getEmailUpdates({email, emailAction}:any) {
+function* getEmailUpdates({email, emailAction}:any): SagaIterator {
try{
const response = yield call(getAccountEmails, email, emailAction)
yield put(getEmailsSuccess(response));
-
}catch(e){
-
}
}
-function* sendEmailUpdates({payload}: any){
+function* sendEmailUpdates({payload}: any): SagaIterator {
try{
const response = yield call(sendAccountEmail, payload)
- yield put(notify(response.message));
+ yield put(notify(response.message));
+ yield put(sendEmailSuccess(response.message));
+ yield put(getEmails(payload.sender, 'send'));
}catch(e){
- // yield put(getError(response));
}
}
-
-function* deleteEmailUpdates({emailUuids}: any){
+function* deleteEmailUpdates({emailUuids}: any): SagaIterator {
try{
const response = yield call(deleteEmails, emailUuids)
yield put(notify(response.message));
yield put(getEmailsSuccess(response.emails));
}catch(e){
- // yield put(getError(response));
}
}
-function* setEmailreadUpdates({emailUuid}:any){
+function* setEmailreadUpdates({emailUuid}:any): SagaIterator {
try{
const response = yield call(setEmailRead, emailUuid)
yield put(getEmailsSuccess(response.emails));
}catch(e){
- // yield put(getError(response));
}
}
@@ -50,6 +45,4 @@ export function* watchEmail() {
yield takeLatest(SEND_EMAIL_START, sendEmailUpdates)
yield takeLatest(DELETE_EMAIL, deleteEmailUpdates)
yield takeLatest(SET_EMAIL_READ, setEmailreadUpdates)
-}
-
-
+}
\ No newline at end of file
diff --git a/src/sagas/index.ts b/src/sagas/index.ts
index 12bdad0..06f5bf9 100644
--- a/src/sagas/index.ts
+++ b/src/sagas/index.ts
@@ -1,7 +1,7 @@
-import { all } from 'redux-saga/effects';
+import { all, fork } from 'redux-saga/effects';
import { watchEmail } from './email';
import {watchAuth} from './auth';
-export default function* rootSaga() {
- return yield all([watchEmail(), watchAuth()]);
+export default function* rootSaga() {
+ yield all([fork(watchEmail), fork(watchAuth)]);
}
\ No newline at end of file
diff --git a/src/services/api.ts b/src/services/api.ts
index 61a22f3..a5886c1 100644
--- a/src/services/api.ts
+++ b/src/services/api.ts
@@ -1,8 +1,8 @@
-import { isJSDocPublicTag } from 'typescript';
import {Credentials, Email, EmailCreation, User} from '../types'
import {includes} from 'lodash';
+
export async function getAccountEmails(email:string, emailAction?:string){
- let emails = localStorage.getItem('emails');
+ let emails = localStorage.getItem('emails');
if(emails && emails.length){
const parsedEmails = JSON.parse(emails);
console.log("emailAction", emailAction);
@@ -10,84 +10,89 @@ export async function getAccountEmails(email:string, emailAction?:string){
case 'send':
return parsedEmails.filter(({sender}: any) => email === sender);
default:
- return parsedEmails.filter(({to}: any) => includes(to, email));
+ return parsedEmails.filter(({to}: any) => includes(to, email));
}
}
return [];
}
export async function sendAccountEmail(email: EmailCreation){
- let emails = localStorage.getItem('emails');
- console.log("ermead", emails)
- if(emails && emails.length){
- const parsedEmails = JSON.parse(emails);
- if(parsedEmails.length){
- let emailUuid = parsedEmails[0] ? (parsedEmails[0].emailUuid + 1) : 1234;
- parsedEmails.unshift({...email, read: false, created_at : Date.now(), emailUuid : emailUuid})
- }
- localStorage.emails = JSON.stringify(parsedEmails);
- return {
- message : "Email send successfully",
- emails
- };
- // return emails.filter(({to}:any) => to === emails)
- }
- return [];
+ let emails = localStorage.getItem('emails');
+
+ // ✅ Fix: handle both empty and non-empty cases
+ const parsedEmails = emails && emails.length ? JSON.parse(emails) : [];
+
+ let emailUuid = parsedEmails.length > 0 ? (parsedEmails[0].emailUuid + 1) : 1234;
+ parsedEmails.unshift({
+ ...email,
+ read: false,
+ created_at: Date.now(),
+ emailUuid: emailUuid
+ });
+
+ // ✅ Fix: always save back to localStorage
+ localStorage.setItem('emails', JSON.stringify(parsedEmails));
+
+ return {
+ message: "Email sent successfully",
+ emails: parsedEmails
+ };
}
export async function login(credentials: Credentials){
- let users = localStorage.getItem('users');
+ let users = localStorage.getItem('users');
if(users && users.length){
const parsedUsers = JSON.parse(users);
if(users.length){
- const selectedUser = parsedUsers.find(({email, password}: User) => credentials.email === email && credentials.password === password)
+ const selectedUser = parsedUsers.find(({email, password}: User) =>
+ credentials.email === email && credentials.password === password
+ )
if(selectedUser){
- localStorage.currentUser = JSON.stringify(selectedUser);
- return Promise.resolve(selectedUser);
+ localStorage.currentUser = JSON.stringify(selectedUser);
+ return Promise.resolve(selectedUser);
}
}
}
-
return Promise.reject({
- message : 'User not found'
+ message: 'User not found'
})
}
export async function signout(currentUser: User){
delete localStorage.currentUser;
- return {message : "Logout successfully"};
+ return {message: "Logout successfully"};
}
-export async function deleteEmails(uuids : string[]){
- let emails = localStorage.getItem('emails');
+export async function deleteEmails(uuids: string[]){
+ let emails = localStorage.getItem('emails');
if(emails && emails.length){
const parsedEmails = JSON.parse(emails);
- const newList = parsedEmails.filter(({emailUuid}:any) => !includes(uuids, emailUuid));
- localStorage.emails = JSON.stringify(newList)
+ const newList = parsedEmails.filter(({emailUuid}:any) => !includes(uuids, emailUuid));
+ localStorage.setItem('emails', JSON.stringify(newList));
return {
- message : "Deleted email successfully",
- emails : newList
+ message: "Deleted email successfully",
+ emails: newList
}
}
return Promise.reject({
- message : 'Email not found'
+ message: 'Email not found'
});
}
export async function setEmailRead(uuid:string){
- let emails = localStorage.getItem('emails');
+ let emails = localStorage.getItem('emails');
if(emails && emails.length){
const parsedEmails = JSON.parse(emails);
- const list = parsedEmails.map(({emailUuid, ...otherInfo}:any) => {
+ const list = parsedEmails.map(({emailUuid, ...otherInfo}:any) => {
if(emailUuid == uuid){
otherInfo.read = true;
}
return {emailUuid, ...otherInfo};
});
- localStorage.emails = JSON.stringify(list);
- return {emails : list}
+ localStorage.setItem('emails', JSON.stringify(list));
+ return {emails: list}
}
return Promise.reject({
- message : 'Email not found'
+ message: 'Email not found'
});
}
\ No newline at end of file