A feature-rich calendar application built with Next.js, TypeScript, and Tailwind CSS. This project provides a modern, responsive interface for managing events and schedules with multiple viewing options.
-
π Multiple calendar views:
- Agenda view
- Year view
- Month view
- Week view with detailed time slots
- Day view with hourly breakdown
-
π¨ Event customization:
- Multiple color options for events
- Three badge display variants (dot, colored and mixed)
- Support for single and multi-day events
-
π Drag and Drop:
- Easily reschedule events by dragging and dropping
- Move events between days in month view
- Adjust event timing in week/day views
- Visual feedback during dragging operations
-
π₯ User management:
- Filter events by user
- View all users's events simultaneously
- User avatars and profile integration
-
β‘ Real-time features:
- Live time indicator
- Current event highlighting
- Dynamic event positioning
-
β° Time customization:
- Configurable working hours with distinct styling
- Adjustable visible hours range
- Focus on relevant time periods
-
π― UI/UX features:
- Responsive design for all screen sizes
- Intuitive navigation between dates
- Clean and modern interface
- Dark mode support
- Framework: Next.js 14
- Language: TypeScript
- Styling: Tailwind v3
- Date Management: date-fns
- UI Components: shadcn/ui
- State Management: React Context
- Clone the repository:
git clone https://github.com/yourusername/calendar-app.git
cd calendar-app
- Install dependencies:
npm install
- Start the development server:
npm run dev
or
npm run turbo
- Open your browser and navigate to
http://localhost:3000
to view the application.
The project structure is organized as follows:
src/
βββ app/
βββ calendar/ # All files related to calendar are in this folder
β βββ components/
β β βββ agenda-view/ # Agenda view components
β β βββ dialogs/ # Dialogs components
β β βββ dnd/ # Drag and drop components
β β βββ header/ # Calendar header components
β β βββ month-view/ # Month view components
β β βββ week-and-day-view/ # Week and day view components
β β βββ year-view/ # Year view components
β βββ contexts/ # Calendar context and state management
β βββ helpers/ # Utility functions
β βββ interfaces/ # TypeScript interfaces
β βββ types/ # TypeScript types
βββ components/ # Components not related to calendar eg: ui and layout components
- Copy the required folders to your project:
src/calendar/ # Core calendar functionality
src/components/ui/ # UI components used by the calendar
src/hooks/ # Required hooks like use-disclosure
- Install dependencies missing in your project
-
Set up the
CalendarProvider
Wrap your application or page with the
CalendarProvider
:
import { CalendarProvider } from "@/calendar/contexts/calendar-context";
// Fetch your events and users data
const events = await getEvents();
const users = await getUsers();
export default function Layout({ children }) {
return (
<CalendarProvider users={users} events={events}>
{children}
</CalendarProvider>
);
}
-
Add a
CalendarView
Use the
ClientContainer
to render a specific view:
import { ClientContainer } from "@/calendar/components/client-container";
export default function CalendarPage() {
return <ClientContainer view="month" />;
}
The calendar supports five different views, each can be used with the ClientContainer
component:
// Day view
<ClientContainer view="day" />
// Week view
<ClientContainer view="week" />
// Month view
<ClientContainer view="month" />
// Year view
<ClientContainer view="year" />
// Agenda view
<ClientContainer view="agenda" />
-
Events Format
Events should follow this interface (you can modify it as you want, but the calendar will expect these fields):
interface IEvent {
id: string;
title: string;
description: string;
startDate: string; // ISO string
endDate: string; // ISO string
color: "blue" | "green" | "red" | "yellow" | "purple" | "orange";
user: {
id: string;
name: string;
};
}
-
Users format
Users should follow this interface (you can modify it as you want, but the calendar will expect these fields):
interface IUser {
id: string;
name: string;
picturePath?: string; // Optional avatar image
}
-
Badge Variants
You can control the event display style with the
ChangeBadgeVariantInput
component:
import { ChangeBadgeVariantInput } from "@/calendar/components/change-badge-variant-input";
// Place this anywhere in your project tree inside the CalendarProvider
<ChangeBadgeVariantInput />;
-
Creating events
Implement your own event creation by modifying the
onSubmit
handler in theAddEventDialog
component.
You can access and control the calendar state from any component using the useCalendar
hook:
import { useCalendar } from "@/calendar/contexts/calendar-context";
function MyComponent() {
const { selectedDate, setSelectedDate, selectedUserId, setSelectedUserId, events, users, badgeVariant, setBadgeVariant } = useCalendar();
// Your component logic
}
// pages/calendar.tsx
import { CalendarProvider } from "@/calendar/contexts/calendar-context";
import { ClientContainer } from "@/calendar/components/client-container";
import { ChangeBadgeVariantInput } from "@/calendar/components/change-badge-variant-input";
export default function CalendarPage({ events, users }) {
return (
<CalendarProvider events={events} users={users}>
<div className="mx-auto flex max-w-screen-2xl flex-col gap-4 p-4">
<ClientContainer view="month" />
<ChangeBadgeVariantInput />
</div>
</CalendarProvider>
);
}
Contributions are welcome! Please feel free to submit a Pull Request.
Made by Leonardo Ramos π Get in touch!