feat: timeline multi-select, demand popover, resource hover card, merged tooltips, dark mode fixes

Major timeline enhancements:
- Right-click drag multi-selection with floating action bar (batch delete/assign)
- DemandPopover for demand strip details (replaces broken "Loading" modal)
- ResourceHoverCard on name hover showing skills, rates, role, chapter
- Merged heatmap+vacation tooltips into unified TimelineTooltip component
- Fixed overbooking blink animation (date normalization, z-index ordering)
- Fixed dark mode sticky column bleed-through in project view
- System roles admin page, notification task management, performance review docs

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-03-18 23:43:51 +01:00
parent d0f04f13f8
commit ddec3a927a
67 changed files with 4930 additions and 1166 deletions
@@ -20,7 +20,7 @@ const ACCENT_OPTIONS: { value: AccentColor; label: string; swatch: string }[] =
export function PreferencesModal({ onClose }: PreferencesModalProps) {
const { prefs, setMode, setAccent } = useTheme();
const { prefs: appPrefs, setHideCompletedProjects, setTimelineDisplayMode, setHeatmapColorScheme, setShowDemandProjects } = useAppPreferences();
const { prefs: appPrefs, setHideCompletedProjects, setTimelineDisplayMode, setHeatmapColorScheme, setShowDemandProjects, setBlinkOverbookedDays } = useAppPreferences();
return (
<div
@@ -219,6 +219,34 @@ export function PreferencesModal({ onClose }: PreferencesModalProps) {
</div>
</div>
{/* Overbooked blink */}
<label className="flex items-start gap-3 cursor-pointer mb-3">
<div className="relative mt-0.5 flex-shrink-0">
<input
type="checkbox"
checked={appPrefs.blinkOverbookedDays}
onChange={(e) => setBlinkOverbookedDays(e.target.checked)}
className="sr-only peer"
/>
<div className={clsx(
"w-9 h-5 rounded-full transition-colors",
appPrefs.blinkOverbookedDays ? "bg-brand-600" : "bg-gray-200 dark:bg-gray-700",
)} />
<div className={clsx(
"absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full shadow transition-transform",
appPrefs.blinkOverbookedDays ? "translate-x-4" : "translate-x-0",
)} />
</div>
<div>
<span className="text-sm text-gray-800 dark:text-gray-200 font-medium leading-tight block">
Blink overbooked days
</span>
<span className="text-xs text-gray-400 dark:text-gray-500">
Highlight days where a resource exceeds 8h with a pulsing animation.
</span>
</div>
</label>
<label className="flex items-start gap-3 cursor-pointer">
<div className="relative mt-0.5 flex-shrink-0">
<input