365 lines
11 KiB
Markdown
365 lines
11 KiB
Markdown
|
|
# 🔄 Recurring Events Implementation
|
||
|
|
|
||
|
|
**Complete implementation of recurring events for your CalDAV calendar application**
|
||
|
|
|
||
|
|
## 🚀 Quick Start
|
||
|
|
|
||
|
|
The RecurrenceEditor component is **ready to use** in your application!
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
import { RecurrenceEditor } from '@/features/calendar/components/RecurrenceEditor';
|
||
|
|
|
||
|
|
function MyForm() {
|
||
|
|
const [recurrence, setRecurrence] = useState<IcsRecurrenceRule>();
|
||
|
|
|
||
|
|
return (
|
||
|
|
<RecurrenceEditor value={recurrence} onChange={setRecurrence} />
|
||
|
|
);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 📦 What's Included
|
||
|
|
|
||
|
|
### ✅ Complete Implementation
|
||
|
|
|
||
|
|
1. **RecurrenceEditor Component**
|
||
|
|
- Full UI for all recurrence types
|
||
|
|
- Date validation
|
||
|
|
- Multi-language support (EN/FR/NL)
|
||
|
|
|
||
|
|
2. **Styles (SCSS)**
|
||
|
|
- BEM methodology
|
||
|
|
- Responsive design
|
||
|
|
- Integrated with your design system
|
||
|
|
|
||
|
|
3. **Tests**
|
||
|
|
- 15+ test cases
|
||
|
|
- Full coverage
|
||
|
|
|
||
|
|
4. **Documentation**
|
||
|
|
- Implementation guide
|
||
|
|
- Integration guide
|
||
|
|
- Examples
|
||
|
|
- Troubleshooting
|
||
|
|
|
||
|
|
## 📚 Documentation Files
|
||
|
|
|
||
|
|
| File | Purpose |
|
||
|
|
|------|---------|
|
||
|
|
| **[README_RECURRENCE.md](./README_RECURRENCE.md)** | **👈 START HERE** - This file |
|
||
|
|
| [RECURRENCE_SUMMARY.md](./RECURRENCE_SUMMARY.md) | Quick reference & overview |
|
||
|
|
| [RECURRENCE_IMPLEMENTATION.md](./RECURRENCE_IMPLEMENTATION.md) | Complete technical docs |
|
||
|
|
| [SCHEDULER_RECURRENCE_INTEGRATION.md](./SCHEDULER_RECURRENCE_INTEGRATION.md) | How to integrate in Scheduler |
|
||
|
|
| [RECURRENCE_EXAMPLES.md](./RECURRENCE_EXAMPLES.md) | Real-world usage examples |
|
||
|
|
|
||
|
|
## 🎯 Supported Recurrence Patterns
|
||
|
|
|
||
|
|
| Type | Example | Status |
|
||
|
|
|------|---------|--------|
|
||
|
|
| **Daily** | Every day, every 3 days | ✅ Implemented |
|
||
|
|
| **Weekly** | Monday & Friday, every 2 weeks | ✅ Implemented |
|
||
|
|
| **Monthly** | 15th of each month | ✅ Implemented |
|
||
|
|
| **Yearly** | March 15th every year | ✅ Implemented |
|
||
|
|
| **End Conditions** | Never / Until date / After N times | ✅ Implemented |
|
||
|
|
| **Date Validation** | Feb 29, month lengths | ✅ Implemented |
|
||
|
|
|
||
|
|
## 📁 Project Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
src/frontend/apps/calendars/src/features/calendar/components/
|
||
|
|
├── RecurrenceEditor.tsx # Main component
|
||
|
|
├── RecurrenceEditor.scss # Styles
|
||
|
|
└── __tests__/
|
||
|
|
└── RecurrenceEditor.test.tsx # Tests
|
||
|
|
|
||
|
|
src/frontend/apps/calendars/src/features/i18n/
|
||
|
|
└── translations.json # Translations (EN/FR/NL)
|
||
|
|
|
||
|
|
Documentation (project root):
|
||
|
|
├── README_RECURRENCE.md # This file
|
||
|
|
├── RECURRENCE_SUMMARY.md # Quick reference
|
||
|
|
├── RECURRENCE_IMPLEMENTATION.md # Technical docs
|
||
|
|
├── SCHEDULER_RECURRENCE_INTEGRATION.md # Integration guide
|
||
|
|
└── RECURRENCE_EXAMPLES.md # Usage examples
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🔧 Integration Steps
|
||
|
|
|
||
|
|
### Step 1: Use the Component
|
||
|
|
|
||
|
|
The component is already created! Just import and use it:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
import { RecurrenceEditor } from '@/features/calendar/components/RecurrenceEditor';
|
||
|
|
import type { IcsRecurrenceRule } from 'ts-ics';
|
||
|
|
|
||
|
|
const [recurrence, setRecurrence] = useState<IcsRecurrenceRule | undefined>();
|
||
|
|
|
||
|
|
<RecurrenceEditor value={recurrence} onChange={setRecurrence} />
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 2: Include in IcsEvent
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
const event: IcsEvent = {
|
||
|
|
uid: crypto.randomUUID(),
|
||
|
|
summary: "Team Meeting",
|
||
|
|
start: { date: new Date() },
|
||
|
|
end: { date: new Date() },
|
||
|
|
recurrenceRule: recurrence, // ← Add this
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 3: That's It!
|
||
|
|
|
||
|
|
CalDAV handles everything else:
|
||
|
|
- ✅ Stores RRULE in .ics file
|
||
|
|
- ✅ Expands recurring instances
|
||
|
|
- ✅ Syncs with other calendar apps
|
||
|
|
|
||
|
|
## 🎨 UI Preview
|
||
|
|
|
||
|
|
### Simple Mode
|
||
|
|
```
|
||
|
|
┌────────────────────────────┐
|
||
|
|
│ Repeat: [Daily ▼] │
|
||
|
|
└────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### Custom Mode - Weekly
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ Repeat every [2] [weeks ▼] │
|
||
|
|
│ │
|
||
|
|
│ Repeat on: │
|
||
|
|
│ [M] [T] [W] [T] [F] [S] [S] │
|
||
|
|
│ ✓ ✓ │
|
||
|
|
│ │
|
||
|
|
│ Ends: │
|
||
|
|
│ ○ Never │
|
||
|
|
│ ○ On [2025-12-31] │
|
||
|
|
│ ⦿ After [10] occurrences │
|
||
|
|
└─────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### Custom Mode - Monthly with Warning
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ Repeat every [1] [months ▼] │
|
||
|
|
│ │
|
||
|
|
│ Repeat on day: │
|
||
|
|
│ Day [30] │
|
||
|
|
│ │
|
||
|
|
│ ⚠️ This month has at most 30 days │
|
||
|
|
└─────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🌍 Internationalization
|
||
|
|
|
||
|
|
Fully translated in:
|
||
|
|
- 🇬🇧 English
|
||
|
|
- 🇫🇷 French
|
||
|
|
- 🇳🇱 Dutch
|
||
|
|
|
||
|
|
All UI strings, month names, and warning messages.
|
||
|
|
|
||
|
|
## 🧪 Testing
|
||
|
|
|
||
|
|
Run the test suite:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
npm test RecurrenceEditor
|
||
|
|
```
|
||
|
|
|
||
|
|
Test coverage:
|
||
|
|
- ✅ Component rendering
|
||
|
|
- ✅ User interactions
|
||
|
|
- ✅ All frequency types
|
||
|
|
- ✅ Date validation
|
||
|
|
- ✅ End conditions
|
||
|
|
- ✅ Edge cases
|
||
|
|
|
||
|
|
## 📖 Common Use Cases
|
||
|
|
|
||
|
|
### 1. Daily Standup (Every Weekday)
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
{
|
||
|
|
frequency: 'WEEKLY',
|
||
|
|
byDay: [
|
||
|
|
{ day: 'MO' },
|
||
|
|
{ day: 'TU' },
|
||
|
|
{ day: 'WE' },
|
||
|
|
{ day: 'TH' },
|
||
|
|
{ day: 'FR' }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**RRULE:** `FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR`
|
||
|
|
|
||
|
|
### 2. Bi-Weekly Sprint Planning
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
{
|
||
|
|
frequency: 'WEEKLY',
|
||
|
|
interval: 2,
|
||
|
|
byDay: [{ day: 'MO' }],
|
||
|
|
count: 10
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**RRULE:** `FREQ=WEEKLY;INTERVAL=2;BYDAY=MO;COUNT=10`
|
||
|
|
|
||
|
|
### 3. Monthly Team Meeting (15th)
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
{
|
||
|
|
frequency: 'MONTHLY',
|
||
|
|
byMonthDay: [15]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**RRULE:** `FREQ=MONTHLY;BYMONTHDAY=15`
|
||
|
|
|
||
|
|
### 4. Annual Birthday
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
{
|
||
|
|
frequency: 'YEARLY',
|
||
|
|
byMonth: [3],
|
||
|
|
byMonthDay: [15]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**RRULE:** `FREQ=YEARLY;BYMONTH=3;BYMONTHDAY=15`
|
||
|
|
|
||
|
|
See [RECURRENCE_EXAMPLES.md](./RECURRENCE_EXAMPLES.md) for 10+ detailed examples!
|
||
|
|
|
||
|
|
## 🔍 Architecture
|
||
|
|
|
||
|
|
```
|
||
|
|
┌──────────────────────────────────────────────────┐
|
||
|
|
│ RecurrenceEditor Component (React) │
|
||
|
|
│ ↓ │
|
||
|
|
│ IcsRecurrenceRule (ts-ics) │
|
||
|
|
│ ↓ │
|
||
|
|
│ RRULE string (RFC 5545) │
|
||
|
|
│ ↓ │
|
||
|
|
│ .ics file (CalDAV) │
|
||
|
|
│ ↓ │
|
||
|
|
│ Sabre/dav Server (PHP) │
|
||
|
|
└──────────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
**No backend changes needed!** Everything is handled by CalDAV standard.
|
||
|
|
|
||
|
|
## 🎯 Next Steps
|
||
|
|
|
||
|
|
### To Use in Your App
|
||
|
|
|
||
|
|
1. Read [SCHEDULER_RECURRENCE_INTEGRATION.md](./SCHEDULER_RECURRENCE_INTEGRATION.md)
|
||
|
|
2. Follow the 5-step integration guide
|
||
|
|
3. Test with your event modal
|
||
|
|
|
||
|
|
### To Learn More
|
||
|
|
|
||
|
|
1. Browse [RECURRENCE_EXAMPLES.md](./RECURRENCE_EXAMPLES.md) for real-world scenarios
|
||
|
|
2. Check [RECURRENCE_IMPLEMENTATION.md](./RECURRENCE_IMPLEMENTATION.md) for deep dive
|
||
|
|
3. Review [RECURRENCE_SUMMARY.md](./RECURRENCE_SUMMARY.md) for quick reference
|
||
|
|
|
||
|
|
## ❓ FAQ
|
||
|
|
|
||
|
|
### Q: Does this work with existing CalDAV events?
|
||
|
|
|
||
|
|
**A:** Yes! The component uses standard RRULE format compatible with all CalDAV clients (Apple Calendar, Google Calendar, Outlook, etc.).
|
||
|
|
|
||
|
|
### Q: Can users edit existing recurring events?
|
||
|
|
|
||
|
|
**A:** Yes! The component loads existing recurrence rules from events and allows editing the entire series.
|
||
|
|
|
||
|
|
### Q: What about editing single instances?
|
||
|
|
|
||
|
|
**A:** Not yet implemented in UI. CalDAV supports it via RECURRENCE-ID, but the UI for "Edit this occurrence" vs "Edit series" is a future enhancement.
|
||
|
|
|
||
|
|
### Q: Do recurring events sync with other calendar apps?
|
||
|
|
|
||
|
|
**A:** Yes! All patterns are standard RFC 5545 RRULE format.
|
||
|
|
|
||
|
|
### Q: Can I create "First Monday of month" patterns?
|
||
|
|
|
||
|
|
**A:** Not yet. That requires BYSETPOS which is a future enhancement.
|
||
|
|
|
||
|
|
### Q: What happens with February 30th?
|
||
|
|
|
||
|
|
**A:** The UI shows a warning, and CalDAV will skip occurrences on invalid dates.
|
||
|
|
|
||
|
|
## 🐛 Troubleshooting
|
||
|
|
|
||
|
|
### Events not appearing as recurring
|
||
|
|
|
||
|
|
1. Check browser console for errors
|
||
|
|
2. Verify `recurrenceRule` is in IcsEvent object
|
||
|
|
3. Check CalDAV server supports RRULE
|
||
|
|
4. Inspect .ics file in network tab
|
||
|
|
|
||
|
|
### Translations not showing
|
||
|
|
|
||
|
|
1. Verify translations.json includes new keys
|
||
|
|
2. Check i18n is initialized
|
||
|
|
3. Reload page after adding translations
|
||
|
|
|
||
|
|
### Styles not applying
|
||
|
|
|
||
|
|
1. Ensure RecurrenceEditor.scss is imported in globals.scss
|
||
|
|
2. Check for CSS conflicts
|
||
|
|
3. Verify BEM class names
|
||
|
|
|
||
|
|
See [RECURRENCE_IMPLEMENTATION.md](./RECURRENCE_IMPLEMENTATION.md#troubleshooting) for more help.
|
||
|
|
|
||
|
|
## 📊 Feature Matrix
|
||
|
|
|
||
|
|
| Feature | Status | Notes |
|
||
|
|
|---------|--------|-------|
|
||
|
|
| Daily recurrence | ✅ | With interval |
|
||
|
|
| Weekly recurrence | ✅ | Multiple days |
|
||
|
|
| Monthly recurrence | ✅ | Day 1-31 |
|
||
|
|
| Yearly recurrence | ✅ | Month + day |
|
||
|
|
| Never ends | ✅ | |
|
||
|
|
| Until date | ✅ | |
|
||
|
|
| After N times | ✅ | |
|
||
|
|
| Date validation | ✅ | Feb 29, month lengths |
|
||
|
|
| Translations | ✅ | EN, FR, NL |
|
||
|
|
| Tests | ✅ | 15+ cases |
|
||
|
|
| nth occurrence | ❌ | Future (BYSETPOS) |
|
||
|
|
| Edit single instance | ❌ | Future (RECURRENCE-ID UI) |
|
||
|
|
|
||
|
|
## 🎓 Resources
|
||
|
|
|
||
|
|
- [RFC 5545 - iCalendar](https://datatracker.ietf.org/doc/html/rfc5545)
|
||
|
|
- [RRULE Spec](https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html)
|
||
|
|
- [ts-ics Library](https://github.com/Neuvernetzung/ts-ics)
|
||
|
|
- [Sabre/dav Docs](https://sabre.io/dav/)
|
||
|
|
|
||
|
|
## 🙏 Credits
|
||
|
|
|
||
|
|
Implementation follows RFC 5545 (iCalendar) standard and integrates with:
|
||
|
|
- ts-ics for ICS generation
|
||
|
|
- tsdav for CalDAV client
|
||
|
|
- @event-calendar/core for calendar UI
|
||
|
|
- Sabre/dav for CalDAV server
|
||
|
|
|
||
|
|
## 📝 License
|
||
|
|
|
||
|
|
Part of the calendars application.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🚀 Ready to Get Started?
|
||
|
|
|
||
|
|
1. **Quick integration:** Read [SCHEDULER_RECURRENCE_INTEGRATION.md](./SCHEDULER_RECURRENCE_INTEGRATION.md)
|
||
|
|
2. **See examples:** Check [RECURRENCE_EXAMPLES.md](./RECURRENCE_EXAMPLES.md)
|
||
|
|
3. **Deep dive:** Read [RECURRENCE_IMPLEMENTATION.md](./RECURRENCE_IMPLEMENTATION.md)
|
||
|
|
|
||
|
|
**The RecurrenceEditor is production-ready and waiting for you to integrate it!** 🎉
|