go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/components/page_meta/page_meta_provider.tsx (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import {
    16    Dispatch,
    17    SetStateAction,
    18    createContext,
    19    useContext,
    20    useState,
    21  } from 'react';
    22  
    23  import { UiPage } from '@/common/constants/view';
    24  
    25  interface PageMetaContextData {
    26    selectedPage?: UiPage;
    27    setSelectedPage: Dispatch<SetStateAction<UiPage | undefined>>;
    28    project?: string;
    29    setProject: Dispatch<SetStateAction<string | undefined>>;
    30  }
    31  
    32  export const PageMetaContext = createContext<PageMetaContextData | null>(null);
    33  
    34  export function useSelectedPage() {
    35    const context = useContext(PageMetaContext);
    36  
    37    if (!context) {
    38      throw new Error('useSelectedPage can only be used in a PageMetaContext');
    39    }
    40  
    41    return context.selectedPage;
    42  }
    43  
    44  export function useProject() {
    45    const context = useContext(PageMetaContext);
    46  
    47    if (!context) {
    48      throw new Error('useSelectedProject can only be used in a PageMetaContext');
    49    }
    50  
    51    return context.project;
    52  }
    53  
    54  export function useSetSelectedPage() {
    55    const context = useContext(PageMetaContext);
    56  
    57    if (!context) {
    58      throw new Error('useSetSelectedPage can only be used in a PageMetaContext');
    59    }
    60  
    61    return context.setSelectedPage;
    62  }
    63  
    64  export function useSetProject() {
    65    const context = useContext(PageMetaContext);
    66  
    67    if (!context) {
    68      throw new Error('useSetProject can only be used in a PageMetaContext');
    69    }
    70  
    71    return context.setProject;
    72  }
    73  
    74  interface Props {
    75    children: React.ReactNode;
    76    initProject?: string;
    77    initPage?: UiPage;
    78  }
    79  
    80  export const PageMetaProvider = ({
    81    children,
    82    initProject = '',
    83    initPage = UiPage.Builders,
    84  }: Props) => {
    85    const [selectedPage, setSelectedPage] = useState<UiPage | undefined>(
    86      initPage,
    87    );
    88    const [project, setProject] = useState<string | undefined>(initProject);
    89    return (
    90      <PageMetaContext.Provider
    91        value={{
    92          selectedPage,
    93          setSelectedPage,
    94          project,
    95          setProject,
    96        }}
    97      >
    98        {children}
    99      </PageMetaContext.Provider>
   100    );
   101  };