From 0544b8358af68df87dbc472221d8c0842c2b2db0 Mon Sep 17 00:00:00 2001
From: Sebastian <sebasjm@gmail.com>
Date: Fri, 19 May 2023 13:26:47 -0300
Subject: accounts and notifications

---
 packages/exchange-backoffice-ui/src/Dashboard.tsx | 217 +++++++++++++++++-----
 1 file changed, 173 insertions(+), 44 deletions(-)

(limited to 'packages/exchange-backoffice-ui/src/Dashboard.tsx')

diff --git a/packages/exchange-backoffice-ui/src/Dashboard.tsx b/packages/exchange-backoffice-ui/src/Dashboard.tsx
index 9a0ba41d5..9be86c533 100644
--- a/packages/exchange-backoffice-ui/src/Dashboard.tsx
+++ b/packages/exchange-backoffice-ui/src/Dashboard.tsx
@@ -3,19 +3,26 @@ import {
   ChevronDownIcon,
   MagnifyingGlassIcon,
   UserIcon,
+  XCircleIcon,
 } from "@heroicons/react/20/solid";
 import {
   Bars3Icon,
   BellIcon,
+  CheckCircleIcon,
   Cog6ToothIcon,
   XMarkIcon,
 } from "@heroicons/react/24/outline";
 import { ComponentChildren, Fragment, VNode, h } from "preact";
 import { ForwardedRef, forwardRef } from "preact/compat";
-import { useRef, useState } from "preact/hooks";
+import { useEffect, useRef, useState } from "preact/hooks";
 import { Pages } from "./pages.js";
 import { Router, useCurrentLocation } from "./route.js";
 import { InformationCircleIcon } from "@heroicons/react/24/solid";
+import {
+  useLocalStorage,
+  useMemoryStorage,
+  useNotifications,
+} from "@gnu-taler/web-util/browser";
 
 /**
  * references between forms
@@ -259,6 +266,7 @@ export function Dashboard({
             setSidebarOpen(true);
           }}
         />
+        <Notifications />
         <main class="py-10 px-4 sm:px-6 lg:px-8">
           <div class="mx-auto max-w-3xl">
             <Router
@@ -355,6 +363,9 @@ function NavigationBar({
 }
 
 function TopBar({ onOpenSidebar }: { onOpenSidebar: () => void }) {
+  const password = useMemoryStorage("password");
+  const officer = useLocalStorage("officer");
+
   return (
     <div class="sticky top-0 z-40 flex h-16 shrink-0 items-center gap-x-4 border-b border-gray-200 bg-white px-4 shadow-sm sm:gap-x-6 sm:px-6 lg:px-8">
       <button
@@ -402,60 +413,66 @@ function TopBar({ onOpenSidebar }: { onOpenSidebar: () => void }) {
             aria-hidden="true"
           />
 
-          {/* Profile dropdown */}
-          <Menu
-            as="div"
-            /* @ts-ignore */
-            class="relative"
-          >
-            <Menu.Button class="-m-1.5 flex items-center p-1.5">
-              <span class="sr-only">Open user menu</span>
-              <img
-                class="h-8 w-8 rounded-full bg-gray-50"
-                src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
-                alt=""
-              />
-              <span class="hidden lg:flex lg:items-center">
-                <span
-                  class="ml-4 text-sm font-semibold leading-6 text-gray-900"
-                  aria-hidden="true"
-                >
-                  Tom Cook
-                </span>
-                <ChevronDownIcon
-                  class="ml-2 h-5 w-5 text-gray-400"
-                  aria-hidden="true"
-                />
-              </span>
-            </Menu.Button>
-            <Transition
-              as={Fragment}
-              enter="transition ease-out duration-100"
-              enterFrom="transform opacity-0 scale-95"
-              enterTo="transform opacity-100 scale-100"
-              leave="transition ease-in duration-75"
-              leaveFrom="transform opacity-100 scale-100"
-              leaveTo="transform opacity-0 scale-95"
+          {officer.value === undefined ? (
+            <div />
+          ) : (
+            <Menu
+              as="div"
+              /* @ts-ignore */
+              class="relative"
             >
-              <Menu.Items class="absolute right-0 z-10 mt-2.5 w-32 origin-top-right rounded-md bg-white py-2 shadow-lg ring-1 ring-gray-900/5 focus:outline-none">
-                {userNavigation.map((item) => (
-                  <Menu.Item key={item.name}>
+              <Menu.Button class="-m-1.5 flex items-center p-1.5">
+                <span class="sr-only">Open user menu</span>
+                <img
+                  class="h-8 w-8 rounded-full bg-gray-50"
+                  src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
+                  alt=""
+                />
+                <span class="hidden lg:flex lg:items-center">
+                  <span
+                    class="ml-4 text-sm font-semibold leading-6 text-gray-900"
+                    aria-hidden="true"
+                  >
+                    {/* Tom Cook */}
+                    {officer.value?.substring(0, 6)}
+                  </span>
+                  <ChevronDownIcon
+                    class="ml-2 h-5 w-5 text-gray-400"
+                    aria-hidden="true"
+                  />
+                </span>
+              </Menu.Button>
+              <Transition
+                as={Fragment}
+                enter="transition ease-out duration-100"
+                enterFrom="transform opacity-0 scale-95"
+                enterTo="transform opacity-100 scale-100"
+                leave="transition ease-in duration-75"
+                leaveFrom="transform opacity-100 scale-100"
+                leaveTo="transform opacity-0 scale-95"
+              >
+                <Menu.Items class="absolute right-0 z-10 mt-2.5 w-48 origin-top-right rounded-md bg-white py-2 shadow-lg ring-1 ring-gray-900/5 focus:outline-none">
+                  <Menu.Item>
                     {({ active }: { active: boolean }) => (
                       <a
-                        href={item.href}
+                        // href={item.href}
+                        onClick={() => {
+                          officer.reset();
+                          password.reset();
+                        }}
                         class={classNames(
                           active ? "bg-gray-50" : "",
                           "block px-3 py-1 text-sm leading-6 text-gray-900",
                         )}
                       >
-                        {item.name}
+                        Forget account
                       </a>
                     )}
                   </Menu.Item>
-                ))}
-              </Menu.Items>
-            </Transition>
-          </Menu>
+                </Menu.Items>
+              </Transition>
+            </Menu>
+          )}
         </div>
       </div>
     </div>
@@ -473,3 +490,115 @@ function Footer() {
     </footer>
   );
 }
+
+function Notifications() {
+  const ns = useNotifications();
+
+  // useEffect(() => {
+  //   if (ns.length) {
+  //     // remove notifications after some timeout
+  //   }
+  // }, []);
+  {
+    /* <!-- Global notification live region, render this permanently at the end of the document --> */
+  }
+  console.log("render", ns.length);
+  return (
+    <div
+      aria-live="assertive"
+      class="pointer-events-none fixed inset-0 flex items-end px-4 py-6 sm:items-start sm:p-6 z-50"
+    >
+      <div class="flex w-full flex-col items-center space-y-4 sm:items-end ">
+        {/* <!--
+  Notification panel, dynamically insert this into the live region when it needs to be displayed
+
+  Entering: "transform ease-out duration-300 transition"
+    From: "translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
+    To: "translate-y-0 opacity-100 sm:translate-x-0"
+  Leaving: "transition ease-in duration-100"
+    From: "opacity-100"
+    To: "opacity-0"
+--> */}
+        {ns.map(({ message, remove }) => {
+          switch (message.type) {
+            case "error": {
+              return (
+                <div class="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5 ">
+                  <div class="p-4 ">
+                    <div class="flex items-start ">
+                      <div class="flex-shrink-0">
+                        <XCircleIcon class="h-6 w-6 text-red-400" />
+                      </div>
+                      <div class="ml-3 w-0 flex-1 pt-0.5">
+                        <p class="text-sm font-medium text-gray-900">
+                          {message.title}
+                        </p>
+                        {message.description && (
+                          <p class="mt-1 text-sm text-gray-500">
+                            {message.description}
+                          </p>
+                        )}
+                      </div>
+                      <div class="ml-4 flex flex-shrink-0">
+                        <button
+                          type="button"
+                          onClick={remove}
+                          class="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
+                        >
+                          <span class="sr-only">Close</span>
+                          <svg
+                            class="h-5 w-5"
+                            viewBox="0 0 20 20"
+                            fill="currentColor"
+                            aria-hidden="true"
+                          >
+                            <path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
+                          </svg>
+                        </button>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              );
+            }
+            case "info": {
+              return (
+                <div class="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5 ">
+                  <div class="p-4 ">
+                    <div class="flex items-start ">
+                      <div class="flex-shrink-0">
+                        <CheckCircleIcon class="h-6 w-6 text-green-400" />
+                      </div>
+                      <div class="ml-3 w-0 flex-1 pt-0.5">
+                        <p class="text-sm font-medium text-gray-900">
+                          {message.title}
+                        </p>
+                      </div>
+                      <div class="ml-4 flex flex-shrink-0">
+                        <button
+                          type="button"
+                          onClick={remove}
+                          class="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
+                        >
+                          <span class="sr-only">Close</span>
+                          <svg
+                            class="h-5 w-5"
+                            viewBox="0 0 20 20"
+                            fill="currentColor"
+                            aria-hidden="true"
+                          >
+                            <path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
+                          </svg>
+                        </button>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              );
+            }
+          }
+        })}
+      </div>
+    </div>
+  );
+}
-- 
cgit v1.2.3

