Header.tsx 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import React from 'react';
  2. import { IconBrandGithub, IconHeart, IconLogout, IconMoon, IconSun } from '@tabler/icons';
  3. import Image from 'next/image';
  4. import clsx from 'clsx';
  5. import router from 'next/router';
  6. import Link from 'next/link';
  7. import { getUrl } from '../../../core/helpers/url-helpers';
  8. import { useUIStore } from '../../../state/uiStore';
  9. import { NavBar } from '../NavBar';
  10. import { useLogoutMutation } from '../../../generated/graphql';
  11. interface IProps {
  12. isUpdateAvailable?: boolean;
  13. }
  14. export const Header: React.FC<IProps> = ({ isUpdateAvailable }) => {
  15. const { setDarkMode } = useUIStore();
  16. const [logout] = useLogoutMutation();
  17. const handleLogout = async () => {
  18. await logout();
  19. localStorage.removeItem('token');
  20. router.reload();
  21. };
  22. return (
  23. <header className="navbar navbar-expand-md navbar-dark navbar-overlap d-print-none">
  24. <div className="container-xl">
  25. <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu">
  26. <span className="navbar-toggler-icon" />
  27. </button>
  28. <Link href="/" passHref>
  29. <h1 className="navbar-brand d-none-navbar-horizontal pe-0 pe-md-3">
  30. <Image
  31. priority
  32. alt="Tipi logo"
  33. className={clsx('navbar-brand-image me-3')}
  34. width={100}
  35. height={100}
  36. src={getUrl('tipi.png')}
  37. style={{
  38. width: '30px',
  39. maxWidth: '30px',
  40. height: 'auto',
  41. }}
  42. />
  43. Tipi
  44. </h1>
  45. </Link>
  46. <div className="navbar-nav flex-row order-md-last">
  47. <div className="nav-item d-none d-lg-flex me-3">
  48. <div className="btn-list">
  49. <a href="https://github.com/meienberger/runtipi" target="_blank" rel="noreferrer" className="btn btn-dark">
  50. <IconBrandGithub data-testid="icon-github" className="me-1 icon" size={24} />
  51. Source code
  52. </a>
  53. <a href="https://github.com/meienberger/runtipi?sponsor=1" target="_blank" rel="noreferrer" className="btn btn-dark">
  54. <IconHeart className="me-1 icon text-pink" size={24} />
  55. Sponsor
  56. </a>
  57. </div>
  58. </div>
  59. <div className="d-flex">
  60. <div onClick={() => setDarkMode(true)} role="button" aria-hidden="true" className="nav-link px-0 hide-theme-dark cursor-pointer" data-tip="Dark mode">
  61. <IconMoon data-testid="icon-moon" size={24} />
  62. </div>
  63. <div onClick={() => setDarkMode(false)} aria-hidden="true" className="nav-link px-0 hide-theme-light cursor-pointer" data-tip="Light mode">
  64. <IconSun data-testid="icon-sun" size={24} />
  65. </div>
  66. <div onClick={handleLogout} tabIndex={0} onKeyPress={handleLogout} role="button" className="nav-link px-0 cursor-pointer" data-tip="Log out">
  67. <IconLogout size={24} />
  68. </div>
  69. </div>
  70. </div>
  71. <NavBar isUpdateAvailable={isUpdateAvailable} />
  72. </div>
  73. </header>
  74. );
  75. };