Fixes all 542 ESLint problems in the web package to achieve 0 errors and 0 warnings. Changes: - Fixed 144 issues: nullish coalescing, return types, unused variables - Fixed 118 issues: unnecessary conditions, type safety, template literals - Fixed 79 issues: non-null assertions, unsafe assignments, empty functions - Fixed 67 issues: explicit return types, promise handling, enum comparisons - Fixed 45 final warnings: missing return types, optional chains - Fixed 25 typecheck-related issues: async/await, type assertions, formatting - Fixed JSX.Element namespace errors across 90+ files All Quality Rails violations resolved. Lint and typecheck both pass with 0 problems. Files modified: 118 components, tests, hooks, and utilities Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import type { Event } from "@mosaic/shared";
|
|
import { EventCard } from "./EventCard";
|
|
import { getDateGroupLabel } from "@/lib/utils/date-format";
|
|
|
|
interface CalendarProps {
|
|
events: Event[];
|
|
isLoading: boolean;
|
|
}
|
|
|
|
export function Calendar({ events, isLoading }: CalendarProps): React.JSX.Element {
|
|
if (isLoading) {
|
|
return (
|
|
<div className="flex justify-center items-center p-8">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"></div>
|
|
<span className="ml-3 text-gray-600">Loading calendar...</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (events.length === 0) {
|
|
return (
|
|
<div className="text-center p-8 text-gray-500">
|
|
<p className="text-lg">No events scheduled</p>
|
|
<p className="text-sm mt-2">Your calendar is clear</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Group events by date
|
|
const groupedEvents = events.reduce<Record<string, Event[]>>((groups, event) => {
|
|
const label = getDateGroupLabel(event.startTime);
|
|
groups[label] ??= [] as Event[];
|
|
groups[label].push(event);
|
|
return groups;
|
|
}, {});
|
|
|
|
const groupOrder = ["Today", "Tomorrow", "This Week", "Next Week", "Later"];
|
|
|
|
return (
|
|
<main className="space-y-6">
|
|
{groupOrder.map((groupLabel) => {
|
|
const groupEvents = groupedEvents[groupLabel];
|
|
if (!groupEvents || groupEvents.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<section key={groupLabel}>
|
|
<h2 className="text-lg font-semibold text-gray-700 mb-3">{groupLabel}</h2>
|
|
<div className="space-y-2">
|
|
{groupEvents.map((event) => (
|
|
<EventCard key={event.id} event={event} />
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
})}
|
|
</main>
|
|
);
|
|
}
|