diff --git a/client/src/App.tsx b/client/src/App.tsx
index 3037371..e5afd55 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -1,19 +1,17 @@
import {
+ RouterProvider,
createBrowserRouter,
Navigate,
- RouterProvider,
} from 'react-router-dom';
-import { Suspense } from 'react';
-import Chat from './pages/Chat';
-import Login from './pages/Login';
-import Signup from './pages/Signup';
-import Settings from './pages/Settings';
-import Lost from './pages/404';
-import { AuthProvider } from '@/utils/AuthProvider.tsx';
-import ProtectedRoutes from './utils/ProtectedRoutes';
-import PublicRoute from './utils/PublicRoute';
-import { ChatProvider } from './context/chat/ChatProvider';
-import LoadingScreen from './components/LoadingScreen';
+import Chat from './pages/Chat.tsx';
+import Login from './pages/Login.tsx';
+import Signup from './pages/Signup.tsx';
+import Settings from './pages/Settings.tsx';
+import Lost from './pages/404.tsx';
+import { AuthProvider } from './utils/AuthProvider.tsx';
+import ProtectedRoutes from './utils/ProtectedRoutes.tsx';
+import { ChatProvider } from '@/context/chat/ChatProvider.tsx';
+import PublicRoute from '@/utils/PublicRoute.tsx';
const router = createBrowserRouter([
{
@@ -26,11 +24,9 @@ const router = createBrowserRouter([
{
path: '/chat',
element: (
- }>
-
-
-
-
+
+
+
),
},
{
diff --git a/client/src/components/chat/chatArea/AnimatedMessage.tsx b/client/src/components/chat/chatArea/AnimatedMessage.tsx
index ae21ef6..10697dd 100644
--- a/client/src/components/chat/chatArea/AnimatedMessage.tsx
+++ b/client/src/components/chat/chatArea/AnimatedMessage.tsx
@@ -1,9 +1,9 @@
-import { useState } from 'react';
+import { useContext, useState } from 'react';
import { Trash2 } from 'lucide-react';
import AttachmentPreview from './AttachmentPreview.tsx';
-import { ChatMessagesProps, UserType } from '@/types/types.ts';
-import { useOutletContext } from 'react-router-dom';
+import { ChatMessagesProps } from '@/types/types.ts';
import { useChat } from '@/context/chat/useChat.ts';
+import { AuthContext } from '@/utils/AuthProvider.tsx';
type AnimatedMessageProps = {
message: ChatMessagesProps;
@@ -11,7 +11,7 @@ type AnimatedMessageProps = {
};
const AnimatedMessage = ({ onDelete, message }: AnimatedMessageProps) => {
- const user: UserType = useOutletContext();
+ const { user } = useContext(AuthContext);
const { me, groupOwner } = useChat();
const [isRemoving, setIsRemoving] = useState(false);
@@ -51,7 +51,7 @@ const AnimatedMessage = ({ onDelete, message }: AnimatedMessageProps) => {
)}
{me.isGroupOwner ||
- message.sender == user.username ||
+ message.sender == user?.username ||
(me.isGroupAdmin &&
me.isGroupOwner &&
message.sender_id !== groupOwner) ? (
diff --git a/client/src/components/chat/chatArea/MessageForm.tsx b/client/src/components/chat/chatArea/MessageForm.tsx
index 3a3fe4e..3b1c497 100644
--- a/client/src/components/chat/chatArea/MessageForm.tsx
+++ b/client/src/components/chat/chatArea/MessageForm.tsx
@@ -100,6 +100,12 @@ const MessageForm = () => {
},
);
setIsUploading(false);
+ console.error(response.data);
+ if (!response.data) {
+ setErrorMessage('Failed to upload attachments');
+ return console.error('Failed to upload attachments');
+ }
+
return response.data;
} catch (e) {
setIsUploading(false);
diff --git a/client/src/components/chat/chatArea/MessagesArea.tsx b/client/src/components/chat/chatArea/MessagesArea.tsx
index 4b62ab0..7315083 100644
--- a/client/src/components/chat/chatArea/MessagesArea.tsx
+++ b/client/src/components/chat/chatArea/MessagesArea.tsx
@@ -1,11 +1,11 @@
-import { useEffect, useRef, useState } from 'react';
+import { useContext, useEffect, useRef, useState } from 'react';
import { socket } from '@/socket/socket.ts';
-import { useOutletContext } from 'react-router-dom';
import { sendContact } from '@/api/contactsApi.tsx';
import LoadingWheel from '../LoadingWheel.tsx';
import AnimatedMessage from '@/components/chat/chatArea/AnimatedMessage.tsx';
-import { ChatMessagesProps, UserType } from '@/types/types.ts';
+import { ChatMessagesProps } from '@/types/types.ts';
import { useChat } from '@/context/chat/useChat.ts';
+import { AuthContext } from '@/utils/AuthProvider.tsx';
function MessagesArea() {
const {
@@ -19,7 +19,7 @@ function MessagesArea() {
fetchPreviousMessages,
} = useChat();
const containerRef = useRef(null);
- const user: UserType = useOutletContext();
+ const { user } = useContext(AuthContext);
const [isLoading, setIsLoading] = useState(false);
const [shouldScrollToBottom, setShouldScrollToBottom] = useState(true);
const previousMessagesLength = useRef(messages.length);
@@ -90,7 +90,7 @@ function MessagesArea() {
console.log('Received message: ', msg);
if (
msg.conversation_id !== currentContact?.conversation_id &&
- msg.sender !== user.username
+ msg.sender !== user?.username
) {
setContactsList((prevContacts) => {
// Find if contact already exists1
@@ -197,10 +197,10 @@ function MessagesArea() {
currentContainer.removeEventListener('scroll', handleScroll);
}
socket.off('chat message');
+ socket.off('delete message');
};
- }, [currentContact, user.username, setContactsList, updateContactStatus]);
+ }, [currentContact, user?.username, setContactsList, updateContactStatus]);
- // Handle auto-scrolling when new messages arrive
useEffect(() => {
const hasNewMessages = messages.length > previousMessagesLength.current;
previousMessagesLength.current = messages.length;
@@ -222,7 +222,11 @@ function MessagesArea() {
{isLoading ? : null}
{messages.map((msg: ChatMessagesProps) => (
-
+
))}
diff --git a/client/src/components/chat/leftSidebar/LastActiveTime.tsx b/client/src/components/chat/leftSidebar/LastActiveTime.tsx
index ccdb93b..79a3ea0 100644
--- a/client/src/components/chat/leftSidebar/LastActiveTime.tsx
+++ b/client/src/components/chat/leftSidebar/LastActiveTime.tsx
@@ -12,6 +12,9 @@ const LastActiveTime = ({ contact }: LastActiveTimeProps) => {
useEffect(() => {
const updateTime = () => {
+ if (!contact?.last_message_time) {
+ return;
+ }
const lastActiveDate = new Date(contact.last_message_time);
const secondsDiff = differenceInSeconds(new Date(), lastActiveDate);
diff --git a/client/src/components/chat/leftSidebar/UserProfile.tsx b/client/src/components/chat/leftSidebar/UserProfile.tsx
index 9ca1b4f..a96221b 100644
--- a/client/src/components/chat/leftSidebar/UserProfile.tsx
+++ b/client/src/components/chat/leftSidebar/UserProfile.tsx
@@ -1,11 +1,11 @@
import zdjecie from '../../../../assets/turtleProfileImg3.webp';
import logoutIcon from '../../../../assets/logout.svg';
import Cookies from 'js-cookie';
-import { useOutletContext } from 'react-router-dom';
-import { UserType } from '@/types/types.ts';
+import { useContext } from 'react';
+import { AuthContext } from '@/utils/AuthProvider.tsx';
function UserProfile() {
- const user: UserType = useOutletContext();
+ const { user } = useContext(AuthContext);
function logout() {
Cookies.remove('token');
localStorage.removeItem('contact');
@@ -27,7 +27,7 @@ function UserProfile() {
/>
-
{user.username}
+
{user?.username}
diff --git a/client/src/components/chat/rightSidebar/ParticipantsBar.tsx b/client/src/components/chat/rightSidebar/ParticipantsBar.tsx
index fc03777..82c9332 100644
--- a/client/src/components/chat/rightSidebar/ParticipantsBar.tsx
+++ b/client/src/components/chat/rightSidebar/ParticipantsBar.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useMemo, useState } from 'react';
+import { useContext, useEffect, useMemo, useState } from 'react';
import { socket } from '@/socket/socket.ts';
import { Crown, Sword } from 'lucide-react';
import {
@@ -7,17 +7,17 @@ import {
ContextMenuItem,
ContextMenuTrigger,
} from '@/components/ui/context-menu.tsx';
-import { useOutletContext } from 'react-router-dom';
import zdjecie from '../../../../assets/turtleProfileImg3.webp';
-import { ParticipantsProps, UserType } from '@/types/types.ts';
+import { ParticipantsProps } from '@/types/types.ts';
import { useChat } from '@/context/chat/useChat.ts';
import { axiosClient } from '@/utils/axiosClient.ts';
+import { AuthContext } from '@/utils/AuthProvider.tsx';
function ParticipantsBar() {
const { setMe, initializeContact, setGroupOwner, currentContact, me } =
useChat();
const [participants, setParticipants] = useState([]);
- const user: UserType = useOutletContext();
+ const { user } = useContext(AuthContext);
const getParticipants = async () => {
try {
const response = await axiosClient.get(
@@ -90,7 +90,6 @@ function ParticipantsBar() {
};
useEffect(() => {
- console.error(participants.length, user.id);
if (participants.length > 0 && user?.id) {
const userIsAdmin = participants.some(
(participant) => participant.user_id === user.id && participant.isadmin,
@@ -104,7 +103,6 @@ function ParticipantsBar() {
);
setGroupOwner(whoIsOwner?.user_id);
setMe({ isGroupAdmin: userIsAdmin, isGroupOwner: userIsOwner });
- console.error('SETME: ', userIsAdmin, userIsOwner);
}
}, [participants, user?.id]);
@@ -256,7 +254,7 @@ function ParticipantsBar() {
- {user.id !== participant.user_id &&
+ {user?.id !== participant.user_id &&
me.isGroupAdmin &&
(!participant.isadmin || me.isGroupOwner) ? (
diff --git a/client/src/pages/Login.tsx b/client/src/pages/Login.tsx
index 82a40c6..74952ac 100644
--- a/client/src/pages/Login.tsx
+++ b/client/src/pages/Login.tsx
@@ -2,10 +2,10 @@ import { useForm, SubmitHandler } from 'react-hook-form';
import icon from '../../assets/icon.png';
import { Link, useNavigate } from 'react-router-dom';
import { useContext, useState } from 'react';
-import { AuthContext } from '@/utils/AuthContext.tsx';
import LoadingWheel from '../components/chat/LoadingWheel.tsx';
import { axiosClient } from '@/utils/axiosClient.ts';
+import { AuthContext } from '@/utils/AuthProvider.tsx';
export type Inputs = {
username: string;
@@ -31,7 +31,7 @@ export default function Login() {
setAuthorized(true);
setIsLoading(false);
console.log('redirecting');
- navigate('/chat');
+ navigate('/');
})
.catch((err) => {
if (err.response) {
diff --git a/client/src/pages/Signup.tsx b/client/src/pages/Signup.tsx
index e545a94..591bdb1 100644
--- a/client/src/pages/Signup.tsx
+++ b/client/src/pages/Signup.tsx
@@ -2,9 +2,9 @@ import icon from '../../assets/icon.png';
import { useForm, SubmitHandler } from 'react-hook-form';
import { Link, useNavigate } from 'react-router-dom';
import { useContext, useState } from 'react';
-import { AuthContext } from '@/utils/AuthContext.tsx';
import LoadingWheel from '../components/chat/LoadingWheel.tsx';
import { axiosClient } from '@/utils/axiosClient.ts';
+import { AuthContext } from '@/utils/AuthProvider.tsx';
type Inputs = {
username: string;
@@ -44,7 +44,7 @@ export default function Signup() {
.then(() => {
setAuthorized(true);
setIsLoading(false);
- navigate('/chat');
+ navigate('/');
console.log('Signed up');
})
.catch((err) => {
diff --git a/client/src/utils/AuthContext.tsx b/client/src/utils/AuthContext.tsx
deleted file mode 100644
index 1caed72..0000000
--- a/client/src/utils/AuthContext.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { createContext } from 'react';
-import { UserType } from '@/types/types.ts';
-
-interface AuthContextType {
- authorized: boolean;
- isLoading: boolean;
- user: UserType | null;
- setAuthorized: (value: boolean) => void;
-}
-
-export const AuthContext = createContext({
- authorized: false,
- isLoading: true,
- user: null,
- setAuthorized: () => {},
-});
diff --git a/client/src/utils/AuthProvider.tsx b/client/src/utils/AuthProvider.tsx
index 226b25a..74b1874 100644
--- a/client/src/utils/AuthProvider.tsx
+++ b/client/src/utils/AuthProvider.tsx
@@ -1,47 +1,52 @@
-import { AuthContext } from './AuthContext';
-import Cookies from 'js-cookie';
-import { axiosClient } from '@/utils/axiosClient.ts';
-import { ReactNode, useEffect, useState } from 'react';
+import { createContext, useState, useEffect, ReactNode } from 'react';
+import Cookie from 'js-cookie';
+import { axiosClient } from '@/utils/axiosClient';
import { UserType } from '@/types/types.ts';
+type AuthContextType = {
+ authorized: boolean | null;
+ setAuthorized: (value: boolean) => void;
+ user: UserType | null;
+ setUser: (user: UserType | null) => void;
+};
+
+export const AuthContext = createContext({
+ authorized: null,
+ setAuthorized: () => {},
+ user: null,
+ setUser: () => {},
+});
+
export function AuthProvider({ children }: { children: ReactNode }) {
- const [authorized, setAuthorized] = useState(false);
- const [isLoading, setIsLoading] = useState(true);
+ const [authorized, setAuthorized] = useState(null);
const [user, setUser] = useState(null);
- const token = Cookies.get('token');
useEffect(() => {
- async function validateAuth() {
+ async function validateToken() {
+ const token = Cookie.get('token');
if (!token) {
- setIsLoading(false);
+ setAuthorized(false);
return;
}
try {
- const response = await axiosClient.get('/api/auth/validate', {
+ const res = await axiosClient.get('/api/auth/validate', {
withCredentials: true,
});
- setUser({
- username: response.data.username,
- id: response.data.user_id,
- });
+ setUser({ username: res.data.username, id: res.data.user_id });
setAuthorized(true);
- } catch (error) {
- console.error('Auth validation failed:', error);
+ } catch (err) {
setAuthorized(false);
setUser(null);
- } finally {
- setIsLoading(false);
+ console.error('Token validation failed:', err);
}
}
- validateAuth();
- }, [token]);
+ validateToken();
+ }, []);
return (
-
+
{children}
);
diff --git a/client/src/utils/ProtectedRoutes.tsx b/client/src/utils/ProtectedRoutes.tsx
index 5dd4d87..0688b76 100644
--- a/client/src/utils/ProtectedRoutes.tsx
+++ b/client/src/utils/ProtectedRoutes.tsx
@@ -1,18 +1,16 @@
import { Navigate, Outlet } from 'react-router-dom';
-import { useAuth } from '@/utils/useAuth.tsx';
-import LoadingScreen from '@/components/LoadingScreen';
+import { useContext } from 'react';
+import { AuthContext } from './AuthProvider';
+import LoadingScreen from '../components/LoadingScreen';
function ProtectedRoutes() {
- const { authorized, isLoading, user } = useAuth();
- if (isLoading) {
+ const { authorized } = useContext(AuthContext);
+
+ if (authorized === null) {
return ;
}
- return authorized ? (
-
- ) : (
-
- );
+ return authorized ? : ;
}
export default ProtectedRoutes;
diff --git a/client/src/utils/PublicRoute.tsx b/client/src/utils/PublicRoute.tsx
index 850c890..c6098c6 100644
--- a/client/src/utils/PublicRoute.tsx
+++ b/client/src/utils/PublicRoute.tsx
@@ -1,11 +1,12 @@
import { Navigate, Outlet } from 'react-router-dom';
-import { useAuth } from '@/utils/useAuth.tsx';
-import LoadingScreen from '@/components/LoadingScreen';
+import { useContext } from 'react';
+import { AuthContext } from './AuthProvider';
+import LoadingScreen from '../components/LoadingScreen';
function PublicRoute() {
- const { authorized, isLoading } = useAuth();
+ const { authorized } = useContext(AuthContext);
- if (isLoading) {
+ if (authorized === null) {
return ;
}
diff --git a/client/src/utils/useAuth.tsx b/client/src/utils/useAuth.tsx
deleted file mode 100644
index 239ef19..0000000
--- a/client/src/utils/useAuth.tsx
+++ /dev/null
@@ -1,4 +0,0 @@
-import { useContext } from 'react';
-import { AuthContext } from '@/utils/AuthContext.tsx';
-
-export const useAuth = () => useContext(AuthContext);