Tighten typing and input validation across study pages
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m2s

This commit is contained in:
Elijah 2026-07-13 06:55:17 -07:00
parent 6d1d918355
commit d6f3502cb1
16 changed files with 170 additions and 56 deletions

View file

@ -27,6 +27,7 @@ import {
useSortable,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import type { ReorderItem } from "@/types/study";
interface DeckItem {
id: string;
@ -65,7 +66,14 @@ function getProgressLabel(deck: DeckItem) {
return `${current}/${total}, ${modeLabel} · ${correctCount}`;
}
function SortableDeckCard({ deck, onEdit, onDelete, classSlug }: any) {
interface SortableDeckCardProps {
deck: DeckItem;
onEdit: (deck: DeckItem) => void;
onDelete: (deck: DeckItem) => void;
classSlug: string;
}
function SortableDeckCard({ deck, onEdit, onDelete, classSlug }: SortableDeckCardProps) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: deck.id });
const style = {
transform: CSS.Transform.toString(transform),
@ -314,8 +322,6 @@ export default function FlashcardsPage() {
if (!activeDeck) return;
let targetGroupId: string | null = null;
let targetIndex = 0;
const overContainerId = over.data.current?.sortable?.containerId;
if (overContainerId) {
targetGroupId = overContainerId === "uncategorized" ? null : overContainerId;
@ -344,7 +350,7 @@ export default function FlashcardsPage() {
}
const affectedGroups = new Set([activeDeck.groupId, targetGroupId]);
const updates: any[] = [];
const updates: ReorderItem[] = [];
affectedGroups.forEach(gId => {
const gItems = newItems.filter(d => d.groupId === gId);

View file

@ -27,6 +27,7 @@ import {
useSortable,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import type { ReorderItem } from "@/types/study";
interface QuizItem {
id: string;
@ -51,7 +52,14 @@ interface MaterialGroup {
const cache: Record<string, { quizzes: QuizItem[]; groups: MaterialGroup[] }> = {};
function SortableQuizCard({ quiz, onEdit, onDelete, classSlug }: any) {
interface SortableQuizCardProps {
quiz: QuizItem;
onEdit: (quiz: QuizItem) => void;
onDelete: (quiz: QuizItem) => void;
classSlug: string;
}
function SortableQuizCard({ quiz, onEdit, onDelete, classSlug }: SortableQuizCardProps) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: quiz.id });
const style = {
transform: CSS.Transform.toString(transform),
@ -312,8 +320,6 @@ export default function QuizzesPage() {
if (!activeQuiz) return;
let targetGroupId: string | null = null;
let targetIndex = 0;
// Check if over a group container directly
const overContainerId = over.data.current?.sortable?.containerId;
if (overContainerId) {
@ -345,7 +351,7 @@ export default function QuizzesPage() {
// Re-calculate sortOrder for the affected groups to persist
const affectedGroups = new Set([activeQuiz.groupId, targetGroupId]);
const updates: any[] = [];
const updates: ReorderItem[] = [];
affectedGroups.forEach(gId => {
const gItems = newItems.filter(q => q.groupId === gId);