From a2035e3b9fe2a937a88573a2d9bf3e936b8127d2 Mon Sep 17 00:00:00 2001 From: Avdhesh-Varshney Date: Mon, 19 Jan 2026 22:46:12 +0530 Subject: [PATCH 1/5] rename notification module & create notification route --- client/src/app/routes/constants/routes.ts | 1 + .../modules/notification/constants/index.ts | 1 - client/src/modules/notification/index.tsx | 227 ----------------- client/src/modules/settings/modules/index.tsx | 3 + .../v1}/components/notificationCard.tsx | 79 +++--- .../components/notificationCommentField.tsx | 17 +- .../notification/v1/constants/index.ts | 1 + .../modules/notification/v1}/hooks/index.ts | 10 +- .../modules/notification/v1/index.tsx | 238 ++++++++++++++++++ .../modules/notification/v1}/states/index.ts | 2 +- client/src/modules/settings/routes/index.tsx | 25 +- 11 files changed, 321 insertions(+), 283 deletions(-) delete mode 100644 client/src/modules/notification/constants/index.ts delete mode 100644 client/src/modules/notification/index.tsx rename client/src/modules/{notification => settings/modules/notification/v1}/components/notificationCard.tsx (79%) rename client/src/modules/{notification => settings/modules/notification/v1}/components/notificationCommentField.tsx (87%) create mode 100644 client/src/modules/settings/modules/notification/v1/constants/index.ts rename client/src/modules/{notification => settings/modules/notification/v1}/hooks/index.ts (84%) create mode 100644 client/src/modules/settings/modules/notification/v1/index.tsx rename client/src/modules/{notification => settings/modules/notification/v1}/states/index.ts (73%) diff --git a/client/src/app/routes/constants/routes.ts b/client/src/app/routes/constants/routes.ts index 5c6927608..ca0158881 100644 --- a/client/src/app/routes/constants/routes.ts +++ b/client/src/app/routes/constants/routes.ts @@ -16,6 +16,7 @@ export enum ROUTES_HOME_V1 { export enum ROUTES_SETTINGS_V1 { PROFILE = '/profile', + NOTIFICATION = '/notification', MANAGE_ARTICLES = '/manage-articles', INTEGRATIONS = '/integrations', } 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 && ( - - - - )} - - )} - - ); -}; - -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, }} > + ); + })} + + + + + + {notifications === null ? ( + + + + ) : ( + <> + {notifications.results.length ? ( + + {notifications.results.map((notification, i) => ( + + ))} + + ) : ( + } + variant="outlined" + sx={{ + textAlign: 'center', + py: 4, + borderColor: 'divider', + '& .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 && ( + + + + )} + + )} + + + ); +}; + +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/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 = ({ } />, + + } + />, Date: Mon, 19 Jan 2026 22:46:26 +0530 Subject: [PATCH 2/5] renamed auth module --- client/src/app/components/index.tsx | 4 +--- client/src/modules/{user-auth-form => auth}/v1/hooks/index.ts | 0 client/src/modules/{user-auth-form => auth}/v1/index.tsx | 0 3 files changed, 1 insertion(+), 3 deletions(-) rename client/src/modules/{user-auth-form => auth}/v1/hooks/index.ts (100%) rename client/src/modules/{user-auth-form => auth}/v1/index.tsx (100%) diff --git a/client/src/app/components/index.tsx b/client/src/app/components/index.tsx index e9a53eaaf..06e3c762f 100644 --- a/client/src/app/components/index.tsx +++ b/client/src/app/components/index.tsx @@ -8,9 +8,7 @@ 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') ); 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 From c0eb3405db72e7e5c958b81533154987d2bf8494 Mon Sep 17 00:00:00 2001 From: Avdhesh-Varshney Date: Mon, 19 Jan 2026 22:50:42 +0530 Subject: [PATCH 3/5] delete 404 page --- client/src/modules/404/index.tsx | 93 -------------------------------- 1 file changed, 93 deletions(-) delete mode 100644 client/src/modules/404/index.tsx diff --git a/client/src/modules/404/index.tsx b/client/src/modules/404/index.tsx deleted file mode 100644 index e82be034e..000000000 --- a/client/src/modules/404/index.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Box, Typography, Link as MUILink, useTheme } from '@mui/material'; -import { Link } from 'react-router-dom'; - -const PageNotFound = () => { - 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; From fdf639a33736a38c9b460580570b80f50350eb8b Mon Sep 17 00:00:00 2001 From: Avdhesh-Varshney Date: Mon, 19 Jan 2026 22:51:04 +0530 Subject: [PATCH 4/5] renamed change password module --- .../modules/profile/v1/components/change-password.tsx} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename client/src/modules/{change-password/index.tsx => settings/modules/profile/v1/components/change-password.tsx} (89%) 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); From a9f8d40b1f6a96ca160f1719b1f2086bac86d018 Mon Sep 17 00:00:00 2001 From: Avdhesh-Varshney Date: Mon, 19 Jan 2026 23:21:39 +0530 Subject: [PATCH 5/5] added 2 chats & editor pages --- client/src/app/components/index.tsx | 6 ++++++ .../src/app/routes/auth-routes/v1/index.tsx | 20 +++++++++++++++++++ client/src/app/routes/constants/routes.ts | 4 ++++ client/src/modules/chats/v1/index.tsx | 11 ++++++++++ client/src/modules/code/v1/index.tsx | 11 ++++++++++ .../sidebar/components/SidebarMenuItem.tsx | 15 ++++++++++---- .../organisms/sidebar/hooks/index.ts | 16 +++++++++++++++ 7 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 client/src/modules/chats/v1/index.tsx create mode 100644 client/src/modules/code/v1/index.tsx diff --git a/client/src/app/components/index.tsx b/client/src/app/components/index.tsx index 06e3c762f..4f6369dbd 100644 --- a/client/src/app/components/index.tsx +++ b/client/src/app/components/index.tsx @@ -12,6 +12,12 @@ 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() { } />, + }> + + + } + />, + }> + + + } + />, { + 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/shared/components/organisms/sidebar/components/SidebarMenuItem.tsx b/client/src/shared/components/organisms/sidebar/components/SidebarMenuItem.tsx index e45f1a939..b570cef10 100644 --- a/client/src/shared/components/organisms/sidebar/components/SidebarMenuItem.tsx +++ b/client/src/shared/components/organisms/sidebar/components/SidebarMenuItem.tsx @@ -12,6 +12,8 @@ import LockIcon from '@mui/icons-material/Lock'; import { ROUTES_PAGE_V1 } from '../../../../../app/routes/constants/routes'; import { useCustomNavigate } from '../../../../hooks/use-custom-navigate'; import { openPopup } from '../../../../utils/popup'; +import { useNotifications } from '../../../../hooks/use-notification'; +import { NotificationType } from '../../../../states/notification'; const SidebarMenuItem: FC<{ Icon: ElementType; @@ -40,6 +42,7 @@ const SidebarMenuItem: FC<{ }) => { 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,