Files
experiments-database/frontend/src/App.jsx
T
Experiments DB Dev c8f0c5f298 feat: replace calendar day modal with dedicated day-view page
Calendar day clicks now navigate to /experiments/:id/day/:date
(with ?field= param). ExperimentDayView shows a sticky-column table
of all subjects with data that day, inline edit via modal, and a
session-metrics bar chart from analysis_summary. Subject name links
to /daily-statuses/:id. Backend adds ?date= filtering to
GET /experiments/:id/daily-statuses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:46:35 -04:00

71 lines
2.8 KiB
React

import React, { useEffect, useState } from 'react';
import { Routes, Route, Link, useLocation } from 'react-router-dom';
import { systemApi } from './api/client';
import Dashboard from './pages/Dashboard';
import ExperimentDetail from './pages/ExperimentDetail';
import AnimalDetail from './pages/AnimalDetail';
import DailyStatusDetail from './pages/DailyStatusDetail';
import ExperimentDayView from './pages/ExperimentDayView';
function Navbar() {
return (
<header className="bg-white border-b border-gray-200 sticky top-0 z-40">
<div className="max-w-5xl mx-auto px-4 h-14 flex items-center justify-between">
<Link to="/" className="flex items-center gap-2 font-bold text-gray-900 hover:text-blue-700 transition-colors">
<svg className="w-6 h-6 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
</svg>
Animal Experiments DB
</Link>
<nav className="text-sm text-gray-500">
<Link to="/" className="hover:text-blue-600 transition-colors">Dashboard</Link>
</nav>
</div>
</header>
);
}
function NotFound() {
return (
<div className="max-w-5xl mx-auto px-4 py-20 text-center">
<h1 className="text-4xl font-bold text-gray-300 mb-4">404</h1>
<p className="text-gray-500 mb-6">Page not found.</p>
<Link to="/" className="text-blue-600 hover:underline"> Return to Dashboard</Link>
</div>
);
}
function Footer() {
const [dbTimezone, setDbTimezone] = useState(null);
useEffect(() => {
systemApi.info().then((d) => setDbTimezone(d.dbTimezone)).catch(() => {});
}, []);
return (
<footer className="border-t border-gray-200 mt-12 py-3">
<div className="max-w-5xl mx-auto px-4 text-xs text-gray-400 text-right">
Database timezone: <span className="font-mono">{dbTimezone ?? '…'}</span>
</div>
</footer>
);
}
export default function App() {
return (
<div className="min-h-screen bg-gray-50 flex flex-col">
<Navbar />
<main className="flex-1">
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/experiments/:id" element={<ExperimentDetail />} />
<Route path="/experiments/:id/day/:date" element={<ExperimentDayView />} />
<Route path="/animals/:id" element={<AnimalDetail />} />
<Route path="/daily-statuses/:id" element={<DailyStatusDetail />} />
<Route path="*" element={<NotFound />} />
</Routes>
</main>
<Footer />
</div>
);
}