import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'; import deleteSchedule from '@pages/background/lib/deleteSchedule'; import duplicateSchedule from '@pages/background/lib/duplicateSchedule'; import renameSchedule from '@pages/background/lib/renameSchedule'; import { Circle, CopySimple, DotsSixVertical, DotsThree, PencilSimpleLine, RadioButton, Trash, } from '@phosphor-icons/react'; import { background } from '@shared/messages'; import type { UserSchedule } from '@shared/types/UserSchedule'; import Text from '@views/components/common/Text/Text'; import { useEnforceScheduleLimit } from '@views/hooks/useEnforceScheduleLimit'; import useSchedules from '@views/hooks/useSchedules'; import { LONGHORN_DEVELOPERS_ADMINS, LONGHORN_DEVELOPERS_SWE } from '@views/lib/getGitHubStats'; import clsx from 'clsx'; import React, { useEffect, useMemo, useState } from 'react'; import { Button } from './Button'; import DialogProvider, { usePrompt } from './DialogProvider/DialogProvider'; import { ExtensionRootWrapper, styleResetClass } from './ExtensionRoot/ExtensionRoot'; import Link from './Link'; import { SortableListDragHandle } from './SortableListDragHandle'; /** * Props for the ScheduleListItem component. */ interface ScheduleListItemProps { schedule: UserSchedule; onClick?: React.DOMAttributes['onClick']; } const IS_STORYBOOK = import.meta.env.STORYBOOK; const teamMembers = [...LONGHORN_DEVELOPERS_ADMINS, ...LONGHORN_DEVELOPERS_SWE]; /** * This is a reusable dropdown component that can be used to toggle the visiblity of information */ export default function ScheduleListItem({ schedule, onClick }: ScheduleListItemProps): JSX.Element { const [activeSchedule] = useSchedules(); const [isEditing, setIsEditing] = useState(false); const [editorValue, setEditorValue] = useState(schedule.name); const teamMember = teamMembers[Math.floor(Math.random() * teamMembers.length)]; const showDialog = usePrompt(); const enforceScheduleLimit = useEnforceScheduleLimit(); const handleDuplicateSchedule = (scheduleId: string) => { if (enforceScheduleLimit()) { duplicateSchedule(scheduleId); } }; const editorRef = React.useRef(null); useEffect(() => { const editor = editorRef.current; setEditorValue(schedule.name); if (isEditing && editor) { editor.focus(); editor.setSelectionRange(0, editor.value.length); } }, [isEditing, schedule.name, editorRef]); const isActive = useMemo(() => activeSchedule.id === schedule.id, [activeSchedule, schedule]); const handleBlur = async () => { if (editorValue.trim() !== '' && editorValue.trim() !== schedule.name) { schedule.name = (await renameSchedule(schedule.id, editorValue.trim())) as string; if (schedule.name === '404') { const url = chrome.runtime.getURL('/404.html'); background.openNewTab({ url }); } if (Math.random() < 0.002) { showDialog({ title: 'Schedule name already taken', description: ( <> Schedule name {schedule.name} is already taken.

Join the 
Discord to contact {teamMember?.name as string}. ), // eslint-disable-next-line react/no-unstable-nested-components buttons: close => ( ), }); } } setIsEditing(false); }; const handleDelete = () => { showDialog({ title: 'Delete schedule?', description: ( <> Deleting {schedule.name} is permanent and will remove all added courses from {schedule.name} . ), // eslint-disable-next-line react/no-unstable-nested-components buttons: close => ( <> ), }); }; return (
{IS_STORYBOOK ? ( ) : ( )}
!isEditing && onClick?.(...e)} > {isActive ? ( ) : ( )} {isEditing && ( setEditorValue(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') handleBlur(); if (e.key === 'Escape') { setIsEditing(false); } }} onBlur={handleBlur} ref={editorRef} /> )} {!isEditing && ( setIsEditing(true)} > {schedule.name} )}
); }