118 lines
4.2 KiB
TypeScript
118 lines
4.2 KiB
TypeScript
import React, { useState, useRef, useEffect } from 'react';
|
|
|
|
interface SettingsPopoverProps {
|
|
dayStart: string;
|
|
dayEnd: string;
|
|
wakeupRef: string;
|
|
bedtimeRef: string;
|
|
onSave: (settings: { dayStart: string; dayEnd: string; wakeupRef: string; bedtimeRef: string }) => void;
|
|
}
|
|
|
|
export function SettingsPopover({ dayStart, dayEnd, wakeupRef, bedtimeRef, onSave }: SettingsPopoverProps) {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [localDayStart, setLocalDayStart] = useState(dayStart);
|
|
const [localDayEnd, setLocalDayEnd] = useState(dayEnd);
|
|
const [localWakeupRef, setLocalWakeupRef] = useState(wakeupRef);
|
|
const [localBedtimeRef, setLocalBedtimeRef] = useState(bedtimeRef);
|
|
const popoverRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
setLocalDayStart(dayStart);
|
|
setLocalDayEnd(dayEnd);
|
|
setLocalWakeupRef(wakeupRef);
|
|
setLocalBedtimeRef(bedtimeRef);
|
|
}, [dayStart, dayEnd, wakeupRef, bedtimeRef]);
|
|
|
|
useEffect(() => {
|
|
const handleClickOutside = (e: MouseEvent) => {
|
|
if (popoverRef.current && !popoverRef.current.contains(e.target as Node)) {
|
|
setIsOpen(false);
|
|
}
|
|
};
|
|
if (isOpen) {
|
|
document.addEventListener('mousedown', handleClickOutside);
|
|
}
|
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
}, [isOpen]);
|
|
|
|
const handleSave = () => {
|
|
onSave({
|
|
dayStart: localDayStart,
|
|
dayEnd: localDayEnd,
|
|
wakeupRef: localWakeupRef,
|
|
bedtimeRef: localBedtimeRef,
|
|
});
|
|
setIsOpen(false);
|
|
};
|
|
|
|
return (
|
|
<div className="relative" ref={popoverRef}>
|
|
<button
|
|
onClick={() => setIsOpen(!isOpen)}
|
|
className="p-2 text-gray-500 hover:text-gray-700"
|
|
aria-label="Settings"
|
|
>
|
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
</svg>
|
|
</button>
|
|
|
|
{isOpen && (
|
|
<div className="absolute right-0 top-full mt-2 w-64 bg-white rounded-xl shadow-lg border border-gray-200 p-4 z-50">
|
|
<h4 className="font-semibold text-gray-800 mb-4">Settings</h4>
|
|
|
|
<div className="space-y-3">
|
|
<div>
|
|
<label htmlFor="day-start" className="block text-xs text-gray-500 mb-1">Day starts (HH:MM)</label>
|
|
<input
|
|
id="day-start"
|
|
type="time"
|
|
value={localDayStart}
|
|
onChange={(e) => setLocalDayStart(e.target.value)}
|
|
className="w-full p-2 border rounded-md text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label htmlFor="day-end" className="block text-xs text-gray-500 mb-1">Day ends (HH:MM)</label>
|
|
<input
|
|
id="day-end"
|
|
type="time"
|
|
value={localDayEnd}
|
|
onChange={(e) => setLocalDayEnd(e.target.value)}
|
|
className="w-full p-2 border rounded-md text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label htmlFor="wakeup-ref" className="block text-xs text-gray-500 mb-1">Wakeup ref (HH:MM)</label>
|
|
<input
|
|
id="wakeup-ref"
|
|
type="time"
|
|
value={localWakeupRef}
|
|
onChange={(e) => setLocalWakeupRef(e.target.value)}
|
|
className="w-full p-2 border rounded-md text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label htmlFor="bedtime-ref" className="block text-xs text-gray-500 mb-1">Bedtime ref (HH:MM)</label>
|
|
<input
|
|
id="bedtime-ref"
|
|
type="time"
|
|
value={localBedtimeRef}
|
|
onChange={(e) => setLocalBedtimeRef(e.target.value)}
|
|
className="w-full p-2 border rounded-md text-sm"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<button
|
|
onClick={handleSave}
|
|
className="w-full mt-4 py-2 bg-blue-600 text-white rounded-md text-sm font-medium hover:bg-blue-700"
|
|
>
|
|
Save
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
} |