diff --git a/index.js b/index.js index 9cd64cd..6656ce2 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ const cookieParser = require('cookie-parser'); const path = require('path'); const routes = require('./src/routes'); const { router: filesRouter } = require('./src/files'); +const teacherRouter = require('./src/teacher'); const app = express(); const PORT = 3010; @@ -12,6 +13,7 @@ app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/api', routes); app.use('/api/files', filesRouter); +app.use('/api/teacher', teacherRouter); const html = f => (req, res) => res.sendFile(path.join(__dirname, 'public', f)); diff --git a/public/index.html b/public/index.html index 3260fb4..aadd42d 100644 --- a/public/index.html +++ b/public/index.html @@ -793,60 +793,135 @@ footer { .col-primary > *:not(#card-tt) { display: none !important; } } -/* ── SIDEBAR ─────────────────────────────────────────────── */ +/* ── PAGE LAYOUT ─────────────────────────────────────────────── */ -.sidebar-backdrop { - position: fixed; inset: 0; - background: rgba(0,0,0,.32); - z-index: 150; - opacity: 0; pointer-events: none; - transition: opacity .2s; +.page-body { + display: flex; + flex: 1; + align-items: stretch; + min-height: 0; } -.sidebar-backdrop.open { opacity: 1; pointer-events: all; } -.sidebar { - position: fixed; top: 0; right: 0; - width: 360px; max-width: 100vw; height: 100%; - background: var(--bg); - border-left: 1px solid var(--border); - box-shadow: var(--shadow-lg); - z-index: 160; - transform: translateX(100%); - transition: transform .22s cubic-bezier(.4,0,.2,1); - display: flex; flex-direction: column; - overflow: hidden; -} -.sidebar.open { transform: translateX(0); } +/* ── LEFT SIDEBAR ─────────────────────────────────────────────── */ -.sidebar-head { - height: 54px; - padding: 0 16px; - border-bottom: 1px solid var(--border); - display: flex; align-items: center; justify-content: space-between; gap: 10px; - background: var(--surface); +.app-sidebar { + width: 296px; flex-shrink: 0; + border-right: 1px solid var(--border); + background: var(--surface); + position: sticky; + top: 54px; + height: calc(100vh - 54px); + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: var(--n-200) transparent; + display: flex; + flex-direction: column; + z-index: 10; } -.sidebar-title { font-size: 13px; font-weight: 600; color: var(--text); } -.sidebar-close { - width: 28px; height: 28px; + +.app-sidebar-inner { + padding: 10px; + display: flex; + flex-direction: column; + gap: 8px; + flex: 1; +} + +.sb-nav-item { + display: flex; align-items: center; gap: 9px; + width: 100%; padding: 9px 10px; + border: none; background: none; cursor: pointer; + border-radius: var(--r-sm); + font-size: 13px; font-weight: 500; color: var(--text); + font-family: inherit; text-align: left; + transition: background .12s, color .12s; +} +.sb-nav-item:hover { background: var(--n-100); color: var(--blue); } +.sb-nav-item .lucide { width: 15px; height: 15px; color: var(--text-muted); flex-shrink: 0; } +.sb-nav-item:hover .lucide { color: var(--blue); } +.sb-nav-arrow { margin-left: auto; } + +/* Overlay panel */ +.overlay-panel { + position: fixed !important; inset: 16px !important; + z-index: 260; border-radius: var(--r-xl) !important; + overflow: hidden !important; box-shadow: var(--shadow-xl) !important; + flex-direction: column; +} +.overlay-panel .card-body { + overflow-y: auto; + flex: 1; +} + +.sb-group-label { + font-size: 10px; + font-weight: 700; + letter-spacing: .6px; + text-transform: uppercase; + color: var(--text-subtle); + padding: 6px 6px 2px; + margin-top: 2px; +} +.sb-group-label:first-child { margin-top: 0; padding-top: 2px; } + +/* Expand-to-fullscreen button */ +.card-expand-btn { + width: 24px; height: 24px; border: none; background: none; cursor: pointer; border-radius: var(--r-sm); display: flex; align-items: center; justify-content: center; - font-size: 18px; line-height: 1; color: var(--text-muted); - transition: background .1s; font-family: inherit; + color: var(--text-subtle); + transition: background .1s, color .1s; + flex-shrink: 0; + padding: 0; } -.sidebar-close:hover { background: var(--n-100); color: var(--text); } +.card-expand-btn:hover { background: var(--n-100); color: var(--text); } +.card-expand-btn .lucide { width: 13px; height: 13px; } -.sidebar-body { - flex: 1; overflow-y: auto; - padding: 14px; - display: flex; flex-direction: column; gap: 12px; - scrollbar-width: thin; - scrollbar-color: var(--n-200) transparent; +/* Fullscreen card overlay */ +.card.fullscreen { + position: fixed !important; + inset: 16px !important; + z-index: 260; + border-radius: var(--r-xl) !important; + overflow: auto !important; + box-shadow: var(--shadow-xl) !important; + display: flex !important; + flex-direction: column; + max-width: none !important; } +.card.fullscreen .card-body { + flex: 1; + overflow-y: auto; + max-width: 860px; + width: 100%; + margin: 0 auto; +} +.card.fullscreen .chat-msgs { height: auto; min-height: 300px; flex: 1; } -/* burger button badge dot (optional active state) */ -#sidebar-btn { position: relative; } +/* Fullscreen backdrop */ +#fs-backdrop { + position: fixed; inset: 0; + background: rgba(0,0,0,.45); + z-index: 259; + opacity: 0; pointer-events: none; + transition: opacity .2s; +} +#fs-backdrop.open { opacity: 1; pointer-events: all; } + +/* Sidebar overlay (small screens) */ +.sidebar-backdrop { + position: fixed; inset: 0; + background: rgba(0,0,0,.32); + z-index: 140; + opacity: 0; pointer-events: none; + transition: opacity .2s; + display: none; +} +.sidebar-backdrop.open { opacity: 1; pointer-events: all; } + +#sidebar-btn { position: relative; font-size: 18px; } /* ── RESPONSIVE ──────────────────────────────────────────── */ @@ -866,7 +941,29 @@ footer { .thread-reply-row textarea { flex:1; border:1.5px solid var(--border); border-radius:var(--r-sm); padding:8px 10px; font-size:13px; font-family:inherit; resize:none; outline:none; background:var(--surface); color:var(--text); transition:border-color .12s; } .thread-reply-row textarea:focus { border-color:var(--blue); } -@media (max-width: 860px) { +/* Large: sidebar always visible, no burger */ +@media (min-width: 1101px) { + #sidebar-btn { display: none !important; } + .sidebar-backdrop { display: none !important; } +} + +/* Small: sidebar becomes overlay, burger appears */ +@media (max-width: 1100px) { + .app-sidebar { + position: fixed; + top: 54px; left: 0; + height: calc(100vh - 54px); + transform: translateX(-100%); + transition: transform .22s cubic-bezier(.4,0,.2,1); + box-shadow: var(--shadow-lg); + z-index: 150; + } + .app-sidebar.open { transform: translateX(0); } + .sidebar-backdrop { display: block; } + #sidebar-btn { display: flex !important; } +} + +@media (max-width: 900px) { .main-grid { grid-template-columns: 1fr; } } @media (max-width: 600px) { @@ -881,6 +978,15 @@ footer { footer { padding: 11px 14px; } } +/* ── TEACHER TABS ────────────────────────────────────────── */ +.t-tabs { display:flex; border-bottom:1px solid var(--border); margin-bottom:12px; gap:0; overflow-x:auto; } +.t-tab { padding:8px 14px; font-size:12px; font-weight:600; color:var(--text-muted); cursor:pointer; border-bottom:2px solid transparent; margin-bottom:-1px; transition:color .12s, border-color .12s; white-space:nowrap; flex-shrink:0; } +.t-tab.active { color:var(--blue); border-bottom-color:var(--blue); } +.t-pane { display:none; } +.t-pane.active { display:block; } +.t-input { width:100%; padding:7px 10px; border:1px solid var(--border); border-radius:var(--r-sm); font-size:13px; font-family:inherit; background:var(--surface); color:var(--text); outline:none; transition:border-color .12s; } +.t-input:focus { border-color:var(--blue); } + /* ── ICONS ───────────────────────────────────────────────── */ .lucide { display: inline-block; @@ -908,6 +1014,8 @@ footer {
+ +
i1
@@ -922,8 +1030,7 @@ footer {
- - +
Anmelden Registrieren @@ -945,6 +1052,200 @@ footer {
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
@@ -1048,72 +1349,11 @@ footer {
- - - - - - +
- - +