# Nuxt Calendar

[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![License][license-src]][license-href]
[![Nuxt][nuxt-src]][nuxt-href]

A powerful, production-ready calendar module for Nuxt 3 & 4 with comprehensive features for building modern calendar applications.

## ✨ Features

- 🎯 **Strongly Typed** - Full TypeScript support with comprehensive type definitions
- 🧩 **Modular Architecture** - Composable API design for maximum flexibility
- 🎨 **Highly Customizable** - Extensive configuration options for UI and behavior
- 🚀 **Best DX** - Auto-imported composables and components with full IDE support
- 🌍 **Internationalization** - Built-in i18n with `date-fns` locale support
- 🌐 **Timezone Support** - Full timezone handling with `date-fns-tz`
- 📅 **ICS Export** - Generate and download `.ics` files for calendar events
- 💾 **Database Sync** - Optional PostgreSQL integration via NuxtHub
- 🎯 **Multiple Views** - Day, week, and month calendar views
- ⚡ **Performance** - Optimized rendering with Vue 3 composition API
- 🎨 **Nuxt UI Integration** - Seamless integration with Nuxt UI components

## 📦 Installation

```bash
npx nuxi module add nuxt-calendar
```

Or install manually:

```bash
npm install nuxt-calendar
# or
pnpm add nuxt-calendar
# or
yarn add nuxt-calendar
```

## 🚀 Quick Start

Add the module to your `nuxt.config.ts`:

```ts
export default defineNuxtConfig({
  modules: ['nuxt-calendar'],
  
  NuxtCalendar: {
    // Optional configuration
    timeFormat: '24h',
    i18n: {
      locale: 'en',
      timezone: 'UTC',
      weekStartsOn: 1, // Monday
    },
    enableIcsExport: true,
    enableDatabaseSync: false,
  },
})
```

Use in your components:

```vue
<template>
  <NuxtCalendar 
    :events="events"
    :teams="teams"
    @event-click="handleEventClick"
  />
</template>

<script setup lang="ts">
const events = ref([
  {
    id: '1',
    title: 'Team Meeting',
    start: new Date('2024-01-15T10:00:00'),
    end: new Date('2024-01-15T11:00:00'),
    description: 'Weekly team sync',
    location: 'Conference Room A',
  },
])

function handleEventClick(event) {
  console.log('Event clicked:', event)
}
</script>
```

## 📖 Configuration

### Module Options

```ts
interface ModuleOptions {
  // License key for commercial features (optional)
  licenseKey?: string
  
  // Time format for display
  timeFormat?: '12h' | '24h'
  
  // Team/calendar configuration
  teams?: Team[]
  
  // Company branding
  company?: {
    name: string
    logo: string
  }
  
  // Internationalization settings
  i18n?: {
    locale: string           // 'en', 'nl', 'de', 'fr', etc.
    timezone: string         // IANA timezone identifier
    weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6  // 0 = Sunday, 1 = Monday
  }
  
  // Enable ICS file export functionality
  enableIcsExport?: boolean
  
  // Enable database sync with NuxtHub
  enableDatabaseSync?: boolean
}
```

### Default Configuration

```ts
{
  timeFormat: '24h',
  i18n: {
    locale: 'en',
    timezone: 'UTC',
    weekStartsOn: 1,
  },
  enableIcsExport: true,
  enableDatabaseSync: false,
}
```

## 🎯 Usage Examples

### Basic Calendar

```vue
<template>
  <NuxtCalendar :events="events" />
</template>

<script setup lang="ts">
const events = ref([
  {
    id: '1',
    title: 'Meeting',
    start: new Date(),
    end: new Date(Date.now() + 3600000),
  },
])
</script>
```

### With Teams

```vue
<template>
  <NuxtCalendar :events="events" :teams="teams" />
</template>

<script setup lang="ts">
const teams = ref([
  {
    id: 'dev-team',
    name: 'Development Team',
    members: [
      {
        id: 'user-1',
        name: 'John Doe',
        email: 'john@example.com',
        color: {
          background: '#34D399',
          border: '#10B981',
        },
        visible: true,
      },
    ],
  },
])
</script>
```

### ICS Export

```vue
<script setup lang="ts">
import { useCalendarIcs } from '#imports'

const { exportToIcs } = useCalendarIcs()

async function handleExport() {
  const result = await exportToIcs(events.value, 'my-calendar.ics')
  if (result.success) {
    console.log('Calendar exported successfully')
  }
}
</script>
```

### Database Sync

First, enable database sync in your config:

```ts
// nuxt.config.ts
export default defineNuxtConfig({
  NuxtCalendar: {
    enableDatabaseSync: true,
  },
})
```

Then use the composable:

```vue
<script setup lang="ts">
import { useCalendarDatabase } from '#imports'

const { fetchEvents, createEvent, updateEvent, deleteEvent } = useCalendarDatabase()

// Fetch events from database
const { events } = await fetchEvents()

// Create a new event
await createEvent({
  id: '1',
  title: 'New Meeting',
  start: new Date(),
  end: new Date(Date.now() + 3600000),
})

// Update an event
await updateEvent('1', {
  title: 'Updated Meeting Title',
})

// Delete an event
await deleteEvent('1')
</script>
```

### Timezone Support

```vue
<script setup lang="ts">
import { useCalendarI18n } from '#imports'

const { locale, timezone, formatDate, toLocalTimezone } = useCalendarI18n()

// Format date in configured timezone
const formattedDate = formatDate(new Date(), 'PPpp')

// Convert to local timezone
const localDate = toLocalTimezone(new Date())
</script>
```

## 🎨 Composables

### `useNuxtCalendarConfig()`

Access the calendar configuration:

```ts
const config = useNuxtCalendarConfig()
console.log(config.timeFormat) // '24h'
console.log(config.i18n.locale) // 'en'
```

### `useCalendarIcs()`

Export calendar events to ICS format:

```ts
const { exportToIcs, exportToIcsServer } = useCalendarIcs()

// Client-side export (downloads file)
await exportToIcs(events, 'calendar.ics')

// Server-side export (returns ICS data)
const { data } = await exportToIcsServer(events)
```

### `useCalendarDatabase()`

Sync calendar events with database:

```ts
const { fetchEvents, createEvent, updateEvent, deleteEvent } = useCalendarDatabase()

const result = await fetchEvents()
if (result.success) {
  console.log(result.events)
}
```

### `useCalendarI18n()`

Handle internationalization and timezones:

```ts
const { locale, timezone, weekStartsOn, formatDate, toLocalTimezone } = useCalendarI18n()

const formatted = formatDate(new Date(), 'yyyy-MM-dd HH:mm')
```

### `useCalendarSlotHeight()`

Manage calendar grid height:

```ts
const { hourHeight, getEventTop, getEventHeight } = useCalendarSlotHeight()
```

## 🌍 Supported Locales

The module supports all locales available in `date-fns`. Configure via:

```ts
NuxtCalendar: {
  i18n: {
    locale: 'en', // or 'nl', 'de', 'fr', 'es', 'it', 'pt', 'ja', 'zh', 'ko', 'ru', etc.
  },
}
```

## 🌐 Supported Timezones

Full IANA timezone database support including:

- UTC
- America/* (New_York, Los_Angeles, Chicago, etc.)
- Europe/* (London, Paris, Berlin, etc.)
- Asia/* (Tokyo, Shanghai, Dubai, etc.)
- Australia/* (Sydney, Melbourne, etc.)
- And many more...

## 📅 Event Types

```ts
interface CalendarEvent {
  id: string | number
  title: string
  start: Date
  end: Date
  description?: string
  location?: string
  organizer?: {
    name: string
    email: string
  }
  attendees?: Array<{
    name: string
    email: string
    rsvp?: boolean
  }>
  meetLink?: string
  category?: string
  teamMemberIds?: (string | number)[]
}
```

## 🔌 API Endpoints

When features are enabled, the module provides these endpoints:

### ICS Export (`enableIcsExport: true`)

- `POST /api/nuxt-calendar/export/ics` - Generate ICS file from events

### Database Sync (`enableDatabaseSync: true`)

- `GET /api/nuxt-calendar/events` - Fetch all events
- `POST /api/nuxt-calendar/events` - Create a new event
- `PUT /api/nuxt-calendar/events/:id` - Update an event
- `DELETE /api/nuxt-calendar/events/:id` - Delete an event

## 🎯 TypeScript Support

The module is fully typed with comprehensive TypeScript definitions. All types are auto-imported:

```ts
import type { 
  CalendarEvent,
  Team,
  TeamMember,
  View,
  SlotHeightConfig,
  NuxtCalendarPublicConfig,
} from '#imports'
```

## 🤝 Contributing

Contributions are welcome! Please see the [repository](https://github.com/dennisadriaans/nuxtcalendar.com) for more details.

## 📄 License

[MIT License](./LICENSE)

<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/nuxt-calendar/latest.svg?style=flat&colorA=020420&colorB=00DC82
[npm-version-href]: https://npmjs.com/package/nuxt-calendar

[npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-calendar.svg?style=flat&colorA=020420&colorB=00DC82
[npm-downloads-href]: https://npm.chart.dev/nuxt-calendar

[license-src]: https://img.shields.io/npm/l/nuxt-calendar.svg?style=flat&colorA=020420&colorB=00DC82
[license-href]: https://npmjs.com/package/nuxt-calendar

[nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
[nuxt-href]: https://nuxt.com
