Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b949578
docs: Add comprehensive calendar suite reimplementation plan
claude Jan 4, 2026
c58b37d
docs: Revise calendar plan - no timetable changes, add migration details
claude Jan 4, 2026
c08332b
feat: Implement calendar v2 schemas and migration (Week 1 - Part 1)
claude Jan 4, 2026
1979601
feat: Complete Week 1 - Event fetching hooks and UI store
claude Jan 4, 2026
61d2c04
test: Add calendar v2 test components and routes
claude Jan 4, 2026
0009654
fix: TypeScript errors in calendar v2 implementation
claude Jan 4, 2026
71923a5
test: Add comprehensive Vitest test suite for Week 1 calendar impleme…
claude Jan 4, 2026
6f41c2f
feat: Implement Week 2 - Calendar utilities with RRULE and timezone s…
claude Jan 5, 2026
db59e7b
feat: Implement Week 3 - Calendar UI components
claude Jan 7, 2026
8acb8ee
feat: Implement Week 4 - Calendar view components (WeekView, MonthVie…
claude Jan 7, 2026
5f6b9a9
feat: Complete Week 4 - Event dialogs, forms, and CalendarApp integra…
claude Jan 8, 2026
8ecdffb
feat: Complete Week 5 - Performance testing infrastructure
claude Jan 8, 2026
f0d70c4
feat: Integrate CalendarPageV2 with v2 components into main calendar …
claude Jan 8, 2026
fb9a954
feat: Week 6-7 - Add drag-drop, search, sidebar to calendar v2
claude Jan 8, 2026
01cc23c
test: Add comprehensive tests for Week 6-7 calendar v2 features
claude Jan 8, 2026
5fbe7b9
fix: Resolve module import errors and add missing useCalendars hook
claude Jan 8, 2026
1b799b6
fix: Correct useCalendarEvents hook call signature in CalendarApp
claude Jan 8, 2026
6839073
fix: Update handleSaveEvent to use correct CreateEventParams interface
claude Jan 8, 2026
53141c4
fix: Replace allDay with isAllDay to match RxDB schema
claude Jan 8, 2026
2a17564
fix: Remove incorrect stopPropagation call on CalendarEvent
claude Jan 11, 2026
00e6736
fix: Resolve all TypeScript errors in calendar v2 implementation
ImJustChew Jan 11, 2026
ba1230f
fix: Ignore TypeScript build errors in Next.js config
ImJustChew Jan 12, 2026
23ade5e
fix: Use db.calendars and add lastModified timestamp
ImJustChew Jan 12, 2026
d25ff73
Add calendar v2 migrations and tests
ImJustChew Jan 14, 2026
6f4cfe1
feat: working calendar v2
ImJustChew Feb 2, 2026
cf482d8
feat(calendar): Major week view improvements matching Google Calendar…
ImJustChew Feb 25, 2026
ddaf8d6
feat(calendar): Add timetable auto-sync integration
ImJustChew Feb 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,487 changes: 1,487 additions & 0 deletions CALENDAR_MIGRATION_PLAN.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions apps/web/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ const nextConfig = {
// your project has ESLint errors.
ignoreDuringBuilds: true,
},
typescript: {
// NOTE: This ignores type errors during build. Only enable if you're confident
// your code is type-safe (e.g., run tsc separately in CI)
ignoreBuildErrors: true,
},
experimental: {
turbo: {
resolveAlias: {
Expand Down
18 changes: 15 additions & 3 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
"lint": "next lint --fix",
"type-check": "tsc --noEmit",
"clean": "rm -rf .next dist",
"gentype": "bunx supabase gen types typescript --project-id \"cmzdlrqfpuktcczvsobs\" --schema public > src/types/supabase.ts"
"gentype": "bunx supabase gen types typescript --project-id \"cmzdlrqfpuktcczvsobs\" --schema public > src/types/supabase.ts",
"test": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest --coverage"
},
"dependencies": {
"@courseweb/api-types": "*",
Expand Down Expand Up @@ -79,6 +82,7 @@
"react-turnstile": "^1.1.4",
"recharts": "^2.12.7",
"remark-gfm": "^4.0.1",
"rrule": "^2.8.1",
"rxdb": "^16.11.0",
"rxdb-hooks": "^5.0.2",
"rxjs": "^7.8.1",
Expand All @@ -93,10 +97,15 @@
"usehooks-ts": "^3.1.0",
"uuid": "^9.0.1",
"vaul": "^0.8.9",
"zod": "^3.22.4"
"zod": "^3.22.4",
"zustand": "^5.0.9"
},
"devDependencies": {
"@courseweb/eslint-config": "*",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.1",
"@testing-library/user-event": "^14.6.1",
"@types/jsdom": "^21.1.7",
"@types/jsonwebtoken": "^9.0.6",
"@types/leaflet": "^1.9.11",
Expand All @@ -107,11 +116,14 @@
"@types/react-dom": "18.3.0",
"@types/react-transition-group": "^4.4.10",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^5.1.2",
"eslint": "8.57.0",
"eslint-config-next": "14.2.26",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-unused-imports": "^4.1.3",
"prettier": "3.3.3"
"happy-dom": "^20.0.11",
"prettier": "3.3.3",
"vitest": "^4.0.16"
},
"eslintConfig": {
"extends": [
Expand Down
13 changes: 13 additions & 0 deletions apps/web/src/app/[lang]/(mods-pages)/calendar-test/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use client";
import { NextPage } from "next";
import { CalendarV2Test } from "@/components/Calendar/CalendarV2Test";

const CalendarTestPage: NextPage = () => {
return (
<div className="container mx-auto py-8">
<CalendarV2Test />
</div>
);
};

export default CalendarTestPage;
8 changes: 4 additions & 4 deletions apps/web/src/app/[lang]/(mods-pages)/calendar/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use client";
import { NextPage } from "next";
import CalendarPage from "@/components/Calendar/CalendarPage";
import CalendarPageV2 from "@/components/Calendar/CalendarPageV2";

const TodayPage: NextPage = () => {
return <CalendarPage />;
const CalendarPage: NextPage = () => {
return <CalendarPageV2 />;
};

export default TodayPage;
export default CalendarPage;
137 changes: 137 additions & 0 deletions apps/web/src/components/Calendar/CalendarErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* Error Boundary for Calendar
*
* Catches React errors in the calendar component tree and displays a fallback UI.
* Prevents the entire app from crashing if there's an error in the calendar.
*/

import { Component, ReactNode, ErrorInfo } from "react";
import { AlertTriangle, RefreshCcw } from "lucide-react";
import { Button } from "@courseweb/ui";

interface Props {
children: ReactNode;
fallback?: ReactNode;
}

interface State {
hasError: boolean;
error: Error | null;
errorInfo: ErrorInfo | null;
}

export class CalendarErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null,
};
}

static getDerivedStateFromError(error: Error): Partial<State> {
return {
hasError: true,
error,
};
}

componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error("[Calendar Error Boundary]:", error, errorInfo);

this.setState({
error,
errorInfo,
});

// TODO: Log to error tracking service (Sentry, etc.)
// logErrorToService(error, errorInfo);
}

handleReset = () => {
this.setState({
hasError: false,
error: null,
errorInfo: null,
});
};

handleReload = () => {
window.location.reload();
};

render() {
if (this.state.hasError) {
// Use custom fallback if provided
if (this.props.fallback) {
return this.props.fallback;
}

// Default error UI
return (
<div className="flex flex-col items-center justify-center h-full min-h-[400px] p-8 bg-gray-50 dark:bg-gray-900 rounded-lg">
<AlertTriangle className="w-16 h-16 text-red-500 mb-4" />

<h2 className="text-2xl font-semibold mb-2 text-gray-900 dark:text-gray-100">
Something went wrong
</h2>

<p className="text-gray-600 dark:text-gray-400 mb-6 text-center max-w-md">
{this.state.error?.message ||
"An unexpected error occurred in the calendar"}
</p>

<div className="flex gap-3">
<Button onClick={this.handleReset} variant="outline">
<RefreshCcw className="w-4 h-4 mr-2" />
Try Again
</Button>

<Button onClick={this.handleReload}>Reload Page</Button>
</div>

{process.env.NODE_ENV === "development" && this.state.errorInfo && (
<details className="mt-8 max-w-2xl w-full">
<summary className="cursor-pointer text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300">
Show error details
</summary>
<pre className="mt-4 p-4 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto max-h-64">
{this.state.error?.stack}
{"\n\n"}
{this.state.errorInfo.componentStack}
</pre>
</details>
)}
</div>
);
}

return this.props.children;
}
}

/**
* Hook-based error boundary for simpler use cases
*/
export function CalendarErrorFallback({
error,
resetError,
}: {
error: Error;
resetError: () => void;
}) {
return (
<div className="flex flex-col items-center justify-center h-full min-h-[200px] p-6">
<AlertTriangle className="w-12 h-12 text-red-500 mb-3" />
<h3 className="text-lg font-semibold mb-2">Error loading calendar</h3>
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4 text-center">
{error.message}
</p>
<Button onClick={resetError} size="sm" variant="outline">
<RefreshCcw className="w-3 h-3 mr-2" />
Retry
</Button>
</div>
);
}
Loading