diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/properties.tsx b/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/properties.tsx index 96ed4a2a94..92a8bc0d6a 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/properties.tsx +++ b/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/properties.tsx @@ -1,12 +1,21 @@ // plane imports -import { SyntheticEvent } from "react"; +import { SyntheticEvent, useMemo } from "react"; import { observer } from "mobx-react"; +import { CalendarCheck2, CalendarClock } from "lucide-react"; +import { useTranslation } from "@plane/i18n"; import { IIssueDisplayProperties, TIssue } from "@plane/types"; -import { getDate, renderFormattedPayloadDate } from "@plane/utils"; +import { getDate, renderFormattedPayloadDate, shouldHighlightIssueDueDate } from "@plane/utils"; // components -import { PriorityDropdown, MemberDropdown, StateDropdown, DateRangeDropdown } from "@/components/dropdowns"; +import { + PriorityDropdown, + MemberDropdown, + StateDropdown, + DateRangeDropdown, + DateDropdown, +} from "@/components/dropdowns"; // hooks import { WithDisplayPropertiesHOC } from "@/components/issues/issue-layouts/properties/with-display-properties-HOC"; +import { useProjectState } from "@/hooks/store/use-project-state"; type Props = { workspaceSlug: string; @@ -27,6 +36,8 @@ type Props = { export const SubIssuesListItemProperties: React.FC = observer((props) => { const { workspaceSlug, parentIssueId, issueId, disabled, updateSubIssue, displayProperties, issue } = props; + const { t } = useTranslation(); + const { getStateById } = useProjectState(); const handleEventPropagation = (e: SyntheticEvent) => { e.stopPropagation(); @@ -49,10 +60,22 @@ export const SubIssuesListItemProperties: React.FC = observer((props) => } }; + //derived values + const stateDetails = useMemo(() => getStateById(issue.state_id), [getStateById, issue.state_id]); + const shouldHighlight = useMemo( + () => shouldHighlightIssueDueDate(issue.target_date, stateDetails?.group), + [issue.target_date, stateDetails?.group] + ); + // date range is enabled only when both dates are available and both dates are enabled + const isDateRangeEnabled: boolean = Boolean( + issue.start_date && issue.target_date && displayProperties?.start_date && displayProperties?.due_date + ); + if (!displayProperties) return <>; const maxDate = getDate(issue.target_date); - maxDate?.setDate(maxDate.getDate()); + const minDate = getDate(issue.start_date); + return (
@@ -104,7 +127,7 @@ export const SubIssuesListItemProperties: React.FC = observer((props) => !!(properties.start_date || properties.due_date)} + shouldRenderProperty={() => isDateRangeEnabled} >
= observer((props) => isClearable mergeDates buttonVariant={issue.start_date || issue.target_date ? "border-with-text" : "border-without-text"} + buttonClassName={shouldHighlight ? "text-red-500" : ""} disabled={!disabled} showTooltip customTooltipHeading="Date Range" @@ -130,6 +154,50 @@ export const SubIssuesListItemProperties: React.FC = observer((props) =>
+ {/* start date */} + !isDateRangeEnabled} + > +
+ } + buttonVariant={issue.start_date ? "border-with-text" : "border-without-text"} + optionsClassName="z-30" + disabled={!disabled} + showTooltip + /> +
+
+ + {/* target/due date */} + !isDateRangeEnabled} + > +
+ } + buttonVariant={issue.target_date ? "border-with-text" : "border-without-text"} + buttonClassName={shouldHighlight ? "text-red-500" : ""} + clearIconClassName="text-custom-text-100" + optionsClassName="z-30" + disabled={!disabled} + showTooltip + /> +
+
+
= observer((props) => { if (!displayProperties || !issue.project_id) return null; + // date range is enabled only when both dates are available and both dates are enabled + const isDateRangeEnabled: boolean = Boolean( + issue.start_date && issue.target_date && displayProperties.start_date && displayProperties.due_date + ); + const defaultLabelOptions = issue?.label_ids?.map((id) => labelMap[id]) || []; + const minDate = getDate(issue.start_date); + const maxDate = getDate(issue.target_date); + const handleEventPropagation = (e: SyntheticEvent) => { e.stopPropagation(); e.preventDefault(); @@ -312,7 +321,7 @@ export const IssueProperties: React.FC = observer((props) => { !!(properties.start_date || properties.due_date)} + shouldRenderProperty={() => isDateRangeEnabled} >
= observer((props) => { mergeDates buttonVariant={issue.start_date || issue.target_date ? "border-with-text" : "border-without-text"} buttonClassName={shouldHighlightIssueDueDate(issue.target_date, stateDetails?.group) ? "text-red-500" : ""} + clearIconClassName="!text-custom-text-100" disabled={isReadOnly} renderByDefault={isMobile} showTooltip @@ -340,6 +350,52 @@ export const IssueProperties: React.FC = observer((props) => {
+ {/* start date */} + !isDateRangeEnabled} + > +
+ } + buttonVariant={issue.start_date ? "border-with-text" : "border-without-text"} + optionsClassName="z-10" + disabled={isReadOnly} + renderByDefault={isMobile} + showTooltip + /> +
+
+ + {/* target/due date */} + !isDateRangeEnabled} + > +
+ } + buttonVariant={issue.target_date ? "border-with-text" : "border-without-text"} + buttonClassName={shouldHighlightIssueDueDate(issue.target_date, stateDetails?.group) ? "text-red-500" : ""} + clearIconClassName="!text-custom-text-100" + optionsClassName="z-10" + disabled={isReadOnly} + renderByDefault={isMobile} + showTooltip + /> +
+
+ {/* assignee */}