Sign In Required
-Open any lesson and sign in from the Student Notes panel to see your saved notes here.
- Create Account or Sign In -diff --git a/package-lock.json b/package-lock.json index df5f8b9..809342e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "siteforge", - "version": "2.11.2", + "version": "2.12.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "siteforge", - "version": "2.11.2", + "version": "2.12.0", "dependencies": { "@aws-sdk/client-s3": "^3.1135.0", "@dnd-kit/core": "^6.3.1", diff --git a/package.json b/package.json index 1b407fe..387cbcd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "siteforge", "private": true, - "version": "2.11.2", + "version": "2.12.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src/App.css b/src/App.css index 7697f0c..8309044 100644 --- a/src/App.css +++ b/src/App.css @@ -4156,6 +4156,346 @@ border-left: 3px solid rgba(111, 207, 151, 0.7); } +/* ── Reflection questions ── */ +.quiz-page { + padding: clamp(1.5rem, 4vw, 2.5rem) 1.25rem 5rem; + background: + radial-gradient(ellipse at top, rgba(201, 168, 76, 0.09) 0%, transparent 55%), + var(--brand-black); +} + +.quiz-shell { max-width: 780px; margin: 0 auto; } + +.quiz-header { margin: 1rem 0 1.5rem; } +.quiz-header .eyebrow { margin: 0; } + +.quiz-header h1 { + margin: 0.15rem 0 0.2rem; + font-family: var(--brand-font-heading); + font-size: clamp(1.9rem, 4.5vw, 2.6rem); + color: var(--brand-warm-white); +} + +.quiz-reference { + margin: 0 0 0.75rem; + color: var(--brand-gold); + font-size: 0.82rem; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.quiz-intro { margin: 0 0 1.25rem; color: var(--brand-muted); line-height: 1.6; max-width: 600px; } + +.quiz-progress-label { + display: flex; + justify-content: space-between; + gap: 1rem; + margin-bottom: 0.4rem; + font-size: 0.85rem; + color: var(--brand-muted); +} + +.quiz-progress-label a { color: var(--brand-gold); text-decoration: none; } +.quiz-progress-label a:hover { text-decoration: underline; } + +.quiz-form { display: flex; flex-direction: column; gap: 1rem; } + +.quiz-card { + padding: 1.25rem 1.35rem; + border: 1px solid rgba(201, 168, 76, 0.2); + border-radius: 16px; + background: rgba(17, 17, 15, 0.84); + transition: border-color 0.2s ease; +} + +.quiz-card:focus-within { border-color: rgba(201, 168, 76, 0.55); } +.quiz-card--answered { border-left: 3px solid rgba(111, 207, 151, 0.7); } + +.quiz-card-head { display: flex; gap: 0.85rem; align-items: flex-start; margin-bottom: 0.85rem; } + +.quiz-card-number { + flex-shrink: 0; + width: 2rem; + height: 2rem; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 50%; + border: 1px solid rgba(201, 168, 76, 0.55); + background: rgba(201, 168, 76, 0.12); + color: var(--brand-gold); + font-family: var(--brand-font-heading); + font-weight: 700; +} + +.quiz-card-question { + font-family: var(--brand-font-heading); + font-size: 1.25rem; + line-height: 1.35; + color: var(--brand-warm-white); + padding-top: 0.1rem; +} + +.quiz-card-textarea { + width: 100%; + min-height: 110px; + box-sizing: border-box; + resize: vertical; + padding: 0.8rem 1rem; + border: 1px solid rgba(201, 168, 76, 0.22); + border-radius: 12px; + background: rgba(255, 255, 255, 0.04); + color: var(--brand-warm-white); + font-family: var(--brand-font-body); + font-size: 1rem; + line-height: 1.6; +} + +.quiz-card-textarea:focus { outline: none; border-color: rgba(201, 168, 76, 0.6); } + +.quiz-card-foot { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + margin-top: 0.6rem; + flex-wrap: wrap; +} + +.quiz-card-count { font-size: 0.78rem; color: var(--brand-muted); } + +.quiz-savebar { + position: sticky; + bottom: 0.75rem; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + flex-wrap: wrap; + padding: 0.85rem 1.1rem; + border: 1px solid rgba(201, 168, 76, 0.35); + border-radius: 14px; + background: rgba(14, 14, 12, 0.96); + backdrop-filter: blur(6px); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); +} + +.quiz-savebar-status { margin: 0; font-size: 0.9rem; color: var(--brand-muted); } +.quiz-savebar-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; } + +@media (max-width: 560px) { + .quiz-savebar { padding: 0.6rem 0.75rem; gap: 0.5rem; } + .quiz-savebar-status { width: 100%; font-size: 0.8rem; } + .quiz-savebar-actions { width: 100%; flex-wrap: nowrap; } + .quiz-savebar-actions .btn-primary, + .quiz-savebar-actions .btn-secondary { flex: 1; justify-content: center; padding: 0.55rem 0.5rem; font-size: 0.8rem; letter-spacing: 0.04em; } +} + +/* ── My Notes ── */ +.notes-page { + padding: clamp(1.5rem, 4vw, 2.5rem) 1.25rem 4rem; + background: + radial-gradient(ellipse at top, rgba(201, 168, 76, 0.09) 0%, transparent 55%), + var(--brand-black); +} + +.notes-shell { max-width: 1040px; margin: 0 auto; } + +.notes-header { + display: flex; + align-items: flex-end; + justify-content: space-between; + flex-wrap: wrap; + gap: 1rem; + margin: 1rem 0 1.25rem; +} + +.notes-header .eyebrow { margin: 0; } + +.notes-header h1 { + margin: 0.15rem 0 0.2rem; + font-family: var(--brand-font-heading); + font-size: clamp(1.9rem, 4.5vw, 2.6rem); + color: var(--brand-warm-white); +} + +.notes-subtitle { margin: 0; color: var(--brand-muted); } + +.notes-header-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; } + +.notes-tracks { + display: flex; + gap: 0.5rem; + flex-wrap: wrap; + margin-bottom: 1.25rem; +} + +.notes-track { + padding: 0.4rem 1rem; + border: 1px solid rgba(201, 168, 76, 0.3); + border-radius: 999px; + color: var(--brand-muted); + text-decoration: none; + font-size: 0.88rem; +} + +.notes-track:hover { color: var(--brand-warm-white); border-color: rgba(201, 168, 76, 0.6); } + +.notes-track--active { + background: var(--brand-gold); + border-color: var(--brand-gold); + color: var(--brand-black); + font-weight: 600; +} + +.notes-layout { + display: grid; + grid-template-columns: minmax(250px, 340px) minmax(0, 1fr); + gap: 1.25rem; + align-items: start; +} + +.notes-list-pane { + position: sticky; + top: 5.5rem; + max-height: calc(100vh - 7rem); + overflow-y: auto; + padding: 0.9rem; + border: 1px solid rgba(201, 168, 76, 0.2); + border-radius: 16px; + background: rgba(17, 17, 15, 0.84); +} + +.notes-search { + width: 100%; + margin-bottom: 0.75rem; + padding: 0.6rem 0.9rem; + border: 1px solid rgba(201, 168, 76, 0.25); + border-radius: 999px; + background: rgba(255, 255, 255, 0.04); + color: var(--brand-warm-white); + font-family: var(--brand-font-body); + font-size: 0.9rem; +} + +.notes-search:focus { outline: none; border-color: rgba(201, 168, 76, 0.6); } + +.notes-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; } + +.notes-item { + width: 100%; + display: flex; + gap: 0.75rem; + align-items: flex-start; + padding: 0.7rem 0.7rem; + border: 1px solid transparent; + border-radius: 12px; + background: none; + color: inherit; + text-align: left; + cursor: pointer; + font-family: var(--brand-font-body); +} + +.notes-item:hover { background: rgba(201, 168, 76, 0.07); } + +.notes-item--active { + background: rgba(201, 168, 76, 0.12); + border-color: rgba(201, 168, 76, 0.45); +} + +.notes-item-number { + flex-shrink: 0; + width: 1.9rem; + height: 1.9rem; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 50%; + border: 1px solid rgba(201, 168, 76, 0.5); + color: var(--brand-gold); + font-family: var(--brand-font-heading); + font-weight: 700; + font-size: 0.95rem; +} + +.notes-item-body { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; } +.notes-item-body strong { color: var(--brand-warm-white); font-weight: 600; font-size: 0.95rem; } +.notes-item-body small { color: var(--brand-gold); font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; } + +.notes-item-snippet { + color: var(--brand-muted); + font-size: 0.82rem; + line-height: 1.4; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; +} + +.notes-reader { + padding: clamp(1.25rem, 3vw, 2rem); + border: 1px solid rgba(201, 168, 76, 0.22); + border-radius: 18px; + background: linear-gradient(180deg, rgba(26, 26, 22, 0.95), rgba(16, 16, 14, 0.95)); +} + +.notes-reader-label { + margin: 0 0 0.3rem; + font-size: 0.75rem; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--brand-gold); +} + +.notes-reader h2 { + margin: 0 0 1.25rem; + font-family: var(--brand-font-heading); + font-size: clamp(1.5rem, 3vw, 2rem); + color: var(--brand-warm-white); +} + +.notes-block + .notes-block { margin-top: 1.25rem; padding-top: 1.25rem; border-top: 1px solid rgba(201, 168, 76, 0.14); } + +.notes-block h3 { + margin: 0 0 0.5rem; + font-size: 0.78rem; + letter-spacing: 0.12em; + text-transform: uppercase; + font-family: var(--brand-font-body); + font-weight: 600; + color: var(--brand-muted); +} + +.notes-reader-actions { margin-top: 1.75rem; } + +.notes-empty { + max-width: 520px; + margin: 2rem auto; + padding: 2rem; + text-align: center; + border: 1px solid rgba(201, 168, 76, 0.22); + border-radius: 18px; + background: rgba(17, 17, 15, 0.84); +} + +.notes-empty-icon { font-size: 2.2rem; margin-bottom: 0.5rem; } + +.notes-empty h2 { + margin: 0 0 0.5rem; + font-family: var(--brand-font-heading); + color: var(--brand-warm-white); +} + +.notes-empty p { margin: 0 0 1.25rem; color: var(--brand-muted); line-height: 1.6; } + +.notes-empty-text { color: var(--brand-muted); font-size: 0.92rem; } + +@media (max-width: 820px) { + .notes-layout { grid-template-columns: 1fr; } + .notes-list-pane { position: static; max-height: 18rem; } +} + /* ── My Account ── */ .account-page { padding: clamp(1.5rem, 5vw, 3rem) 1.25rem 4rem; @@ -14338,3 +14678,165 @@ a.study-track-card:hover { .admin-tabs--page { margin: 0 0 1.5rem; padding-bottom: 1rem; border-bottom: 1px solid #2a2518; } .admin-tabs--page .admin-tab { font-size: 0.8rem; padding: 0.45rem 0.9rem; } + +/* ── Study community (redesign) ── */ +.community-page { + padding: clamp(1.5rem, 4vw, 2.5rem) 1.25rem 4rem; + background: + radial-gradient(ellipse at top, rgba(201, 168, 76, 0.09) 0%, transparent 55%), + var(--brand-black); +} + +.community-shell { max-width: 1040px; margin: 0 auto; } + +.community-header { + display: flex; + align-items: flex-end; + justify-content: space-between; + flex-wrap: wrap; + gap: 1rem; + margin: 1rem 0 1.5rem; +} + +.community-header .eyebrow { margin: 0; } + +.community-header h1 { + margin: 0.15rem 0 0.2rem; + font-family: var(--brand-font-heading); + font-size: clamp(1.9rem, 4.5vw, 2.6rem); + color: var(--brand-warm-white); +} + +.community-subtitle { margin: 0; color: var(--brand-muted); } +.community-header-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; } + +.community-layout { + display: grid; + grid-template-columns: minmax(0, 1fr) 300px; + gap: 1.5rem; + align-items: start; +} + +.community-layout > .community-feed { min-width: 0; } + +.community-layout .community-post-card { + padding: 1.1rem 1.25rem; + margin-bottom: 0.85rem; + border: 1px solid rgba(201, 168, 76, 0.18); + border-radius: 14px; + background: rgba(17, 17, 15, 0.84); +} + +.community-layout .community-post-card:last-child { border-bottom: 1px solid rgba(201, 168, 76, 0.18); } + +.community-layout .community-compose-card { + border-color: rgba(201, 168, 76, 0.3); + background: linear-gradient(180deg, rgba(26, 26, 22, 0.95), rgba(16, 16, 14, 0.95)); +} + +.community-aside { + position: sticky; + top: 5.5rem; + display: flex; + flex-direction: column; + gap: 1rem; +} + +.community-aside-card { + padding: 1.1rem 1.15rem; + border: 1px solid rgba(201, 168, 76, 0.2); + border-radius: 16px; + background: rgba(17, 17, 15, 0.84); +} + +.community-aside-card h2 { + margin: 0 0 0.7rem; + font-family: var(--brand-font-heading); + font-size: 1.1rem; + color: #e8d9b5; +} + +.community-lesson-list { + list-style: none; + margin: 0; + padding: 0; + max-height: 22rem; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 0.2rem; +} + +.community-lesson-item { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + padding: 0.5rem 0.7rem; + border: 1px solid transparent; + border-radius: 10px; + background: none; + color: var(--brand-muted); + text-align: left; + font-family: var(--brand-font-body); + font-size: 0.9rem; + cursor: pointer; +} + +.community-lesson-item:hover { background: rgba(201, 168, 76, 0.07); color: var(--brand-warm-white); } + +.community-lesson-item--active { + background: rgba(201, 168, 76, 0.12); + border-color: rgba(201, 168, 76, 0.4); + color: var(--brand-warm-white); +} + +.community-lesson-item small { + flex-shrink: 0; + min-width: 1.5rem; + padding: 0.05rem 0.45rem; + border-radius: 999px; + background: rgba(201, 168, 76, 0.14); + color: var(--brand-gold); + text-align: center; + font-size: 0.75rem; +} + +.community-aside-note { margin: 0.75rem 0 0; font-size: 0.85rem; color: var(--brand-muted); } + +.community-guidelines { + margin: 0; + padding-left: 1.1rem; + color: #b9aa86; + font-size: 0.88rem; + line-height: 1.6; +} + +.community-filter-select { display: none; margin-bottom: 1rem; } + +.community-filter-select label { + display: block; + margin-bottom: 0.3rem; + font-size: 0.75rem; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--brand-muted); +} + +.community-filter-select select { + width: 100%; + padding: 0.6rem 0.8rem; + border: 1px solid rgba(201, 168, 76, 0.3); + border-radius: 10px; + background: rgba(255, 255, 255, 0.04); + color: var(--brand-warm-white); + font-family: var(--brand-font-body); +} + +@media (max-width: 860px) { + .community-layout { grid-template-columns: 1fr; } + .community-aside { position: static; order: 2; } + .community-aside .community-aside-card:first-child { display: none; } + .community-filter-select { display: block; } +} diff --git a/src/studyPages.tsx b/src/studyPages.tsx index c71daa1..a935a83 100644 --- a/src/studyPages.tsx +++ b/src/studyPages.tsx @@ -418,15 +418,23 @@ function CommunityBoard({ } } + const postCountFor = (sectionId: string) => posts.filter(p => p.sectionId === sectionId).length + const lessonsForFilter = releasedSections.filter(item => postCountFor(item.id) > 0 || item.id === activeSection) + const activeSectionTitle = releasedSections.find(item => item.id === activeSection)?.title + return ( +
Student Workspace
-Signed in as {auth.username}
} - {enrolledStudies.length > 1 && ( -Switch Track
-Loading your notes...
} - {!loading && !auth.authenticated && ( -Open any lesson and sign in from the Student Notes panel to see your saved notes here.
- Create Account or Sign In -You need to enroll in this study before accessing your notes.
- Go to Study Enrollment -You have not saved notes yet. Open a lesson and use the Student Notes area to start.
- {study.sections[0] && Open First Lesson} -{active.section ? `Lesson ${getLessonNumber(study.sections, active.section.id)}` : 'Saved Note'}
-{active.section ? active.section.reference : 'Lesson reference unavailable'}
- {(() => { - const anchorMap = parseNoteMap(active.note) - const hasContent = Object.values(anchorMap).some(v => v?.trim()) - if (!hasContent) returnNo notes saved for this lesson yet.
- return Object.entries(anchorMap).map(([key, html]) => ( - html?.trim() ? ( -{ANCHOR_LABELS[key] ?? key}
- -{message}
} -Student Workspace
++ {study.title} + {!loading && auth.authenticated && enrolled && <> · {entries.length} {entries.length === 1 ? 'lesson' : 'lessons'} with notes>} +
+Loading your notes…
} + + {!loading && !auth.authenticated && ( +Open any lesson and sign in from the Student Notes panel, and your saved notes will show up here.
+ Create Account or Sign In +You need to enroll in this study before you can write and read lesson notes.
+ Go to Study Enrollment +Open a lesson and use the Student Notes panel to jot down what stands out. Everything you save collects here, private to you.
+ {study.sections.find(isSectionReleased) && Open the First Lesson} +{active.section ? `Lesson ${getLessonNumber(study.sections, active.section.id)}` : 'Saved note'}{active.section?.reference ? ` · ${active.section.reference}` : ''}
+No notes saved for this lesson yet.
+ return blocks.map(([key, html]) => ( +{message}
} +Reflection Questions
Write out your answers below — they're saved privately. You can also choose to share individual answers to the lesson discussion.
-{section.reference}
} +Take your time. Your answers are saved privately to your account{canShare ? ', and you can choose to share any of them with the lesson discussion' : ''}.
+ {canSubmit && !loading && !error && ( +Loading reflection questions...
- ) : error ? ( -{error}
- ) : !canSubmit ? ( -This lesson does not have reflection questions configured yet.
-{study.title}
-Talk with other enrolled students. Keep it gracious and on topic.
-{study.title}
+Talk with the other students in this study. Keep it gracious and on topic.
+