diff --git a/public/manifest.json b/public/manifest.json index 53370a4..7232a76 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -19,7 +19,7 @@ "sizes": "512x512" } ], - "start_url": ".", + "start_url": "/", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" diff --git a/src/components/header/components/settingsDropdown/settingsOverlay/SettingsOverlay/SettingsOverlay.tsx b/src/components/header/components/settingsDropdown/settingsOverlay/SettingsOverlay/SettingsOverlay.tsx index 40218f2..bf44d64 100644 --- a/src/components/header/components/settingsDropdown/settingsOverlay/SettingsOverlay/SettingsOverlay.tsx +++ b/src/components/header/components/settingsDropdown/settingsOverlay/SettingsOverlay/SettingsOverlay.tsx @@ -6,33 +6,28 @@ import { NightModeSettings } from '../nightModeSettings/NightModeSettings'; import { ThemePicker } from '../ThemePicker/ThemePicker'; import { BaseButton } from '@app/components/common/BaseButton/BaseButton'; import { useAppSelector } from '@app/hooks/reduxHooks'; +import { useAppDispatch } from '@app/hooks/reduxHooks'; +import { setShowAlert } from '@app/store/slices/pwaSlice'; import * as S from './SettingsOverlay.styles'; +import { Alert } from 'antd'; export const SettingsOverlay: React.FC = ({ ...props }) => { const { t } = useTranslation(); - const { isPWASupported } = useAppSelector((state) => state.pwa); - const [promptEvent, setPromptEvent] = useState(null); - - useEffect(() => { - const handler = (e: Event) => { - e.preventDefault(); - console.log('beforeinstallprompt event fired'); - setPromptEvent(e as any); - }; - - window.addEventListener('beforeinstallprompt', handler as EventListener); - - return () => { - window.removeEventListener('beforeinstallprompt', handler as EventListener); - }; - }, []); - - useEffect(() => { - if (promptEvent) { - console.log('Prompt event set:', promptEvent); + + const dispatch = useAppDispatch(); + const { isPWASupported, event } = useAppSelector((state) => state.pwa); + + const handleInstallClick = () => { + console.log('event', event); + if (event == null) { + // Display an alert if event is not available + console.log('Event is not available'); + dispatch(setShowAlert(true)); + return; } - }, [promptEvent]); + (event as BeforeInstallPromptEvent).prompt(); + }; return ( @@ -46,9 +41,9 @@ export const SettingsOverlay: React.FC = ({ ...props }) => { {t('header.logout')} - {isPWASupported && promptEvent && ( + {isPWASupported && ( - (promptEvent as any).prompt()}> + {t('common.pwa')} diff --git a/src/components/layouts/main/MainLayout/MainLayout.tsx b/src/components/layouts/main/MainLayout/MainLayout.tsx index f2c5c30..dc01b3a 100644 --- a/src/components/layouts/main/MainLayout/MainLayout.tsx +++ b/src/components/layouts/main/MainLayout/MainLayout.tsx @@ -4,6 +4,8 @@ import MainSider from '../sider/MainSider/MainSider'; import MainContent from '../MainContent/MainContent'; import { MainHeader } from '../MainHeader/MainHeader'; import * as S from './MainLayout.styles'; +import { setShowAlert } from '@app/store/slices/pwaSlice'; + import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import { MEDICAL_DASHBOARD_PATH, @@ -16,15 +18,21 @@ import { References } from '@app/components/common/References/References'; import { useAppDispatch } from '@app/hooks/reduxHooks'; import { doLogout } from '@app/store/slices/authSlice'; import useIdleTimer from '@app/hooks/useIdleTimer'; +import { Alert, theme } from 'antd'; +import { useAppSelector } from '@app/hooks/reduxHooks'; +import { themeObject } from '@app/styles/themes/themeVariables'; const MainLayout: React.FC = () => { const [isTwoColumnsLayout, setIsTwoColumnsLayout] = useState(true); const [siderCollapsed, setSiderCollapsed] = useState(true); + const { isDesktop } = useResponsive(); const location = useLocation(); const dispatch = useAppDispatch(); const navigate = useNavigate(); + const { showAlert } = useAppSelector((state) => state.pwa); + const theme = useAppSelector((state) => state.theme.theme); const toggleSider = () => setSiderCollapsed(!siderCollapsed); useEffect(() => { @@ -61,6 +69,33 @@ const MainLayout: React.FC = () => { {!isTwoColumnsLayout && } + {showAlert && ( +
+ dispatch(setShowAlert(false))} + style={{ + color: 'black', + width: 'fit-content', + + backgroundColor: themeObject[theme].notificationWarning, + }} + /> +
+ )} ); diff --git a/src/hooks/usePWA.ts b/src/hooks/usePWA.ts index 305465e..f2a4804 100644 --- a/src/hooks/usePWA.ts +++ b/src/hooks/usePWA.ts @@ -1,32 +1,18 @@ import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; -import { setPWASupported } from '@app/store/slices/pwaSlice'; +import { addDeferredPrompt } from '@app/store/slices/pwaSlice'; -export const usePWA = () => { +export const usePWA = (): void => { const dispatch = useDispatch(); useEffect(() => { - const handler = (e: Event) => { + const handler = (e: any) => { e.preventDefault(); - // Assuming e is the BeforeInstallPromptEvent - // Instead of storing the event, we just indicate support is available - dispatch(setPWASupported(true)); + console.log(e); + dispatch(addDeferredPrompt(e)); }; window.addEventListener('beforeinstallprompt', handler); - - console.log('Setting up global beforeinstallprompt listener'); - window.addEventListener('beforeinstallprompt', (e) => { - e.preventDefault(); - console.log('Global beforeinstallprompt event fired and stored'); - (window as any).deferredPrompt = e; - }); - - return () => { - window.removeEventListener('beforeinstallprompt', handler); - // Optionally, dispatch that PWA is no longer supported if the event is dismissed - dispatch(setPWASupported(false)); - }; }, [dispatch]); }; diff --git a/src/store/slices/pwaSlice.ts b/src/store/slices/pwaSlice.ts index d198913..4b87c54 100644 --- a/src/store/slices/pwaSlice.ts +++ b/src/store/slices/pwaSlice.ts @@ -2,7 +2,9 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; // Define the initial state using only serializable values const initialState = { + event: null as BeforeInstallPromptEvent | null, isPWASupported: false, + showAlert: false, isStandalone: window.matchMedia('(display-mode: standalone)').matches, }; @@ -18,11 +20,18 @@ export const pwaSlice = createSlice({ clearPWASupport: (state) => { state.isPWASupported = false; }, + addDeferredPrompt: (state, action: PayloadAction) => { + state.event = action.payload; + state.isPWASupported = true; + }, + setShowAlert: (state, action: PayloadAction) => { + state.showAlert = action.payload; + }, }, }); // Exporting actions -export const { setPWASupported, clearPWASupport } = pwaSlice.actions; +export const { setPWASupported, clearPWASupport, addDeferredPrompt, setShowAlert } = pwaSlice.actions; export default pwaSlice.reducer; diff --git a/src/store/store.ts b/src/store/store.ts index acc491b..07e7996 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -14,7 +14,10 @@ const initialState = { export const store = configureStore({ reducer: rootReducer, - middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(errorLoggingMiddleware), + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: false, + }).concat(errorLoggingMiddleware), preloadedState: initialState, }); diff --git a/src/styles/GlobalStyle.ts b/src/styles/GlobalStyle.ts index db27d79..cd36054 100644 --- a/src/styles/GlobalStyle.ts +++ b/src/styles/GlobalStyle.ts @@ -70,7 +70,6 @@ export default createGlobalStyle` .ant-picker-cell { color: var(--text-main-color); } - .ant-picker-cell-in-view .ant-picker-calendar-date-value { color: var(--text-main-color); font-weight: ${FONT_WEIGHT.bold}; @@ -205,6 +204,9 @@ export default createGlobalStyle` background-color: white; border-color: themeObject[theme].textMain; } + .ant-alert-message{ + color: black + } .custom-checkbox-group .ant-checkbox-checked .ant-checkbox-inner { background-color: #1890ff;