feat(calendar): click due-date day to navigate to filtered Reporting view

- CalendarWidget accepts onDateClick prop; due-date cells are clickable
  with pointer cursor, red hover highlight, and updated tooltip
- App.js wires onDateClick: sets calendarFilter state and navigates to
  the Reporting page
- NavDrawer navigation to Reporting clears calendarFilter so it only
  applies on calendar-initiated navigation
- ReportingPage accepts filterDate prop; initializes columnFilters with
  { dueDate: Set([filterDate]) } so the view lands pre-filtered
- Existing Clear Filters button lets the user dismiss the filter normally

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 14:09:08 -06:00
parent 669396f635
commit 51b1f99b3a
3 changed files with 24 additions and 8 deletions

View File

@@ -178,6 +178,7 @@ export default function App() {
const [quickCheckResult, setQuickCheckResult] = useState(null);
const [currentPage, setCurrentPage] = useState('home');
const [navOpen, setNavOpen] = useState(false);
const [calendarFilter, setCalendarFilter] = useState(null);
const [showAddCVE, setShowAddCVE] = useState(false);
const [showUserManagement, setShowUserManagement] = useState(false);
const [showAuditLog, setShowAuditLog] = useState(false);
@@ -961,7 +962,11 @@ export default function App() {
isOpen={navOpen}
onClose={() => setNavOpen(false)}
currentPage={currentPage}
onNavigate={setCurrentPage}
onNavigate={(page) => {
// Clear calendar filter when navigating directly via the nav drawer
if (page === 'reporting') setCalendarFilter(null);
setCurrentPage(page);
}}
/>
{/* Scanning line effect */}
<div className="scan-line"></div>
@@ -1036,7 +1041,7 @@ export default function App() {
</div>
{/* Page content */}
{currentPage === 'reporting' && <ReportingPage />}
{currentPage === 'reporting' && <ReportingPage filterDate={calendarFilter} />}
{currentPage === 'knowledge-base' && <KnowledgeBasePage />}
{currentPage === 'exports' && <ExportsPage />}
@@ -2220,7 +2225,12 @@ export default function App() {
Calendar
</h2>
<CalendarWidget />
<CalendarWidget
onDateClick={(dateStr) => {
setCalendarFilter(dateStr);
setCurrentPage('reporting');
}}
/>
</div>
{/* Open Vendor Tickets */}

View File

@@ -16,7 +16,7 @@ function toLocalDateStr(date) {
return `${y}-${m}-${d}`;
}
export default function CalendarWidget() {
export default function CalendarWidget({ onDateClick }) {
const today = new Date();
const todayStr = toLocalDateStr(today);
@@ -116,15 +116,19 @@ export default function CalendarWidget() {
return (
<div
key={idx}
title={hasDue ? `${dueCount} finding${dueCount > 1 ? 's' : ''} due` : undefined}
title={hasDue ? `${dueCount} finding${dueCount > 1 ? 's' : ''} due — click to view` : undefined}
onClick={hasDue && onDateClick ? () => onDateClick(dateStr) : undefined}
style={{
display: 'flex', flexDirection: 'column', alignItems: 'center',
gap: '2px', padding: '3px 1px',
borderRadius: '4px',
background: isToday ? 'rgba(14,165,233,0.2)' : 'transparent',
border: isToday ? '1px solid rgba(14,165,233,0.5)' : '1px solid transparent',
cursor: hasDue ? 'default' : 'default',
cursor: hasDue ? 'pointer' : 'default',
transition: hasDue ? 'background 0.15s' : undefined,
}}
onMouseEnter={hasDue ? (e) => { e.currentTarget.style.background = isToday ? 'rgba(14,165,233,0.35)' : 'rgba(239,68,68,0.15)'; } : undefined}
onMouseLeave={hasDue ? (e) => { e.currentTarget.style.background = isToday ? 'rgba(14,165,233,0.2)' : 'transparent'; } : undefined}
>
<span style={{
fontSize: '0.7rem', fontFamily: 'monospace', lineHeight: 1,

View File

@@ -564,7 +564,7 @@ function TableCell({ colKey, finding }) {
// ---------------------------------------------------------------------------
// Main ReportingPage
// ---------------------------------------------------------------------------
export default function ReportingPage() {
export default function ReportingPage({ filterDate }) {
const [findings, setFindings] = useState([]);
const [total, setTotal] = useState(null);
const [syncedAt, setSyncedAt] = useState(null);
@@ -574,7 +574,9 @@ export default function ReportingPage() {
const [syncing, setSyncing] = useState(false);
const [sort, setSort] = useState({ field: 'severity', dir: 'desc' });
const [columnOrder, setColumnOrder] = useState(loadColumnOrder);
const [columnFilters, setColumnFilters] = useState({});
const [columnFilters, setColumnFilters] = useState(() =>
filterDate ? { dueDate: new Set([filterDate]) } : {}
);
const [openFilter, setOpenFilter] = useState(null);
const filterBtnRefs = useRef({});