├── src ├── index.css ├── redux │ ├── store.js │ └── appSlice.js ├── components │ ├── Body.jsx │ ├── Login.jsx │ ├── Messages.jsx │ ├── Message.jsx │ ├── Sidebar.jsx │ ├── SendEmail.jsx │ ├── Inbox.jsx │ ├── Navbar.jsx │ └── Mail.jsx ├── main.jsx ├── firebase.js ├── App.jsx └── assets │ └── react.svg ├── .firebaserc ├── postcss.config.js ├── .firebase ├── hosting.YnVpbGQ.cache └── hosting.ZGlzdA.cache ├── vite.config.js ├── tailwind.config.js ├── firebase.json ├── .gitignore ├── index.html ├── README.md ├── .eslintrc.cjs ├── package.json └── public └── vite.svg /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "clone-6dd4f" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /.firebase/hosting.YnVpbGQ.cache: -------------------------------------------------------------------------------- 1 | index.html,1716703506255,171519f644167f1bc5a0a4c15052ae48817a7c7b1f802c2052f4ea8f3b37f6e3 2 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./src/**/*.{html,js,jsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/redux/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from "@reduxjs/toolkit"; 2 | import appSlice from "./appSlice"; 3 | 4 | const store = configureStore({ 5 | reducer:{ 6 | app:appSlice 7 | } 8 | }); 9 | 10 | export default store; -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/components/Body.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Sidebar from './Sidebar' 3 | import { Outlet } from 'react-router-dom' 4 | import Navbar from './Navbar' 5 | 6 | const Body = () => { 7 | return ( 8 |
9 | 10 | 11 |
12 | ) 13 | } 14 | 15 | export default Body -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /.firebase/hosting.ZGlzdA.cache: -------------------------------------------------------------------------------- 1 | index.html,1716704170440,100e2c331ea44f0c698222d72699dc06db4ed1e520a142d21b5de349d567fa92 2 | vite.svg,1712510425607,699a02e0e68a579f687d364bbbe7633161244f35af068220aee37b1b33dfb3c7 3 | assets/index-C60g72fR.css,1716704170440,1db27413a037c5b6f43a37435d052453f13344215b1a49953d4d625c285192ba 4 | assets/index-FEP9XdV2.js,1716704170440,58740b64ff4dae2d28175522c68c5b53022707f1f1b45df3bffd0398ef0c4e8c 5 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gmail 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | import { Provider } from 'react-redux'; 6 | import store from './redux/store.js'; 7 | 8 | ReactDOM.createRoot(document.getElementById('root')).render( 9 | 10 | 11 | 12 | 13 | , 14 | ) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /src/firebase.js: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getAnalytics } from "firebase/analytics"; 3 | import { getDatabase } from "firebase/database"; 4 | import { GoogleAuthProvider,getAuth } from "firebase/auth"; 5 | import { getFirestore } from "firebase/firestore"; 6 | 7 | const firebaseConfig = { 8 | apiKey: "AIzaSyCCxklo4ehV_I5NwZWRkDReg46I-3Rpo5A", 9 | authDomain: "clone-6dd4f.firebaseapp.com", 10 | projectId: "clone-6dd4f", 11 | storageBucket: "clone-6dd4f.appspot.com", 12 | messagingSenderId: "781876226205", 13 | appId: "1:781876226205:web:0d4463c344d70c0994cc74", 14 | measurementId: "G-ZT3MWT0RX8" 15 | }; 16 | 17 | // Initialize Firebase 18 | const app = initializeApp(firebaseConfig); 19 | const analytics = getAnalytics(app); 20 | export const auth = getAuth(); 21 | export const db = getFirestore(app); 22 | export const provider = new GoogleAuthProvider(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gmailclone", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@reduxjs/toolkit": "^2.2.5", 14 | "firebase": "^10.12.1", 15 | "framer-motion": "^11.2.6", 16 | "react": "^18.2.0", 17 | "react-avatar": "^5.0.3", 18 | "react-dom": "^18.2.0", 19 | "react-google-button": "^0.8.0", 20 | "react-icons": "^5.2.1", 21 | "react-redux": "^9.1.2", 22 | "react-router-dom": "^6.23.1" 23 | }, 24 | "devDependencies": { 25 | "@types/react": "^18.2.66", 26 | "@types/react-dom": "^18.2.22", 27 | "@vitejs/plugin-react": "^4.2.1", 28 | "autoprefixer": "^10.4.19", 29 | "eslint": "^8.57.0", 30 | "eslint-plugin-react": "^7.34.1", 31 | "eslint-plugin-react-hooks": "^4.6.0", 32 | "eslint-plugin-react-refresh": "^0.4.6", 33 | "postcss": "^8.4.38", 34 | "tailwindcss": "^3.4.3", 35 | "vite": "^5.2.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/redux/appSlice.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | const appSlice = createSlice({ 4 | name: "app", 5 | initialState: { 6 | open: false, 7 | selectedMail: null, 8 | searchText: "", 9 | emails: null, // This might need to be initialized as an array or object depending on your application logic 10 | authUser: null 11 | }, 12 | reducers: { 13 | setOpen: (state, action) => { 14 | state.open = action.payload; 15 | }, 16 | setSelectedMail: (state, action) => { 17 | state.selectedMail = action.payload; 18 | }, 19 | setSearchText: (state, action) => { 20 | state.searchText = action.payload; 21 | }, 22 | setEmails: (state, action) => { 23 | state.emails = action.payload; 24 | }, 25 | setAuthUser: (state, action) => { 26 | state.authUser = action.payload; 27 | } 28 | } 29 | }); 30 | 31 | export const { 32 | setOpen, 33 | setSelectedMail, 34 | setSearchText, 35 | setEmails, 36 | setAuthUser 37 | } = appSlice.actions; 38 | 39 | export default appSlice.reducer; 40 | -------------------------------------------------------------------------------- /src/components/Login.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { signInWithPopup } from 'firebase/auth'; 3 | import { auth, provider } from '../firebase'; 4 | import GoogleButton from 'react-google-button'; 5 | import { useDispatch } from 'react-redux'; 6 | import { setAuthUser } from '../redux/appSlice'; 7 | 8 | const Login = () => { 9 | 10 | const dispatch = useDispatch(); 11 | 12 | const signInWithGoogle = async () => { 13 | try { 14 | const result = await signInWithPopup(auth, provider); 15 | dispatch(setAuthUser({ 16 | displayName: result.user.displayName, 17 | email: result.user.email, 18 | photoURL: result.user.photoURL 19 | })); 20 | } catch (error) { 21 | console.log(error); 22 | } 23 | } 24 | return ( 25 |
26 |
27 |

LOGIN

28 | 29 |
30 |
31 | ) 32 | } 33 | 34 | export default Login -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Messages.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import Message from './Message' 3 | import { collection, getDocs, onSnapshot, orderBy, query } from 'firebase/firestore'; 4 | import { db } from '../firebase'; 5 | import { useDispatch, useSelector } from 'react-redux'; 6 | import { setEmails } from '../redux/appSlice'; 7 | 8 | const Messages = () => { 9 | const { searchText, emails } = useSelector(store => store.app); 10 | const [filterEmail, setFilterEmail] = useState(emails); 11 | const dispatch = useDispatch(); 12 | 13 | useEffect(() => { 14 | const q = query(collection(db, "emails"), orderBy('createdAt', 'desc')); 15 | const unsubscribe = onSnapshot(q, (snapshot) => { 16 | const allEmails = snapshot.docs.map((doc) => ({ ...doc.data(), id: doc.id })); 17 | dispatch(setEmails(allEmails)); 18 | }); 19 | 20 | return () => unsubscribe(); // Cleanup function to unsubscribe when component unmounts 21 | }, []); 22 | 23 | useEffect(() => { 24 | const filteredEmail = emails?.filter((email) => { 25 | return email.subject.toLowerCase().includes(searchText.toLowerCase()) || email.to.toLowerCase().includes(searchText.toLowerCase()) || email.message.toLowerCase().includes(searchText.toLowerCase()) 26 | }); 27 | setFilterEmail(filteredEmail); 28 | }, [searchText, emails]); 29 | 30 | return ( 31 |
32 | { 33 | filterEmail?.map((email) => ) 34 | } 35 | 36 |
37 | ) 38 | } 39 | 40 | export default Messages -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import Navbar from './components/Navbar'; 2 | import Inbox from './components/Inbox'; 3 | import SendEmail from './components/SendEmail'; 4 | import { createBrowserRouter, RouterProvider } from 'react-router-dom'; 5 | import Mail from './components/Mail'; 6 | import Body from './components/Body'; 7 | import { useDispatch, useSelector } from 'react-redux'; 8 | import Login from './components/Login'; 9 | import { useEffect } from 'react'; 10 | import { auth } from './firebase'; 11 | import { setAuthUser } from './redux/appSlice'; 12 | 13 | const router = createBrowserRouter([ 14 | { 15 | path: '/', 16 | element: , 17 | children: [ 18 | { 19 | path: "/", 20 | element: 21 | }, 22 | { 23 | path: "/mail/:id", 24 | element: 25 | }, 26 | 27 | ] 28 | } 29 | ]) 30 | 31 | function App() { 32 | const { authUser } = useSelector(store => store.app); 33 | const dispatch = useDispatch(); 34 | 35 | useEffect(() => { 36 | auth.onAuthStateChanged((user) => { 37 | if (user) { 38 | dispatch(setAuthUser({ 39 | displayName: user.displayName, 40 | email: user.email, 41 | photoURL: user.photoURL 42 | })); 43 | } 44 | }) 45 | }, []) 46 | 47 | return ( 48 |
49 | { 50 | !authUser ? ( 51 | 52 | ) : ( 53 | <> 54 | 55 | 56 |
57 | 58 |
59 | 60 | ) 61 | } 62 |
63 | ) 64 | } 65 | 66 | export default App 67 | -------------------------------------------------------------------------------- /src/components/Message.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { MdCropSquare } from "react-icons/md"; 3 | import { RiStarLine } from "react-icons/ri"; 4 | import { useDispatch } from 'react-redux'; 5 | import { useNavigate } from 'react-router-dom'; 6 | import { setSelectedMail } from '../redux/appSlice'; 7 | import { motion } from 'framer-motion'; 8 | 9 | const Message = ({ email }) => { 10 | const dispatch = useDispatch(); 11 | const navigate = useNavigate(); 12 | const openMail = () => { 13 | dispatch(setSelectedMail(email)); 14 | navigate(`/mail/${email.id}`); 15 | } 16 | return ( 17 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 |
30 |

{email?.to}

31 |
32 |
33 |
34 |

{`${email.message.length > 130 ? `${email?.message.substring(0, 130)}...` : email.message}`}

35 |
36 |
37 |

{new Date(email?.createdAt?.seconds * 1000).toUTCString()}

38 |
39 |
40 | ) 41 | } 42 | 43 | export default Message -------------------------------------------------------------------------------- /src/components/Sidebar.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { LuPencil } from "react-icons/lu"; 3 | import { IoMdStar } from "react-icons/io"; 4 | import { MdOutlineWatchLater,MdOutlineKeyboardArrowDown,MdOutlineDrafts,MdInbox } from "react-icons/md"; 5 | import { TbSend2 } from "react-icons/tb"; 6 | import { useDispatch } from 'react-redux'; 7 | import { setOpen } from '../redux/appSlice'; 8 | 9 | const sidebarItems = [ 10 | { 11 | icon: , 12 | text: "Inbox" 13 | }, 14 | { 15 | icon: , 16 | text: "Starred" 17 | }, 18 | { 19 | icon: , 20 | text: "Snoozed" 21 | }, 22 | { 23 | icon: , 24 | text: "Sent" 25 | }, 26 | { 27 | icon: , 28 | text: "Drafts" 29 | }, 30 | ] 31 | 32 | const Sidebar = () => { 33 | const [selected, setSelected] = useState(0); 34 | const dispatch = useDispatch(); 35 | return ( 36 |
37 |
38 | 42 |
43 |
44 | { 45 | sidebarItems.map((item, idx) => { 46 | return ( 47 |
setSelected(idx)} key={idx} className={`${selected === idx ? 'bg-[#C2E7FF] text-black' : "hover:bg-gray-200 hover:text-black"} flex pl-6 py-1 rounded-r-full items-center gap-4 my-2 hover:cursor-pointer`}> 48 | {item.icon} 49 |

{item.text}

50 |
51 | ) 52 | }) 53 | } 54 |
55 | 56 | More 57 |
58 |
59 |
60 |
61 | ) 62 | } 63 | 64 | export default Sidebar -------------------------------------------------------------------------------- /src/components/SendEmail.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { RxCross2 } from "react-icons/rx"; 3 | import { useDispatch, useSelector } from 'react-redux'; 4 | import { setOpen } from '../redux/appSlice'; 5 | import { db } from '../firebase'; 6 | import { collection, addDoc, serverTimestamp } from 'firebase/firestore'; 7 | 8 | const SendEmail = () => { 9 | const [formData, setFormData] = useState({ 10 | recipients: "", 11 | subject: "", 12 | message: "" 13 | }) 14 | const { open } = useSelector(store => store.app); 15 | const dispatch = useDispatch(); 16 | 17 | const changeEventHandler = (e) => { 18 | setFormData({ ...formData, [e.target.name]: e.target.value }) 19 | } 20 | 21 | const submitHandler = async (e) => { 22 | e.preventDefault(); 23 | await addDoc(collection(db, "emails"), { 24 | to: formData.recipients, 25 | subject: formData.subject, 26 | message: formData.message, 27 | createdAt: serverTimestamp(), 28 | }) 29 | dispatch(setOpen(false)); 30 | setFormData({ 31 | recipients: "", 32 | subject: "", 33 | message: "" 34 | }); 35 | } 36 | 37 | return ( 38 |
39 |
40 |

New Message

41 |
dispatch(setOpen(false))} className='p-2 rounded-full hover:bg-gray-200 cursor-pointer'> 42 | 43 |
44 |
45 |
46 | 47 | 48 | 49 | 50 |
51 |
52 | ) 53 | } 54 | 55 | export default SendEmail -------------------------------------------------------------------------------- /src/components/Inbox.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { MdCropSquare } from "react-icons/md"; 3 | import { FaCaretDown,FaUserFriends } from "react-icons/fa"; 4 | import { IoMdRefresh, IoMdMore } from "react-icons/io"; 5 | import { MdKeyboardArrowLeft, MdKeyboardArrowRight,MdInbox } from "react-icons/md"; 6 | import { GoTag } from "react-icons/go"; 7 | import Messages from './Messages'; 8 | import { useSelector } from 'react-redux'; 9 | 10 | const mailType = [ 11 | { 12 | icon:, 13 | text:"Primary", 14 | }, 15 | { 16 | icon:, 17 | text:"Promotions", 18 | }, 19 | { 20 | icon:, 21 | text:"Social", 22 | }, 23 | ]; 24 | 25 | const Inbox = () => { 26 | const [mailTypeSelected, setMailTypeSelected] = useState(0); 27 | const {emails} = useSelector(store=>store.app); 28 | 29 | return ( 30 |
31 |
32 |
33 |
34 | 35 | 36 |
37 |
38 | 39 |
40 |
41 | 42 |
43 |
44 |
45 |

1-50 of {emails?.length}

46 | 47 | 48 |
49 |
50 |
51 |
52 | { 53 | mailType.map((item, index) => 54 | 64 | ) 65 | } 66 |
67 | 68 |
69 |
70 | ) 71 | } 72 | 73 | export default Inbox -------------------------------------------------------------------------------- /src/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import { IoSettingsOutline } from "react-icons/io5"; 3 | import { FaRegQuestionCircle } from "react-icons/fa"; 4 | import { PiDotsNineBold } from "react-icons/pi"; 5 | import { IoIosSearch } from "react-icons/io"; 6 | import Avatar from 'react-avatar'; 7 | import { RxHamburgerMenu } from "react-icons/rx"; 8 | import { useDispatch, useSelector } from 'react-redux'; 9 | import { setAuthUser, setSearchText } from '../redux/appSlice'; 10 | import { auth } from '../firebase'; 11 | import { signOut } from 'firebase/auth'; 12 | import { motion, AnimatePresence } from 'framer-motion'; 13 | 14 | 15 | const Navbar = () => { 16 | const [search, setSearch] = useState(""); 17 | const [toggle, setToggle] = useState(false); 18 | const dispatch = useDispatch(); 19 | const { authUser } = useSelector(store => store.app); 20 | 21 | const signOutHandler = () => { 22 | signOut(auth).then(() => { 23 | dispatch(setAuthUser(null)); 24 | }).catch((error) => { 25 | console.log(error); 26 | }); 27 | } 28 | useEffect(() => { 29 | dispatch(setSearchText(search)); 30 | }, [search]); 31 | 32 | 33 | return ( 34 |
35 |
36 |
37 |
38 | 39 |
40 | 41 |

Gmail

42 |
43 |
44 |
45 |
46 | 47 | setSearch(e.target.value)} 51 | placeholder='Seach mail' 52 | className='rounded-full w-full bg-transparent outline-none px-1' 53 | /> 54 |
55 |
56 |
57 |
58 |
59 | 60 |
61 |
62 | 63 |
64 |
65 | 66 |
67 |
68 | setToggle(!toggle)} src={authUser?.photoURL} googleId="118096717852922241760" size="40" round={true} /> 69 | 70 | { 71 | toggle && ( 72 | 78 |

LogOut

79 |
80 | ) 81 | } 82 |
83 |
84 |
85 |
86 |
87 | ) 88 | } 89 | 90 | export default Navbar -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Mail.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useNavigate, useParams } from 'react-router-dom' 3 | import { IoMdMore, IoMdArrowBack } from "react-icons/io"; 4 | import { 5 | MdKeyboardArrowLeft, 6 | MdKeyboardArrowRight, 7 | MdDeleteOutline, 8 | MdOutlineReport, 9 | MdOutlineMarkEmailUnread, 10 | MdOutlineWatchLater, 11 | MdOutlineAddTask, 12 | MdOutlineDriveFileMove, 13 | } from "react-icons/md"; 14 | import { BiArchiveIn } from "react-icons/bi"; 15 | import { useSelector } from 'react-redux'; 16 | import { deleteDoc, doc } from 'firebase/firestore'; 17 | import { db } from '../firebase'; 18 | import { motion } from "framer-motion" 19 | 20 | const Mail = () => { 21 | const params = useParams(); 22 | const navigate = useNavigate(); 23 | const { selectedMail } = useSelector(store => store.app); 24 | 25 | const deleteMailById = async (id) => { 26 | try { 27 | await deleteDoc(doc(db, 'emails', id)); 28 | navigate("/"); 29 | } catch (error) { 30 | console.log(error); 31 | } 32 | } 33 | return ( 34 | 39 |
40 |
41 |
navigate("/")} className='p-2 rounded-full hover:bg-gray-100 cursor-pointer'> 42 | 43 |
44 |
45 | 46 |
47 |
48 | 49 |
50 |
deleteMailById(params.id)} className='p-2 rounded-full hover:bg-gray-100 cursor-pointer'> 51 | 52 |
53 |
54 | 55 |
56 |
57 | 58 |
59 |
60 | 61 |
62 |
63 | 64 |
65 |
66 | 67 |
68 |
69 |
70 | 71 | 72 |
73 |
74 |
75 |
76 |
77 |

{selectedMail?.subject}

78 | inbox 79 |
80 |
81 |

{new Date(selectedMail?.createdAt?.seconds * 1000).toUTCString()}

82 |
83 |
84 |
85 |

{selectedMail?.to}

86 | to me 87 |
88 |
89 |

{selectedMail?.message}

90 |
91 |
92 |
93 | ) 94 | } 95 | 96 | export default Mail --------------------------------------------------------------------------------