app\containers\SampleFirebaseApps\Email\services\emailApi.js
fetchMails: builder.query({
queryFn: async () => {
const emailRef = child(dbRef, 'emails/');
const querySnapshot = await get(emailRef).then((snapshot) => {
if (snapshot.exists()) {
return snapshot.val();
}
return false;
}).catch((error) => error);
const emails = Object.keys(querySnapshot).map(key => ({
id: key,
...querySnapshot[key]
}));
return { data: emails.reverse() };
},
providesTags: ['Email'],
}),
refetchEmail: builder.mutation({
queryFn: async () => ({
data: null
}),
invalidatesTags: ['Email'],
}),
app\containers\SampleFirebaseApps\Email\slice\emailSlice.js
fetchData: (state, action) => {
const items = action.payload;
state.inbox = items;
},
\app\containers\SampleFirebaseApps\Email\index.js
import { useFetchMailsQuery } from './services/emailApi';
import { fetchData } from './reducers/emailSlice';
const emailData = useSelector(state => state.emailFb.inbox);
const { data, isLoading } = useFetchMailsQuery();
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchData(data));
}, [data]);
return {
<EmailList
loading={isLoading}
emailData={emailData}
openMail={(payload) => dispatch(open(payload))}
filterPage={currentPage}
keyword={keyword}
moveTo={(mail, category) => handleMove({ mail, category })}
remove={(mail) => handleDelete(mail)}
toggleStar={(mail) => handleToggle(mail)}
reply={handleReply}
/>
}
app\components\Email\EmailList.js
const getItem = dataArray => dataArray.map(data => {
const renderHTML = { __html: mail.content };
if (mail.subject.toLowerCase().indexOf(keyword) === -1) {
return false;
}
return (
<ExpansionPanel className={classes.emailList} key={mail.id} onChange={() => openMail(mail)}>
<ExpansionPanelSummary className={classes.emailSummary} expandIcon={<ExpandMoreIcon />}>
<div className={classes.fromHeading}>
<Tooltip id="tooltip-mark" title={intl.formatMessage(messages.stared)}>
<IconButton onClick={() => this.handleStared(mail)} className={classes.starBtn}>{mail.stared ? (<Star className={classes.iconOrange} />) : (<StarBorder />) }</IconButton>
</Tooltip>
{mail.category !== 'spam'
? (<Avatar alt="avatar" src={mail.avatar} className={classes.avatar} />)
: (<Avatar alt="avatar" className={classes.avatar}><ReportIcon /></Avatar>)
}
<Typography className={classes.heading}>
{mail.category === 'sent' && ('To ')}
{mail.name}
<Typography variant="caption">{mail.date}</Typography>
</Typography>
</div>
<div className={classes.column}>
<Typography className={classes.secondaryHeading} noWrap>{mail.subject}</Typography>
{getCategory(mail.category)}
</div>
</ExpansionPanelSummary>
<ExpansionPanelDetails className={classes.details}>
<section>
<div className={classes.topAction}>
<Typography className={classes.headMail}>
{mail.category !== 'sent' && (
<Fragment>
<FormattedMessage {...messages.from} />
{mail.name}
to me
</Fragment>
)}
</Typography>
<div className={classes.opt}>
<Tooltip id="tooltip-mark" title={intl.formatMessage(messages.stared)}>
<IconButton onClick={() => this.handleStared(mail)}>{mail.stared ? (<Star className={classes.iconOrange} />) : (<StarBorder />) }</IconButton>
</Tooltip>
<Tooltip id="tooltip-mark" title={intl.formatMessage(messages.mark_to)}>
<IconButton
className={classes.button}
aria-label="mark"
aria-owns={anchorElOpt ? 'long-menu' : null}
aria-haspopup="true"
onClick={(event) => this.handleClickOpt(event, mail)}
>
<Bookmark />
</IconButton>
</Tooltip>
<Tooltip id="tooltip-mark" title={intl.formatMessage(messages.remove)}>
<IconButton className={classes.button} aria-label="Delete" onClick={() => remove(mail)}><Delete /></IconButton>
</Tooltip>
</div>
</div>
<div className={classes.emailContent}>
<Typography variant="h6" gutterBottom>{mail.subject}</Typography>
<article dangerouslySetInnerHTML={renderHTML} />
</div>
</section>
</ExpansionPanelDetails>
<Divider />
<ExpansionPanelActions>
<div className={classes.action}>
<Button size="small">
<FormattedMessage {...messages.forward} />
</Button>
<Button size="small" color="secondary" onClick={() => reply(mail)}>
<FormattedMessage {...messages.reply} />
</Button>
</div>
</ExpansionPanelActions>
</ExpansionPanel>
);
});
app\containers\SampleFirebaseApps\Email\services\emailApi.js
sendMail: builder.mutation({
queryFn: async (payload) => {
const { name, subject, content } = payload;
const newMail = buildMessage(name, subject, content);
const mailId = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
set(ref(db, 'emails/' + mailId), newMail);
return { data: null };
},
invalidatesTags: ['Email'],
}),
app\containers\SampleFirebaseApps\Email\slice\emailSlice.js
send: (state) => {
state.selectedMail = '';
state.openFrm = false;
},
app\containers\SampleFirebaseApps\Email\index.js
import { useSendMailMutation } from './services/emailApi';
import { send } from './reducers/emailSlice';
const [sendMail, { isLoading: sendingMail }] = useSendMailMutation();
const handleSend = (payload) => {
sendMail(payload);
dispatch(send());
setMessage(notif.sent);
};
return (
<ComposeEmail
to={field.to}
subject={field.subject}
compose={handleCompose}
validMail={validMail}
sendEmail={(payload) => handleSend(payload)}
inputChange={(e, name) => handleChange(e, name)}
open={openFrm}
closeForm={() => dispatch(discard())}
processing={sendingMail}
/>
)
app\components\Email\ComposeEmail.js
handleSend = message => {
const { sendEmail } = this.props;
sendEmail(message);
this.setState({ emailContent: '', files: [] });
};
return (
<Button
variant="contained"
color="secondary"
type="button"
disabled={!to || !subject || processing}
onClick={() => handleSend(newData)}
>
{processing && <CircularProgress size={24} className={classes.buttonProgress} />}
<FormattedMessage {...messages.send} />
<Send className={classes.sendIcon} />
</Button>
)
app\containers\SampleFirebaseApps\Email\services\emailServices.js
toggleStar: builder.mutation({
queryFn: async (mail) => {
const updates = {};
updates['/emails/' + mail.id] = { ...mail, stared: !mail.stared };
update(ref(db), updates);
return { data: null };
},
invalidatesTags: ['Email'],
}),
moveMail: builder.mutation({
queryFn: async (payload) => {
const { mail, category } = payload;
const updates = {};
updates['/emails/' + mail.id] = { ...mail, category };
await update(ref(db), updates)
.then(() => {
console.log('changes success');
}).catch((error) => {
console.log(error);
});
return { data: null };
},
invalidatesTags: ['Email'],
})
app\containers\SampleFirebaseApps\Email\index.js
import { useToggleStarMutation, useMoveMailMutation } from './services/emailApi';
const [toggleStar] = useToggleStarMutation();
const [moveMail] = useMoveMailMutation();
const handleToggle = (mail) => {
toggleStar(mail);
};
const handleMove = (payload) => {
moveMail(payload);
setMessage(notif.labeled);
};
return (
<EmailList
loading={isLoading}
emailData={emailData}
openMail={(payload) => dispatch(open(payload))}
filterPage={currentPage}
keyword={keyword}
moveTo={(mail, category) => handleMove({ mail, category })}
remove={(mail) => handleDelete(mail)}
toggleStar={(mail) => handleToggle(mail)}
reply={handleReply}
/>
)
app\components\Email\EmailList.js
const handleMoveTo = (item, category) => {
moveTo(item, category);
setAnchorElOpt(null);
};
const handleStared = mail => {
toggleStar(mail, { stared: !mail.stared });
};
return (
<IconButton onClick={() => handleStared(mail)} className={classes.starBtn}>{mail.stared ? (<Star className={classes.iconOrange} />) : (<StarBorder />) }</IconButton>
<MenuItem selected onClick={() => handleMoveTo(itemToMove, 'updates')}>
<Flag className={classes.iconOrange} />
<FormattedMessage {...messages.updates} />
</MenuItem>
)
app\containers\SampleFirebaseApps\Email\services\emailApi.js
deleteMail: builder.mutation({
queryFn: async (mail) => {
const mailId = mail.id;
await remove(ref(db, 'emails/' + mailId))
.then(() => {
console.log('delete success');
}).catch((error) => {
console.log(error);
});
return { data: null };
},
invalidatesTags: ['Email'],
}),
app\containers\SampleFirebaseApps\Email\index.js
import { useDeleteMailMutation } from './services/emailApi';
const [deleteMail] = useDeleteMailMutation();
const handleDelete = (mail) => {
deleteMail(mail);
setMessage(notif.removed);
};
return (
<EmailList
loading={isLoading}
emailData={emailData}
openMail={(payload) => dispatch(open(payload))}
filterPage={currentPage}
keyword={keyword}
moveTo={(mail, category) => handleMove({ mail, category })}
remove={(mail) => handleDelete(mail)}
toggleStar={(mail) => handleToggle(mail)}
reply={handleReply}
/>
)
app/components/Email/EmailList.js
return (
<IconButton className={classes.button} aria-label="Delete" onClick={() => remove(mail)}><Delete /></IconButton>
)