feat: rework start time to checkboxes (#553)
* feat: replace dropdown with checkbox * refactor: remove console logs * refactor: eslint happy * refactor: change daysValue from string to array * style: match course schedule page styling * style: remove label font-normal * style: finalize course schedule page style match --------- Co-authored-by: Samuel Gunter <29130894+Samathingamajig@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import CourseCatalogMain from '@views/components/CourseCatalogMain';
|
import CourseCatalogMain from '@views/components/CourseCatalogMain';
|
||||||
import InjectedButton from '@views/components/injected/AddAllButton';
|
import InjectedButton from '@views/components/injected/AddAllButton';
|
||||||
|
import DaysCheckbox from '@views/components/injected/DaysCheckbox';
|
||||||
import getSiteSupport, { SiteSupport } from '@views/lib/getSiteSupport';
|
import getSiteSupport, { SiteSupport } from '@views/lib/getSiteSupport';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
@@ -25,3 +26,7 @@ if (support === SiteSupport.COURSE_CATALOG_DETAILS || support === SiteSupport.CO
|
|||||||
if (support === SiteSupport.MY_UT) {
|
if (support === SiteSupport.MY_UT) {
|
||||||
renderComponent(InjectedButton);
|
renderComponent(InjectedButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (support === SiteSupport.COURSE_CATALOG_SEARCH) {
|
||||||
|
renderComponent(DaysCheckbox);
|
||||||
|
}
|
||||||
|
|||||||
89
src/views/components/injected/DaysCheckbox.tsx
Normal file
89
src/views/components/injected/DaysCheckbox.tsx
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
|
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] as const;
|
||||||
|
/**
|
||||||
|
* Component that transforms the days dropdown into a series of checkboxes
|
||||||
|
* on the course catalog search page
|
||||||
|
*
|
||||||
|
* @returns The rendered checkbox component or null if the container is not found.
|
||||||
|
*/
|
||||||
|
export default function DaysCheckbox(): JSX.Element | null {
|
||||||
|
const [container, setContainer] = useState<HTMLDivElement | null>(null);
|
||||||
|
const [daysValue, setDaysValue] = useState<number[]>([0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const daysDropdown = document.getElementById('mtg_days_st') as HTMLSelectElement | null;
|
||||||
|
if (!daysDropdown) {
|
||||||
|
console.error('Days dropdown not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formElement = daysDropdown.closest('.form_element')!;
|
||||||
|
const checkboxContainer = document.createElement('div');
|
||||||
|
|
||||||
|
// Create a hidden input to store the value
|
||||||
|
const hiddenInput = document.createElement('input');
|
||||||
|
hiddenInput.type = 'hidden';
|
||||||
|
hiddenInput.name = 'mtg_days_st';
|
||||||
|
hiddenInput.id = 'mtg_days_st_hidden';
|
||||||
|
hiddenInput.value = daysDropdown.value;
|
||||||
|
|
||||||
|
// Remove old dropdown
|
||||||
|
formElement.innerHTML = '';
|
||||||
|
|
||||||
|
// Add the label back
|
||||||
|
const newLabel = document.createElement('label');
|
||||||
|
newLabel.className = 'primary_label';
|
||||||
|
newLabel.htmlFor = 'mtg_days_st_hidden';
|
||||||
|
newLabel.textContent = 'AND days';
|
||||||
|
|
||||||
|
formElement.appendChild(newLabel);
|
||||||
|
formElement.appendChild(hiddenInput);
|
||||||
|
formElement.appendChild(checkboxContainer);
|
||||||
|
setContainer(checkboxContainer);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
checkboxContainer.remove();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Update hidden input when daysValue changes
|
||||||
|
const hiddenInput = document.getElementById('mtg_days_st_hidden') as HTMLInputElement | null;
|
||||||
|
if (hiddenInput) {
|
||||||
|
hiddenInput.value = daysValue.join('');
|
||||||
|
}
|
||||||
|
}, [daysValue]);
|
||||||
|
|
||||||
|
const handleDayChange = (position: number, checked: boolean) => {
|
||||||
|
setDaysValue(prev => prev.with(position, checked ? 1 : 0));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!container) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReactDOM.createPortal(
|
||||||
|
<ExtensionRoot>
|
||||||
|
<ul className='text-black font-[Verdana,_"Helvetica_Neue",_Helvetica,_Arial,_sans-serif]'>
|
||||||
|
{days.map((day, index) => (
|
||||||
|
<li key={day}>
|
||||||
|
<input
|
||||||
|
type='checkbox'
|
||||||
|
id={`day_${day}`}
|
||||||
|
checked={daysValue[index] === 1}
|
||||||
|
onChange={e => {
|
||||||
|
handleDayChange(index, e.target.checked);
|
||||||
|
}}
|
||||||
|
className='form-checkbox m-[3px_3px_3px_4px]'
|
||||||
|
/>{' '}
|
||||||
|
<label htmlFor={`day_${day}`}>{day}</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</ExtensionRoot>,
|
||||||
|
container
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ export const SiteSupport = {
|
|||||||
MY_CALENDAR: 'MY_CALENDAR',
|
MY_CALENDAR: 'MY_CALENDAR',
|
||||||
REPORT_ISSUE: 'REPORT_ISSUE',
|
REPORT_ISSUE: 'REPORT_ISSUE',
|
||||||
MY_UT: 'MY_UT',
|
MY_UT: 'MY_UT',
|
||||||
|
COURSE_CATALOG_SEARCH: 'COURSE_CATALOG_SEARCH',
|
||||||
CLASSLIST: 'CLASSLIST',
|
CLASSLIST: 'CLASSLIST',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ export default function getSiteSupport(url: string): SiteSupportType | null {
|
|||||||
if (document.querySelector('#details')) {
|
if (document.querySelector('#details')) {
|
||||||
return SiteSupport.COURSE_CATALOG_DETAILS;
|
return SiteSupport.COURSE_CATALOG_DETAILS;
|
||||||
}
|
}
|
||||||
|
return SiteSupport.COURSE_CATALOG_SEARCH;
|
||||||
}
|
}
|
||||||
if (url.includes('utdirect.utexas.edu') && (url.includes('waitlist') || url.includes('classlist'))) {
|
if (url.includes('utdirect.utexas.edu') && (url.includes('waitlist') || url.includes('classlist'))) {
|
||||||
return SiteSupport.WAITLIST;
|
return SiteSupport.WAITLIST;
|
||||||
|
|||||||
Reference in New Issue
Block a user