oxios 1.5.2

Oxios Agent OS — Agent Operating System powered by oxi-sdk
import { X } from 'lucide-react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Select } from '@/components/ui/select'
import { Switch } from '@/components/ui/switch'
import type { RepeatRule } from '@/types/calendar'

interface Props {
  value: RepeatRule | undefined
  onChange: (value: RepeatRule | undefined) => void
}

export function RepeatEditor({ value, onChange }: Props) {
  const { t } = useTranslation()
  const [expanded, setExpanded] = useState(!!value)

  const FREQUENCY_OPTIONS = [
    { label: t('calendar.freqDaily'), value: 'daily' },
    { label: t('calendar.freqWeekly'), value: 'weekly' },
    { label: t('calendar.freqMonthly'), value: 'monthly' },
    { label: t('calendar.freqYearly'), value: 'yearly' },
  ]

  const DAY_LABELS = [
    t('calendar.daySun'),
    t('calendar.dayMon'),
    t('calendar.dayTue'),
    t('calendar.dayWed'),
    t('calendar.dayThu'),
    t('calendar.dayFri'),
    t('calendar.daySat'),
  ]

  const handleToggle = (checked: boolean) => {
    setExpanded(checked)
    if (!checked) {
      onChange(undefined)
    } else if (!value) {
      onChange({ frequency: 'daily', interval: 1 })
    }
  }

  const updateRule = (partial: Partial<RepeatRule>) => {
    if (!value) return
    onChange({ ...value, ...partial })
  }

  const toggleDay = (dayLabel: string) => {
    if (!value) return
    const current = Array.isArray(value?.days) ? value.days : []
    const next = current.includes(dayLabel)
      ? current.filter((d) => d !== dayLabel)
      : [...current, dayLabel]
    updateRule({ days: next })
  }

  const handleClear = () => {
    setExpanded(false)
    onChange(undefined)
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <Label className="text-sm font-medium">{t('calendar.repeat')}</Label>
        <Switch checked={expanded} onCheckedChange={handleToggle} />
      </div>

      {expanded && value && (
        <div className="space-y-3 rounded-md border p-3">
          {/* Frequency */}
          <div className="flex items-center gap-3">
            <Label className="text-sm whitespace-nowrap">{t('calendar.frequency')}</Label>
            <Select
              value={value.frequency}
              onValueChange={(v) =>
                updateRule({
                  frequency: v as RepeatRule['frequency'],
                  days: v === 'weekly' ? ['mon'] : undefined,
                })
              }
              options={FREQUENCY_OPTIONS}
              className="flex-1"
            />
          </div>

          {/* Interval */}
          <div className="flex items-center gap-3">
            <Label className="text-sm whitespace-nowrap">{t('calendar.interval')}</Label>
            <Input
              type="number"
              min={1}
              max={99}
              value={value.interval ?? 1}
              onChange={(e) => updateRule({ interval: Math.max(1, Number(e.target.value)) })}
              className="w-20"
            />
            <span className="text-sm text-muted-foreground">{t('calendar.intervalSuffix')}</span>
          </div>

          {/* Weekly day selection */}
          {value.frequency === 'weekly' && (
            <div className="flex items-center gap-1">
              {DAY_LABELS.map((label) => {
                const dayKey = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'][
                  DAY_LABELS.indexOf(label)
                ]!
                const active = (value.days ?? []).includes(dayKey)
                return (
                  <button
                    key={dayKey}
                    type="button"
                    onClick={() => toggleDay(dayKey)}
                    className={`flex h-8 w-8 items-center justify-center rounded-md text-xs font-medium transition-colors ${
                      active
                        ? 'bg-primary text-primary-foreground'
                        : 'bg-muted text-muted-foreground hover:bg-accent'
                    }`}
                  >
                    {label}
                  </button>
                )
              })}
            </div>
          )}

          {/* Until / Count */}
          <div className="flex items-center gap-3">
            <Label className="text-sm whitespace-nowrap">{t('calendar.endCondition')}</Label>
            <div className="flex flex-1 items-center gap-2">
              <Input
                type="date"
                value={value.until ?? ''}
                onChange={(e) =>
                  updateRule({
                    until: e.target.value || undefined,
                    count: e.target.value ? undefined : value.count,
                  })
                }
                className="flex-1"
                placeholder={t('calendar.endDatePlaceholder')}
              />
              <span className="text-sm text-muted-foreground">{t('calendar.or')}</span>
              <Input
                type="number"
                min={1}
                max={999}
                value={value.count ?? ''}
                onChange={(e) =>
                  updateRule({
                    count: e.target.value ? Math.max(1, Number(e.target.value)) : undefined,
                    until: e.target.value ? undefined : value.until,
                  })
                }
                className="w-20"
                placeholder={t('calendar.countPlaceholder')}
              />
              <span className="text-sm text-muted-foreground">{t('calendar.countSuffix')}</span>
            </div>
          </div>

          {/* Clear */}
          <div className="flex justify-end">
            <Button type="button" variant="ghost" size="sm" onClick={handleClear}>
              <X className="mr-1 h-3 w-3" />
              {t('calendar.clearRepeat')}
            </Button>
          </div>
        </div>
      )}
    </div>
  )
}