Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 92 additions & 4 deletions client/src/components/SearchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { normalizeName } from "../utils/index";
import { useDb } from "../utils/useDb";
import Search from "./Search";
import SearchResultsContent from "./SearchResultsContent";
import SectionList from "./SectionList";
import { SectionList } from "./SectionList";

const Container = styled.div`
display: block;
Expand Down Expand Up @@ -52,7 +52,10 @@ interface ResultsProps {
}

const Results = React.memo(function Results({ search, sectionId, router }: ResultsProps) {
// Track current page for SectionList pagination
const [currentPage, setCurrentPage] = useState(1);
const scrollRef = useRef<HTMLDivElement>(null);
const hasAutoSelected = useRef(false);

const { data: db } = useDb();

Expand All @@ -74,6 +77,36 @@ const Results = React.memo(function Results({ search, sectionId, router }: Resul
}
);

// Auto-select first section when sections load and no section is selected
useEffect(() => {
if (sections && sections.length > 0 && !sectionId && !hasAutoSelected.current) {
hasAutoSelected.current = true;
const firstSection = sections[0];
if (firstSection) {
void router.push({
pathname: "/results",
query: { search, sectionId: firstSection.id },
}, undefined, { shallow: true });
}
}
}, [sections, sectionId, search, router]);

// Reset auto-select flag when search changes
useEffect(() => {
hasAutoSelected.current = false;
}, [search]);

// Update page when sectionId changes (arrow navigation or click)
useEffect(() => {
if (sections && sections.length > 0) {
const idx = sections.findIndex(s => s.id === sectionId);
if (idx !== -1) {
const newPage = Math.floor(idx / 5) + 1;
setCurrentPage(newPage);
}
}
}, [sectionId, sections]);

// get the section data
const {
data: section,
Expand Down Expand Up @@ -238,13 +271,66 @@ const Results = React.memo(function Results({ search, sectionId, router }: Resul
void debouncedNavigate(id);
}, [sectionId, debouncedNavigate]);

// Arrow key navigation between sections
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
// Don't handle arrow keys if user is typing in an input field or textarea
const target = event.target as HTMLElement;
if (
target.tagName === 'INPUT' ||
target.tagName === 'TEXTAREA' ||
target.isContentEditable
) {
return;
}

// Only handle arrow keys when a section is selected
if (!sections || sections.length === 0 || !sectionId) {
return;
}

// Find the current section index
const currentIndex = sections.findIndex((s) => s.id === sectionId);

if (currentIndex === -1) {
return;
}

let newIndex = -1;

if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
// Navigate to previous section
newIndex = currentIndex > 0 ? currentIndex - 1 : currentIndex;
event.preventDefault();
} else if (event.key === "ArrowRight" || event.key === "ArrowDown") {
// Navigate to next section
newIndex = currentIndex < sections.length - 1 ? currentIndex + 1 : currentIndex;
event.preventDefault();
}

// Navigate to the new section if index changed
if (newIndex !== -1 && newIndex !== currentIndex) {
const target = sections[newIndex];
if (target && typeof target.id === "number") {
handleClick(target.id);
}
}
};

// Add event listener
window.addEventListener("keydown", handleKeyDown);

// Cleanup
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [sections, sectionId, handleClick]);

const handleSubmit = useCallback(({ search }: SearchQuery) => {
void stableRouter.current.push({
pathname: "/results",
query: { search },
}).catch(error => {
}).catch((error: unknown) => {
console.error('Navigation error:', error);
});
}, []);
Expand All @@ -265,7 +351,7 @@ const Results = React.memo(function Results({ search, sectionId, router }: Resul
duration: 400,
smooth: true
});
}).catch(error => {
}).catch((error: unknown) => {
console.error('Navigation error:', error);
});
}, []);
Expand All @@ -288,6 +374,8 @@ const Results = React.memo(function Results({ search, sectionId, router }: Resul
loading={sectionsStatus === "loading"}
id={sectionId}
error={sectionsError}
page={currentPage}
setPage={setCurrentPage}
/>
</Col>

Expand All @@ -314,4 +402,4 @@ const Results = React.memo(function Results({ search, sectionId, router }: Resul
prevProps.sectionId === nextProps.sectionId;
});

export default Results;
export default Results;
2 changes: 1 addition & 1 deletion client/src/components/SearchResultsContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default function SearchResultsContent({
} else {
return (
<EmptyContainer>
<Empty>Nothing to see here, select a section!</Empty>
{/* <Empty>Nothing to see here, select a section!</Empty> */}
</EmptyContainer>
);
}
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/SectionContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,11 @@ const FlexSmall = styled.div`
`;

interface SectionContentProps {
// relatedSections: Grades[];
section: Grades;
instructor: RMPInstructor;
courseRating: number | null;
// handleRelatedSectionClick: (search: string, id: number) => void;
relatedSections?: Grades[];
handleRelatedSectionClick?: (search: string, id: number) => void;
}

const getDifficultyColor = (difficulty: number): string => {
Expand Down
Loading