diff --git a/web/components/core/favorite-star.tsx b/web/components/core/favorite-star.tsx new file mode 100644 index 000000000..40e8ddf08 --- /dev/null +++ b/web/components/core/favorite-star.tsx @@ -0,0 +1,28 @@ +import { Star } from "lucide-react"; +// helpers +import { cn } from "@/helpers/common.helper"; + +type Props = { + buttonClassName?: string; + iconClassName?: string; + onClick: (e: React.MouseEvent) => void; + selected: boolean; +}; + +export const FavoriteStar: React.FC = (props) => { + const { buttonClassName, iconClassName, onClick, selected } = props; + + return ( + + ); +}; diff --git a/web/components/core/index.ts b/web/components/core/index.ts index f68ff5f3c..3f753e025 100644 --- a/web/components/core/index.ts +++ b/web/components/core/index.ts @@ -1,7 +1,8 @@ export * from "./filters"; export * from "./modals"; export * from "./sidebar"; -export * from "./theme"; export * from "./activity"; +export * from "./favorite-star"; +export * from "./theme"; export * from "./image-picker-popover"; export * from "./page-title"; diff --git a/web/components/cycles/active-cycle/upcoming-cycles-list-item.tsx b/web/components/cycles/active-cycle/upcoming-cycles-list-item.tsx index 303d91752..d928b5fbb 100644 --- a/web/components/cycles/active-cycle/upcoming-cycles-list-item.tsx +++ b/web/components/cycles/active-cycle/upcoming-cycles-list-item.tsx @@ -1,17 +1,18 @@ import { observer } from "mobx-react"; import Link from "next/link"; import { useRouter } from "next/router"; -import { Star, User2 } from "lucide-react"; -// hooks -import { Avatar, AvatarGroup, setPromiseToast } from "@plane/ui"; -import { CycleQuickActions } from "@/components/cycles"; -import { CYCLE_FAVORITED, CYCLE_UNFAVORITED } from "@/constants/event-tracker"; -import { renderFormattedDate } from "@/helpers/date-time.helper"; -import { useCycle, useEventTracker, useMember } from "@/hooks/store"; -// components +import { User2 } from "lucide-react"; // ui -// helpers +import { Avatar, AvatarGroup, setPromiseToast } from "@plane/ui"; +// components +import { FavoriteStar } from "@/components/core"; +import { CycleQuickActions } from "@/components/cycles"; // constants +import { CYCLE_FAVORITED, CYCLE_UNFAVORITED } from "@/constants/event-tracker"; +// helpers +import { renderFormattedDate } from "@/helpers/date-time.helper"; +// hooks +import { useCycle, useEventTracker, useMember } from "@/hooks/store"; type Props = { cycleId: string; @@ -112,15 +113,13 @@ export const UpcomingCycleListItem: React.FC = observer((props) => { )} - {cycle.is_favorite ? ( - - ) : ( - - )} + { + if (cycle.is_favorite) handleRemoveFromFavorites(e); + else handleAddToFavorites(e); + }} + selected={!!cycle.is_favorite} + /> {workspaceSlug && projectId && ( = observer((props) => { ? cycleTotalIssues === 0 ? "0 Issue" : cycleTotalIssues === cycleDetails.completed_issues - ? `${cycleTotalIssues} Issue${cycleTotalIssues > 1 ? "s" : ""}` - : `${cycleDetails.completed_issues}/${cycleTotalIssues} Issues` + ? `${cycleTotalIssues} Issue${cycleTotalIssues > 1 ? "s" : ""}` + : `${cycleDetails.completed_issues}/${cycleTotalIssues} Issues` : "0 Issue"; const handleAddToFavorites = (e: MouseEvent) => { @@ -234,16 +232,15 @@ export const CyclesBoardCard: FC = observer((props) => { No due date )}
- {isEditingAllowed && - (cycleDetails.is_favorite ? ( - - ) : ( - - ))} + {isEditingAllowed && ( + { + if (cycleDetails.is_favorite) handleRemoveFromFavorites(e); + else handleAddToFavorites(e); + }} + selected={!!cycleDetails.is_favorite} + /> + )}
diff --git a/web/components/cycles/list/cycles-list-item.tsx b/web/components/cycles/list/cycles-list-item.tsx index 827f91ad8..d6bc484b1 100644 --- a/web/components/cycles/list/cycles-list-item.tsx +++ b/web/components/cycles/list/cycles-list-item.tsx @@ -3,12 +3,13 @@ import { observer } from "mobx-react"; import Link from "next/link"; import { useRouter } from "next/router"; // icons -import { Check, Info, Star, User2 } from "lucide-react"; +import { Check, Info, User2 } from "lucide-react"; // types import type { TCycleGroups } from "@plane/types"; // ui import { Tooltip, CircularProgressIndicator, CycleGroupIcon, AvatarGroup, Avatar, setPromiseToast } from "@plane/ui"; // components +import { FavoriteStar } from "@/components/core"; import { CycleQuickActions } from "@/components/cycles"; // constants import { CYCLE_STATUS } from "@/constants/cycle"; @@ -231,17 +232,15 @@ export const CyclesListItem: FC = observer((props) => { - {isEditingAllowed && - !isArchived && - (cycleDetails.is_favorite ? ( - - ) : ( - - ))} + {isEditingAllowed && !isArchived && ( + { + if (cycleDetails.is_favorite) handleRemoveFromFavorites(e); + else handleAddToFavorites(e); + }} + selected={!!cycleDetails.is_favorite} + /> + )} = observer((props) => { ? !moduleTotalIssues || moduleTotalIssues === 0 ? "0 Issue" : moduleTotalIssues === moduleDetails.completed_issues - ? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? "s" : ""}` - : `${moduleDetails.completed_issues}/${moduleTotalIssues} Issues` + ? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? "s" : ""}` + : `${moduleDetails.completed_issues}/${moduleTotalIssues} Issues` : "0 Issue"; return ( @@ -224,16 +224,15 @@ export const ModuleCardItem: React.FC = observer((props) => { )}
- {isEditingAllowed && - (moduleDetails.is_favorite ? ( - - ) : ( - - ))} + {isEditingAllowed && ( + { + if (moduleDetails.is_favorite) handleRemoveFromFavorites(e); + else handleAddToFavorites(e); + }} + selected={!!moduleDetails.is_favorite} + /> + )} {workspaceSlug && projectId && ( = observer((props) => {
- {isEditingAllowed && - !isArchived && - (moduleDetails.is_favorite ? ( - - ) : ( - - ))} + {isEditingAllowed && !isArchived && ( + { + if (moduleDetails.is_favorite) handleRemoveFromFavorites(e); + else handleAddToFavorites(e); + }} + selected={moduleDetails.is_favorite} + /> + )} {workspaceSlug && projectId && ( = observer((props) => { {/* favorite/unfavorite */} - + selected={is_favorite} + /> {/* quick actions dropdown */} diff --git a/web/components/project/card.tsx b/web/components/project/card.tsx index 0540273eb..046c0f716 100644 --- a/web/components/project/card.tsx +++ b/web/components/project/card.tsx @@ -2,23 +2,23 @@ import React, { useState } from "react"; import { observer } from "mobx-react-lite"; import Link from "next/link"; import { useRouter } from "next/router"; -import { ArchiveRestoreIcon, Check, LinkIcon, Lock, Pencil, Star, Trash2 } from "lucide-react"; +import { ArchiveRestoreIcon, Check, LinkIcon, Lock, Pencil, Trash2 } from "lucide-react"; +// types import type { IProject } from "@plane/types"; // ui import { Avatar, AvatarGroup, Button, Tooltip, TOAST_TYPE, setToast, setPromiseToast } from "@plane/ui"; // components +import { FavoriteStar } from "@/components/core"; import { ArchiveRestoreProjectModal, DeleteProjectModal, JoinProjectModal, ProjectLogo } from "@/components/project"; -// helpers +// constants import { EUserProjectRoles } from "@/constants/project"; +// helpers import { cn } from "@/helpers/common.helper"; import { renderFormattedDate } from "@/helpers/date-time.helper"; import { copyUrlToClipboard } from "@/helpers/string.helper"; // hooks import { useProject } from "@/hooks/store"; -// types import { usePlatformOS } from "@/hooks/use-platform-os"; -// hooks -// constants type Props = { project: IProject; @@ -166,19 +166,19 @@ export const ProjectCard: React.FC = observer((props) => { > - + selected={project.is_favorite} + /> )} diff --git a/web/components/project/sidebar-list-item.tsx b/web/components/project/sidebar-list-item.tsx index 5041e81c3..bc6166fbb 100644 --- a/web/components/project/sidebar-list-item.tsx +++ b/web/components/project/sidebar-list-item.tsx @@ -273,7 +273,7 @@ export const ProjectSidebarListItem: React.FC = observer((props) => { {project.is_favorite && ( - + Remove from favorites diff --git a/web/components/views/view-list-item.tsx b/web/components/views/view-list-item.tsx index 034a40ecb..c3731696e 100644 --- a/web/components/views/view-list-item.tsx +++ b/web/components/views/view-list-item.tsx @@ -2,11 +2,13 @@ import React, { useState } from "react"; import { observer } from "mobx-react-lite"; import Link from "next/link"; import { useRouter } from "next/router"; -import { LinkIcon, PencilIcon, StarIcon, TrashIcon } from "lucide-react"; +import { LinkIcon, PencilIcon, TrashIcon } from "lucide-react"; +// types import { IProjectView } from "@plane/types"; // ui import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui"; // components +import { FavoriteStar } from "@/components/core"; import { CreateUpdateProjectViewModal, DeleteProjectViewModal } from "@/components/views"; // constants import { EUserProjectRoles } from "@/constants/project"; @@ -15,7 +17,6 @@ import { calculateTotalFilters } from "@/helpers/filter.helper"; import { copyUrlToClipboard } from "@/helpers/string.helper"; // hooks import { useProjectView, useUser } from "@/hooks/store"; -// types type Props = { view: IProjectView; @@ -91,32 +92,17 @@ export const ProjectViewListItem: React.FC = observer((props) => {

{totalFilters} {totalFilters === 1 ? "filter" : "filters"}

- {isEditingAllowed && - (view.is_favorite ? ( - - ) : ( - - ))} + {isEditingAllowed && ( + { + e.preventDefault(); + e.stopPropagation(); + if (view.is_favorite) handleRemoveFromFavorites(); + else handleAddToFavorites(); + }} + selected={view.is_favorite} + /> + )} {isEditingAllowed && (