import React, { useState, useRef, useEffect } from 'react' import ReactDOM from 'react-dom' import { Calendar, Clock, ChevronLeft, ChevronRight, ChevronUp, ChevronDown } from 'lucide-react' import { useTranslation } from '../../i18n' function daysInMonth(year, month) { return new Date(year, month + 1, 0).getDate() } function getWeekday(year, month, day) { return new Date(year, month, day).getDay() } // ── Datum-Only Picker ──────────────────────────────────────────────────────── export function CustomDatePicker({ value, onChange, placeholder, style = {} }) { const { locale, t } = useTranslation() const [open, setOpen] = useState(false) const ref = useRef(null) const dropRef = useRef(null) const parsed = value ? new Date(value + 'T00:00:00') : null const [viewYear, setViewYear] = useState(parsed?.getFullYear() || new Date().getFullYear()) const [viewMonth, setViewMonth] = useState(parsed?.getMonth() ?? new Date().getMonth()) useEffect(() => { const handler = (e) => { if (ref.current?.contains(e.target)) return if (dropRef.current?.contains(e.target)) return setOpen(false) } if (open) document.addEventListener('mousedown', handler) return () => document.removeEventListener('mousedown', handler) }, [open]) useEffect(() => { if (open && parsed) { setViewYear(parsed.getFullYear()); setViewMonth(parsed.getMonth()) } }, [open]) const prevMonth = () => { if (viewMonth === 0) { setViewMonth(11); setViewYear(y => y - 1) } else setViewMonth(m => m - 1) } const nextMonth = () => { if (viewMonth === 11) { setViewMonth(0); setViewYear(y => y + 1) } else setViewMonth(m => m + 1) } const monthLabel = new Date(viewYear, viewMonth).toLocaleDateString(locale, { month: 'long', year: 'numeric' }) const days = daysInMonth(viewYear, viewMonth) const startDay = (getWeekday(viewYear, viewMonth, 1) + 6) % 7 // Mo=0 const weekdays = Array.from({ length: 7 }, (_, i) => new Date(2024, 0, i + 1).toLocaleDateString(locale, { weekday: 'narrow' })) const displayValue = parsed ? parsed.toLocaleDateString(locale, { day: 'numeric', month: 'short', year: 'numeric' }) : null const selectDay = (day) => { const y = String(viewYear) const m = String(viewMonth + 1).padStart(2, '0') const d = String(day).padStart(2, '0') onChange(`${y}-${m}-${d}`) setOpen(false) } const selectedDay = parsed && parsed.getFullYear() === viewYear && parsed.getMonth() === viewMonth ? parsed.getDate() : null const today = new Date() const isToday = (d) => today.getFullYear() === viewYear && today.getMonth() === viewMonth && today.getDate() === d return (
{open && ReactDOM.createPortal(
{ const r = ref.current?.getBoundingClientRect() if (!r) return { top: 0, left: 0 } const w = 268, pad = 8 const vw = window.innerWidth const vh = window.innerHeight let left = r.left let top = r.bottom + 4 // Keep within viewport horizontally if (left + w > vw - pad) left = Math.max(pad, vw - w - pad) // If not enough space below, open above if (top + 320 > vh) top = Math.max(pad, r.top - 320) // On very small screens, center horizontally if (vw < 360) left = Math.max(pad, (vw - w) / 2) return { top, left } })(), zIndex: 99999, background: 'var(--bg-card)', border: '1px solid var(--border-primary)', borderRadius: 14, boxShadow: '0 8px 32px rgba(0,0,0,0.12)', padding: 12, width: 268, maxWidth: 'calc(100vw - 16px)', animation: 'selectIn 0.15s ease-out', backdropFilter: 'blur(24px)', WebkitBackdropFilter: 'blur(24px)', }}> {/* Month nav */}
{monthLabel}
{/* Weekday headers */}
{weekdays.map((d, i) => (
{d}
))}
{/* Days grid */}
{Array.from({ length: startDay }, (_, i) =>
)} {Array.from({ length: days }, (_, i) => { const d = i + 1 const sel = d === selectedDay const td = isToday(d) return ( ) })}
{/* Clear */} {value && (
)}
, document.body )}
) } // ── DateTime Picker (Datum + Uhrzeit kombiniert) ───────────────────────────── export function CustomDateTimePicker({ value, onChange, placeholder, style = {} }) { const { locale } = useTranslation() // value = "2024-03-15T14:30" oder "" const [datePart, timePart] = (value || '').split('T') const handleDateChange = (d) => { onChange(d ? `${d}T${timePart || '12:00'}` : '') } const handleTimeChange = (t) => { const d = datePart || new Date().toISOString().split('T')[0] onChange(t ? `${d}T${t}` : `${d}T00:00`) } return (
) } // Inline re-export for convenience import CustomTimePicker from './CustomTimePicker'