stuff
This commit is contained in:
+136
-21
@@ -1227,6 +1227,8 @@ export function ColossiansStudySectionPage({ content }: Props) {
|
||||
const [noteLoading, setNoteLoading] = useState(false)
|
||||
const [noteSaving, setNoteSaving] = useState(false)
|
||||
const [noteMessage, setNoteMessage] = useState('')
|
||||
const [notesModalOpen, setNotesModalOpen] = useState(false)
|
||||
const [contextNoteMenu, setContextNoteMenu] = useState<{ x: number; y: number; text: string } | null>(null)
|
||||
const [completedSectionIds, setCompletedSectionIds] = useState<string[]>([])
|
||||
const [progressLoading, setProgressLoading] = useState(false)
|
||||
const [progressSaving, setProgressSaving] = useState(false)
|
||||
@@ -1392,6 +1394,35 @@ export function ColossiansStudySectionPage({ content }: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
function closeNotesModal() {
|
||||
setNotesModalOpen(false)
|
||||
}
|
||||
|
||||
function appendSelectedTextToNotes(selectedText: string) {
|
||||
if (!selectedText.trim()) return
|
||||
setNoteText(prev => prev ? `${prev.trim()}\n\n${selectedText.trim()}` : selectedText.trim())
|
||||
setNotesModalOpen(true)
|
||||
}
|
||||
|
||||
function handleLessonContentContextMenu(e: React.MouseEvent<HTMLDivElement>) {
|
||||
if (!auth.checked || !auth.authenticated || !isEnrolled || !study || !section) return
|
||||
const selection = window.getSelection()
|
||||
const selectedText = selection?.toString().trim() ?? ''
|
||||
if (!selectedText) {
|
||||
setContextNoteMenu(null)
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
setContextNoteMenu({ x: e.clientX + 4, y: e.clientY + 4, text: selectedText })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!contextNoteMenu) return
|
||||
const handleClick = () => setContextNoteMenu(null)
|
||||
window.addEventListener('mousedown', handleClick)
|
||||
return () => window.removeEventListener('mousedown', handleClick)
|
||||
}, [contextNoteMenu])
|
||||
|
||||
async function markLessonComplete() {
|
||||
if (!study || !section?.id || progressSaving) return
|
||||
setProgressSaving(true)
|
||||
@@ -1548,7 +1579,7 @@ export function ColossiansStudySectionPage({ content }: Props) {
|
||||
|
||||
return (
|
||||
<main className="study-section-page" aria-label={section.title}>
|
||||
<section className="section-study-classroom">
|
||||
<section className="section-study-classroom" onContextMenu={handleLessonContentContextMenu}>
|
||||
<div className="section-inner study-classroom-shell">
|
||||
<div className="study-classroom-main">
|
||||
<Link to={`/study/${study.slug}`} className="study-detail-back">Back to {study.title}</Link>
|
||||
@@ -1685,28 +1716,11 @@ export function ColossiansStudySectionPage({ content }: Props) {
|
||||
<div className="study-notes-box">
|
||||
<p className="study-notes-user">Signed in as {auth.username}</p>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap', marginBottom: '0.5rem' }}>
|
||||
<Link to={`/study/${study.slug}/notes`} className="btn-secondary">Open My Notes</Link>
|
||||
<button type="button" className="btn-primary" onClick={() => setNotesModalOpen(true)}>Open Notes</button>
|
||||
<Link to="/study/account" className="btn-secondary">My Account</Link>
|
||||
</div>
|
||||
<textarea
|
||||
rows={8}
|
||||
value={noteText}
|
||||
onChange={e => setNoteText(e.target.value)}
|
||||
placeholder="Write your lesson notes here..."
|
||||
disabled={noteLoading || noteSaving}
|
||||
/>
|
||||
<div className="study-auth-actions" style={{ flexWrap: 'wrap', gap: '0.5rem' }}>
|
||||
<button type="button" className="btn-primary" disabled={!canSaveNote} onClick={saveNote}>{noteSaving ? 'Saving...' : 'Save Notes'}</button>
|
||||
<button type="button" className="btn-secondary" disabled={authBusy} onClick={logoutStudyUser}>Sign Out</button>
|
||||
<button
|
||||
type="button"
|
||||
className={lessonCompleted ? 'btn-secondary' : 'btn-primary'}
|
||||
disabled={!isEnrolled || progressSaving || progressLoading}
|
||||
onClick={lessonCompleted ? unmarkLessonCompletion : markLessonComplete}
|
||||
>
|
||||
{progressSaving ? 'Updating...' : lessonCompleted ? 'Mark Incomplete' : 'Mark Complete'}
|
||||
</button>
|
||||
</div>
|
||||
<p style={{ margin: '0.5rem 0 0', color: '#b9b09b', fontSize: '0.9rem' }}>Highlight scripture, commentary, or Greek word text, right click, and add it to your notes.</p>
|
||||
{noteLoading ? <p style={{ marginTop: '0.75rem' }}>Loading notes…</p> : null}
|
||||
</div>
|
||||
)}
|
||||
{(authMessage || noteMessage || progressMessage) && <p className="study-note-status">{authMessage || noteMessage || progressMessage}</p>}
|
||||
@@ -1726,6 +1740,107 @@ export function ColossiansStudySectionPage({ content }: Props) {
|
||||
</div>
|
||||
</article>
|
||||
</aside>
|
||||
|
||||
{contextNoteMenu && (
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
left: contextNoteMenu.x,
|
||||
top: contextNoteMenu.y,
|
||||
zIndex: 50,
|
||||
backgroundColor: '#1f1d19',
|
||||
border: '1px solid #3f3b2f',
|
||||
borderRadius: '12px',
|
||||
padding: '0.75rem',
|
||||
boxShadow: '0 10px 30px rgba(0,0,0,0.25)',
|
||||
minWidth: '220px',
|
||||
}}
|
||||
onMouseDown={e => e.stopPropagation()}
|
||||
>
|
||||
<p style={{ margin: '0 0 0.75rem', color: '#ece3c6', fontSize: '0.95rem' }}>Add selected text to notes:</p>
|
||||
<div style={{ marginBottom: '0.75rem', maxHeight: '100px', overflow: 'auto', color: '#f0ead8', fontSize: '0.9rem' }}>
|
||||
{contextNoteMenu.text}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-primary"
|
||||
onClick={() => {
|
||||
appendSelectedTextToNotes(contextNoteMenu.text)
|
||||
setContextNoteMenu(null)
|
||||
}}
|
||||
>
|
||||
Add to Notes
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{notesModalOpen && (
|
||||
<div
|
||||
className="study-modal-overlay"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="Lesson notes editor"
|
||||
onClick={closeNotesModal}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
inset: 0,
|
||||
backgroundColor: 'rgba(12, 11, 10, 0.75)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
zIndex: 40,
|
||||
padding: '1rem',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="study-modal"
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{
|
||||
width: 'min(760px, 100%)',
|
||||
maxHeight: 'min(90vh, 900px)',
|
||||
overflowY: 'auto',
|
||||
backgroundColor: '#1b1a16',
|
||||
border: '1px solid #3c3a31',
|
||||
borderRadius: '18px',
|
||||
padding: '1.5rem',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '1rem', marginBottom: '1rem' }}>
|
||||
<div>
|
||||
<h2 style={{ margin: 0 }}>Lesson Notes</h2>
|
||||
<p style={{ margin: '0.5rem 0 0', color: '#b9b09b' }}>Save notes for this lesson and paste selections from the page.</p>
|
||||
</div>
|
||||
<button type="button" className="btn-secondary" onClick={closeNotesModal}>Close</button>
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
rows={12}
|
||||
value={noteText}
|
||||
onChange={e => setNoteText(e.target.value)}
|
||||
placeholder="Write your notes here..."
|
||||
style={{
|
||||
width: '100%',
|
||||
minHeight: '280px',
|
||||
padding: '1rem',
|
||||
borderRadius: '16px',
|
||||
border: '1px solid #3f3b2f',
|
||||
background: '#14130f',
|
||||
color: '#f0ead8',
|
||||
fontSize: '1rem',
|
||||
lineHeight: '1.6',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', justifyContent: 'flex-end', marginTop: '1rem' }}>
|
||||
<button type="button" className="btn-primary" onClick={saveNote} disabled={!canSaveNote}>
|
||||
{noteSaving ? 'Saving...' : 'Save Notes'}
|
||||
</button>
|
||||
<button type="button" className="btn-secondary" onClick={closeNotesModal}>Cancel</button>
|
||||
</div>
|
||||
{(noteMessage || progressMessage) && <p className="study-note-status" style={{ marginTop: '1rem' }}>{noteMessage || progressMessage}</p>}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user