You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
6.9 KiB

  1. import { useState, PropsWithChildren, ReactNode } from 'react';
  2. import ApplicationLogo from '@/Components/ApplicationLogo';
  3. import Dropdown from '@/Components/Dropdown';
  4. import NavLink from '@/Components/NavLink';
  5. import ResponsiveNavLink from '@/Components/ResponsiveNavLink';
  6. import { Link } from '@inertiajs/react';
  7. import { User } from '@/types';
  8. export default function Authenticated({ user, header, children }: PropsWithChildren<{ user: User, header?: ReactNode }>) {
  9. const [showingNavigationDropdown, setShowingNavigationDropdown] = useState(false);
  10. return (
  11. <div className="min-h-screen bg-gray-100">
  12. <nav className="bg-white border-b border-gray-100">
  13. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  14. <div className="flex justify-between h-16">
  15. <div className="flex">
  16. <div className="shrink-0 flex items-center">
  17. <Link href="/">
  18. <ApplicationLogo className="block h-9 w-auto fill-current text-gray-800" />
  19. </Link>
  20. </div>
  21. <div className="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
  22. <NavLink href={route('dashboard')} active={route().current('dashboard')}>
  23. Dashboard
  24. </NavLink>
  25. </div>
  26. </div>
  27. <div className="hidden sm:flex sm:items-center sm:ms-6">
  28. <div className="ms-3 relative">
  29. <Dropdown>
  30. <Dropdown.Trigger>
  31. <span className="inline-flex rounded-md">
  32. <button
  33. type="button"
  34. className="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:text-gray-700 focus:outline-none transition ease-in-out duration-150"
  35. >
  36. {user.name}
  37. <svg
  38. className="ms-2 -me-0.5 h-4 w-4"
  39. xmlns="http://www.w3.org/2000/svg"
  40. viewBox="0 0 20 20"
  41. fill="currentColor"
  42. >
  43. <path
  44. fillRule="evenodd"
  45. d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
  46. clipRule="evenodd"
  47. />
  48. </svg>
  49. </button>
  50. </span>
  51. </Dropdown.Trigger>
  52. <Dropdown.Content>
  53. <Dropdown.Link href={route('profile.edit')}>Profile</Dropdown.Link>
  54. <Dropdown.Link href={route('logout')} method="post" as="button">
  55. Log Out
  56. </Dropdown.Link>
  57. </Dropdown.Content>
  58. </Dropdown>
  59. </div>
  60. </div>
  61. <div className="-me-2 flex items-center sm:hidden">
  62. <button
  63. onClick={() => setShowingNavigationDropdown((previousState) => !previousState)}
  64. className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out"
  65. >
  66. <svg className="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
  67. <path
  68. className={!showingNavigationDropdown ? 'inline-flex' : 'hidden'}
  69. strokeLinecap="round"
  70. strokeLinejoin="round"
  71. strokeWidth="2"
  72. d="M4 6h16M4 12h16M4 18h16"
  73. />
  74. <path
  75. className={showingNavigationDropdown ? 'inline-flex' : 'hidden'}
  76. strokeLinecap="round"
  77. strokeLinejoin="round"
  78. strokeWidth="2"
  79. d="M6 18L18 6M6 6l12 12"
  80. />
  81. </svg>
  82. </button>
  83. </div>
  84. </div>
  85. </div>
  86. <div className={(showingNavigationDropdown ? 'block' : 'hidden') + ' sm:hidden'}>
  87. <div className="pt-2 pb-3 space-y-1">
  88. <ResponsiveNavLink href={route('dashboard')} active={route().current('dashboard')}>
  89. Dashboard
  90. </ResponsiveNavLink>
  91. </div>
  92. <div className="pt-4 pb-1 border-t border-gray-200">
  93. <div className="px-4">
  94. <div className="font-medium text-base text-gray-800">
  95. {user.name}
  96. </div>
  97. <div className="font-medium text-sm text-gray-500">{user.email}</div>
  98. </div>
  99. <div className="mt-3 space-y-1">
  100. <ResponsiveNavLink href={route('profile.edit')}>Profile</ResponsiveNavLink>
  101. <ResponsiveNavLink method="post" href={route('logout')} as="button">
  102. Log Out
  103. </ResponsiveNavLink>
  104. </div>
  105. </div>
  106. </div>
  107. </nav>
  108. {header && (
  109. <header className="bg-white shadow">
  110. <div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">{header}</div>
  111. </header>
  112. )}
  113. <main>{children}</main>
  114. </div>
  115. );
  116. }