samling 0.13.1

App for managing apparel collections
Documentation
import { Route, Routes } from "react-router-dom";

import React, { useEffect } from "react";
import NotFound from "./pages/app/errors/NotFound";
import NotFoundPublic from "./pages/public/errors/NotFoundPublic";
import LocaleNavigate from "./components/LocaleNavigate";
import SplashPage from "./pages/public/SplashPage";
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import { defaultLocale, dynamicActivate, useLocaleParam } from "./i18n";
import store from "./state/store";
import SignInPage from "./pages/public/SignInPage";
import SignOutPage from "./pages/app/SignOutPage";
import { debounce } from "debounce";
import { saveState } from "./browser-storage";
import UserMessagesList from "./components/UserMessagesList";
import { useAppSelector } from "./state/hooks";
import { GoogleOAuthProvider } from "@react-oauth/google";
import { MsalProvider } from "@azure/msal-react";
import { msalInstance } from "./msal";
import settings from "./settings";
import AdminLayout from "./pages/app/admin/AdminLayout";
import Loading from "./components/Loading";
import AdminGroupsPage from "./pages/app/admin/AdminGroups";
import AdminUsersPage from "./pages/app/admin/AdminUsers";
import AdminCollectionsPage from "./pages/app/admin/AdminCollections";

const AppLayout = React.lazy(() => import("./AppLayout"));
const HomeScreen = React.lazy(() => import("./pages/app/HomeScreen"));
const Collection = React.lazy(() => import("./pages/app/Collection"));
const Style = React.lazy(() => import("./pages/app/Style"));
const AdminHome = React.lazy(() => import("./pages/app/admin/AdminHome"));
const AdminEditGroup = React.lazy(
  () => import("./pages/app/admin/AdminEditGroup"),
);
const AdminEditUser = React.lazy(
  () => import("./pages/app/admin/AdminEditUser"),
);
const AdminEditCollection = React.lazy(
  () => import("./pages/app/admin/AdminEditCollection"),
);
const AdminCreateCollection = React.lazy(
  () => import("./pages/app/admin/AdminCreateCollection"),
);

export default function App() {
  const localeParam = useLocaleParam();
  const user = useAppSelector((state) => state.user.user);

  useEffect(() => {
    // Activate i18n/l10n for the locale specified for the route
    dynamicActivate(!localeParam ? defaultLocale : localeParam);
  }, [localeParam]);

  // Save Redux state on changes
  const saveStateDebounced = debounce(() => {
    const result = saveState(store.getState());
    result.mapErr((err) => {
      console.error(err);
    });
  }, 800);
  store.subscribe(saveStateDebounced);

  // Ensure that Redux state is persisted on user exit
  useEffect(() => {
    window.addEventListener("beforeunload", () => {
      saveStateDebounced.flush();
    });
  });

  return (
    <MsalProvider instance={msalInstance}>
      <GoogleOAuthProvider clientId={settings.googleClientId}>
        <I18nProvider i18n={i18n} forceRenderOnLocaleChange={false}>
          <UserMessagesList />
          <Routes>
            <Route path="/" element={<SplashPage />} caseSensitive></Route>
            <Route
              path="/app"
              element={<LocaleNavigate to="/app" />}
              caseSensitive
            ></Route>
            <Route path="/:locale/">
              <Route path="" element={<SplashPage />} caseSensitive />
              <Route path="auth/login" element={<SignInPage />}></Route>
              <Route path="auth/logout" element={<SignOutPage />}></Route>
              <Route
                path="app/"
                element={
                  <React.Suspense fallback={<Loading />}>
                    <AppLayout />
                  </React.Suspense>
                }
                caseSensitive
              >
                <Route
                  path=""
                  element={
                    <React.Suspense fallback={<Loading />}>
                      <HomeScreen />
                    </React.Suspense>
                  }
                  caseSensitive
                />
                <Route path="admin/" element={<AdminLayout />} caseSensitive>
                  <Route
                    path=""
                    element={
                      <React.Suspense fallback={<Loading />}>
                        <AdminHome />
                      </React.Suspense>
                    }
                    caseSensitive
                  />
                  <Route
                    path="groups"
                    element={
                      <React.Suspense fallback={<Loading />}>
                        <AdminGroupsPage />
                      </React.Suspense>
                    }
                    caseSensitive
                  />
                  <Route
                    path="groups/:groupSlug"
                    element={
                      <React.Suspense fallback={<Loading />}>
                        <AdminEditGroup />
                      </React.Suspense>
                    }
                    caseSensitive
                  />
                  <Route
                    path="users"
                    element={
                      <React.Suspense fallback={<Loading />}>
                        <AdminUsersPage />
                      </React.Suspense>
                    }
                    caseSensitive
                  />
                  <Route
                    path="users/:userId"
                    element={
                      <React.Suspense fallback={<Loading />}>
                        <AdminEditUser />
                      </React.Suspense>
                    }
                    caseSensitive
                  />
                  <Route
                    path="collections"
                    element={
                      <React.Suspense fallback={<Loading />}>
                        <AdminCollectionsPage />
                      </React.Suspense>
                    }
                    caseSensitive
                  />
                  <Route
                    path="collections/new"
                    element={
                      <React.Suspense fallback={<Loading />}>
                        <AdminCreateCollection />
                      </React.Suspense>
                    }
                    caseSensitive
                  />
                  <Route
                    path="collections/:collectionId"
                    element={
                      <React.Suspense fallback={<Loading />}>
                        <AdminEditCollection />
                      </React.Suspense>
                    }
                    caseSensitive
                  />
                </Route>
                <Route
                  path="collections/:collectionSlug"
                  element={
                    <React.Suspense fallback={<Loading />}>
                      <Collection />
                    </React.Suspense>
                  }
                  caseSensitive
                />
                <Route
                  path="collections/:collectionSlug/:styleSlug"
                  element={
                    <React.Suspense fallback={<Loading />}>
                      <Style />
                    </React.Suspense>
                  }
                  caseSensitive
                />
                <Route
                  path="collections/:collectionSlug/:styleSlug/:colorSlug"
                  element={
                    <React.Suspense fallback={<Loading />}>
                      <Style />
                    </React.Suspense>
                  }
                  caseSensitive
                />
                <Route
                  path="*"
                  element={user ? <NotFound /> : <NotFoundPublic />}
                />
              </Route>
              <Route path="*" element={<NotFoundPublic />} />
            </Route>
          </Routes>
        </I18nProvider>
      </GoogleOAuthProvider>
    </MsalProvider>
  );
}