basic test
This commit is contained in:
929
009/9-all.html
Normal file
929
009/9-all.html
Normal file
@@ -0,0 +1,929 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>GlobalMail - Inbox (3 unread)</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: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, 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> GlobalMail (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 Mode">🌓</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 Mail</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
|
||||
</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
|
||||
</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">Tags</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 as 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: <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 email to read</h3>
|
||||
<p>Click on an email from the list 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: 'Human Resources',
|
||||
senderEmail: 'hr@company.com',
|
||||
subject: 'Action Required: 2026 Benefits Enrollment Open',
|
||||
preview: '2026 Benefits Open Enrollment is now live. Please log in to the portal to make your selections...',
|
||||
body: `<p>Dear Employee,</p><p>We are pleased to announce that <strong>2026 Benefits Enrollment</strong> is now live!</p><p>You have until <strong>January 31st</strong> to make changes to your medical, dental, and vision plans.</p><ul><li>Please review the new premiums in the attached PDF.</li><li>Update your beneficiaries if necessary.</li></ul><p>Best regards,<br>The 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 move the 2pm sync to 3pm? Client just had a fire drill.',
|
||||
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 login to your account',
|
||||
preview: 'We noticed a new login to your Netflix account from a new device in Brazil.',
|
||||
body: `<p>Hi John,</p><p>We detected a new login to your account.</p><p><strong>Device:</strong> Smart TV<br><strong>Location:</strong> Sao Paulo, Brazil</p><p>If this was you, please 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 to your front porch.',
|
||||
body: `<p>Hello,</p><p>Your package has arrived!</p><p><strong>Tracking #:</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: 'Sunday Dinner?',
|
||||
preview: 'Are you free for roast chicken this Sunday? Dad wants to know.',
|
||||
body: `<p>Honey,</p><p>Are you coming over this Sunday? I am 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: 'Scheduled Maintenance: This Saturday',
|
||||
preview: 'System maintenance scheduled for Sat 10:00 PM - 2:00 AM. Services will be unavailable.',
|
||||
body: `<p>Attention Team,</p><p>We will be performing server upgrades 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: 'Check out 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 now 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 will 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 your thoughts.',
|
||||
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) {
|
||||
const folderNameCN = { 'inbox': 'Inbox', 'sent': 'Sent', 'drafts': 'Drafts', 'junk': 'Junk', 'trash': 'Trash' }[currentFolder] || currentFolder;
|
||||
container.innerHTML = `<div style="padding:40px; text-align:center; color:var(--text-secondary);">${folderNameCN} is empty</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">Finance</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(`Deleted ${count} emails`);
|
||||
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');
|
||||
|
||||
const folderMap = { 'inbox': 'Inbox', 'sent': 'Sent', 'drafts': 'Drafts', 'junk': 'Junk', 'trash': 'Trash' };
|
||||
const displayName = folderMap[folderName] || folderName;
|
||||
|
||||
// Clear reading pane
|
||||
document.getElementById('reading-pane').innerHTML = `
|
||||
<div class="reading-empty-state">
|
||||
<div class="empty-icon">📂</div>
|
||||
<h3>${displayName}</h3>
|
||||
<p>Select an email 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('Permanently Deleted');
|
||||
}
|
||||
selectedEmailId = null;
|
||||
document.getElementById('reading-pane').innerHTML = '<div class="reading-empty-state">Email 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: Tech Market Rebounds',
|
||||
preview: 'Global markets are showing significant upward trends 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 Received');
|
||||
renderMailList();
|
||||
} else {
|
||||
showToast('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('Email 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">Search Result</div>
|
||||
`;
|
||||
container.appendChild(el);
|
||||
});
|
||||
}
|
||||
|
||||
// Init
|
||||
renderMailList();
|
||||
console.log('App v6.0 Initialized');
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user