Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function to format DatePanel dates #67

Merged
merged 1 commit into from
Sep 23, 2021

Conversation

juanruben
Copy link
Contributor

Pass as prop a function to DatePanel plugin in order to format each item

@juanruben juanruben changed the title Add function to format dates Add function to format DatePanel dates Sep 22, 2021
@shahabyazdi
Copy link
Owner

shahabyazdi commented Sep 22, 2021

Hi
Thank you for this PR.
Since all the dates in this package have a format method, instead of receiving the format function, we can take the format value and pass it as an argument to the format method of all the dates that are being rendered.

If your goal is the same as what I said, please modify that code and I will definitely merge it, otherwise please explain a bit about it.

Please read the comments I wrote with numbers 01 ~ 04:

import React from "react";
import DateObject from "react-date-object";
import getAllDatesInRange from "../../shared/getAllDatesInRange";
import isArray from "../../shared/isArray";
import getBorderClass from "../../shared/getBorderClass";
import getValidProps from "../../shared/getValidProps";
import getLocaleName from "../../shared/getLocaleName";
import "./date_panel.css";

export default function DatePanel({
  state,
  setState,
  position,
  nodes,
  handleChange,
  eachDaysInRange,
  sort,
  style = {},
  className = "",
  onClickDate,
  removeButton = true,
  header,
  markFocused,
  focusedClassName = "",
  handleFocusedDate,
  // 01- getting format value as a prop
  format = state.date._format,
  ...props
}) {
  let headers = { en: "Dates", fa: "تاریخ ها", ar: "تواریخ", hi: "खजूर" },
    dates = [],
    {
      multiple,
      range,
      inRangeDates,
      selectedDate,
      date: { locale },
    } = state,
    classNames = ["rmdp-panel", position, getBorderClass(position, nodes)];

  locale = locale.name.split("_")[1];

  if (multiple || (range && !eachDaysInRange)) {
    dates = (inRangeDates || selectedDate).map((date, index) => {
      return {
        date,
        // 02- passing format value as an argument to the format method
        format: date.format(format),
        index,
      };
    });
  } else if (range && eachDaysInRange) {
    let allDates = getAllDatesInRange(inRangeDates || selectedDate);

    dates = allDates.map((date, index) => {
      return {
        //in range mode
        //To find out which date is between the start and end date
        //We change its value to undefined
        date: index === 0 || index === allDates.length - 1 ? date : undefined,
        // 03- passing format value as an argument to the format method
        format: date.format(format),
        index,
      };
    });
  } else if (selectedDate && !isArray(selectedDate)) {
    dates = [
      {
        date: selectedDate,
        // 04- passing format value as an argument to the format method
        format: selectedDate.format(format),
        index: 0,
      },
    ];
  }

  if (multiple && sort === "date") dates.sort((a, b) => a.date - b.date);

  if (
    multiple &&
    sort === "color" &&
    dates.every((object) => object.date.color)
  ) {
    dates.sort((a, b) => {
      if (a.date.color < b.date.color) return -1;
      if (a.date.color > b.date.color) return 1;

      return 0;
    });
  }

  if (["fa", "ar"].includes(getLocaleName(locale))) {
    classNames.push("rmdp-rtl");
  }

  return (
    <div
      className={`${classNames.join(" ")} ${className}`}
      style={{
        display: "grid",
        gridTemplateRows: "auto 1fr",
        ...style,
      }}
      {...getValidProps(props)}
    >
      <div className="rmdp-panel-header">{header || headers[locale]}</div>
      <div
        style={{
          position: "relative",
          overflow: "auto",
          height: ["top", "bottom"].includes(position) ? "100px" : "",
        }}
      >
        <ul className="rmdp-panel-body">
          {isArray(dates) &&
            dates.map((object, index) => {
              return (
                <li
                  key={index}
                  className={`${
                    object.date?.color ? `bg-${object.date.color}` : ""
                  } ${
                    markFocused &&
                    object.date?.valueOf?.() === state.focused?.valueOf?.()
                      ? focusedClassName || "rmdp-focused"
                      : ""
                  }`}
                  onClick={() =>
                    !removeButton && selectDate(object.date, object.index)
                  }
                >
                  <span
                    onClick={() =>
                      removeButton && selectDate(object.date, object.index)
                    }
                    style={{ cursor: object.date ? "pointer" : "default" }}
                  >
                    {object.format}
                  </span>
                  {object.date && removeButton && (
                    <button
                      type="button"
                      className="b-deselect"
                      onClick={() => deSelect(object.index)}
                    >
                      +
                    </button>
                  )}
                </li>
              );
            })}
        </ul>
      </div>
    </div>
  );

  function selectDate(date, index) {
    handleClick(date ? selectedDate[index] : undefined);

    if (!date) return;

    setState({
      ...state,
      date: new DateObject(date),
      focused: selectedDate[index],
    });

    handleFocusedDate(selectedDate[index]);
  }

  function deSelect(index) {
    let dates, focused;

    if (range || multiple) {
      dates = selectedDate.filter((d, i) => i !== index);
      focused = dates.find((d) => d.valueOf() === state.focused?.valueOf?.());
    } else {
      dates = null;
      focused = undefined;
    }

    handleChange(dates, {
      ...state,
      selectedDate: dates,
      focused,
    });

    handleClick();
    handleFocusedDate(focused);
  }

  function handleClick(date) {
    if (onClickDate instanceof Function) onClickDate(date);
  }
}

@juanruben
Copy link
Contributor Author

juanruben commented Sep 22, 2021

Hi. Thanks for your response.

My goal is to use any format function to convert the dates to different locale settings.. I don't know if your proposal would allow that. For example, I use date-fns functions to many things and it would be nice to use its format function with your calendar component, or specifically within the DatePanel plugin renderer

@shahabyazdi shahabyazdi merged commit 9fb07a0 into shahabyazdi:develop Sep 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants