diff --git a/client/src/app/components/index.tsx b/client/src/app/components/index.tsx
index e9a53eaaf..4f6369dbd 100644
--- a/client/src/app/components/index.tsx
+++ b/client/src/app/components/index.tsx
@@ -8,12 +8,16 @@ import { SIDEBAR_WIDTH } from '../../shared/components/organisms/sidebar/constan
import { Routes } from 'react-router-dom';
import getRoutesV1 from '../routes/auth-routes/v1';
-export const LoginLazyComponent = lazy(
- () => import('../../modules/user-auth-form/v1')
-);
+export const LoginLazyComponent = lazy(() => import('../../modules/auth/v1'));
export const HomePageLazyComponent = lazy(
() => import('../../modules/home/v1')
);
+export const ChatsPageLazyComponent = lazy(
+ () => import('../../modules/chats/v1')
+);
+export const CodePageLazyComponent = lazy(
+ () => import('../../modules/code/v1')
+);
export const SettingsPageLazyComponent = lazy(
() => import('../../modules/settings/v1')
);
diff --git a/client/src/app/routes/auth-routes/v1/index.tsx b/client/src/app/routes/auth-routes/v1/index.tsx
index aed905306..0e549dab8 100644
--- a/client/src/app/routes/auth-routes/v1/index.tsx
+++ b/client/src/app/routes/auth-routes/v1/index.tsx
@@ -5,7 +5,9 @@ import { LOADING } from '../../constants';
import Loader from '../../../../shared/components/molecules/loader';
import {
HomePageLazyComponent,
+ ChatsPageLazyComponent,
SettingsPageLazyComponent,
+ CodePageLazyComponent,
} from '../../../components';
export default function getRoutesV1() {
@@ -19,6 +21,24 @@ export default function getRoutesV1() {
}
/>,
+ }>
+
+
+ }
+ />,
+ }>
+
+
+ }
+ />,
{
- const theme = useTheme();
-
- return (
-
-
-
-
- Page not found
-
-
-
- The page you are looking for does not exist. Head back to the{' '}
-
- home page
-
- .
-
-
-
-
-
- Read millions of project scripts around the world.
-
-
-
- );
-};
-
-export default PageNotFound;
diff --git a/client/src/modules/user-auth-form/v1/hooks/index.ts b/client/src/modules/auth/v1/hooks/index.ts
similarity index 100%
rename from client/src/modules/user-auth-form/v1/hooks/index.ts
rename to client/src/modules/auth/v1/hooks/index.ts
diff --git a/client/src/modules/user-auth-form/v1/index.tsx b/client/src/modules/auth/v1/index.tsx
similarity index 100%
rename from client/src/modules/user-auth-form/v1/index.tsx
rename to client/src/modules/auth/v1/index.tsx
diff --git a/client/src/modules/chats/v1/index.tsx b/client/src/modules/chats/v1/index.tsx
new file mode 100644
index 000000000..f6dc52e6d
--- /dev/null
+++ b/client/src/modules/chats/v1/index.tsx
@@ -0,0 +1,11 @@
+import { Box } from '@mui/material';
+
+const Chats = () => {
+ return (
+
+ Chats
+
+ );
+};
+
+export default Chats;
diff --git a/client/src/modules/code/v1/index.tsx b/client/src/modules/code/v1/index.tsx
new file mode 100644
index 000000000..f848fd4f5
--- /dev/null
+++ b/client/src/modules/code/v1/index.tsx
@@ -0,0 +1,11 @@
+import { Box } from '@mui/material';
+
+const Code = () => {
+ return (
+
+ Code
+
+ );
+};
+
+export default Code;
diff --git a/client/src/modules/notification/constants/index.ts b/client/src/modules/notification/constants/index.ts
deleted file mode 100644
index 5ef1c59b4..000000000
--- a/client/src/modules/notification/constants/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const notificationFilters = ['all', 'like', 'comment', 'reply'];
diff --git a/client/src/modules/notification/index.tsx b/client/src/modules/notification/index.tsx
deleted file mode 100644
index 2126c8ae6..000000000
--- a/client/src/modules/notification/index.tsx
+++ /dev/null
@@ -1,227 +0,0 @@
-import { useEffect, useState, useRef, useCallback } from 'react';
-import NotificationCard from './components/notificationCard';
-import { notificationFilters } from './constants';
-import { useSetAtom } from 'jotai';
-import { NotificationsAtom } from './states';
-import useNotifications from './hooks';
-import { useAuth } from '../../shared/hooks/use-auth';
-import {
- Box,
- Typography,
- Button,
- ButtonGroup,
- List,
- Alert,
- CircularProgress,
-} from '@mui/material';
-import {
- Notifications as NotificationsIcon,
- Favorite,
- Comment,
- Reply,
-} from '@mui/icons-material';
-import { NOTIFICATION_FILTER_TYPE } from '../../infra/rest/typings';
-
-const Notifications = () => {
- const prevFilterRef = useRef(null);
- const setNotifications = useSetAtom(NotificationsAtom);
- const [filter, setFilter] = useState(
- NOTIFICATION_FILTER_TYPE.ALL
- );
- const { fetchNotifications, notifications } = useNotifications();
- const { isAuthenticated } = useAuth();
- const [isLoadingMore, setIsLoadingMore] = useState(false);
- const [isFilterLoading, setIsFilterLoading] = useState(false);
-
- // Avoid refetching notifications when the same filter is selected again
- useEffect(() => {
- if (!isAuthenticated()) return;
- if (prevFilterRef.current === filter && notifications !== null) {
- return;
- }
- prevFilterRef.current = filter;
- setIsFilterLoading(true);
- setNotifications(null);
- fetchNotifications({
- page: 1,
- filter,
- deletedDocCount: 0,
- }).finally(() => {
- setIsFilterLoading(false);
- });
- }, [
- filter,
- isAuthenticated,
- fetchNotifications,
- notifications,
- setNotifications,
- ]);
-
- const handleFilter = useCallback((filterName: string) => {
- setFilter(filterName as NOTIFICATION_FILTER_TYPE);
- }, []);
-
- const handleLoadMore = async () => {
- if (
- !notifications ||
- isLoadingMore ||
- notifications.results.length >= notifications.totalDocs
- ) {
- return;
- }
-
- try {
- setIsLoadingMore(true);
- await fetchNotifications({
- page: notifications.page + 1,
- filter,
- deletedDocCount: notifications.deleteDocCount || 0,
- });
- } finally {
- setIsLoadingMore(false);
- }
- };
-
- return (
-
-
-
- Notifications
-
-
- Stay updated with your latest activity and interactions
-
-
-
-
-
- {notificationFilters.map((filterName, i) => {
- const isActive = filter === filterName;
- return (
-
- );
- })}
-
-
-
- {notifications === null ? (
-
-
-
- ) : (
- <>
- {notifications.results.length ? (
-
- {notifications.results.map((notification, i) => (
-
- ))}
-
- ) : (
- }
- sx={{
- textAlign: 'center',
- py: 4,
- '& .MuiAlert-message': {
- width: '100%',
- },
- }}
- >
-
- No notifications yet
-
-
- {filter === NOTIFICATION_FILTER_TYPE.ALL
- ? "You're all caught up! Check back later for new notifications."
- : `No ${filter} notifications found.`}
-
-
- )}
-
- {notifications.results.length > 0 &&
- notifications.results.length < notifications.totalDocs && (
-
- : null
- }
- >
- {isLoadingMore ? 'Loading...' : 'Load More'}
-
-
- )}
- >
- )}
-
- );
-};
-
-export default Notifications;
diff --git a/client/src/modules/settings/modules/index.tsx b/client/src/modules/settings/modules/index.tsx
index 1a8ffba31..c246e9700 100644
--- a/client/src/modules/settings/modules/index.tsx
+++ b/client/src/modules/settings/modules/index.tsx
@@ -10,3 +10,6 @@ export const OpenAILazyComponentV1 = lazy(
export const ManageArticlesLazyComponentV1 = lazy(
() => import('./manage-articles/v1')
);
+export const NotificationLazyComponentV1 = lazy(
+ () => import('./notification/v1')
+);
diff --git a/client/src/modules/notification/components/notificationCard.tsx b/client/src/modules/settings/modules/notification/v1/components/notificationCard.tsx
similarity index 79%
rename from client/src/modules/notification/components/notificationCard.tsx
rename to client/src/modules/settings/modules/notification/v1/components/notificationCard.tsx
index 8148e9dbb..6455d15fa 100644
--- a/client/src/modules/notification/components/notificationCard.tsx
+++ b/client/src/modules/settings/modules/notification/v1/components/notificationCard.tsx
@@ -1,12 +1,12 @@
import { Link } from 'react-router-dom';
import { useState } from 'react';
-import { getDay } from '../../../shared/utils/date';
+import { getDay } from '../../../../../../shared/utils/date';
import NotificationCommentField from './notificationCommentField';
-import { GetNotificationsResponse } from '../../../infra/rest/apis/notification/typing';
+import { GetNotificationsResponse } from '../../../../../../infra/rest/apis/notification/typing';
import { NotificationPaginationState } from '../states';
-import { deleteComment } from '../../../infra/rest/apis/comment';
-import { useNotifications as useNotificationHook } from '../../../shared/hooks/use-notification';
-import { ROUTES_V1 } from '../../../app/routes/constants/routes';
+import { deleteComment } from '../../../../../../infra/rest/apis/comment';
+import { useNotifications as useNotificationHook } from '../../../../../../shared/hooks/use-notification';
+import { ROUTES_V1 } from '../../../../../../app/routes/constants/routes';
import {
ListItem,
ListItemAvatar,
@@ -106,13 +106,18 @@ const NotificationCard = ({
elevation={!seen ? 3 : 1}
sx={{
mb: 2,
- borderLeft: !seen ? 4 : 2,
+ borderRadius: 2,
+ borderLeftWidth: !seen ? 4 : 2,
+ borderLeftStyle: 'solid',
borderLeftColor: `${getNotificationColor()}.main`,
+ border: 1,
+ borderColor: 'divider',
+ bgcolor: 'background.paper',
position: 'relative',
+ transition: 'box-shadow 0.2s ease, transform 0.2s ease',
'&:hover': {
- boxShadow: theme => theme.shadows[4],
- transform: 'scale(1.01)',
- transition: 'all 0.2s ease-in-out',
+ boxShadow: theme => theme.shadows[3],
+ transform: 'translateY(-2px)',
},
}}
>
@@ -121,26 +126,26 @@ const NotificationCard = ({
`0 0 0 4px ${theme.palette.primary.main}20`,
}}
/>
)}
-
+
{type === 'like' ? (
-
+
) : type === 'comment' ? (
-
+
) : type === 'reply' ? (
-
+
) : (
-
+
)}
@@ -176,7 +181,15 @@ const NotificationCard = ({
+
@@ -256,13 +269,13 @@ const NotificationCard = ({
{type !== 'like' && comment_id?.comment && (
-
+
@@ -276,10 +289,12 @@ const NotificationCard = ({
@@ -314,7 +329,7 @@ const NotificationCard = ({
-
+
{
const [comment, setComment] = useState('');
- const user = useAtomValue(UserAtom);
- const { isAuthenticated } = useAuth();
const handleComment = () => {
if (!comment.length) {
@@ -29,11 +24,6 @@ const NotificationCommentField = ({
return;
}
- if (!isAuthenticated() || !user) {
- console.error('User not authenticated');
- return;
- }
-
axios
.post(
import.meta.env.VITE_SERVER_DOMAIN + '/api/comment',
@@ -74,11 +64,12 @@ const NotificationCommentField = ({
sx={{
'& .MuiOutlinedInput-root': {
resize: 'none',
+ bgcolor: 'background.paper',
'& fieldset': {
- borderColor: 'grey.300',
+ borderColor: 'divider',
},
'&:hover fieldset': {
- borderColor: 'grey.400',
+ borderColor: 'text.secondary',
},
'&.Mui-focused fieldset': {
borderColor: 'primary.main',
@@ -105,6 +96,8 @@ const NotificationCommentField = ({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
+ flexWrap: 'wrap',
+ gap: 1,
}}
>
+
+ )}
+ >
+ )}
+
+
+ );
+};
+
+export default Notifications;
diff --git a/client/src/modules/notification/states/index.ts b/client/src/modules/settings/modules/notification/v1/states/index.ts
similarity index 73%
rename from client/src/modules/notification/states/index.ts
rename to client/src/modules/settings/modules/notification/v1/states/index.ts
index cdd9986e4..89fbad099 100644
--- a/client/src/modules/notification/states/index.ts
+++ b/client/src/modules/settings/modules/notification/v1/states/index.ts
@@ -1,5 +1,5 @@
import { atom } from 'jotai';
-import { GetNotificationsResponse } from '../../../infra/rest/apis/notification/typing';
+import { GetNotificationsResponse } from '../../../../../../infra/rest/apis/notification/typing';
export interface NotificationPaginationState {
results: GetNotificationsResponse[];
diff --git a/client/src/modules/change-password/index.tsx b/client/src/modules/settings/modules/profile/v1/components/change-password.tsx
similarity index 89%
rename from client/src/modules/change-password/index.tsx
rename to client/src/modules/settings/modules/profile/v1/components/change-password.tsx
index 3493121bb..43285df9b 100644
--- a/client/src/modules/change-password/index.tsx
+++ b/client/src/modules/settings/modules/profile/v1/components/change-password.tsx
@@ -1,12 +1,12 @@
import { useRef, useState } from 'react';
-import { useNotifications } from '../../shared/hooks/use-notification';
-import { passwordRegex } from '../../shared/utils/regex';
-import { changePassword } from '../../infra/rest/apis/auth';
-import InputBox from '../../shared/components/atoms/input-box';
+import { useNotifications } from '../../../../../../shared/hooks/use-notification';
+import { passwordRegex } from '../../../../../../shared/utils/regex';
+import { changePassword } from '../../../../../../infra/rest/apis/auth';
+import InputBox from '../../../../../../shared/components/atoms/input-box';
import { Box, Button, Stack, CircularProgress } from '@mui/material';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import VpnKeyOutlinedIcon from '@mui/icons-material/VpnKeyOutlined';
-import A2ZTypography from '../../shared/components/atoms/typography';
+import A2ZTypography from '../../../../../../shared/components/atoms/typography';
const ChangePassword = () => {
const changePasswordForm = useRef(null);
diff --git a/client/src/modules/settings/routes/index.tsx b/client/src/modules/settings/routes/index.tsx
index b71b59e1d..a4b78246a 100644
--- a/client/src/modules/settings/routes/index.tsx
+++ b/client/src/modules/settings/routes/index.tsx
@@ -1,6 +1,7 @@
import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined';
import ExtensionIcon from '@mui/icons-material/Extension';
import ArticleIcon from '@mui/icons-material/Article';
+import NotificationsIcon from '@mui/icons-material/Notifications';
import {
ROUTES_V1,
ROUTES_SETTINGS_V1,
@@ -14,6 +15,7 @@ import {
IntegrationsLazyComponentV1,
OpenAILazyComponentV1,
ManageArticlesLazyComponentV1,
+ NotificationLazyComponentV1,
} from '../modules';
import OpenAIIcon from '../../../shared/icons/openai';
@@ -28,21 +30,28 @@ export const settingsRoutes = ({
icon: ,
path: ROUTES_SETTINGS_V1.PROFILE,
name: 'Your profile',
- description: 'Edit your personal details',
+ description: 'Manage your personal details and preferences',
+ },
+ {
+ id: 'notification',
+ icon: ,
+ path: ROUTES_SETTINGS_V1.NOTIFICATION,
+ name: 'Notifications',
+ description: 'Stay updated with your latest activity and interactions',
},
{
id: 'manage-articles',
icon: ,
path: ROUTES_SETTINGS_V1.MANAGE_ARTICLES,
name: 'Manage Articles',
- description: 'Manage your articles',
+ description: 'Edit, publish, and manage your articles',
},
{
id: 'integrations',
icon: ,
path: ROUTES_SETTINGS_V1.INTEGRATIONS,
name: 'Integrations',
- description: 'Manage your integrations',
+ description: 'Connect your accounts and services',
},
];
@@ -54,6 +63,16 @@ export const settingsRoutes = ({
}
/>,
+
+ }
+ />,
{
const navigate = useCustomNavigate();
const theme = useTheme();
+ const { addNotification } = useNotifications();
const getCurrentPage = useCallback(() => {
if (!path || !screenName) return false;
@@ -80,8 +83,8 @@ const SidebarMenuItem: FC<{
) => {
if (isLocked && !onClick) {
- return;
+ return addNotification({
+ message: 'Coming soon',
+ type: NotificationType.INFO,
+ });
}
if (path) {
@@ -141,7 +147,7 @@ const SidebarMenuItem: FC<{
onClick?.(event);
}
},
- [isLocked, onClick, path, navigate]
+ [isLocked, onClick, path, navigate, addNotification]
);
if (hide) return null;
@@ -189,6 +195,7 @@ const SidebarMenuItem: FC<{
flex: '0 0 auto',
width: '28px',
height: '28px',
+ padding: '3px',
color: iconColorValue,
transition: 'all 280ms ease-in-out',
'& svg': {
diff --git a/client/src/shared/components/organisms/sidebar/hooks/index.ts b/client/src/shared/components/organisms/sidebar/hooks/index.ts
index ac646c428..70500aeca 100644
--- a/client/src/shared/components/organisms/sidebar/hooks/index.ts
+++ b/client/src/shared/components/organisms/sidebar/hooks/index.ts
@@ -1,5 +1,7 @@
import { useCallback, useState, useMemo } from 'react';
import HomeIcon from '@mui/icons-material/Home';
+import ChatIcon from '@mui/icons-material/Chat';
+import CodeIcon from '@mui/icons-material/Code';
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
import SettingsIcon from '@mui/icons-material/Settings';
import { SideBarItemsType } from '../typings';
@@ -32,6 +34,20 @@ const useSidebar = () => {
title: 'Home',
screenName: ROUTES_PAGE_V1.HOME,
},
+ {
+ icon: ChatIcon,
+ path: ROUTES_V1.CHATS,
+ title: 'Chats',
+ screenName: ROUTES_PAGE_V1.CHATS,
+ hasAccess: false,
+ },
+ {
+ icon: CodeIcon,
+ path: ROUTES_V1.CODE,
+ title: 'Code',
+ screenName: ROUTES_PAGE_V1.CODE,
+ hasAccess: false,
+ },
{
icon: SettingsIcon,
path: ROUTES_V1.SETTINGS,