code refactor, created separate file for types
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { axiosClient } from '../App.tsx';
|
import { axiosClient } from '../App.tsx';
|
||||||
import { ChatMessagesProps } from '../pages/Chat.tsx';
|
|
||||||
import { ContactsProps } from '../pages/Chat.tsx';
|
import { ChatMessagesProps, ContactsProps } from '@/types/types.ts';
|
||||||
|
|
||||||
export async function getContactsList(): Promise<ContactsProps[]> {
|
export async function getContactsList(): Promise<ContactsProps[]> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Trash2 } from 'lucide-react';
|
import { Trash2 } from 'lucide-react';
|
||||||
import AttachmentPreview from './AttachmentPreview.tsx';
|
import AttachmentPreview from './AttachmentPreview.tsx';
|
||||||
import { ChatMessagesProps } from '@/pages/Chat.tsx';
|
|
||||||
|
import { ChatMessagesProps } from '@/types/types.ts';
|
||||||
|
|
||||||
type AnimatedMessageProps = {
|
type AnimatedMessageProps = {
|
||||||
message: ChatMessagesProps;
|
message: ChatMessagesProps;
|
||||||
|
|||||||
@@ -1,37 +1,28 @@
|
|||||||
import { useRef, useCallback, useEffect, useState } from 'react';
|
|
||||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
|
||||||
import type { KeyboardEventHandler } from 'react';
|
import type { KeyboardEventHandler } from 'react';
|
||||||
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
||||||
import { socket } from '../../../socket/socket.tsx';
|
import { socket } from '../../../socket/socket.tsx';
|
||||||
import { ChatMessagesProps, ContactsProps } from '../../../pages/Chat.tsx';
|
|
||||||
import { axiosClient } from '../../../App.tsx';
|
import { axiosClient } from '../../../App.tsx';
|
||||||
import { File, Paperclip, Send, X } from 'lucide-react';
|
import { File, Paperclip, Send, X } from 'lucide-react';
|
||||||
import LoadingWheel from '@/components/chat/LoadingWheel.tsx';
|
import LoadingWheel from '@/components/chat/LoadingWheel.tsx';
|
||||||
type Input = {
|
import {
|
||||||
message: string;
|
FileWithPreviewProps,
|
||||||
attachments: FileList | null;
|
InputProps,
|
||||||
};
|
MessageFormProps,
|
||||||
|
} from '@/types/types.ts';
|
||||||
type MessageFormProps = {
|
|
||||||
contact: ContactsProps;
|
|
||||||
messages: ChatMessagesProps[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type FileWithPreview = {
|
|
||||||
file: File;
|
|
||||||
preview: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const MessageForm = ({ contact }: MessageFormProps) => {
|
const MessageForm = ({ contact }: MessageFormProps) => {
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreviewProps[]>([]);
|
||||||
const [isUploading, setIsUploading] = useState(false);
|
const [isUploading, setIsUploading] = useState(false);
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||||
|
|
||||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
const { register, handleSubmit, reset, watch, setValue } = useForm<Input>({
|
const { register, handleSubmit, reset, watch, setValue } =
|
||||||
mode: 'onChange',
|
useForm<InputProps>({
|
||||||
});
|
mode: 'onChange',
|
||||||
|
});
|
||||||
|
|
||||||
const message = watch('message', '');
|
const message = watch('message', '');
|
||||||
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
|
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
|
||||||
@@ -114,7 +105,7 @@ const MessageForm = ({ contact }: MessageFormProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitMessage: SubmitHandler<Input> = async (data) => {
|
const submitMessage: SubmitHandler<InputProps> = async (data) => {
|
||||||
if ((!data.message && files.length === 0) || isSending) return;
|
if ((!data.message && files.length === 0) || isSending) return;
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
setIsSending(true);
|
setIsSending(true);
|
||||||
@@ -172,7 +163,7 @@ const MessageForm = ({ contact }: MessageFormProps) => {
|
|||||||
|
|
||||||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
if (e.target.files && e.target.files.length > 0) {
|
if (e.target.files && e.target.files.length > 0) {
|
||||||
const newFiles: FileWithPreview[] = Array.from(e.target.files).map(
|
const newFiles: FileWithPreviewProps[] = Array.from(e.target.files).map(
|
||||||
(file) => ({
|
(file) => ({
|
||||||
file,
|
file,
|
||||||
preview: file.type.startsWith('image/')
|
preview: file.type.startsWith('image/')
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ import { socket } from '@/socket/socket.tsx';
|
|||||||
import { useOutletContext } from 'react-router-dom';
|
import { useOutletContext } from 'react-router-dom';
|
||||||
import { sendContact } from '@/api/contactsApi.tsx';
|
import { sendContact } from '@/api/contactsApi.tsx';
|
||||||
import LoadingWheel from '../LoadingWheel.tsx';
|
import LoadingWheel from '../LoadingWheel.tsx';
|
||||||
import { ChatMessagesProps, MeProps } from '@/pages/Chat.tsx';
|
|
||||||
import { ContactsProps } from '@/pages/Chat.tsx';
|
|
||||||
import { UsernameType } from '@/utils/ProtectedRoutes.tsx';
|
|
||||||
import AnimatedMessage from '@/components/chat/chatArea/AnimatedMessage.tsx';
|
import AnimatedMessage from '@/components/chat/chatArea/AnimatedMessage.tsx';
|
||||||
|
import {
|
||||||
|
ChatMessagesProps,
|
||||||
|
ContactsProps,
|
||||||
|
MeProps,
|
||||||
|
UsernameType,
|
||||||
|
} from '@/types/types.ts';
|
||||||
|
|
||||||
type MessagesAreaProps = {
|
type MessagesAreaProps = {
|
||||||
messages: ChatMessagesProps[];
|
messages: ChatMessagesProps[];
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import LoadingWheel from '../LoadingWheel.tsx';
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { SubmitHandler, useForm } from 'react-hook-form';
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
||||||
import { axiosClient } from '../../../App.tsx';
|
import { axiosClient } from '../../../App.tsx';
|
||||||
import { ContactsProps } from '../../../pages/Chat.tsx';
|
|
||||||
import { socket } from '../../../socket/socket.tsx';
|
import { socket } from '../../../socket/socket.tsx';
|
||||||
import { UserRoundPlus } from 'lucide-react';
|
import { UserRoundPlus } from 'lucide-react';
|
||||||
import { Button } from '@/components/ui/button.tsx';
|
import { Button } from '@/components/ui/button.tsx';
|
||||||
|
import { ContactsProps } from '@/types/types.ts';
|
||||||
|
|
||||||
type Inputs = {
|
type Inputs = {
|
||||||
username: string;
|
username: string;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import profile from '../../../../assets/profile.svg';
|
import profile from '../../../../assets/profile.svg';
|
||||||
import CreateGroupButton from './CreateGroupButton.tsx';
|
import CreateGroupButton from './CreateGroupButton.tsx';
|
||||||
import AddGroupMember from './AddGroupMember.tsx';
|
import AddGroupMember from './AddGroupMember.tsx';
|
||||||
import { ContactsProps } from '@/pages/Chat.tsx';
|
|
||||||
import { UsersRound } from 'lucide-react';
|
import { UsersRound } from 'lucide-react';
|
||||||
|
import { ContactsProps } from '@/types/types.ts';
|
||||||
|
|
||||||
type ContactProfileProps = {
|
type ContactProfileProps = {
|
||||||
contact: ContactsProps | null;
|
contact: ContactsProps | null;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||||
import { ContactsProps } from '../../../pages/Chat.tsx';
|
|
||||||
import { axiosClient } from '../../../App.tsx';
|
import { axiosClient } from '../../../App.tsx';
|
||||||
import { AxiosResponse } from 'axios';
|
import { AxiosResponse } from 'axios';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import LoadingWheel from '../LoadingWheel.tsx';
|
import LoadingWheel from '../LoadingWheel.tsx';
|
||||||
import { Search } from 'lucide-react';
|
import { Search } from 'lucide-react';
|
||||||
|
import { ContactsProps } from '@/types/types.ts';
|
||||||
|
|
||||||
type Input = {
|
type Input = {
|
||||||
contact: string;
|
contact: string;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { ChatMessagesProps, ContactsProps } from '@/pages/Chat.tsx';
|
|
||||||
import { socket } from '@/socket/socket.tsx';
|
import { socket } from '@/socket/socket.tsx';
|
||||||
import GroupIcon from '../../../../assets/group.svg';
|
import GroupIcon from '../../../../assets/group.svg';
|
||||||
import {
|
import {
|
||||||
@@ -16,6 +15,7 @@ import {
|
|||||||
import { axiosClient } from '@/App.tsx';
|
import { axiosClient } from '@/App.tsx';
|
||||||
import { Dot } from 'lucide-react';
|
import { Dot } from 'lucide-react';
|
||||||
import LastActiveTime from '@/components/chat/leftSidebar/LastActiveTime.tsx';
|
import LastActiveTime from '@/components/chat/leftSidebar/LastActiveTime.tsx';
|
||||||
|
import { ChatMessagesProps, ContactsProps } from '@/types/types.ts';
|
||||||
|
|
||||||
type ContactsListProps = {
|
type ContactsListProps = {
|
||||||
initializeContact: (contact: ContactsProps) => void;
|
initializeContact: (contact: ContactsProps) => void;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { formatDistanceToNow, differenceInSeconds } from 'date-fns';
|
import { formatDistanceToNow, differenceInSeconds } from 'date-fns';
|
||||||
import { ContactsProps } from '@/pages/Chat.tsx';
|
|
||||||
|
import { ContactsProps } from '@/types/types.ts';
|
||||||
|
|
||||||
type LastActiveTimeProps = {
|
type LastActiveTimeProps = {
|
||||||
contact: ContactsProps;
|
contact: ContactsProps;
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import zdjecie from '../../../../assets/turtleProfileImg3.webp';
|
|||||||
import logoutIcon from '../../../../assets/logout.svg';
|
import logoutIcon from '../../../../assets/logout.svg';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import { useOutletContext } from 'react-router-dom';
|
import { useOutletContext } from 'react-router-dom';
|
||||||
import { UsernameType } from '../../../utils/ProtectedRoutes.tsx';
|
|
||||||
|
import { UsernameType } from '@/types/types.ts';
|
||||||
|
|
||||||
function UserProfile() {
|
function UserProfile() {
|
||||||
const user: UsernameType = useOutletContext();
|
const user: UsernameType = useOutletContext();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { useContext, useEffect, useMemo, useState } from 'react';
|
import { useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { axiosClient } from '@/App.tsx';
|
import { axiosClient } from '@/App.tsx';
|
||||||
import { ContactsProps, MeProps } from '@/pages/Chat.tsx';
|
|
||||||
import { socket } from '@/socket/socket.tsx';
|
import { socket } from '@/socket/socket.tsx';
|
||||||
import { Crown, Sword } from 'lucide-react';
|
import { Crown, Sword } from 'lucide-react';
|
||||||
import {
|
import {
|
||||||
@@ -9,9 +8,9 @@ import {
|
|||||||
ContextMenuItem,
|
ContextMenuItem,
|
||||||
ContextMenuTrigger,
|
ContextMenuTrigger,
|
||||||
} from '@/components/ui/context-menu.tsx';
|
} from '@/components/ui/context-menu.tsx';
|
||||||
import { UsernameType } from '@/utils/ProtectedRoutes.tsx';
|
|
||||||
import { useOutletContext } from 'react-router-dom';
|
import { useOutletContext } from 'react-router-dom';
|
||||||
import zdjecie from '../../../../assets/turtleProfileImg3.webp';
|
import zdjecie from '../../../../assets/turtleProfileImg3.webp';
|
||||||
|
import { ContactsProps, MeProps, UsernameType } from '@/types/types.ts';
|
||||||
type ParticipantsProps = {
|
type ParticipantsProps = {
|
||||||
user_id: string;
|
user_id: string;
|
||||||
username: string;
|
username: string;
|
||||||
|
|||||||
0
client/src/context/ContactContext.tsx
Normal file
0
client/src/context/ContactContext.tsx
Normal file
@@ -10,35 +10,7 @@ import Cookies from 'js-cookie';
|
|||||||
import { getMessages, setContactStatus } from '../api/contactsApi.tsx';
|
import { getMessages, setContactStatus } from '../api/contactsApi.tsx';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import ParticipantsBar from '@/components/chat/rightSidebar/ParticipantsBar.tsx';
|
import ParticipantsBar from '@/components/chat/rightSidebar/ParticipantsBar.tsx';
|
||||||
|
import { ChatMessagesProps, ContactsProps, MeProps } from '@/types/types.ts';
|
||||||
export type MeProps = {
|
|
||||||
isGroupAdmin: boolean;
|
|
||||||
isGroupOwner: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ChatMessagesProps = {
|
|
||||||
sender: string;
|
|
||||||
message: string;
|
|
||||||
recipient: string; // conversation_id
|
|
||||||
message_id: number;
|
|
||||||
attachment_urls: string[] | null;
|
|
||||||
sender_id: string;
|
|
||||||
conversation_id: string;
|
|
||||||
sent_at: Date;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ContactsProps = {
|
|
||||||
read: boolean;
|
|
||||||
username: string;
|
|
||||||
user_id: string;
|
|
||||||
id: number;
|
|
||||||
type: 'direct' | 'group';
|
|
||||||
conversation_id: string;
|
|
||||||
last_active: string;
|
|
||||||
last_message: string;
|
|
||||||
last_message_time: string;
|
|
||||||
last_message_sender: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Chat() {
|
function Chat() {
|
||||||
const meDefaultValue = {
|
const meDefaultValue = {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { AuthContext } from '../utils/AuthProvider.tsx';
|
|||||||
import LoadingWheel from '../components/chat/LoadingWheel.tsx';
|
import LoadingWheel from '../components/chat/LoadingWheel.tsx';
|
||||||
import { axiosClient } from '../App.tsx';
|
import { axiosClient } from '../App.tsx';
|
||||||
|
|
||||||
type Inputs = {
|
export type Inputs = {
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
};
|
};
|
||||||
|
|||||||
44
client/src/types/types.ts
Normal file
44
client/src/types/types.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { File } from 'lucide-react';
|
||||||
|
|
||||||
|
export type MeProps = {
|
||||||
|
isGroupAdmin: boolean;
|
||||||
|
isGroupOwner: boolean;
|
||||||
|
};
|
||||||
|
export type ChatMessagesProps = {
|
||||||
|
sender: string;
|
||||||
|
message: string;
|
||||||
|
recipient: string; // conversation_id
|
||||||
|
message_id: number;
|
||||||
|
attachment_urls: string[] | null;
|
||||||
|
sender_id: string;
|
||||||
|
conversation_id: string;
|
||||||
|
sent_at: Date;
|
||||||
|
};
|
||||||
|
export type ContactsProps = {
|
||||||
|
read: boolean;
|
||||||
|
username: string;
|
||||||
|
user_id: string;
|
||||||
|
id: number;
|
||||||
|
type: 'direct' | 'group';
|
||||||
|
conversation_id: string;
|
||||||
|
last_active: string;
|
||||||
|
last_message: string;
|
||||||
|
last_message_time: string;
|
||||||
|
last_message_sender: string;
|
||||||
|
};
|
||||||
|
export type InputProps = {
|
||||||
|
message: string;
|
||||||
|
attachments: FileList | null;
|
||||||
|
};
|
||||||
|
export type MessageFormProps = {
|
||||||
|
contact: ContactsProps;
|
||||||
|
messages: ChatMessagesProps[];
|
||||||
|
};
|
||||||
|
export type FileWithPreviewProps = {
|
||||||
|
file: File;
|
||||||
|
preview: string | null;
|
||||||
|
};
|
||||||
|
export type UsernameType = {
|
||||||
|
username: string | null;
|
||||||
|
user_id: string | null;
|
||||||
|
};
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
import { Navigate, Outlet } from 'react-router-dom';
|
import { Navigate, Outlet } from 'react-router-dom';
|
||||||
import { useState, useEffect, useContext } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { AuthContext } from './AuthProvider.tsx';
|
import { AuthContext } from './AuthProvider.tsx';
|
||||||
import LoadingScreen from '../components/LoadingScreen.tsx';
|
import LoadingScreen from '../components/LoadingScreen.tsx';
|
||||||
import { axiosClient } from '../App.tsx';
|
import { axiosClient } from '../App.tsx';
|
||||||
|
import { UsernameType } from '@/types/types.ts';
|
||||||
export type UsernameType = {
|
|
||||||
username: string | null;
|
|
||||||
user_id: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
function ProtectedRoutes() {
|
function ProtectedRoutes() {
|
||||||
const { authorized, isLoading } = useContext(AuthContext);
|
const { authorized, isLoading } = useContext(AuthContext);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
important: true,
|
|
||||||
darkMode: ['class'],
|
darkMode: ['class'],
|
||||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
|
|||||||
Reference in New Issue
Block a user