diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 62acd1c0c..38ddaa79c 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -5,10 +5,17 @@ import { AppRoutes } from '@/routes/AppRoutes';
import { ThemeProvider } from '@/contexts/ThemeContext';
import QueryClientProviders from '@/config/QueryClientProvider';
import { GlobalLoader } from './components/Loader/GlobalLoader';
+import { InfoDialog } from './components/Dialog/InfoDialog';
import { useSelector } from 'react-redux';
import { RootState } from './app/store';
const App: React.FC = () => {
const { loading, message } = useSelector((state: RootState) => state.loader);
+ const {
+ isOpen,
+ title,
+ message: infoMessage,
+ variant,
+ } = useSelector((state: RootState) => state.infoDialog);
return (
@@ -16,6 +23,7 @@ const App: React.FC = () => {
+
);
diff --git a/frontend/src/app/store.ts b/frontend/src/app/store.ts
index d2849c5d8..4c4d02206 100644
--- a/frontend/src/app/store.ts
+++ b/frontend/src/app/store.ts
@@ -1,10 +1,13 @@
import { configureStore } from '@reduxjs/toolkit';
import loaderReducer from '@/features/loaderSlice';
import onboardingReducer from '@/features/onboardingSlice';
+import infoDialogReducer from '@/features/infoDialogSlice';
+
export const store = configureStore({
reducer: {
loader: loaderReducer,
onboarding: onboardingReducer,
+ infoDialog: infoDialogReducer,
},
});
diff --git a/frontend/src/components/Dialog/InfoDialog.tsx b/frontend/src/components/Dialog/InfoDialog.tsx
new file mode 100644
index 000000000..7226aa9d5
--- /dev/null
+++ b/frontend/src/components/Dialog/InfoDialog.tsx
@@ -0,0 +1,69 @@
+import React from 'react';
+import { Info, AlertTriangle } from 'lucide-react';
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+ DialogFooter,
+} from '@/components/ui/dialog';
+import { Button } from '@/components/ui/button';
+import { InfoDialogProps } from '@/types/infoDialog';
+import { useDispatch } from 'react-redux';
+import { hideInfoDialog } from '@/features/infoDialogSlice';
+
+export const InfoDialog: React.FC = ({
+ isOpen,
+ title,
+ message,
+ variant = 'info',
+}) => {
+ const dispatch = useDispatch();
+
+ const handleClose = () => {
+ dispatch(hideInfoDialog());
+ };
+
+ // Define styles and icons based on variant
+ const variantStyles = {
+ info: {
+ iconColor: 'text-primary',
+ messageColor: '',
+ icon: ,
+ buttonVariant: 'default' as const,
+ },
+ error: {
+ iconColor: 'text-destructive',
+ messageColor: 'text-destructive',
+ icon: ,
+ buttonVariant: 'destructive' as const,
+ },
+ };
+
+ const { icon, iconColor, messageColor, buttonVariant } = variantStyles[variant];
+
+ return (
+
+ );
+};
diff --git a/frontend/src/features/infoDialogSlice.ts b/frontend/src/features/infoDialogSlice.ts
new file mode 100644
index 000000000..cd828ecce
--- /dev/null
+++ b/frontend/src/features/infoDialogSlice.ts
@@ -0,0 +1,38 @@
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+import { InfoDialogProps, InfoDialogVariant } from '@/types/infoDialog';
+
+const initialState: InfoDialogProps = {
+ isOpen: false,
+ title: '',
+ message: '',
+ variant: 'info',
+};
+
+const infoDialogSlice = createSlice({
+ name: 'infoDialog',
+ initialState,
+ reducers: {
+ showInfoDialog(
+ state,
+ action: PayloadAction<{
+ title: string;
+ message: string;
+ variant?: InfoDialogVariant;
+ }>,
+ ) {
+ state.isOpen = true;
+ state.title = action.payload.title;
+ state.message = action.payload.message;
+ state.variant = action.payload.variant || 'info';
+ },
+ hideInfoDialog(state) {
+ state.isOpen = false;
+ state.title = '';
+ state.message = '';
+ state.variant = 'info';
+ },
+ },
+});
+
+export const { showInfoDialog, hideInfoDialog } = infoDialogSlice.actions;
+export default infoDialogSlice.reducer;
diff --git a/frontend/src/pages/SettingsPage/Settings.tsx b/frontend/src/pages/SettingsPage/Settings.tsx
index 61a7b400a..7635c8745 100644
--- a/frontend/src/pages/SettingsPage/Settings.tsx
+++ b/frontend/src/pages/SettingsPage/Settings.tsx
@@ -17,6 +17,7 @@ import { usePictoMutation } from '@/hooks/useQueryExtensio';
import { useDispatch } from 'react-redux';
import { showLoader, hideLoader } from '@/features/loaderSlice';
+import { showInfoDialog } from '@/features/infoDialogSlice';
import {
deleteFolder,
@@ -84,6 +85,16 @@ const Settings: React.FC = () => {
const hasUpdate = await checkForUpdates();
if (hasUpdate) {
setUpdateDialogOpen(true);
+ } else {
+ // Show info dialog when no updates are available
+ dispatch(
+ showInfoDialog({
+ title: 'No Updates Available',
+ message:
+ 'Your application is already up to date with the latest version.',
+ variant: 'info',
+ }),
+ );
}
dispatch(hideLoader());
};
@@ -113,9 +124,23 @@ const Settings: React.FC = () => {
const result = await deleteCache();
if (result) {
console.log('Cache deleted');
+ dispatch(
+ showInfoDialog({
+ title: 'Cache Refreshed',
+ message: 'The application cache has been successfully refreshed.',
+ variant: 'info',
+ }),
+ );
}
} catch (error) {
console.error('Error deleting cache:', error);
+ dispatch(
+ showInfoDialog({
+ title: 'Cache Refresh Error',
+ message: 'Failed to refresh the application cache. Please try again.',
+ variant: 'error',
+ }),
+ );
}
};
@@ -134,10 +159,21 @@ const Settings: React.FC = () => {
};
const showErrorDialog = (title: string, err: unknown) => {
+ const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
+
+ // Use the InfoDialog with error variant for consistent UI
+ dispatch(
+ showInfoDialog({
+ title,
+ message: errorMessage,
+ variant: 'error',
+ }),
+ );
+
+ // Also set the legacy error dialog content for backward compatibility
setErrorDialogContent({
title,
- description:
- err instanceof Error ? err.message : 'An unknown error occurred',
+ description: errorMessage,
});
};
@@ -235,7 +271,6 @@ const Settings: React.FC = () => {
-
setErrorDialogContent(null)}
diff --git a/frontend/src/types/infoDialog.ts b/frontend/src/types/infoDialog.ts
new file mode 100644
index 000000000..342654375
--- /dev/null
+++ b/frontend/src/types/infoDialog.ts
@@ -0,0 +1,8 @@
+export type InfoDialogVariant = 'info' | 'error';
+
+export interface InfoDialogProps {
+ isOpen: boolean;
+ title: string;
+ message: string;
+ variant?: InfoDialogVariant;
+}