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:
Vadim Sobinin
2026-02-02 17:37:06 +03:00
parent 4a273c336b
commit 7f7b33f4df
2 changed files with 65 additions and 12 deletions

View File

@@ -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>

View File

@@ -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)}