fix(practice): use Next.js Link for student tiles + fix session observer z-index
- Replace <button> with <Link> in StudentCard for proper routing - Enables Cmd/Ctrl+Click to open in new tab - Shows URL on hover in browser status bar - Enables Next.js prefetching - Close NotesModal before opening SessionObserverModal - Fixes z-index stacking issue where observer appeared behind quicklook 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
07484fdfac
commit
6def610877
|
|
@ -120,7 +120,13 @@ function buildStudentActionData(student: StudentProp): StudentActionData {
|
|||
* - Overflow menu: All student actions (uses shared useStudentActions hook)
|
||||
* - Zoom animation from source tile
|
||||
*/
|
||||
export function NotesModal({ isOpen, student, sourceBounds, onClose, onObserveSession }: NotesModalProps) {
|
||||
export function NotesModal({
|
||||
isOpen,
|
||||
student,
|
||||
sourceBounds,
|
||||
onClose,
|
||||
onObserveSession,
|
||||
}: NotesModalProps) {
|
||||
const router = useRouter()
|
||||
const { resolvedTheme } = useTheme()
|
||||
const isDark = resolvedTheme === 'dark'
|
||||
|
|
@ -140,9 +146,13 @@ export function NotesModal({ isOpen, student, sourceBounds, onClose, onObserveSe
|
|||
const studentActionData = buildStudentActionData(student)
|
||||
const { actions, handlers, modals } = useStudentActions(studentActionData, {
|
||||
// Session observer is rendered at parent level to avoid z-index issues
|
||||
// Close this modal first so the observer modal appears on top
|
||||
onObserveSession:
|
||||
onObserveSession && student.activity?.sessionId
|
||||
? () => onObserveSession(student.activity!.sessionId!)
|
||||
? () => {
|
||||
onClose()
|
||||
onObserveSession(student.activity!.sessionId!)
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
|
||||
|
|
@ -207,10 +217,12 @@ export function NotesModal({ isOpen, student, sourceBounds, onClose, onObserveSe
|
|||
|
||||
const handleBannerWatchSession = useCallback(() => {
|
||||
// Session observer is rendered at parent level to avoid z-index issues
|
||||
// Close this modal first so the observer modal appears on top
|
||||
if (onObserveSession && student.activity?.sessionId) {
|
||||
onClose()
|
||||
onObserveSession(student.activity.sessionId)
|
||||
}
|
||||
}, [onObserveSession, student.activity?.sessionId])
|
||||
}, [onObserveSession, student.activity?.sessionId, onClose])
|
||||
|
||||
// ========== Effects ==========
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import * as Checkbox from '@radix-ui/react-checkbox'
|
||||
import * as HoverCard from '@radix-ui/react-hover-card'
|
||||
import Link from 'next/link'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTheme } from '@/contexts/ThemeContext'
|
||||
import { Z_INDEX } from '@/constants/zIndex'
|
||||
|
|
@ -159,7 +160,8 @@ export interface StudentWithProgress extends Player {
|
|||
|
||||
interface StudentCardProps {
|
||||
student: StudentWithProgress
|
||||
onSelect: (student: StudentWithProgress) => void
|
||||
/** Optional callback when student is selected (Link handles navigation) */
|
||||
onSelect?: (student: StudentWithProgress) => void
|
||||
onToggleSelection: (student: StudentWithProgress) => void
|
||||
onOpenQuickLook: (student: StudentWithProgress, bounds: DOMRect) => void
|
||||
isSelected?: boolean
|
||||
|
|
@ -323,11 +325,7 @@ function StudentCard({
|
|||
})}
|
||||
aria-label="View relationship details"
|
||||
>
|
||||
<RelationshipBadge
|
||||
relationship={relationship}
|
||||
size="sm"
|
||||
showTooltip={false}
|
||||
/>
|
||||
<RelationshipBadge relationship={relationship} size="sm" showTooltip={false} />
|
||||
</button>
|
||||
</HoverCard.Trigger>
|
||||
<HoverCard.Portal>
|
||||
|
|
@ -406,11 +404,12 @@ function StudentCard({
|
|||
</button>
|
||||
)}
|
||||
|
||||
{/* Main clickable area */}
|
||||
<button
|
||||
type="button"
|
||||
{/* Main clickable area - uses Next.js Link for proper routing */}
|
||||
<Link
|
||||
href={`/practice/${student.id}/dashboard`}
|
||||
scroll={false}
|
||||
data-action="select-student"
|
||||
onClick={() => onSelect(student)}
|
||||
onClick={() => onSelect?.(student)}
|
||||
className={css({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
|
|
@ -422,6 +421,8 @@ function StudentCard({
|
|||
padding: '0.5rem',
|
||||
paddingTop: '1.5rem', // Extra space for the notes/checkbox
|
||||
width: '100%',
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
_hover: {
|
||||
'& > div:first-child': {
|
||||
transform: 'scale(1.05)',
|
||||
|
|
@ -618,7 +619,7 @@ function StudentCard({
|
|||
<span>{student.intervention.message}</span>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
</Link>
|
||||
|
||||
{/* Enrollment action buttons (for enrollment requests) */}
|
||||
{enrollmentActions && student.enrollmentRequestId && (
|
||||
|
|
@ -753,7 +754,8 @@ function AddStudentButton({ onClick }: AddStudentButtonProps) {
|
|||
|
||||
interface StudentSelectorProps {
|
||||
students: StudentWithProgress[]
|
||||
onSelectStudent: (student: StudentWithProgress) => void
|
||||
/** Optional callback when student is selected (Link handles navigation) */
|
||||
onSelectStudent?: (student: StudentWithProgress) => void
|
||||
onToggleSelection: (student: StudentWithProgress) => void
|
||||
onAddStudent?: () => void
|
||||
title?: string
|
||||
|
|
|
|||
Loading…
Reference in New Issue