EN · DE · RU · FR · ES

#2654: DateInput.jsx

projectforge-webapp/src/components/design/input/calendar/DateInput.jsx Type : JavaScript/React · Rôle : Calendrier · Source : projectforge-webapp/src/components/design/input/calendar/DateInput.jsx 184 lignes · 159 code · 1 commentaire · 24 vides
Composant React de saisie de date/heure fournissant un sélecteur de calendrier, une plage de dates et un affichage formaté pour l'application web ProjectForge.

Structure du code

Hooks utilisés : Selector, Selector, Selector, State, State, State, Ref, Effect

Importations depuis : ../../../../utilities/propTypes, ../../popper/AdvancedPopper, ../AdditionalLabel, ../InputContainer, ./CalendarInput.module.scss, moment, prop-types, react, react-day-picker, react-day-picker/locale, react-redux

Possède PropTypes pour : DateInput

Utilise les modules CSS pour le style.

Code source (abrégé)

import moment from 'moment';
import 'moment/min/locales';
import PropTypes from 'prop-types';
import React from 'react';
import { DayPicker } from 'react-day-picker';
import { de } from 'react-day-picker/locale';
import { useSelector } from 'react-redux';
import { colorPropType } from '../../../../utilities/propTypes';
import AdvancedPopper from '../../popper/AdvancedPopper';
import AdditionalLabel from '../AdditionalLabel';
import InputContainer from '../InputContainer';
import styles from './CalendarInput.module.scss';

function DateInput(
    {
        additionalLabel,
        color,
        hideDayPicker = false,
        label,
        noInputContainer = false,
        setDate,
        todayButton,
        value,
    },
) {
    const jsDateFormat = useSelector((state) => state.authentication.user.jsDateFormat);
    const locale = useSelector((state) => state.authentication.user.locale) || 'en';
    const weekStartsOn = useSelector((state) => state.authentication.user.firstDayOfWeekSunday0);
    const [inputValue, setInputValue] = React.useState('');
    const [isActive, setIsActive] = React.useState(false);
    const [isOpen, setIsOpen] = React.useState(false);
    const inputRef = React.useRef(null);
    const Tag = noInputContainer ? React.Fragment : InputContainer;

    React.useEffect(() => {
        if (value) {
            setInputValue(moment(value)
                .format(jsDateFormat));
        } else {
            setInputValue('');
        }
    }, [value]);

    const handleBlur = () => {
        setIsActive(false);

        if (inputValue.trim() === '') {
            setDate(undefined);
            return;
        }

        const momentDate = moment(inputValue, jsDateFormat);

        if (momentDate.isValid()) {
            setDate(momentDate.toDate());
        } else {
            setInputValue(moment(value)
                .format(jsDateFormat));
        }
    };

    const handleChange = ({ target }) => {
        setInputValue(target.value);

        // Doit être strict, pour que moment ne corrige pas votre saisie à chaque frappe
        const momentDate = moment(target.value, jsDateFormat, true);

        if (momentDate.isValid()) {
            setDate(momentDate.toDate());
        }
    };

    const handleFocus = () => setIsActive(true);

    const handleKeyDown = (event) => {
        const momentDate = moment(inputValue, jsDateFormat, true);

        if (momentDate.isValid()) {
            let newDate;
            if (event.key === 'ArrowUp') {
                newDate = momentDate.add(1, 'd');
            } else if (event.key === 'ArrowDown') {
                newDate = momentDate.subtract(1, 'd');
            }

            if (newDate) {
                event.preventDefault();
                setDate(newDate.toDate());
            }
        }
    };

    const handleTagClick = () => {
        if (inputRef.current) {
            inputRef.current.focus();
        }
    };

    const tagProps = {};

    if (Tag !== React.Fragment) {
        tagProps.color = color;
        tagProps.isActive = isActive || inputValue !== '';
        tagProps.label = label;
        tagProps.onClick = handleTagClick;
        tagProps.withMargin = true;
    }

    const placeholder = jsDateFormat
        .split('')
        .filter((char, index) => index >= inputValue.length)
        .join('');

    const input = (
        <>
            <Tag {...tagProps}>
                <div className={styles.dateInput}>
                    {isActive && (
                        <span
                            className={styles.placeholder}
// ... (tronqué, total 184 lignes)

Historique Git

bf988bc6d Élimination de 43 vulnérabilités npm : react-scripts→Vite, ESLint 9, nettoyage des dépendances, corrections de bugs
ae4653957 correction du mois par défaut du champ date
95b5d879a DayPicker également en allemand.
f586d54a5 correction du premier jour de la semaine pour le daypicker
284e5d90f correction de la navigation mensuelle du day picker