Improve analysis UX: algorithm explanations, skeleton loading, auto-expand achieved specs
- Replace terse one-line optimization mode descriptions with clearer multi-sentence explanations of how Maximize Count and Priority Order algorithms behave - Add skeleton loading placeholders on course buttons while analysis is pending - Auto-expand achieved specializations to show credit breakdown by default - Add instructional subtitles to Course Selection and Specializations sections - Make Clear and Clear All buttons more prominent with visible backgrounds
This commit is contained in:
@@ -64,19 +64,17 @@ function ElectiveSet({
|
||||
{!isPinned && hasHighImpact && (
|
||||
<span style={{ fontSize: '11px', color: '#d97706', marginLeft: '8px', fontWeight: 400 }}>high impact</span>
|
||||
)}
|
||||
{!isPinned && loading && !analysis && (
|
||||
<span style={{ fontSize: '11px', color: '#888', marginLeft: '8px', fontWeight: 400 }}>analyzing...</span>
|
||||
)}
|
||||
</h4>
|
||||
{isPinned && (
|
||||
<button
|
||||
onClick={onUnpin}
|
||||
style={{
|
||||
fontSize: '11px', border: 'none', background: 'none',
|
||||
color: '#3b82f6', cursor: 'pointer', padding: '2px 4px',
|
||||
fontSize: '11px', border: '1px solid #bfdbfe', background: '#eff6ff',
|
||||
color: '#2563eb', cursor: 'pointer', padding: '3px 10px',
|
||||
borderRadius: '4px', fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
clear
|
||||
Clear
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -89,6 +87,7 @@ function ElectiveSet({
|
||||
{courses.map((course) => {
|
||||
const ceiling = ceilingMap.get(course.id);
|
||||
const reqFor = requiredForSpec[course.id];
|
||||
const showSkeleton = loading && !analysis;
|
||||
return (
|
||||
<button
|
||||
key={course.id}
|
||||
@@ -102,7 +101,19 @@ function ElectiveSet({
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '8px' }}>
|
||||
<span style={{ flex: 1 }}>{course.name}</span>
|
||||
{ceiling && (
|
||||
{showSkeleton ? (
|
||||
<span
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '60px',
|
||||
height: '14px',
|
||||
borderRadius: '3px',
|
||||
background: 'linear-gradient(90deg, #e5e7eb 25%, #f0f0f0 50%, #e5e7eb 75%)',
|
||||
backgroundSize: '200% 100%',
|
||||
animation: 'skeleton-pulse 1.5s ease-in-out infinite',
|
||||
}}
|
||||
/>
|
||||
) : ceiling ? (
|
||||
<span style={{
|
||||
fontSize: '11px', whiteSpace: 'nowrap', fontWeight: 600,
|
||||
color: ceiling.ceilingCount >= 3 ? '#16a34a' : ceiling.ceilingCount >= 2 ? '#2563eb' : '#666',
|
||||
@@ -114,7 +125,7 @@ function ElectiveSet({
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
{reqFor && (
|
||||
<span style={{ fontSize: '11px', color: '#92400e', marginTop: '2px' }}>
|
||||
@@ -130,6 +141,8 @@ function ElectiveSet({
|
||||
);
|
||||
}
|
||||
|
||||
const skeletonStyle = `@keyframes skeleton-pulse { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }`;
|
||||
|
||||
export function CourseSelection({ pinnedCourses, treeResults, treeLoading, onPin, onUnpin, onClearAll }: CourseSelectionProps) {
|
||||
const terms: Term[] = ['Spring', 'Summer', 'Fall'];
|
||||
const hasPinned = Object.keys(pinnedCourses).length > 0;
|
||||
@@ -139,14 +152,19 @@ export function CourseSelection({ pinnedCourses, treeResults, treeLoading, onPin
|
||||
|
||||
return (
|
||||
<div>
|
||||
<style>{skeletonStyle}</style>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' }}>
|
||||
<h2 style={{ fontSize: '16px', margin: 0 }}>Course Selection</h2>
|
||||
<div>
|
||||
<h2 style={{ fontSize: '16px', margin: 0 }}>Course Selection</h2>
|
||||
<p style={{ fontSize: '12px', color: '#888', margin: '2px 0 0' }}>Select one course per elective slot. Analysis shows how each choice affects your specializations.</p>
|
||||
</div>
|
||||
{hasPinned && (
|
||||
<button
|
||||
onClick={onClearAll}
|
||||
style={{
|
||||
fontSize: '12px', border: 'none', background: 'none',
|
||||
color: '#ef4444', cursor: 'pointer', padding: '2px 6px',
|
||||
fontSize: '12px', border: '1px solid #fecaca', background: '#fef2f2',
|
||||
color: '#dc2626', cursor: 'pointer', padding: '3px 10px',
|
||||
borderRadius: '4px', fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
Clear All
|
||||
|
||||
Reference in New Issue
Block a user