diff --git a/.dockerignore b/.dockerignore index db1431a..130667e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,23 +1,12 @@ -.git/ -.gitignore -.dockerignore -docker-compose* -Dockerfile -makefile -htmlcov/ -coverage.xml -.coverage* - -.vscode/ -*.dat - -.DS_Store node_modules -/build -/package +.git +.gitignore +README.md .env -.env.* -!.env.example -vite.config.js.timestamp-* -vite.config.ts.timestamp-* -.idea \ No newline at end of file +.npm +.cache +dist +*.log +.DS_Store +coverage +.nyc_output \ No newline at end of file diff --git a/backend/tsconfig.json b/backend/tsconfig.json index b38a93d..9859f32 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -3,7 +3,7 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, - "module": "CommonJS" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "module": "node16" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, // "lib": [], /* Specify library files to be included in the compilation. */ "allowJs": true /* Allow javascript files to be compiled. */, // "checkJs": true, /* Report errors in .js files. */ @@ -38,7 +38,7 @@ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ /* Module Resolution Options */ - "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + "moduleResolution": "node16" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ diff --git a/debug-resend.ts b/debug-resend.ts new file mode 100644 index 0000000..ce98804 --- /dev/null +++ b/debug-resend.ts @@ -0,0 +1,47 @@ +// debug-resend.js +require('dotenv').config(); +const { Resend } = require('resend'); + +console.log('πŸ” Debugging Resend...'); + +// Check environment +console.log('RESEND_API_KEY exists:', !!process.env.RESEND_API_KEY); +console.log('RESEND_API_KEY starts with:', process.env.RESEND_API_KEY ? process.env.RESEND_API_KEY.substring(0, 3) : 'N/A'); +console.log('FROM_EMAIL:', process.env.FROM_EMAIL); + +if (!process.env.RESEND_API_KEY) { + console.log('❌ RESEND_API_KEY is missing!'); + process.exit(1); +} + +const resend = new Resend(process.env.RESEND_API_KEY); + +async function test() { + try { + console.log('\nπŸš€ Testing Resend API...'); + + const { data, error } = await resend.emails.send({ + from: process.env.FROM_EMAIL || 'myDrive ', + to: 'hamodeh.mnzk@gmail.com', + subject: 'Resend Test', + text: 'This is a test email from Resend.', + }); + + if (error) { + console.log('❌ Resend API Error:'); + console.log('Error name:', error.name); + console.log('Error message:', error.message); + console.log('Error status:', error.statusCode); + return; + } + + console.log('βœ… Email sent!'); + console.log('Email ID:', data.id); + + } catch (err) { + console.log('❌ Unexpected error:'); + console.log(err.message); + } +} + +test(); \ No newline at end of file diff --git a/index.html b/index.html index 7b10970..bdee313 100644 --- a/index.html +++ b/index.html @@ -2,17 +2,17 @@ - myDrive + FlowSync | Drive - - - + + + - + diff --git a/package.json b/package.json index 11d9036..3d1daa7 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "aws-sdk": "^2.657.0", "axios": "^1.7.2", "bcryptjs": "^3.0.2", - "body-parser": "^1.20.2", + "body-parser": "^2.2.1", "bytes": "^3.1.0", "classnames": "^2.5.1", "cli-progress": "^3.6.0", @@ -40,7 +40,7 @@ "cors": "^2.8.5", "dayjs": "^1.11.13", "dotenv": "^8.2.0", - "express": "^4.19.2", + "express": "^5.1.0", "express-validator": "^7.1.0", "fluent-ffmpeg": "^2.1.3", "helmet": "^3.21.2", @@ -49,7 +49,7 @@ "lodash.debounce": "^4.0.8", "mongodb": "^6.20.0", "mongoose": "^8.4.1", - "nodemailer": "^6.9.14", + "nodemailer": "^7.0.10", "normalize.css": "^8.0.1", "password-prompt": "^1.1.2", "progress-stream": "^2.0.0", @@ -64,6 +64,7 @@ "react-toastify": "^10.0.5", "redux": "^5.0.1", "regenerator-runtime": "^0.13.3", + "resend": "^6.5.2", "sharp": "^0.33.4", "sweetalert2": "^11.15.10", "temp": "^0.9.1", @@ -88,6 +89,7 @@ "@types/connect-busboy": "0.0.2", "@types/cookie-parser": "^1.4.2", "@types/cors": "^2.8.17", + "@types/dotenv": "^6.1.1", "@types/express": "^4.17.21", "@types/fluent-ffmpeg": "^2.1.24", "@types/helmet": "0.0.45", @@ -128,7 +130,7 @@ "tailwindcss": "^3.4.4", "typescript": "^5.4.5", "typescript-eslint": "^7.14.1", - "vite": "^5.2.13", - "vite-plugin-pwa": "^0.21.1" + "vite": "^6.0.0", + "vite-plugin-pwa": "^1.1.0" } } diff --git a/public/images/favicon-32x32.png b/public/images/favicon-32x32.png new file mode 100644 index 0000000..a519029 Binary files /dev/null and b/public/images/favicon-32x32.png differ diff --git a/public/images/icon.png b/public/images/icon.png deleted file mode 100644 index 42ae808..0000000 Binary files a/public/images/icon.png and /dev/null differ diff --git a/src/api/userAPI.ts b/src/api/userAPI.ts index 6b8e876..58b7172 100644 --- a/src/api/userAPI.ts +++ b/src/api/userAPI.ts @@ -4,7 +4,7 @@ import axios from "../axiosInterceptor"; export const getUserToken = async () => { const response = await axios.post("/user-service/get-token"); - response.data; + return response.data; // FIXED: Added return }; export const getUserAPI = async () => { @@ -54,6 +54,12 @@ export const getAccessToken = async (uuid: string) => { return response.data; }; +export const sendPasswordResetAPI = async (email: string) => { + const response = await axios.post("/api/user-service/send-password-reset", { + email, + }); + return response.data; +}; // PATCH export const changePasswordAPI = async ( @@ -79,13 +85,6 @@ export const verifyEmailAPI = async (emailToken: string) => { return response.data; }; -export const sendPasswordResetAPI = async (email: string) => { - const response = await axios.patch("/user-service/send-password-reset", { - email, - }); - return response.data; -}; - export const resetPasswordAPI = async ( password: string, passwordToken: string @@ -95,4 +94,4 @@ export const resetPasswordAPI = async ( password, }); return response.data; -}; +}; \ No newline at end of file diff --git a/src/components/LandingPage/LandingPage.tsx b/src/components/LandingPage/LandingPage.tsx index ca01a7e..d4b46e9 100644 --- a/src/components/LandingPage/LandingPage.tsx +++ b/src/components/LandingPage/LandingPage.tsx @@ -9,7 +9,7 @@ const LandingPage = () => {
{/* Header */}
-
🌊 FlowSync
+
♾️ FlowSync
@@ -516,8 +516,7 @@ const LandingPage = () => {
-
🌊 FlowSpace
-

Innovating the future of digital storage and collaboration

+
♾️ FlowSync

Innovating the future of digital storage and collaboration

Secure. Simple. Seamless.

diff --git a/src/components/LoginPage/LoginPage.tsx b/src/components/LoginPage/LoginPage.tsx index 6bd4372..fcff31d 100644 --- a/src/components/LoginPage/LoginPage.tsx +++ b/src/components/LoginPage/LoginPage.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useRef, useState, useCallback ,FormEvent } from "react"; import { createAccountAPI, getUserAPI, @@ -16,6 +16,8 @@ import Swal from "sweetalert2"; import { AxiosError } from "axios"; import isEmail from "validator/es/lib/isEmail"; + + // ADD THE defaultView PROP HERE const LoginPage = ({ defaultView = "login" }) => { const [email, setEmail] = useState(""); @@ -30,7 +32,7 @@ const LoginPage = ({ defaultView = "login" }) => { const navigate = useNavigate(); const lastSentPassowordReset = useRef(0); - const attemptLoginWithToken = async () => { + const attemptLoginWithToken = useCallback(async () => { setAttemptingLogin(true); try { @@ -47,7 +49,7 @@ const LoginPage = ({ defaultView = "login" }) => { window.localStorage.removeItem("hasPreviouslyLoggedIn"); } } - }; + }, [location.state?.from?.pathname, dispatch, navigate]); const login = async () => { try { @@ -147,16 +149,16 @@ const LoginPage = ({ defaultView = "login" }) => { } })(); - const onSubmit = (e: any) => { - e.preventDefault(); - if (mode === "login") { - login(); - } else if (mode === "create") { - createAccount(); - } else if (mode === "reset") { - resetPassword(); - } - }; + const onSubmit = (e: FormEvent) => { + e.preventDefault(); + if (mode === "login") { + login(); + } else if (mode === "create") { + createAccount(); + } else if (mode === "reset") { + resetPassword(); + } +}; const headerTitle = (() => { switch (mode) { @@ -287,13 +289,13 @@ const LoginPage = ({ defaultView = "login" }) => { /> {mode === "login" && (
- +
)}
diff --git a/src/routers/AppRouter.jsx b/src/routers/AppRouter.jsx index c5aaf03..6983f2b 100644 --- a/src/routers/AppRouter.jsx +++ b/src/routers/AppRouter.jsx @@ -13,6 +13,7 @@ import Homepage from "../components/Homepage/Homepage"; import SettingsPage from "../components/SettingsPage/SettingsPage"; import LandingPage from '../components/LandingPage/LandingPage'; import PrivateRoute from "./PrivateRoute"; +import ForgotPasswordPage from "../components/ForgotPasswordPage/ForgotPasswordPage"; const AppRouter = () => { return ( @@ -23,6 +24,7 @@ const AppRouter = () => { } /> } /> } /> + } /> } /> } /> } /> diff --git a/tsconfig.json b/tsconfig.json index a7fc6fb..b2f104c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["src"], + "include": ["src", "backend/utils/emailService.ts"], "references": [{ "path": "./tsconfig.node.json" }] }