diff --git a/src/App.jsx b/src/App.jsx index f94c854..3d1aa6e 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -22,8 +22,6 @@ import Achievement from './pages/Achievement'; import Gallery from './pages/Gallery'; import Contact from './pages/Contact'; import Login from './pages/Login'; -import MailConsole from './pages/MailConsole'; -import FirstYearRegistration from './pages/FirstYearRegistration'; function AnimatedRoutes() { const location = useLocation(); @@ -102,9 +100,6 @@ function AnimatedRoutes() { } /> } /> } /> - } /> - } /> - ); diff --git a/src/pages/FirstYearRegistration.jsx b/src/pages/FirstYearRegistration.jsx deleted file mode 100644 index f24c0a0..0000000 --- a/src/pages/FirstYearRegistration.jsx +++ /dev/null @@ -1,391 +0,0 @@ -import { useState } from 'react'; - -const SHEET_URL = 'PASTE_BACKEND_URL_HERE'; - -const DOMAINS = ['Software', 'Electrical', 'Aeronautics', 'Mechanical']; -const BRANCHES = [ - 'Computer Engineering', - 'Information Technology', - 'Electronics & Telecommunication', - 'Mechanical Engineering', - 'Electrical Engineering', - 'Civil Engineering', -]; - -const generateTempRtfId = () => `RTF-${Math.floor(100000 + Math.random() * 900000)}`; - -const emptyForm = { - name: '', - email: '', - branch: '', - yop: '2030', - phone: '', - domain: '', - rtfId: generateTempRtfId(), - tenth: '', - twelfth: '', - cet: '', - jee: '', - diploma: '', -}; - - -const inputClass = - 'w-full bg-black/50 border border-zinc-700/80 rounded-lg px-4 py-2.5 text-white ' + - 'placeholder-gray-500 focus:outline-none focus:border-red-600 transition backdrop-blur-xs'; - -const labelClass = 'block text-sm font-medium text-gray-300 mb-1'; - -export default function FirstYearRegistration() { - const [type, setType] = useState('first'); // 'first' or 'dsy' - const [form, setForm] = useState(emptyForm); - const [step, setStep] = useState('form'); // 'form' -> 'review' -> 'done' - const [loading, setLoading] = useState(false); - const [error, setError] = useState(''); - - const handleType = (t) => { - setType(t); - setForm((prev) => ({ ...prev, yop: t === 'first' ? '2030' : '2029' })); - }; - - const handleChange = (e) => - setForm({ ...form, [e.target.name]: e.target.value }); - - // Step 1: Check details, then show the review screen - const handleReview = (e) => { - e.preventDefault(); - if (!/^[6-9]\d{9}$/.test(form.phone)) { - setError('Enter a valid 10-digit mobile number.'); - return; - } - setError(''); - setStep('review'); - window.scrollTo(0, 0); - }; - - - const handleSubmit = async () => { - setLoading(true); - setError(''); - const payload = { - type, - ...form, - createdAt: Date.now(), - }; - - try { - if (SHEET_URL.includes('PASTE_BACKEND_URL_HERE')) { - console.log('Form data payload:', payload); - } else { - await fetch(SHEET_URL, { - method: 'POST', - mode: 'no-cors', - headers: { 'Content-Type': 'text/plain;charset=utf-8' }, - body: JSON.stringify(payload), - }); - } - setStep('done'); - } catch (err) { - setError('Something went wrong. Please try again.'); - } - setLoading(false); - }; - - const tabClass = (active) => - 'flex-1 py-2.5 rounded-lg font-semibold text-sm transition ' + - (active - ? 'bg-red-600 text-white shadow-lg shadow-red-950/50' - : 'bg-black/40 border border-zinc-700/80 text-gray-300 hover:border-red-600 hover:text-white'); - - - if (step === 'done') { - return ( -
-
-

Registration Successful!

-

- Thank you for registering with The Robo-Tech Forum. -

-
-
- ); - } - - // ---------- Review screen ---------- - if (step === 'review') { - const rows = [ - ['Student Type', type === 'first' ? 'First Year ' : 'DSY '], - ['Name', form.name], - ['Personal Email', form.email], - ['Branch', form.branch], - ['Year of Passing', form.yop], - ['Phone', form.phone], - ['Domain', form.domain], - ['RTF ID (Temp)', form.rtfId], - ['10th Score (%)', `${form.tenth}%`], - ...(type === 'first' - ? [ - ['12th Score (%)', `${form.twelfth}%`], - ['CET Score (%)', `${form.cet}%`], - ['JEE Main Score (%)', form.jee ? `${form.jee}%` : 'N/A (Optional)'], - ] - : [['Diploma Percentage (%)', `${form.diploma}%`]]), - ]; - - return ( -
-
-

- Verify Your Details -

-

- Please check everything carefully before submitting. -

- -
- {rows.map(([label, value]) => ( -
- {label} - {value} -
- ))} -
- - {error &&

{error}

} - -
- - -
-
-
- ); - } - - // ---------- Form screen ---------- - return ( -
-
-
-

- RTF Registration -

-

Select your admission type and enter your details

-
- - {/* Admission Mode Switcher */} -
- - -
- - {/* SECTION 1: COMMON DETAILS */} -
-

- 1. Basic Information -

- -
- - -
- -
-
- - -
- -
- - -
-
- -
-
- - -
- -
- - -
-
- -
-
- - -
- -
- - -
-
- -
- - -
-
- - {/* SECTION 2: CONDITIONAL ACADEMIC DETAILS */} -
-

- 2. {type === 'first' ? 'First Year Academic Scores' : 'DSY Academic Scores'} -

- - {type === 'first' ? ( -
-
- - -
- -
- - -
- -
- - -
-
- ) : ( -
- - -
- )} -
- - {error &&

{error}

} - - -
-
- ); -} \ No newline at end of file diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 461d036..732814e 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -1,5 +1,3 @@ -import { Link } from 'react-router-dom'; - import { motion } from 'framer-motion'; import { pageTransition } from '../lib/animations'; import HeroSection from '../components/sections/HeroSection'; @@ -19,9 +17,6 @@ const MotionMain = motion.main; export default function Home() { return ( - - -
- - - πŸŽ“ First Year Registration is Open. Click Here! - -
-
{/* */} diff --git a/src/pages/MailConsole/MailConsole.css b/src/pages/MailConsole/MailConsole.css deleted file mode 100644 index 553a774..0000000 --- a/src/pages/MailConsole/MailConsole.css +++ /dev/null @@ -1,657 +0,0 @@ -/* ---------------- Page + canvas background ---------------- */ -.mail-console { - position: relative; - min-height: 100vh; - background-color: #000000; - color: #ffffff; - font-family: 'Segoe UI', sans-serif; - overflow: hidden; -} - -.dotgrid-canvas { - position: fixed; - inset: 0; - z-index: 0; - pointer-events: none; -} - -.mail-content { - position: relative; - z-index: 1; - padding: 140px 40px 60px; - max-width: 1400px; - margin: 0 auto; -} - -/* ---------------- Toast ---------------- */ -.mail-toast { - position: fixed; - top: 24px; - right: 24px; - z-index: 50; - background: #0a0a0a; - border: 1px solid #ff2e2e; - color: #ffffff; - padding: 14px 22px; - border-radius: 10px; - font-size: 0.85rem; - font-weight: 600; - box-shadow: 0 0 20px rgba(255, 46, 46, 0.4); - animation: toast-in 0.3s ease; -} - -@keyframes toast-in { - from { opacity: 0; transform: translateY(-10px); } - to { opacity: 1; transform: translateY(0); } -} - -/* ---------------- Page header ---------------- */ -.page-header { - display: flex; - justify-content: space-between; - align-items: baseline; - margin-bottom: 24px; -} - -.page-title { - font-size: 2.1rem; - font-weight: 800; - margin: 0; - letter-spacing: 0.5px; -} - -.page-title-accent { - color: #ff2e2e; -} - -.page-date { - color: #8a8a8a; - font-size: 0.85rem; -} - -/* ---------------- Tabs ---------------- */ -.mail-tabs { - display: flex; - gap: 28px; - border-bottom: 1px solid #232323; - margin-bottom: 24px; -} - -.mail-tab { - background: none; - border: none; - color: #8a8a8a; - font-size: 0.92rem; - font-weight: 600; - padding: 0 0 12px; - cursor: pointer; - border-bottom: 2px solid transparent; - display: flex; - align-items: center; - gap: 8px; -} - -.mail-tab.active { - color: #ffffff; - border-bottom-color: #ff2e2e; -} - -.tab-count { - background: #1a1a1a; - border: 1px solid #333; - border-radius: 999px; - font-size: 0.7rem; - padding: 1px 8px; - color: #cccccc; -} - -/* ---------------- Grid + cards ---------------- */ -.mail-grid { - display: grid; - grid-template-columns: 1fr 1.4fr; - gap: 24px; - align-items: stretch; -} - -.mail-card { - background: rgba(10, 10, 10, 0.92); - border: 1px solid #232323; - border-radius: 14px; - padding: 22px 24px; - backdrop-filter: blur(4px); -} - -.card-eyebrow { - color: #ff2e2e; - font-size: 0.7rem; - font-weight: 800; - text-transform: uppercase; - letter-spacing: 1.2px; - margin-bottom: 6px; -} - -.card-title-row { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 18px; -} - -.card-title { - font-size: 1.15rem; - font-weight: 700; - margin: 0; -} - -.muted-small { - color: #8a8a8a; - font-size: 0.78rem; -} - -.pill-badge { - background: #1a0a0a; - border: 1px solid #ff2e2e; - color: #ff2e2e; - font-size: 0.72rem; - font-weight: 700; - padding: 4px 12px; - border-radius: 999px; -} - -/* ---------------- Labels + inputs ---------------- */ -.field-label { - display: block; - color: #8a8a8a; - font-size: 0.7rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.8px; - margin-bottom: 6px; -} - -.field-label-row { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 14px; -} - -.field-label-row .field-label { - margin-bottom: 6px; -} - -.char-counter { - font-size: 0.7rem; - color: #666666; -} - -.mail-select, -.mail-input, -.mail-textarea { - width: 100%; - background: #000000; - border: 1px solid #2d2d2d; - border-radius: 8px; - padding: 11px 14px; - color: #ffffff; - margin-bottom: 14px; - font-size: 0.9rem; - outline: none; - transition: border-color 0.2s; - box-sizing: border-box; - font-family: inherit; -} - -.mail-select:focus, -.mail-input:focus, -.mail-textarea:focus { - border-color: #ff2e2e; -} - -.mail-textarea { - min-height: 130px; - resize: vertical; - margin-bottom: 0; -} - -/* ---------------- Select all / clear ---------------- */ -.mail-select-row { - display: flex; - justify-content: space-between; - margin-bottom: 10px; -} - -.mail-link-btn { - background: none; - border: none; - color: #ff2e2e; - cursor: pointer; - font-size: 0.82rem; - font-weight: 700; - padding: 0; -} - -.mail-link-muted { - color: #8a8a8a; -} - -.mail-link-btn:hover { - text-decoration: underline; -} - -/* ---------------- Recipient list ---------------- */ -.mail-recipient-list { - max-height: 380px; - overflow-y: auto; - border-top: 1px solid #232323; - padding-top: 6px; - margin-right: -8px; - padding-right: 8px; -} - -.mail-recipient-list::-webkit-scrollbar { - width: 6px; -} -.mail-recipient-list::-webkit-scrollbar-thumb { - background: rgba(255, 46, 46, 0.35); - border-radius: 10px; -} - -.recipient-row { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 6px; - cursor: pointer; - border-radius: 8px; - border-bottom: 1px solid #161616; -} - -.recipient-row:last-child { - border-bottom: none; -} - -.recipient-row:hover { - background: #131313; -} - -.recipient-row input { - accent-color: #ff2e2e; - width: 16px; - height: 16px; - flex-shrink: 0; -} - -.avatar { - width: 34px; - height: 34px; - border-radius: 50%; - background: #1a1a1a; - border: 1px solid #333333; - display: flex; - align-items: center; - justify-content: center; - font-size: 0.75rem; - font-weight: 700; - color: #ffffff; - flex-shrink: 0; -} - -.recipient-info { - display: flex; - flex-direction: column; - min-width: 0; -} - -.recipient-name { - font-size: 0.9rem; - color: #ffffff; - font-weight: 600; -} - -.recipient-email { - font-size: 0.75rem; - color: #7a8a94; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.recipient-group { - font-size: 0.7rem; - color: #ff6b6b; - font-weight: 600; - margin-top: 1px; -} - -.empty-state { - color: #7a7a7a; - font-size: 0.85rem; - text-align: center; - padding: 30px 0; -} - -/* ---------------- To chips ---------------- */ -.to-box { - min-height: 46px; - background: #000000; - border: 1px solid #2d2d2d; - border-radius: 8px; - padding: 10px 12px; - margin-bottom: 4px; - display: flex; - flex-wrap: wrap; - gap: 8px; - align-items: center; -} - -.to-placeholder { - color: #666666; - font-size: 0.85rem; -} - -.to-chip { - background: #1a0a0a; - border: 1px solid #ff2e2e; - color: #ffffff; - font-size: 0.78rem; - font-weight: 600; - padding: 4px 8px 4px 12px; - border-radius: 999px; - display: flex; - align-items: center; - gap: 6px; -} - -.to-chip-remove { - background: none; - border: none; - color: #ff6b6b; - cursor: pointer; - font-size: 1rem; - line-height: 1; - padding: 0; -} - -/* ---------------- Compose footer (no dead space) ---------------- */ -.compose-footer { - margin-top: 16px; - padding-top: 16px; - border-top: 1px solid #1e1e1e; - display: flex; - align-items: center; - gap: 14px; - flex-wrap: wrap; -} - -.mail-attach-btn { - background: #161616; - border: 1px solid #2d2d2d; - border-radius: 999px; - padding: 9px 16px; - cursor: pointer; - font-size: 0.82rem; - color: #ffffff; - font-weight: 600; -} - -.mail-attach-btn:hover { - border-color: #ff2e2e; -} - -.mail-file-name { - font-size: 0.78rem; - color: #a0a0a0; - display: flex; - align-items: center; - gap: 6px; -} - -.file-remove { - background: none; - border: none; - color: #ff6b6b; - cursor: pointer; - font-size: 0.9rem; -} - -.footer-actions { - margin-left: auto; - display: flex; - gap: 10px; -} - -.btn-ghost, -.btn-outline, -.btn-primary { - border-radius: 999px; - font-size: 0.82rem; - font-weight: 700; - padding: 10px 20px; - cursor: pointer; - font-family: inherit; -} - -.btn-ghost { - background: none; - border: 1px solid #2d2d2d; - color: #a0a0a0; -} - -.btn-ghost:hover { - border-color: #555; - color: #ffffff; -} - -.btn-outline { - background: #161616; - border: 1px solid #2d2d2d; - color: #ffffff; -} - -.btn-outline:hover { - border-color: #ffffff; -} - -.btn-primary { - background: #ff2e2e; - border: none; - color: #ffffff; - box-shadow: 0 0 15px rgba(255, 46, 46, 0.35); - transition: background 0.2s, transform 0.15s; -} - -.btn-primary:disabled { - opacity: 0.4; - cursor: not-allowed; - box-shadow: none; -} - -.btn-primary:hover:not(:disabled) { - background: #ff0000; - transform: translateY(-1px); -} - -/* ---------------- History tab ---------------- */ -.history-card { - min-height: 340px; -} - -.history-empty { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; - padding: 60px 20px; - color: #8a8a8a; -} - -.history-empty-icon { - width: 56px; - height: 56px; - border-radius: 14px; - background: #161616; - border: 1px solid #2d2d2d; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.4rem; - color: #ff2e2e; - margin-bottom: 18px; -} - -.history-empty h3 { - color: #ffffff; - font-size: 1rem; - margin: 0 0 8px; -} - -.history-empty p { - font-size: 0.82rem; - max-width: 340px; - line-height: 1.5; - margin: 0; -} - -.history-list { - display: flex; - flex-direction: column; -} - -.history-row { - display: flex; - justify-content: space-between; - align-items: center; - padding: 14px 4px; - border-bottom: 1px solid #1a1a1a; -} - -.history-row:hover { - background: #101010; -} - -.history-row-main { - display: flex; - flex-direction: column; -} - -.history-subject { - color: #ffffff; - font-weight: 600; - font-size: 0.9rem; -} - -.history-recipients { - color: #7a8a94; - font-size: 0.78rem; - margin-top: 2px; -} - -.history-row-side { - display: flex; - align-items: center; - gap: 14px; -} - -.history-time { - color: #666666; - font-size: 0.75rem; -} - -.status-pill { - background: #06210f; - border: 1px solid #22c55e; - color: #22c55e; - font-size: 0.7rem; - font-weight: 700; - text-transform: uppercase; - padding: 3px 12px; - border-radius: 999px; -} - -/* ---------------- Stats bar (bottom) ---------------- */ -.stats-bar { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 16px; - margin-top: 40px; -} - -.stat-card { - background: rgba(10, 10, 10, 0.92); - border: 1px solid #232323; - border-radius: 12px; - padding: 16px 18px; - display: flex; - align-items: center; - gap: 14px; -} - -.stat-card-red { - border-color: #ff2e2e; - box-shadow: 0 0 12px rgba(255, 46, 46, 0.25); -} - -.stat-icon { - width: 38px; - height: 38px; - border-radius: 10px; - background: #161616; - border: 1px solid #2d2d2d; - display: flex; - align-items: center; - justify-content: center; - color: #ff2e2e; - font-size: 1rem; - flex-shrink: 0; -} - -.stat-label { - font-size: 0.68rem; - color: #8a8a8a; - text-transform: uppercase; - letter-spacing: 0.6px; -} - -.stat-value { - font-size: 1.3rem; - font-weight: 800; - color: #ffffff; -} - -/* ---------------- Floating scroll-to-top ---------------- */ -.scroll-top-btn { - position: fixed; - bottom: 28px; - right: 28px; - width: 48px; - height: 48px; - border-radius: 50%; - background: #0a0a0a; - border: 1px solid #ff2e2e; - color: #ff2e2e; - font-size: 1rem; - cursor: pointer; - z-index: 40; - box-shadow: 0 0 18px rgba(255, 46, 46, 0.45); - transition: transform 0.2s, box-shadow 0.2s; -} - -.scroll-top-btn:hover { - transform: translateY(-3px); - box-shadow: 0 0 26px rgba(255, 46, 46, 0.65); -} - -/* ---------------- Responsive ---------------- */ -@media (max-width: 900px) { - .mail-grid { - grid-template-columns: 1fr; - } - .stats-bar { - grid-template-columns: repeat(2, 1fr); - } - .mail-content { - padding: 120px 20px 40px; - } -} \ No newline at end of file diff --git a/src/pages/MailConsole/index.jsx b/src/pages/MailConsole/index.jsx index c6edbba..e69de29 100644 --- a/src/pages/MailConsole/index.jsx +++ b/src/pages/MailConsole/index.jsx @@ -1,467 +0,0 @@ -import { useState, useEffect, useRef } from 'react'; -import './MailConsole.css'; - -const RECIPIENTS = [ - { id: 1, name: 'Anushka Garpawar', email: 'aditi.rao@gmail.com', group: 'AIML' }, - { id: 2, name: 'Radhika Roy', email: 'karan.mehta@gmail.com', group: 'IOT' }, - { id: 3, name: 'sanika Kulkarni', email: 'neha.kulkarni@gmail.com', group: 'Advanced Mechanism' }, - { id: 4, name: 'Rohan Deshmukh', email: 'rohan.iyer@gmail.com', group: 'Robotics' }, - { id: 5, name: 'divya Shah', email: 'priya.shah@gmail.com', group: 'IOT' }, - { id: 6, name: 'Arjun Patil', email: 'arjun.patil@gmail.com', group: 'Advanced Mechanism' }, - { id: 7, name: 'mukta Joshi', email: 'sneha.joshi@gmail.com', group: 'Robotics' }, - { id: 8, name: 'gaurav Desai', email: 'vikram.desai@gmail.com', group: 'IOT' }, -]; - -const SUBJECT_LIMIT = 120; -const MESSAGE_LIMIT = 2000; - -/* ---------------- Interactive canvas dot-grid, glows red near cursor ---------------- */ -function DotGridBackground() { - const canvasRef = useRef(null); - const mouseRef = useRef({ x: -9999, y: -9999 }); - - useEffect(() => { - const canvas = canvasRef.current; - const ctx = canvas.getContext('2d'); - let animationId; - let width, height; - const spacing = 26; - const maxDist = 170; - - function resize() { - width = canvas.width = window.innerWidth; - height = canvas.height = window.innerHeight; - } - resize(); - window.addEventListener('resize', resize); - - function handleMove(e) { - mouseRef.current = { x: e.clientX, y: e.clientY }; - } - window.addEventListener('mousemove', handleMove); - - function handleLeave() { - mouseRef.current = { x: -9999, y: -9999 }; - } - window.addEventListener('mouseout', handleLeave); - - function draw() { - ctx.clearRect(0, 0, width, height); - const { x: mx, y: my } = mouseRef.current; - - for (let y = 0; y <= height; y += spacing) { - for (let x = 0; x <= width; x += spacing) { - const dx = x - mx; - const dy = y - my; - const dist = Math.sqrt(dx * dx + dy * dy); - - let radius = 1.1; - let color = 'rgba(255,255,255,0.06)'; - let glow = 0; - - if (dist < maxDist) { - const t = 1 - dist / maxDist; - radius = 1.1 + t * 2.2; - const g = Math.round(255 - t * 215); - const b = Math.round(255 - t * 212); - color = `rgba(255,${g},${b},${0.12 + t * 0.85})`; - glow = t * 12; - } - - ctx.beginPath(); - ctx.fillStyle = color; - ctx.shadowColor = 'rgba(255,46,46,0.85)'; - ctx.shadowBlur = glow; - ctx.arc(x, y, radius, 0, Math.PI * 2); - ctx.fill(); - } - } - animationId = requestAnimationFrame(draw); - } - draw(); - - return () => { - window.removeEventListener('resize', resize); - window.removeEventListener('mousemove', handleMove); - window.removeEventListener('mouseout', handleLeave); - cancelAnimationFrame(animationId); - }; - }, []); - - return ; -} - -function initials(name) { - return name - .split(' ') - .map((w) => w[0]) - .join('') - .slice(0, 2) - .toUpperCase(); -} - -function timeAgo(ts) { - const diff = Math.floor((Date.now() - ts) / 1000); - if (diff < 60) return 'just now'; - if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; - if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; - return `${Math.floor(diff / 86400)}d ago`; -} - -function MailConsole() { - const [activeTab, setActiveTab] = useState('compose'); // 'compose' | 'history' - const [search, setSearch] = useState(''); - const [domain, setDomain] = useState('all'); - const [selected, setSelected] = useState([]); - const [subject, setSubject] = useState(''); - const [message, setMessage] = useState(''); - const [attachment, setAttachment] = useState(null); - const [sending, setSending] = useState(false); - const [toast, setToast] = useState(null); - const [drafts, setDrafts] = useState([]); - const [history, setHistory] = useState([]); - - const domains = ['all', ...new Set(RECIPIENTS.map((r) => r.email.split('@')[1]))]; - - const filtered = RECIPIENTS.filter((r) => { - const matchesSearch = - r.name.toLowerCase().includes(search.toLowerCase()) || - r.email.toLowerCase().includes(search.toLowerCase()); - const matchesDomain = domain === 'all' || r.email.endsWith(`@${domain}`); - return matchesSearch && matchesDomain; - }); - - const selectedRecipients = RECIPIENTS.filter((r) => selected.includes(r.id)); - - const toggleOne = (id) => { - setSelected((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id])); - }; - const removeChip = (id) => setSelected((prev) => prev.filter((x) => x !== id)); - const selectAll = () => setSelected(filtered.map((r) => r.id)); - const clearAll = () => setSelected([]); - - const showToast = (text) => { - setToast(text); - setTimeout(() => setToast(null), 2800); - }; - - const resetComposeFields = () => { - setSubject(''); - setMessage(''); - setAttachment(null); - }; - - const handleClear = () => resetComposeFields(); - - const handleSaveDraft = () => { - if (!subject.trim() && !message.trim()) return; - setDrafts((prev) => [ - { id: Date.now(), subject: subject || '(no subject)', recipients: selected.length }, - ...prev, - ]); - showToast('Draft saved'); - }; - - const handleSend = (e) => { - e.preventDefault(); - if (selected.length === 0 || !subject.trim()) return; - setSending(true); - - setTimeout(() => { - const entry = { - id: Date.now(), - recipients: selectedRecipients.map((r) => r.name), - subject, - status: 'sent', - ts: Date.now(), - }; - setHistory((prev) => [entry, ...prev]); - setSending(false); - showToast(`Sent to ${selected.length} recipient${selected.length > 1 ? 's' : ''}`); - resetComposeFields(); - setSelected([]); - }, 700); - }; - - const scrollToTop = () => window.scrollTo({ top: 0, behavior: 'smooth' }); - - const totalMembers = RECIPIENTS.length; - const membersEmailed = new Set(history.flatMap((h) => h.recipients)).size; - const draftsCount = drafts.length; - - return ( -
- - - {toast &&
{toast}
} - -
- {/* Page header */} -
-

- Email Console -

- - {new Date().toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - year: 'numeric', - })} - -
- - {/* Tabs */} -
- - -
- - {/* ---------------- COMPOSE TAB ---------------- */} - {activeTab === 'compose' && ( -
- {/* Recipients panel */} -
-
Recipients
-
-

Choose recipients

- {selected.length} selected -
- - - - - setSearch(e.target.value)} - /> - -
- - -
- -
- {filtered.map((r) => ( - - ))} - {filtered.length === 0 && ( -

No recipients found.

- )} -
-
- - {/* Compose panel */} -
-
Message
-
-

Compose email

- {selected.length} recipients -
- - -
- {selectedRecipients.length === 0 ? ( - Select recipients from the left - ) : ( - selectedRecipients.map((r) => ( - - {r.name} - - - )) - )} -
- -
- - - {subject.length}/{SUBJECT_LIMIT} - -
- setSubject(e.target.value)} - /> - -
- - - {message.length}/{MESSAGE_LIMIT} - -
-