adding tooltip with which class has conflicts

This commit is contained in:
Sriram Hariharan
2023-03-22 22:48:14 -05:00
parent 2ddfde2642
commit ad85c2b816
6 changed files with 71 additions and 11 deletions

View File

@@ -34,6 +34,10 @@
font-size: $x_small_size; font-size: $x_small_size;
} }
.xx_small_size {
font-size: $xx_small_size;
}
.small_size { .small_size {
font-size: $small_size; font-size: $small_size;
} }

View File

@@ -21,8 +21,37 @@
.isConflict { .isConflict {
* { * {
color: $speedway_brick; color: $speedway_brick !important;
text-decoration: line-through !important;
font-weight: normal !important; font-weight: normal !important;
text-decoration: line-through !important;
}
}
.row {
.conflictTooltip {
position: relative;
display: none;
.body {
position: absolute;
left: 40px;
display: flex;
flex-direction: column;
background: black;
padding: 8px;
width: 120px;
border-radius: 0px 5px 5px 0px;
opacity: 0.5;
div {
color: white !important;
text-decoration: none !important;
font-weight: normal !important;
}
}
}
&:hover {
.conflictTooltip {
display: initial;
}
} }
} }

View File

@@ -4,6 +4,7 @@ import { Course, ScrapedRow } from 'src/shared/types/Course';
import { UserSchedule } from 'src/shared/types/UserSchedule'; import { UserSchedule } from 'src/shared/types/UserSchedule';
import { Button } from '../../common/Button/Button'; import { Button } from '../../common/Button/Button';
import Icon from '../../common/Icon/Icon'; import Icon from '../../common/Icon/Icon';
import Text from '../../common/Text/Text';
import styles from './TableRow.module.scss'; import styles from './TableRow.module.scss';
interface Props { interface Props {
@@ -20,9 +21,13 @@ interface Props {
export default function TableRow({ row, isSelected, activeSchedule, onClick }: Props): JSX.Element | null { export default function TableRow({ row, isSelected, activeSchedule, onClick }: Props): JSX.Element | null {
const [container, setContainer] = useState<HTMLTableCellElement | null>(null); const [container, setContainer] = useState<HTMLTableCellElement | null>(null);
// the courses in the active schedule that conflict with the course for this row
const [conflicts, setConflicts] = useState<Course[]>([]);
const { element, course } = row; const { element, course } = row;
useEffect(() => { useEffect(() => {
element.classList.add(styles.row);
const portalContainer = document.createElement('td'); const portalContainer = document.createElement('td');
const lastTableCell = element.querySelector('td:last-child'); const lastTableCell = element.querySelector('td:last-child');
lastTableCell!.after(portalContainer); lastTableCell!.after(portalContainer);
@@ -30,6 +35,7 @@ export default function TableRow({ row, isSelected, activeSchedule, onClick }: P
return () => { return () => {
portalContainer.remove(); portalContainer.remove();
element.classList.remove(styles.row);
}; };
}, [element]); }, [element]);
@@ -54,15 +60,20 @@ export default function TableRow({ row, isSelected, activeSchedule, onClick }: P
return; return;
} }
let hasConflicts = activeSchedule.courses.find(c => { let conflicts: Course[] = [];
let conflicts = course.getConflicts(c);
return conflicts.length > 0;
});
element.classList[hasConflicts ? 'add' : 'remove'](styles.isConflict); for (const c of activeSchedule.courses) {
if (c.uniqueId !== course.uniqueId && course.getConflicts(c).length > 0) {
conflicts.push(c);
}
}
element.classList[conflicts.length ? 'add' : 'remove'](styles.isConflict);
setConflicts(conflicts);
return () => { return () => {
element.classList.remove(styles.isConflict); element.classList.remove(styles.isConflict);
setConflicts([]);
}; };
}, [activeSchedule, course]); }, [activeSchedule, course]);
@@ -71,9 +82,22 @@ export default function TableRow({ row, isSelected, activeSchedule, onClick }: P
} }
return ReactDOM.createPortal( return ReactDOM.createPortal(
<Button className={styles.rowButton} onClick={onClick} type='secondary'> <>
<Icon name='bar_chart' color='white' size='medium' /> <Button className={styles.rowButton} onClick={onClick} type='secondary'>
</Button>, <Icon name='bar_chart' color='white' size='medium' />
</Button>
{conflicts.length > 0 && (
<div className={styles.conflictTooltip}>
<div className={styles.body}>
{conflicts.map(c => (
<Text size='small' key={c.uniqueId}>
{c.department} {c.number} ({c.uniqueId})
</Text>
))}
</div>
</div>
)}
</>,
container container
); );
} }

View File

@@ -23,6 +23,7 @@ $semi_bold_weight: 600;
$bold_weight: 700; $bold_weight: 700;
$black_weight: 900; $black_weight: 900;
$xx_small_size: 4px;
$x_small_size: 8px; $x_small_size: 8px;
$small_size: 12px; $small_size: 12px;
$medium_size: 16px; $medium_size: 16px;
@@ -38,6 +39,7 @@ $xx_large_size: 48px;
bold_weight: $bold_weight; bold_weight: $bold_weight;
black_weight: $black_weight; black_weight: $black_weight;
xx_small_size: $xx_small_size;
x_small_size: $x_small_size; x_small_size: $x_small_size;
small_size: $small_size; small_size: $small_size;
medium_size: $medium_size; medium_size: $medium_size;

View File

@@ -14,6 +14,7 @@ export interface IWeights {
* the type for all the size scss variables exported from fonts.module.scss * the type for all the size scss variables exported from fonts.module.scss
*/ */
export interface ISizes { export interface ISizes {
xx_small_size: number;
x_small_size: number; x_small_size: number;
small_size: number; small_size: number;
medium_size: number; medium_size: number;

View File

@@ -19,7 +19,7 @@ Last Updated: 03/4/2023
- [ ] copy unique id quickly from browser action - [ ] copy unique id quickly from browser action
- [x] Clickable links to buildings - [x] Clickable links to buildings
- [ ] Count how many hours and # of classes in schedule - [ ] Count how many hours and # of classes in schedule
- [ ] Conflict highlighting - [x] Conflict highlighting
- [ ] Tooltip that says which classes conflict, maybe suggest a different section or time that doesn't conflict - [ ] Tooltip that says which classes conflict, maybe suggest a different section or time that doesn't conflict
- [ ] import / export schedules from JSON file - [ ] import / export schedules from JSON file
- [ ] Search for classes from within extension - [ ] Search for classes from within extension