From a423c6ed4e559763a30d8eeb6696568c613c8e35 Mon Sep 17 00:00:00 2001 From: Derek Chen Date: Sun, 15 Jun 2025 20:41:37 -0500 Subject: [PATCH] feat: initial commit bs code --- .../CollapsibleCourses/CourseCollapsible.tsx | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/views/components/injected/CollapsibleCourses/CourseCollapsible.tsx diff --git a/src/views/components/injected/CollapsibleCourses/CourseCollapsible.tsx b/src/views/components/injected/CollapsibleCourses/CourseCollapsible.tsx new file mode 100644 index 00000000..0ebd6ec6 --- /dev/null +++ b/src/views/components/injected/CollapsibleCourses/CourseCollapsible.tsx @@ -0,0 +1,62 @@ +import React, { useEffect, useState } from 'react'; +import ReactDOM from 'react-dom'; + +function getCourseSections() { + const table = document.querySelector('table'); + if (!table) return []; + + const rows = Array.from(table.querySelectorAll('tr')); + const sections: { header: HTMLTableRowElement; children: HTMLTableRowElement[] }[] = []; + let currentSection: { header: HTMLTableRowElement; children: HTMLTableRowElement[] } | null = null; + + for (const row of rows) { + const headerCell = row.querySelector('td.course_header'); + if (headerCell) { + if (currentSection) sections.push(currentSection); + currentSection = { header: row, children: [] }; + } else if (currentSection) { + currentSection.children.push(row); + } + } + if (currentSection) sections.push(currentSection); + return sections; +} + +const CollapsibleSection: React.FC<{ + header: HTMLTableRowElement; + childrenRows: HTMLTableRowElement[]; +}> = ({ header, childrenRows }) => { + const [open, setOpen] = useState(false); + + useEffect(() => { + // Hide children rows initially + childrenRows.forEach(row => (row.style.display = open ? '' : 'none')); + // Clean up on unmount + return () => { + childrenRows.forEach(row => (row.style.display = '')); + }; + }, [open, childrenRows]); + + // Inject a button into the header cell + useEffect(() => { + const cell = header.querySelector('td.course_header'); + if (!cell) return; + let button = cell.querySelector('.utrp-collapse-btn') as HTMLButtonElement | null; + if (!button) { + button = document.createElement('button'); + button.className = 'utrp-collapse-btn'; + button.style.marginRight = '8px'; + cell.prepend(button); + } + button.textContent = open ? '▼' : '►'; + button.onclick = () => setOpen(o => !o); + // Clean up + return () => { + button?.remove(); + }; + }, [header, open]); + + return null; +}; + +export default