925 lines
38 KiB
HTML
925 lines
38 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>MyGlobalMail - Inbox (3 new)</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
/* === CSS Variables System === */
|
|
:root {
|
|
/* Light Mode */
|
|
--primary: #0078d4;
|
|
--primary-light: #e0eeff;
|
|
--accent: #258cfb;
|
|
--bg-body: #f0f0f0;
|
|
--bg-nav: #f3f2f1;
|
|
--bg-white: #ffffff;
|
|
--bg-hover: #f5f5f5;
|
|
--bg-selected: #c7e0f4;
|
|
--text-main: #201f1e;
|
|
--text-secondary: #605e5c;
|
|
--text-placeholder: #a19f9d;
|
|
--border: #edebe9;
|
|
--separator: #e1dfdd;
|
|
--shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
|
|
--danger: #d93025;
|
|
--success: #1e8e3e;
|
|
--warning: #f9ab00;
|
|
}
|
|
|
|
body[data-theme='dark'] {
|
|
--primary: #4da6ff;
|
|
--primary-light: #1b2a3a;
|
|
--accent: #6db1ff;
|
|
--bg-body: #121212;
|
|
--bg-nav: #1f1f1f;
|
|
--bg-white: #272727;
|
|
--bg-hover: #333333;
|
|
--bg-selected: #2a3d50;
|
|
--text-main: #ffffff;
|
|
--text-secondary: #b3b3b3;
|
|
--text-placeholder: #777777;
|
|
--border: #383838;
|
|
--separator: #444444;
|
|
--shadow-sm: 0 1px 3px rgba(0,0,0,0.5);
|
|
}
|
|
|
|
/* === Reset & Base === */
|
|
* { box-sizing: border-box; }
|
|
body {
|
|
font-family: 'Roboto', 'Segoe UI', -apple-system, sans-serif;
|
|
margin: 0;
|
|
height: 100vh;
|
|
background-color: var(--bg-body);
|
|
color: var(--text-main);
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
transition: background-color 0.3s, color 0.3s;
|
|
}
|
|
|
|
button { font-family: inherit; cursor: pointer; border: none; outline: none; background: transparent; }
|
|
a { text-decoration: none; color: inherit; }
|
|
ul { list-style: none; padding: 0; margin: 0; }
|
|
|
|
/* === Layout Grid === */
|
|
.app-container {
|
|
display: grid;
|
|
grid-template-rows: 48px 1fr; /* Header | Main */
|
|
height: 100%;
|
|
}
|
|
|
|
.main-layout {
|
|
display: grid;
|
|
grid-template-columns: 240px 350px 1fr; /* Nav | List | Reading Pane */
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* === Header === */
|
|
.app-header {
|
|
background-color: var(--primary);
|
|
color: white;
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0 16px;
|
|
justify-content: space-between;
|
|
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
|
|
z-index: 10;
|
|
}
|
|
|
|
.logo-area { display: flex; align-items: center; gap: 12px; font-weight: 500; font-size: 18px; }
|
|
.logo-icon { font-size: 20px; }
|
|
|
|
.search-bar {
|
|
background: rgba(255,255,255,0.15);
|
|
border-radius: 4px;
|
|
padding: 0 12px;
|
|
height: 32px;
|
|
display: flex;
|
|
align-items: center;
|
|
width: 400px;
|
|
transition: background 0.2s;
|
|
}
|
|
.search-bar:focus-within { background: white; color: black; }
|
|
.search-bar:focus-within input { color: black; }
|
|
.search-bar:focus-within input::placeholder { color: #666; }
|
|
.search-bar input {
|
|
background: transparent; border: none; color: white; width: 100%; margin-left: 8px; font-size: 14px;
|
|
}
|
|
.search-bar input::placeholder { color: rgba(255,255,255,0.7); }
|
|
|
|
.user-actions { display: flex; align-items: center; gap: 15px; }
|
|
.theme-toggle { cursor: pointer; padding: 5px; border-radius: 50%; display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; }
|
|
.theme-toggle:hover { background: rgba(255,255,255,0.1); }
|
|
.user-avatar { width: 32px; height: 32px; border-radius: 50%; background: #005a9e; border: 2px solid white; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: bold; }
|
|
|
|
/* === Sidebar (Navigation) === */
|
|
.sidebar {
|
|
background-color: var(--bg-nav);
|
|
border-right: 1px solid var(--border);
|
|
padding-top: 20px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.compose-btn-wrapper { padding: 0 16px 20px; }
|
|
.btn-compose {
|
|
background: var(--primary); color: white; width: 100%; border-radius: 4px; height: 40px; font-weight: 500; font-size: 15px;
|
|
box-shadow: 0 1px 2px rgba(0,0,0,0.2); transition: background 0.2s;
|
|
}
|
|
.btn-compose:hover { background: #0063b1; }
|
|
|
|
.nav-item {
|
|
padding: 10px 24px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
}
|
|
.nav-item:hover { background-color: var(--bg-hover); color: var(--text-main); }
|
|
.nav-item.active { background-color: var(--bg-selected); color: var(--text-main); font-weight: 500; border-left: 3px solid var(--primary); padding-left: 21px; }
|
|
|
|
.nav-icon { margin-right: 12px; font-size: 16px; width: 20px; text-align: center; }
|
|
.unread-badge { font-weight: bold; color: var(--primary); font-size: 12px; }
|
|
|
|
.sidebar-section-title {
|
|
padding: 20px 24px 10px; font-size: 12px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px;
|
|
}
|
|
|
|
/* === Mail List === */
|
|
.mail-list-panel {
|
|
background-color: var(--bg-white);
|
|
border-right: 1px solid var(--border);
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.toolbar {
|
|
height: 48px;
|
|
border-bottom: 1px solid var(--border);
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0 16px;
|
|
gap: 15px;
|
|
flex-shrink: 0;
|
|
background: var(--bg-white);
|
|
}
|
|
.tool-icon { color: var(--text-secondary); font-size: 16px; cursor: pointer; padding: 6px; border-radius: 2px; }
|
|
.tool-icon:hover { background: var(--bg-hover); color: var(--text-main); }
|
|
|
|
.mail-items-container { overflow-y: auto; flex: 1; }
|
|
|
|
.mail-item {
|
|
padding: 12px 16px;
|
|
border-bottom: 1px solid var(--border);
|
|
cursor: pointer;
|
|
position: relative;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
}
|
|
.mail-left {
|
|
margin-right: 12px;
|
|
padding-top: 2px;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.mail-checkbox { margin: 0; cursor: pointer; }
|
|
.mail-content-block { flex: 1; min-width: 0; }
|
|
|
|
.mail-item:hover { background-color: var(--bg-hover); }
|
|
.mail-item.selected { background-color: var(--bg-selected); border-left: 3px solid var(--primary); padding-left: 13px; }
|
|
.mail-item.unread .mail-subject { font-weight: bold; }
|
|
.mail-item.unread .mail-sender { font-weight: bold; color: var(--text-main); }
|
|
.mail-item.unread::after {
|
|
content: ''; position: absolute; top: 18px; left: 4px; width: 4px; height: 4px; background: var(--primary); border-radius: 50%;
|
|
}
|
|
|
|
.mail-header-row { display: flex; justify-content: space-between; margin-bottom: 4px; }
|
|
.mail-sender { font-size: 14px; color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; }
|
|
.mail-date { font-size: 12px; color: var(--text-secondary); flex-shrink: 0; }
|
|
.mail-subject { font-size: 14px; color: var(--text-secondary); margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.mail-preview { font-size: 13px; color: var(--text-placeholder); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
|
|
/* === Reading Pane === */
|
|
.reading-pane {
|
|
background-color: var(--bg-white);
|
|
padding: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
|
|
.reading-empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 100%;
|
|
color: var(--text-placeholder);
|
|
}
|
|
.empty-icon { font-size: 64px; margin-bottom: 20px; opacity: 0.5; }
|
|
|
|
.email-detail-view { display: flex; flex-direction: column; height: 100%; }
|
|
.email-header { padding: 20px 30px; border-bottom: 1px solid var(--border); }
|
|
.email-subject-lg { font-size: 20px; font-weight: 500; margin-bottom: 16px; color: var(--text-main); }
|
|
.email-meta { display: flex; justify-content: space-between; align-items: flex-start; }
|
|
.sender-info-lg { display: flex; gap: 12px; }
|
|
.sender-avi { width: 40px; height: 40px; border-radius: 50%; background: #e0eeff; color: #0078d4; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 16px; }
|
|
.sender-text div:first-child { font-weight: 500; font-size: 14px; color: var(--text-main); }
|
|
.sender-text div:last-child { font-size: 12px; color: var(--text-secondary); }
|
|
.email-actions { display: flex; gap: 10px; }
|
|
|
|
.email-body { padding: 30px; overflow-y: auto; flex: 1; font-size: 15px; line-height: 1.6; color: var(--text-main); }
|
|
|
|
/* === Compose Modal === */
|
|
.modal-overlay {
|
|
position: fixed; bottom: 0; right: 80px; width: 500px; height: 600px;
|
|
background: var(--bg-white); border-radius: 8px 8px 0 0;
|
|
box-shadow: 0 -4px 16px rgba(0,0,0,0.15); border: 1px solid var(--border);
|
|
display: none; flex-direction: column; z-index: 100;
|
|
}
|
|
.modal-header {
|
|
background: var(--primary); color: white; padding: 10px 15px; border-radius: 8px 8px 0 0;
|
|
display: flex; justify-content: space-between; font-weight: 500;
|
|
}
|
|
.modal-body { flex: 1; padding: 15px; display: flex; flex-direction: column; gap: 15px; }
|
|
.input-group input, .input-group textarea {
|
|
width: 100%; border: none; border-bottom: 1px solid var(--border); padding: 8px 0;
|
|
font-family: inherit; background: transparent; color: var(--text-main); resize: none;
|
|
}
|
|
.input-group input:focus, .input-group textarea:focus { border-bottom-color: var(--primary); }
|
|
.modal-footer { padding: 15px; display: flex; justify-content: space-between; border-top: 1px solid var(--border); }
|
|
|
|
/* === Utilities === */
|
|
.tag { font-size: 11px; padding: 2px 6px; border-radius: 3px; margin-right: 6px; display: inline-block; }
|
|
.tag-work { background: #e3f2fd; color: #1565c0; }
|
|
.tag-finance { background: #e8f5e9; color: #2e7d32; }
|
|
.tag-urgent { background: #ffebee; color: #c62828; }
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="app-container">
|
|
<!-- Header -->
|
|
<header class="app-header">
|
|
<div class="logo-area">
|
|
<span class="logo-icon">📧</span> MyGlobalMail
|
|
</div>
|
|
<div class="search-bar">
|
|
<span>🔍</span>
|
|
<input type="text" id="searchInput" placeholder="Search mail..." onkeyup="filterEmails()">
|
|
</div>
|
|
<div class="user-actions">
|
|
<div class="theme-toggle" onclick="toggleTheme()" title="Toggle Dark/Light Theme">🌓</div>
|
|
<div title="Notifications">🔔</div>
|
|
<div title="Settings">⚙️</div>
|
|
<div class="user-avatar">JD</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Layout -->
|
|
<div class="main-layout">
|
|
|
|
<!-- Sidebar -->
|
|
<aside class="sidebar">
|
|
<div class="compose-btn-wrapper">
|
|
<button class="btn-compose" onclick="openCompose()">+ New Message</button>
|
|
</div>
|
|
|
|
<ul id="nav-folder-list">
|
|
<li class="nav-item active" onclick="selectFolder('inbox')">
|
|
<div style="display:flex; align-items:center;">
|
|
<span class="nav-icon">📥</span> Inbox
|
|
</div>
|
|
<span class="unread-badge" id="badge-inbox">3</span>
|
|
</li>
|
|
<li class="nav-item" onclick="selectFolder('sent')">
|
|
<div style="display:flex; align-items:center;">
|
|
<span class="nav-icon">📤</span> Sent Items
|
|
</div>
|
|
</li>
|
|
<li class="nav-item" onclick="selectFolder('drafts')">
|
|
<div style="display:flex; align-items:center;">
|
|
<span class="nav-icon">📝</span> Drafts
|
|
</div>
|
|
<span class="unread-badge">1</span>
|
|
</li>
|
|
<li class="nav-item" onclick="selectFolder('junk')">
|
|
<div style="display:flex; align-items:center;">
|
|
<span class="nav-icon">🚫</span> Junk Mail
|
|
</div>
|
|
</li>
|
|
<li class="nav-item" onclick="selectFolder('trash')">
|
|
<div style="display:flex; align-items:center;">
|
|
<span class="nav-icon">🗑️</span> Trash
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="sidebar-section-title">Labels</div>
|
|
<ul>
|
|
<li class="nav-item">
|
|
<span style="width:10px; height:10px; border-radius:50%; background:#1565c0; margin-right:12px;"></span> Work
|
|
</li>
|
|
<li class="nav-item">
|
|
<span style="width:10px; height:10px; border-radius:50%; background:#2e7d32; margin-right:12px;"></span> Finance
|
|
</li>
|
|
<li class="nav-item">
|
|
<span style="width:10px; height:10px; border-radius:50%; background:#c62828; margin-right:12px;"></span> Urgent
|
|
</li>
|
|
<li class="nav-item">
|
|
<span style="width:10px; height:10px; border-radius:50%; background:#f9ab00; margin-right:12px;"></span> Travel
|
|
</li>
|
|
</ul>
|
|
</aside>
|
|
|
|
<!-- Mail List Column -->
|
|
<main class="mail-list-panel">
|
|
<div class="toolbar">
|
|
<div class="tool-icon" title="Select All"><input type="checkbox" style="margin:0;" id="select-all-checkbox" onclick="toggleSelectAll()"></div>
|
|
<div class="tool-icon" title="Refresh" onclick="refreshMail()">🔄</div>
|
|
<div class="tool-icon" title="Mark Read" onclick="markSelectedAsRead()">✉️</div>
|
|
<div class="tool-icon" title="Delete" onclick="deleteSelected()">🗑️</div>
|
|
<div style="flex:1"></div>
|
|
<div style="font-size:12px; color:var(--text-secondary);">Sort by: <b>Date</b></div>
|
|
</div>
|
|
<div class="mail-items-container" id="mail-list-container">
|
|
<!-- Emails will be injected here by JS -->
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Reading Pane Column -->
|
|
<section class="reading-pane" id="reading-pane">
|
|
<div class="reading-empty-state">
|
|
<div class="empty-icon">📧</div>
|
|
<h3>Select an item to read</h3>
|
|
<p>Click on an email on the left to view details.</p>
|
|
</div>
|
|
</section>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Compose Modal -->
|
|
<div class="modal-overlay" id="compose-modal">
|
|
<div class="modal-header">
|
|
<span>New Message</span>
|
|
<span style="cursor:pointer;" onclick="closeCompose()">✕</span>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="input-group">
|
|
<input type="text" placeholder="To" id="compose-to">
|
|
</div>
|
|
<div class="input-group">
|
|
<input type="text" placeholder="Subject" id="compose-subject">
|
|
</div>
|
|
<div class="input-group" style="flex:1;">
|
|
<textarea style="height:100%;" placeholder="Type your message..." id="compose-body"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn-compose" style="width:100px;" onclick="sendEmail()">Send</button>
|
|
<button style="color:var(--text-secondary);" onclick="closeCompose()">Discard</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// -------------------------------------------------------------------------
|
|
// Data Model
|
|
// -------------------------------------------------------------------------
|
|
const EMAILS = [
|
|
{
|
|
id: 1,
|
|
folder: 'inbox',
|
|
sender: 'HR Department',
|
|
senderEmail: 'hr@company.com',
|
|
subject: 'Action Required: 2026 Benefits Enrollment Open',
|
|
preview: 'The open enrollment period for 2026 benefits is now open. Please login to the portal to make your selections...',
|
|
body: `<p>Dear Employee,</p><p>We are pleased to announce that <strong>Open Enrollment for 2026 Benefits</strong> is now live!</p><p>You have until <strong>Jan 31st</strong> to make changes to your medical, dental, and vision plans.</p><ul><li>Review new premiums in the attached PDF.</li><li>Update beneficiaries if needed.</li></ul><p>Regards,<br>HR Team</p>`,
|
|
date: '10:42 AM',
|
|
unread: true,
|
|
checked: false,
|
|
tag: 'work',
|
|
avatar: 'HR'
|
|
},
|
|
{
|
|
id: 2,
|
|
folder: 'inbox',
|
|
sender: 'Boss_Steve',
|
|
senderEmail: 'steve.jobs@apple-mock.com',
|
|
subject: 'URGENT: Project Beta Update Meeting',
|
|
preview: 'Can we reschedule our 2pm sync to 3pm? Something came up with the client.',
|
|
body: `<p>Hi,</p><p>Can we push the Beta review to <strong>3:00 PM</strong> today? The client just sent over some last-minute requirements we need to discuss first.</p><p>Thanks,<br>Steve</p>`,
|
|
date: '09:15 AM',
|
|
unread: true,
|
|
checked: false,
|
|
tag: 'urgent',
|
|
avatar: 'BS'
|
|
},
|
|
{
|
|
id: 3,
|
|
folder: 'inbox',
|
|
sender: 'Netflix',
|
|
senderEmail: 'info@netflix.com',
|
|
subject: 'New sign-in to your account',
|
|
preview: 'We noticed a new sign-in to your Netflix account from a new device in Brazil.',
|
|
body: `<p>Hi John,</p><p>We detected a new sign-in to your account.</p><p><strong>Device:</strong> Smart TV<br><strong>Location:</strong> São Paulo, Brazil</p><p>If this was you, you can ignore this email. If not, please change your password immediately.</p>`,
|
|
date: 'Yesterday',
|
|
unread: false,
|
|
checked: false,
|
|
tag: null,
|
|
avatar: 'N'
|
|
},
|
|
{
|
|
id: 4,
|
|
folder: 'inbox',
|
|
sender: 'Amazon Orders',
|
|
senderEmail: 'order-update@amazon.com',
|
|
subject: 'Your package has been delivered!',
|
|
preview: 'Your package containing "Wireless Headphones..." was delivered at front door.',
|
|
body: `<p>Hello,</p><p>Your package has arrived!</p><p><strong>Tracking ID:</strong> TBA99881223<br><strong>Location:</strong> Front Porch</p><p><button style="background:#f9ab00; padding:10px; border-radius:4px; border:none; color:black; font-weight:bold;">View Order</button></p>`,
|
|
date: 'Yesterday',
|
|
unread: true,
|
|
checked: false,
|
|
tag: 'finance',
|
|
avatar: 'A'
|
|
},
|
|
{
|
|
id: 5,
|
|
folder: 'inbox',
|
|
sender: 'Mom',
|
|
senderEmail: 'mom@family.com',
|
|
subject: 'Dinner on Sunday?',
|
|
preview: 'Are you free this Sunday for roast chicken? Dad wants to know.',
|
|
body: `<p>Hi honey,</p><p>Are you coming over this Sunday? I'm making your favorite roast chicken. Let me know so I can buy enough potatoes.</p><p>Love,<br>Mom</p>`,
|
|
date: 'Jan 15',
|
|
unread: false,
|
|
checked: false,
|
|
tag: null,
|
|
avatar: 'M'
|
|
},
|
|
// New Emails added per user request
|
|
{
|
|
id: 6,
|
|
folder: 'inbox',
|
|
sender: 'IT Support',
|
|
senderEmail: 'support@company.com',
|
|
subject: 'Planned Maintenance: This Saturday',
|
|
preview: 'System maintenance scheduled for Sat 10:00 PM - 2:00 AM. Services unavailable.',
|
|
body: `<p>Attention Team,</p><p>We will be performing upgrading server maintenance this Saturday.</p><p><strong>Impact:</strong> Email and File Servers will be down for approx 4 hours.</p>`,
|
|
date: 'Jan 14',
|
|
unread: false,
|
|
checked: false,
|
|
tag: 'work',
|
|
avatar: 'IT'
|
|
},
|
|
{
|
|
id: 7,
|
|
folder: 'inbox',
|
|
sender: 'LinkedIn',
|
|
senderEmail: 'notifications@linkedin.com',
|
|
subject: 'You appeared in 15 searches this week',
|
|
preview: 'See who is looking at your profile. 3 recruiters viewed your profile.',
|
|
body: `<p>Hi John,</p><p>Your profile is getting noticed.</p><p>People from <strong>Google</strong> and <strong>Meta</strong> viewed your profile.</p>`,
|
|
date: 'Jan 13',
|
|
unread: false,
|
|
checked: false,
|
|
tag: null,
|
|
avatar: 'Li'
|
|
},
|
|
{
|
|
id: 8,
|
|
folder: 'inbox',
|
|
sender: 'Spotify',
|
|
senderEmail: 'no-reply@spotify.com',
|
|
subject: 'Your 2025 Wrapped is here! 🎵',
|
|
preview: 'See your top songs, artists, and podcasts for the year.',
|
|
body: `<p>It's that time of year!</p><h1>Your 2025 Wrapped</h1><p>Top Genre: Lo-Fi Beats<br>Top Artist: Unknown</p>`,
|
|
date: 'Jan 10',
|
|
unread: false,
|
|
checked: false,
|
|
tag: null,
|
|
avatar: 'S'
|
|
},
|
|
{
|
|
id: 9,
|
|
folder: 'trash',
|
|
sender: 'Spam Bot',
|
|
senderEmail: 'winner@lottery.com',
|
|
subject: 'YOU WON $1,000,000!!',
|
|
preview: 'Click here to claim your prize immediately before it expires.',
|
|
body: `<p>CLICK HERE NOW!!!</p>`,
|
|
date: 'Jan 01',
|
|
unread: true,
|
|
checked: false,
|
|
tag: null,
|
|
avatar: 'SB'
|
|
},
|
|
// Folder: Sent
|
|
{
|
|
id: 101,
|
|
folder: 'sent',
|
|
sender: 'Me',
|
|
senderEmail: 'john.doe@globalmail.com',
|
|
subject: 'Re: Project Beta Update Meeting',
|
|
preview: 'Sure, 3pm works for me. See you then.',
|
|
body: `<p>Hi Steve,</p><p>3 PM is fine. I'll update the calendar invite.</p><p>Best,<br>John</p>`,
|
|
date: '09:20 AM',
|
|
unread: false,
|
|
checked: false,
|
|
tag: null,
|
|
avatar: 'JD'
|
|
},
|
|
{
|
|
id: 102,
|
|
folder: 'sent',
|
|
sender: 'Me',
|
|
senderEmail: 'john.doe@globalmail.com',
|
|
subject: 'Draft Proposal V2',
|
|
preview: 'Attached is the revised proposal. Let me know what you think.',
|
|
body: `<p>Hi All,</p><p>Please find attached.</p>`,
|
|
date: 'Yesterday',
|
|
unread: false,
|
|
checked: false,
|
|
tag: 'work',
|
|
avatar: 'JD'
|
|
}
|
|
];
|
|
|
|
let currentFolder = 'inbox';
|
|
let selectedEmailId = null;
|
|
|
|
// -------------------------------------------------------------------------
|
|
// View Logic
|
|
// -------------------------------------------------------------------------
|
|
function renderMailList() {
|
|
const container = document.getElementById('mail-list-container');
|
|
container.innerHTML = '';
|
|
|
|
// Filter emails
|
|
const filtered = EMAILS.filter(e => e.folder === currentFolder);
|
|
|
|
// Update Select All Checkbox State
|
|
const allChecked = filtered.length > 0 && filtered.every(e => e.checked);
|
|
const selectAllCb = document.getElementById('select-all-checkbox');
|
|
if(selectAllCb) {
|
|
selectAllCb.checked = allChecked;
|
|
// Handle indeterminate state if needed, but simple boolean is fine here
|
|
}
|
|
|
|
if (filtered.length === 0) {
|
|
container.innerHTML = `<div style="padding:40px; text-align:center; color:var(--text-secondary);">No mail in ${currentFolder}</div>`;
|
|
return;
|
|
}
|
|
|
|
filtered.forEach(email => {
|
|
const el = document.createElement('div');
|
|
el.className = `mail-item ${email.unread ? 'unread' : ''} ${selectedEmailId === email.id ? 'selected' : ''}`;
|
|
el.onclick = () => openEmail(email.id);
|
|
|
|
// Generate Tags HTML
|
|
let tagHtml = '';
|
|
if (email.tag === 'work') tagHtml = '<span class="tag tag-work">Work</span>';
|
|
if (email.tag === 'finance') tagHtml = '<span class="tag tag-finance">Order</span>';
|
|
if (email.tag === 'urgent') tagHtml = '<span class="tag tag-urgent">Urgent</span>';
|
|
|
|
// Insert Checkbox in HTML
|
|
el.innerHTML = `
|
|
<div class="mail-left" onclick="event.stopPropagation()">
|
|
<input type="checkbox" class="mail-checkbox" ${email.checked ? 'checked' : ''} onchange="toggleEmailCheck(${email.id})">
|
|
</div>
|
|
<div class="mail-content-block">
|
|
<div class="mail-header-row">
|
|
<span class="mail-sender">${email.sender}</span>
|
|
<span class="mail-date">${email.date}</span>
|
|
</div>
|
|
<div class="mail-subject">${tagHtml}${email.subject}</div>
|
|
<div class="mail-preview">${email.preview}</div>
|
|
</div>
|
|
`;
|
|
container.appendChild(el);
|
|
});
|
|
|
|
// Update Folder Badge
|
|
const unreadCount = EMAILS.filter(e => e.folder === 'inbox' && e.unread).length;
|
|
const badge = document.getElementById('badge-inbox');
|
|
if (badge) badge.innerText = unreadCount > 0 ? unreadCount : '';
|
|
}
|
|
|
|
function toggleEmailCheck(id) {
|
|
const email = EMAILS.find(e => e.id === id);
|
|
if(email) {
|
|
email.checked = !email.checked;
|
|
// Check "Select All" status
|
|
const filtered = EMAILS.filter(e => e.folder === currentFolder);
|
|
const allChecked = filtered.length > 0 && filtered.every(e => e.checked);
|
|
document.getElementById('select-all-checkbox').checked = allChecked;
|
|
}
|
|
}
|
|
|
|
function toggleSelectAll() {
|
|
const selectAllCb = document.getElementById('select-all-checkbox');
|
|
const isChecked = selectAllCb.checked;
|
|
|
|
EMAILS.forEach(e => {
|
|
if(e.folder === currentFolder) {
|
|
e.checked = isChecked;
|
|
}
|
|
});
|
|
renderMailList();
|
|
}
|
|
|
|
function deleteSelected() {
|
|
const selected = EMAILS.filter(e => e.folder === currentFolder && e.checked);
|
|
if (selected.length === 0) {
|
|
// Also handle single selection if no checks
|
|
if(selectedEmailId) {
|
|
deleteEmail(selectedEmailId);
|
|
return;
|
|
}
|
|
showToast('No emails selected', '#d93025');
|
|
return;
|
|
}
|
|
|
|
let count = 0;
|
|
selected.forEach(email => {
|
|
// Logic similar to deleteEmail but bulk
|
|
if (email.folder !== 'trash') {
|
|
email.folder = 'trash';
|
|
email.checked = false; // reset check
|
|
count++;
|
|
} else {
|
|
// Permanently delete
|
|
const idx = EMAILS.findIndex(x => x.id === email.id);
|
|
if(idx > -1) {
|
|
EMAILS.splice(idx, 1);
|
|
count++;
|
|
}
|
|
}
|
|
});
|
|
|
|
showToast(`${count} item(s) deleted`);
|
|
selectedEmailId = null;
|
|
document.getElementById('reading-pane').innerHTML = `<div class="reading-empty-state"><div class="empty-icon">🗑️</div><h3>Moved to Trash</h3></div>`;
|
|
renderMailList();
|
|
}
|
|
|
|
function markSelectedAsRead() {
|
|
const selected = EMAILS.filter(e => e.folder === currentFolder && e.checked);
|
|
if (selected.length === 0) {
|
|
showToast('No emails selected', '#f9ab00');
|
|
return;
|
|
}
|
|
|
|
selected.forEach(e => {
|
|
e.unread = false;
|
|
e.checked = false; // Optional: uncheck after action
|
|
});
|
|
|
|
showToast('Marked as Read', 'var(--primary)');
|
|
renderMailList();
|
|
}
|
|
|
|
function openEmail(id) {
|
|
selectedEmailId = id;
|
|
const email = EMAILS.find(e => e.id === id);
|
|
|
|
// Mark as read
|
|
if (email.unread) {
|
|
email.unread = false;
|
|
}
|
|
|
|
renderMailList(); // Re-render to update selection style and unread status
|
|
|
|
// Render Reading Pane
|
|
const pane = document.getElementById('reading-pane');
|
|
pane.innerHTML = `
|
|
<div class="email-detail-view">
|
|
<div class="email-header">
|
|
<div class="email-subject-lg">${email.subject}</div>
|
|
<div class="email-meta">
|
|
<div class="sender-info-lg">
|
|
<div class="sender-avi">${email.avatar}</div>
|
|
<div class="sender-text">
|
|
<div>${email.sender} <${email.senderEmail}></div>
|
|
<div>To: Me</div>
|
|
</div>
|
|
</div>
|
|
<div class="email-actions">
|
|
<button class="tool-icon" title="Reply" onclick="replyEmail(${email.id})">↩️</button>
|
|
<button class="tool-icon" title="Forward" onclick="forwardEmail(${email.id})">➡️</button>
|
|
<button class="tool-icon" title="Delete" onclick="deleteEmail(${email.id})">🗑️</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="email-body">
|
|
${email.body}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
function selectFolder(folderName) {
|
|
currentFolder = folderName;
|
|
selectedEmailId = null;
|
|
|
|
// Update Nav UI
|
|
document.querySelectorAll('.nav-item').forEach(el => el.classList.remove('active'));
|
|
// Find the element that called this function - simplistic approach for demo
|
|
// (In real React/Vue this is state bound)
|
|
const clicked = event.currentTarget;
|
|
if(clicked) clicked.classList.add('active');
|
|
|
|
// Clear reading pane
|
|
document.getElementById('reading-pane').innerHTML = `
|
|
<div class="reading-empty-state">
|
|
<div class="empty-icon">📂</div>
|
|
<h3>${folderName.charAt(0).toUpperCase() + folderName.slice(1)}</h3>
|
|
<p>Select an item to view.</p>
|
|
</div>
|
|
`;
|
|
|
|
renderMailList();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Actions
|
|
// -------------------------------------------------------------------------
|
|
function deleteEmail(id) {
|
|
const index = EMAILS.findIndex(e => e.id === id);
|
|
if (index > -1) {
|
|
// Move to trash if not already there, else permanent delete
|
|
if (EMAILS[index].folder !== 'trash') {
|
|
EMAILS[index].folder = 'trash';
|
|
showToast('Moved to Trash');
|
|
} else {
|
|
EMAILS.splice(index, 1);
|
|
showToast('Deleted permanently');
|
|
}
|
|
selectedEmailId = null;
|
|
document.getElementById('reading-pane').innerHTML = '<div class="reading-empty-state">Item deleted</div>';
|
|
renderMailList();
|
|
}
|
|
}
|
|
|
|
function replyEmail(id) {
|
|
const email = EMAILS.find(e => e.id === id);
|
|
if (!email) return;
|
|
document.getElementById('compose-modal').style.display = 'flex';
|
|
document.getElementById('compose-to').value = email.senderEmail;
|
|
document.getElementById('compose-subject').value = 'Re: ' + email.subject;
|
|
document.getElementById('compose-body').focus();
|
|
}
|
|
|
|
function forwardEmail(id) {
|
|
const email = EMAILS.find(e => e.id === id);
|
|
if (!email) return;
|
|
document.getElementById('compose-modal').style.display = 'flex';
|
|
document.getElementById('compose-to').value = '';
|
|
document.getElementById('compose-subject').value = 'Fwd: ' + email.subject;
|
|
document.getElementById('compose-body').value = `\n\n\n------ Original Message ------\nFrom: ${email.sender} <${email.senderEmail}>\nSubject: ${email.subject}\n\n`;
|
|
document.getElementById('compose-body').focus();
|
|
}
|
|
|
|
function refreshMail() {
|
|
const btn = document.querySelector('.tool-icon[title="Refresh"]');
|
|
btn.style.transform = "rotate(360deg)";
|
|
btn.style.transition = "transform 0.5s";
|
|
|
|
setTimeout(() => {
|
|
btn.style.transform = "none";
|
|
// Simulate new mail
|
|
if (Math.random() > 0.5) {
|
|
const newMail = {
|
|
id: Date.now(),
|
|
folder: 'inbox',
|
|
sender: 'News Bot',
|
|
senderEmail: 'news@daily.com',
|
|
subject: 'Breaking News: Tech market rally',
|
|
preview: 'Global markets are seeing a significant uptrend today...',
|
|
body: '<p>Markets are up 2% today.</p>',
|
|
date: 'Just Now',
|
|
unread: true,
|
|
checked: false,
|
|
tag: null,
|
|
avatar: 'NB'
|
|
};
|
|
EMAILS.unshift(newMail);
|
|
showToast('1 New Email Arrived');
|
|
renderMailList();
|
|
} else {
|
|
showToast('All up to date');
|
|
}
|
|
}, 600);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Compose Logic
|
|
// -------------------------------------------------------------------------
|
|
function openCompose() {
|
|
document.getElementById('compose-modal').style.display = 'flex';
|
|
document.getElementById('compose-to').focus();
|
|
}
|
|
|
|
function closeCompose() {
|
|
document.getElementById('compose-modal').style.display = 'none';
|
|
// reset fields
|
|
document.getElementById('compose-to').value = '';
|
|
document.getElementById('compose-subject').value = '';
|
|
document.getElementById('compose-body').value = '';
|
|
}
|
|
|
|
function sendEmail() {
|
|
const to = document.getElementById('compose-to').value;
|
|
const subj = document.getElementById('compose-subject').value;
|
|
|
|
if (!to) { showToast('Please add a recipient', '#d93025'); return; }
|
|
|
|
showToast('Sending...', 'var(--primary)');
|
|
setTimeout(() => {
|
|
showToast('Message sent!', 'var(--success)');
|
|
closeCompose();
|
|
// Add to Sent
|
|
EMAILS.unshift({
|
|
id: Date.now(),
|
|
folder: 'sent',
|
|
sender: 'Me',
|
|
senderEmail: 'john.doe@globalmail.com',
|
|
subject: subj || '(No Subject)',
|
|
preview: 'You sent a message...',
|
|
body: `<p>${document.getElementById('compose-body').value}</p>`,
|
|
date: 'Just Now',
|
|
unread: false,
|
|
tag: null,
|
|
avatar: 'JD'
|
|
});
|
|
}, 1000);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Theme & Utilities
|
|
// -------------------------------------------------------------------------
|
|
function toggleTheme() {
|
|
if (document.body.getAttribute('data-theme') === 'dark') {
|
|
document.body.removeAttribute('data-theme');
|
|
} else {
|
|
document.body.setAttribute('data-theme', 'dark');
|
|
}
|
|
}
|
|
|
|
function showToast(text, bg) {
|
|
const toast = document.createElement('div');
|
|
toast.innerText = text;
|
|
toast.style.cssText = `
|
|
position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
|
|
background: ${bg || '#323130'}; color: white; padding: 10px 20px; border-radius: 4px;
|
|
font-size: 14px; z-index: 200; box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
|
`;
|
|
document.body.appendChild(toast);
|
|
setTimeout(() => toast.remove(), 2500);
|
|
}
|
|
|
|
function filterEmails() {
|
|
const term = document.getElementById('searchInput').value.toLowerCase();
|
|
if(!term) {
|
|
renderMailList();
|
|
return;
|
|
}
|
|
|
|
// Simple client-side search
|
|
const filtered = EMAILS.filter(e =>
|
|
e.subject.toLowerCase().includes(term) ||
|
|
e.sender.toLowerCase().includes(term) ||
|
|
e.body.toLowerCase().includes(term)
|
|
);
|
|
|
|
const container = document.getElementById('mail-list-container');
|
|
container.innerHTML = '';
|
|
filtered.forEach(email => {
|
|
// Reuse render logic ideally, but duplication here for brevity
|
|
const el = document.createElement('div');
|
|
el.className = `mail-item ${email.unread ? 'unread' : ''}`;
|
|
el.onclick = () => openEmail(email.id);
|
|
el.innerHTML = `
|
|
<div class="mail-header-row"><span class="mail-sender">${email.sender}</span></div>
|
|
<div class="mail-subject">${email.subject}</div>
|
|
<div class="mail-preview">Found in search</div>
|
|
`;
|
|
container.appendChild(el);
|
|
});
|
|
}
|
|
|
|
// Init
|
|
renderMailList();
|
|
console.log('App v6.0 Initialized');
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html> |