const { useState, useMemo, useEffect, useRef } = React; /* ============================================================ ICONS — minimal stroke set, no external deps ============================================================ */ const I = { dot: (p) => , search: (p) => , bell: (p) => , mail: (p) => , cog: (p) => , home: (p) => , cal: (p) => , book: (p) => , list: (p) => , cash: (p) => , user: (p) => , mega: (p) => , file: (p) => , edit: (p) => , arrow: (p) => , ext: (p) => , chev: (p) => , pin: (p) => , check: (p) => , out: (p) => , shield: (p) => , help: (p) => , star: (p) => , menu: (p) => , x: (p) => , }; /* ============================================================ DATA — fully anonymized, generic "School" ============================================================ */ const me = { name: 'Name Surname', album: '00000', programs: ['Computer Science, BEng', 'sem. 6'], email: 'name.surname@school.edu', initials: 'NS', }; const upcoming = [ { when: 'Day after tomorrow · Thursday, May 28', blocks: [ { time: '12:15–14:00', code: 'STAT-DC', name: 'Mathematical Statistics', type: 'lab', room: 'B-204', online: 'Teams', teacher: 'Dr. K. Miller' }, ], }, { when: 'Friday · May 29', blocks: [ { time: '08:00–09:30', code: 'ELEC-DB', name: 'Electronics Laboratory', type: 'lab', room: 'C-117', online: null, teacher: 'J. Sawyer, MSc' }, { time: '11:45–13:15', code: 'PY-2', name: 'Python — Data Mining', type: 'lab', room: 'A-301', online: 'Teams', teacher: 'Dr. M. Collins' }, ], }, { when: 'Thursday · June 11', blocks: [ { time: '10:15–12:00', code: 'STAT-DC', name: 'Mathematical Statistics', type: 'lecture', room: 'Aula A', online: 'Teams', teacher: 'Prof. P. Lawson' }, { time: '12:00–13:30', code: 'STAT-DC', name: 'Mathematical Statistics · 2nd midterm (25/26)', type: 'midterm', room: '—', online: 'Inspera', teacher: 'Dr. K. Miller' }, { time: '12:15–14:00', code: 'STAT-DC', name: 'Mathematical Statistics', type: 'lab', room: 'B-204', online: 'Teams', teacher: 'Dr. K. Miller' }, ], }, { when: 'Tuesday · June 16', blocks: [ { time: '09:00–10:30', code: 'OR-DC', name: 'Operations Research — final test', type: 'midterm', room: 'D-22', online: null, teacher: 'Dr. B. Jenkins' }, ], }, ]; const announcements = [ { course: 'Programming Lab 2 — Python (Data Mining)', subject: 'Running late', body: 'Good morning, my sincere apologies — I will be about 15 minutes late today.', when: 'today · 08:17', author: 'Dr. M. Collins', unread: true }, { course: 'Programming Lab 2 — Python (Data Mining)', subject: 'Project — summary as requested', body: 'Dear students, for the Python 2 — Data Mining course you are required to prepare a final project as a notebook, e.g. Jupyter Notebook or Google Colab. (…)', when: 'May 24 · 12:22', author: 'Dr. M. Collins', unread: true }, { course: 'Programming Lab 2 — Python (Data Mining)', subject: 'Action needed — project groups', body: 'Please fill in the group assignment table by May 25. Four people are still missing.', when: 'May 19 · 10:15', author: 'Dr. M. Collins', unread: false }, { course: 'Operations Research & Logistics', subject: 'Materials for lecture 11', body: 'I have uploaded the presentation and two exercise files to the documents section.', when: 'May 18 · 09:01', author: 'Dr. B. Jenkins', unread: false }, ]; const fileGroups = [ { course: 'Applied Electronics Laboratory', items: [ { name: 'Distance-sensor-HC-SR04-1.ino', when: 'today · 17:23', kind: 'ino' }, { name: 'Motion-sensor-test-PIR-HC-SR501.ino', when: 'today · 17:23', kind: 'ino' }, { name: 'ELEC-DB-group-Lab-12-surname-name-id.docx', when: 'today · 17:23', kind: 'docx' }, { name: 'ELEC-DB-Lab-12.pptx', when: 'today · 17:23', kind: 'pptx' }, { name: 'Programmable-LEDs-Task-1.ino', when: 'May 18 · 14:53', kind: 'ino' }, ], }, { course: 'Programming Lab 2 — Python (Data Mining)', items: [ { name: 'Python_data_mining_LAB_12_2.pptx', when: 'today · 10:22', kind: 'pptx' }, { name: 'Python_data_mining_LAB_12_1.pdf', when: 'today · 10:21', kind: 'pdf' }, { name: 'Python_data_mining_LAB_11.pdf', when: 'today · 09:20', kind: 'pdf' }, { name: '3classificationFinal.py', when: 'May 19 · 09:46', kind: 'py' }, { name: '2classificationTest.py', when: 'May 19 · 09:46', kind: 'py' }, ], }, { course: 'Operations Research & Logistics', items: [ { name: 'Lecture 11.pdf', when: 'yesterday · 10:56', kind: 'pdf' }, { name: 'Lecture 11.pdf', when: 'yesterday · 10:55', kind: 'pdf' }, ], }, ]; const activity = [ { browser: 'Chrome 148', host: '178.42.0.10 · home-isp.example.net', when: 'May 26 · 21:10', status: 'ok' }, { browser: 'Chrome 148', host: 'lab392.school.edu', when: 'May 26 · 13:34', status: 'ok' }, { browser: 'Chrome 148', host: 'lab392.school.edu', when: 'May 26 · 09:45', status: 'ok' }, { browser: 'Chrome 143 · Android', host: 'mobile-5453.carrier.example.net', when: 'May 26 · 09:28', status: 'ok' }, { browser: 'Chrome 148', host: 'lab392.school.edu', when: 'May 25 · 14:25', status: 'ok' }, { browser: 'Chrome 148', host: '178.42.0.10 · home-isp.example.net', when: 'May 25 · 11:43', status: 'ok' }, { browser: 'Chrome 148', host: '178.42.0.10 · home-isp.example.net', when: 'May 25 · 11:43', status: 'bad' }, { browser: 'Chrome 136 · Android', host: '178.42.0.10 · home-isp.example.net', when: 'May 25 · 10:05', status: 'ok' }, ]; const events = [ { date: 'Jun 13', time: '10:00', title: 'School Open Day — main campus', tag: 'soon' }, { date: 'Jun 10', time: '18:00', title: 'Print Design in the 21st Century — online webinar', tag: 'webinar' }, { date: 'Jun 03', time: '17:30', title: 'AI Student Club meetup', tag: 'student club' }, ]; const news = [ { kind: 'Accreditation', title: 'Graphic Design program receives a positive accreditation review' }, { kind: 'Partnership', title: 'School joins a creative-campus program — a new era of digital education' }, { kind: 'Timetable', title: 'Timetable search for other groups is now open — check their schedules' }, ]; const navMain = [ { id: 'dashboard', label: 'Dashboard', icon: 'home', badge: null }, { id: 'timetable', label: 'Timetable', icon: 'cal', badge: '3' }, { id: 'grades', label: 'Grades', icon: 'list', badge: null }, { id: 'courses', label: 'Courses', icon: 'book', badge: null }, { id: 'finance', label: 'Finance', icon: 'cash', badge: null }, ]; const navAccount = [ { id: 'profile', label: 'Profile', icon: 'user' }, { id: 'announcements', label: 'Announcements', icon: 'mega', badge: '2' }, { id: 'documents', label: 'Documents', icon: 'file' }, { id: 'enrollment', label: 'Enrollment', icon: 'edit' }, ]; /* ============================================================ PRIMITIVES ============================================================ */ const Pill = ({ children, tone='neutral', size='sm', ...rest }) => { const map = { neutral: { bg:'#F2E7D9', fg:'#5A4A42', bd:'#E8DAC6' }, accent: { bg:'var(--accent-soft)', fg:'var(--accent-ink)', bd:'transparent' }, warn: { bg:'var(--warn-soft)', fg:'var(--warn)', bd:'transparent' }, info: { bg:'var(--info-soft)', fg:'var(--info)', bd:'transparent' }, ink: { bg:'var(--ink)', fg:'#F6EDE4', bd:'transparent' }, ghost: { bg:'transparent', fg:'var(--ink-2)', bd:'var(--line)' }, }; const t = map[tone] || map.neutral; const sz = size==='xs' ? { padding:'1px 7px', fontSize:10.5, letterSpacing:'.04em' } : { padding:'2px 9px', fontSize:11.5, letterSpacing:'.02em' }; return {children}; }; const Card = ({ children, style, pad=20, className, ...rest }) => (
{children}
); const SectionLabel = ({ children, action, icon }) => (
{icon && {icon}}

{children}

{action}
); const Avatar = ({ initials='NS', size=36 }) => (
{initials}
); const btnPrimary = { display:'inline-flex', alignItems:'center', gap:7, padding:'9px 13px', borderRadius:10, background:'var(--ink)', color:'#F6EDE4', fontSize:13, fontWeight:500 }; const btnGhost = { display:'inline-flex', alignItems:'center', gap:7, padding:'9px 13px', borderRadius:10, background:'#FFF', color:'var(--ink)', border:'1px solid var(--line)', fontSize:13, fontWeight:500 }; /* ============================================================ SIDEBAR ============================================================ */ function Sidebar({ active, onSelect, open, onClose }) { return ( ); } function NavGroup({ title, children }) { return (
{title}
{children}
); } function NavItem({ active, icon, label, badge, onClick }) { const Icon = I[icon] || I.dot; return ( ); } /* ============================================================ TOPBAR ============================================================ */ function TopBar({ active, onMenu, onSelect }) { const labels = { dashboard:'Dashboard', timetable:'Timetable', grades:'Grades', courses:'Courses', finance:'Finance', profile:'Profile', announcements:'Announcements', documents:'Documents', enrollment:'Enrollment' }; const [open, setOpen] = useState(null); // 'mail' | 'bell' | 'settings' | 'user' const wrapRef = useRef(null); useEffect(() => { const close = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(null); }; document.addEventListener('pointerdown', close); return () => document.removeEventListener('pointerdown', close); }, []); const toggle = (k) => setOpen(o => o===k ? null : k); const go = (id) => { setOpen(null); onSelect && onSelect(id); }; return (
toggle('mail')}> {open==='mail' && ( go('announcements')}> {[ { from:'Dr. M. Collins', subject:'Running late', when:'08:17', unread:true }, { from:'Dean\u2019s Office', subject:'Student ID renewal confirmation', when:'yesterday', unread:true }, { from:'Dr. K. Miller', subject:'Midterm scope — chapters 5–8', when:'May 24', unread:false }, { from:'Library', subject:'Return reminder: 2 items due Friday', when:'May 23', unread:false }, ].map((m, i) => ( ))} )}
toggle('bell')}> {open==='bell' && ( go('dashboard')}> {[ { icon:, text:'2 new announcements in Python — Data Mining', when:'today', tone:'var(--warn-soft)', fg:'var(--warn)' }, { icon:, text:'Midterm scheduled: Mathematical Statistics · Jun 11', when:'yesterday', tone:'var(--info-soft)', fg:'var(--info)' }, { icon:, text:'5 new files in Applied Electronics Laboratory', when:'May 26', tone:'var(--green-soft)', fg:'var(--green)' }, ].map((n, i) => ( ))} )}
toggle('settings')}> {open==='settings' && ( } label="Account settings" onClick={()=>go('profile')}/> } label="Notification preferences" onClick={()=>go('profile')}/> } label="Password & security" onClick={()=>go('profile')}/> } label="Language — English" hint="EN" onClick={()=>setOpen(null)}/> )}
{open==='user' && (
{me.name}
{me.email}
} label="My profile" onClick={()=>go('profile')}/> } label="My grades" onClick={()=>go('grades')}/> } label="Billing" onClick={()=>go('finance')}/>
} label="Sign out" danger onClick={()=>setOpen(null)}/>
)}
); } function Dropdown({ title, children, footer, onFooter }) { return (
{title &&
{title}
} {children} {footer && ( )}
); } function MenuRow({ icon, label, hint, danger, onClick }) { return ( ); } function IconBtn({ children, badge, title, active, onClick }) { return ( ); } /* ============================================================ HERO — greeting + next class ============================================================ */ function Hero() { const greeting = useMemo(()=> { const h=new Date().getHours(); if (h<12) return 'Good morning'; if (h<18) return 'Good afternoon'; return 'Good evening'; }, []); const today = new Date().toLocaleDateString('en-US', { weekday:'long', month:'long', day:'numeric' }); return (
{/* Greeting */}
{today} · Even week

{greeting}, Name.

You have 2 new announcements from your lecturers and one midterm next week. Enrollment for the winter semester opens June 2.

{/* Next class card */}
Next class in ~ 47h

Mathematical Statistics

lab · Dr. K. Miller
); } function MetaCell({ k, v, sub }) { return (
{k}
{v}
{sub}
); } /* ============================================================ SCHEDULE ============================================================ */ function Schedule({ initialTab='online', dense=false }) { const [tab, setTab] = useState(initialTab); const filtered = useMemo(()=> { return upcoming.map(d => ({ ...d, blocks: d.blocks.filter(b => { if (tab==='week') return true; if (tab==='online') return !!b.online; if (tab==='exams') return b.type==='midterm'; return true; }) })).filter(d => d.blocks.length>0); }, [tab]); return ( } action={
{[['online','Online classes'],['week','Full week'],['exams','Exams']].map(([k,l])=>( ))}
} >{dense ? 'Weekly plan' : 'Upcoming classes'}
{filtered.length === 0 && (
Nothing in this view — switch to Full week to see all classes.
)} {filtered.map((d, i) => (
{d.when}
{d.blocks.map((b, j) => )}
))}
Online class times are set by the lecturer and may differ from the timetable.
); } function ClassRow({ time, code, name, type, room, online, teacher }) { const onlineMap = { 'Teams': { bg:'oklch(0.94 0.04 270)', fg:'oklch(0.42 0.13 270)', label:'Teams' }, 'Inspera': { bg:'oklch(0.95 0.05 50)', fg:'oklch(0.5 0.13 50)', label:'Inspera' }, }; const o = online ? onlineMap[online] : null; const typeTone = type==='midterm' ? 'warn' : type==='lecture' ? 'info' : 'neutral'; return (
e.currentTarget.style.background='#FCEFE0'} onMouseLeave={e=>e.currentTarget.style.background='var(--surface-2)'}>
{time.split('–')[0]} {time.split('–')[1]}
{code} {name} {type}
{teacher} · room {room}
{o ? ( {o.label} ) : ( in person )}
); } /* ============================================================ ANNOUNCEMENTS ============================================================ */ function Announcements() { const [filter, setFilter] = useState('all'); return ( } action={
·
} >Latest announcements
{announcements .filter(a => filter==='all' || a.unread) .map((a, i) => (
{a.course}
{a.subject}
{a.body}
{a.author} · {a.when}
))}
); } /* ============================================================ FILES ============================================================ */ const fileColors = { pdf: { bg:'oklch(0.95 0.04 25)', fg:'oklch(0.45 0.15 25)' }, pptx: { bg:'oklch(0.95 0.05 50)', fg:'oklch(0.45 0.14 50)' }, docx: { bg:'oklch(0.95 0.04 240)', fg:'oklch(0.42 0.13 240)' }, ino: { bg:'oklch(0.95 0.05 200)', fg:'oklch(0.42 0.12 200)' }, py: { bg:'oklch(0.95 0.04 145)', fg:'oklch(0.4 0.1 145)' }, }; function FileGroup({ group, defaultOpen=false }) { const [open, setOpen] = useState(defaultOpen); return (
{open && (
{group.items.map((f, i) => ( e.currentTarget.style.background='var(--surface-2)'} onMouseLeave={e=>e.currentTarget.style.background='transparent'}> {f.name} {f.when} ))}
)}
); } function FileIcon({ kind }) { const c = fileColors[kind] || { bg:'#F2E7D9', fg:'#6B5D52' }; return ( .{kind} ); } function Files() { return ( } action={} >Latest files
{fileGroups.map((g, i) => )}
); } /* ============================================================ ACTIVITY ============================================================ */ function Activity() { const [showAll, setShowAll] = useState(false); const visible = showAll ? activity : activity.slice(0,5); return ( } action={} >Account activity
{visible.map((a, i) => (
{a.browser} · {a.when}
{a.host}
{a.status==='bad' ? 'failed' : 'signed in'}
))}
); } /* ============================================================ NEWS, EVENTS, SOCIAL ============================================================ */ function NewsBoard() { return ( } action={} >School news
{/* Events */}
Events
{events.map((e, i) => (
{e.date.split(' ')[1]}
{e.date.split(' ')[0]}
{e.title}
{e.time} · {e.tag}
))}
School notices
{news.map((n, i) => ( {n.kind} {n.title} ))}
{/* Social */}
School online
live
); } function SocialGrid() { const tiles = [ { tag:'IG', seed:'campus-lecture', text:'Explore the Computer Science specializations' }, { tag:'IG', seed:'laptop-code', text:'If you are into more than just graphics…' }, { tag:'IG', seed:'design-studio', text:'Positive accreditation review for Graphic Design' }, { tag:'IG', seed:'open-day', text:'Come to the Open Day and see for yourself…' }, { tag:'TT', seed:'students-talk', text:'Like taking the lead? Hear from our graduates.' }, { tag:'IG', seed:'gallery-night', text:'Reminder: exhibition opening tomorrow evening' }, ]; return (
{tiles.map((t, i) => (
{t.text} {t.tag}
{t.text}
))}
); } /* ============================================================ CONTACT FOOTER ============================================================ */ function ContactFooter() { const items = [ { tag:'ACCOUNT', label:'Locked or inactive account', value:'passwords@school.edu', icon: }, { tag:'E-MAIL', label:'Mailbox issues', value:'mail-support@school.edu', icon: }, { tag:'DEAN\u2019S OFFICE', label:'Graphic Design · Computer Science', value:'cs-office@school.edu', icon: }, { tag:'DEAN\u2019S OFFICE', label:'IT Management · Management', value:'mgmt-office@school.edu', icon: }, ]; return ( }>Contact — when something breaks
{items.map((c, i) => (
{c.icon} {c.tag}
{c.label}
{c.value}
))}
); } /* ============================================================ PAGE HEADER ============================================================ */ function PageHeader({ title, eyebrow, lead, action }) { return (
{eyebrow}

{title}

{lead &&

{lead}

}
{action}
); } /* Share with views file */ Object.assign(window, { I, me, upcoming, announcements, fileGroups, activity, events, news, navMain, navAccount, Pill, Card, SectionLabel, Avatar, btnPrimary, btnGhost, Sidebar, TopBar, Hero, Schedule, ClassRow, Announcements, Files, FileGroup, Activity, NewsBoard, ContactFooter, PageHeader, });