DateTimePicker not working, textField not updating with selected hours and minutes

23 views Asked by At

I am developing a custom DatePicker using the moment.js library in React. However, I have noticed that the value of my TextField is not updated when I select a new hour and minute in the DatePicker.

import clsx from "clsx";
import moment from "moment";
import React, { useCallback, useMemo } from "react";
import { WiTime3 } from "react-icons/wi";
import { Popover, PopoverContent, PopoverTrigger, Timer } from "../../atoms";
import { TextField } from "../../forms";
import { timeFormat } from "../../util/time-helpers";

export interface TimePickerFieldProps {
  id: string;
  name: string;
  label?: string;
  className?: string;
  value?: moment.Moment;
  onChange: (time: moment.Moment) => void;
  onBlur?: () => void;
  error?: string;
  disabled?: boolean;
  align?: "start" | "center" | "end";
}

export const TimePickerField = React.forwardRef<
  HTMLInputElement,
  TimePickerFieldProps
>(
  (
    {
      id,
      name,
      onChange,
      align,
      className,
      disabled,
      error,
      label,
      onBlur,
      value,
    },
    ref
  ) => {
    const formattedValue = useMemo(
      () => (value ? timeFormat(value) : ""),
      [value]
    );

    const handleSelectTime = useCallback(
      (time?: moment.Moment) => {
        if (time) {
          onChange(time);
        }
      },
      [onChange]
    );

    const handleOpenChange = useCallback(
      (open: boolean) => {
        if (!open) {
          onBlur?.();
        }
      },
      [onBlur]
    );

    return (
      <Popover onOpenChange={handleOpenChange}>
        <PopoverTrigger className="block w-full">
          <TextField
            id={id}
            name={name}
            label={label}
            autoComplete="off"
            error={error}
            disabled={disabled}
            ref={ref}
            readOnly
            suffix={<WiTime3 className="text-primary" />}
            className={clsx("pointer-events-none", className)}
            value={formattedValue}
          />
        </PopoverTrigger>
        <PopoverContent align={align}>
          <Timer selected={value} onSelect={handleSelectTime} />
        </PopoverContent>
      </Popover>
    );
  }
);

import moment from "moment";
import { useState } from "react";
import { HourBar } from "./HourBar/HourBar";
import { MinuteBar } from "./MinuteBar/MinuteBar";

export interface TimerProps {
  selected?: moment.Moment | undefined;
  onSelect?: (time: moment.Moment) => void;
}

export const Timer: React.FC<TimerProps> = ({ onSelect, selected }) => {
  const [selectedTime, setSelectedTime] = useState<moment.Moment>(moment());

  const handleTimeChange = (field: "hour" | "minute", value: number) => {
    setSelectedTime((prevTime) => prevTime.clone().set(field, value));
  };

  return (
    <div>
      <div className="flex flex-row h-[7.75rem] w-[6.5rem] bg-other-transparent-darkest rounded p-2 gap-2">
        <HourBar
          selectedHour={selectedTime.hour()}
          onHourChange={handleTimeChange}
        />
        <MinuteBar
          selectedMinute={selectedTime.minute()}
          onMinuteChange={handleTimeChange}
        />
      </div>
    </div>
  );
};

import { Caption } from "../../../typography";

export interface HourBarProps {
  selectedHour: number;
  onHourChange: (field: "hour" | "minute", value: number) => void;
}

export const HourBar: React.FC<HourBarProps> = ({
  selectedHour,
  onHourChange,
}) => {
  const hours = Array.from({ length: 24 }, (_, i) => i);

  return (
    <div className="flex flex-col overflow-y-auto scrollbar-hide w-full items-center gap-1">
      {hours.map((hour, index) => (
        <Caption
          key={index}
          className={`flex justify-center rounded py-[0.125rem] size-full text-sm cursor-pointer 
        ${hour === selectedHour && "bg-primary text-font-primary"}`}
          onClick={() => onHourChange("hour", hour)}
        >
          {hour}
        </Caption>
      ))}
    </div>
  );
};

import { Caption } from "../../../typography";

export interface HourBarProps {
  selectedMinute: number;
  onMinuteChange: (field: "hour" | "minute", value: number) => void;
}

export const MinuteBar: React.FC<HourBarProps> = ({
  selectedMinute,
  onMinuteChange,
}) => {
  const minutes = Array.from({ length: 60 }, (_, i) => i);
  const filteredMinutes = minutes.filter((minute) => minute % 15 === 0);

  return (
    <div className="flex flex-col overflow-y-auto scrollbar-hide w-full items-center gap-1">
      {filteredMinutes.map((minute, index) => (
        <Caption
          key={index}
          className={`flex justify-center rounded py-[0.125rem] size-full text-sm cursor-pointer 
        ${minute === selectedMinute && "bg-primary text-font-primary"}`}
          onClick={() => onMinuteChange("minute", minute)}
        >
          {minute}
        </Caption>
      ))}
    </div>
  );
};

**Consultation: ** What could be causing the TextField value to not update correctly when selecting a new hour and minute in the DatePicker? Are there any additional steps I need to take to ensure the value is updated correctly in the UI?

Any suggestions or help would be greatly appreciated! Thank you very much in advance. When I select a new hour and minutes the value of the TextField is not updating

0

There are 0 answers