diff --git a/components/Email.jsx b/components/Email.jsx
new file mode 100644
index 0000000..021af89
--- /dev/null
+++ b/components/Email.jsx
@@ -0,0 +1,31 @@
+import "./styles/Email.css"
+
+function Email(props) {
+ return (
+
+
+
+
+ props.toggleRead(props.email)}
+ />
+
+
+ props.toggleStar(props.email)}
+ />
+
+
{props.email.sender}
+
{props.email.title}
+
+
+ )
+}
+
+export default Email
\ No newline at end of file
diff --git a/components/EmailInstance.jsx b/components/EmailInstance.jsx
new file mode 100644
index 0000000..fdc8d70
--- /dev/null
+++ b/components/EmailInstance.jsx
@@ -0,0 +1,63 @@
+import "./styles/EmailInstance.css"
+
+function EmailInstance(props) {
+ return (
+
+
+
{props.selectedEmail.title}
+
+
+
+
+ {props.selectedEmail.textContent}
+
+
+

+
+
+
+
+ )
+}
+
+export default EmailInstance
\ No newline at end of file
diff --git a/components/Emails.jsx b/components/Emails.jsx
new file mode 100644
index 0000000..08ed887
--- /dev/null
+++ b/components/Emails.jsx
@@ -0,0 +1,27 @@
+import Email from "./Email"
+import "./styles/Emails.css"
+
+function Emails(props) {
+ return (
+ <>
+
+
+ {props.filteredEmails.map((email, index) => (
+ - {props.setShowEmails(false); props.setShowEmail(true); props.selectedEmail(email)}}
+ >
+
+
+ ))}
+
+
+ >
+)
+}
+
+export default Emails
\ No newline at end of file
diff --git a/components/Header.jsx b/components/Header.jsx
new file mode 100644
index 0000000..ac68de7
--- /dev/null
+++ b/components/Header.jsx
@@ -0,0 +1,22 @@
+import Search from "./Search"
+import './styles/Header.css'
+
+function Header(props) {
+ return (
+
+
+
+
+

+
+
+
+ )
+}
+
+export default Header
\ No newline at end of file
diff --git a/components/HideRead.jsx b/components/HideRead.jsx
new file mode 100644
index 0000000..857a351
--- /dev/null
+++ b/components/HideRead.jsx
@@ -0,0 +1,16 @@
+
+function HideRead(props) {
+ return (
+
+
+ props.setHideRead(e.target.checked)}
+ />
+
+ )
+}
+
+export default HideRead
\ No newline at end of file
diff --git a/components/Inbox.jsx b/components/Inbox.jsx
new file mode 100644
index 0000000..6bfa8cc
--- /dev/null
+++ b/components/Inbox.jsx
@@ -0,0 +1,14 @@
+
+function Inbox(props) {
+ return (
+ {props.setCurrentTab('inbox'); props.setShowEmails(true); props.setShowEmail(false)}}
+ >
+ Inbox
+ {props.unreadEmails.length}
+
+ )
+}
+
+export default Inbox
\ No newline at end of file
diff --git a/components/LeftMenu.jsx b/components/LeftMenu.jsx
new file mode 100644
index 0000000..37c7140
--- /dev/null
+++ b/components/LeftMenu.jsx
@@ -0,0 +1,33 @@
+import Inbox from './Inbox'
+import Starred from './Starred'
+import HideRead from './HideRead'
+import './styles/LeftMenu.css'
+
+function LeftMenu(props) {
+ return (
+
+ )
+}
+
+export default LeftMenu
\ No newline at end of file
diff --git a/components/Search.jsx b/components/Search.jsx
new file mode 100644
index 0000000..a837326
--- /dev/null
+++ b/components/Search.jsx
@@ -0,0 +1,14 @@
+import './styles/Search.css'
+
+function Search(props) {
+ const handleChange = (event) => {
+ props.getSearchEmails(event.target.value)
+ }
+ return (
+
+
+
+ )
+}
+
+export default Search
\ No newline at end of file
diff --git a/components/Starred.jsx b/components/Starred.jsx
new file mode 100644
index 0000000..dcb8415
--- /dev/null
+++ b/components/Starred.jsx
@@ -0,0 +1,14 @@
+
+function Starred(props) {
+ return (
+ {props.setCurrentTab('starred'); props.setShowEmails(true); props.setShowEmail(false)}}
+ >
+ Starred
+ {props.starredEmails.length}
+
+ )
+}
+
+export default Starred
\ No newline at end of file
diff --git a/components/styles/Email.css b/components/styles/Email.css
new file mode 100644
index 0000000..c813ad6
--- /dev/null
+++ b/components/styles/Email.css
@@ -0,0 +1,63 @@
+.email-component {
+ display: grid;
+ grid-template-columns: 30px 30px 150px 1fr;
+ padding: 10px;
+ background-color: white;
+ font-size: 0.9rem;
+ border-bottom: solid 1px #00000020;
+}
+
+.email-component:first-child {
+ border-top: solid 1px #00000020;
+}
+
+
+.email-component:hover {
+ box-shadow: -1px 1px 2px 0 #00000040;
+ z-index: 1;
+}
+
+.email-component.read {
+ background-color: rgb(240, 240, 240);
+}
+
+.email-component.unread {
+ font-weight: 600;
+}
+
+
+
+.email-component .title {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.email-component .star-checkbox {
+ appearance: none;
+ position: relative;
+ display: grid;
+ align-content: center;
+}
+
+.email-component .star-checkbox:focus {
+ outline: none;
+}
+
+.email-component .star-checkbox:checked::before,
+.email-component .star-checkbox::before {
+ content: '';
+ background-size: cover;
+ width: 20px;
+ height: 20px;
+ position: absolute;
+ top: -3px;
+}
+
+.email-component .star-checkbox::before {
+ background-image: url(https://www.gstatic.com/images/icons/material/system/2x/star_border_black_20dp.png);
+}
+
+.email-component .star-checkbox:checked::before {
+ background-image: url(https://www.gstatic.com/images/icons/material/system/2x/star_googyellow500_20dp.png);
+}
\ No newline at end of file
diff --git a/components/styles/EmailInstance.css b/components/styles/EmailInstance.css
new file mode 100644
index 0000000..137f705
--- /dev/null
+++ b/components/styles/EmailInstance.css
@@ -0,0 +1,128 @@
+.email-content {
+ background-color: #ffffff;
+ padding: 24px;
+ border-radius: 8px;
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ color: #333;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+ max-width: 800px;
+ margin: 20px auto;
+ box-sizing: border-box;
+}
+
+.email-content .title h1 {
+ font-size: 1.75rem;
+ margin-bottom: 16px;
+ line-height: 1.2;
+}
+
+.email-content--header {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: flex-start;
+ padding: 16px 0;
+ border-top: 1px solid #eee;
+ border-bottom: 1px solid #eee;
+ gap: 20px;
+}
+
+.avatar {
+ width: 50px;
+ height: 50px;
+ background-color: #ccc;
+ border-radius: 50%;
+ flex-shrink: 0;
+}
+
+.email-info {
+ flex: 1;
+ min-width: 200px;
+}
+
+.sender-info h2 {
+ margin: 0;
+ font-size: 1.1rem;
+}
+
+.sender-info em {
+ display: block;
+ font-style: normal;
+ font-size: 0.9rem;
+ color: #666;
+}
+
+.user-info p {
+ margin: 6px 0 0;
+ font-size: 0.9rem;
+ color: #555;
+}
+
+.date-info {
+ white-space: nowrap;
+ font-size: 0.85rem;
+ color: #888;
+ margin-left: auto;
+ align-self: center;
+}
+
+.email-action-icons ul {
+ display: flex;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ gap: 12px;
+}
+
+.email-action-icons li {
+ cursor: pointer;
+}
+
+.icon {
+ width: 20px;
+ height: 20px;
+}
+
+.email-body {
+ margin-top: 24px;
+ font-size: 0.95rem;
+ line-height: 1.6;
+ color: #444;
+}
+
+.content-text {
+ margin-bottom: 20px;
+ white-space: pre-wrap; /* preserve line breaks */
+}
+
+.content {
+ text-align: center;
+}
+
+.content img {
+ max-width: 100%;
+ height: auto;
+ border-radius: 4px;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
+}
+
+.email-actions {
+ margin-top: 30px;
+ display: flex;
+ gap: 12px;
+}
+
+.email-actions button {
+ padding: 10px 16px;
+ background-color: #0073e6;
+ color: #fff;
+ border: none;
+ border-radius: 4px;
+ font-size: 0.95rem;
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+}
+
+.email-actions button:hover {
+ background-color: #005bb5;
+}
diff --git a/components/styles/Emails.css b/components/styles/Emails.css
new file mode 100644
index 0000000..a8cfa0e
--- /dev/null
+++ b/components/styles/Emails.css
@@ -0,0 +1,9 @@
+.emails > ul {
+ list-style: none;
+ display: grid;
+}
+
+.emails {
+ grid-area: emails;
+ padding: 10px 0;
+}
diff --git a/components/styles/Header.css b/components/styles/Header.css
new file mode 100644
index 0000000..7ba04a6
--- /dev/null
+++ b/components/styles/Header.css
@@ -0,0 +1,22 @@
+.header .left-menu {
+ display: grid;
+ grid-auto-flow: column;
+ align-items: center;
+ justify-content: left;
+}
+
+.header .left-menu .menu-icon {
+ width: 25px;
+ height: 25px;
+ margin: 10px;
+}
+
+.header {
+ grid-area: header;
+
+ display: grid;
+ grid-template-columns: 180px 1fr;
+
+ border-bottom: solid 1px #00000020;
+}
+
diff --git a/components/styles/LeftMenu.css b/components/styles/LeftMenu.css
new file mode 100644
index 0000000..4e8de72
--- /dev/null
+++ b/components/styles/LeftMenu.css
@@ -0,0 +1,29 @@
+.left-menu .menu-icon {
+ width: 25px;
+ height: 25px;
+ margin: 10px;
+}
+
+.left-menu .inbox-list {
+ display: grid;
+ grid-gap: 10px;
+}
+
+.left-menu .inbox-list .item {
+ padding: 5px 10px;
+ display: grid;
+ grid-auto-flow: column;
+ justify-content: space-between;
+ align-items: center;
+
+ border-top-right-radius: 20px;
+ border-bottom-right-radius: 20px;
+}
+
+.left-menu .inbox-list .item.active {
+ background-color: #ff000050;
+}
+
+.left-menu .inbox-list .item.toggle {
+ background-color: transparent;
+}
diff --git a/components/styles/Search.css b/components/styles/Search.css
new file mode 100644
index 0000000..b637d0e
--- /dev/null
+++ b/components/styles/Search.css
@@ -0,0 +1,12 @@
+.search {
+ display: grid;
+ padding: 6px;
+}
+
+.search .search-bar {
+ border: none;
+ border-radius: 5px;
+ background-color: rgb(240, 240, 240);
+ padding: 0 10px;
+ font-size: 1rem;
+}
diff --git a/src/App.jsx b/src/App.jsx
index c902699..0398486 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,8 +1,19 @@
import { useState } from 'react'
+import backArrow from './assets/icons/back-arrow.png'
+import downloadButton from './assets/icons/download-button.png'
+import rateStarButton from './assets/icons/rate-star-button.png'
+import rubbishButton from './assets/icons/rubbish-bin-delete-button.png'
+
+
import initialEmails from './data/emails'
+import Emails from '../components/Emails'
+import Header from '../components/Header'
+import LeftMenu from '../components/LeftMenu'
import './styles/App.css'
+import EmailInstance from '../components/EmailInstance'
+//import emails from './data/emails'
const getReadEmails = emails => emails.filter(email => !email.read)
@@ -12,10 +23,15 @@ function App() {
const [emails, setEmails] = useState(initialEmails)
const [hideRead, setHideRead] = useState(false)
const [currentTab, setCurrentTab] = useState('inbox')
+ const [showEmail, setShowEmail] = useState(false)
+ const [showEmails, setShowEmails] = useState(true)
+ const [selectedEmail, setSelectedEmail] = useState(null)
const unreadEmails = emails.filter(email => !email.read)
const starredEmails = emails.filter(email => email.starred)
+ const getSearchEmails = search => {var searched = emails.filter(email => email.title.toLowerCase().includes(search.toLowerCase())); setEmails(searched); if (search.length === 0) {setEmails(initialEmails)}}
+
const toggleStar = targetEmail => {
const updatedEmails = emails =>
emails.map(email =>
@@ -43,79 +59,34 @@ function App() {
return (
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
+
+
+ {showEmails &&
}
+ {showEmail &&
}
)
}
diff --git a/src/assets/icons/back-arrow.png b/src/assets/icons/back-arrow.png
new file mode 100644
index 0000000..77bf292
Binary files /dev/null and b/src/assets/icons/back-arrow.png differ
diff --git a/src/assets/icons/download-button.png b/src/assets/icons/download-button.png
new file mode 100644
index 0000000..ddb5a11
Binary files /dev/null and b/src/assets/icons/download-button.png differ
diff --git a/src/assets/icons/rate-star-button.png b/src/assets/icons/rate-star-button.png
new file mode 100644
index 0000000..16d6722
Binary files /dev/null and b/src/assets/icons/rate-star-button.png differ
diff --git a/src/assets/icons/rubbish-bin-delete-button.png b/src/assets/icons/rubbish-bin-delete-button.png
new file mode 100644
index 0000000..7090fb1
Binary files /dev/null and b/src/assets/icons/rubbish-bin-delete-button.png differ
diff --git a/src/assets/images/calendly.png b/src/assets/images/calendly.png
new file mode 100644
index 0000000..1ad641b
Binary files /dev/null and b/src/assets/images/calendly.png differ
diff --git a/src/assets/images/notion.jpg b/src/assets/images/notion.jpg
new file mode 100644
index 0000000..e52d467
Binary files /dev/null and b/src/assets/images/notion.jpg differ
diff --git a/src/assets/images/zoomjoin.png b/src/assets/images/zoomjoin.png
new file mode 100644
index 0000000..8983092
Binary files /dev/null and b/src/assets/images/zoomjoin.png differ
diff --git a/src/data/emails.js b/src/data/emails.js
index 68fb1fc..9ef4fee 100644
--- a/src/data/emails.js
+++ b/src/data/emails.js
@@ -1,37 +1,58 @@
+
+import calendlyImage from '../assets/images/calendly.png'
+import notionImage from '../assets/images/notion.jpg'
+import zoomjoinImage from '../assets/images/zoomjoin.png'
+
+
export default [
{
id: 1,
sender: `Zoom`,
title: `Cloud Recording - Nicolas Marcora's Personal Meeting Room is now available`,
starred: false,
- read: true
+ read: true,
+ senderEmail: `zoom-noreply@zoom.com`,
+ textContent: `Your cloud recording is now available. Click the link below to view or share your recording. Please note that it may take several minutes for the recording to become available.`,
+ image: zoomjoinImage
},
{
id: 2,
sender: `Zoom`,
title: `Sean Davison has joined your Personal Meeting Room`,
starred: false,
- read: false
+ read: false,
+ senderEmail: `zoom-noreply@zoom.com`,
+ textContent: `We wanted to let you know that Sean Davison has joined your Personal Meeting Room. You can start your meeting at any time by joining your Personal Meeting Room`,
+ image: zoomjoinImage
},
{
id: 3,
sender: `Notion`,
title: `1 update in Boolean`,
starred: true,
- read: true
+ read: true,
+ senderEmail: `NotionSupport@notion.com`,
+ textContent: `New comment in "Project Brainstorming" @here I think we should also consider adding a section for user feedback. What do you all think?`,
+ image: notionImage
},
{
id: 4,
sender: `The Calendly Team`,
title: `Use more than one calendar?`,
starred: false,
- read: false
+ read: false,
+ senderEmail: `Calendlymarketing@calendlyteam.com`,
+ textContent: `You can connect multiple calendars to your Calendly account. This way, you can manage all your events in one place and avoid double bookings. To add another calendar, go to your account settings and select "Calendar Connections". From there, you can connect additional calendars from Google, Outlook, Office 365, or iCloud.`,
+ image: calendlyImage
},
{
id: 5,
sender: `Patrick`,
title: `Updated invitation: Coding chat with Nico`,
starred: true,
- read: false
+ read: false,
+ senderEmail: `Patrick123@gmail.com`,
+ textContent: `Hey Nico, just wanted to let you know that I've updated the invitation for our coding chat. I've added a Zoom link and changed the time to 3 PM. Let me know if that works for you! Looking forward to catching up and coding together.`,
+ image: zoomjoinImage
}
]
diff --git a/src/styles/App.css b/src/styles/App.css
index da375b1..d1ffb04 100644
--- a/src/styles/App.css
+++ b/src/styles/App.css
@@ -17,130 +17,8 @@
border-bottom: solid 1px #00000020;
}
-.app > .header > .left-menu {
- display: grid;
- grid-auto-flow: column;
- align-items: center;
- justify-content: left;
-}
-
-.app > .header > .left-menu .menu-icon {
- width: 25px;
- height: 25px;
- margin: 10px;
-}
-
-.app > .header > .search {
- display: grid;
- padding: 6px;
-}
-
-.app > .header > .search .search-bar {
- border: none;
- border-radius: 5px;
- background-color: rgb(240, 240, 240);
- padding: 0 10px;
- font-size: 1rem;
-}
-
-.app > .emails {
- grid-area: emails;
- padding: 10px 0;
-}
-
-.app > .emails > ul {
- list-style: none;
- display: grid;
-}
-
.app > .left-menu {
grid-area: left-menu;
padding: 10px;
padding-left: 0;
}
-
-.app > .left-menu .inbox-list {
- display: grid;
- grid-gap: 10px;
-}
-
-.app > .left-menu .inbox-list .item {
- padding: 5px 10px;
- display: grid;
- grid-auto-flow: column;
- justify-content: space-between;
- align-items: center;
-
- border-top-right-radius: 20px;
- border-bottom-right-radius: 20px;
-}
-
-.app > .left-menu .inbox-list .item.active {
- background-color: #ff000050;
-}
-
-.app > .left-menu .inbox-list .item.toggle {
- background-color: transparent;
-}
-
-.email {
- display: grid;
- grid-template-columns: 30px 30px 150px 1fr;
- padding: 10px;
- background-color: white;
- font-size: 0.9rem;
-
- border-bottom: solid 1px #00000020;
-}
-
-.email:first-child {
- border-top: solid 1px #00000020;
-}
-
-.email:hover {
- box-shadow: -1px 1px 2px 0 #00000040;
- z-index: 1;
-}
-
-.email.read {
- background-color: rgb(240, 240, 240);
-}
-
-.email.unread {
- font-weight: 600;
-}
-
-.email .title {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.email .star-checkbox {
- appearance: none;
- position: relative;
- display: grid;
- align-content: center;
-}
-
-.email .star-checkbox:focus {
- outline: none;
-}
-
-.email .star-checkbox:checked::before,
-.email .star-checkbox::before {
- content: '';
- background-size: cover;
- width: 20px;
- height: 20px;
- position: absolute;
- top: -3px;
-}
-
-.email .star-checkbox::before {
- background-image: url(https://www.gstatic.com/images/icons/material/system/2x/star_border_black_20dp.png);
-}
-
-.email .star-checkbox:checked::before {
- background-image: url(https://www.gstatic.com/images/icons/material/system/2x/star_googyellow500_20dp.png);
-}