diff --git a/backend/src/common/types.ts b/backend/src/common/types.ts
index 9e89be644..dabdae257 100644
--- a/backend/src/common/types.ts
+++ b/backend/src/common/types.ts
@@ -248,7 +248,10 @@ export type ColumnDefinitionType =
| 'cargo'
| 'island'
| 'wind'
- | 'rock';
+ | 'rock'
+ | 'mad'
+ | 'sad'
+ | 'glad';
export type StripeLocales =
| 'ar-AR'
diff --git a/docs/docs/self-hosting/optionals.md b/docs/docs/self-hosting/optionals.md
index 85cf4188c..4b66dc142 100644
--- a/docs/docs/self-hosting/optionals.md
+++ b/docs/docs/self-hosting/optionals.md
@@ -119,6 +119,7 @@ services:
FRONTEND_GIPHY_API_KEY: '' # Optional, can be obtained here: https://developers.giphy.com/
FRONTEND_DEFAULT_LANGUAGE: 'en-GB' # Set the default language for new users
FRONTEND_MARKETING_ROOT: 'https://www.retrospected.com' # URL of the marketing website
+ FRONTEND_AI_FEEDBACK_URL: 'http://' # URL of a freeform feedback form for AI feedback
# -- Do Not Change --
BACKEND_HOST: backend # This should be the name of the backend service
diff --git a/frontend/.env b/frontend/.env
index 808fa5753..913a3b3ef 100644
--- a/frontend/.env
+++ b/frontend/.env
@@ -1,7 +1,11 @@
+# Do not fill any of these values except VITE_VERSION
+# use the .env.local file instead
+
VITE_VERSION=$npm_package_version
VITE_STRIPE_KEY=
VITE_GIPHY_API_KEY=
-VITE_MARKETING_ROOT=http://localhost:3001
+VITE_MARKETING_ROOT=
VITE_GOOGLE_ANALYTICS_ID=
VITE_GOOGLE_AD_WORDS_ID=
VITE_GOOGLE_AD_WORDS_CONVERSION_ID=
+VITE_AI_FEEDBACK_URL=
\ No newline at end of file
diff --git a/frontend/index.html b/frontend/index.html
index 639ae3ecf..4346a25db 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -77,11 +77,14 @@
.loader {
font-size: 5rem;
font-weight: bold;
+ padding: 0;
+ margin: 0;
+ display: flex;
}
@keyframes blink {
50% { color: transparent }
}
- .loader__dot { animation: 1s blink infinite }
+ .loader__dot { animation: 1s blink infinite; padding: 0; margin: 0; display: block; }
.loader__dot:nth-child(2) { animation-delay: 250ms }
.loader__dot:nth-child(3) { animation-delay: 500ms }
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 670443a9e..404cf33b2 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -14,11 +14,12 @@ import { Suspense } from 'react';
import { CodeSplitLoader } from './CodeSplitLoader';
import QuotaManager from './auth/QuotaManager';
import { ConfirmProvider } from 'material-ui-confirm';
+import { FullScreenLoader } from 'components/loaders/FullScreenLoader';
function App() {
return (
-
-
+
+ }>
-
-
+
+
);
}
diff --git a/frontend/src/Layout.tsx b/frontend/src/Layout.tsx
index 8a0a4383d..5ba6b1a26 100644
--- a/frontend/src/Layout.tsx
+++ b/frontend/src/Layout.tsx
@@ -3,13 +3,13 @@ import { Routes, Route, useLocation } from 'react-router-dom';
import { trackPageView } from './track';
import useIsCompatibleBrowser from './hooks/useIsCompatibleBrowser';
import OutdatedBrowser from './components/OutdatedBrowser';
-import useUser from './auth/useUser';
import { CodeSplitLoader } from './CodeSplitLoader';
import { Alert, AlertTitle } from '@mui/material';
import useBackendCapabilities from './global/useBackendCapabilities';
import { useTranslation } from 'react-i18next';
import { Welcome } from 'views/Welcome';
import { Header } from 'views/layout/Header';
+import useUser from 'state/user/useUser';
const Home = lazy(() => import('./views/Home'));
const Game = lazy(() => import('./views/Game'));
diff --git a/frontend/src/auth/AccountMenu.tsx b/frontend/src/auth/AccountMenu.tsx
index 5598c632e..0b8b2f08d 100644
--- a/frontend/src/auth/AccountMenu.tsx
+++ b/frontend/src/auth/AccountMenu.tsx
@@ -1,13 +1,12 @@
-import { useCallback, useState, useRef, useContext } from 'react';
+import { useCallback, useState, useRef } from 'react';
import styled from '@emotion/styled';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import Button from '@mui/material/Button';
import AccountIcon from '@mui/icons-material/AccountCircle';
-import useUser from './useUser';
+import useUser from '../state/user/useUser';
import LoginModal from './modal/LoginModal';
import { logout } from '../api';
-import UserContext from './Context';
import Avatar from '../components/Avatar';
import { useMatch, useNavigate } from 'react-router-dom';
import { Key, Logout, Star } from '@mui/icons-material';
@@ -21,10 +20,11 @@ import {
import AccountCircle from '@mui/icons-material/AccountCircle';
import useIsAdmin from './useIsAdmin';
import { useTranslation } from 'react-i18next';
+import { useSetUser } from 'state/user/useSetUser';
const AccountMenu = () => {
const { t } = useTranslation();
- const { setUser } = useContext(UserContext);
+ const setUser = useSetUser();
const [modalOpened, setModalOpen] = useState(false);
const [menuOpen, setMenuOpen] = useState(false);
const menuAnchor = useRef(null);
@@ -79,20 +79,18 @@ const AccountMenu = () => {
ref={menuAnchor}
data-cy="account-menu"
>
-
{user.name}
{user.accountType === 'anonymous' ? (
) : null}
-
-
-
+
{menuAnchor.current ? (