fix: merge conflicts resolved

This commit is contained in:
sriram veeraghanta 2024-03-19 18:00:43 +05:30
commit 473dfc7a5b
41 changed files with 317 additions and 219 deletions

View File

@ -72,7 +72,7 @@ export const EditorHeader = (props: IEditorHeader) => {
Icon={Archive} Icon={Archive}
backgroundColor="bg-blue-500/20" backgroundColor="bg-blue-500/20"
textColor="text-blue-500" textColor="text-blue-500"
label={`Archived at ${new Date(archivedAt).toLocaleString()}`} label={`Archived at ${archivedAt.toLocaleString()}`}
/> />
)} )}

View File

@ -52,14 +52,14 @@ export const InfoPopover: React.FC<Props> = (props) => {
<h6 className="text-xs text-custom-text-400">Last updated on</h6> <h6 className="text-xs text-custom-text-400">Last updated on</h6>
<h5 className="flex items-center gap-1 text-sm"> <h5 className="flex items-center gap-1 text-sm">
<History className="h-3 w-3" /> <History className="h-3 w-3" />
{renderDate(new Date(documentDetails.last_updated_at))} {renderDate(documentDetails.last_updated_at)}
</h5> </h5>
</div> </div>
<div className="space-y-1.5"> <div className="space-y-1.5">
<h6 className="text-xs text-custom-text-400">Created on</h6> <h6 className="text-xs text-custom-text-400">Created on</h6>
<h5 className="flex items-center gap-1 text-sm"> <h5 className="flex items-center gap-1 text-sm">
<Calendar className="h-3 w-3" /> <Calendar className="h-3 w-3" />
{renderDate(new Date(documentDetails.created_on))} {renderDate(documentDetails.created_on)}
</h5> </h5>
</div> </div>
</div> </div>

View File

@ -7,8 +7,8 @@ import { X } from "lucide-react";
// ui // ui
import { Button } from "@plane/ui"; import { Button } from "@plane/ui";
// helpers // helpers
import { renderFormattedPayloadDate, renderFormattedDate } from "helpers/date-time.helper";
import { DateFilterSelect } from "./date-filter-select"; import { DateFilterSelect } from "./date-filter-select";
import { renderFormattedPayloadDate, renderFormattedDate, getDate } from "helpers/date-time.helper";
type Props = { type Props = {
title: string; title: string;
@ -44,10 +44,10 @@ export const DateFilterModal: React.FC<Props> = ({ title, handleClose, isOpen, o
handleClose(); handleClose();
}; };
const date1 = watch("date1"); const date1 = getDate(watch("date1"));
const date2 = watch("date2"); const date2 = getDate(watch("date1"));
const isInvalid = watch("filterType") === "range" ? new Date(date1) > new Date(date2) : false; const isInvalid = watch("filterType") === "range" && date1 && date2 ? date1 > date2 : false;
return ( return (
<Transition.Root show={isOpen} as={Fragment}> <Transition.Root show={isOpen} as={Fragment}>
@ -90,37 +90,45 @@ export const DateFilterModal: React.FC<Props> = ({ title, handleClose, isOpen, o
<Controller <Controller
control={control} control={control}
name="date1" name="date1"
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => {
<DayPicker const dateValue = getDate(value);
selected={value ? new Date(value) : undefined} const date2Value = getDate(watch("date2"));
defaultMonth={value ? new Date(value) : undefined} return (
onSelect={(date) => {
if (!date) return;
onChange(date);
}}
mode="single"
disabled={[{ after: new Date(watch("date2")) }]}
className="border border-custom-border-200 p-3 rounded-md"
/>
)}
/>
{watch("filterType") === "range" && (
<Controller
control={control}
name="date2"
render={({ field: { value, onChange } }) => (
<DayPicker <DayPicker
selected={value ? new Date(value) : undefined} selected={dateValue}
defaultMonth={value ? new Date(value) : undefined} defaultMonth={dateValue}
onSelect={(date) => { onSelect={(date) => {
if (!date) return; if (!date) return;
onChange(date); onChange(date);
}} }}
mode="single" mode="single"
disabled={[{ before: new Date(watch("date1")) }]} disabled={date2Value ? [{ after: date2Value }] : undefined}
className="border border-custom-border-200 p-3 rounded-md" className="border border-custom-border-200 p-3 rounded-md"
/> />
)} );
}}
/>
{watch("filterType") === "range" && (
<Controller
control={control}
name="date2"
render={({ field: { value, onChange } }) => {
const dateValue = getDate(value);
const date1Value = getDate(watch("date1"));
return (
<DayPicker
selected={dateValue}
defaultMonth={dateValue}
onSelect={(date) => {
if (!date) return;
onChange(date);
}}
mode="single"
disabled={date1Value ? [{ before: date1Value }] : undefined}
className="border border-custom-border-200 p-3 rounded-md"
/>
);
}}
/> />
)} )}
</div> </div>

View File

@ -3,7 +3,7 @@ import { eachDayOfInterval, isValid } from "date-fns";
// ui // ui
import { LineGraph } from "components/ui"; import { LineGraph } from "components/ui";
// helpers // helpers
import { renderFormattedDateWithoutYear } from "helpers/date-time.helper"; import { getDate, renderFormattedDateWithoutYear } from "helpers/date-time.helper";
//types //types
import { TCompletionChartDistribution } from "@plane/types"; import { TCompletionChartDistribution } from "@plane/types";
@ -47,11 +47,11 @@ const ProgressChart: React.FC<Props> = ({ distribution, startDate, endDate, tota
})); }));
const generateXAxisTickValues = () => { const generateXAxisTickValues = () => {
const start = new Date(startDate); const start = getDate(startDate);
const end = new Date(endDate); const end = getDate(endDate);
let dates: Date[] = []; let dates: Date[] = [];
if (isValid(start) && isValid(end)) { if (start && end && isValid(start) && isValid(end)) {
dates = eachDayOfInterval({ start, end }); dates = eachDayOfInterval({ start, end });
} }

View File

@ -28,7 +28,12 @@ import { EmptyState } from "components/empty-state";
// icons // icons
import { ArrowRight, CalendarCheck, CalendarDays, Star, Target } from "lucide-react"; import { ArrowRight, CalendarCheck, CalendarDays, Star, Target } from "lucide-react";
// helpers // helpers
import { renderFormattedDate, findHowManyDaysLeft, renderFormattedDateWithoutYear } from "helpers/date-time.helper"; import {
renderFormattedDate,
findHowManyDaysLeft,
renderFormattedDateWithoutYear,
getDate,
} from "helpers/date-time.helper";
import { truncateText } from "helpers/string.helper"; import { truncateText } from "helpers/string.helper";
import { cn } from "helpers/common.helper"; import { cn } from "helpers/common.helper";
// types // types
@ -124,8 +129,8 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
); );
} }
const endDate = new Date(activeCycle.end_date ?? ""); const endDate = getDate(activeCycle.end_date);
const startDate = new Date(activeCycle.start_date ?? ""); const startDate = getDate(activeCycle.start_date);
const daysLeft = findHowManyDaysLeft(activeCycle.end_date) ?? 0; const daysLeft = findHowManyDaysLeft(activeCycle.end_date) ?? 0;
const cycleStatus = activeCycle.status.toLowerCase() as TCycleGroups; const cycleStatus = activeCycle.status.toLowerCase() as TCycleGroups;
@ -349,7 +354,11 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
buttonVariant="background-with-text" buttonVariant="background-with-text"
/> />
{issue.target_date && ( {issue.target_date && (
<Tooltip tooltipHeading="Target Date" tooltipContent={renderFormattedDate(issue.target_date)} isMobile={isMobile}> <Tooltip
tooltipHeading="Target Date"
tooltipContent={renderFormattedDate(issue.target_date)}
isMobile={isMobile}
>
<div className="flex h-full cursor-not-allowed items-center gap-1.5 rounded bg-custom-background-80 px-2 py-0.5 text-xs"> <div className="flex h-full cursor-not-allowed items-center gap-1.5 rounded bg-custom-background-80 px-2 py-0.5 text-xs">
<CalendarCheck className="h-3 w-3 flex-shrink-0" /> <CalendarCheck className="h-3 w-3 flex-shrink-0" />
<span className="text-xs">{renderFormattedDateWithoutYear(issue.target_date)}</span> <span className="text-xs">{renderFormattedDateWithoutYear(issue.target_date)}</span>

View File

@ -11,10 +11,12 @@ import { CycleQuickActions } from "components/cycles";
// ui // ui
// icons // icons
// helpers // helpers
import { findHowManyDaysLeft, getDate, renderFormattedDate } from "helpers/date-time.helper";
// import { copyTextToClipboard } from "helpers/string.helper";
// constants
import { CYCLE_STATUS } from "constants/cycle"; import { CYCLE_STATUS } from "constants/cycle";
import { CYCLE_FAVORITED, CYCLE_UNFAVORITED } from "constants/event-tracker"; import { CYCLE_FAVORITED, CYCLE_UNFAVORITED } from "constants/event-tracker";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserWorkspaceRoles } from "constants/workspace";
import { findHowManyDaysLeft, renderFormattedDate } from "helpers/date-time.helper";
// constants // constants
import { useEventTracker, useCycle, useUser, useMember } from "hooks/store"; import { useEventTracker, useCycle, useUser, useMember } from "hooks/store";
//.types //.types
@ -45,8 +47,9 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
if (!cycleDetails) return null; if (!cycleDetails) return null;
const cycleStatus = cycleDetails.status.toLocaleLowerCase(); const cycleStatus = cycleDetails.status.toLocaleLowerCase();
const endDate = new Date(cycleDetails.end_date ?? ""); // const isCompleted = cycleStatus === "completed";
const startDate = new Date(cycleDetails.start_date ?? ""); const endDate = getDate(cycleDetails.end_date);
const startDate = getDate(cycleDetails.start_date);
const isDateValid = cycleDetails.start_date || cycleDetails.end_date; const isDateValid = cycleDetails.start_date || cycleDetails.end_date;
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;

View File

@ -5,8 +5,8 @@ import { Button, Input, TextArea } from "@plane/ui";
import { DateRangeDropdown, ProjectDropdown } from "components/dropdowns"; import { DateRangeDropdown, ProjectDropdown } from "components/dropdowns";
// ui // ui
// helpers // helpers
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
import { shouldRenderProject } from "helpers/project.helper"; import { shouldRenderProject } from "helpers/project.helper";
import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
// types // types
import { ICycle } from "@plane/types"; import { ICycle } from "@plane/types";
@ -137,8 +137,8 @@ export const CycleForm: React.FC<Props> = (props) => {
className="h-7" className="h-7"
minDate={new Date()} minDate={new Date()}
value={{ value={{
from: startDateValue ? new Date(startDateValue) : undefined, from: getDate(startDateValue),
to: endDateValue ? new Date(endDateValue) : undefined, to: getDate(endDateValue),
}} }}
onSelect={(val) => { onSelect={(val) => {
onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null); onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null);

View File

@ -8,6 +8,7 @@ import { useCycle } from "hooks/store";
// components // components
// types // types
import { ICycle } from "@plane/types"; import { ICycle } from "@plane/types";
import { getDate } from "helpers/date-time.helper";
// constants // constants
type Props = { type Props = {
@ -41,8 +42,8 @@ export const CyclesListGanttChartView: FC<Props> = observer((props) => {
data: block, data: block,
id: block?.id ?? "", id: block?.id ?? "",
sort_order: block?.sort_order ?? 0, sort_order: block?.sort_order ?? 0,
start_date: new Date(block?.start_date ?? ""), start_date: getDate(block?.start_date),
target_date: new Date(block?.end_date ?? ""), target_date: getDate(block?.end_date),
})); }));
return structuredBlocks; return structuredBlocks;

View File

@ -7,9 +7,15 @@ import { usePlatformOS } from "hooks/use-platform-os";
import { Check, Info, Star, User2 } from "lucide-react"; import { Check, Info, Star, User2 } from "lucide-react";
import { Tooltip, CircularProgressIndicator, CycleGroupIcon, AvatarGroup, Avatar, setPromiseToast } from "@plane/ui"; import { Tooltip, CircularProgressIndicator, CycleGroupIcon, AvatarGroup, Avatar, setPromiseToast } from "@plane/ui";
import { CycleQuickActions } from "components/cycles"; import { CycleQuickActions } from "components/cycles";
// components
// import { CycleCreateUpdateModal, CycleDeleteModal } from "components/cycles";
// ui
// icons
// helpers
import { findHowManyDaysLeft, getDate, renderFormattedDate } from "helpers/date-time.helper";
// constants
import { CYCLE_STATUS } from "constants/cycle"; import { CYCLE_STATUS } from "constants/cycle";
import { CYCLE_FAVORITED, CYCLE_UNFAVORITED } from "constants/event-tracker"; import { CYCLE_FAVORITED, CYCLE_UNFAVORITED } from "constants/event-tracker";
import { findHowManyDaysLeft, renderFormattedDate } from "helpers/date-time.helper";
import { useEventTracker, useCycle, useUser, useMember } from "hooks/store"; import { useEventTracker, useCycle, useUser, useMember } from "hooks/store";
// components // components
// ui // ui
@ -119,8 +125,8 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
// TODO: change this logic once backend fix the response // TODO: change this logic once backend fix the response
const cycleStatus = cycleDetails.status ? (cycleDetails.status.toLocaleLowerCase() as TCycleGroups) : "draft"; const cycleStatus = cycleDetails.status ? (cycleDetails.status.toLocaleLowerCase() as TCycleGroups) : "draft";
const isCompleted = cycleStatus === "completed"; const isCompleted = cycleStatus === "completed";
const endDate = new Date(cycleDetails.end_date ?? ""); const endDate = getDate(cycleDetails.end_date);
const startDate = new Date(cycleDetails.start_date ?? ""); const startDate = getDate(cycleDetails.start_date);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;

View File

@ -18,12 +18,12 @@ import { CYCLE_STATUS } from "constants/cycle";
import { CYCLE_UPDATED } from "constants/event-tracker"; import { CYCLE_UPDATED } from "constants/event-tracker";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserWorkspaceRoles } from "constants/workspace";
// helpers // helpers
import { findHowManyDaysLeft, renderFormattedPayloadDate } from "helpers/date-time.helper";
import { copyUrlToClipboard } from "helpers/string.helper";
// hooks // hooks
import { useEventTracker, useCycle, useUser, useMember } from "hooks/store"; import { useEventTracker, useCycle, useUser, useMember } from "hooks/store";
// services // services
import { CycleService } from "services/cycle.service"; import { CycleService } from "services/cycle.service";
import { findHowManyDaysLeft, getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
import { copyUrlToClipboard } from "helpers/string.helper";
// types // types
import { ICycle } from "@plane/types"; import { ICycle } from "@plane/types";
@ -182,8 +182,11 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
const cycleStatus = cycleDetails?.status.toLocaleLowerCase(); const cycleStatus = cycleDetails?.status.toLocaleLowerCase();
const isCompleted = cycleStatus === "completed"; const isCompleted = cycleStatus === "completed";
const isStartValid = new Date(`${cycleDetails?.start_date}`) <= new Date(); const startDate = getDate(cycleDetails?.start_date);
const isEndValid = new Date(`${cycleDetails?.end_date}`) >= new Date(`${cycleDetails?.start_date}`); const endDate = getDate(cycleDetails?.end_date);
const isStartValid = startDate && startDate <= new Date();
const isEndValid = endDate && startDate && endDate >= startDate;
const progressPercentage = cycleDetails const progressPercentage = cycleDetails
? isCompleted && cycleDetails?.progress_snapshot ? isCompleted && cycleDetails?.progress_snapshot
@ -313,8 +316,8 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
buttonVariant="background-with-text" buttonVariant="background-with-text"
minDate={new Date()} minDate={new Date()}
value={{ value={{
from: startDateValue ? new Date(startDateValue) : undefined, from: getDate(startDateValue),
to: endDateValue ? new Date(endDateValue) : undefined, to: getDate(endDateValue),
}} }}
onSelect={(val) => { onSelect={(val) => {
onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null); onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null);

View File

@ -4,8 +4,8 @@ import { observer } from "mobx-react-lite";
// ui // ui
import { Avatar, AvatarGroup, ControlLink, PriorityIcon } from "@plane/ui"; import { Avatar, AvatarGroup, ControlLink, PriorityIcon } from "@plane/ui";
// helpers // helpers
import { findTotalDaysInRange, renderFormattedDate } from "helpers/date-time.helper";
import { useIssueDetail, useMember, useProject } from "hooks/store"; import { useIssueDetail, useMember, useProject } from "hooks/store";
import { findTotalDaysInRange, getDate, renderFormattedDate } from "helpers/date-time.helper";
// types // types
import { TIssue, TWidgetIssue } from "@plane/types"; import { TIssue, TWidgetIssue } from "@plane/types";
@ -34,6 +34,8 @@ export const AssignedUpcomingIssueListItem: React.FC<IssueListItemProps> = obser
const blockedByIssueProjectDetails = const blockedByIssueProjectDetails =
blockedByIssues.length === 1 ? getProjectById(blockedByIssues[0]?.project_id ?? "") : null; blockedByIssues.length === 1 ? getProjectById(blockedByIssues[0]?.project_id ?? "") : null;
const targetDate = getDate(issueDetails.target_date);
return ( return (
<ControlLink <ControlLink
href={`/${workspaceSlug}/projects/${issueDetails.project_id}/issues/${issueDetails.id}`} href={`/${workspaceSlug}/projects/${issueDetails.project_id}/issues/${issueDetails.id}`}
@ -48,11 +50,7 @@ export const AssignedUpcomingIssueListItem: React.FC<IssueListItemProps> = obser
<h6 className="text-sm flex-grow truncate">{issueDetails.name}</h6> <h6 className="text-sm flex-grow truncate">{issueDetails.name}</h6>
</div> </div>
<div className="text-xs text-center"> <div className="text-xs text-center">
{issueDetails.target_date {targetDate ? (isToday(targetDate) ? "Today" : renderFormattedDate(targetDate)) : "-"}
? isToday(new Date(issueDetails.target_date))
? "Today"
: renderFormattedDate(issueDetails.target_date)
: "-"}
</div> </div>
<div className="text-xs text-center"> <div className="text-xs text-center">
{blockedByIssues.length > 0 {blockedByIssues.length > 0
@ -83,7 +81,7 @@ export const AssignedOverdueIssueListItem: React.FC<IssueListItemProps> = observ
const blockedByIssueProjectDetails = const blockedByIssueProjectDetails =
blockedByIssues.length === 1 ? getProjectById(blockedByIssues[0]?.project_id ?? "") : null; blockedByIssues.length === 1 ? getProjectById(blockedByIssues[0]?.project_id ?? "") : null;
const dueBy = findTotalDaysInRange(new Date(issueDetails.target_date ?? ""), new Date(), false) ?? 0; const dueBy = findTotalDaysInRange(getDate(issueDetails.target_date), new Date(), false) ?? 0;
return ( return (
<ControlLink <ControlLink
@ -212,7 +210,7 @@ export const CreatedOverdueIssueListItem: React.FC<IssueListItemProps> = observe
const projectDetails = getProjectById(issue.project_id); const projectDetails = getProjectById(issue.project_id);
const dueBy = findTotalDaysInRange(new Date(issue.target_date ?? ""), new Date(), false) ?? 0; const dueBy = findTotalDaysInRange(getDate(issue.target_date), new Date(), false) ?? 0;
return ( return (
<ControlLink <ControlLink

View File

@ -3,14 +3,14 @@ import { DayPicker, Matcher } from "react-day-picker";
import { usePopper } from "react-popper"; import { usePopper } from "react-popper";
import { Combobox } from "@headlessui/react"; import { Combobox } from "@headlessui/react";
import { CalendarDays, X } from "lucide-react"; import { CalendarDays, X } from "lucide-react";
// hooks // helpers
import { cn } from "helpers/common.helper"; import { cn } from "helpers/common.helper";
import { renderFormattedDate } from "helpers/date-time.helper"; import { renderFormattedDate, getDate } from "helpers/date-time.helper";
// hooks
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down"; import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
import useOutsideClickDetector from "hooks/use-outside-click-detector"; import useOutsideClickDetector from "hooks/use-outside-click-detector";
// components // components
import { DropdownButton } from "./buttons"; import { DropdownButton } from "./buttons";
// helpers
// types // types
import { BUTTON_VARIANTS_WITH_TEXT } from "./constants"; import { BUTTON_VARIANTS_WITH_TEXT } from "./constants";
import { TDropdownProps } from "./types"; import { TDropdownProps } from "./types";
@ -168,8 +168,8 @@ export const DateDropdown: React.FC<Props> = (props) => {
{...attributes.popper} {...attributes.popper}
> >
<DayPicker <DayPicker
selected={value ? new Date(value) : undefined} selected={getDate(value)}
defaultMonth={value ? new Date(value) : undefined} defaultMonth={getDate(value)}
onSelect={(date) => { onSelect={(date) => {
dropdownOnChange(date ?? null); dropdownOnChange(date ?? null);
}} }}

View File

@ -2,7 +2,7 @@ import { useState, FC } from "react";
// ui // ui
import { Button } from "@plane/ui"; import { Button } from "@plane/ui";
// helpers // helpers
import { renderFormattedDate } from "helpers/date-time.helper"; import { getDate, renderFormattedDate } from "helpers/date-time.helper";
// types // types
import { IExportData } from "@plane/types"; import { IExportData } from "@plane/types";
@ -18,7 +18,8 @@ export const SingleExport: FC<Props> = ({ service, refreshing }) => {
const checkExpiry = (inputDateString: string) => { const checkExpiry = (inputDateString: string) => {
const currentDate = new Date(); const currentDate = new Date();
const expiryDate = new Date(inputDateString); const expiryDate = getDate(inputDateString);
if (!expiryDate) return false;
expiryDate.setDate(expiryDate.getDate() + 7); expiryDate.setDate(expiryDate.getDate() + 7);
return expiryDate > currentDate; return expiryDate > currentDate;
}; };

View File

@ -64,9 +64,9 @@ export const ChartViewRoot: FC<ChartViewRootProps> = observer((props) => {
useGanttChart(); useGanttChart();
// rendering the block structure // rendering the block structure
const renderBlockStructure = (view: any, blocks: IGanttBlock[] | null) => const renderBlockStructure = (view: ChartDataType, blocks: IGanttBlock[] | null) =>
blocks blocks
? blocks.map((block: any) => ({ ? blocks.map((block: IGanttBlock) => ({
...block, ...block,
position: getMonthChartItemPositionWidthInMonth(view, block), position: getMonthChartItemPositionWidthInMonth(view, block),
})) }))

View File

@ -6,8 +6,8 @@ export interface IGanttBlock {
width: number; width: number;
}; };
sort_order: number; sort_order: number;
start_date: Date | null; start_date: Date | undefined;
target_date: Date | null; target_date: Date | undefined;
} }
export interface IBlockUpdateData { export interface IBlockUpdateData {

View File

@ -1,5 +1,6 @@
// types // types
import { weeks, months } from "../data"; import { weeks, months } from "../data";
import { findTotalDaysInRange } from "helpers/date-time.helper";
import { ChartDataType, IGanttBlock } from "../types"; import { ChartDataType, IGanttBlock } from "../types";
// data // data
// helpers // helpers
@ -167,15 +168,16 @@ export const getMonthChartItemPositionWidthInMonth = (chartData: ChartDataType,
const { startDate } = chartData.data; const { startDate } = chartData.data;
const { start_date: itemStartDate, target_date: itemTargetDate } = itemData; const { start_date: itemStartDate, target_date: itemTargetDate } = itemData;
if (!itemStartDate || !itemTargetDate) return null; if (!itemStartDate || !itemTargetDate) return;
startDate.setHours(0, 0, 0, 0); startDate.setHours(0, 0, 0, 0);
itemStartDate.setHours(0, 0, 0, 0); itemStartDate.setHours(0, 0, 0, 0);
itemTargetDate.setHours(0, 0, 0, 0); itemTargetDate.setHours(0, 0, 0, 0);
// position code starts const positionDaysDifference = findTotalDaysInRange(startDate, itemStartDate, false);
const positionTimeDifference: number = startDate.getTime() - itemStartDate.getTime();
const positionDaysDifference: number = Math.abs(Math.floor(positionTimeDifference / (1000 * 60 * 60 * 24))); if (!positionDaysDifference) return;
scrollPosition = positionDaysDifference * chartData.data.width; scrollPosition = positionDaysDifference * chartData.data.width;
let diffMonths = (itemStartDate.getFullYear() - startDate.getFullYear()) * 12; let diffMonths = (itemStartDate.getFullYear() - startDate.getFullYear()) * 12;

View File

@ -20,6 +20,8 @@ import { EUserProjectRoles } from "constants/project";
import { useUser, useInboxIssues, useIssueDetail, useWorkspace, useEventTracker } from "hooks/store"; import { useUser, useInboxIssues, useIssueDetail, useWorkspace, useEventTracker } from "hooks/store";
// types // types
import type { TInboxDetailedStatus } from "@plane/types"; import type { TInboxDetailedStatus } from "@plane/types";
//helpers
import { getDate } from "helpers/date-time.helper";
type TInboxIssueActionsHeader = { type TInboxIssueActionsHeader = {
workspaceSlug: string; workspaceSlug: string;
@ -168,11 +170,11 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER; const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const today = new Date(); const today = new Date();
const tomorrow = new Date(today); const tomorrow = getDate(today);
tomorrow.setDate(today.getDate() + 1); tomorrow?.setDate(today.getDate() + 1);
useEffect(() => { useEffect(() => {
if (!issueStatus || !issueStatus.snoozed_till) return; if (!issueStatus || !issueStatus.snoozed_till) return;
setDate(new Date(issueStatus.snoozed_till)); setDate(issueStatus.snoozed_till);
}, [issueStatus]); }, [issueStatus]);
if (!issueStatus || !issue || !inboxIssues) return <></>; if (!issueStatus || !issue || !inboxIssues) return <></>;
@ -266,19 +268,23 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
{({ close }) => ( {({ close }) => (
<div className="flex h-full w-full flex-col gap-y-1"> <div className="flex h-full w-full flex-col gap-y-1">
<DayPicker <DayPicker
selected={date ? new Date(date) : undefined} selected={getDate(date)}
defaultMonth={date ? new Date(date) : undefined} defaultMonth={getDate(date)}
onSelect={(date) => { onSelect={(date) => {
if (!date) return; if (!date) return;
setDate(date); setDate(date);
}} }}
mode="single" mode="single"
className="rounded-md border border-custom-border-200 p-3" className="border border-custom-border-200 rounded-md p-3"
disabled={[ disabled={
{ tomorrow
before: tomorrow, ? [
}, {
]} before: tomorrow,
},
]
: undefined
}
/> />
<Button <Button
variant="primary" variant="primary"
@ -286,7 +292,7 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
close(); close();
inboxIssueOperations.updateInboxIssueStatus({ inboxIssueOperations.updateInboxIssueStatus({
status: 0, status: 0,
snoozed_till: new Date(date), snoozed_till: date,
}); });
}} }}
> >

View File

@ -28,7 +28,7 @@ export const InboxIssueStatus: React.FC<Props> = observer((props) => {
if (!inboxIssueStatusDetail) return <></>; if (!inboxIssueStatusDetail) return <></>;
const isSnoozedDatePassed = const isSnoozedDatePassed =
inboxIssueDetail.status === 0 && new Date(inboxIssueDetail.snoozed_till ?? "") < new Date(); inboxIssueDetail.status === 0 && !!inboxIssueDetail.snoozed_till && inboxIssueDetail.snoozed_till < new Date();
return ( return (
<div <div
@ -46,7 +46,7 @@ export const InboxIssueStatus: React.FC<Props> = observer((props) => {
workspaceSlug, workspaceSlug,
projectId, projectId,
inboxIssueDetail.duplicate_to ?? "", inboxIssueDetail.duplicate_to ?? "",
new Date(inboxIssueDetail.snoozed_till ?? "") inboxIssueDetail.snoozed_till
) )
) : ( ) : (
<span>{inboxIssueStatusDetail.title}</span> <span>{inboxIssueStatusDetail.title}</span>

View File

@ -8,8 +8,8 @@ import { DateDropdown, PriorityDropdown, MemberDropdown, StateDropdown } from "c
import { IssueLabel, TIssueOperations } from "components/issues"; import { IssueLabel, TIssueOperations } from "components/issues";
// icons // icons
// helper // helper
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
import { useIssueDetail, useProject, useProjectState } from "hooks/store"; import { useIssueDetail, useProject, useProjectState } from "hooks/store";
import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
type Props = { type Props = {
workspaceSlug: string; workspaceSlug: string;
@ -33,7 +33,7 @@ export const InboxIssueDetailsSidebar: React.FC<Props> = observer((props) => {
const projectDetails = issue ? getProjectById(issue.project_id) : null; const projectDetails = issue ? getProjectById(issue.project_id) : null;
const minDate = issue.start_date ? new Date(issue.start_date) : null; const minDate = issue.start_date ? getDate(issue.start_date) : null;
minDate?.setDate(minDate.getDate()); minDate?.setDate(minDate.getDate());
const currentIssueState = projectStates?.find((s) => s.id === issue.state_id); const currentIssueState = projectStates?.find((s) => s.id === issue.state_id);

View File

@ -41,15 +41,17 @@ import {
IssueLabel, IssueLabel,
ArchiveIssueModal, ArchiveIssueModal,
} from "components/issues"; } from "components/issues";
// helpers
import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
import { copyTextToClipboard } from "helpers/string.helper";
import { cn } from "helpers/common.helper";
import { shouldHighlightIssueDueDate } from "helpers/issue.helper";
// types
import type { TIssueOperations } from "./root";
import { STATE_GROUPS } from "constants/state"; import { STATE_GROUPS } from "constants/state";
// types // types
import { cn } from "helpers/common.helper";
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "helpers/issue.helper";
import { copyTextToClipboard } from "helpers/string.helper";
import { useEstimate, useIssueDetail, useProject, useProjectState, useUser } from "hooks/store"; import { useEstimate, useIssueDetail, useProject, useProjectState, useUser } from "hooks/store";
// components // components
import type { TIssueOperations } from "./root";
import { IssueSubscription } from "./subscription"; import { IssueSubscription } from "./subscription";
// icons // icons
// helpers // helpers
@ -112,10 +114,10 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
const isInArchivableGroup = const isInArchivableGroup =
!!stateDetails && [STATE_GROUPS.completed.key, STATE_GROUPS.cancelled.key].includes(stateDetails?.group); !!stateDetails && [STATE_GROUPS.completed.key, STATE_GROUPS.cancelled.key].includes(stateDetails?.group);
const minDate = issue.start_date ? new Date(issue.start_date) : null; const minDate = issue.start_date ? getDate(issue.start_date) : null;
minDate?.setDate(minDate.getDate()); minDate?.setDate(minDate.getDate());
const maxDate = issue.target_date ? new Date(issue.target_date) : null; const maxDate = issue.target_date ? getDate(issue.target_date) : null;
maxDate?.setDate(maxDate.getDate()); maxDate?.setDate(maxDate.getDate());
return ( return (

View File

@ -12,6 +12,8 @@ import { ICycleIssuesFilter } from "store/issue/cycle";
import { IModuleIssuesFilter } from "store/issue/module"; import { IModuleIssuesFilter } from "store/issue/module";
import { IProjectIssuesFilter } from "store/issue/project"; import { IProjectIssuesFilter } from "store/issue/project";
import { IProjectViewIssuesFilter } from "store/issue/project-views"; import { IProjectViewIssuesFilter } from "store/issue/project-views";
// helpers
import { getDate } from "helpers/date-time.helper";
interface Props { interface Props {
issuesFilterStore: IProjectIssuesFilter | IModuleIssuesFilter | ICycleIssuesFilter | IProjectViewIssuesFilter; issuesFilterStore: IProjectIssuesFilter | IModuleIssuesFilter | ICycleIssuesFilter | IProjectViewIssuesFilter;
@ -47,8 +49,10 @@ export const CalendarMonthsDropdown: React.FC<Props> = observer((props: Props) =
const daysList = Object.keys(allDaysOfActiveWeek); const daysList = Object.keys(allDaysOfActiveWeek);
const firstDay = new Date(daysList[0]); const firstDay = getDate(daysList[0]);
const lastDay = new Date(daysList[daysList.length - 1]); const lastDay = getDate(daysList[daysList.length - 1]);
if (!firstDay || !lastDay) return "Week view";
if (firstDay.getMonth() === lastDay.getMonth() && firstDay.getFullYear() === lastDay.getFullYear()) if (firstDay.getMonth() === lastDay.getMonth() && firstDay.getFullYear() === lastDay.getFullYear())
return `${MONTHS_LIST[firstDay.getMonth() + 1].title} ${firstDay.getFullYear()}`; return `${MONTHS_LIST[firstDay.getMonth() + 1].title} ${firstDay.getFullYear()}`;

View File

@ -14,15 +14,19 @@ import {
CycleDropdown, CycleDropdown,
StateDropdown, StateDropdown,
} from "components/dropdowns"; } from "components/dropdowns";
// helpers
import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
import { cn } from "helpers/common.helper";
// types
import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types";
// constants
import { ISSUE_UPDATED } from "constants/event-tracker"; import { ISSUE_UPDATED } from "constants/event-tracker";
import { EIssuesStoreType } from "constants/issue"; import { EIssuesStoreType } from "constants/issue";
import { cn } from "helpers/common.helper";
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "helpers/issue.helper"; import { shouldHighlightIssueDueDate } from "helpers/issue.helper";
import { useEventTracker, useEstimate, useLabel, useIssues, useProjectState } from "hooks/store"; import { useEventTracker, useEstimate, useLabel, useIssues, useProjectState } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os"; import { usePlatformOS } from "hooks/use-platform-os";
// components // components
import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types";
import { IssuePropertyLabels } from "../properties/labels"; import { IssuePropertyLabels } from "../properties/labels";
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC"; import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
// helpers // helpers
@ -242,10 +246,10 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
const defaultLabelOptions = issue?.label_ids?.map((id) => labelMap[id]) || []; const defaultLabelOptions = issue?.label_ids?.map((id) => labelMap[id]) || [];
const minDate = issue.start_date ? new Date(issue.start_date) : null; const minDate = getDate(issue.start_date);
minDate?.setDate(minDate.getDate()); minDate?.setDate(minDate.getDate());
const maxDate = issue.target_date ? new Date(issue.target_date) : null; const maxDate = getDate(issue.target_date);
maxDate?.setDate(maxDate.getDate()); maxDate?.setDate(maxDate.getDate());
return ( return (
@ -297,7 +301,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
<DateDropdown <DateDropdown
value={issue.start_date ?? null} value={issue.start_date ?? null}
onChange={handleStartDate} onChange={handleStartDate}
maxDate={maxDate ?? undefined} maxDate={maxDate}
placeholder="Start date" placeholder="Start date"
icon={<CalendarClock className="h-3 w-3 flex-shrink-0" />} icon={<CalendarClock className="h-3 w-3 flex-shrink-0" />}
buttonVariant={issue.start_date ? "border-with-text" : "border-without-text"} buttonVariant={issue.start_date ? "border-with-text" : "border-without-text"}
@ -313,7 +317,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
<DateDropdown <DateDropdown
value={issue?.target_date ?? null} value={issue?.target_date ?? null}
onChange={handleTargetDate} onChange={handleTargetDate}
minDate={minDate ?? undefined} minDate={minDate}
placeholder="Due date" placeholder="Due date"
icon={<CalendarCheck2 className="h-3 w-3 flex-shrink-0" />} icon={<CalendarCheck2 className="h-3 w-3 flex-shrink-0" />}
buttonVariant={issue.target_date ? "border-with-text" : "border-without-text"} buttonVariant={issue.target_date ? "border-with-text" : "border-without-text"}

View File

@ -6,9 +6,9 @@ import { CalendarCheck2 } from "lucide-react";
import { DateDropdown } from "components/dropdowns"; import { DateDropdown } from "components/dropdowns";
// helpers // helpers
import { cn } from "helpers/common.helper"; import { cn } from "helpers/common.helper";
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "helpers/issue.helper";
import { useProjectState } from "hooks/store"; import { useProjectState } from "hooks/store";
import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "helpers/issue.helper";
// types // types
import { TIssue } from "@plane/types"; import { TIssue } from "@plane/types";
@ -30,7 +30,7 @@ export const SpreadsheetDueDateColumn: React.FC<Props> = observer((props: Props)
<div className="h-11 border-b-[0.5px] border-custom-border-200"> <div className="h-11 border-b-[0.5px] border-custom-border-200">
<DateDropdown <DateDropdown
value={issue.target_date} value={issue.target_date}
minDate={issue.start_date ? new Date(issue.start_date) : undefined} minDate={getDate(issue.start_date)}
onChange={(data) => { onChange={(data) => {
const targetDate = data ? renderFormattedPayloadDate(data) : null; const targetDate = data ? renderFormattedPayloadDate(data) : null;
onChange( onChange(

View File

@ -4,7 +4,7 @@ import { CalendarClock } from "lucide-react";
// components // components
import { DateDropdown } from "components/dropdowns"; import { DateDropdown } from "components/dropdowns";
// helpers // helpers
import { renderFormattedPayloadDate } from "helpers/date-time.helper"; import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
// types // types
import { TIssue } from "@plane/types"; import { TIssue } from "@plane/types";
@ -22,7 +22,7 @@ export const SpreadsheetStartDateColumn: React.FC<Props> = observer((props: Prop
<div className="h-11 border-b-[0.5px] border-custom-border-200"> <div className="h-11 border-b-[0.5px] border-custom-border-200">
<DateDropdown <DateDropdown
value={issue.start_date} value={issue.start_date}
maxDate={issue.target_date ? new Date(issue.target_date) : undefined} maxDate={getDate(issue.target_date)}
onChange={(data) => { onChange={(data) => {
const startDate = data ? renderFormattedPayloadDate(data) : null; const startDate = data ? renderFormattedPayloadDate(data) : null;
onChange( onChange(

View File

@ -21,7 +21,6 @@ import {
import { ParentIssuesListModal } from "components/issues"; import { ParentIssuesListModal } from "components/issues";
import { IssueLabelSelect } from "components/issues/select"; import { IssueLabelSelect } from "components/issues/select";
import { CreateLabelModal } from "components/labels"; import { CreateLabelModal } from "components/labels";
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
import { useApplication, useEstimate, useIssueDetail, useMention, useProject, useWorkspace } from "hooks/store"; import { useApplication, useEstimate, useIssueDetail, useMention, useProject, useWorkspace } from "hooks/store";
// services // services
import { AIService } from "services/ai.service"; import { AIService } from "services/ai.service";
@ -31,6 +30,7 @@ import { FileService } from "services/file.service";
// helpers // helpers
import { getChangedIssuefields } from "helpers/issue.helper"; import { getChangedIssuefields } from "helpers/issue.helper";
import { shouldRenderProject } from "helpers/project.helper"; import { shouldRenderProject } from "helpers/project.helper";
import { renderFormattedPayloadDate, getDate } from "helpers/date-time.helper";
// types // types
import type { TIssue, ISearchIssueResponse } from "@plane/types"; import type { TIssue, ISearchIssueResponse } from "@plane/types";
@ -242,10 +242,10 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
const startDate = watch("start_date"); const startDate = watch("start_date");
const targetDate = watch("target_date"); const targetDate = watch("target_date");
const minDate = startDate ? new Date(startDate) : null; const minDate = getDate(startDate);
minDate?.setDate(minDate.getDate()); minDate?.setDate(minDate.getDate());
const maxDate = targetDate ? new Date(targetDate) : null; const maxDate = getDate(targetDate);
maxDate?.setDate(maxDate.getDate()); maxDate?.setDate(maxDate.getDate());
const projectDetails = getProjectById(projectId); const projectDetails = getProjectById(projectId);

View File

@ -14,6 +14,7 @@ import {
// hooks // hooks
// ui icons // ui icons
import { DiceIcon, DoubleCircleIcon, UserGroupIcon, ContrastIcon, RelatedIcon } from "@plane/ui"; import { DiceIcon, DoubleCircleIcon, UserGroupIcon, ContrastIcon, RelatedIcon } from "@plane/ui";
// components
import { DateDropdown, EstimateDropdown, PriorityDropdown, MemberDropdown, StateDropdown } from "components/dropdowns"; import { DateDropdown, EstimateDropdown, PriorityDropdown, MemberDropdown, StateDropdown } from "components/dropdowns";
import { import {
IssueLinkRoot, IssueLinkRoot,
@ -24,10 +25,9 @@ import {
TIssueOperations, TIssueOperations,
IssueRelationSelect, IssueRelationSelect,
} from "components/issues"; } from "components/issues";
// components
import { cn } from "helpers/common.helper";
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
// helpers // helpers
import { cn } from "helpers/common.helper";
import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "helpers/issue.helper"; import { shouldHighlightIssueDueDate } from "helpers/issue.helper";
import { useIssueDetail, useProject, useProjectState } from "hooks/store"; import { useIssueDetail, useProject, useProjectState } from "hooks/store";
@ -54,10 +54,10 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
const isEstimateEnabled = projectDetails?.estimate; const isEstimateEnabled = projectDetails?.estimate;
const stateDetails = getStateById(issue.state_id); const stateDetails = getStateById(issue.state_id);
const minDate = issue.start_date ? new Date(issue.start_date) : null; const minDate = getDate(issue.start_date);
minDate?.setDate(minDate.getDate()); minDate?.setDate(minDate.getDate());
const maxDate = issue.target_date ? new Date(issue.target_date) : null; const maxDate = getDate(issue.target_date);
maxDate?.setDate(maxDate.getDate()); maxDate?.setDate(maxDate.getDate());
return ( return (

View File

@ -1,13 +1,13 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
// components // ui
import { Button, Input, TextArea } from "@plane/ui"; import { Button, Input, TextArea } from "@plane/ui";
// components
import { DateRangeDropdown, ProjectDropdown, MemberDropdown } from "components/dropdowns"; import { DateRangeDropdown, ProjectDropdown, MemberDropdown } from "components/dropdowns";
import { ModuleStatusSelect } from "components/modules"; import { ModuleStatusSelect } from "components/modules";
// ui
// helpers // helpers
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
import { shouldRenderProject } from "helpers/project.helper"; import { shouldRenderProject } from "helpers/project.helper";
import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
// types // types
import { IModule } from "@plane/types"; import { IModule } from "@plane/types";
@ -149,8 +149,8 @@ export const ModuleForm: React.FC<Props> = (props) => {
className="h-7" className="h-7"
minDate={new Date()} minDate={new Date()}
value={{ value={{
from: startDateValue ? new Date(startDateValue) : undefined, from: getDate(startDateValue),
to: endDateValue ? new Date(endDateValue) : undefined, to: getDate(endDateValue),
}} }}
onSelect={(val) => { onSelect={(val) => {
onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null); onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null);

View File

@ -7,6 +7,7 @@ import { ModuleGanttBlock } from "components/modules";
import { useModule, useProject } from "hooks/store"; import { useModule, useProject } from "hooks/store";
// types // types
import { IModule } from "@plane/types"; import { IModule } from "@plane/types";
import { getDate } from "helpers/date-time.helper";
export const ModulesListGanttChartView: React.FC = observer(() => { export const ModulesListGanttChartView: React.FC = observer(() => {
// router // router
@ -34,8 +35,8 @@ export const ModulesListGanttChartView: React.FC = observer(() => {
data: block, data: block,
id: block.id, id: block.id,
sort_order: block.sort_order, sort_order: block.sort_order,
start_date: block.start_date ? new Date(block.start_date) : null, start_date: getDate(block.start_date),
target_date: block.target_date ? new Date(block.target_date) : null, target_date: getDate(block.target_date),
}; };
}); });

View File

@ -3,20 +3,20 @@ import { observer } from "mobx-react-lite";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { Info, LinkIcon, Pencil, Star, Trash2 } from "lucide-react"; import { Info, LinkIcon, Pencil, Star, Trash2 } from "lucide-react";
// hooks // ui
import { Avatar, AvatarGroup, CustomMenu, LayersIcon, Tooltip, TOAST_TYPE, setToast, setPromiseToast } from "@plane/ui"; import { Avatar, AvatarGroup, CustomMenu, LayersIcon, Tooltip, TOAST_TYPE, setToast, setPromiseToast } from "@plane/ui";
// components
import { CreateUpdateModuleModal, DeleteModuleModal } from "components/modules"; import { CreateUpdateModuleModal, DeleteModuleModal } from "components/modules";
// constants
import { MODULE_FAVORITED, MODULE_UNFAVORITED } from "constants/event-tracker"; import { MODULE_FAVORITED, MODULE_UNFAVORITED } from "constants/event-tracker";
import { MODULE_STATUS } from "constants/module"; import { MODULE_STATUS } from "constants/module";
import { EUserProjectRoles } from "constants/project"; import { EUserProjectRoles } from "constants/project";
import { renderFormattedDate } from "helpers/date-time.helper"; // helpers
import { copyUrlToClipboard } from "helpers/string.helper"; import { copyUrlToClipboard } from "helpers/string.helper";
import { getDate, renderFormattedDate } from "helpers/date-time.helper";
// hooks
import { useEventTracker, useMember, useModule, useUser } from "hooks/store"; import { useEventTracker, useMember, useModule, useUser } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os"; import { usePlatformOS } from "hooks/use-platform-os";
// components
// ui
// helpers
// constants
type Props = { type Props = {
moduleId: string; moduleId: string;
@ -147,8 +147,8 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
const completionPercentage = (moduleDetails.completed_issues / moduleTotalIssues) * 100; const completionPercentage = (moduleDetails.completed_issues / moduleTotalIssues) * 100;
const endDate = new Date(moduleDetails.target_date ?? ""); const endDate = getDate(moduleDetails.target_date);
const startDate = new Date(moduleDetails.start_date ?? ""); const startDate = getDate(moduleDetails.start_date);
const isDateValid = moduleDetails.target_date || moduleDetails.start_date; const isDateValid = moduleDetails.target_date || moduleDetails.start_date;
@ -160,8 +160,8 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
? !moduleTotalIssues || moduleTotalIssues === 0 ? !moduleTotalIssues || moduleTotalIssues === 0
? "0 Issue" ? "0 Issue"
: moduleTotalIssues === moduleDetails.completed_issues : moduleTotalIssues === moduleDetails.completed_issues
? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? "s" : ""}` ? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? "s" : ""}`
: `${moduleDetails.completed_issues}/${moduleTotalIssues} Issues` : `${moduleDetails.completed_issues}/${moduleTotalIssues} Issues`
: "0 Issue"; : "0 Issue";
return ( return (

View File

@ -3,7 +3,7 @@ import { observer } from "mobx-react-lite";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { Check, Info, LinkIcon, Pencil, Star, Trash2, User2 } from "lucide-react"; import { Check, Info, LinkIcon, Pencil, Star, Trash2, User2 } from "lucide-react";
// hooks // ui
import { import {
Avatar, Avatar,
AvatarGroup, AvatarGroup,
@ -16,10 +16,13 @@ import {
} from "@plane/ui"; } from "@plane/ui";
import { CreateUpdateModuleModal, DeleteModuleModal } from "components/modules"; import { CreateUpdateModuleModal, DeleteModuleModal } from "components/modules";
import { MODULE_FAVORITED, MODULE_UNFAVORITED } from "constants/event-tracker"; import { MODULE_FAVORITED, MODULE_UNFAVORITED } from "constants/event-tracker";
// helpers
import { copyUrlToClipboard } from "helpers/string.helper";
import { getDate, renderFormattedDate } from "helpers/date-time.helper";
// constants
import { MODULE_STATUS } from "constants/module"; import { MODULE_STATUS } from "constants/module";
import { EUserProjectRoles } from "constants/project"; import { EUserProjectRoles } from "constants/project";
import { renderFormattedDate } from "helpers/date-time.helper"; // hooks
import { copyUrlToClipboard } from "helpers/string.helper";
import { useModule, useUser, useEventTracker, useMember } from "hooks/store"; import { useModule, useUser, useEventTracker, useMember } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os"; import { usePlatformOS } from "hooks/use-platform-os";
// components // components
@ -150,8 +153,8 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
const completionPercentage = const completionPercentage =
((moduleDetails.completed_issues + moduleDetails.cancelled_issues) / moduleDetails.total_issues) * 100; ((moduleDetails.completed_issues + moduleDetails.cancelled_issues) / moduleDetails.total_issues) * 100;
const endDate = new Date(moduleDetails.target_date ?? ""); const endDate = getDate(moduleDetails.target_date);
const startDate = new Date(moduleDetails.start_date ?? ""); const startDate = getDate(moduleDetails.start_date);
const renderDate = moduleDetails.start_date || moduleDetails.target_date; const renderDate = moduleDetails.start_date || moduleDetails.target_date;

View File

@ -35,7 +35,7 @@ import { MODULE_LINK_CREATED, MODULE_LINK_DELETED, MODULE_LINK_UPDATED, MODULE_U
import { MODULE_STATUS } from "constants/module"; import { MODULE_STATUS } from "constants/module";
import { EUserProjectRoles } from "constants/project"; import { EUserProjectRoles } from "constants/project";
// helpers // helpers
import { renderFormattedPayloadDate } from "helpers/date-time.helper"; import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
import { copyUrlToClipboard } from "helpers/string.helper"; import { copyUrlToClipboard } from "helpers/string.helper";
// hooks // hooks
import { useModule, useUser, useEventTracker } from "hooks/store"; import { useModule, useUser, useEventTracker } from "hooks/store";
@ -207,8 +207,10 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
}); });
}, [moduleDetails, reset]); }, [moduleDetails, reset]);
const isStartValid = new Date(`${moduleDetails?.start_date}`) <= new Date(); const startDate = getDate(moduleDetails?.start_date);
const isEndValid = new Date(`${moduleDetails?.target_date}`) >= new Date(`${moduleDetails?.start_date}`); const endDate = getDate(moduleDetails?.target_date);
const isStartValid = startDate && startDate <= new Date();
const isEndValid = startDate && endDate && endDate >= startDate;
const progressPercentage = moduleDetails const progressPercentage = moduleDetails
? Math.round((moduleDetails.completed_issues / moduleDetails.total_issues) * 100) ? Math.round((moduleDetails.completed_issues / moduleDetails.total_issues) * 100)
@ -348,26 +350,30 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
<Controller <Controller
control={control} control={control}
name="target_date" name="target_date"
render={({ field: { value: endDateValue, onChange: onChangeEndDate } }) => ( render={({ field: { value: endDateValue, onChange: onChangeEndDate } }) => {
<DateRangeDropdown const startDate = getDate(startDateValue);
buttonContainerClassName="w-full" const endDate = getDate(endDateValue);
buttonVariant="background-with-text" return (
minDate={new Date()} <DateRangeDropdown
value={{ buttonContainerClassName="w-full"
from: startDateValue ? new Date(startDateValue) : undefined, buttonVariant="background-with-text"
to: endDateValue ? new Date(endDateValue) : undefined, minDate={new Date()}
}} value={{
onSelect={(val) => { from: startDate,
onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null); to: endDate,
onChangeEndDate(val?.to ? renderFormattedPayloadDate(val.to) : null); }}
handleDateChange(val?.from, val?.to); onSelect={(val) => {
}} onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null);
placeholder={{ onChangeEndDate(val?.to ? renderFormattedPayloadDate(val.to) : null);
from: "Start date", handleDateChange(val?.from, val?.to);
to: "Target date", }}
}} placeholder={{
/> from: "Start date",
)} to: "Target date",
}}
/>
);
}}
/> />
)} )}
/> />

View File

@ -117,7 +117,7 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
const notificationField = notification.data.issue_activity.field; const notificationField = notification.data.issue_activity.field;
const notificationTriggeredBy = notification.triggered_by_details; const notificationTriggeredBy = notification.triggered_by_details;
if (isSnoozedTabOpen && new Date(notification.snoozed_till!) < new Date()) return null; if (isSnoozedTabOpen && notification.snoozed_till! < new Date()) return null;
return ( return (
<Link <Link

View File

@ -56,7 +56,7 @@ export const SnoozeNotificationModal: FC<SnoozeModalProps> = (props) => {
if (!formDataDate) return timeStamps; if (!formDataDate) return timeStamps;
const isToday = today.toDateString() === new Date(formDataDate).toDateString(); const isToday = today.toDateString() === formDataDate.toDateString();
if (!isToday) return timeStamps; if (!isToday) return timeStamps;
@ -89,7 +89,7 @@ export const SnoozeNotificationModal: FC<SnoozeModalProps> = (props) => {
); );
const minutes = parseInt(time[1]); const minutes = parseInt(time[1]);
const dateTime = new Date(formData.date); const dateTime = formData.date;
dateTime.setHours(hours); dateTime.setHours(hours);
dateTime.setMinutes(minutes); dateTime.setMinutes(minutes);

View File

@ -8,7 +8,12 @@ export const INBOX_STATUS: {
status: number; status: number;
icon: LucideIcon; icon: LucideIcon;
title: string; title: string;
description: (workspaceSlug: string, projectId: string, issueId: string, snoozedTillDate: Date) => JSX.Element; description: (
workspaceSlug: string,
projectId: string,
issueId: string,
snoozedTillDate: Date | undefined
) => JSX.Element;
textColor: (snoozeDatePassed: boolean) => string; textColor: (snoozeDatePassed: boolean) => string;
bgColor: (snoozeDatePassed: boolean) => string; bgColor: (snoozeDatePassed: boolean) => string;
borderColor: (snoozeDatePassed: boolean) => string; borderColor: (snoozeDatePassed: boolean) => string;

View File

@ -91,7 +91,7 @@ const UserNotificationContextProvider: React.FC<{
const [state, dispatch] = useReducer(reducer, initialState); const [state, dispatch] = useReducer(reducer, initialState);
const { selectedTab, snoozed, archived, readNotification, selectedNotificationForSnooze } = state; const { selectedTab, snoozed, archived, readNotification } = state;
const params = { const params = {
type: snoozed || archived || readNotification ? undefined : selectedTab, type: snoozed || archived || readNotification ? undefined : selectedTab,
@ -207,7 +207,7 @@ const UserNotificationContextProvider: React.FC<{
(previousNotifications: any) => (previousNotifications: any) =>
previousNotifications?.map((notification: any) => previousNotifications?.map((notification: any) =>
notification.id === notificationId notification.id === notificationId
? { ...notification, snoozed_till: isSnoozed ? null : new Date(dateTime!) } ? { ...notification, snoozed_till: isSnoozed ? null : dateTime }
: notification : notification
) || [], ) || [],
false false

View File

@ -1,5 +1,5 @@
import { differenceInDays, format, formatDistanceToNow, isAfter, isEqual, isValid, parseISO } from "date-fns"; import { differenceInDays, format, formatDistanceToNow, isAfter, isEqual, isValid, parseISO } from "date-fns";
import { isNil } from "lodash"; import isNumber from "lodash/isNumber";
// Format Date Helpers // Format Date Helpers
/** /**
@ -8,10 +8,11 @@ import { isNil } from "lodash";
* @param {Date | string} date * @param {Date | string} date
* @example renderFormattedDate("2024-01-01") // Jan 01, 2024 * @example renderFormattedDate("2024-01-01") // Jan 01, 2024
*/ */
export const renderFormattedDate = (date: string | Date): string | null => { export const renderFormattedDate = (date: string | Date | undefined): string | null => {
if (!date) return null;
// Parse the date to check if it is valid // Parse the date to check if it is valid
const parsedDate = new Date(date); const parsedDate = getDate(date);
// return if undefined
if (!parsedDate) return null;
// Check if the parsed date is valid before formatting // Check if the parsed date is valid before formatting
if (!isValid(parsedDate)) return null; // Return null for invalid dates if (!isValid(parsedDate)) return null; // Return null for invalid dates
// Format the date in format (MMM dd, yyyy) // Format the date in format (MMM dd, yyyy)
@ -26,9 +27,10 @@ export const renderFormattedDate = (date: string | Date): string | null => {
* @example renderShortDateFormat("2024-01-01") // Jan 01 * @example renderShortDateFormat("2024-01-01") // Jan 01
*/ */
export const renderFormattedDateWithoutYear = (date: string | Date): string => { export const renderFormattedDateWithoutYear = (date: string | Date): string => {
if (!date) return "";
// Parse the date to check if it is valid // Parse the date to check if it is valid
const parsedDate = new Date(date); const parsedDate = getDate(date);
// return if undefined
if (!parsedDate) return "";
// Check if the parsed date is valid before formatting // Check if the parsed date is valid before formatting
if (!isValid(parsedDate)) return ""; // Return empty string for invalid dates if (!isValid(parsedDate)) return ""; // Return empty string for invalid dates
// Format the date in short format (MMM dd) // Format the date in short format (MMM dd)
@ -43,9 +45,10 @@ export const renderFormattedDateWithoutYear = (date: string | Date): string => {
* @example renderFormattedPayloadDate("Jan 01, 20224") // "2024-01-01" * @example renderFormattedPayloadDate("Jan 01, 20224") // "2024-01-01"
*/ */
export const renderFormattedPayloadDate = (date: Date | string): string | null => { export const renderFormattedPayloadDate = (date: Date | string): string | null => {
if (!date) return null;
// Parse the date to check if it is valid // Parse the date to check if it is valid
const parsedDate = new Date(date); const parsedDate = getDate(date);
// return if undefined
if (!parsedDate) return null;
// Check if the parsed date is valid before formatting // Check if the parsed date is valid before formatting
if (!isValid(parsedDate)) return null; // Return null for invalid dates if (!isValid(parsedDate)) return null; // Return null for invalid dates
// Format the date in payload format (yyyy-mm-dd) // Format the date in payload format (yyyy-mm-dd)
@ -63,9 +66,10 @@ export const renderFormattedPayloadDate = (date: Date | string): string | null =
* @example renderFormattedTime("2024-01-01 13:00:00", "12-hour") // 01:00 PM * @example renderFormattedTime("2024-01-01 13:00:00", "12-hour") // 01:00 PM
*/ */
export const renderFormattedTime = (date: string | Date, timeFormat: "12-hour" | "24-hour" = "24-hour"): string => { export const renderFormattedTime = (date: string | Date, timeFormat: "12-hour" | "24-hour" = "24-hour"): string => {
if (!date || date === "") return "";
// Parse the date to check if it is valid // Parse the date to check if it is valid
const parsedDate = new Date(date); const parsedDate = getDate(date);
// return if undefined
if (!parsedDate) return "";
// Check if the parsed date is valid // Check if the parsed date is valid
if (!isValid(parsedDate)) return ""; // Return empty string for invalid dates if (!isValid(parsedDate)) return ""; // Return empty string for invalid dates
// Format the date in 12 hour format if in12HourFormat is true // Format the date in 12 hour format if in12HourFormat is true
@ -92,10 +96,11 @@ export const findTotalDaysInRange = (
endDate: Date | string | undefined | null, endDate: Date | string | undefined | null,
inclusive: boolean = true inclusive: boolean = true
): number | undefined => { ): number | undefined => {
if (!startDate || !endDate) return undefined;
// Parse the dates to check if they are valid // Parse the dates to check if they are valid
const parsedStartDate = new Date(startDate); const parsedStartDate = getDate(startDate);
const parsedEndDate = new Date(endDate); const parsedEndDate = getDate(endDate);
// return if undefined
if (!parsedStartDate || !parsedEndDate) return;
// Check if the parsed dates are valid before calculating the difference // Check if the parsed dates are valid before calculating the difference
if (!isValid(parsedStartDate) || !isValid(parsedEndDate)) return 0; // Return 0 for invalid dates if (!isValid(parsedStartDate) || !isValid(parsedEndDate)) return 0; // Return 0 for invalid dates
// Calculate the difference in days // Calculate the difference in days
@ -131,6 +136,7 @@ export const calculateTimeAgo = (time: string | number | Date | null): string =>
if (!time) return ""; if (!time) return "";
// Parse the time to check if it is valid // Parse the time to check if it is valid
const parsedTime = typeof time === "string" || typeof time === "number" ? parseISO(String(time)) : time; const parsedTime = typeof time === "string" || typeof time === "number" ? parseISO(String(time)) : time;
// return if undefined
if (!parsedTime) return ""; // Return empty string for invalid dates if (!parsedTime) return ""; // Return empty string for invalid dates
// Format the time in the form of amount of time passed since the event happened // Format the time in the form of amount of time passed since the event happened
const distance = formatDistanceToNow(parsedTime, { addSuffix: true }); const distance = formatDistanceToNow(parsedTime, { addSuffix: true });
@ -164,7 +170,7 @@ export const isDateGreaterThanToday = (dateStr: string): boolean => {
* @example getWeekNumber(new Date("2023-09-01")) // 35 * @example getWeekNumber(new Date("2023-09-01")) // 35
*/ */
export const getWeekNumberOfDate = (date: Date): number => { export const getWeekNumberOfDate = (date: Date): number => {
const currentDate = new Date(date); const currentDate = date;
// Adjust the starting day to Sunday (0) instead of Monday (1) // Adjust the starting day to Sunday (0) instead of Monday (1)
const startDate = new Date(currentDate.getFullYear(), 0, 1); const startDate = new Date(currentDate.getFullYear(), 0, 1);
// Calculate the number of days between currentDate and startDate // Calculate the number of days between currentDate and startDate
@ -186,10 +192,30 @@ export const checkIfDatesAreEqual = (
date1: Date | string | null | undefined, date1: Date | string | null | undefined,
date2: Date | string | null | undefined date2: Date | string | null | undefined
): boolean => { ): boolean => {
if (isNil(date1) && isNil(date2)) return true; const parsedDate1 = getDate(date1);
if (isNil(date1) || isNil(date2)) return false; const parsedDate2 = getDate(date2);
// return if undefined
if (!parsedDate1 && !parsedDate2) return true;
if (!parsedDate1 || !parsedDate2) return false;
const parsedDate1 = new Date(date1);
const parsedDate2 = new Date(date2);
return isEqual(parsedDate1, parsedDate2); return isEqual(parsedDate1, parsedDate2);
}; };
/**
* This method returns a date from string of type yyyy-mm-dd
* This method is recommended to use instead of new Date() as this does not introduce any timezone offsets
* @param date
* @returns date or undefined
*/
export const getDate = (date: string | Date | undefined | null): Date | undefined => {
if (!date || date === "") return;
if (typeof date !== "string" && !(date instanceof String)) return date;
const [yearString, monthString, dayString] = date.substring(0, 10).split("-");
const year = parseInt(yearString);
const month = parseInt(monthString);
const day = parseInt(dayString);
if (!isNumber(year) || !isNumber(month) || !isNumber(day)) return;
return new Date(year, month - 1, day);
};

View File

@ -1,4 +1,8 @@
import differenceInCalendarDays from "date-fns/differenceInCalendarDays"; import differenceInCalendarDays from "date-fns/differenceInCalendarDays";
// helpers
import { getDate } from "./date-time.helper";
// types
// import { IIssueFilterOptions } from "@plane/types";
type TFilters = { type TFilters = {
[key: string]: string[] | null; [key: string]: string[] | null;
@ -31,9 +35,10 @@ export const calculateTotalFilters = (filters: TFilters): number =>
export const satisfiesDateFilter = (date: Date, filter: string): boolean => { export const satisfiesDateFilter = (date: Date, filter: string): boolean => {
const [value, operator, from] = filter.split(";"); const [value, operator, from] = filter.split(";");
if (!from) { const dateValue = getDate(value);
if (operator === "after") return date >= new Date(value); if (!from && dateValue) {
if (operator === "before") return date <= new Date(value); if (operator === "after") return date >= dateValue;
if (operator === "before") return date <= dateValue;
} }
if (from === "fromnow") { if (from === "fromnow") {

View File

@ -1,12 +1,13 @@
import differenceInCalendarDays from "date-fns/differenceInCalendarDays"; import differenceInCalendarDays from "date-fns/differenceInCalendarDays";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
// helpers // helpers
import { getDate } from "helpers/date-time.helper";
import { orderArrayBy } from "helpers/array.helper";
// types // types
import { IGanttBlock } from "components/gantt-chart"; import { IGanttBlock } from "components/gantt-chart";
// constants // constants
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue"; import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
import { STATE_GROUPS } from "constants/state"; import { STATE_GROUPS } from "constants/state";
import { orderArrayBy } from "helpers/array.helper";
import { import {
TIssue, TIssue,
TIssueGroupByOptions, TIssueGroupByOptions,
@ -157,7 +158,9 @@ export const shouldHighlightIssueDueDate = (
// if the issue is completed or cancelled, don't highlight the due date // if the issue is completed or cancelled, don't highlight the due date
if ([STATE_GROUPS.completed.key, STATE_GROUPS.cancelled.key].includes(stateGroup)) return false; if ([STATE_GROUPS.completed.key, STATE_GROUPS.cancelled.key].includes(stateGroup)) return false;
const parsedDate = new Date(date); const parsedDate = getDate(date);
if (!parsedDate) return false;
const targetDateDistance = differenceInCalendarDays(parsedDate, new Date()); const targetDateDistance = differenceInCalendarDays(parsedDate, new Date());
// if the issue is overdue, highlight the due date // if the issue is overdue, highlight the due date
@ -168,8 +171,8 @@ export const renderIssueBlocksStructure = (blocks: TIssue[]): IGanttBlock[] =>
data: block, data: block,
id: block.id, id: block.id,
sort_order: block.sort_order, sort_order: block.sort_order,
start_date: block.start_date ? new Date(block.start_date) : null, start_date: getDate(block.start_date),
target_date: block.target_date ? new Date(block.target_date) : null, target_date: getDate(block.target_date),
})); }));
export function getChangedIssuefields(formData: Partial<TIssue>, dirtyFields: { [key: string]: boolean | undefined }) { export function getChangedIssuefields(formData: Partial<TIssue>, dirtyFields: { [key: string]: boolean | undefined }) {

View File

@ -24,6 +24,7 @@ import { FileService } from "services/file.service";
// ui // ui
// assets // assets
// helpers // helpers
import { getDate } from "helpers/date-time.helper";
// types // types
import { IPage } from "@plane/types"; import { IPage } from "@plane/types";
// fetch-keys // fetch-keys
@ -276,7 +277,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
? { ? {
action: archived_at ? unArchivePage : archivePage, action: archived_at ? unArchivePage : archivePage,
is_archived: archived_at ? true : false, is_archived: archived_at ? true : false,
archived_at: archived_at ? new Date(archived_at) : undefined, archived_at: archived_at ? getDate(archived_at) : undefined,
} }
: undefined : undefined
} }

View File

@ -3,15 +3,17 @@ import set from "lodash/set";
import sortBy from "lodash/sortBy"; import sortBy from "lodash/sortBy";
import { action, computed, observable, makeObservable, runInAction } from "mobx"; import { action, computed, observable, makeObservable, runInAction } from "mobx";
import { computedFn } from "mobx-utils"; import { computedFn } from "mobx-utils";
// types // helpers
// mobx import { getDate } from "helpers/date-time.helper";
import { orderCycles, shouldFilterCycle } from "helpers/cycle.helper";
// services // services
import { CycleService } from "services/cycle.service"; import { CycleService } from "services/cycle.service";
import { IssueService } from "services/issue"; import { IssueService } from "services/issue";
import { ProjectService } from "services/project"; import { ProjectService } from "services/project";
// mobx
import { RootStore } from "store/root.store"; import { RootStore } from "store/root.store";
// types
import { ICycle, CycleDateCheckData } from "@plane/types"; import { ICycle, CycleDateCheckData } from "@plane/types";
import { orderCycles, shouldFilterCycle } from "helpers/cycle.helper";
export interface ICycleStore { export interface ICycleStore {
// loaders // loaders
@ -121,8 +123,9 @@ export class CycleStore implements ICycleStore {
const projectId = this.rootStore.app.router.projectId; const projectId = this.rootStore.app.router.projectId;
if (!projectId || !this.fetchedMap[projectId]) return null; if (!projectId || !this.fetchedMap[projectId]) return null;
let completedCycles = Object.values(this.cycleMap ?? {}).filter((c) => { let completedCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
const hasEndDatePassed = isPast(new Date(c.end_date ?? "")); const endDate = getDate(c.end_date);
const isEndDateToday = isToday(new Date(c.end_date ?? "")); const hasEndDatePassed = endDate && isPast(endDate);
const isEndDateToday = endDate && isToday(endDate);
return c.project_id === projectId && hasEndDatePassed && !isEndDateToday; return c.project_id === projectId && hasEndDatePassed && !isEndDateToday;
}); });
completedCycles = sortBy(completedCycles, [(c) => c.sort_order]); completedCycles = sortBy(completedCycles, [(c) => c.sort_order]);
@ -137,7 +140,8 @@ export class CycleStore implements ICycleStore {
const projectId = this.rootStore.app.router.projectId; const projectId = this.rootStore.app.router.projectId;
if (!projectId || !this.fetchedMap[projectId]) return null; if (!projectId || !this.fetchedMap[projectId]) return null;
let upcomingCycles = Object.values(this.cycleMap ?? {}).filter((c) => { let upcomingCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
const isStartDateUpcoming = isFuture(new Date(c.start_date ?? "")); const startDate = getDate(c.start_date);
const isStartDateUpcoming = startDate && isFuture(startDate);
return c.project_id === projectId && isStartDateUpcoming; return c.project_id === projectId && isStartDateUpcoming;
}); });
upcomingCycles = sortBy(upcomingCycles, [(c) => c.sort_order]); upcomingCycles = sortBy(upcomingCycles, [(c) => c.sort_order]);
@ -152,7 +156,8 @@ export class CycleStore implements ICycleStore {
const projectId = this.rootStore.app.router.projectId; const projectId = this.rootStore.app.router.projectId;
if (!projectId || !this.fetchedMap[projectId]) return null; if (!projectId || !this.fetchedMap[projectId]) return null;
let incompleteCycles = Object.values(this.cycleMap ?? {}).filter((c) => { let incompleteCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
const hasEndDatePassed = isPast(new Date(c.end_date ?? "")); const endDate = getDate(c.end_date);
const hasEndDatePassed = endDate && isPast(endDate);
return c.project_id === projectId && !hasEndDatePassed; return c.project_id === projectId && !hasEndDatePassed;
}); });
incompleteCycles = sortBy(incompleteCycles, [(c) => c.sort_order]); incompleteCycles = sortBy(incompleteCycles, [(c) => c.sort_order]);

View File

@ -73,8 +73,8 @@ export class ProjectPageStore implements IProjectPageStore {
const allProjectIds = Object.keys(this.projectPageMap[projectId]); const allProjectIds = Object.keys(this.projectPageMap[projectId]);
return allProjectIds.sort((a, b) => { return allProjectIds.sort((a, b) => {
const dateA = new Date(this.projectPageMap[projectId][a].created_at).getTime(); const dateA = this.projectPageMap[projectId][a].created_at.getTime();
const dateB = new Date(this.projectPageMap[projectId][b].created_at).getTime(); const dateB = this.projectPageMap[projectId][b].created_at.getTime();
return dateB - dateA; return dateB - dateA;
}); });
} }
@ -84,8 +84,8 @@ export class ProjectPageStore implements IProjectPageStore {
if (!projectId || !this.projectArchivedPageMap[projectId]) return []; if (!projectId || !this.projectArchivedPageMap[projectId]) return [];
const archivedPages = Object.keys(this.projectArchivedPageMap[projectId]); const archivedPages = Object.keys(this.projectArchivedPageMap[projectId]);
return archivedPages.sort((a, b) => { return archivedPages.sort((a, b) => {
const dateA = new Date(this.projectArchivedPageMap[projectId][a].created_at).getTime(); const dateA = this.projectArchivedPageMap[projectId][a].created_at.getTime();
const dateB = new Date(this.projectArchivedPageMap[projectId][b].created_at).getTime(); const dateB = this.projectArchivedPageMap[projectId][b].created_at.getTime();
return dateB - dateA; return dateB - dateA;
}); });
} }
@ -127,25 +127,21 @@ export class ProjectPageStore implements IProjectPageStore {
if (!this.projectPageIds || !projectId) return; if (!this.projectPageIds || !projectId) return;
const today: string[] = this.projectPageIds.filter((page) => const today: string[] = this.projectPageIds.filter((page) =>
isToday(new Date(this.projectPageMap[projectId][page].updated_at)) isToday(this.projectPageMap[projectId][page].updated_at)
); );
const yesterday: string[] = this.projectPageIds.filter((page) => const yesterday: string[] = this.projectPageIds.filter((page) =>
isYesterday(new Date(this.projectPageMap[projectId][page].updated_at)) isYesterday(this.projectPageMap[projectId][page].updated_at)
); );
const this_week: string[] = this.projectPageIds.filter((page) => { const this_week: string[] = this.projectPageIds.filter((page) => {
const pageUpdatedAt = this.projectPageMap[projectId][page].updated_at; const pageUpdatedAt = this.projectPageMap[projectId][page].updated_at;
return ( return isThisWeek(pageUpdatedAt) && !isToday(pageUpdatedAt) && !isYesterday(pageUpdatedAt);
isThisWeek(new Date(pageUpdatedAt)) &&
!isToday(new Date(pageUpdatedAt)) &&
!isYesterday(new Date(pageUpdatedAt))
);
}); });
const older: string[] = this.projectPageIds.filter((page) => { const older: string[] = this.projectPageIds.filter((page) => {
const pageUpdatedAt = this.projectPageMap[projectId][page].updated_at; const pageUpdatedAt = this.projectPageMap[projectId][page].updated_at;
return !isThisWeek(new Date(pageUpdatedAt)) && !isYesterday(new Date(pageUpdatedAt)); return !isThisWeek(pageUpdatedAt) && !isYesterday(pageUpdatedAt);
}); });
return { today, yesterday, this_week, older }; return { today, yesterday, this_week, older };