瀏覽代碼

fix: custom 404 page & styling fixes

Nicolas Meienberger 2 年之前
父節點
當前提交
f3dff9c576

+ 13 - 2
packages/dashboard/src/components/StatusScreen/StatusScreen.tsx

@@ -1,13 +1,17 @@
 import Image from 'next/image';
 import React from 'react';
 import { getUrl } from '../../core/helpers/url-helpers';
+import { Button } from '../ui/Button';
 
 interface IProps {
   title: string;
   subtitle: string;
+  onAction?: () => void;
+  actionTitle?: string;
+  loading?: boolean;
 }
 
-export const StatusScreen: React.FC<IProps> = ({ title, subtitle }) => (
+export const StatusScreen: React.FC<IProps> = ({ title, subtitle, onAction, actionTitle, loading = true }) => (
   <div className="page page-center">
     <div className="container container-tight py-4 d-flex align-items-center flex-column">
       <Image
@@ -23,7 +27,14 @@ export const StatusScreen: React.FC<IProps> = ({ title, subtitle }) => (
       />
       <h1 className="text-center mb-1">{title}</h1>
       <div className="text-center text-muted mb-3">{subtitle}</div>
-      <div className="spinner-border spinner-border-sm text-muted" />
+      {loading && <div className="spinner-border spinner-border-sm text-muted" />}
+      {onAction && (
+        <div className="empty-action">
+          <Button onClick={onAction} className="btn">
+            {actionTitle}
+          </Button>
+        </div>
+      )}
     </div>
   </div>
 );

+ 2 - 1
packages/dashboard/src/components/ui/EmptyPage/EmptyPage.tsx

@@ -1,3 +1,4 @@
+import clsx from 'clsx';
 import Image from 'next/image';
 import React from 'react';
 import { getUrl } from '../../../core/helpers/url-helpers';
@@ -18,7 +19,7 @@ export const EmptyPage: React.FC<IProps> = ({ title, subtitle, onAction, actionL
       alt="Empty box"
       height="80"
       width="80"
-      className={styles.emptyImage}
+      className={clsx(styles.emptyImage, 'mb-3')}
       style={{
         maxWidth: '100%',
         height: 'auto',

+ 5 - 2
packages/dashboard/src/components/ui/Header/Header.tsx

@@ -3,6 +3,7 @@ import { IconBrandGithub, IconHeart, IconLogout, IconMoon, IconSun } from '@tabl
 import Image from 'next/image';
 import clsx from 'clsx';
 import router from 'next/router';
+import Link from 'next/link';
 import { getUrl } from '../../../core/helpers/url-helpers';
 import { useUIStore } from '../../../state/uiStore';
 import { NavBar } from '../NavBar';
@@ -28,22 +29,24 @@ export const Header: React.FC<IProps> = ({ isUpdateAvailable }) => {
         <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu">
           <span className="navbar-toggler-icon" />
         </button>
-        <a href="/">
+        <Link href="/" passHref>
           <h1 className="navbar-brand d-none-navbar-horizontal pe-0 pe-md-3">
             <Image
+              priority
               alt="Tipi logo"
               className={clsx('navbar-brand-image me-3')}
               width={100}
               height={100}
               src={getUrl('tipi.png')}
               style={{
+                width: '30px',
                 maxWidth: '30px',
                 height: 'auto',
               }}
             />
             Tipi
           </h1>
-        </a>
+        </Link>
         <div className="navbar-nav flex-row order-md-last">
           <div className="nav-item d-none d-lg-flex me-3">
             <div className="btn-list">

+ 0 - 5
packages/dashboard/src/hooks/useCachedRessources.ts

@@ -1,7 +1,6 @@
 import { useEffect, useState } from 'react';
 import { ApolloClient } from '@apollo/client';
 import { createApolloClient } from '../core/apollo/client';
-import { initMocks } from '../mocks';
 
 interface IReturnProps {
   client?: ApolloClient<unknown>;
@@ -13,10 +12,6 @@ export default function useCachedResources(): IReturnProps {
   const [client, setClient] = useState<ApolloClient<unknown>>();
 
   async function loadResourcesAndDataAsync() {
-    if (process.env.NEXT_PUBLIC_API_MOCKING === 'enabled') {
-      await initMocks();
-    }
-
     try {
       const restoredClient = createApolloClient();
 

+ 4 - 2
packages/dashboard/src/modules/Auth/containers/RegisterContainer/RegisterContainer.tsx

@@ -30,11 +30,13 @@ export const RegisterContainer: React.FC = () => {
       if (data?.register?.token) {
         localStorage.setItem('token', data.register.token);
         router.reload();
+      } else {
+        setLoading(false);
+        handleError(new Error('Something went wrong'));
       }
     } catch (error) {
-      handleError(error);
-    } finally {
       setLoading(false);
+      handleError(error);
     }
   };
 

+ 15 - 0
packages/dashboard/src/pages/404.tsx

@@ -0,0 +1,15 @@
+import { useRouter } from 'next/router';
+import React from 'react';
+import { StatusScreen } from '../components/StatusScreen';
+
+const ErrorPage: React.FC = () => {
+  const router = useRouter();
+
+  const handleHome = () => {
+    router.push('/');
+  };
+
+  return <StatusScreen loading={false} title="404" subtitle="Page not found" actionTitle="Home page" onAction={handleHome} />;
+};
+
+export default ErrorPage;

+ 0 - 5
packages/dashboard/src/pages/_app.tsx

@@ -11,11 +11,6 @@ import { StatusProvider } from '../components/hoc/StatusProvider';
 import { AuthProvider } from '../components/hoc/AuthProvider';
 import { StatusScreen } from '../components/StatusScreen';
 
-if (process.env.NEXT_PUBLIC_API_MOCKING === 'enabled') {
-  // eslint-disable-next-line global-require
-  require('../mocks');
-}
-
 function MyApp({ Component, pageProps }: AppProps) {
   const { setDarkMode } = useUIStore();
 

+ 6 - 0
packages/dashboard/src/styles/global.scss

@@ -1,2 +1,8 @@
 // import tabler scss
 @import '../../node_modules/@tabler/core/dist/css/tabler.min.css';
+
+@supports (font: -apple-system-body) and (-webkit-appearance: none) {
+  img[loading='lazy'] {
+    clip-path: inset(0.6px);
+  }
+}