├── src
├── components
│ ├── Grid
│ │ └── Grid.jsx
│ ├── Modal
│ │ ├── Rename.jsx
│ │ ├── CloseButton.jsx
│ │ ├── Modal.jsx
│ │ ├── ShareModal.jsx
│ │ ├── FolderModal.jsx
│ │ ├── BasicModal.jsx
│ │ └── FileModal.jsx
│ ├── PreLoader
│ │ ├── PreLoader.css
│ │ └── PreLoader.jsx
│ ├── Button
│ │ ├── Button.jsx
│ │ └── FileButton.jsx
│ ├── Header
│ │ └── Header.jsx
│ ├── NaveBar
│ │ ├── NavBar.css
│ │ └── DashNavBar.jsx
│ ├── Sidebar
│ │ ├── SidebarElements
│ │ │ ├── StorageSize.css
│ │ │ ├── BuyNow.jsx
│ │ │ ├── DashboardILinks.jsx
│ │ │ ├── CreateButton.jsx
│ │ │ └── StorageSize.jsx
│ │ └── SideBar.jsx
│ ├── Footer
│ │ └── Footer.jsx
│ ├── Card
│ │ ├── FileCard2.jsx
│ │ └── FileCard.jsx
│ ├── index
│ │ └── index.jsx
│ ├── FolderTree
│ │ └── FolderTree.jsx
│ ├── Test.jsx
│ ├── Notification
│ │ └── Notification.jsx
│ ├── ForgotLayout.jsx
│ ├── Menu
│ │ ├── CreateMenu.jsx
│ │ └── RightClick.jsx
│ ├── Navbar.jsx
│ ├── HomePage.jsx
│ ├── UserProfile
│ │ └── UserProfile.jsx
│ ├── Folder
│ │ └── Folder.jsx
│ └── Login.jsx
├── assets
│ ├── doc.png
│ ├── pdf.png
│ ├── ppt.png
│ ├── xls.png
│ ├── cloud.png
│ ├── v1443.png
│ ├── avatar2.jpg
│ ├── avatar3.png
│ ├── avatar4.jpg
│ ├── logoText.png
│ ├── unnamed.jpg
│ ├── cloudLogin.jpg
│ ├── avatar.svg
│ └── warning.svg
├── features
│ ├── file
│ │ ├── fileSlice.js
│ │ ├── fileApiSlice.js
│ │ └── previewImage.js
│ ├── Global
│ │ ├── sidebarSlice.js
│ │ ├── fileSizeSlice.js
│ │ ├── menuSlice.js
│ │ ├── iconSlice.js
│ │ └── modalSlice.js
│ ├── favourite
│ │ └── favouriteSlice.js
│ ├── trash
│ │ ├── trashFileApiSlice.js
│ │ └── trashFileSlice.js
│ ├── shared
│ │ ├── shareFileApiSlice.js
│ │ └── shareFileSlice.js
│ ├── auth
│ │ ├── RequireAuth.jsx
│ │ ├── authSlice.js
│ │ └── authApiSlice.js
│ ├── folder
│ │ ├── folderApiSlice.js
│ │ └── folderSlice.js
│ └── aws
│ │ └── s3Bucket.js
├── main.css
├── pages
│ ├── LandingPage.jsx
│ ├── OtpPage.jsx
│ ├── FilesPage.jsx
│ ├── DashBoard
│ │ ├── DashBoard.css
│ │ └── Dashboard.jsx
│ ├── TrashPage.jsx
│ ├── FavouirtePage.jsx
│ ├── SharedWithMe.jsx
│ ├── ForgotPassword.jsx
│ ├── ChangePasswordPage.jsx
│ ├── MyDrive.jsx
│ ├── UserProfilePage.jsx
│ ├── SignUpPage.jsx
│ └── LoginPage.jsx
├── main.jsx
├── app
│ ├── api
│ │ ├── driveApiSlice.js
│ │ └── apiSlice.js
│ └── store.js
├── hooks
│ └── useFolder.js
├── routers
│ └── Routers.jsx
├── data
│ └── DummyData.jsx
└── App.jsx
├── public
├── _redirects
└── vite.svg
├── postcss.config.cjs
├── craco.config.js
├── .gitignore
├── .eslintrc.json
├── vite.config.js
├── index.html
├── tailwind.config.cjs
└── package.json
/src/components/Grid/Grid.jsx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/Modal/Rename.jsx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/_redirects:
--------------------------------------------------------------------------------
1 | /* /index.html 200
--------------------------------------------------------------------------------
/src/components/PreLoader/PreLoader.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/doc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/doc.png
--------------------------------------------------------------------------------
/src/assets/pdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/pdf.png
--------------------------------------------------------------------------------
/src/assets/ppt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/ppt.png
--------------------------------------------------------------------------------
/src/assets/xls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/xls.png
--------------------------------------------------------------------------------
/src/features/file/fileSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const fileSlice
--------------------------------------------------------------------------------
/src/assets/cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/cloud.png
--------------------------------------------------------------------------------
/src/assets/v1443.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/v1443.png
--------------------------------------------------------------------------------
/src/assets/avatar2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/avatar2.jpg
--------------------------------------------------------------------------------
/src/assets/avatar3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/avatar3.png
--------------------------------------------------------------------------------
/src/assets/avatar4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/avatar4.jpg
--------------------------------------------------------------------------------
/src/assets/logoText.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/logoText.png
--------------------------------------------------------------------------------
/src/assets/unnamed.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/unnamed.jpg
--------------------------------------------------------------------------------
/src/assets/cloudLogin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfasareekkan/Cloud-Box-Client/HEAD/src/assets/cloudLogin.jpg
--------------------------------------------------------------------------------
/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Button/Button.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | function Button() {
4 | return
Button
;
5 | }
6 |
7 | export default Button;
8 |
--------------------------------------------------------------------------------
/src/components/Header/Header.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | function Header() {
4 | return Header
;
5 | }
6 |
7 | export default Header;
8 |
--------------------------------------------------------------------------------
/src/components/Button/FileButton.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | function FileButton() {
4 | return (
5 | FileButton
6 | );
7 | }
8 |
9 | export default FileButton;
10 |
--------------------------------------------------------------------------------
/src/components/NaveBar/NavBar.css:
--------------------------------------------------------------------------------
1 | .nav{
2 | -webkit-box-shadow: -1px 63px 132px -33px rgba(0,0,0,0.75);
3 | -moz-box-shadow: -1px 63px 132px -33px rgba(0,0,0,0.75);
4 | box-shadow: -1px 63px 132px -33px rgba(0,0,0,0.75);
5 | }
--------------------------------------------------------------------------------
/craco.config.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line linebreak-style
2 | module.exports = {
3 | style: {
4 | postcss: {
5 | plugins: [
6 | require('tailwindcss'), require('autoprefixer')],
7 | },
8 | },
9 | };
10 |
--------------------------------------------------------------------------------
/src/main.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700;800&display=swap');
2 | @tailwind base;
3 | @tailwind components;
4 | @tailwind utilities;
5 |
6 | *{
7 | font-family: 'Open Sans', sans-serif;
8 | }
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/Sidebar/SidebarElements/StorageSize.css:
--------------------------------------------------------------------------------
1 | .css-qhoknl-MuiLinearProgress-bar1{
2 | background-color:#9fa2f6 !important;
3 | }
4 | .css-8ub8io-MuiLinearProgress-dashed{
5 | background-image: radial-gradient(rgb(167, 202, 237) 0%, #9fa2f6 16%, transparent 42%) !important;
6 | }
--------------------------------------------------------------------------------
/src/components/Footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | function Footer() {
4 | return (
5 |
6 |
7 | © 2022 All rights reserved by CloudBox.com
8 |
9 |
10 | );
11 | }
12 |
13 | export default Footer;
14 |
--------------------------------------------------------------------------------
/.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 | .env
--------------------------------------------------------------------------------
/src/components/Sidebar/SidebarElements/BuyNow.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function BuyNow() {
4 | return (
5 | <>
6 |
9 | >
10 | )
11 | }
12 |
13 | export default BuyNow
--------------------------------------------------------------------------------
/src/pages/LandingPage.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable linebreak-style */
2 | import React from 'react';
3 | import HomePage from '../components/HomePage';
4 | import Navebar from '../components/Navbar';
5 |
6 | function LandingPage() {
7 | return (
8 |
9 |
10 |
11 |
12 | );
13 | }
14 |
15 | export default LandingPage;
16 |
--------------------------------------------------------------------------------
/src/components/Modal/CloseButton.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | import React from 'react';
3 | import { IoCloseSharp } from 'react-icons/io5';
4 |
5 | function CloseButton({ closeModal }) {
6 | return (
7 |
11 | );
12 | }
13 |
14 | export default CloseButton;
15 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true
5 | },
6 | "extends": [
7 | "plugin:react/recommended",
8 | "airbnb"
9 | ],
10 | "overrides": [
11 | ],
12 | "parserOptions": {
13 | "ecmaVersion": "latest",
14 | "sourceType": "module"
15 | },
16 | "plugins": [
17 | "react"
18 | ],
19 | "rules": {
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/features/Global/sidebarSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from '@reduxjs/toolkit';
2 |
3 | const sideBarSlice = createSlice({
4 | name: 'sidebar',
5 | initialState: { menu: true },
6 | reducers: {
7 | setSidebar: (state, action) => {
8 | // eslint-disable-next-line no-param-reassign
9 | state.menu = action.payload;
10 | },
11 | },
12 | });
13 |
14 | export const { setSidebar } = sideBarSlice.actions;
15 | export default sideBarSlice.reducer;
16 |
--------------------------------------------------------------------------------
/src/features/Global/fileSizeSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-param-reassign */
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | const fileSizeSlice = createSlice({
5 | name: 'fileSize',
6 | initialState: {
7 | fileSize: 0,
8 | },
9 | reducers: {
10 | setFileSize: (state, action) => {
11 | state.fileSize = action.payload;
12 | },
13 | },
14 | });
15 | export const { setFileSize } = fileSizeSlice.actions;
16 | export default fileSizeSlice.reducer;
17 |
--------------------------------------------------------------------------------
/src/features/favourite/favouriteSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const favouriteSlice = createSlice({
4 | name: 'favourite',
5 | initialState: {
6 | favouriteFiles:[]
7 | },
8 | reducers: {
9 | setFavourite: (state,action) => {
10 | state.favouriteFiles = action.payload
11 | }
12 | }
13 | })
14 |
15 | export const { setFavourite } = favouriteSlice.actions;
16 | export default favouriteSlice.reducer;
--------------------------------------------------------------------------------
/src/features/trash/trashFileApiSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/prefer-default-export */
2 | import { driveApiSlice } from '../../app/api/driveApiSlice';
3 |
4 | export const fileTrashApiSlice = driveApiSlice.injectEndpoints({
5 | endpoints: (builder) => ({
6 | getTrashFile: builder.mutation({
7 | query: (credentials) => ({
8 | url: 'trash/',
9 | method: 'GET',
10 | }),
11 | }),
12 | }),
13 | });
14 |
15 | export const {
16 | useGetTrashFileMutation
17 | }=fileTrashApiSlice
18 |
--------------------------------------------------------------------------------
/src/features/shared/shareFileApiSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/prefer-default-export */
2 | import { driveApiSlice } from '../../app/api/driveApiSlice';
3 |
4 | export const fileShareApiSlice = driveApiSlice.injectEndpoints({
5 | endpoints: (builder) => ({
6 | getAllShareFiles: builder.mutation({
7 | query: (credentials) => ({
8 | url: `files/get-shared-files`,
9 | method: 'GET',
10 | }),
11 | }),
12 | }),
13 | });
14 |
15 | export const
16 | {
17 | useGetAllShareFilesMutation,
18 | } = fileShareApiSlice;
19 |
--------------------------------------------------------------------------------
/src/features/trash/trashFileSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-param-reassign */
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | const trashFileSlice = createSlice({
5 | name: 'trash',
6 | initialState: {
7 | folderId: null,
8 | folder: null,
9 | childFolders: [],
10 | childFiles: [],
11 | // path: [{ path: 'MyDrive', id: 'myDrive' }],
12 | },
13 | reducers: {
14 | setTrashFile: (state, action) => {
15 | state.childFiles = action.payload;
16 | },
17 | },
18 | });
19 |
20 | export const { setTrashFile } = trashFileSlice.actions;
21 | export default trashFileSlice.reducer;
22 |
--------------------------------------------------------------------------------
/src/features/shared/shareFileSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-param-reassign */
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | const sharedFileSlice = createSlice({
5 | name: 'sharedFile',
6 | initialState: {
7 | folderId: null,
8 | folder: null,
9 | childFolders: [],
10 | childFiles: [],
11 | // path: [{ path: 'MyDrive', id: 'myDrive' }],
12 | },
13 | reducers: {
14 | setChileFiles: (state, action) => {
15 | state.childFiles = action.payload;
16 | },
17 | },
18 | });
19 |
20 | export const { setChileFiles } = sharedFileSlice.actions;
21 | export default sharedFileSlice.reducer;
22 |
--------------------------------------------------------------------------------
/src/components/Card/FileCard2.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 |
4 | export default function FileCard2({value}) {
5 | return (
6 |
7 |
8 |

11 |
12 | {value?.fileName}
13 |
14 |
15 |
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/features/auth/RequireAuth.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useLocation, Navigate ,Outlet} from 'react-router-dom';
3 | import { useSelector } from 'react-redux';
4 | import { selectCurrentToken } from './authSlice';
5 |
6 | // eslint-disable-next-line react/prop-types
7 | function RequireAuth({ children }) {
8 | const token = localStorage.getItem('accessToken');
9 | const location = useLocation();
10 |
11 | // eslint-disable-next-line react/jsx-filename-extension
12 | return (
13 | token ? :
14 | );
15 | }
16 |
17 | export default RequireAuth;
18 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | resolve: {
8 | alias: {
9 | './runtimeConfig': './runtimeConfig.browser',
10 | },
11 | },
12 | build: {
13 | commonjsOptions: { include: [] },
14 | },
15 | optimizeDeps: {
16 | disabled: false,
17 | },
18 | });
19 |
20 | // import { defineConfig } from "vite";
21 | // import { NgmiPolyfill } from "vite-plugin-ngmi-polyfill";
22 |
23 | // export default defineConfig({
24 | // plugins: [NgmiPolyfill()],
25 | // });
26 |
--------------------------------------------------------------------------------
/src/features/Global/menuSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from '@reduxjs/toolkit';
2 |
3 | const createMenuSlice = createSlice({
4 | name: 'createMenu',
5 | initialState: { createMenu: false, rightClickMenu: false },
6 | reducers: {
7 | setCreateMenu: (state, action) => {
8 | // eslint-disable-next-line no-param-reassign
9 | state.createMenu = action.payload;
10 | },
11 | setRightClickMenu: (state, action) => {
12 | // eslint-disable-next-line no-param-reassign
13 | state.rightClickMenu = action.payload;
14 | },
15 | },
16 | });
17 | export const { setCreateMenu, setRightClickMenu } = createMenuSlice.actions;
18 | export default createMenuSlice.reducer;
19 |
--------------------------------------------------------------------------------
/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Provider } from 'react-redux';
3 | import ReactDOM from 'react-dom/client';
4 | import { BrowserRouter } from 'react-router-dom';
5 | import { PersistGate } from 'redux-persist/integration/react';
6 |
7 |
8 |
9 | import App from './App';
10 | import './main.css';
11 | import { store, persistor } from './app/store';
12 |
13 | ReactDOM.createRoot(document.getElementById('root')).render(
14 | //
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | //
25 | ,
26 | );
27 |
--------------------------------------------------------------------------------
/src/features/Global/iconSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-param-reassign */
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | const iconSlice = createSlice({
5 | name: 'icon',
6 | initialState: { notification: false, userProfile: false },
7 | reducers: {
8 | setNotification: (state, action) => {
9 | state.notification = action.payload;
10 | state.userProfile = false;
11 | },
12 | setUserProfile: (state, action) => {
13 | // eslint-disable-next-line no-param-reassign
14 | state.notification = false;
15 | state.userProfile = action.payload;
16 | },
17 | },
18 |
19 | });
20 | export const { setNotification, setUserProfile } = iconSlice.actions;
21 | export default iconSlice.reducer;
22 |
--------------------------------------------------------------------------------
/src/components/index/index.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-cycle */
2 | /* eslint-disable import/prefer-default-export */
3 | export { default as Button } from '../Button/Button';
4 | export { default as Footer } from '../Footer/Footer';
5 | export { default as Header } from '../Header/Header';
6 | export { default as DashNavBar } from '../NaveBar/DashNavBar';
7 | export { default as SideBar } from '../Sidebar/SideBar';
8 | export { default as Notification } from '../Notification/Notification';
9 | export { default as UserProfile } from '../UserProfile/UserProfile';
10 | export { default as FolderTree } from '../FolderTree/FolderTree';
11 | export { default as Folder } from '../Folder/Folder';
12 | export { default as FileCard } from '../Card/FileCard';
13 |
--------------------------------------------------------------------------------
/src/components/Sidebar/SidebarElements/DashboardILinks.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 | import { links } from '../../../data/DummyData';
4 |
5 | function DashboardILinks() {
6 | return (
7 | <>
8 | {
9 | links.map((link) => (
10 |
11 |
12 |
{link.icon}
13 |
14 |
{link.title}
15 |
16 |
17 | ))
18 | }
19 | >
20 | );
21 | }
22 |
23 | export default DashboardILinks;
24 |
--------------------------------------------------------------------------------
/src/components/PreLoader/PreLoader.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { motion } from 'framer-motion';
3 | import logoText from '../../assets/logoText.png';
4 | import './PreLoader.css';
5 |
6 | const imageVariants = {
7 | hidden: {
8 | opacity: 0,
9 | },
10 | visible: {
11 | opacity: 1,
12 | transition: {
13 | duration: 1,
14 | yoyo: Infinity,
15 | ease: 'easeInOut',
16 | },
17 | },
18 | };
19 |
20 | function PreLoader() {
21 | return (
22 |
27 | );
28 | }
29 |
30 | export default PreLoader;
31 |
--------------------------------------------------------------------------------
/src/app/api/driveApiSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/prefer-default-export */
2 |
3 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
4 |
5 | const driveBaseQuery = fetchBaseQuery({
6 | baseUrl: import.meta.env.VITE_DRIVE_API,
7 | credentials: 'include',
8 | prepareHeaders: (headers) => {
9 | const token = localStorage.getItem('refreshToken');
10 | const accessToken = localStorage.getItem('accessToken');
11 | if (token) {
12 | headers.set('refreshAuthorization', `Bearer ${token}`);
13 | }
14 | if (accessToken) {
15 | headers.set('authorization', `Bearer ${accessToken}`);
16 | }
17 | return headers;
18 | },
19 | });
20 |
21 | export const driveApiSlice = createApi({
22 | baseQuery: driveBaseQuery,
23 | reducerPath: 'driveApi',
24 | endpoints: () => ({}),
25 | });
26 |
--------------------------------------------------------------------------------
/src/features/auth/authSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-param-reassign */
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | const authSlice = createSlice({
5 | name: 'auth',
6 | initialState: { user: null, token: null },
7 | reducers: {
8 | setCredentials: (state, action) => {
9 | const { user, accessToken } = action.payload;
10 | state.user = user;
11 | state.token = accessToken;
12 | },
13 | logOut(state) {
14 | state.user = null;
15 | state.token = null;
16 | },
17 | changeOtpStatus: (state) => {
18 | state.user.otpVerify = true;
19 | }
20 | },
21 | });
22 |
23 | export const { setCredentials, logOut, changeOtpStatus } = authSlice.actions;
24 | export default authSlice.reducer;
25 | export const selectCurrentUser = (state) => state.auth.user;
26 | export const selectCurrentToken = (state) => state.auth.token;
27 |
--------------------------------------------------------------------------------
/src/components/Sidebar/SidebarElements/CreateButton.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { MdAdd } from 'react-icons/md';
3 | import { useDispatch, useSelector } from 'react-redux';
4 | import { setCreateMenu } from '../../../features/Global/menuSlice';
5 |
6 |
7 | function CreateButton() {
8 | const dispatch=useDispatch()
9 | const createMenu = useSelector((state) => state.createMenu.createMenu);
10 | const clickHandler = () => {
11 | dispatch(setCreateMenu(!createMenu));
12 | };
13 | // const folderState = useFolder('639abaa0dd042441f67912a5')
14 | // console.log(folderState);
15 | return (
16 |
17 |
21 |
22 | );
23 | }
24 |
25 | export default CreateButton;
26 |
--------------------------------------------------------------------------------
/src/components/Modal/Modal.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | /* eslint-disable jsx-a11y/no-static-element-interactions */
3 | /* eslint-disable jsx-a11y/click-events-have-key-events */
4 | import React from 'react';
5 | import CloseButton from './CloseButton';
6 |
7 | function Modal({
8 | children, id, active, closeActive,
9 | }) {
10 | const handleClose = (e) => {
11 | if (e.target.id === id) {
12 | closeActive();
13 | }
14 | };
15 |
16 | return (
17 |
24 |
27 | {children}
28 |
29 |
30 |
31 | );
32 | }
33 |
34 | export default Modal;
35 |
--------------------------------------------------------------------------------
/src/components/FolderTree/FolderTree.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
2 | /* eslint-disable jsx-a11y/click-events-have-key-events */
3 | import React from 'react';
4 | import { useSelector, useDispatch } from 'react-redux';
5 | import { useNavigate } from 'react-router-dom';
6 | import Breadcrumbs from '@mui/material/Breadcrumbs';
7 | import { updatePath } from '../../features/folder/folderSlice';
8 |
9 | function FolderTree() {
10 | const dispatch = useDispatch();
11 | const paths = useSelector((state) => state.folder.path);
12 | const navigate = useNavigate();
13 | const handleClick = (path) => {
14 | dispatch(updatePath(path));
15 | navigate(`/dashboard/v1/${path.id}`);
16 | };
17 | return (
18 |
19 |
20 | {paths.map((path) => (
21 | handleClick(path)} color="inherit">
22 | {path.path}
23 |
24 | ))}
25 |
26 | {/* File */}
27 |
28 |
29 | );
30 | }
31 |
32 | export default FolderTree;
33 |
--------------------------------------------------------------------------------
/src/pages/OtpPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { useLocation, useNavigate } from 'react-router-dom';
3 | import { toast } from 'react-hot-toast';
4 | import ForgotLayout from '../components/ForgotLayout';
5 | import { useSubmitChangeOtpMutation } from '../features/auth/authApiSlice';
6 |
7 | function OtpPage() {
8 | const [otp, setOtp] = useState('');
9 | const navigate = useNavigate();
10 | const location = useLocation();
11 | const [submitChangeOtp]=useSubmitChangeOtpMutation()
12 | const handleChang = (e) => {
13 | setOtp(e.target.value);
14 | };
15 | const handleSubmit = async(e) => {
16 | try {
17 | await submitChangeOtp({ email: location.state.email, otp }).unwrap();
18 | navigate('/change-password', {
19 | state: {
20 | email: location.state.email,
21 | otp
22 | },
23 | });
24 | } catch (error) {
25 | toast.error(error.data.message)
26 | }
27 |
28 | };
29 | return (
30 |
31 | );
32 | }
33 |
34 | export default OtpPage;
35 |
--------------------------------------------------------------------------------
/src/components/Test.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react"
2 |
3 | export default () => {
4 | const [cur, setCur] = useState('')
5 | const [prev, setPrev] = useState('')
6 | const [post, setPost] = useState('')
7 |
8 |
9 | function sample(n,e) {
10 | if (n == 1) {
11 | setCur('red')
12 | setPrev('')
13 | setPost('blue')
14 | }
15 |
16 |
17 | }
18 | return (
19 |
20 |
21 |
22 |
28 |
33 |
37 |
41 |
45 |
46 | )
47 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cloud Box
8 |
9 |
15 |
30 |
31 |
32 |
33 |
36 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/features/folder/folderApiSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/prefer-default-export */
2 | import { driveApiSlice } from '../../app/api/driveApiSlice';
3 |
4 | export const folderApiSlice = driveApiSlice.injectEndpoints({
5 | endpoints: (builder) => ({
6 | createFolder: builder.mutation({
7 | query: (credentials) => ({
8 | url: 'create-folder',
9 | method: 'POST',
10 | body: { ...credentials },
11 | }),
12 | }),
13 | getFolder: builder.mutation({
14 | query: (credentials) => ({
15 | url: 'get-folder',
16 | body: { ...credentials },
17 | method: 'POST',
18 | }),
19 | }),
20 | getAllFoldersAndFiles: builder.mutation({
21 | query: (credentials) => ({
22 | url: 'get-all-folders',
23 | body: { ...credentials },
24 | method: 'POST',
25 | }),
26 | }),
27 | isUserShareFolder: builder.mutation({
28 | query: (credentials) => ({
29 | url: 'share-folder',
30 | body: { ...credentials },
31 | method: 'POST',
32 | }),
33 | }),
34 | }),
35 | });
36 |
37 | export const
38 | {
39 | useCreateFolderMutation, useGetFolderMutation,
40 | useGetAllFoldersAndFilesMutation, useIsUserShareFolderMutation,
41 | } = folderApiSlice;
42 |
--------------------------------------------------------------------------------
/src/hooks/useFolder.js:
--------------------------------------------------------------------------------
1 | // /* eslint-disable consistent-return */
2 | // /* eslint-disable import/prefer-default-export */
3 | // import { useEffect } from 'react';
4 | // import { useDispatch, useSelector } from 'react-redux';
5 | // import { selectFolder, updateFolder } from '../features/folder/folderSlice';
6 | // import { useGetFolderMutation } from '../features/folder/folderApiSlice';
7 |
8 | // const ROOT_FOLDER = { title: 'Root', folderId: null };
9 |
10 | // export function useFolder(folderId = null, folder = null, level=1) {
11 | // const dispatch = useDispatch();
12 | // const folderState = useSelector((state) => state.folder);
13 | // const [getFolder, { isLoading }] = useGetFolderMutation();
14 | // // eslint-disable-next-line no-shadow
15 | // // async function getOneFolder(folderId) {
16 | // // let data = await getFolder({ folderId }).unwrap();
17 | // // console.log(data);
18 | // // }
19 | // useEffect(() => {
20 | // dispatch(selectFolder(folderId, folder));
21 | // }, [folder, folderId]);
22 |
23 | // // useEffect(() => {
24 | // // if (folderId == null) {
25 | // // return dispatch(updateFolder(ROOT_FOLDER));
26 | // // }
27 | // // getOneFolder(folderId);
28 | // // }, [folderId]);
29 |
30 | // return folderState;
31 | // }
32 |
--------------------------------------------------------------------------------
/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ["./src/**/*.{js,jsx,ts,tsx}",],
4 | darkMode: 'class',
5 | theme: {
6 | fontFamily: {
7 | display: ['Open Sans', 'sans-serif'],
8 | body: ['Open Sans', 'sans-serif'],
9 | },
10 | extend: {
11 | fontSize: {
12 | 14: '14px',
13 | },
14 | backgroundColor: {
15 | 'main-bg': '#FAFBFB',
16 | 'main-dark-bg': '#20232A',
17 | 'secondary-dark-bg': '#33373E',
18 | 'light-gray': '#F7F7F7',
19 | 'half-transparent': 'rgba(0, 0, 0, 0.5)',
20 | },
21 | borderWidth: {
22 | 1: '1px',
23 | },
24 | borderColor: {
25 | color: 'rgba(0, 0, 0, 0.1)',
26 | },
27 | width: {
28 | 400: '400px',
29 | 760: '760px',
30 | 780: '780px',
31 | 800: '800px',
32 | 1000: '1000px',
33 | 1200: '1200px',
34 | 1400: '1400px',
35 | },
36 | height: {
37 | 80: '80px',
38 | },
39 | minHeight: {
40 | 590: '590px',
41 | },
42 | backgroundImage: {
43 | 'hero-pattern':
44 | "url('https://i.ibb.co/MkvLDfb/Rectangle-4389.png')",
45 | },
46 | },
47 | },
48 | plugins: [],
49 | };
50 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/pages/FilesPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect ,useState} from 'react'
2 | import FileCard2 from '../components/Card/FileCard2'
3 | import { useGetAllFileMutation } from '../features/file/fileApiSlice'
4 |
5 | function FilesPages() {
6 | const [files, setFiles] = useState([])
7 | const [getAllFile] = useGetAllFileMutation()
8 | async function getAllFiles() {
9 | let data =await getAllFile().unwrap();
10 | setFiles(data);
11 | console.log(files);
12 | }
13 | useEffect(() => {
14 | getAllFiles()
15 | },[])
16 | return (
17 |
18 |
19 |
Documents
20 |
21 |
22 |
23 | {
24 | files?.map((value) => (
25 |
26 | ))
27 | }
28 | {/* {
29 | folder.childFiles?.map((value) => (
30 | // eslint-disable-next-line no-underscore-dangle
31 |
32 |
33 | ))
34 | } */}
35 |
36 |
37 |
38 |
39 | )
40 | }
41 |
42 | export default FilesPages
--------------------------------------------------------------------------------
/src/features/Global/modalSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-param-reassign */
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | const modalSlice = createSlice({
5 | name: 'modal',
6 | initialState: {
7 | folderCreationModal: false,
8 | fileCreationModal: false,
9 | shareFolder: false,
10 | shareFolderId: '',
11 | },
12 | reducers: {
13 | openFolderCreation: (state) => {
14 | if (state.folderCreationModal) state.folderCreationModal = false;
15 | state.folderCreationModal = true;
16 | },
17 | closeFolderCreation: (state) => {
18 | state.folderCreationModal = false;
19 | },
20 | openFileCreation: (state) => {
21 | if (state.fileCreationModal) state.fileCreationModal = false;
22 | state.fileCreationModal = true;
23 | },
24 | closeFileCreation: (state) => {
25 | state.fileCreationModal = false;
26 | },
27 | openFolderShare: (state) => {
28 | if (state.shareFolder) state.shareFolder = false;
29 | state.shareFolder = true;
30 | },
31 | closeFolderShare: (state) => {
32 | state.shareFolder = false;
33 | },
34 | setShareFolderModalId: (state, action) => {
35 | state.shareFolderId = action.payload;
36 | },
37 | },
38 |
39 | });
40 |
41 | export const
42 | {
43 | openFolderCreation, closeFolderCreation,
44 | openFileCreation, closeFileCreation, openFolderShare, closeFolderShare, setShareFolderModalId,
45 | } = modalSlice.actions;
46 | export default modalSlice.reducer;
47 |
--------------------------------------------------------------------------------
/src/pages/DashBoard/DashBoard.css:
--------------------------------------------------------------------------------
1 | @import url('https://cdn.syncfusion.com/ej2/material.css');
2 |
3 | .sidebar {
4 | box-shadow: rgb(113 122 131 / 11%) 0px 7px 30px 0px;
5 | }
6 | .nav-item,
7 | .navbar {
8 | z-index: 10000;
9 | }
10 | @media screen and (max-width:800px) {
11 | .sidebar{
12 | z-index: 10000000;
13 | }
14 | }
15 |
16 | .e-dlg-center-center, .e-quick-popup-wrapper.e-device{
17 | z-index: 1000000 !important;
18 | }
19 |
20 | ::-webkit-scrollbar {
21 | width: 6px;
22 | }
23 | ::-webkit-scrollbar-thumb {
24 | background-color: rgb(216, 216, 216);
25 | border-radius: 40px;
26 | }
27 | ::-webkit-scrollbar-track {
28 | background-color: transparent;
29 | }
30 |
31 | /* color-picker style */
32 |
33 | #preview {
34 | background: transparent
35 | url('https://ej2.syncfusion.com/react/demos/src/color-picker/images/pen.png')
36 | no-repeat;
37 | display: inline-block;
38 | height: 80px;
39 | margin: 10px 0;
40 | min-width: 300px;
41 | max-width: 600px;
42 | background-color: #008000;
43 | }
44 |
45 | .e-input-group:not(.e-float-icon-left), .e-input-group.e-success:not(.e-float-icon-left), .e-input-group.e-warning:not(.e-float-icon-left), .e-input-group.e-error:not(.e-float-icon-left), .e-input-group.e-control-wrapper:not(.e-float-icon-left), .e-input-group.e-control-wrapper.e-success:not(.e-float-icon-left), .e-input-group.e-control-wrapper.e-warning:not(.e-float-icon-left), .e-input-group.e-control-wrapper.e-error:not(.e-float-icon-left){
46 | border: none;
47 | }
--------------------------------------------------------------------------------
/src/features/aws/s3Bucket.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable consistent-return */
2 | /* eslint-disable import/prefer-default-export */
3 | import S3 from 'aws-sdk/clients/s3';
4 | // import {S3Client} from "@aws-sdk/client-s3";
5 |
6 |
7 | const bucketName = import.meta.env.VITE_AWS_BUCKET_NAME;
8 | const region = import.meta.env.VITE_AWS_BUCKET_REGION;
9 | const accessKeyId = import.meta.env.VITE_AWS_ACCESS_KEY;
10 | const secretAccessKey = import.meta.env.VITE_AWS_SECRET_KEY;
11 |
12 | const s3 = new S3({
13 | region,
14 | accessKeyId,
15 | secretAccessKey,
16 | });
17 | export async function getObjectUrl(key, bucket) {
18 | const params = {
19 | Bucket: bucket,
20 | Key: key,
21 | };
22 | try {
23 | const data = await s3.getObject(params).promise();
24 | const url = data.Body.toString('utf-8');
25 | return url;
26 | } catch (error) {
27 | console.log(error);
28 | }
29 | }
30 |
31 | export async function uploadFile(file, fileStream) {
32 | const uploadParams = {
33 | Bucket: bucketName,
34 | Key: file.name,
35 | Body: fileStream
36 | }
37 | return s3.upload(uploadParams).promise()
38 | // const signedUrl = await s3.getSignedUrlPromise('putObject', {
39 | // Bucket: bucketName,
40 | // Key: file.name,
41 | // ContentType: file.type,
42 |
43 | // });
44 | // console.log(signedUrl);
45 | // // upload the file to the signed URL
46 | // const response = await fetch(signedUrl, {
47 | // method: 'PUT',
48 | // body: fileStream,
49 | // // mode: 'no-cors'
50 |
51 | // });
52 | // console.log(response);
53 | }
54 |
--------------------------------------------------------------------------------
/src/components/Sidebar/SidebarElements/StorageSize.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import { useDispatch, useSelector } from 'react-redux';
3 | import Box from '@mui/material/Box';
4 | import LinearProgress from '@mui/material/LinearProgress';
5 | import './StorageSize.css';
6 | import { useGetFileSizeQuery } from '../../../features/file/fileApiSlice';
7 | import { setFileSize } from '../../../features/Global/fileSizeSlice';
8 |
9 | function StorageSize() {
10 | const dispatch = useDispatch();
11 | const { data: getFileSize } = useGetFileSizeQuery();
12 | // console.log(data);
13 | useEffect(() => {
14 | console.log(getFileSize);
15 | dispatch(setFileSize(getFileSize?.fileSize));
16 | }, [getFileSize]);
17 |
18 | const fileSize = useSelector((state) => state.fileSize?.fileSize);
19 | const kb = fileSize / 1024;
20 | let mb = Math.floor(kb / 1024);
21 | let percentage = Math.ceil(mb / (1024 * 100));
22 | // if (typeof percentage !== 'number' && typeof mb !== 'number') {
23 | // console.log(mb);
24 | // mb = 0;
25 | // percentage = 0;
26 | // }
27 | return (
28 |
29 |
30 | {mb}
31 | Mb / 1 GB Used
32 |
33 |
34 |
35 |
36 |
37 | { percentage}
38 | % Used
39 |
40 |
41 |
42 | );
43 | }
44 |
45 | export default StorageSize;
46 |
--------------------------------------------------------------------------------
/src/components/Modal/ShareModal.jsx:
--------------------------------------------------------------------------------
1 | // import React, { useState, useRef, useEffect } from 'react';
2 | // import { useDispatch, useSelector } from 'react-redux';
3 | // import Modal from './Modal';
4 | // import { closeFolderShare } from '../../features/Global/modalSlice';
5 |
6 | // function ShareModal() {
7 | // const inputRef=useRef()
8 | // const [email, setEmail] = useState('');
9 | // const handleEmail = (e) => {
10 | // setEmail(e.target.value);
11 | // }
12 | // const dispatch = useDispatch();
13 | // const folderShare = useSelector((state) => state.modal.shareFolder);
14 | // const modalId = useSelector((state) => state.modal.shareFolderId);
15 | // console.log(email);
16 | // useEffect(() => {
17 | // inputRef.current.focus()
18 | // inputRef.current.select()
19 | // },[folderShare])
20 | // return (
21 | // dispatch(closeFolderShare())}>
22 | //
23 | //
Add Users
24 | //
25 | //
26 | //
27 | //
28 |
29 | //
30 |
31 | //
32 | //
33 | // );
34 | // }
35 |
36 | // export default ShareModal;
37 |
--------------------------------------------------------------------------------
/src/app/api/apiSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/prefer-default-export */
2 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
3 | import { setCredentials, logOut } from '../../features/auth/authSlice';
4 |
5 | const baseQuery = fetchBaseQuery({
6 | baseUrl: import.meta.env.VITE_AUTH_API,
7 | credentials: 'include',
8 | prepareHeaders: (headers) => {
9 | const token = localStorage.getItem('refreshToken');
10 | const accessToken = localStorage.getItem('accessToken');
11 | if (token) {
12 | headers.set('refreshAuthorization', `Bearer ${token}`);
13 | }
14 | if (accessToken) {
15 | headers.set('authorization', `Bearer ${accessToken}`);
16 | }
17 | return headers;
18 | },
19 | });
20 |
21 | const baseQueryWithReAuth = async (args, api, extraOptions) => {
22 | let result = await baseQuery(args, api, extraOptions);
23 | if (result?.error?.originalStatus === 403) {
24 | // console.log(`sending refresh token`);
25 | // send the refresh token to get new accessToken
26 | const refreshResult = await baseQuery('/refresh', api, extraOptions);
27 | console.log(refreshResult);
28 | if (refreshResult?.data) {
29 | // eslint-disable-next-line no-undef
30 | const user = getState().auth.token;
31 | api.dispatch(setCredentials({ ...refreshResult.data, user }));
32 | // retry the original query with new access token
33 | result = await baseQuery(args, api, extraOptions);
34 | } else {
35 | api.dispatch(logOut());
36 | }
37 | }
38 | return result;
39 | };
40 |
41 | export const apiSlice = createApi({
42 | baseQuery,
43 |
44 | endpoints: () => ({}),
45 | });
46 |
--------------------------------------------------------------------------------
/src/components/Notification/Notification.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { MdOutlineCancel } from 'react-icons/md';
3 |
4 | import { chatData } from '../../data/DummyData';
5 | import { Button } from '../index';
6 |
7 | function Notification() {
8 | return (
9 |
10 |
11 |
12 |
Notifications
13 |
14 |
15 |
} color="rgb(153, 171, 180)" bgHoverColor="light-gray" size="2xl" borderRadius="50%" />
16 |
17 |
18 | {chatData?.map((item, index) => (
19 |
20 |

21 |
22 |
{item.message}
23 |
24 | {' '}
25 | {item.desc}
26 | {' '}
27 |
28 |
29 |
30 | ))}
31 |
32 |
33 |
34 |
35 |
36 | );
37 | }
38 |
39 | export default Notification;
40 |
--------------------------------------------------------------------------------
/src/features/file/fileApiSlice.js:
--------------------------------------------------------------------------------
1 | import { driveApiSlice } from '../../app/api/driveApiSlice';
2 |
3 | const fileApiSlice = driveApiSlice.injectEndpoints({
4 | endpoints: (builder) => ({
5 | uploadFile: builder.mutation({
6 | query: (credentials) => ({
7 | url: 'files/upload',
8 | method: 'POST',
9 | body: { ...credentials },
10 | }),
11 | }),
12 | getFileSize: builder.query({
13 | query: () => ({
14 | url: 'files/get-file-size',
15 | method: 'GET',
16 |
17 | // body: { ...credentials },
18 | }),
19 | }),
20 | getFile: builder.mutation({
21 | query: (credentials) => ({
22 | url: 'files/get-file',
23 | method: 'POST',
24 |
25 | body: { ...credentials },
26 | }),
27 | }),
28 | getAllFile: builder.mutation({
29 | query: (credentials) => ({
30 | url: 'files/get-all-file',
31 | method: 'GET',
32 | }),
33 | }),
34 | deleteFile: builder.mutation({
35 | query: (credentials) => ({
36 | url: `files/delete-file/${credentials}`,
37 | method: 'DELETE',
38 | }),
39 | }),
40 | addToFavourite: builder.mutation({
41 | query: (credentials) => ({
42 | url: `files/add-to-favourite/${credentials}`,
43 | method: 'PATCH',
44 | }),
45 | }),
46 | getAllFavorite: builder.mutation({
47 | query: () => ({
48 | url: 'files/get-all-favorite',
49 | method: 'GET',
50 | }),
51 | }),
52 | }),
53 |
54 | });
55 |
56 | export const {
57 | useUploadFileMutation, useGetFileSizeQuery, useGetFileMutation, useGetAllFileMutation,
58 | useDeleteFileMutation,useAddToFavouriteMutation,useGetAllFavoriteMutation
59 | } = fileApiSlice;
60 |
--------------------------------------------------------------------------------
/src/assets/avatar.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/pages/TrashPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react';
2 | import { useDispatch, useSelector } from 'react-redux';
3 | import { setTrashFile } from '../features/trash/trashFileSlice';
4 | import FileCard2 from '../components/Card/FileCard2';
5 | import { useGetTrashFileMutation } from '../features/trash/trashFileApiSlice';
6 |
7 | function TrashPage() {
8 | const [getTrashFile] = useGetTrashFileMutation()
9 | const dispatch = useDispatch();
10 | const childFiles=useSelector((state)=>state.trash.childFiles)
11 | async function SharedWithMeGET() {
12 | const data = await getTrashFile().unwrap();
13 | dispatch(setTrashFile(data))
14 | }
15 | useEffect(() => {
16 | SharedWithMeGET()
17 |
18 | },[])
19 | return (
20 |
21 |
22 | {/*
23 |
Folders
24 |
25 | {/*
26 | {folder.childFolders?.map((value) => (
27 | // eslint-disable-next-line no-underscore-dangle
28 |
29 | ))} */}
30 |
31 | {/*
*/}
32 | {/*
*/}
33 |
34 |
Trash
35 |
36 |
37 | {
38 | childFiles?.map((value) => (
39 | // eslint-disable-next-line no-underscore-dangle
40 |
41 |
42 | ))
43 | }
44 |
45 |
46 |
47 |
48 | );
49 | }
50 |
51 | export default TrashPage;
52 |
--------------------------------------------------------------------------------
/src/pages/FavouirtePage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react';
2 | import { useDispatch, useSelector } from 'react-redux';
3 | import { setFavourite } from '../features/favourite/favouriteSlice';
4 | import FileCard2 from '../components/Card/FileCard2';
5 | import { useGetAllFavoriteMutation } from '../features/file/fileApiSlice';
6 |
7 | function FavouritePage() {
8 | const [getAllFavorite] = useGetAllFavoriteMutation();
9 | const dispatch = useDispatch();
10 | const childFiles = useSelector((state) => state.favourite.favouriteFiles);
11 | async function favouriteFiles() {
12 | const data = await getAllFavorite().unwrap();
13 | dispatch(setFavourite(data));
14 | }
15 | useEffect(() => {
16 | favouriteFiles();
17 | }, []);
18 | return (
19 |
20 |
21 | {/*
22 |
Folders
23 |
24 | {/*
25 | {folder.childFolders?.map((value) => (
26 | // eslint-disable-next-line no-underscore-dangle
27 |
28 | ))} */}
29 |
30 | {/*
*/}
31 | {/*
*/}
32 |
33 |
Trash
34 |
35 |
36 | {
37 | childFiles?.map((value) => (
38 | // eslint-disable-next-line no-underscore-dangle
39 |
40 |
41 | ))
42 | }
43 |
44 |
45 |
46 |
47 | );
48 | }
49 |
50 | export default FavouritePage;
51 |
--------------------------------------------------------------------------------
/src/pages/SharedWithMe.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react'
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { useGetAllShareFilesMutation } from '../features/shared/shareFileApiSlice';
4 | import { setChileFiles } from '../features/shared/shareFileSlice';
5 | import { FileCard } from '../components/index';
6 |
7 | function SharedWithMe() {
8 | const [getAllShareFiles] = useGetAllShareFilesMutation()
9 | const dispatch = useDispatch();
10 | const childFiles=useSelector((state)=>state.shared.childFiles)
11 | async function SharedWithMeGET() {
12 | let data = await getAllShareFiles().unwrap()
13 | dispatch(setChileFiles(data))
14 | }
15 | useEffect(() => {
16 | SharedWithMeGET()
17 |
18 | },[])
19 | return (
20 |
21 |
22 |
23 |
Folders
24 |
25 | {/*
26 | {folder.childFolders?.map((value) => (
27 | // eslint-disable-next-line no-underscore-dangle
28 |
29 | ))} */}
30 |
31 |
32 |
33 |
34 |
Documents
35 |
36 |
37 |
38 | {
39 | childFiles?.map((value) => (
40 | // eslint-disable-next-line no-underscore-dangle
41 |
42 |
43 | ))
44 | }
45 |
46 |
47 |
48 |
49 | )
50 | }
51 |
52 | export default SharedWithMe
--------------------------------------------------------------------------------
/src/routers/Routers.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Routes, Route } from 'react-router-dom';
3 | import LandingPage from '../pages/LandingPage';
4 | import LoginPage from '../pages/LoginPage';
5 | import SignUpPage from '../pages/SignUpPage';
6 | import Dashboard from '../pages/DashBoard/Dashboard';
7 | import RequireAuth from '../features/auth/RequireAuth';
8 | import MyDrive from '../pages/MyDrive';
9 | import SharedWithMe from '../pages/SharedWithMe';
10 | import FilesPages from '../pages/FilesPage';
11 | import UserProfilePage from '../pages/UserProfilePage';
12 | import ForgotPassword from '../pages/ForgotPassword';
13 | import OtpPage from '../pages/OtpPage';
14 | import ChangePasswordPage from '../pages/ChangePasswordPage';
15 | import TrashPage from '../pages/TrashPage';
16 | import FavouritePage from '../pages/FavouirtePage';
17 |
18 | function Routers() {
19 | return (
20 |
21 | } />
22 | } />
23 | } />
24 | } />
25 | } />
26 | } />
27 |
28 |
29 | {/* protected route */}
30 | }>
31 | }>
32 | } />
33 | } />
34 | } />
35 | } />
36 | } />
37 | } />
38 | } />
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | );
47 | }
48 |
49 | export default Routers;
50 |
--------------------------------------------------------------------------------
/src/app/store.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/prefer-default-export */
2 | import { configureStore } from '@reduxjs/toolkit';
3 | import {
4 | persistStore, persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER,
5 | } from 'redux-persist';
6 | import storage from 'redux-persist/lib/storage';
7 | import { apiSlice } from './api/apiSlice';
8 | import authReducer from '../features/auth/authSlice';
9 | import SidebarReducer from '../features/Global/sidebarSlice';
10 | import iconReducer from '../features/Global/iconSlice';
11 | import createMenuReducer from '../features/Global/menuSlice';
12 | import modalReducer from '../features/Global/modalSlice';
13 | import { driveApiSlice } from './api/driveApiSlice';
14 | import fileSizeReducer from '../features/Global/fileSizeSlice';
15 | import folderReducer from '../features/folder/folderSlice';
16 | import { authApiSlice } from '../features/auth/authApiSlice';
17 | import sharedFileReducer from '../features/shared/shareFileSlice';
18 | import trashFileReducer from '../features/trash/trashFileSlice'
19 | import favouriteReducer from '../features/favourite/favouriteSlice';
20 |
21 | const persistConfig = {
22 | key: 'root',
23 | version: 1,
24 | storage,
25 | };
26 |
27 | export const store = configureStore({
28 | reducer: {
29 | [driveApiSlice.reducerPath]: driveApiSlice.reducer,
30 | [apiSlice.reducerPath]: apiSlice.reducer,
31 | auth: authReducer,
32 |
33 | folder: persistReducer(persistConfig, folderReducer),
34 |
35 | sideBar: SidebarReducer,
36 | icon: iconReducer,
37 | createMenu: createMenuReducer,
38 | modal: modalReducer,
39 | fileSize: fileSizeReducer,
40 | shared: sharedFileReducer,
41 | trash: trashFileReducer,
42 | favourite: favouriteReducer,
43 |
44 | },
45 | middleware: (getDefaultMiddleware) => getDefaultMiddleware({
46 | serializableCheck: {
47 | ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
48 | },
49 | }).concat([driveApiSlice.middleware, authApiSlice.middleware]),
50 | devTools: true,
51 | });
52 | export const persistor = persistStore(store);
53 |
--------------------------------------------------------------------------------
/src/components/ForgotLayout.jsx:
--------------------------------------------------------------------------------
1 | import React,{useState} from 'react';
2 | import { Link } from 'react-router-dom';
3 | import { Toaster } from 'react-hot-toast';
4 | import TextField from '@mui/material/TextField';
5 | import CircularProgress from '@mui/material/CircularProgress';
6 |
7 | // import warning from '../assets/warning.svg';
8 | import warning from '../assets/warning.svg';
9 |
10 |
11 | function ForgotLayout({handleChange,heading,paragraph,handleSubmit,value,label,isLoading}) {
12 | return (
13 |
14 |
18 |
19 |
20 |
21 |

22 |
{heading}
23 |
{ paragraph}
24 |
25 | {
26 | isLoading ? (
) : (
28 |
29 | )
30 | }
31 |
32 |
Back to login
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | );
41 | }
42 |
43 | export default ForgotLayout;
44 |
--------------------------------------------------------------------------------
/src/data/DummyData.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/jsx-filename-extension */
2 | /* eslint-disable import/prefer-default-export */
3 | import React from 'react';
4 | import { FiHardDrive, FiFileText, FiCreditCard } from 'react-icons/fi';
5 | import { RiTimerLine } from 'react-icons/ri';
6 | import { AiOutlineStar } from 'react-icons/ai';
7 | import { BsTrash, BsCurrencyDollar, BsShield,BsPersonCircle } from 'react-icons/bs';
8 | import avatar from '../assets/avatar.svg';
9 | import avatar2 from '../assets/avatar2.jpg';
10 | import avatar3 from '../assets/avatar3.png';
11 | import avatar4 from '../assets/avatar4.jpg';
12 |
13 | export const links = [
14 | {
15 | title: 'My Drive',
16 | icon: ,
17 | link: '/dashboard/v1/myDrive',
18 |
19 | },
20 | {
21 | title: 'Files',
22 | icon: ,
23 | link: '/dashboard/v1/all-files',
24 | },
25 | {
26 | title: 'Shared with me',
27 | icon: ,
28 | link: '/dashboard/v1/shared-with-me',
29 | },
30 | {
31 | title: 'Favourite',
32 | icon: ,
33 | link: '/dashboard/v1/favorite',
34 | },
35 | {
36 | title: 'Trash',
37 | icon: ,
38 | link: '/dashboard/v1/trash',
39 | },
40 | ];
41 |
42 | export const chatData = [
43 | {
44 | image:
45 | avatar2,
46 | message: 'Roman Joined the Team!',
47 | desc: 'Congratulate him',
48 | time: '9:08 AM',
49 | },
50 | {
51 | image:
52 | avatar3,
53 | message: 'New message received',
54 | desc: 'Salma sent you new message',
55 | time: '11:56 AM',
56 | },
57 | {
58 | image:
59 | avatar4,
60 | message: 'New Payment received',
61 | desc: 'Check your earnings',
62 | time: '4:39 AM',
63 | },
64 | {
65 | image:
66 | avatar,
67 | message: 'Jolly completed tasks',
68 | desc: 'Assign her new tasks',
69 | time: '1:12 AM',
70 | },
71 | ];
72 |
73 | export const userProfileData = [
74 | {
75 | icon: ,
76 | title: 'My Profile',
77 | desc: 'Account Settings',
78 | iconColor: '#03C9D7',
79 | iconBg: '#E5FAFB',
80 | },
81 | ];
82 |
--------------------------------------------------------------------------------
/src/pages/DashBoard/Dashboard.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useSelector } from 'react-redux';
3 | import { Outlet } from 'react-router-dom';
4 | import { FiSettings } from 'react-icons/fi';
5 | import { TooltipComponent } from '@syncfusion/ej2-react-popups';
6 | import {
7 |
8 | DashNavBar,
9 | SideBar,
10 | FolderTree,
11 | } from '../../components/index';
12 | import './DashBoard.css';
13 |
14 | function Dashboard() {
15 | const activeMenu = useSelector((state) => state.sideBar.menu);
16 | return (
17 |
18 |
19 |
20 |
21 |
29 |
30 |
31 |
32 | {activeMenu ? (
33 |
38 |
39 |
40 | ) : (
41 |
45 |
46 |
47 | )}
48 |
53 |
59 |
60 | {/* */}
61 |
62 |
63 |
64 |
65 |
66 | );
67 | }
68 |
69 | export default Dashboard;
70 |
--------------------------------------------------------------------------------
/src/pages/ForgotPassword.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import Toaster, { toast } from 'react-hot-toast';
3 | import { useNavigate } from 'react-router-dom';
4 | import TextField from '@mui/material/TextField';
5 | import warning from '../assets/warning.svg';
6 | import ForgotLayout from '../components/ForgotLayout';
7 | import { useForgotOtpMutation } from '../features/auth/authApiSlice';
8 |
9 | function ForgotPassword() {
10 | const [email, setEmail] = useState('');
11 | const navigate = useNavigate();
12 | const [forgotOtp, { isLoading }] = useForgotOtpMutation();
13 | const handleChange = (e) => {
14 | setEmail(e.target.value);
15 | };
16 | const handleSubmit = async () => {
17 | try {
18 | await forgotOtp({ email }).unwrap();
19 | navigate('/otp',{state:{email}});
20 | } catch (error) {
21 | toast.error(error.data.message);
22 | }
23 | };
24 | return (
25 | //
26 | //
27 | //
28 | //
29 | //

30 | //
Forgot Password
31 | //
Enter your email and we'll send you a otp
32 | //
setOtp(e.target.value)} />
33 | //
34 | // Back to login
35 | //
36 |
37 | //
38 |
39 | //
40 |
41 | //
42 |
51 | );
52 | }
53 |
54 | export default ForgotPassword;
55 |
--------------------------------------------------------------------------------
/src/components/Menu/CreateMenu.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/no-static-element-interactions */
2 | /* eslint-disable jsx-a11y/click-events-have-key-events */
3 | import React, { useState } from 'react';
4 | import { AiOutlineFolderAdd, AiOutlineFileAdd } from 'react-icons/ai';
5 | import { useDispatch } from 'react-redux';
6 | import { openFolderCreation,openFileCreation } from '../../features/Global/modalSlice';
7 |
8 | function CreateMenu() {
9 | const [file, setFile] = useState(null);
10 | const handleSubmit = () => {
11 | console.log(file);
12 | const reader = new FileReader();
13 | console.log(reader);
14 | reader.onload = () => {
15 | const fileContents = reader.result;
16 | console.log(fileContents);
17 | const typedArray = new Uint8Array(fileContents);
18 | console.log(typedArray);
19 |
20 | }
21 | reader.readAsText(file);
22 | };
23 | const handleFileChange = (event) => {
24 |
25 | if (event.target.files.length > 0) {
26 |
27 | setFile(event.target.files[0]);
28 | }
29 | };
30 | const dispatch = useDispatch();
31 | const handleCreateFolder = () => {
32 | dispatch(openFolderCreation());
33 | };
34 | const handleFileCreation = () => {
35 | dispatch(openFileCreation())
36 | }
37 | return (
38 |
39 |
40 |
44 |
45 |
46 | New Folder
47 |
48 |
49 |
50 |
51 | {/*
*/}
52 | {/*
*/}
53 |
Upload file
54 |
55 |
56 |
57 |
58 | );
59 | }
60 |
61 | export default CreateMenu;
62 |
--------------------------------------------------------------------------------
/src/components/Modal/FolderModal.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React,{ useEffect, useRef } from 'react'
3 | import { useDispatch, useSelector } from 'react-redux'
4 | import { closeFolderCreation } from '../../features/Global/modalSlice'
5 | import { useCreateFolderMutation } from '../../features/folder/folderApiSlice'
6 | import { updateChildFolders } from '../../features/folder/folderSlice'
7 | import {setCreateMenu} from '../../features/Global/menuSlice'
8 | // import {useFolder} from '../../hooks/useFolder'
9 |
10 |
11 | import Modal from './Modal'
12 | import PreLoader from '../PreLoader/PreLoader'
13 |
14 | function FolderModal() {
15 | const inputRef=useRef()
16 | const dispatch = useDispatch()
17 | const user = useSelector(state => state.auth.token)
18 | const folderCreationOverlay = useSelector((state) => state.modal.folderCreationModal)
19 | const folder=useSelector((state)=>state.folder)
20 | const [createFolder,{isLoading}]=useCreateFolderMutation()
21 | const handleSubmit = async () => {
22 | let res= await createFolder({
23 | "folderName":inputRef.current.value,
24 | "userId":user,
25 | "folderId": folder.folderId,
26 | "level":folder.level
27 |
28 | }).unwrap()
29 | dispatch(updateChildFolders(res))
30 | dispatch(closeFolderCreation())
31 | dispatch(setCreateMenu(false))
32 | }
33 | useEffect(() => {
34 | inputRef.current.focus()
35 | inputRef.current.select()
36 |
37 | },[folderCreationOverlay])
38 | const content = isLoading ? (
39 |
40 | ):(
41 | {dispatch(closeFolderCreation())}}>
42 |
43 |
New Folder
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | Modal>
53 | )
54 | return content
55 | }
56 |
57 | export default FolderModal
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import { useDispatch } from 'react-redux';
3 | import Cookies from 'universal-cookie';
4 | import Routers from './routers/Routers';
5 | import { Footer } from './components/index';
6 | import { setCredentials } from './features/auth/authSlice';
7 | import FolderModal from './components/Modal/FolderModal';
8 | import FileModal from './components/Modal/FileModal';
9 | import { useGetRefreshTokenMutation,useGetUserDetailsMutation } from './features/auth/authApiSlice';
10 | import { Toaster } from 'react-hot-toast';
11 | // import ShareModal from './components/Modal/ShareModal';
12 | // import {useFolder} from './hooks/useFolder'
13 |
14 | function App() {
15 | // const folderState = useFolder()
16 | // console.log(folderState);
17 | const [isLoading, setLoading] = useState(true);
18 | const dispatch = useDispatch();
19 | const cookie = new Cookies();
20 | const userToken = localStorage.getItem('refreshToken');
21 | const [getRefreshToken] = useGetRefreshTokenMutation();
22 | const [getUserDetails] = useGetUserDetailsMutation();
23 |
24 | function someRequest() { // Simulates a request; makes a "promise" that'll run for 2.5 seconds
25 | // eslint-disable-next-line no-promise-executor-return
26 | return new Promise((resolve) => setTimeout(() => resolve(), 100));
27 | }
28 |
29 | useEffect(() => {
30 | someRequest().then(() => {
31 | const loaderElement = document.querySelector('.loader-container');
32 | if (loaderElement) {
33 | loaderElement.remove();
34 | setLoading(!isLoading);
35 | }
36 | });
37 | dispatch(setCredentials({ token: userToken }));
38 | }, []);
39 | async function getToken() {
40 | try {
41 | const refreshToken = await getRefreshToken().unwrap()
42 | const getUser=await getUserDetails().unwrap()
43 |
44 | localStorage.setItem('refreshToken', refreshToken.refreshToken);
45 | dispatch(setCredentials({ token: refreshToken,user:getUser }));
46 |
47 |
48 | } catch (error) {
49 | localStorage.removeItem('refreshToken');
50 | localStorage.removeItem('accessToken');
51 | }
52 | }
53 | useEffect(() => {
54 | getToken()
55 | },[])
56 | setInterval(() => {
57 | getToken();
58 | }, 60000 * 4);
59 |
60 | if (isLoading) { //
61 | return null;
62 | }
63 | return (
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | );
72 | }
73 |
74 | export default App;
75 |
--------------------------------------------------------------------------------
/src/features/folder/folderSlice.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-underscore-dangle */
2 | /* eslint-disable no-param-reassign */
3 | import { createSlice } from '@reduxjs/toolkit';
4 |
5 | const folderSlice = createSlice({
6 | name: 'folder',
7 | initialState: {
8 | folderId: null,
9 | folder: null,
10 | childFolders: [],
11 | childFiles: [],
12 | level: 1,
13 | path: [{ path: 'MyDrive', id: 'myDrive' }],
14 |
15 | },
16 | reducers: {
17 | selectFolder: (state, action) => {
18 | state.folderId = action.folderId;
19 | state.folder = action.folder;
20 | },
21 | updateFolder: (state, action) => {
22 | state.folder = action.payload.folderName;
23 | state.folderId = action.payload._id;
24 | state.childFolders = [];
25 | state.level = action.payload.folderLevel + 1;
26 | },
27 | updateChildFolders: (state, action) => {
28 | state.childFolders.push(action.payload);
29 | },
30 | insertChildFolders: (state, action) => {
31 | state.childFolders = [...action.payload.folders];
32 | state.childFiles = [...action.payload.files];
33 | },
34 | insertPath: (state, action) => {
35 | const data = state.path.find((path) => path.id === action.payload._id);
36 | if (!data) {
37 | state.path.push({ path: action.payload.folderName, id: action.payload._id });
38 | }
39 | },
40 | updatePath: (state, action) => {
41 | const index = state.path.findIndex((path) => path.id === action.payload.id);
42 | if (index === state.path.length - 1) return;
43 | const newPaths = state.path.slice(0, index + 1);
44 | if (index === 0) {
45 | // state
46 | state.folder = null;
47 | state.folderId = null;
48 | state.level = 1;
49 | } else {
50 | state.folder = action.payload.path;
51 | state.folderId = action.payload.id;
52 | }
53 | state.path = newPaths;
54 |
55 | state.childFolders = [];
56 | },
57 | pushFile: (state, action) => {
58 | state.childFiles = [...state.childFiles, action.payload];
59 | },
60 | removeFile: (state, action) => {
61 | const index = state.childFiles.findIndex((file) => file._id === action.payload);
62 | state.childFiles.splice(index, 1);
63 |
64 | }
65 |
66 | // default: (state) => state,
67 | },
68 | });
69 | export const {
70 | selectFolder, updateFolder, updateChildFolders,
71 | insertChildFolders, updatePath, insertPath, pushFile,
72 | removeFile
73 | } = folderSlice.actions;
74 | export default folderSlice.reducer;
75 |
--------------------------------------------------------------------------------
/src/features/auth/authApiSlice.js:
--------------------------------------------------------------------------------
1 | import { apiSlice } from '../../app/api/apiSlice';
2 |
3 | export const authApiSlice = apiSlice.injectEndpoints({
4 | endpoints: (builder) => ({
5 | signup: builder.mutation({
6 | query: (credentials) => ({
7 | url: '/signup',
8 | method: 'POST',
9 | body: { ...credentials },
10 | }),
11 | }),
12 | login: builder.mutation({
13 | query: (credentials) => ({
14 | url: '/login',
15 | method: 'POST',
16 | body: { ...credentials },
17 | }),
18 | }),
19 | googleSignUP: builder.mutation({
20 | query: (credentials) => ({
21 | url: '/google-signup',
22 | method: 'POST',
23 | body: { credentials },
24 | }),
25 | }),
26 | getRefreshToken: builder.mutation({
27 | query: () => ({
28 | url: '/refresh-token',
29 | method: 'POST',
30 | }),
31 | }),
32 | getUserDetails: builder.mutation({
33 | query: () => ({
34 | url: 'user/get-user',
35 | method: 'GET',
36 | }),
37 | }),
38 | sendOtp: builder.mutation({
39 | query: (credentials) => ({
40 | url: 'user/send-otp',
41 | method: 'POST',
42 | body: credentials,
43 | }),
44 | }),
45 | submitOtp: builder.mutation({
46 | query: (credentials) => ({
47 | url: 'user/submit-otp',
48 | method: 'POST',
49 | body: credentials,
50 | }),
51 | }),
52 | changePassword: builder.mutation({
53 | query: (credentials) => ({
54 | url: 'user/change-password',
55 | method: 'POST',
56 | body: credentials,
57 | }),
58 | }),
59 | submitChangeOtp: builder.mutation({
60 | query: (credentials) => ({
61 | url: 'user/otp-password',
62 | method: 'POST',
63 | body: credentials,
64 | }),
65 | }),
66 | forgotOtp: builder.mutation({
67 | query: (credentials) => ({
68 | url: 'user/forgot-password',
69 | method: 'POST',
70 | body: credentials,
71 | }),
72 | }),
73 | newPasswordSet: builder.mutation({
74 | query: (credentials) => ({
75 | url: 'user/new-password',
76 | method: 'POST',
77 | body: credentials,
78 | }),
79 | }),
80 | }),
81 | });
82 |
83 | export const {
84 | useLoginMutation, useSignupMutation, useGetRefreshTokenMutation,
85 | useGoogleSignUPMutation, useGetUserDetailsMutation, useSendOtpMutation, useSubmitOtpMutation,
86 | useChangePasswordMutation, useForgotOtpMutation, useNewPasswordSetMutation,
87 | useSubmitChangeOtpMutation
88 | } = authApiSlice;
89 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "sync":"aws s3 sync ./dist/ s3://cloud-box.tech/ ",
10 | "invalidate":"aws cloudfront create-invalidation --distribution-id E12LYV72UDJK8I --paths /*",
11 | "preview": "vite preview"
12 | },
13 | "dependencies": {
14 | "@aws-sdk/client-s3": "^3.245.0",
15 | "@emotion/react": "^11.10.5",
16 | "@emotion/styled": "^11.10.5",
17 | "@headlessui/react": "^1.7.4",
18 | "@heroicons/react": "^2.0.13",
19 | "@mui/icons-material": "^5.11.0",
20 | "@mui/material": "^5.11.4",
21 | "@mui/styled-engine-sc": "^5.11.0",
22 | "@reduxjs/toolkit": "^1.9.1",
23 | "@syncfusion/ej2": "^19.4.48",
24 | "@syncfusion/ej2-react-buttons": "^20.3.58",
25 | "@syncfusion/ej2-react-calendars": "^19.4.48",
26 | "@syncfusion/ej2-react-charts": "^19.4.50",
27 | "@syncfusion/ej2-react-dropdowns": "^19.4.52",
28 | "@syncfusion/ej2-react-grids": "^19.4.50",
29 | "@syncfusion/ej2-react-inputs": "^19.4.52",
30 | "@syncfusion/ej2-react-kanban": "^19.4.48",
31 | "@syncfusion/ej2-react-popups": "^19.4.52",
32 | "@syncfusion/ej2-react-richtexteditor": "^19.4.50",
33 | "@syncfusion/ej2-react-schedule": "^19.4.50",
34 | "aws-sdk": "^2.1295.0",
35 | "buffer": "^6.0.3",
36 | "crypto-js": "^4.1.1",
37 | "docx": "^7.8.1",
38 | "framer-motion": "^7.6.19",
39 | "html2canvas": "^1.4.1",
40 | "pdf-image": "^2.0.0",
41 | "pdfjs-dist": "^3.1.81",
42 | "prop-types": "^15.8.1",
43 | "react": "^18.2.0",
44 | "react-dom": "^18.2.0",
45 | "react-drag-drop-files": "^2.3.8",
46 | "react-hot-toast": "^2.4.0",
47 | "react-icons": "^4.3.1",
48 | "react-redux": "^8.0.5",
49 | "react-router-dom": "^6.4.3",
50 | "react-spinners": "^0.13.7",
51 | "redux-persist": "^6.0.0",
52 | "styled-components": "^5.3.6",
53 | "universal-cookie": "^4.0.4",
54 | "vite-plugin-ngmi-polyfill": "^0.0.2",
55 | "xlsx": "^0.18.5"
56 | },
57 | "devDependencies": {
58 | "@types/react": "^18.0.24",
59 | "@types/react-dom": "^18.0.8",
60 | "@vitejs/plugin-react": "^2.2.0",
61 | "autoprefixer": "^10.4.13",
62 | "eslint": "^8.29.0",
63 | "eslint-config-airbnb": "^19.0.4",
64 | "eslint-config-prettier": "^8.5.0",
65 | "eslint-plugin-import": "^2.26.0",
66 | "eslint-plugin-jsx-a11y": "^6.6.1",
67 | "eslint-plugin-prettier": "^4.2.1",
68 | "eslint-plugin-react": "^7.31.11",
69 | "eslint-plugin-react-hooks": "^4.6.0",
70 | "postcss": "^8.4.19",
71 | "prettier": "^2.8.0",
72 | "tailwindcss": "^3.2.4",
73 | "vite": "^3.2.5"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/pages/ChangePasswordPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import { Link,useLocation ,useNavigate} from 'react-router-dom';
3 | import { Toaster,toast } from 'react-hot-toast';
4 | import TextField from '@mui/material/TextField';
5 | import CircularProgress from '@mui/material/CircularProgress';
6 | import warning from '../assets/warning.svg';
7 | import { useNewPasswordSetMutation } from '../features/auth/authApiSlice';
8 |
9 |
10 | function ChangePasswordPage() {
11 | const [newPassword, setNewPassword] = useState("");
12 | const [reNewPasswords, setReNewPassword] = useState("");
13 | const location = useLocation()
14 | const navigate=useNavigate()
15 | const [newPasswordSet]=useNewPasswordSetMutation()
16 |
17 | const handleSubmit = async() => {
18 | if (newPassword !== reNewPasswords) return toast.error("Passwords not match")
19 | try {
20 | await newPasswordSet({ email: location.state.email, password: newPassword, otp: location.state.otp })
21 | toast.success("Password Changed");
22 | navigate("/login");
23 | } catch (error) {
24 | toast.error(error.message);
25 |
26 | }
27 | }
28 | return (
29 |
30 |
34 |
35 |
36 |
37 |

38 |
Change Password
39 |
setNewPassword(e.target.value)} />
40 | setReNewPassword(e.target.value)} />
41 |
42 | {/* {
43 | isLoading ? () : ( */}
45 |
46 | {/* // )
47 | // } */}
48 |
49 | Back to login
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | )
58 | }
59 |
60 | export default ChangePasswordPage
--------------------------------------------------------------------------------
/src/components/Modal/BasicModal.jsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect, useState } from 'react';
2 | import { useSelector, useDispatch } from 'react-redux';
3 | import Box from '@mui/material/Box';
4 | import Button from '@mui/material/Button';
5 | import Typography from '@mui/material/Typography';
6 | import Modal from '@mui/material/Modal';
7 | import { closeFolderShare } from '../../features/Global/modalSlice';
8 | import { useIsUserShareFolderMutation } from '../../features/folder/folderApiSlice';
9 |
10 | const style = {
11 | position: 'absolute',
12 | top: '50%',
13 | left: '50%',
14 | transform: 'translate(-50%, -50%)',
15 | width: 400,
16 | bgcolor: 'background.paper',
17 | border: '2px solid #000',
18 | boxShadow: 24,
19 | p: 4,
20 | };
21 |
22 | export default function BasicModal() {
23 | const dispatch = useDispatch();
24 | const [error, setError] = useState('');
25 | const folderShare = useSelector((state) => state.modal.shareFolder);
26 | const modalId = useSelector((state) => state.modal.shareFolderId);
27 | const [isUserShareFolder, { isLoading }] = useIsUserShareFolderMutation();
28 | const inputRef = useRef();
29 | // const [open, setOpen] = React.useState(false);
30 | const handleClose = () => dispatch(closeFolderShare());
31 | useEffect(() => {
32 | // inputRef.current.focus();
33 | // inputRef.current.select();
34 | }, [folderShare]);
35 |
36 | const handleSubmit = async () => {
37 |
38 | try {
39 | console.log(modalId);
40 | const result = await isUserShareFolder({
41 | email: inputRef.current.value, folderId: modalId,
42 | }).unwrap();
43 | console.log(result);
44 | if (result) {
45 | setError("");
46 | dispatch(closeFolderShare())
47 | }
48 | } catch (error) {
49 | setError('user not exist');
50 | }
51 | };
52 | return (
53 |
54 |
60 |
61 |
62 |
63 |
Add Users
64 |
65 |
{error }
66 |
67 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | );
85 | }
86 |
--------------------------------------------------------------------------------
/src/components/Menu/RightClick.jsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { styled, alpha } from '@mui/material/styles';
3 | import Button from '@mui/material/Button';
4 | import Menu from '@mui/material/Menu';
5 | import MenuItem from '@mui/material/MenuItem';
6 | import EditIcon from '@mui/icons-material/Edit';
7 | import Divider from '@mui/material/Divider';
8 | import ArchiveIcon from '@mui/icons-material/Archive';
9 | import FileCopyIcon from '@mui/icons-material/FileCopy';
10 | import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
11 | import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
12 |
13 | const StyledMenu = styled((props) => (
14 |
26 | ))(({ theme }) => ({
27 | '& .MuiPaper-root': {
28 | borderRadius: 6,
29 | marginTop: theme.spacing(1),
30 | minWidth: 180,
31 | color:
32 | theme.palette.mode === 'light' ? 'rgb(55, 65, 81)' : theme.palette.grey[300],
33 | boxShadow:
34 | 'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px',
35 | '& .MuiMenu-list': {
36 | padding: '4px 0',
37 | },
38 | '& .MuiMenuItem-root': {
39 | '& .MuiSvgIcon-root': {
40 | fontSize: 18,
41 | color: theme.palette.text.secondary,
42 | marginRight: theme.spacing(1.5),
43 | },
44 | '&:active': {
45 | backgroundColor: alpha(
46 | theme.palette.primary.main,
47 | theme.palette.action.selectedOpacity,
48 | ),
49 | },
50 | },
51 | },
52 | }));
53 |
54 | function CustomizedMenus() {
55 | const [anchorEl, setAnchorEl] = React.useState(null);
56 | const open = Boolean(anchorEl);
57 | const handleClick = (event) => {
58 | setAnchorEl(event.currentTarget);
59 | };
60 | const handleClose = () => {
61 | setAnchorEl(null);
62 | };
63 |
64 | return (
65 |
66 |
93 |
94 | );
95 | }
96 |
97 | export default CustomizedMenus
--------------------------------------------------------------------------------
/src/pages/MyDrive.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-plusplus */
2 | /* eslint-disable no-underscore-dangle */
3 | import React, { useEffect } from 'react';
4 | import { useParams } from 'react-router-dom';
5 | import { useDispatch, useSelector } from 'react-redux';
6 | import { Folder, FileCard } from '../components/index';
7 | import { useGetAllFoldersAndFilesMutation } from '../features/folder/folderApiSlice';
8 | import { insertChildFolders, updateFolder, pushFile } from '../features/folder/folderSlice';
9 | import PreLoader from '../components/PreLoader/PreLoader';
10 | import { Toaster } from 'react-hot-toast';
11 |
12 | function MyDrive() {
13 | const folder = useSelector((state) => state.folder);
14 | const dispatch = useDispatch();
15 | const { id } = useParams();
16 |
17 | const [getAllFoldersAndFiles, { isLoading }] = useGetAllFoldersAndFilesMutation();
18 | const user = localStorage.getItem('refreshToken');
19 | async function fetchFolders() {
20 | const contents = await getAllFoldersAndFiles({
21 | user,
22 | folderId: folder.folderId,
23 | level: folder.level,
24 | }).unwrap();
25 | dispatch(insertChildFolders(contents));
26 | }
27 | useEffect(() => {
28 | if (id) {
29 | // let subFolder = folder.childFolders.filter((val) => id === val._id);
30 | for (let i = 0; i < folder.childFolders.length; i++) {
31 | if (id === folder.childFolders[i]._id) {
32 | dispatch(updateFolder(folder.childFolders[i]));
33 | break;
34 | }
35 | }
36 | }
37 | }, [id]);
38 | useEffect(() => {
39 | fetchFolders();
40 | }, [folder.folderId]);
41 |
42 | const content = isLoading ? (
43 |
44 | ) : (
45 |
46 |
47 |
48 |
Folders
49 |
50 | {/* */}
51 | {folder.childFolders?.map((value) => (
52 | // eslint-disable-next-line no-underscore-dangle
53 |
54 | ))}
55 |
56 |
57 |
58 |
59 |
Documents
60 |
61 | {/*
![]()
*/}
62 |
63 |
64 | {
65 | folder.childFiles?.map((value) => (
66 | // eslint-disable-next-line no-underscore-dangle
67 |
68 |
69 | ))
70 | }
71 |
72 |
73 |
74 |
75 |
76 |
80 |
81 | );
82 | return content;
83 | }
84 |
85 | export default MyDrive;
86 |
--------------------------------------------------------------------------------
/src/components/Sidebar/SideBar.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/self-closing-comp */
2 | import React from 'react';
3 | import { Link } from 'react-router-dom';
4 | import { useDispatch, useSelector } from 'react-redux';
5 | // import { SiShopware } from 'react-icons/si';
6 | import { MdOutlineCancel } from 'react-icons/md';
7 | import { BsCloud } from 'react-icons/bs';
8 | import { TooltipComponent } from '@syncfusion/ej2-react-popups';
9 | import { setSidebar } from '../../features/Global/sidebarSlice';
10 | import { setCreateMenu } from '../../features/Global/menuSlice';
11 | import logText from '../../assets/logoText.png';
12 | import CreateButton from './SidebarElements/CreateButton';
13 | import DashboardILinks from './SidebarElements/DashboardILinks';
14 | import StorageSize from './SidebarElements/StorageSize';
15 | import BuyNow from './SidebarElements/BuyNow';
16 | import CreateMenu from '../Menu/CreateMenu';
17 |
18 | function SideBar() {
19 | const activeMenu = useSelector((state) => state.sideBar.menu);
20 | const createMenu = useSelector((state) => state.createMenu.createMenu);
21 |
22 | const dispatch = useDispatch();
23 |
24 | return (
25 |
26 | {activeMenu && (
27 | <>
28 |
29 | {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
30 |
{ }}
32 | className="items-center ml-3 mt-4 flex text-xl font-extrabold
33 | tracking-tight dark:text-white text-slate-900"
34 | >
35 |

36 | {' '}
37 |
38 | Cloud
39 | BOX
40 |
41 |
42 |
46 |
57 | {createMenu && }
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
Storage
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | >
84 | )}
85 |
86 | );
87 | }
88 |
89 | export default SideBar;
90 |
--------------------------------------------------------------------------------
/src/components/Navbar.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | import React, { Fragment } from 'react';
3 | import { Link } from 'react-router-dom';
4 | import { Disclosure } from '@headlessui/react';
5 | import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline';
6 | import v1443 from '../assets/v1443.png';
7 |
8 | // eslint-disable-next-line react/prop-types
9 | export default function Example({ data }) {
10 | return (
11 | // eslint-disable-next-line react/react-in-jsx-scope, react/jsx-no-comment-textnodes
12 |
13 |
14 |
15 | {({ open }) => (
16 | // eslint-disable-next-line react/react-in-jsx-scope
17 | <>
18 |
19 |
20 |
21 | {/* Mobile menu button */}
22 |
23 | Open main menu
24 | {open ? (
25 |
26 | ) : (
27 |
28 | )}
29 |
30 |
31 |
32 |
33 |

38 |

43 |
44 |
45 |
46 | {data.auth}
47 | GoTo Box
48 | {/*
*/}
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | Sign in
59 | GoTo Box
60 |
61 |
62 | >
63 | )}
64 |
65 |
66 |
67 | );
68 | }
69 |
--------------------------------------------------------------------------------
/src/components/NaveBar/DashNavBar.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/no-static-element-interactions */
2 | /* eslint-disable jsx-a11y/click-events-have-key-events */
3 | /* eslint-disable react/prop-types */
4 | import React from 'react';
5 | import { useDispatch, useSelector } from 'react-redux';
6 | import { AiOutlineMenu } from 'react-icons/ai';
7 | import { RiNotification3Line } from 'react-icons/ri';
8 | import { MdKeyboardArrowDown } from 'react-icons/md';
9 | import { TooltipComponent } from '@syncfusion/ej2-react-popups';
10 | import { setSidebar } from '../../features/Global/sidebarSlice';
11 | import { setNotification, setUserProfile } from '../../features/Global/iconSlice';
12 | import avatar from '../../assets/avatar.svg';
13 | import { UserProfile, Notification } from '../index';
14 | import './NavBar.css';
15 | import { setCreateMenu } from '../../features/Global/menuSlice';
16 |
17 | export function NavButton({
18 | title, customFun, color, icon, dotColor,
19 | }) {
20 | return (
21 |
22 |
27 |
28 | );
29 | }
30 |
31 | function DashNavBar() {
32 | const activeMenu = useSelector((state) => state.sideBar.menu);
33 | const notification = useSelector((state) => state.icon.notification);
34 | const userProfile = useSelector((state) => state.icon.userProfile);
35 | const user = useSelector((state) => state.auth.user);
36 |
37 | // const user = useSelector((state) => state.auth.user);
38 |
39 | const dispatch = useDispatch();
40 | return (
41 |
42 |
dispatch(setSidebar(!activeMenu, dispatch(setCreateMenu(false))))}
45 | color="#9fa2f6"
46 | icon={}
47 | />
48 |
49 |
dispatch(setNotification(!notification))}
52 | color="#9fa2f6"
53 | icon={}
54 | dotColor="#03C9D7"
55 | />
56 |
57 | dispatch(setUserProfile(!userProfile))}
60 | >
61 | {
62 | user?.profile ? (

) : (
63 |

)
64 | }
65 |
66 |
67 | Hi,
68 | {' '}
69 | {/* { user} */}
70 |
71 |
72 |
73 |
74 | {notification && }
75 | {userProfile && }
76 |
77 |
78 | );
79 | }
80 |
81 | export default DashNavBar;
82 |
--------------------------------------------------------------------------------
/src/components/HomePage.jsx:
--------------------------------------------------------------------------------
1 | import React, { Fragment } from 'react';
2 | import {Link, useNavigate } from 'react-router-dom';
3 | import { motion } from 'framer-motion';
4 | import unnamed from '../assets/unnamed.jpg';
5 | import logoText from '../assets/logoText.png';
6 | import cloud from '../assets/cloud.png';
7 |
8 | function HomePage() {
9 | const navigate = useNavigate();
10 | const handleNavigate = () => {
11 | navigate('/dashboard/v1/myDrive')
12 | }
13 | return (
14 | <>
15 |
16 |
17 |
18 |
19 | Easy and secure access to your content
20 |
21 |
22 | Store, share, and collaborate on files and folders from your
23 | mobile device, tablet, or computer
24 |
25 |
26 |
33 |
34 |
41 |
42 |
43 |
44 |
Don`t have an account?
45 |
46 | Sign up at no cost
47 |
48 |
49 |
50 |
51 |
52 |
53 | {/* eslint-disable-next-line jsx-a11y/alt-text */}
54 |

55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |

63 |
Cloud Box
64 |
72 |
73 | {/*
*/}
74 |

75 | {/*
*/}
76 |
77 |
78 | >
79 | );
80 | }
81 |
82 | export default HomePage;
83 |
--------------------------------------------------------------------------------
/src/components/Modal/FileModal.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/button-has-type */
2 | import React, { useState } from 'react';
3 | import { useDispatch, useSelector } from 'react-redux';
4 | import { FileUploader } from 'react-drag-drop-files';
5 | import pdfjsLib, { getDocument } from 'pdfjs-dist';
6 | import CryptoJS from 'crypto-js';
7 |
8 | import ClipLoader from 'react-spinners/ClipLoader';
9 | import Modal from './Modal';
10 | import { closeFileCreation } from '../../features/Global/modalSlice';
11 | import { useUploadFileMutation } from '../../features/file/fileApiSlice';
12 | import { createPreviewImage } from '../../features/file/previewImage';
13 | import { pushFile } from '../../features/folder/folderSlice';
14 | import { uploadFile } from '../../features/aws/s3Bucket';
15 |
16 | function FileModal() {
17 | const dispatch = useDispatch();
18 | const fileOverLay = useSelector((state) => state.modal.fileCreationModal);
19 | const [file, setFile] = useState(null);
20 | const [uploadedFile, { isLoading }] = useUploadFileMutation();
21 | const folder = useSelector((state) => state.folder);
22 | function encryptFile(file) {
23 | const encrypted = CryptoJS.AES.encrypt(file, '12345')
24 | return encrypted;
25 | }
26 | const handleChange = (event) => {
27 | setFile(event);
28 | };
29 | const handleModalCancel = () => {
30 | dispatch(closeFileCreation());
31 | setFile(null);
32 | };
33 |
34 | const handleUpload = async (e) => {
35 | document.getElementById('root').style.pointerEvents = 'none';
36 | const previewImage = await createPreviewImage(file, e);
37 | const reader = new FileReader();
38 | reader.onload = async (e) => {
39 | const fileContents = reader.result;
40 | const awsRes = await uploadFile(file, fileContents);
41 | // const typedArray = new Uint8Array(fileContents);
42 | // console.log(typedArray);
43 | // let enc = encryptFile(fileContents);
44 | // enc=JSON.stringify(enc)
45 | // console.log(enc);
46 | // const hash = await window.crypto.subtle.digest('SHA-256', typedArray);
47 |
48 | // const fileHash = Array.from(new Uint8Array(hash)).map((b) => b.toString(16).padStart(2, '0')).join('');
49 | const r = await uploadedFile({
50 | folderId: folder.folderId,
51 | level: folder.level,
52 | fileName: file.name,
53 | fileContents: awsRes,
54 | previewImage,
55 | fileSize: file.size,
56 | fileType: file.type,
57 | }).unwrap();
58 | setFile(null);
59 | dispatch(pushFile(r));
60 | dispatch(closeFileCreation());
61 | document.getElementById('root').style.pointerEvents = '';
62 | };
63 |
64 | reader.readAsArrayBuffer(file);
65 | };
66 | return (
67 | dispatch(closeFileCreation())}>
68 |
69 |
70 |
71 |
72 |
{file ? `File name: ${file.name}` : 'Upload or Drop here'}
73 |
74 |
75 |
76 | {/*
*/}
77 |
78 |
79 | {
80 | isLoading ? :
81 | }
82 |
83 |
84 | {/*
{file ? `File name: ${file[0].name}` : 'no files uploaded yet'}
*/}
85 |
86 |
87 |
88 | );
89 | }
90 |
91 | export default FileModal;
92 |
--------------------------------------------------------------------------------
/src/components/UserProfile/UserProfile.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useSelector, useDispatch } from 'react-redux';
3 | import { useNavigate } from 'react-router-dom';
4 | import { BsPersonX } from 'react-icons/bs';
5 | import { userProfileData } from '../../data/DummyData';
6 | import avatar from '../../assets/avatar.svg';
7 | import { logOut } from '../../features/auth/authSlice';
8 | import { setUserProfile } from '../../features/Global/iconSlice';
9 |
10 | function UserProfile() {
11 | const dispatch = useDispatch();
12 | const navigate = useNavigate();
13 | const user = useSelector((state) => state.auth.user);
14 | const userProfile = useSelector((state) => state.icon.userProfile);
15 |
16 |
17 | function handleLogout() {
18 | dispatch(logOut());
19 | localStorage.removeItem('refreshToken');
20 | localStorage.removeItem('accessToken');
21 | navigate('/login');
22 | }
23 | function handleProfile() {
24 | dispatch(setUserProfile(!userProfile));
25 | navigate('/dashboard/v1/user-profile');
26 | }
27 |
28 | return (
29 |
30 |
33 |
34 | {
35 | user.profile ? (
36 |

41 | ) : (
42 |

47 | )
48 | }
49 | {/*

*/}
54 |
55 |
56 | {user.email}
57 |
58 |
59 |
60 |
61 | {userProfileData.map((item, index) => (
62 | // eslint-disable-next-line react/no-array-index-key
63 |
64 |
71 |
72 |
73 |
{item.title}
74 |
75 | {' '}
76 | {item.desc}
77 | {' '}
78 |
79 |
80 |
81 | ))}
82 |
83 |
84 |
91 |
92 |
95 |
96 |
97 | );
98 | }
99 |
100 | export default UserProfile;
101 |
--------------------------------------------------------------------------------
/src/features/file/previewImage.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | import * as PDFJS from 'pdfjs-dist';
3 | import * as XLSX from 'xlsx';
4 | import * as docx from 'docx';
5 | import { Document } from 'docx';
6 | import html2canvas from 'html2canvas';
7 |
8 | /* eslint-disable import/prefer-default-export */
9 |
10 | async function getImageData(element) {
11 | // Render the element to a canvas
12 | const canvas = await html2canvas(element);
13 | // Extract the image data from the canvas
14 | const imageData = canvas.toDataURL();
15 | document.getElementById('xlsxDiv').style.display = 'none';
16 | return imageData;
17 | }
18 |
19 | async function generatePdfPreviewImage(file) {
20 | const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.entry');
21 | // console.log(file);
22 | // // const pdfDocument = await
23 | // console.log(pdfjsLib);
24 | PDFJS.GlobalWorkerOptions.workerSrc = pdfjsWorker;
25 |
26 | return PDFJS.getDocument(file).promise
27 | .then(async (aa) => {
28 | const page = await aa.getPage(1);
29 | const viewPort = page.getViewport({ scale: 1 });
30 | const canvas = document.getElementById('canvas');
31 | const context = canvas.getContext('2d');
32 | canvas.height = viewPort.height;
33 | canvas.width = viewPort.width;
34 | return page.render(
35 | { canvasContext: context, viewport: viewPort },
36 | ).promise.then(() => {
37 | const imageData = canvas.toDataURL();
38 | // document.getElementById('preview12345678').src = imageData;
39 | // console.log(imageData);
40 | return imageData;
41 | });
42 | });
43 | //
44 | }
45 |
46 | export const createPreviewImage = (file) => {
47 | if (file.type.match(/image.*/)) {
48 | return new Promise((resolve) => {
49 | const reader = new FileReader();
50 | reader.onload = (e) => {
51 | const imageData = e.target.result;
52 | resolve(imageData);
53 | };
54 | reader.readAsDataURL(file);
55 | });
56 | } if (file.type === 'application/pdf') {
57 | return new Promise((resolve) => {
58 | const reader = new FileReader();
59 | let previewImage;
60 | reader.onload = async (e) => {
61 | const a = e.target.result;
62 | previewImage = await generatePdfPreviewImage(a);
63 | resolve(previewImage);
64 | };
65 | reader.readAsDataURL(file);
66 | });
67 | } if (file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.type === 'application/vnd.ms-excel') {
68 | return new Promise((resolve) => {
69 | const reader = new FileReader();
70 | reader.onload = async (e) => {
71 | const data = e.target.result;
72 | const workbook = XLSX.read(data, { type: 'binary' });
73 | const sheet = workbook.Sheets[workbook.SheetNames[0]];
74 | const html = XLSX.utils.sheet_to_html(sheet);
75 | const container = document.getElementById('xlsxDiv');
76 | container.innerHTML = html;
77 | const imageData = await getImageData(container);
78 | resolve(imageData);
79 | };
80 | reader.readAsBinaryString(file);
81 | });
82 | } if (file.type === 'application/msword') {
83 | return new Promise((resolve) => {
84 | // const doc = await docx.parse(file);
85 | // const docText = doc.getFullText();
86 | // const pages = docText.split('\n');
87 | // const pageText = pages[0];
88 | // const div = document.getElementById('xlsxDiv');
89 | // div.innerHTML = pageText;
90 | // const canvas = await html2canvas(div);
91 | // const imageData = canvas.toDataURL();
92 | // document.getElementById('xlsxDiv').style.display = 'none';
93 | // resolve(imageData);
94 | const reader = new FileReader();
95 | reader.onload = async (e) => {
96 | const data = e.target.result;
97 | console.log(data);
98 | // const docaa = await docx.parse(data);
99 |
100 | const doc = new docx.Document([data]);
101 | const content = doc.getFullText();
102 | const pages = content.split('\n');
103 | const pageText = pages[0];
104 | const container = document.createElement('xlsxDiv');
105 | container.innerHTML = pageText;
106 | // Extract the image data from the container element
107 | const imageData = getImageData(container);
108 | container.innerHTML = '';
109 | resolve(imageData);
110 | };
111 | reader.readAsArrayBuffer(file);
112 | });
113 | }
114 | };
115 |
--------------------------------------------------------------------------------
/src/components/Folder/Folder.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-underscore-dangle */
2 | /* eslint-disable react/prop-types */
3 | /* eslint-disable react/destructuring-assignment */
4 | /* eslint-disable jsx-a11y/no-static-element-interactions */
5 | /* eslint-disable jsx-a11y/click-events-have-key-events */
6 | import React from 'react';
7 | import { useNavigate } from 'react-router-dom';
8 | import { BsFillFolderFill } from 'react-icons/bs';
9 | import { useDispatch } from 'react-redux';
10 |
11 | import { styled, alpha } from '@mui/material/styles';
12 |
13 | import Menu from '@mui/material/Menu';
14 | import MenuItem from '@mui/material/MenuItem';
15 | import EditIcon from '@mui/icons-material/Edit';
16 | import Divider from '@mui/material/Divider';
17 | import ArchiveIcon from '@mui/icons-material/Archive';
18 | import FileCopyIcon from '@mui/icons-material/FileCopy';
19 | import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
20 | import { insertPath } from '../../features/folder/folderSlice';
21 | import { openFolderShare, setShareFolderModalId } from '../../features/Global/modalSlice';
22 | // import ShareModal from '../Modal/ShareModal';
23 | import BasicModal from '../Modal/BasicModal';
24 |
25 | const StyledMenu = styled((props) => (
26 |
38 | ))(({ theme }) => ({
39 | '& .MuiPaper-root': {
40 | borderRadius: 6,
41 | marginTop: theme.spacing(1),
42 | minWidth: 180,
43 | color:
44 | theme.palette.mode === 'light' ? 'rgb(55, 65, 81)' : theme.palette.grey[300],
45 | boxShadow:
46 | 'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px',
47 | '& .MuiMenu-list': {
48 | padding: '4px 0',
49 | },
50 | '& .MuiMenuItem-root': {
51 | '& .MuiSvgIcon-root': {
52 | fontSize: 18,
53 | color: theme.palette.text.secondary,
54 | marginRight: theme.spacing(1.5),
55 | },
56 | '&:active': {
57 | backgroundColor: alpha(
58 | theme.palette.primary.main,
59 | theme.palette.action.selectedOpacity,
60 | ),
61 | },
62 | },
63 | },
64 | }));
65 |
66 | export default function Folder(props) {
67 | const dispatch = useDispatch();
68 | const [anchorEl, setAnchorEl] = React.useState(null);
69 | const open = Boolean(anchorEl);
70 | const handleRightClick = (event) => {
71 | event.preventDefault(); // This will prevent the default right-click menu from appearing
72 | if (anchorEl) {
73 | setAnchorEl(null);
74 |
75 | } else {
76 | setAnchorEl(event.currentTarget);
77 | dispatch(setShareFolderModalId(props.folder._id))
78 |
79 | }
80 | };
81 | const handleClose = () => {
82 | setAnchorEl(null);
83 | };
84 | const navigate = useNavigate();
85 | const handleClick = () => {
86 | dispatch(insertPath(props.folder));
87 | navigate(`/dashboard/v1/${props?.folder._id}`, { replace: true });
88 | };
89 | // const handleRightClick = (event) => {
90 | // // Do something when the element is right-clicked
91 | // event.preventDefault(); // This will prevent the default right-click menu from appearing
92 | // alert('hi');
93 | // };
94 | const handleShare = (event) => {
95 | // event.preventDefault()
96 | // setAnchorEl(event.currentTarget);
97 | dispatch(openFolderShare())
98 | }
99 | return (
100 |
101 |
102 |
103 |
104 |
{props?.folder.folderName}
105 |
106 |
107 |
108 |
135 |
136 |
137 |
138 |
139 | );
140 | }
141 |
--------------------------------------------------------------------------------
/src/components/Card/FileCard.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useDispatch } from 'react-redux';
3 | import { Toaster, toast } from 'react-hot-toast';
4 |
5 | import { styled, alpha } from '@mui/material/styles';
6 |
7 | import Menu from '@mui/material/Menu';
8 | import MenuItem from '@mui/material/MenuItem';
9 | import EditIcon from '@mui/icons-material/Edit';
10 | import Divider from '@mui/material/Divider';
11 | import FileCopyIcon from '@mui/icons-material/FileCopy';
12 | import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
13 | import DeleteIcon from '@mui/icons-material/Delete';
14 | import GradeIcon from '@mui/icons-material/Grade';
15 | import { openFolderShare, setShareFolderModalId } from '../../features/Global/modalSlice';
16 | import { useGetFileMutation, useDeleteFileMutation,useAddToFavouriteMutation } from '../../features/file/fileApiSlice';
17 | import BasicModal from '../Modal/BasicModal';
18 | import { removeFile } from '../../features/folder/folderSlice';
19 |
20 | const StyledMenu = styled((props) => (
21 |
33 | ))(({ theme }) => ({
34 | '& .MuiPaper-root': {
35 | borderRadius: 6,
36 | marginTop: theme.spacing(1),
37 | minWidth: 180,
38 | color:
39 | theme.palette.mode === 'light' ? 'rgb(55, 65, 81)' : theme.palette.grey[300],
40 | boxShadow:
41 | 'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px',
42 | '& .MuiMenu-list': {
43 | padding: '4px 0',
44 | },
45 | '& .MuiMenuItem-root': {
46 | '& .MuiSvgIcon-root': {
47 | fontSize: 18,
48 | color: theme.palette.text.secondary,
49 | marginRight: theme.spacing(1.5),
50 | },
51 | '&:active': {
52 | backgroundColor: alpha(
53 | theme.palette.primary.main,
54 | theme.palette.action.selectedOpacity,
55 | ),
56 | },
57 | },
58 | },
59 | }));
60 |
61 | function FileCard(props) {
62 | const dispatch = useDispatch();
63 | const [anchorEl, setAnchorEl] = React.useState(null);
64 | const [deleteFile] = useDeleteFileMutation();
65 | const [addToFavourite]=useAddToFavouriteMutation()
66 | const open = Boolean(anchorEl);
67 | const handleRightClick = (event) => {
68 | event.preventDefault(); // This will prevent the default right-click menu from appearing
69 | if (anchorEl) {
70 | setAnchorEl(null);
71 | } else {
72 | setAnchorEl(event.currentTarget);
73 | dispatch(setShareFolderModalId(props.file._id));
74 | }
75 | };
76 | const handleClose = () => {
77 | setAnchorEl(null);
78 | };
79 | const [getFile] = useGetFileMutation();
80 | const handleOpen = async () => {
81 | const data = await getFile({ key: props.file.AWSKey }).unwrap();
82 | const imageUrl = data.url.split('?')[0];
83 | window.open(imageUrl, '_blank');
84 | };
85 | const handleShare = (event) => {
86 | // event.preventDefault()
87 | // setAnchorEl(event.currentTarget);
88 | dispatch(openFolderShare());
89 | };
90 | const handleDelete = async () => {
91 | try {
92 | await deleteFile(props.file._id).unwrap();
93 | toast.success('File moved to trash');
94 | dispatch(removeFile(props.file._id));
95 | setAnchorEl(null);
96 | } catch (error) {
97 | toast.error(error.data.message);
98 | setAnchorEl(null);
99 | }
100 | };
101 | const handleFavourite = async () => {
102 | try {
103 | await addToFavourite(props.file._id).unwrap();
104 | toast.success('File added to favorites');
105 |
106 |
107 | } catch (error) {
108 | toast.error(error.data.message);
109 | setAnchorEl(null);
110 | }
111 | }
112 | return (
113 |
114 |
115 |

116 |
{props.file.fileName}
117 |
118 |
119 |
150 |
151 |
152 |
153 |
154 | );
155 | }
156 |
157 | // #f6f8fa
158 | export default FileCard;
159 |
--------------------------------------------------------------------------------
/src/components/Login.jsx:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useEffect, useState } from 'react'
2 | import LogoText from '../assets/logoText.png'
3 | import { LockClosedIcon } from '@heroicons/react/20/solid'
4 |
5 | function Login({ data }) {
6 | // const [authState, setAuthState] = useState(false)
7 | // useEffect(() => {
8 | // setAuthState(data.state)
9 | // },[data.state])
10 | return (
11 |
12 |
13 |
14 |
15 |

20 |
21 | login to your account
22 |
23 | {/*
24 | Or{' '}
25 |
26 |
*/}
27 |
28 |
129 |
130 |
131 |
132 | )
133 | }
134 |
135 | export default Login
--------------------------------------------------------------------------------
/src/pages/UserProfilePage.jsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Link } from 'react-router-dom';
3 | import { useSelector, useDispatch } from 'react-redux';
4 | import PropTypes from 'prop-types';
5 | import toast, { Toaster } from 'react-hot-toast';
6 | import Tabs from '@mui/material/Tabs';
7 | import Tab from '@mui/material/Tab';
8 | import Typography from '@mui/material/Typography';
9 | import TextField from '@mui/material/TextField';
10 | import Box from '@mui/material/Box';
11 | import EmailIcon from '@mui/icons-material/Email';
12 | import EnhancedEncryptionIcon from '@mui/icons-material/EnhancedEncryption';
13 | import CurrencyExchangeIcon from '@mui/icons-material/CurrencyExchange';
14 | import avatar from '../assets/avatar.svg';
15 | import { useSendOtpMutation, useSubmitOtpMutation, useChangePasswordMutation } from '../features/auth/authApiSlice';
16 | import { changeOtpStatus } from '../features/auth/authSlice';
17 |
18 | function TabPanel(props) {
19 | const {
20 | children, value, index, ...other
21 | } = props;
22 |
23 | return (
24 |
31 | {value === index && (
32 |
33 | {children}
34 |
35 | )}
36 |
37 | );
38 | }
39 |
40 | TabPanel.propTypes = {
41 | children: PropTypes.node,
42 | index: PropTypes.number.isRequired,
43 | value: PropTypes.number.isRequired,
44 | };
45 | function a11yProps(index) {
46 | return {
47 | id: `simple-tab-${index}`,
48 | 'aria-controls': `simple-tabpanel-${index}`,
49 | };
50 | }
51 | const style = {
52 | color:"#9fa2f6"
53 | }
54 |
55 | function UserProfilePage() {
56 | const user = useSelector((state) => state.auth.user);
57 | const [value, setValue] = React.useState(0);
58 | const [form, setForm] = React.useState(false);
59 | const [oldPassword, setOldPassword] = React.useState('');
60 | const [newPassword, setNewPassword] = React.useState('');
61 | const [reNewPasswords, setReNewPassword] = React.useState('');
62 | const [otp, setOtp] = React.useState('');
63 | const [sendOtp, { isLoading }] = useSendOtpMutation();
64 | const [submitOtp, { isLoading: otpLoading }] = useSubmitOtpMutation();
65 | const [changePassword]=useChangePasswordMutation()
66 | const dispatch = useDispatch();
67 |
68 | const handleChange = (event, newValue) => {
69 | setValue(newValue);
70 | };
71 | async function sendOtpCall() {
72 | try {
73 | setForm(true);
74 | const data = await sendOtp({ email: user.email }).unwrap();
75 | } catch (error) {
76 |
77 | }
78 | }
79 |
80 | async function submitOtpCall() {
81 | // console.log(otpRef.current.value);
82 | try {
83 | await submitOtp({ otp }).unwrap();
84 | setForm(false);
85 | dispatch(changeOtpStatus());
86 | setOtp('');
87 | } catch (error) {
88 | toast.error(error.data.message);
89 | }
90 | }
91 | async function handlePassword() {
92 | try {
93 | if (newPassword === reNewPasswords) {
94 | await changePassword({ oldPassword, newPassword }).unwrap();
95 | toast.success("password changed");
96 | setOldPassword("");
97 | setNewPassword("");
98 | setReNewPassword("")
99 | }
100 | else {
101 | toast.error("Incorrect password");
102 |
103 | }
104 | } catch (error) {
105 | toast.error(error.data.message);
106 | }
107 |
108 | }
109 | return (
110 |
111 |
112 |
113 | {
114 | user?.profile ? (

) : (

)
115 | }
116 |
117 |
118 |
119 |
120 |
121 |
{ `${user?.firstName} ${user?.lastName}` }
122 |
126 |
127 |
128 |
129 |
130 |
131 | } />
132 | } />
133 | } />
134 |
135 |
136 |
137 | {
138 | form ? (
139 |
140 | setOtp(e.target.value)} autoFocus />
141 |
144 |
145 | ) : (
146 |
147 |
{user?.email}
148 | {
149 | user?.otpVerify ? (
verified
) : (
150 |
153 | )
154 | }
155 |
156 |
157 | )
158 | }
159 |
160 |
161 |
162 |
163 |
{ setOldPassword(e.target.value) }} type="password" />
164 |
165 | setNewPassword(e.target.value)} type="password" />
166 |
167 | setReNewPassword(e.target.value)} />
168 |
169 |
172 |
173 | Forgot your password?
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 | coming soon
182 |
183 |
184 |
185 |
186 |
187 |
188 | );
189 | }
190 |
191 | export default UserProfilePage;
192 |
--------------------------------------------------------------------------------
/src/assets/warning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/pages/SignUpPage.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | import React, { useEffect, useState, useRef } from 'react';
3 | import { useNavigate } from 'react-router-dom';
4 | import { useDispatch } from 'react-redux';
5 | import toast, { Toaster } from 'react-hot-toast';
6 | import ClipLoader from 'react-spinners/ClipLoader';
7 |
8 | import { LockClosedIcon } from '@heroicons/react/20/solid';
9 | import { setCredentials } from '../features/auth/authSlice';
10 | import {
11 | useSignupMutation,
12 | useGoogleSignUPMutation,
13 | } from '../features/auth/authApiSlice';
14 | import Navbar from '../components/Navbar';
15 | import cloudLogin from '../assets/cloudLogin.jpg';
16 | import LogoText from '../assets/logoText.png';
17 | import PreLoader from '../components/PreLoader/PreLoader';
18 |
19 | function SignUpPage() {
20 | const userRef = useRef();
21 | // const errRef = useRef();
22 | const [email, setEmail] = useState('');
23 | const [password, setPassword] = useState('');
24 | const [firstName, setFName] = useState('');
25 | const [lastName, setLName] = useState('');
26 |
27 | // const [errMsg, setErrMsg] = useState('');
28 | const navigate = useNavigate();
29 |
30 | const [signup, { isLoading }] = useSignupMutation();
31 | const [googleSignUP, { isLoading: isGoogleSignUpLoading }] = useGoogleSignUPMutation();
32 | const dispatch = useDispatch();
33 | async function handleCallbackResponse(res) {
34 | try {
35 | const googleRes = await googleSignUP(res.credential).unwrap();
36 | if (googleRes) {
37 | localStorage.setItem('accessToken', googleRes.accessToken);
38 | dispatch(setCredentials({ user: googleRes.user, accessToken: googleRes.accessToken }));
39 | navigate('/dashboard/v1/myDrive');
40 | }
41 | } catch (error) {
42 | toast.error('server error');
43 | }
44 | }
45 |
46 | useEffect(() => {
47 | userRef.current.focus();
48 | }, []);
49 |
50 | useEffect(() => {
51 | /* global google */
52 | google.accounts.id.initialize({
53 | client_id:
54 | '24354248382-7hun00kkq9vbrbp0i2okgsv67ah20fp1.apps.googleusercontent.com',
55 | callback: handleCallbackResponse,
56 | });
57 | google.accounts.id.renderButton(document.getElementById('signUpGoogle'), {
58 | theme: 'outline',
59 | size: 'large',
60 | text: 'continue_with',
61 | });
62 | }, []);
63 | const handleSubmitSignup = async (e) => {
64 | e.preventDefault();
65 | try {
66 | const userData = await signup({
67 | email,
68 | password,
69 | firstName,
70 | lastName,
71 | }).unwrap();
72 | dispatch(setCredentials({ user: userData.data, accessToken: userData.accessToken }));
73 | localStorage.setItem('accessToken', userData.accessToken);
74 |
75 | navigate('/dashboard/v1/myDrive');
76 |
77 | } catch (error) {
78 | toast.error(error.data.errors.email);
79 | }
80 | };
81 | const content = isGoogleSignUpLoading ? : (
82 |
83 |
84 |
88 |
89 |
90 |

91 |
92 |
93 |
94 |
95 |
96 |

101 |
102 | Create account
103 |
104 |
105 |
219 |
220 |
221 |
222 |
223 |
224 |
225 | );
226 | return content;
227 | }
228 |
229 | export default SignUpPage;
230 |
--------------------------------------------------------------------------------
/src/pages/LoginPage.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/label-has-associated-control */
2 | import React, { useEffect, useState, useRef } from 'react';
3 | import { Link, useNavigate } from 'react-router-dom';
4 | import { useDispatch } from 'react-redux';
5 | import Cookies from 'universal-cookie';
6 | import ClipLoader from 'react-spinners/ClipLoader';
7 | import toast, { Toaster } from 'react-hot-toast';
8 |
9 | import { LockClosedIcon } from '@heroicons/react/20/solid';
10 | import { setCredentials } from '../features/auth/authSlice';
11 | import { useLoginMutation, useGoogleSignUPMutation } from '../features/auth/authApiSlice';
12 | import Navbar from '../components/Navbar';
13 | import PreLoader from '../components/PreLoader/PreLoader';
14 | // eslint-disable-next-line import/no-unresolved
15 | import cloudLogin from '../assets/cloudLogin.jpg';
16 | import LogoText from '../assets/logoText.png';
17 |
18 | function LoginPage() {
19 | const userRef = useRef();
20 | const errRef = useRef();
21 | const [email, setEmail] = useState('');
22 | const [password, setPassword] = useState('');
23 | const [errMsg, setErrMsg] = useState('');
24 | const navigate = useNavigate();
25 |
26 | const [login, { isLoading }] = useLoginMutation();
27 | const [googleSignUP, { isLoading: isGoogleSignUpLoading }] = useGoogleSignUPMutation();
28 |
29 | const dispatch = useDispatch();
30 | const cookies = new Cookies();
31 | async function handleCallbackResponse(res) {
32 | try {
33 | const googleRes = await googleSignUP(res.credential).unwrap();
34 | if (googleRes) {
35 | localStorage.setItem('refreshToken', googleRes.refreshToken);
36 | localStorage.setItem('accessToken', googleRes.accessToken);
37 | dispatch(setCredentials({ user: googleRes.user, accessToken: googleRes.accessToken }));
38 | navigate('/dashboard/v1/myDrive');
39 |
40 | }
41 | } catch (error) {
42 | // toast.error("server error");
43 | }
44 | }
45 | // eslint-disable-next-line no-unused-vars
46 |
47 | useEffect(() => {
48 | userRef.current.focus();
49 | }, []);
50 | useEffect(() => {
51 | /* global google */
52 | google.accounts.id.initialize({
53 | client_id:
54 | '24354248382-7hun00kkq9vbrbp0i2okgsv67ah20fp1.apps.googleusercontent.com',
55 | callback: handleCallbackResponse,
56 | });
57 | google.accounts.id.renderButton(document.getElementById('signUpGoogle'), {
58 | theme: 'outline',
59 | size: 'large',
60 | text: 'continue_with',
61 | });
62 | }, []);
63 |
64 | const handleSubmit = async (e) => {
65 | e.preventDefault();
66 | try {
67 | const userData = await login({ email, password }).unwrap();
68 | dispatch(setCredentials({
69 | user: userData.user, accessToken: userData.accessToken,
70 | }));
71 | localStorage.setItem('accessToken', userData.accessToken);
72 | localStorage.setItem('refreshToken', userData.refreshToken);
73 | setEmail('');
74 | setPassword('')
75 | navigate('/dashboard/v1/myDrive');
76 | } catch (errors) {
77 | if (errors.status === 400) {
78 | toast.error(`${errors.data.errors.email} ${errors.data.errors.password}`);
79 | }
80 | }
81 | };
82 |
83 | const handleUserInput = (e) => setEmail(e.target.value);
84 | const handlePwdInput = (e) => setPassword(e.target.value);
85 |
86 | const content = isGoogleSignUpLoading ? (
87 | // Loading.....
88 |
89 | ) : (
90 |
91 |
92 |
96 |
97 |
98 |

99 |
100 |
101 | {/*
*/}
102 |
103 |
104 |
105 |

110 |
111 | login to your account
112 |
113 | {/*
114 | Or{' '}
115 |
116 |
*/}
117 |
118 |
226 |
227 |
228 |
229 |
230 |
231 | );
232 | return content;
233 | }
234 |
235 | export default LoginPage;
236 |
--------------------------------------------------------------------------------