fix: disable selection of future dates in daily review section (#1983)

* #1952 Fix incorrect localization key for sign-up failure message

* feat: add typeScript support to enforce valid translation keys

* feat: add typeScript support to enforce valid translation keys

* fix lint errors

* fix lint error

* chore: Disallow destructuring 't' from useTranslation

This commit adds a linting rule to disallow the destructuring of the 't' property from the result of the useTranslation function call. The no-restricted-syntax rule in the ESLint configuration has been updated to enforce this restriction. The intention is to promote alternative approaches like using the useTranslate hook for localization.

* fix: typo fixed for memoChat

* fix: copy code button toast message

Refactored the code for the "Copy Code" button to utilize i18 strings for displaying the success message. Replaced the hard-coded value with the appropriate i18 string "Code copied successfully."

* fix: #1980 disable selection of future dates in daily review section
pull/1988/head
Ajay Kumbhare 2 years ago committed by GitHub
parent 8dbc63ed56
commit 83b771d5cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -3,20 +3,22 @@ import { useEffect, useState } from "react";
import { useTranslate } from "@/utils/i18n";
import { DAILY_TIMESTAMP } from "@/helpers/consts";
import { getMemoStats } from "@/helpers/api";
import { getDateStampByDate } from "@/helpers/datetime";
import { getDateStampByDate, isFutureDate } from "@/helpers/datetime";
import { useUserStore } from "@/store/module";
import classNames from "classnames";
import Icon from "../Icon";
import "@/less/common/date-picker.less";
interface DatePickerProps {
className?: string;
isFutureDateDisabled?: boolean;
datestamp: DateStamp;
handleDateStampChange: (datestamp: DateStamp) => void;
}
const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
const t = useTranslate();
const { className, datestamp, handleDateStampChange } = props;
const { className, isFutureDateDisabled, datestamp, handleDateStampChange } = props;
const [currentDateStamp, setCurrentDateStamp] = useState<DateStamp>(getMonthFirstDayDateStamp(datestamp));
const [countByDate, setCountByDate] = useState(new Map());
const currentUserId = useUserStore().getCurrentUserId();
@ -96,6 +98,7 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
</div>
{dayList.map((d) => {
const isDisabled = isFutureDateDisabled && isFutureDate(d.datestamp);
if (d.date === 0) {
return (
<span key={d.datestamp} className="day-item null">
@ -106,8 +109,8 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
return (
<span
key={d.datestamp}
className={`day-item relative ${d.datestamp === datestamp ? "current" : ""}`}
onClick={() => handleDateItemClick(d.datestamp)}
className={classNames(`day-item relative ${d.datestamp === datestamp ? "current" : ""}`, isDisabled && "disabled")}
onClick={() => (isDisabled ? null : handleDateItemClick(d.datestamp))}
>
{countByDate.has(d.datestamp) ? <Badge size="sm">{d.date}</Badge> : d.date}
</span>

@ -216,3 +216,16 @@ export function getUnixTime(t?: Date | number | string): number {
const date = new Date(t ? t : Date.now());
return Math.floor(date.getTime() / 1000);
}
/**
* Checks if the provided date or timestamp is in the future.
*
* If no date is provided, the current date is used.
*
* @param t - Date or timestamp to check.
* @returns `true` if the date is in the future, `false` otherwise.
*/
export function isFutureDate(t?: Date | number | string): boolean {
const timestamp = getTimeStampByDate(t ? t : Date.now());
return timestamp > Date.now();
}

@ -37,6 +37,10 @@
@apply text-blue-600 !bg-blue-100 text-base font-medium;
}
&.disabled {
@apply cursor-not-allowed;
}
&.null {
background-color: unset;
cursor: unset;

@ -13,8 +13,9 @@ import DatePicker from "@/components/kit/DatePicker";
import DailyMemo from "@/components/DailyMemo";
import i18n from "@/i18n";
import { findNearestLanguageMatch } from "@/utils/i18n";
import { convertToMillis, getDateStampByDate, getNormalizedDateString, getTimeStampByDate } from "@/helpers/datetime";
import { convertToMillis, getDateStampByDate, getNormalizedDateString, getTimeStampByDate, isFutureDate } from "@/helpers/datetime";
import Empty from "@/components/Empty";
import classNames from "classnames";
const DailyReview = () => {
const t = useTranslate();
@ -85,6 +86,7 @@ const DailyReview = () => {
const locale = findNearestLanguageMatch(i18n.language);
const currentMonth = currentDate.toLocaleDateString(locale, { month: "short" });
const currentDayOfWeek = currentDate.toLocaleDateString(locale, { weekday: "short" });
const isFutureDateDisabled = isFutureDate(currentDateStamp + DAILY_TIMESTAMP);
return (
<section className="w-full max-w-3xl min-h-full flex flex-col justify-start items-center px-4 sm:px-2 sm:pt-4 pb-8 bg-zinc-100 dark:bg-zinc-800">
@ -105,8 +107,12 @@ const DailyReview = () => {
<Icon.ChevronLeft className="w-full h-auto" />
</button>
<button
className="w-7 h-7 mr-2 flex justify-center items-center rounded cursor-pointer select-none last:mr-0 hover:bg-gray-200 dark:hover:bg-zinc-700 p-0.5"
className={classNames(
"w-7 h-7 mr-2 flex justify-center items-center rounded select-none last:mr-0 hover:bg-gray-200 dark:hover:bg-zinc-700 p-0.5",
isFutureDateDisabled ? "cursor-not-allowed" : "cursor-pointer"
)}
onClick={() => setCurrentDateStamp(currentDateStamp + DAILY_TIMESTAMP)}
disabled={isFutureDateDisabled}
>
<Icon.ChevronRight className="w-full h-auto" />
</button>
@ -123,6 +129,7 @@ const DailyReview = () => {
}`}
datestamp={currentDateStamp}
handleDateStampChange={handleDataPickerChange}
isFutureDateDisabled
/>
</div>
<div

Loading…
Cancel
Save