Admin page now full screen with now extra UI

This commit is contained in:
James Ritchie
2023-10-20 16:53:01 +01:00
parent 5ea6a49d08
commit e7768881af
2 changed files with 10 additions and 175 deletions
+6 -12
View File
@@ -30,9 +30,8 @@ export async function action({ request }: ActionArgs) {
});
}
const headerClassName =
"py-3 px-2 pr-3 text-xs font-semibold leading-tight text-slate-900 text-left";
const cellClassName = "whitespace-nowrap px-2 py-2 text-xs text-slate-500";
const headerClassName = "py-3 px-2 pr-3 text-xs font-semibold leading-tight text-bright text-left";
const cellClassName = "whitespace-nowrap px-2 py-2 text-xs text-bright";
export default function AdminDashboardRoute() {
const { users } = useTypedLoaderData<typeof loader>();
@@ -46,8 +45,8 @@ export default function AdminDashboardRoute() {
>
<h1 className="mb-2 text-2xl">Accounts ({users.length})</h1>
<table className="w-full divide-y divide-slate-300">
<thead className="sticky top-0 bg-white text-left outline outline-2 outline-slate-200">
<table className="w-full divide-y divide-border">
<thead className="sticky top-0 text-left">
<tr>
<th scope="col" className={headerClassName}>
Email
@@ -69,10 +68,10 @@ export default function AdminDashboardRoute() {
</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-200 bg-white">
<tbody className="divide-y divide-border">
{users.map((user) => {
return (
<tr key={user.id} className="w-full bg-white px-4 py-2 text-left hover:bg-slate-50">
<tr key={user.id} className="w-full px-4 py-2 text-left hover:bg-slate-900">
<td className={cellClassName}>{user.email}</td>
<td className={cellClassName}>
<a
@@ -108,11 +107,6 @@ export default function AdminDashboardRoute() {
</tbody>
</table>
</section>
{/* Secondary column (hidden on smaller screens) */}
<aside className="hidden lg:order-first lg:block lg:flex-shrink-0">
<div className="relative flex h-full w-96 flex-col overflow-y-auto border-r border-gray-200 bg-white"></div>
</aside>
</main>
);
}
+4 -163
View File
@@ -1,15 +1,8 @@
import { Dialog, Transition } from "@headlessui/react";
import { HomeIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { UserCircleIcon } from "@heroicons/react/24/solid";
import { HomeIcon } from "@heroicons/react/24/outline";
import { Outlet } from "@remix-run/react";
import type { LoaderArgs } from "@remix-run/server-runtime";
import { Fragment, useState } from "react";
import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson";
import type { User } from "~/models/user.server";
import { getUser, requireUserId } from "~/services/session.server";
import { cn } from "~/utils/cn";
const navigation = [{ name: "Home", href: "/admin", icon: HomeIcon }];
export async function loader({ request }: LoaderArgs) {
await requireUserId(request);
@@ -27,162 +20,10 @@ export async function loader({ request }: LoaderArgs) {
export default function Page() {
const data = useTypedLoaderData<typeof loader>();
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
return (
<>
<div className="flex h-full">
<Transition.Root show={mobileMenuOpen} as={Fragment}>
<Dialog as="div" className="relative z-40 lg:hidden" onClose={setMobileMenuOpen}>
<Transition.Child
as={Fragment}
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-600 bg-opacity-75" />
</Transition.Child>
<div className="fixed inset-0 z-40 flex">
<Transition.Child
as={Fragment}
enter="transition ease-in-out duration-300 transform"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
leave="transition ease-in-out duration-300 transform"
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
>
<Dialog.Panel className="relative flex w-full max-w-xs flex-1 flex-col bg-white focus:outline-none">
<Transition.Child
as={Fragment}
enter="ease-in-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in-out duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="absolute top-0 right-0 -mr-12 pt-4">
<button
type="button"
className="ml-1 flex h-10 w-10 items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
onClick={() => setMobileMenuOpen(false)}
>
<span className="sr-only">Close sidebar</span>
<XMarkIcon className="h-6 w-6 text-white" aria-hidden="true" />
</button>
</div>
</Transition.Child>
<div className="pt-5 pb-4">
<div className="flex flex-shrink-0 items-center px-4">
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-mark.svg?color=indigo&shade=600"
alt="Workflow"
/>
</div>
<nav aria-label="Sidebar" className="mt-5">
<div className="space-y-1 px-2">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
className="group flex items-center rounded-md p-2 text-base font-medium text-gray-600 hover:bg-gray-50 hover:text-gray-900"
>
<item.icon
className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500"
aria-hidden="true"
/>
{item.name}
</a>
))}
</div>
</nav>
</div>
<div className="flex flex-shrink-0 border-t border-gray-200 p-4">
<button className="group block flex-shrink-0">
<div className="flex items-center">
<div>
<UserProfilePhoto user={data.user} className="h-10 w-10" />
</div>
<div className="ml-3">
<p className="text-base font-medium text-gray-700 group-hover:text-gray-900">
{data.user.displayName}
</p>
<p className="text-sm font-medium text-gray-500 group-hover:text-gray-700">
Account Settings
</p>
</div>
</div>
</button>
</div>
</Dialog.Panel>
</Transition.Child>
<div className="w-14 flex-shrink-0" aria-hidden="true">
{/* Force sidebar to shrink to fit close icon */}
</div>
</div>
</Dialog>
</Transition.Root>
{/* Static sidebar for desktop */}
<div className="hidden lg:flex lg:flex-shrink-0">
<div className="flex w-20 flex-col">
<div className="flex min-h-0 flex-1 flex-col overflow-y-auto bg-indigo-600">
<div className="flex-1">
<div className="flex items-center justify-center bg-indigo-700 py-4">
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-mark.svg?color=white"
alt="Workflow"
/>
</div>
<nav aria-label="Sidebar" className="flex flex-col items-center space-y-3 py-6">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
className="flex items-center rounded-lg p-4 text-indigo-200 hover:bg-indigo-700"
>
<item.icon className="h-6 w-6" aria-hidden="true" />
<span className="sr-only">{item.name}</span>
</a>
))}
</nav>
</div>
<div className="flex flex-shrink-0 pb-5">
<button className="flex w-full flex-shrink-0 flex-grow justify-center">
<UserProfilePhoto user={data.user} className="block h-10 w-10" />
<div className="sr-only">
<p>{data.user.displayName}</p>
<p>Account settings</p>
</div>
</button>
</div>
</div>
</div>
</div>
<div className="flex min-w-0 flex-1 flex-col overflow-hidden">
<Outlet />
</div>
</div>
</>
);
}
function UserProfilePhoto({ user, className }: { user: User; className?: string }) {
return user.avatarUrl ? (
<img
className={cn("rounded-full", className)}
src={user.avatarUrl}
alt={user.name ?? user.displayName ?? "User"}
/>
) : (
<UserCircleIcon className={cn("text-gray-400", className)} />
<div className="h-full w-full">
<Outlet />
</div>
);
}