mirror of
https://github.com/usememos/memos.git
synced 2025-09-13 17:24:27 +08:00
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
This commit is contained in:
parent
8dbc63ed56
commit
83b771d5cd
4 changed files with 33 additions and 6 deletions
|
@ -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…
Add table
Reference in a new issue