diff --git a/apps/app/components/command-palette/command-pallette.tsx b/apps/app/components/command-palette/command-pallette.tsx index 4110d0a27..1aeb5d831 100644 --- a/apps/app/components/command-palette/command-pallette.tsx +++ b/apps/app/components/command-palette/command-pallette.tsx @@ -204,7 +204,7 @@ export const CommandPalette: React.FC = () => {
-
+
{ leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > - + { if (value?.url) router.push(value.url); diff --git a/apps/app/components/core/existing-issues-list-modal.tsx b/apps/app/components/core/existing-issues-list-modal.tsx index 59faff3f6..e28d53906 100644 --- a/apps/app/components/core/existing-issues-list-modal.tsx +++ b/apps/app/components/core/existing-issues-list-modal.tsx @@ -129,7 +129,7 @@ export const ExistingIssuesListModal: React.FC = ({ {filteredIssues.length > 0 ? (
  • {query === "" && ( -

    +

    Select issues to add

    )} @@ -175,18 +175,6 @@ export const ExistingIssuesListModal: React.FC = ({
  • )} - - {query !== "" && filteredIssues.length === 0 && ( -
    -
    - )} )} /> diff --git a/apps/app/components/cycles/completed-cycles-list.tsx b/apps/app/components/cycles/completed-cycles-list.tsx index 09020e9d8..a6589f0d2 100644 --- a/apps/app/components/cycles/completed-cycles-list.tsx +++ b/apps/app/components/cycles/completed-cycles-list.tsx @@ -14,6 +14,7 @@ import { CompletedCycleIcon } from "components/icons"; import { ICycle, SelectCycleType } from "types"; // fetch-keys import { CYCLE_COMPLETE_LIST } from "constants/fetch-keys"; +import { Loader } from "components/ui"; export interface CompletedCyclesListProps { setCreateUpdateCycleModal: React.Dispatch>; @@ -49,38 +50,42 @@ export const CompletedCyclesList: React.FC = ({ return ( <> - {completedCycles && ( - <> - - {completedCycles?.completed_cycles.length > 0 ? ( -
    - {completedCycles.completed_cycles.map((cycle) => ( - handleDeleteCycle(cycle)} - handleEditCycle={() => handleEditCycle(cycle)} - /> - ))} -
    - ) : ( -
    - -

    - No completed cycles yet. Create with{" "} -
    Q
    . -

    -
    - )} - + + {completedCycles ? ( + completedCycles.completed_cycles.length > 0 ? ( +
    + {completedCycles.completed_cycles.map((cycle) => ( + handleDeleteCycle(cycle)} + handleEditCycle={() => handleEditCycle(cycle)} + /> + ))} +
    + ) : ( +
    + +

    + No completed cycles yet. Create with{" "} +
    Q
    . +

    +
    + ) + ) : ( + + + + + )} ); diff --git a/apps/app/components/cycles/cycles-list.tsx b/apps/app/components/cycles/cycles-list.tsx index dc4693637..97701202c 100644 --- a/apps/app/components/cycles/cycles-list.tsx +++ b/apps/app/components/cycles/cycles-list.tsx @@ -6,12 +6,13 @@ import { DeleteCycleModal, SingleCycleCard } from "components/cycles"; import { CompletedCycleIcon, CurrentCycleIcon, UpcomingCycleIcon } from "components/icons"; // types import { ICycle, SelectCycleType } from "types"; +import { Loader } from "components/ui"; type TCycleStatsViewProps = { - cycles: ICycle[]; + cycles: ICycle[] | undefined; setCreateUpdateCycleModal: React.Dispatch>; setSelectedCycle: React.Dispatch>; - type: "current" | "upcoming" | "completed"; + type: "current" | "upcoming" | "draft"; }; export const CyclesList: React.FC = ({ @@ -44,31 +45,37 @@ export const CyclesList: React.FC = ({ setIsOpen={setCycleDeleteModal} data={selectedCycleForDelete} /> - {cycles.length > 0 ? ( -
    - {cycles.map((cycle) => ( - handleDeleteCycle(cycle)} - handleEditCycle={() => handleEditCycle(cycle)} - /> - ))} -
    + {cycles ? ( + cycles.length > 0 ? ( +
    + {cycles.map((cycle) => ( + handleDeleteCycle(cycle)} + handleEditCycle={() => handleEditCycle(cycle)} + /> + ))} +
    + ) : ( +
    + {type === "upcoming" ? ( + + ) : type === "draft" ? ( + + ) : ( + + )} +

    + No {type} {type === "current" ? "cycle" : "cycles"} yet. Create with{" "} +
    Q
    . +

    +
    + ) ) : ( -
    - {type === "upcoming" ? ( - - ) : type === "completed" ? ( - - ) : ( - - )} -

    - No {type} {type === "current" ? "cycle" : "cycles"} yet. Create with{" "} -
    Q
    . -

    -
    + + + )} ); diff --git a/apps/app/components/cycles/modal.tsx b/apps/app/components/cycles/modal.tsx index a83d8ca93..d73d667eb 100644 --- a/apps/app/components/cycles/modal.tsx +++ b/apps/app/components/cycles/modal.tsx @@ -43,11 +43,7 @@ export const CreateUpdateCycleModal: React.FC = ({ await cycleService .createCycle(workspaceSlug as string, projectId as string, payload) .then((res) => { - switch ( - res?.start_date && res.end_date - ? getDateRangeStatus(res?.start_date, res.end_date) - : "draft" - ) { + switch (getDateRangeStatus(res.start_date, res.end_date)) { case "completed": mutate(CYCLE_COMPLETE_LIST(projectId as string)); break; @@ -81,11 +77,7 @@ export const CreateUpdateCycleModal: React.FC = ({ await cycleService .updateCycle(workspaceSlug as string, projectId as string, cycleId, payload) .then((res) => { - switch ( - res?.start_date && res.end_date - ? getDateRangeStatus(res?.start_date, res.end_date) - : "draft" - ) { + switch (getDateRangeStatus(res.start_date, res.end_date)) { case "completed": mutate(CYCLE_COMPLETE_LIST(projectId as string)); break; diff --git a/apps/app/components/cycles/single-cycle-card.tsx b/apps/app/components/cycles/single-cycle-card.tsx index 201090ac2..d6685ff1e 100644 --- a/apps/app/components/cycles/single-cycle-card.tsx +++ b/apps/app/components/cycles/single-cycle-card.tsx @@ -17,13 +17,25 @@ import { Disclosure, Transition } from "@headlessui/react"; import { CalendarDaysIcon } from "@heroicons/react/20/solid"; import { ChevronDownIcon, PencilIcon, StarIcon } from "@heroicons/react/24/outline"; // helpers -import { renderShortDateWithYearFormat } from "helpers/date-time.helper"; +import { getDateRangeStatus, renderShortDateWithYearFormat } from "helpers/date-time.helper"; import { groupBy } from "helpers/array.helper"; import { capitalizeFirstLetter, copyTextToClipboard } from "helpers/string.helper"; // types -import { CycleIssueResponse, ICycle } from "types"; +import { + CompletedCyclesResponse, + CurrentAndUpcomingCyclesResponse, + CycleIssueResponse, + DraftCyclesResponse, + ICycle, +} from "types"; // fetch-keys -import { CYCLE_ISSUES, CYCLE_LIST } from "constants/fetch-keys"; +import { + CYCLE_COMPLETE_LIST, + CYCLE_CURRENT_AND_UPCOMING_LIST, + CYCLE_DRAFT_LIST, + CYCLE_ISSUES, + CYCLE_LIST, +} from "constants/fetch-keys"; type TSingleStatProps = { cycle: ICycle; @@ -75,15 +87,45 @@ export const SingleCycleCard: React.FC = (props) => { cycle: cycle.id, }) .then(() => { - mutate( - CYCLE_LIST(projectId as string), - (prevData) => - (prevData ?? []).map((c) => ({ - ...c, - is_favorite: c.id === cycle.id ? true : c.is_favorite, - })), - false - ); + const cycleStatus = getDateRangeStatus(cycle.start_date, cycle.end_date); + + if (cycleStatus === "current" || cycleStatus === "upcoming") + mutate( + CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string), + (prevData) => ({ + current_cycle: (prevData?.current_cycle ?? []).map((c) => ({ + ...c, + is_favorite: c.id === cycle.id ? true : c.is_favorite, + })), + upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({ + ...c, + is_favorite: c.id === cycle.id ? true : c.is_favorite, + })), + }), + false + ); + else if (cycleStatus === "completed") + mutate( + CYCLE_COMPLETE_LIST(projectId as string), + (prevData) => ({ + completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({ + ...c, + is_favorite: c.id === cycle.id ? true : c.is_favorite, + })), + }), + false + ); + else + mutate( + CYCLE_DRAFT_LIST(projectId as string), + (prevData) => ({ + draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({ + ...c, + is_favorite: c.id === cycle.id ? true : c.is_favorite, + })), + }), + false + ); setToastAlert({ type: "success", @@ -106,15 +148,45 @@ export const SingleCycleCard: React.FC = (props) => { cyclesService .removeCycleFromFavorites(workspaceSlug as string, projectId as string, cycle.id) .then(() => { - mutate( - CYCLE_LIST(projectId as string), - (prevData) => - (prevData ?? []).map((c) => ({ - ...c, - is_favorite: c.id === cycle.id ? false : c.is_favorite, - })), - false - ); + const cycleStatus = getDateRangeStatus(cycle.start_date, cycle.end_date); + + if (cycleStatus === "current" || cycleStatus === "upcoming") + mutate( + CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string), + (prevData) => ({ + current_cycle: (prevData?.current_cycle ?? []).map((c) => ({ + ...c, + is_favorite: c.id === cycle.id ? false : c.is_favorite, + })), + upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({ + ...c, + is_favorite: c.id === cycle.id ? false : c.is_favorite, + })), + }), + false + ); + else if (cycleStatus === "completed") + mutate( + CYCLE_COMPLETE_LIST(projectId as string), + (prevData) => ({ + completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({ + ...c, + is_favorite: c.id === cycle.id ? false : c.is_favorite, + })), + }), + false + ); + else + mutate( + CYCLE_DRAFT_LIST(projectId as string), + (prevData) => ({ + draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({ + ...c, + is_favorite: c.id === cycle.id ? false : c.is_favorite, + })), + }), + false + ); setToastAlert({ type: "success", @@ -167,16 +239,12 @@ export const SingleCycleCard: React.FC = (props) => { {cycle.is_favorite ? ( - ) : ( - )}
    diff --git a/apps/app/components/issues/modal.tsx b/apps/app/components/issues/modal.tsx index c87ff2e66..6de90d5c9 100644 --- a/apps/app/components/issues/modal.tsx +++ b/apps/app/components/issues/modal.tsx @@ -231,7 +231,7 @@ export const CreateUpdateIssueModal: React.FC = ({
    -
    +
    { return time; }; -export const getDateRangeStatus = (startDate: string , endDate: string ) => { +export const getDateRangeStatus = (startDate: string | null, endDate: string | null) => { + if (!startDate || !endDate) return "draft"; + const now = new Date(); const start = new Date(startDate); const end = new Date(endDate); @@ -101,12 +103,25 @@ export const getDateRangeStatus = (startDate: string , endDate: string ) => { } else { return "upcoming"; } -} +}; export const renderShortDateWithYearFormat = (date: Date) => { - const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + const months = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ]; const day = date.getDate(); const month = months[date.getMonth()]; const year = date.getFullYear(); - return isNaN(date.getTime()) ? "N/A" : ` ${month} ${day}, ${year}`; -} \ No newline at end of file + return isNaN(date.getTime()) ? "N/A" : ` ${month} ${day}, ${year}`; +}; diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx index 29d30950b..1e547f9fa 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx @@ -115,7 +115,7 @@ const ProjectCycles: NextPage = () => {

    Current Cycle

    { > - `rounded-3xl border px-5 py-1.5 text-sm sm:px-7 sm:py-2 sm:text-base ${ + `rounded-3xl border px-5 py-1.5 text-sm outline-none sm:px-7 sm:py-2 sm:text-base ${ selected ? "border-theme bg-theme text-white" : "border-gray-300 bg-white hover:bg-hover-gray" @@ -143,7 +143,7 @@ const ProjectCycles: NextPage = () => { - `rounded-3xl border px-5 py-1.5 text-sm sm:px-7 sm:py-2 sm:text-base ${ + `rounded-3xl border px-5 py-1.5 text-sm outline-none sm:px-7 sm:py-2 sm:text-base ${ selected ? "border-theme bg-theme text-white" : "border-gray-300 bg-white hover:bg-hover-gray" @@ -154,7 +154,7 @@ const ProjectCycles: NextPage = () => { - `rounded-3xl border px-5 py-1.5 text-sm sm:px-7 sm:py-2 sm:text-base ${ + `rounded-3xl border px-5 py-1.5 text-sm outline-none sm:px-7 sm:py-2 sm:text-base ${ selected ? "border-theme bg-theme text-white" : "border-gray-300 bg-white hover:bg-hover-gray" @@ -167,7 +167,7 @@ const ProjectCycles: NextPage = () => { { diff --git a/apps/app/types/cycles.d.ts b/apps/app/types/cycles.d.ts index 4dc895504..f872339a3 100644 --- a/apps/app/types/cycles.d.ts +++ b/apps/app/types/cycles.d.ts @@ -21,18 +21,17 @@ export interface ICycle { } export interface CurrentAndUpcomingCyclesResponse { - current_cycle : ICycle[]; - upcoming_cycle : ICycle[]; + current_cycle: ICycle[]; + upcoming_cycle: ICycle[]; } - export interface DraftCyclesResponse { - draft_cycles : ICycle[]; - } + draft_cycles: ICycle[]; +} export interface CompletedCyclesResponse { - completed_cycles : ICycle[]; - } + completed_cycles: ICycle[]; +} export interface CycleIssueResponse { id: string;