All files / components layout.tsx

0% Statements 0/84
100% Branches 1/1
100% Functions 1/1
0% Lines 0/84

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                                                                                                                                                                                                                                   
'use client';
 
import {
  useContext, useEffect
} from 'react';
import Container from 'react-bootstrap/Container';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';
 
import CofrnNavbar from './navbar';
 
import { PageConfig } from '@/types/frontend/page';
import {
  DarkModeContext,
  LoggedInUserContext
} from '@/utils/frontend/clientContexts';
 
export default function CofrnLayout({
  children,
  pageConfig,
}: Readonly<{
  children: React.ReactNode;
  pageConfig: PageConfig;
}>) {
  const colorModeName = useContext(DarkModeContext);
  const user = useContext(LoggedInUserContext);
 
  useEffect(() => {
    if (
      user === null ||
      !user.isFinal ||
      (
        !pageConfig.requireAuth &&
        !pageConfig.requireAdmin
      )
    ) {
      return;
    }
 
    if (!user.isUser) {
      window.location.replace(`/login?redirectTo=${
        encodeURIComponent(`${window.location.pathname}${window.location.search}`)
      }`);
      return;
    }
 
    if (pageConfig.requireAdmin && !user.isAdmin) {
      window.location.replace('/');
    }
  }, [
    user,
    pageConfig.requireAdmin,
    pageConfig.requireAuth,
  ]);
 
  if (colorModeName === null) {
    return <></>;
  }
 
  const containerClasses: string[] = [];
  if (pageConfig.centerAll) {
    containerClasses.push('text-center');
  }
  if (pageConfig.containerClass) {
    containerClasses.push(pageConfig.containerClass);
  }
  const containerParams: {
    className?: string;
  } = {};
  if (containerClasses.length > 0) {
    containerParams.className = containerClasses.join(' ');
  }
 
  return (
    <LoggedInUserContext.Provider value={user}>
      <CofrnNavbar pageConfig={pageConfig} />
 
      {pageConfig.title && <h1 className='text-center'>{pageConfig.title}</h1>}
 
      <Container
        {...containerParams}
        fluid={!!pageConfig.fluid}
      >
        {children}
      </Container>
 
      <Navbar
        bg={colorModeName}
        className='mt-4'
      >
        <Container
          fluid={true}
          className='justify-content-center'
        >
          <Navbar.Brand href='#'>
            <img // eslint-disable-line @next/next/no-img-element
              src='/favicon.png'
              width='30'
              height='24'
              className='d-inline-block align-top'
              alt='COFRN'
              style={{
                filter: `invert(${colorModeName === 'dark' ? 1 : 0})`,
              }}
            />
          </Navbar.Brand>
          <Nav.Link className='mx-4' href='/about'>About Us</Nav.Link>
          <Navbar.Text className='mx-4'>© 2025 First Responder Notifications, LLC</Navbar.Text>
        </Container>
      </Navbar>
    </LoggedInUserContext.Provider>
  );
}