feat: improve date handling in UI
- Change date format to DD/MM/YYYY in log list - Add prev/next day buttons in add log modal - Remember last selected date between modal opens
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { format, parseISO } from 'date-fns';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { format, parseISO, addDays, subDays } from 'date-fns';
|
||||
import type { TimeLog } from '../hooks/useLogs';
|
||||
|
||||
interface Props {
|
||||
@@ -16,12 +16,16 @@ function formatTimeForInput(hours: number, mins: number): string {
|
||||
return `${hours}:${String(mins).padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
// Store last used date outside component to persist between modal opens
|
||||
let lastUsedDate: string | null = null;
|
||||
|
||||
export function AddLogModal({ isOpen, onClose, onSave, editingLog }: Props) {
|
||||
const [date, setDate] = useState(format(new Date(), 'yyyy-MM-dd'));
|
||||
const [time, setTime] = useState('8');
|
||||
const [description, setDescription] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const initializedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
@@ -30,14 +34,25 @@ export function AddLogModal({ isOpen, onClose, onSave, editingLog }: Props) {
|
||||
setTime(formatTimeForInput(editingLog.hours, editingLog.mins));
|
||||
setDescription(editingLog.description);
|
||||
} else {
|
||||
setDate(format(new Date(), 'yyyy-MM-dd'));
|
||||
// Use last used date or today
|
||||
setDate(lastUsedDate || format(new Date(), 'yyyy-MM-dd'));
|
||||
setTime('8');
|
||||
setDescription('');
|
||||
}
|
||||
setError('');
|
||||
initializedRef.current = true;
|
||||
} else {
|
||||
initializedRef.current = false;
|
||||
}
|
||||
}, [isOpen, editingLog]);
|
||||
|
||||
// Save date when it changes (but not on initial load)
|
||||
useEffect(() => {
|
||||
if (initializedRef.current && !editingLog) {
|
||||
lastUsedDate = date;
|
||||
}
|
||||
}, [date, editingLog]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
@@ -59,6 +74,18 @@ export function AddLogModal({ isOpen, onClose, onSave, editingLog }: Props) {
|
||||
setTime(value);
|
||||
};
|
||||
|
||||
const handlePrevDay = () => {
|
||||
const currentDate = parseISO(date);
|
||||
setDate(format(subDays(currentDate, 1), 'yyyy-MM-dd'));
|
||||
};
|
||||
|
||||
const handleNextDay = () => {
|
||||
const currentDate = parseISO(date);
|
||||
setDate(format(addDays(currentDate, 1), 'yyyy-MM-dd'));
|
||||
};
|
||||
|
||||
const displayDate = format(parseISO(date), 'dd/MM/yyyy');
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||
<div className="bg-white rounded-lg p-6 w-full max-w-md mx-4">
|
||||
@@ -71,13 +98,40 @@ export function AddLogModal({ isOpen, onClose, onSave, editingLog }: Props) {
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Дата
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handlePrevDay}
|
||||
className="p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-md transition-colors"
|
||||
title="Предыдущий день"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
<div className="flex-1 relative">
|
||||
<input
|
||||
type="date"
|
||||
value={date}
|
||||
onChange={(e) => setDate(e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 opacity-0 absolute inset-0 cursor-pointer"
|
||||
required
|
||||
/>
|
||||
<div className="w-full px-3 py-2 border border-gray-300 rounded-md bg-white text-center font-medium cursor-pointer hover:bg-gray-50">
|
||||
{displayDate}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleNextDay}
|
||||
className="p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-md transition-colors"
|
||||
title="Следующий день"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { format, parseISO } from 'date-fns';
|
||||
import { ru } from 'date-fns/locale';
|
||||
import type { TimeLog } from '../hooks/useLogs';
|
||||
|
||||
interface Props {
|
||||
@@ -143,7 +142,7 @@ export function LogList({ logs, onDelete, onEdit, onUpdateTime, isLoading }: Pro
|
||||
<div key={dateKey} className="bg-white rounded-lg shadow-sm border">
|
||||
<div className="px-4 py-3 bg-gray-50 border-b flex justify-between items-center rounded-t-lg">
|
||||
<span className="font-medium text-gray-700">
|
||||
{format(parseISO(dateKey), 'd MMMM yyyy', { locale: ru })}
|
||||
{format(parseISO(dateKey), 'dd/MM/yyyy')}
|
||||
</span>
|
||||
<span className="text-sm text-gray-500">
|
||||
Всего: {formatTime(totalHours, totalMins)}
|
||||
|
||||
Reference in New Issue
Block a user