├── src ├── assets │ └── notes.txt ├── constants │ ├── config.js │ ├── color.js │ ├── events.js │ └── sampleData.js ├── utils │ └── validators.js ├── components │ ├── auth │ │ └── ProtectRoute.jsx │ ├── shared │ │ ├── Title.jsx │ │ ├── RenderAttachment.jsx │ │ ├── AvatarCard.jsx │ │ ├── Table.jsx │ │ ├── UserItem.jsx │ │ ├── ChatItem.jsx │ │ └── MessageComponent.jsx │ ├── dialogs │ │ ├── ConfirmDeleteDialog.jsx │ │ ├── DeleteChatMenu.jsx │ │ ├── AddMemberDialog.jsx │ │ └── FileMenu.jsx │ ├── specific │ │ ├── ChatList.jsx │ │ ├── Profile.jsx │ │ ├── Charts.jsx │ │ ├── Search.jsx │ │ ├── Notifications.jsx │ │ └── NewGroup.jsx │ ├── styles │ │ └── StyledComponents.jsx │ └── layout │ │ ├── Loaders.jsx │ │ ├── AdminLayout.jsx │ │ ├── AppLayout.jsx │ │ └── Header.jsx ├── pages │ ├── Home.jsx │ ├── NotFound.jsx │ ├── admin │ │ ├── UserManagement.jsx │ │ ├── AdminLogin.jsx │ │ ├── ChatManagement.jsx │ │ ├── MessageManagement.jsx │ │ └── Dashboard.jsx │ ├── Chat.jsx │ ├── Login.jsx │ └── Groups.jsx ├── socket.jsx ├── redux │ ├── store.js │ ├── thunks │ │ └── admin.js │ ├── reducers │ │ ├── chat.js │ │ ├── auth.js │ │ └── misc.js │ └── api │ │ └── api.js ├── main.jsx ├── lib │ └── features.js ├── hooks │ └── hook.jsx └── App.jsx ├── .env ├── vercel.json ├── vite.config.js ├── .gitignore ├── index.html ├── README.md ├── .eslintrc.cjs ├── package.json └── public └── vite.svg /src/assets/notes.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | 2 | 3 | VITE_SERVER = http://localhost:3000 -------------------------------------------------------------------------------- /src/constants/config.js: -------------------------------------------------------------------------------- 1 | export const server = import.meta.env.VITE_SERVER; 2 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] 3 | } 4 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react-swc' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /src/utils/validators.js: -------------------------------------------------------------------------------- 1 | import { isValidUsername } from "6pp"; 2 | 3 | export const usernameValidator = (username) => { 4 | if (!isValidUsername(username)) 5 | return { isValid: false, errorMessage: "Username is Invalid" }; 6 | }; 7 | -------------------------------------------------------------------------------- /src/components/auth/ProtectRoute.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Navigate, Outlet } from "react-router-dom"; 3 | 4 | const ProtectRoute = ({ children, user, redirect = "/login" }) => { 5 | if (!user) return ; 6 | 7 | return children ? children : ; 8 | }; 9 | 10 | export default ProtectRoute; 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Chattu 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/shared/Title.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Helmet } from "react-helmet-async"; 3 | 4 | const Title = ({ 5 | title = "Chat App", 6 | description = "this is the Chat App called Chattu", 7 | }) => { 8 | return ( 9 | 10 | {title} 11 | 12 | 13 | ); 14 | }; 15 | 16 | export default Title; 17 | -------------------------------------------------------------------------------- /src/constants/color.js: -------------------------------------------------------------------------------- 1 | export const orange = "#ea7070"; 2 | export const orangeLight = "rgba(234, 112, 112,0.2)"; 3 | 4 | export const grayColor = "rgba(247,247,247,1)"; 5 | export const lightBlue = "#2694ab"; 6 | export const matBlack = "#1c1c1c"; 7 | export const bgGradient = "linear-gradient(rgb(255 225 209), rgb(249 159 159))"; 8 | 9 | export const purple = "rgba(75,12,192,1)"; 10 | export const purpleLight = "rgba(75,12,192,0.2)"; 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /src/pages/Home.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import AppLayout from "../components/layout/AppLayout"; 3 | import { Box, Typography } from "@mui/material"; 4 | import { grayColor } from "../constants/color"; 5 | 6 | const Home = () => { 7 | return ( 8 | 9 | 10 | Select a friend to chat 11 | 12 | 13 | ); 14 | }; 15 | 16 | export default AppLayout()(Home); 17 | -------------------------------------------------------------------------------- /src/socket.jsx: -------------------------------------------------------------------------------- 1 | import { createContext, useMemo, useContext } from "react"; 2 | import io from "socket.io-client"; 3 | import { server } from "./constants/config"; 4 | 5 | const SocketContext = createContext(); 6 | 7 | const getSocket = () => useContext(SocketContext); 8 | 9 | const SocketProvider = ({ children }) => { 10 | const socket = useMemo(() => io(server, { withCredentials: true }), []); 11 | 12 | return ( 13 | {children} 14 | ); 15 | }; 16 | 17 | export { SocketProvider, getSocket }; 18 | -------------------------------------------------------------------------------- /src/redux/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from "@reduxjs/toolkit"; 2 | import authSlice from "./reducers/auth"; 3 | import api from "./api/api"; 4 | import miscSlice from "./reducers/misc"; 5 | import chatSlice from "./reducers/chat"; 6 | 7 | const store = configureStore({ 8 | reducer: { 9 | [authSlice.name]: authSlice.reducer, 10 | [miscSlice.name]: miscSlice.reducer, 11 | [chatSlice.name]: chatSlice.reducer, 12 | [api.reducerPath]: api.reducer, 13 | }, 14 | middleware: (mid) => [...mid(), api.middleware], 15 | }); 16 | 17 | export default store; 18 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App.jsx"; 4 | import { CssBaseline } from "@mui/material"; 5 | import { HelmetProvider } from "react-helmet-async"; 6 | import { Provider } from "react-redux"; 7 | import store from "./redux/store.js"; 8 | 9 | ReactDOM.createRoot(document.getElementById("root")).render( 10 | 11 | 12 | 13 | 14 |
e.preventDefault()}> 15 | 16 |
17 |
18 |
19 |
20 | ); 21 | -------------------------------------------------------------------------------- /src/constants/events.js: -------------------------------------------------------------------------------- 1 | const ALERT = "ALERT"; 2 | const REFETCH_CHATS = "REFETCH_CHATS"; 3 | 4 | const NEW_ATTACHMENT = "NEW_ATTACHMENT"; 5 | const NEW_MESSAGE_ALERT = "NEW_MESSAGE_ALERT"; 6 | 7 | const NEW_REQUEST = "NEW_REQUEST"; 8 | const NEW_MESSAGE = "NEW_MESSAGE"; 9 | 10 | const START_TYPING = "START_TYPING"; 11 | const STOP_TYPING = "STOP_TYPING"; 12 | 13 | const CHAT_JOINED = "CHAT_JOINED"; 14 | const CHAT_LEAVED = "CHAT_LEAVED"; 15 | 16 | const ONLINE_USERS = "ONLINE_USERS"; 17 | 18 | export { 19 | ALERT, 20 | REFETCH_CHATS, 21 | NEW_ATTACHMENT, 22 | NEW_MESSAGE_ALERT, 23 | NEW_REQUEST, 24 | NEW_MESSAGE, 25 | START_TYPING, 26 | STOP_TYPING, 27 | CHAT_JOINED, 28 | CHAT_LEAVED, 29 | ONLINE_USERS, 30 | }; 31 | -------------------------------------------------------------------------------- /src/pages/NotFound.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Error as ErrorIcon } from "@mui/icons-material"; 3 | import { Container, Stack, Typography } from "@mui/material"; 4 | import { Link } from "react-router-dom"; 5 | 6 | const NotFound = () => { 7 | return ( 8 | 9 | 15 | 16 | 404 17 | Not Found 18 | Go back to home 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default NotFound; 25 | -------------------------------------------------------------------------------- /src/components/shared/RenderAttachment.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { transformImage } from "../../lib/features"; 3 | import { FileOpen as FileOpenIcon } from "@mui/icons-material"; 4 | 5 | const RenderAttachment = (file, url) => { 6 | switch (file) { 7 | case "video": 8 | return