Skip to content

Commit a233e71

Browse files
Merge pull request #488 from Hemil36/InfoDialog-Feature
Add InfoDialog component and integrate with Redux for state management
2 parents f70f2f7 + 6ece99b commit a233e71

File tree

6 files changed

+164
-3
lines changed

6 files changed

+164
-3
lines changed

frontend/src/App.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,25 @@ import { AppRoutes } from '@/routes/AppRoutes';
55
import { ThemeProvider } from '@/contexts/ThemeContext';
66
import QueryClientProviders from '@/config/QueryClientProvider';
77
import { GlobalLoader } from './components/Loader/GlobalLoader';
8+
import { InfoDialog } from './components/Dialog/InfoDialog';
89
import { useSelector } from 'react-redux';
910
import { RootState } from './app/store';
1011
const App: React.FC = () => {
1112
const { loading, message } = useSelector((state: RootState) => state.loader);
13+
const {
14+
isOpen,
15+
title,
16+
message: infoMessage,
17+
variant,
18+
} = useSelector((state: RootState) => state.infoDialog);
1219
return (
1320
<ThemeProvider>
1421
<QueryClientProviders>
1522
<BrowserRouter>
1623
<AppRoutes />
1724
</BrowserRouter>
1825
<GlobalLoader loading={loading} message={message} />
26+
<InfoDialog isOpen={isOpen} title={title} message={infoMessage} variant={variant} />
1927
</QueryClientProviders>
2028
</ThemeProvider>
2129
);

frontend/src/app/store.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { configureStore } from '@reduxjs/toolkit';
22
import loaderReducer from '@/features/loaderSlice';
33
import onboardingReducer from '@/features/onboardingSlice';
4+
import infoDialogReducer from '@/features/infoDialogSlice';
5+
46
export const store = configureStore({
57
reducer: {
68
loader: loaderReducer,
79
onboarding: onboardingReducer,
10+
infoDialog: infoDialogReducer,
811
},
912
});
1013

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import React from 'react';
2+
import { Info, AlertTriangle } from 'lucide-react';
3+
import {
4+
Dialog,
5+
DialogContent,
6+
DialogDescription,
7+
DialogHeader,
8+
DialogTitle,
9+
DialogFooter,
10+
} from '@/components/ui/dialog';
11+
import { Button } from '@/components/ui/button';
12+
import { InfoDialogProps } from '@/types/infoDialog';
13+
import { useDispatch } from 'react-redux';
14+
import { hideInfoDialog } from '@/features/infoDialogSlice';
15+
16+
export const InfoDialog: React.FC<InfoDialogProps> = ({
17+
isOpen,
18+
title,
19+
message,
20+
variant = 'info',
21+
}) => {
22+
const dispatch = useDispatch();
23+
24+
const handleClose = () => {
25+
dispatch(hideInfoDialog());
26+
};
27+
28+
// Define styles and icons based on variant
29+
const variantStyles = {
30+
info: {
31+
iconColor: 'text-primary',
32+
messageColor: '',
33+
icon: <Info className="h-5 w-5" />,
34+
buttonVariant: 'default' as const,
35+
},
36+
error: {
37+
iconColor: 'text-destructive',
38+
messageColor: 'text-destructive',
39+
icon: <AlertTriangle className="h-5 w-5" />,
40+
buttonVariant: 'destructive' as const,
41+
},
42+
};
43+
44+
const { icon, iconColor, messageColor, buttonVariant } = variantStyles[variant];
45+
46+
return (
47+
<Dialog
48+
open={isOpen}
49+
onOpenChange={(open) => {
50+
if (!open) handleClose();
51+
}}
52+
>
53+
<DialogContent className="sm:max-w-md">
54+
<DialogHeader>
55+
<DialogTitle className="flex items-center gap-2">
56+
<span className={iconColor}>{icon}</span>
57+
{title}
58+
</DialogTitle>
59+
<DialogDescription className={messageColor}>{message}</DialogDescription>
60+
</DialogHeader>
61+
<DialogFooter>
62+
<Button variant={buttonVariant} onClick={handleClose}>
63+
Close
64+
</Button>
65+
</DialogFooter>
66+
</DialogContent>
67+
</Dialog>
68+
);
69+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2+
import { InfoDialogProps, InfoDialogVariant } from '@/types/infoDialog';
3+
4+
const initialState: InfoDialogProps = {
5+
isOpen: false,
6+
title: '',
7+
message: '',
8+
variant: 'info',
9+
};
10+
11+
const infoDialogSlice = createSlice({
12+
name: 'infoDialog',
13+
initialState,
14+
reducers: {
15+
showInfoDialog(
16+
state,
17+
action: PayloadAction<{
18+
title: string;
19+
message: string;
20+
variant?: InfoDialogVariant;
21+
}>,
22+
) {
23+
state.isOpen = true;
24+
state.title = action.payload.title;
25+
state.message = action.payload.message;
26+
state.variant = action.payload.variant || 'info';
27+
},
28+
hideInfoDialog(state) {
29+
state.isOpen = false;
30+
state.title = '';
31+
state.message = '';
32+
state.variant = 'info';
33+
},
34+
},
35+
});
36+
37+
export const { showInfoDialog, hideInfoDialog } = infoDialogSlice.actions;
38+
export default infoDialogSlice.reducer;

frontend/src/pages/SettingsPage/Settings.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { usePictoMutation } from '@/hooks/useQueryExtensio';
1717

1818
import { useDispatch } from 'react-redux';
1919
import { showLoader, hideLoader } from '@/features/loaderSlice';
20+
import { showInfoDialog } from '@/features/infoDialogSlice';
2021

2122
import {
2223
deleteFolder,
@@ -84,6 +85,16 @@ const Settings: React.FC = () => {
8485
const hasUpdate = await checkForUpdates();
8586
if (hasUpdate) {
8687
setUpdateDialogOpen(true);
88+
} else {
89+
// Show info dialog when no updates are available
90+
dispatch(
91+
showInfoDialog({
92+
title: 'No Updates Available',
93+
message:
94+
'Your application is already up to date with the latest version.',
95+
variant: 'info',
96+
}),
97+
);
8798
}
8899
dispatch(hideLoader());
89100
};
@@ -113,9 +124,23 @@ const Settings: React.FC = () => {
113124
const result = await deleteCache();
114125
if (result) {
115126
console.log('Cache deleted');
127+
dispatch(
128+
showInfoDialog({
129+
title: 'Cache Refreshed',
130+
message: 'The application cache has been successfully refreshed.',
131+
variant: 'info',
132+
}),
133+
);
116134
}
117135
} catch (error) {
118136
console.error('Error deleting cache:', error);
137+
dispatch(
138+
showInfoDialog({
139+
title: 'Cache Refresh Error',
140+
message: 'Failed to refresh the application cache. Please try again.',
141+
variant: 'error',
142+
}),
143+
);
119144
}
120145
};
121146

@@ -134,10 +159,21 @@ const Settings: React.FC = () => {
134159
};
135160

136161
const showErrorDialog = (title: string, err: unknown) => {
162+
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
163+
164+
// Use the InfoDialog with error variant for consistent UI
165+
dispatch(
166+
showInfoDialog({
167+
title,
168+
message: errorMessage,
169+
variant: 'error',
170+
}),
171+
);
172+
173+
// Also set the legacy error dialog content for backward compatibility
137174
setErrorDialogContent({
138175
title,
139-
description:
140-
err instanceof Error ? err.message : 'An unknown error occurred',
176+
description: errorMessage,
141177
});
142178
};
143179

@@ -235,7 +271,6 @@ const Settings: React.FC = () => {
235271
</p>
236272
</div>
237273
</div>
238-
239274
<ErrorDialog
240275
content={errorDialogContent}
241276
onClose={() => setErrorDialogContent(null)}

frontend/src/types/infoDialog.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export type InfoDialogVariant = 'info' | 'error';
2+
3+
export interface InfoDialogProps {
4+
isOpen: boolean;
5+
title: string;
6+
message: string;
7+
variant?: InfoDialogVariant;
8+
}

0 commit comments

Comments
 (0)