11"use client" ;
22
3- import { useCallback , useState } from "react" ;
3+ import { useCallback , useRef , useState } from "react" ;
44import { observer } from "mobx-react" ;
55import Link from "next/link" ;
66import { useParams } from "next/navigation" ;
@@ -18,12 +18,18 @@ import {
1818// i18n
1919import { useTranslation } from "@plane/i18n" ;
2020// types
21- import { IIssueDisplayFilterOptions , IIssueDisplayProperties , IIssueFilterOptions } from "@plane/types" ;
21+ import {
22+ ICustomSearchSelectOption ,
23+ IIssueDisplayFilterOptions ,
24+ IIssueDisplayProperties ,
25+ IIssueFilterOptions ,
26+ } from "@plane/types" ;
2227// ui
23- import { Breadcrumbs , Button , ContrastIcon , CustomMenu , Tooltip , Header } from "@plane/ui" ;
28+ import { Breadcrumbs , Button , ContrastIcon , CustomMenu , Tooltip , Header , CustomSearchSelect } from "@plane/ui" ;
2429// components
2530import { ProjectAnalyticsModal } from "@/components/analytics" ;
26- import { BreadcrumbLink } from "@/components/common" ;
31+ import { BreadcrumbLink , SwitcherLabel } from "@/components/common" ;
32+ import { CycleQuickActions } from "@/components/cycles" ;
2733import { DisplayFiltersSelection , FiltersDropdown , FilterSelection , LayoutSelection } from "@/components/issues" ;
2834// helpers
2935import { cn } from "@/helpers/common.helper" ;
@@ -69,6 +75,8 @@ const CycleDropdownOption: React.FC<{ cycleId: string }> = ({ cycleId }) => {
6975} ;
7076
7177export const CycleIssuesHeader : React . FC = observer ( ( ) => {
78+ // refs
79+ const parentRef = useRef < HTMLDivElement > ( null ) ;
7280 // states
7381 const [ analyticsModal , setAnalyticsModal ] = useState ( false ) ;
7482 // router
@@ -159,6 +167,25 @@ export const CycleIssuesHeader: React.FC = observer(() => {
159167 EUserPermissionsLevel . PROJECT
160168 ) ;
161169
170+ const switcherOptions = currentProjectCycleIds
171+ ?. map ( ( id ) => {
172+ const _cycle = id === cycleId ? cycleDetails : getCycleById ( id ) ;
173+ if ( ! _cycle ) return ;
174+ const cycleLink = `/${ workspaceSlug } /projects/${ projectId } /cycles/${ _cycle . id } ` ;
175+ return {
176+ value : _cycle . id ,
177+ query : _cycle . name ,
178+ content : (
179+ < Link href = { cycleLink } >
180+ < SwitcherLabel name = { _cycle . name } LabelIcon = { ContrastIcon } />
181+ </ Link >
182+ ) ,
183+ } ;
184+ } )
185+ . filter ( ( option ) => option !== undefined ) as ICustomSearchSelectOption [ ] ;
186+
187+ const workItemsCount = getGroupIssueCount ( undefined , undefined , false ) ;
188+
162189 const issuesCount = getGroupIssueCount ( undefined , undefined , false ) ;
163190
164191 return (
@@ -201,33 +228,29 @@ export const CycleIssuesHeader: React.FC = observer(() => {
201228 < Breadcrumbs . BreadcrumbItem
202229 type = "component"
203230 component = {
204- < CustomMenu
231+ < CustomSearchSelect
232+ options = { switcherOptions }
233+ value = { cycleId }
234+ onChange = { ( ) => { } }
205235 label = {
206- < >
207- < ContrastIcon className = "h-3 w-3" />
208- < div className = "flex w-auto max-w-[70px] items-center gap-2 truncate sm:max-w-[200px]" >
209- < p className = "truncate" > { cycleDetails ?. name && cycleDetails . name } </ p >
210- { issuesCount && issuesCount > 0 ? (
211- < Tooltip
212- isMobile = { isMobile }
213- tooltipContent = { `There are ${ issuesCount } ${
214- issuesCount > 1 ? "work items" : "work item"
215- } in this cycle`}
216- position = "bottom"
217- >
218- < span className = "flex flex-shrink-0 cursor-default items-center justify-center rounded-xl bg-custom-primary-100/20 px-2 text-center text-xs font-semibold text-custom-primary-100" >
219- { issuesCount }
220- </ span >
221- </ Tooltip >
222- ) : null }
223- </ div >
224- </ >
236+ < div className = "flex items-center gap-1" >
237+ < SwitcherLabel name = { cycleDetails ?. name } LabelIcon = { ContrastIcon } />
238+ { workItemsCount && workItemsCount > 0 ? (
239+ < Tooltip
240+ isMobile = { isMobile }
241+ tooltipContent = { `There are ${ workItemsCount } ${
242+ workItemsCount > 1 ? "work items" : "work item"
243+ } in this cycle`}
244+ position = "bottom"
245+ >
246+ < span className = "flex flex-shrink-0 cursor-default items-center justify-center rounded-xl bg-custom-primary-100/20 px-2 text-center text-xs font-semibold text-custom-primary-100" >
247+ { workItemsCount }
248+ </ span >
249+ </ Tooltip >
250+ ) : null }
251+ </ div >
225252 }
226- className = "ml-1.5 flex-shrink-0 truncate"
227- placement = "bottom-start"
228- >
229- { currentProjectCycleIds ?. map ( ( cycleId ) => < CycleDropdownOption key = { cycleId } cycleId = { cycleId } /> ) }
230- </ CustomMenu >
253+ />
231254 }
232255 />
233256 </ Breadcrumbs >
@@ -302,19 +325,19 @@ export const CycleIssuesHeader: React.FC = observer(() => {
302325 ) }
303326 < button
304327 type = "button"
305- className = "grid h-7 w-7 place-items-center rounded p-1 outline-none hover:bg-custom-sidebar-background-80"
328+ className = "p-1 rounded outline-none hover:bg-custom-sidebar-background-80 bg-custom-background-80/70 "
306329 onClick = { toggleSidebar }
307330 >
308- < ArrowRight className = { ` h-4 w-4 duration-300 ${ isSidebarCollapsed ? "-rotate-180 " : "" } ` } />
331+ < PanelRight className = { cn ( " h-4 w-4" , ! isSidebarCollapsed ? "text-[#3E63DD] " : "text-custom-text-200" ) } />
309332 </ button >
333+ < CycleQuickActions
334+ parentRef = { parentRef }
335+ cycleId = { cycleId }
336+ projectId = { projectId }
337+ workspaceSlug = { workspaceSlug }
338+ customClassName = "flex-shrink-0 flex items-center justify-center size-6 bg-custom-background-80/70 rounded"
339+ />
310340 </ div >
311- < button
312- type = "button"
313- className = "grid h-7 w-7 place-items-center rounded p-1 outline-none hover:bg-custom-sidebar-background-80 md:hidden"
314- onClick = { toggleSidebar }
315- >
316- < PanelRight className = { cn ( "h-4 w-4" , ! isSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200" ) } />
317- </ button >
318341 </ Header . RightItem >
319342 </ Header >
320343 </ >
0 commit comments