add recurrence editor component
This commit is contained in:
@@ -4,26 +4,30 @@ export async function POST(request: Request) {
|
||||
const { prompt } = await request.json();
|
||||
|
||||
const systemPrompt = `
|
||||
You are an assistant that converts natural language requests into an ARRAY of JSON calendar events.
|
||||
TypeScript interface:
|
||||
You are an assistant that converts natural language into an ARRAY of calendar events.
|
||||
TypeScript type:
|
||||
|
||||
{
|
||||
id?: string,
|
||||
title: string,
|
||||
description?: string,
|
||||
location?: string,
|
||||
url?: string,
|
||||
start: string, // ISO datetime like 2024-06-14T13:00:00Z
|
||||
start: string, // ISO datetime
|
||||
end?: string,
|
||||
allDay?: boolean
|
||||
allDay?: boolean,
|
||||
recurrenceRule?: string // valid iCal RRULE string like FREQ=WEEKLY;BYDAY=MO;INTERVAL=1
|
||||
}[]
|
||||
|
||||
Rules:
|
||||
- If the user describes multiple events in one prompt, return multiple objects (one per event).
|
||||
- Always return a valid JSON array of objects, even if there's only one event.
|
||||
- Today is ${new Date().toLocaleString()}.
|
||||
- If no time is given, assume allDay event.
|
||||
- If no end time is given (and event is not allDay), default to 1 hour after start.
|
||||
Output ONLY valid JSON (no prose).
|
||||
- If the user describes multiple events in one prompt, return multiple objects (one per event).
|
||||
- Always return a valid JSON array of objects, even if there's only one event.
|
||||
- Today is ${new Date().toLocaleString()}.
|
||||
- If no time is given, assume allDay event.
|
||||
- If no end time is given (and event is not allDay), default to 1 hour after start.
|
||||
- If multiple events are described, return multiple.
|
||||
- If recurrence is implied (e.g. "every Monday", "daily for 10 days", "monthly on the 15th"), generate a recurrenceRule.
|
||||
- Output ONLY valid JSON (no prose).
|
||||
`;
|
||||
|
||||
const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Button } from '@/components/ui/button'
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Card } from '@/components/ui/card'
|
||||
import { RecurrencePicker } from '@/components/recurrence-picker'
|
||||
|
||||
import { addEvent, deleteEvent, getAllEvents, clearEvents, getDB } from '@/lib/db'
|
||||
import { parseICS, generateICS } from '@/lib/ical'
|
||||
@@ -25,7 +26,7 @@ export default function HomePage() {
|
||||
const [start, setStart] = useState('')
|
||||
const [end, setEnd] = useState('')
|
||||
const [allDay, setAllDay] = useState(false)
|
||||
const [recurrenceRule, setRecurrenceRule] = useState('')
|
||||
const [recurrenceRule, setRecurrenceRule] = useState<string | undefined>(undefined)
|
||||
|
||||
// AI
|
||||
const [aiPrompt, setAiPrompt] = useState('')
|
||||
@@ -58,7 +59,7 @@ export default function HomePage() {
|
||||
description,
|
||||
location,
|
||||
url,
|
||||
recurrenceRule: recurrenceRule || undefined,
|
||||
recurrenceRule,
|
||||
start,
|
||||
end: end || undefined,
|
||||
allDay,
|
||||
@@ -155,7 +156,7 @@ export default function HomePage() {
|
||||
setAllDay(ev.allDay || false)
|
||||
setEditingId(null)
|
||||
setDialogOpen(true)
|
||||
setRecurrenceRule(ev.recurrenceRule || '')
|
||||
setRecurrenceRule(ev.recurrenceRule || undefined)
|
||||
} else {
|
||||
// Save them all directly to DB
|
||||
for (const ev of data) {
|
||||
@@ -308,11 +309,8 @@ export default function HomePage() {
|
||||
value={description} onChange={e => setDescription(e.target.value)} />
|
||||
<Input placeholder="Location" value={location} onChange={e => setLocation(e.target.value)} />
|
||||
<Input placeholder="URL" value={url} onChange={e => setUrl(e.target.value)} />
|
||||
<Input
|
||||
placeholder="Recurrence rule (e.g. FREQ=WEEKLY;BYDAY=MO)"
|
||||
value={recurrenceRule}
|
||||
onChange={e => setRecurrenceRule(e.target.value)}
|
||||
/>
|
||||
<RecurrencePicker value={recurrenceRule} onChange={setRecurrenceRule} />
|
||||
|
||||
<label className="flex items-center gap-2 mt-2">
|
||||
<input type="checkbox" checked={allDay} onChange={e => setAllDay(e.target.checked)} />
|
||||
All day event
|
||||
|
||||
Reference in New Issue
Block a user