@@ -82,6 +82,7 @@ type View =
8282 | "audit"
8383 | "configuration"
8484type SortDirection = "asc" | "desc"
85+ type GigTab = "gigs" | "leads"
8586
8687type User = {
8788 subject : string
@@ -666,6 +667,19 @@ function detailIdFromPath(expectedView: "gigs" | "projects" = "gigs") {
666667 }
667668}
668669
670+ function gigTabFromHash ( hash = window . location . hash ) : GigTab {
671+ return hash . replace ( / ^ # / , "" ) === "leads" ? "leads" : "gigs"
672+ }
673+
674+ function updateGigTabHash ( tab : GigTab ) {
675+ const hash = tab === "leads" ? "#leads" : "#gigs"
676+ window . history . replaceState (
677+ window . history . state ,
678+ "" ,
679+ `${ window . location . pathname } ${ window . location . search } ${ hash } ` ,
680+ )
681+ }
682+
669683async function requestJson < T > ( url : string , options : RequestInit = { } ) : Promise < T > {
670684 const method = String ( options . method || "GET" ) . toUpperCase ( )
671685 const headers = new Headers ( options . headers )
@@ -908,7 +922,7 @@ function App() {
908922 const [ gigQuery , setGigQuery ] = useState ( "" )
909923 const [ gigIncludeHistorical , setGigIncludeHistorical ] = useState ( false )
910924 const [ gigLimit , setGigLimit ] = useState ( 100 )
911- const [ activeGigTab , setActiveGigTab ] = useState < "gigs" | "leads" > ( "gigs" )
925+ const [ activeGigTab , setActiveGigTab ] = useState < GigTab > ( gigTabFromHash )
912926 const [ gigLeadStatus , setGigLeadStatus ] = useState ( "pending" )
913927 const [ projectQuery , setProjectQuery ] = useState ( "" )
914928 const [ projectStatus , setProjectStatus ] = useState ( initialProjectDetailId ? "" : "Open" )
@@ -975,6 +989,7 @@ function App() {
975989 if ( normalized !== "projects" ) setSelectedProjectId ( "" )
976990 if ( normalized === "gigs" && push ) setSelectedGigId ( "" )
977991 if ( normalized === "projects" && push ) setSelectedProjectId ( "" )
992+ if ( normalized === "gigs" ) setActiveGigTab ( push ? "gigs" : gigTabFromHash ( ) )
978993 setViewState ( normalized )
979994 if ( push ) {
980995 window . history . pushState ( { view : normalized } , "" , routes [ normalized ] )
@@ -984,6 +999,11 @@ function App() {
984999 }
9851000 navigateRef . current = navigate
9861001
1002+ function selectGigTab ( tab : GigTab ) {
1003+ setActiveGigTab ( tab )
1004+ updateGigTabHash ( tab )
1005+ }
1006+
9871007 function crmContactUrl ( contactId ?: string ) {
9881008 if ( ! crmBaseUrl || ! contactId ) return ""
9891009 return `${ crmBaseUrl } /#Contact/view/${ encodeURIComponent ( contactId ) } `
@@ -1717,7 +1737,7 @@ function App() {
17171737 } ,
17181738 )
17191739 showToast ( "Posted lead to Discord" , "ok" )
1720- setActiveGigTab ( "gigs" )
1740+ selectGigTab ( "gigs" )
17211741 setGigStatus ( "" )
17221742 setGigQuery ( "" )
17231743 await loadGigLeads ( )
@@ -2344,6 +2364,12 @@ function App() {
23442364 return ( ) => window . removeEventListener ( "popstate" , onPopState )
23452365 } , [ ] )
23462366
2367+ useEffect ( ( ) => {
2368+ const onHashChange = ( ) => setActiveGigTab ( gigTabFromHash ( ) )
2369+ window . addEventListener ( "hashchange" , onHashChange )
2370+ return ( ) => window . removeEventListener ( "hashchange" , onHashChange )
2371+ } , [ ] )
2372+
23472373 useEffect ( ( ) => {
23482374 if ( ! toast . message ) return undefined
23492375 const timeout = window . setTimeout ( ( ) => setToast ( { message : "" } ) , 4500 )
@@ -2776,7 +2802,7 @@ function App() {
27762802 canIncludeHistorical = { can ( "people:read" ) }
27772803 crmContactUrl = { crmContactUrl }
27782804 crmAttachmentUrl = { crmAttachmentUrl }
2779- setActiveTab = { setActiveGigTab }
2805+ setActiveTab = { selectGigTab }
27802806 setStatus = { setGigStatus }
27812807 setQuery = { setGigQuery }
27822808 setLeadStatus = { setGigLeadStatus }
0 commit comments