oxios 1.5.2

Oxios Agent OS — Agent Operating System powered by oxi-sdk
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Button } from '@/components/ui/button'
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Switch } from '@/components/ui/switch'
import { Textarea } from '@/components/ui/textarea'
import type {
  CalendarEvent,
  CreateEventRequest,
  RepeatRule,
  UpdateEventRequest,
} from '@/types/calendar'
import { ReminderEditor } from './reminder-editor'
import { RepeatEditor } from './repeat-editor'

interface Props {
  open: boolean
  onClose: () => void
  event?: CalendarEvent
  defaultStart?: Date
  onSubmit: (data: CreateEventRequest | UpdateEventRequest) => void
  isLoading?: boolean
}

/** Format a Date to a datetime-local input value string. */
function toDatetimeLocal(date: Date): string {
  const pad = (n: number) => String(n).padStart(2, '0')
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`
}

/** Parse a datetime-local value string back to an ISO string. */
function fromDatetimeLocal(value: string): string {
  return new Date(value).toISOString()
}

/** Default end time = start + 1 hour. */
function defaultEnd(start: Date): Date {
  const d = new Date(start)
  d.setHours(d.getHours() + 1)
  return d
}

export function EventEditor({ open, onClose, event, defaultStart, onSubmit, isLoading }: Props) {
  const { t } = useTranslation()
  const isEdit = !!event

  const [title, setTitle] = useState('')
  const [start, setStart] = useState('')
  const [end, setEnd] = useState('')
  const [allDay, setAllDay] = useState(false)
  const [description, setDescription] = useState('')
  const [location, setLocation] = useState('')
  const [repeat, setRepeat] = useState<RepeatRule | undefined>(undefined)
  const [reminders, setReminders] = useState<number[]>([])

  // Populate form when event changes or modal opens
  useEffect(() => {
    if (event) {
      setTitle(event.title)
      setStart(toDatetimeLocal(new Date(event.start)))
      setEnd(toDatetimeLocal(new Date(event.end)))
      setAllDay(event.all_day ?? false)
      setDescription(event.description ?? '')
      setLocation(event.location ?? '')
      setRepeat(undefined) // rrule is a raw string, not RepeatRule
      setReminders([]) // not stored on event directly
    } else {
      const startDate = defaultStart ?? new Date()
      setTitle('')
      setStart(toDatetimeLocal(startDate))
      setEnd(toDatetimeLocal(defaultEnd(startDate)))
      setAllDay(false)
      setDescription('')
      setLocation('')
      setRepeat(undefined)
      setReminders([])
    }
  }, [event, defaultStart, open])

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault()

    if (!title.trim() || !start || !end) return

    if (isEdit) {
      const data: UpdateEventRequest = {
        title: title.trim(),
        start: fromDatetimeLocal(start),
        end: fromDatetimeLocal(end),
        all_day: allDay,
        description: description.trim() || undefined,
        location: location.trim() || undefined,
        repeat: repeat ?? null,
        reminder_minutes: reminders.length > 0 ? reminders : undefined,
      }
      onSubmit(data)
    } else {
      const data: CreateEventRequest = {
        title: title.trim(),
        start: fromDatetimeLocal(start),
        end: fromDatetimeLocal(end),
        all_day: allDay,
        description: description.trim() || undefined,
        location: location.trim() || undefined,
        repeat,
        reminder_minutes: reminders.length > 0 ? reminders : undefined,
      }
      onSubmit(data)
    }
  }

  return (
    <Dialog open={open} onOpenChange={(o) => !o && onClose()}>
      <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>{isEdit ? t('calendar.editEvent') : t('calendar.createEvent')}</DialogTitle>
        </DialogHeader>

        <form onSubmit={handleSubmit} className="space-y-4">
          {/* Title */}
          <div className="space-y-2">
            <Label htmlFor="event-title">{t('calendar.titleLabel')}</Label>
            <Input
              id="event-title"
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder={t('calendar.titlePlaceholder')}
              required
              autoFocus
            />
          </div>

          {/* All day toggle */}
          <div className="flex items-center justify-between">
            <Label className="text-sm font-medium">{t('calendar.allDay')}</Label>
            <Switch checked={allDay} onCheckedChange={setAllDay} />
          </div>

          {/* Start / End */}
          <div className="grid grid-cols-2 gap-3">
            <div className="space-y-2">
              <Label htmlFor="event-start">{t('calendar.start')}</Label>
              <Input
                id="event-start"
                type={allDay ? 'date' : 'datetime-local'}
                value={start}
                onChange={(e) => setStart(e.target.value)}
                required
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="event-end">{t('calendar.end')}</Label>
              <Input
                id="event-end"
                type={allDay ? 'date' : 'datetime-local'}
                value={end}
                onChange={(e) => setEnd(e.target.value)}
                required
              />
            </div>
          </div>

          {/* Location */}
          <div className="space-y-2">
            <Label htmlFor="event-location">{t('calendar.location')}</Label>
            <Input
              id="event-location"
              value={location}
              onChange={(e) => setLocation(e.target.value)}
              placeholder={t('calendar.locationPlaceholder')}
            />
          </div>

          {/* Description */}
          <div className="space-y-2">
            <Label htmlFor="event-description">{t('calendar.description')}</Label>
            <Textarea
              id="event-description"
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              placeholder={t('calendar.descriptionPlaceholder')}
              rows={3}
            />
          </div>

          {/* Repeat */}
          <RepeatEditor value={repeat} onChange={setRepeat} />

          {/* Reminders */}
          <div className="space-y-2">
            <Label className="text-sm font-medium">{t('calendar.reminder')}</Label>
            <ReminderEditor value={reminders} onChange={setReminders} />
          </div>

          {/* Actions */}
          <DialogFooter>
            <Button type="button" variant="outline" onClick={onClose} disabled={isLoading}>
              {t('calendar.cancel')}
            </Button>
            <Button type="submit" disabled={isLoading || !title.trim() || !start || !end}>
              {isLoading
                ? t('calendar.processing')
                : isEdit
                  ? t('calendar.editEvent')
                  : t('calendar.createEvent')}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  )
}