39 Commits

Author SHA1 Message Date
Kshitij a5168a282b Merged Salvi's upload functionality and Ombase's list files functionality. 2025-04-15 11:04:40 +05:30
Atharva Ombase 4219570d80 Feat:Added file table on the Dashboard 2025-04-15 04:14:00 +05:30
Atharva Ombase 710a08c868 Feat:Added some dependancies 2025-04-15 04:12:02 +05:30
Atharva Ombase 2f6dcf13f7 Feat:Added some dependancies 2025-04-15 04:11:16 +05:30
Atharva Ombase 8dec47ff63 Feat: Added table to list and view HDFS files with dynamic navigation 2025-04-15 04:10:27 +05:30
Kshitij 9e68d73cf4 Merged Atharv Ombase's changes from frontend branch into the main branch. 2025-03-29 22:28:10 +05:30
Kshitij 65783c1ca0 Merged changes from frontend branch, i.e. commits made by Ombase, Dinesh and me in frontend. 2025-02-27 23:06:51 +05:30
Kshitij 8c070fd616 Added new dashboard in sample, designed by Dinesh! 2025-02-27 23:00:46 +05:30
Kshitij 95995d0a4e Merge branch 'dinesh' into frontend. 2025-02-27 22:52:42 +05:30
Kshitij 72c1968c67 Removed package-lock from Dinesh's commit. 2025-02-27 22:51:29 +05:30
Dinesh065 000ae78d1e Improved the landing page and footer 2025-02-27 22:42:14 +05:30
Kshitij f4ac9a4f15 Removed package-lock from repo. No longer tracking it. 2025-02-26 20:18:16 +05:30
Kshitij 7c7d8a6c3a Manually merging Ombase's changes to NotFoundPage.jsx since I rebased an older commit to add a more descriptive comment. 2025-02-26 20:13:58 +05:30
Kshitij 0fe8077f7e Fix: Changed 404 image in NotFoundPage.jsx 2025-02-26 20:09:52 +05:30
Kshitij a3ab6731c6 Added package-lock to gitignore and added server in vite.config.js 2025-02-26 20:09:37 +05:30
atharvaombase c7697a4b3c Fix:Fixed 404.png import path 2025-02-26 20:08:59 +05:30
Kshitij 7994f2768d Fix: Changed 404 image in NotFoundPage.jsx 2025-02-26 20:01:48 +05:30
Kshitij bb15fe9b7a Added package-lock to gitignore 2025-02-26 19:43:02 +05:30
Kshitij 785eb9e66a Added dashboard sample image & updated README. 2025-02-26 19:07:25 +05:30
Kshitij 7590e81f5c Merged Ombase's changes from frontend branch with main branch. Created sidebar, dashboard, and not found page. Minor changes to landing page. 2025-02-26 19:00:19 +05:30
atharvaombase 8ba3d6e093 Fix:Fixed height of first page where the height was dynamic 2025-02-26 18:04:06 +05:30
atharvaombase 88cd92a159 Fix:Added route for Custom NotFoundPage 2025-02-26 18:03:05 +05:30
atharvaombase 9c5a000555 Feat:Custom Page not found page 2025-02-26 18:02:16 +05:30
atharvaombase 130cada092 Fix:Kept the light theme and removed black theme 2025-02-26 18:01:36 +05:30
atharvaombase 7f6e377674 Feat:Added searchBar in navbar 2025-02-26 16:47:43 +05:30
atharvaombase fe06abadcf Feat:Added the icons and necessary buttons 2025-02-26 15:21:15 +05:30
atharvaombase 00eab70d71 Merge branch 'frontend' of https://github.com/kshitij-ka/cc-mini into frontend 2025-02-26 12:14:50 +05:30
atharvaombase 2e74a8b762 Moved DrivethruLandingPage.jsx to its new location 2025-02-26 12:12:37 +05:30
atharvaombase e3f2d4fd0a Feat:Custom css for the Overflow scrollbar in the sidebar 2025-02-26 12:10:28 +05:30
atharvaombase 6c0b39ddbf Fix:Moved user related pages to UserPages 2025-02-26 12:06:10 +05:30
Kshitij b14c132808 Fix: Moved design link above sample images. 2025-02-26 12:04:54 +05:30
atharvaombase a7b5c24d72 Feat:Created sidebar 2025-02-26 12:04:41 +05:30
Kshitij 2556843ef6 Misc: Added sample images for landing, login and signup page. Also, referenced in README. 2025-02-26 12:03:18 +05:30
atharvaombase 43f4a8f9ce Feat:Added routes 2025-02-26 12:00:49 +05:30
atharvaombase 9abd6c554a Fix:Removed files from Root folder to Frontend folder
Feat:Created landing page,Login page, Signup page
2025-02-26 10:46:33 +05:30
atharvaombase 1005852091 Initail Commit 2025-02-25 23:39:31 +05:30
Kshitij 61a36fc2bc Added link to design in README file. 2025-02-25 01:40:02 +05:30
Kshitij 714ece9637 Added a placeholder file to push Frontend folder. 2025-02-24 23:15:18 +05:30
Kshitij b2ba415373 Initial commit in frontend branch. 2025-02-24 23:04:49 +05:30
26 changed files with 1396 additions and 69 deletions
+1
View File
@@ -11,6 +11,7 @@ node_modules
dist dist
dist-ssr dist-ssr
*.local *.local
package-lock.json
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*
+107 -2
View File
@@ -8,10 +8,13 @@
"name": "drive-thru", "name": "drive-thru",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^2.6.0",
"@tailwindcss/vite": "^4.0.9", "@tailwindcss/vite": "^4.0.9",
"lucide-react": "^0.476.0",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.2.0" "react-router-dom": "^7.2.0"
}, },
"devDependencies": { "devDependencies": {
@@ -921,6 +924,30 @@
"@jridgewell/sourcemap-codec": "^1.4.14" "@jridgewell/sourcemap-codec": "^1.4.14"
} }
}, },
"node_modules/@reduxjs/toolkit": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.6.1.tgz",
"integrity": "sha512-SSlIqZNYhqm/oMkXbtofwZSt9lrncblzo6YcZ9zoX+zLngRBrCOjK4lNLdkNucJF58RHOWrD9txT3bT3piH7Zw==",
"license": "MIT",
"dependencies": {
"immer": "^10.0.3",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
"reselect": "^5.1.0"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.34.8", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz",
@@ -1420,7 +1447,7 @@
"version": "19.0.10", "version": "19.0.10",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz",
"integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==", "integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
@@ -1434,6 +1461,12 @@
"@types/react": "^19.0.0" "@types/react": "^19.0.0"
} }
}, },
"node_modules/@types/use-sync-external-store": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
"integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
"license": "MIT"
},
"node_modules/@vitejs/plugin-react": { "node_modules/@vitejs/plugin-react": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz",
@@ -1897,7 +1930,7 @@
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true "devOptional": true
}, },
"node_modules/data-view-buffer": { "node_modules/data-view-buffer": {
"version": "1.0.2", "version": "1.0.2",
@@ -2847,6 +2880,16 @@
"node": ">= 4" "node": ">= 4"
} }
}, },
"node_modules/immer": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -3624,6 +3667,15 @@
"yallist": "^3.0.2" "yallist": "^3.0.2"
} }
}, },
"node_modules/lucide-react": {
"version": "0.476.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.476.0.tgz",
"integrity": "sha512-x6cLTk8gahdUPje0hSgLN1/MgiJH+Xl90Xoxy9bkPAsMPOUiyRSKR4JCDPGVCEpyqnZXH3exFWNItcvra9WzUQ==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/math-intrinsics": { "node_modules/math-intrinsics": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -3998,6 +4050,29 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true "dev": true
}, },
"node_modules/react-redux": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
"license": "MIT",
"dependencies": {
"@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0"
},
"peerDependencies": {
"@types/react": "^18.2.25 || ^19",
"react": "^18.0 || ^19",
"redux": "^5.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.14.2", "version": "0.14.2",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
@@ -4045,6 +4120,21 @@
"react-dom": ">=18" "react-dom": ">=18"
} }
}, },
"node_modules/redux": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"license": "MIT"
},
"node_modules/redux-thunk": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
"license": "MIT",
"peerDependencies": {
"redux": "^5.0.0"
}
},
"node_modules/reflect.getprototypeof": { "node_modules/reflect.getprototypeof": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -4087,6 +4177,12 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/reselect": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
"license": "MIT"
},
"node_modules/resolve": { "node_modules/resolve": {
"version": "2.0.0-next.5", "version": "2.0.0-next.5",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
@@ -4658,6 +4754,15 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/use-sync-external-store": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "6.2.0", "version": "6.2.0",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz",
+3 -1
View File
@@ -10,11 +10,13 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^2.6.0",
"@tailwindcss/vite": "^4.0.9", "@tailwindcss/vite": "^4.0.9",
"flowbite": "^3.1.2", "lucide-react": "^0.476.0",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.2.0" "react-router-dom": "^7.2.0"
}, },
"devDependencies": { "devDependencies": {
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

+5 -4
View File
@@ -1,19 +1,20 @@
import "./App.css"; import "./App.css";
import DrivethruLandingPage from "./pages/DrivethruLandingPage";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Login from "./pages/Authentication/Login"; import Login from "./pages/Authentication/Login";
import SignUp from "./pages/Authentication/SignUp"; import SignUp from "./pages/Authentication/SignUp";
import DrivethruLandingPage from "./pages/UserPages/DrivethruLandingPage";
import Dashboard from "./pages/UserPages/Dashboard";
import NotFoundPage from "./pages/UserPages/NotFoundPage";
function App() { function App() {
return ( return (
<Router> <Router>
<Routes> <Routes>
{/* Landing Page at root ("/") */}
<Route path="/" element={<DrivethruLandingPage />} /> <Route path="/" element={<DrivethruLandingPage />} />
{/* Login Page at "/login" */}
<Route path="/login" element={<Login />} /> <Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} /> <Route path="/signup" element={<SignUp />} />
<Route path="/Dashboard" element={<Dashboard />} />
<Route path="*" element={<NotFoundPage />} />
</Routes> </Routes>
</Router> </Router>
); );
+134
View File
@@ -0,0 +1,134 @@
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
const FileTable = ({ initialPath }) => {
const [currentPath, setCurrentPath] = useState(initialPath || "/");
const [files, setFiles] = useState([]);
// Helpers to parse entry
const getType = (entry) =>
entry.trim().startsWith("📁") ? "Folder" : "File";
const getName = (entry) => entry.trim().replace(/^📁\s*|^📄\s*/, "");
const isFile = (entry) => getType(entry) === "File";
// Fetch and show only top-level entries (indentation = 0)
const fetchFiles = async () => {
try {
const response = await fetch(
`http://192.168.29.61:8080/api/hdfs/listFiles?hdfsPath=${currentPath}`
);
const data = await response.json();
// Filter entries: only those without leading spaces
const filtered = data.filter(
(entry) => entry.match(/^ */)[0].length === 0
);
setFiles(filtered);
} catch (error) {
console.error("Failed to fetch files:", error);
setFiles([]);
}
};
useEffect(() => {
fetchFiles();
}, [currentPath]);
// Navigate into a folder
const handleOpenFolder = (folderName) => {
const newPath =
currentPath === "/" ? `/${folderName}` : `${currentPath}/${folderName}`;
setCurrentPath(newPath);
};
// Go up one level
const goBack = () => {
if (currentPath === "/") return;
const parts = currentPath.split("/").filter(Boolean);
parts.pop();
setCurrentPath(parts.length === 0 ? "/" : `/${parts.join("/")}`);
};
return (
<div className="relative overflow-x-auto shadow-md rounded-lg">
<div className="flex items-center justify-between px-6 py-4 bg-blue-100 text-black font-medium">
<span>Path: {currentPath}</span>
{currentPath !== "/" && (
<button onClick={goBack} className="text-blue-600 hover:underline">
Go Back
</button>
)}
</div>
<table className="w-full text-sm text-left text-black">
<thead className="text-xs text-black uppercase bg-blue-100">
<tr>
<th scope="col" className="px-6 py-3">
File Name
</th>
<th scope="col" className="px-6 py-3">
Type
</th>
<th scope="col" className="px-6 py-3">
Action
</th>
</tr>
</thead>
<tbody>
{files.length === 0 ? (
<tr>
<td colSpan="3" className="px-6 py-4 text-gray-600">
No files found.
</td>
</tr>
) : (
files.map((entry, idx) => {
const name = getName(entry);
const type = getType(entry);
const encodedPath = encodeURIComponent(`${currentPath}/${name}`);
const downloadUrl = `http://192.168.29.61:8080/api/hdfs/downloadFile?hdfsPath=${encodedPath}&localPath=E:/testdownload/${name}&kalas=${
currentPath.split("/")[1] || "user"
}`;
return (
<tr
key={idx}
className="even:bg-blue-50 odd:bg-white border-b border-blue-200"
>
<td className="px-6 py-4 font-medium whitespace-nowrap">
{name}
</td>
<td className="px-6 py-4">{type}</td>
<td className="px-6 py-4">
{isFile(entry) ? (
<a
href={downloadUrl}
className="font-medium text-blue-600 hover:underline"
target="_blank"
rel="noopener noreferrer"
>
Download
</a>
) : (
<button
onClick={() => handleOpenFolder(name)}
className="font-medium text-blue-600 hover:underline"
>
Open
</button>
)}
</td>
</tr>
);
})
)}
</tbody>
</table>
</div>
);
};
FileTable.propTypes = {
initialPath: PropTypes.string,
};
export default FileTable;
+68
View File
@@ -0,0 +1,68 @@
import React, { useState } from "react";
import { uploadFileToHDFS } from "../utils/api";
const FileUpload = () => {
const [file, setFile] = useState(null);
const [hdfsPath, setHdfsPath] = useState("/kalas");
const [uploadedFileName, setUploadedFileName] = useState("");
const [username, setUsername] = useState("kalas");
const handleSubmit = (e) => {
e.preventDefault();
if (!file || !uploadedFileName) {
return;
}
uploadFileToHDFS(file, hdfsPath, uploadedFileName, username);
};
return (
<form
onSubmit={handleSubmit}
className="p-5 py-16 border rounded shadow w-full max-w-md"
>
<h2 className="text-lg font-bold mb-2">Upload File Your File</h2>
<input
type="file"
onChange={(e) => {
setFile(e.target.files[0]);
setUploadedFileName(e.target.files[0]?.name || "");
}}
className="mb-2"
/>
{/* <input
type="text"
placeholder="HDFS Path"
value={hdfsPath}
onChange={(e) => setHdfsPath(e.target.value)}
className="border p-2 mb-2 w-full"
/> */}
{/* <input
type="text"
placeholder="Uploaded File Name"
value={uploadedFileName}
onChange={(e) => setUploadedFileName(e.target.value)}
className="border p-2 mb-2 w-full"
/> */}
{/* <input
type="text"
placeholder="Username"
value={username}
onChange={(e) => setUsername(e.target.value)}
className="border p-2 mb-2 w-full"
/> */}
<button
type="submit"
className="bg-blue-600 text-white px-4 py-2 rounded"
>
Upload File
</button>
</form>
);
};
export default FileUpload;
+152 -9
View File
@@ -1,16 +1,159 @@
import { useState } from "react";
import {
Facebook,
Twitter,
Instagram,
Linkedin,
Mail,
Phone,
MapPin,
} from "lucide-react";
const Footer = () => { const Footer = () => {
const [email, setEmail] = useState("");
//Currently storing user email in localstorage
const handleSubscribe = () => {
if (email.trim() !== "") {
localStorage.setItem("subscribedEmail", email);
alert("You have successfully subscribed!");
setEmail("");
}
};
return ( return (
<footer className="bg-gradient-to-r from-[#689adc] via-[#6da1e6] h-[353px] w-full pt-16 pb-8"> <footer className="bg-gradient-to-r from-[#4a7cbd] via-[#5b4fd3] to-[#9377ff] w-full pt-16 pb-8">
<div className="container mx-auto px-4"> <div className="container mx-auto px-6">
<div className="flex items-center justify-center mb-4"> <div className="grid grid-cols-1 md:grid-cols-4 gap-8 mb-12">
<div className="text-cyan-400 mr-3"> <div className="space-y-4">
<img src="/image.png" alt="logo" className="h-auto w-16 drop-shadow-lg " /> <div className="flex items-center">
<div className="text-white mr-3">
<svg
className="w-10 h-10"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 2L2 12L12 22L22 12L12 2Z"
stroke="currentColor"
strokeWidth="3"
fill="none"
/>
</svg>
</div>
<h3 className="text-2xl font-bold text-white">Drive-thru</h3>
</div>
<p className="text-white/90">
Your secure cloud storage solution for all your digital needs.
</p>
<div className="flex space-x-4">
<a href="https://facebook.com" target="_blank" rel="noopener noreferrer">
<Facebook className="w-5 h-5 text-white cursor-pointer hover:text-cyan-200 transition-all duration-200 transform hover:scale-110" />
</a>
<a href="https://twitter.com" target="_blank" rel="noopener noreferrer">
<Twitter className="w-5 h-5 text-white cursor-pointer hover:text-cyan-200 transition-all duration-200 transform hover:scale-110" />
</a>
<a href="https://instagram.com" target="_blank" rel="noopener noreferrer">
<Instagram className="w-5 h-5 text-white cursor-pointer hover:text-cyan-200 transition-all duration-200 transform hover:scale-110" />
</a>
<a href="https://linkedin.com" target="_blank" rel="noopener noreferrer">
<Linkedin className="w-5 h-5 text-white cursor-pointer hover:text-cyan-200 transition-all duration-200 transform hover:scale-110" />
</a>
</div>
</div>
{/* Quick Links */}
<div>
<h4 className="font-semibold text-white mb-4">Quick Links</h4>
<ul className="space-y-2">
<li>
<a
href="#about"
className="text-white/90 hover:text-white transition-all duration-200 hover:translate-x-1 inline-block"
>
About Us
</a>
</li>
<li>
<a
href="#features"
className="text-white/90 hover:text-white transition-all duration-200 hover:translate-x-1 inline-block"
>
Features
</a>
</li>
<li>
<a
href="#howItWorks"
className="text-white/90 hover:text-white transition-all duration-200 hover:translate-x-1 inline-block"
>
How It Works
</a>
</li>
</ul>
</div>
{/* Contact Info */}
<div>
<h4 className="font-semibold text-white mb-4">Contact</h4>
<ul className="space-y-2">
<li className="flex items-center text-white/90 hover:text-white group transition-colors duration-200">
<Mail className="w-4 h-4 mr-2 group-hover:text-cyan-200" />
support@drivethru.com
</li>
<li className="flex items-center text-white/90 hover:text-white group transition-colors duration-200">
<Phone className="w-4 h-4 mr-2 group-hover:text-cyan-200" />
+91 3628206234
</li>
<li className="flex items-center text-white/90 hover:text-white group transition-colors duration-200">
<MapPin className="w-4 h-4 mr-2 group-hover:text-cyan-200" />
123 Cloud Street, Digital City
</li>
</ul>
</div>
{/* Newsletter */}
<div>
<h4 className="font-semibold text-white mb-4">Stay Updated</h4>
<p className="text-white/90 mb-4">
Get exclusive tips, updates on new features, and special offers directly in your inbox.
</p>
<div className="space-y-4">
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
className="w-full px-4 py-2 rounded-md bg-white/10 border border-white/20 text-white placeholder:text-white/50 focus:bg-white/20 transition-all duration-200 outline-none focus:ring-2 focus:ring-white/30"
/>
<button
onClick={handleSubscribe}
className="w-full px-4 py-2 rounded-md bg-white text-blue-600 font-medium hover:bg-opacity-90 transition-all duration-200 transform hover:scale-105"
>
Subscribe to Newsletter
</button>
</div>
</div>
</div>
<div className="h-px w-full bg-white/20 my-8" />
{/* Bottom Section */}
<div className="flex flex-col md:flex-row justify-between items-center text-white/90 text-sm">
<p>© {new Date().getFullYear()} Drive-Thru. All rights reserved.</p>
<div className="flex gap-4 mt-4 md:mt-0">
<a href="#" className="hover:text-white transition-all duration-200 hover:translate-x-1 inline-block">
Privacy Policy
</a>
<a href="#" className="hover:text-white transition-all duration-200 hover:translate-x-1 inline-block">
Terms of Service
</a>
<a href="#" className="hover:text-white transition-all duration-200 hover:translate-x-1 inline-block">
Cookie Policy
</a>
</div> </div>
<h1 className="text-5xl font-bold text-black">Drive-thru</h1>
</div> </div>
<p className="text-black text-center">
A mini project designed and engineering by Team 2025 <br />All rights reserved.
</p>
</div> </div>
</footer> </footer>
); );
+308
View File
@@ -0,0 +1,308 @@
import { Link } from "react-router-dom";
const Sidebar = () => {
return (
<>
<nav className="fixed top-0 z-50 h-[60px] w-full bg-white border-b border-gray-200 ">
<div className="p-[15px] h-full lg:px-5 lg:pl-3 ">
<div className="flex h-full items-center justify-between">
<div className="flex items-center justify-start rtl:justify-end">
<button
data-drawer-target="logo-sidebar"
data-drawer-toggle="logo-sidebar"
aria-controls="logo-sidebar"
type="button"
className="inline-flex items-center p-2 text-lg text-white rounded-lg sm:hidden hover:bg-[#37A0EA] focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-[#37A0EA] dark:focus:ring-gray-600"
>
<span className="sr-only">Open sidebar</span>
<svg
className="w-6 h-6"
aria-hidden="true"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clipRule="evenodd"
fillRule="evenodd"
d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z"
></path>
</svg>
</button>
<Link to="/" className="flex ms-2 md:me-24">
<img
src="./image.png"
className="h-8 me-3"
alt="Drive-thru Logo"
/>
<span className="self-center text-xl font-semibold sm:text-2xl whitespace-nowrap dark:text-white">
Drive-thru
</span>
</Link>
</div>
<div className="flex items-center">
{" "}
<div className="flex items-center justify-end mr-40 ">
<input
type="text"
placeholder="Search..."
className="w-full border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
type="button"
className="ml-2 px-4 py-2 text-white bg-blue-500 rounded-lg hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
Search
</button>
</div>
<div className="flex items-center ms-3">
<div>
<button
type="button"
className="flex text-lg bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
aria-expanded="false"
data-dropdown-toggle="dropdown-user"
>
<span className="sr-only">Open user menu</span>
<img
className="w-8 h-8 rounded-full"
src="https://flowbite.com/docs/images/people/profile-picture-5.jpg"
alt="user photo"
/>
</button>
</div>
<div
className="z-50 hidden my-4 text-base list-none bg-[#1877F2] divide-y divide-gray-100 rounded-sm shadow-sm dark:bg-gray-700 dark:divide-gray-600"
id="dropdown-user"
>
<div className="px-4 py-3" role="none">
<p
className="text-lg text-white dark:text-white"
role="none"
>
Neil Sims
</p>
<p
className="text-lg font-medium text-white truncate dark:text-gray-300"
role="none"
>
Drive-thru@Drive-thru.com
</p>
</div>
<ul className="py-1" role="none">
<li>
<Link
to="#"
className="block px-4 py-2 text-lg text-white hover:bg-[#37A0EA] dark:text-gray-300 dark:hover:bg-[#37A0EA] dark:hover:text-white"
role="menuitem"
>
Dashboard
</Link>
</li>
<li>
<Link
to="#"
className="block px-4 py-2 text-lg text-white hover:bg-[#37A0EA] dark:text-gray-300 dark:hover:bg-[##37A0EA] dark:hover:text-white"
role="menuitem"
>
Settings
</Link>
</li>
<li>
<Link
to="#"
className="block px-4 py-2 text-lg text-white hover:bg-[#37A0EA] dark:text-gray-300 dark:hover:bg-[#37A0EA] dark:hover:text-white"
role="menuitem"
>
Earnings
</Link>
</li>
<li>
<Link
to="#"
className="block px-4 py-2 text-lg text-white hover:bg-[#37A0EA] dark:text-gray-300 dark:hover:bg-[#37A0EA] dark:hover:text-white"
role="menuitem"
>
Sign out
</Link>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</nav>
<aside
id="logo-sidebar"
className="fixed top-0 left-0 z-40 w-64 h-screen pt-[60px] transition-transform -translate-x-full bg-[##1877F2] border-r border-gray-200 sm:translate-x-0 dark:bg-[#1877F2] dark:border-gray-700"
aria-label="Sidebar"
>
<div className="h-full px-3 pb-4 overflow-y-auto bg-[#1877F2] dark:bg-[#1877F2] custom-scrollbar">
<ul className="space-y-2 font-medium">
<li>
<Link
to="#"
className="flex items-center p-2 mt-5 pt-4 pb-4 text-white rounded-lg dark:text-white hover:bg-[#37A0EA] dark:hover:bg-[#37A0EA] group"
>
<svg
className="w-5 h-5 text-white transition duration-75 dark:text-gray-400 group-hover:text-white dark:group-hover:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.62L12 2 9.19 8.62 2 9.24l5.46 4.73L5.82 21z" />
</svg>
<span className="ms-3">Starred</span>
</Link>
</li>
<li>
<Link
to="#"
className="flex items-center p-2 pt-4 pb-4 text-white rounded-lg dark:text-white hover:bg-[#37A0EA] dark:hover:bg-[#37A0EA] group"
>
<svg
className="w-5 h-5"
viewBox="0 0 20 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2.31763 16.0834C1.93846 16.0834 1.60669 15.9372 1.32231 15.6449C1.03794 15.3527 0.895752 15.0248 0.895752 14.6615V2.33856C0.895752 1.97519 1.03794 1.64737 1.32231 1.3551C1.60669 1.06282 1.93846 0.916687 2.31763 0.916687H8.97674L10.3986 2.33856H18.4322C18.7956 2.33856 19.1234 2.4847 19.4157 2.77697C19.7079 3.06925 19.8541 3.39707 19.8541 3.76044V14.6615C19.8541 15.0248 19.7079 15.3527 19.4157 15.6449C19.1234 15.9372 18.7956 16.0834 18.4322 16.0834H2.31763ZM9.4033 13.0026H16.9866V12.5524C16.9866 11.8888 16.6509 11.3477 15.9795 10.9291C15.308 10.5104 14.3799 10.3011 13.195 10.3011C12.0101 10.3011 11.0819 10.5104 10.4105 10.9291C9.73903 11.3477 9.4033 11.8888 9.4033 12.5524V13.0026ZM13.195 8.87919C13.6689 8.87919 14.0757 8.70935 14.4154 8.36968C14.7551 8.03001 14.9249 7.6232 14.9249 7.14924C14.9249 6.67528 14.7551 6.26847 14.4154 5.9288C14.0757 5.58913 13.6689 5.41929 13.195 5.41929C12.721 5.41929 12.3142 5.58913 11.9745 5.9288C11.6349 6.26847 11.465 6.67528 11.465 7.14924C11.465 7.6232 11.6349 8.03001 11.9745 8.36968C12.3142 8.70935 12.721 8.87919 13.195 8.87919Z"
fill="white"
/>
</svg>
<span className="flex-1 ms-3 whitespace-nowrap">
Shared with me
</span>
</Link>
</li>
<li>
<Link
to="#"
className="flex items-center p-2 pt-4 pb-4 text-white rounded-lg dark:text-white hover:bg-[#37A0EA] dark:hover:bg-[#37A0EA] group"
>
<svg
className="w-5 h-5"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path d="M5 3h2v18H5V3zm6 6h2v12h-2V9zm6-4h2v16h-2V5z" />
</svg>
<span className="flex-1 ms-3 whitespace-nowrap">
Statistics
</span>
</Link>
</li>
<li>
<Link
to="#"
className="flex items-center p-2 pt-4 pb-4 text-white rounded-lg dark:text-white hover:bg-[#37A0EA] dark:hover:bg-[#37A0EA] group"
>
<svg
className="w-5 h-5 text-white dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
viewBox="0 0 24 24"
>
<path
fillRule="evenodd"
d="M3 6a2 2 0 0 1 2-2h5.532a2 2 0 0 1 1.536.72l1.9 2.28H3V6Zm0 3v10a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9H3Z"
clipRule="evenodd"
/>
</svg>
<span className="flex-1 ms-3 whitespace-nowrap">My files</span>
</Link>
</li>
<li>
<Link
to="#"
className="flex items-center p-2 pt-4 pb-4 text-white rounded-lg dark:text-white hover:bg-[#37A0EA] dark:hover:bg-[#37A0EA] group"
>
<svg
className="w-5 h-5"
viewBox="0 0 20 19"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.19471 18.9791L7.72075 15.9932C7.42058 15.8826 7.10461 15.7325 6.77284 15.5429C6.44106 15.3534 6.14879 15.1559 5.89601 14.9505L3.09966 16.2302L0.895752 12.3437L3.45513 10.4716C3.42353 10.3294 3.40378 10.1675 3.39588 9.98579C3.38798 9.8041 3.38403 9.64217 3.38403 9.49998C3.38403 9.35779 3.38798 9.19586 3.39588 9.01417C3.40378 8.83249 3.42353 8.67055 3.45513 8.52837L0.895752 6.65623L3.09966 2.76977L5.89601 4.04946C6.14879 3.84408 6.44106 3.64659 6.77284 3.45701C7.10461 3.26743 7.42058 3.12524 7.72075 3.03045L8.19471 0.020813H12.5551L13.0291 3.00675C13.3293 3.11734 13.6492 3.26348 13.9889 3.44516C14.3285 3.62685 14.6168 3.82828 14.8538 4.04946L17.6502 2.76977L19.8541 6.65623L17.2947 8.48097C17.3263 8.63896 17.3461 8.80879 17.354 8.99048C17.3619 9.17216 17.3658 9.34199 17.3658 9.49998C17.3658 9.65797 17.3619 9.82385 17.354 9.99764C17.3461 10.1714 17.3263 10.3373 17.2947 10.4953L19.8541 12.3437L17.6502 16.2302L14.8538 14.9505C14.601 15.1559 14.3127 15.3573 13.9889 15.5548C13.665 15.7523 13.3451 15.8984 13.0291 15.9932L12.5551 18.9791H8.19471ZM10.3749 12.5807C11.228 12.5807 11.9548 12.2805 12.5551 11.6802C13.1555 11.0798 13.4556 10.3531 13.4556 9.49998C13.4556 8.64686 13.1555 7.92012 12.5551 7.31977C11.9548 6.71942 11.228 6.41925 10.3749 6.41925C9.52179 6.41925 8.79506 6.71942 8.19471 7.31977C7.59436 7.92012 7.29419 8.64686 7.29419 9.49998C7.29419 10.3531 7.59436 11.0798 8.19471 11.6802C8.79506 12.2805 9.52179 12.5807 10.3749 12.5807Z"
fill="white"
/>
</svg>
<span className="flex-1 ms-3 whitespace-nowrap">Settings</span>
</Link>
</li>
<li>
<Link
to="#"
className="flex items-center p-2 pt-4 pb-4 text-white rounded-lg dark:text-white hover:bg-[#37A0EA] dark:hover:bg-[#37A0EA] group"
>
<svg
className="w-5 h-5 text-white dark:text-white self-center"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
viewBox="0 0 24 24"
>
<path
fillRule="evenodd"
d="M8.586 2.586A2 2 0 0 1 10 2h4a2 2 0 0 1 2 2v2h3a1 1 0 1 1 0 2v12a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V8a1 1 0 0 1 0-2h3V4a2 2 0 0 1 .586-1.414ZM10 6h4V4h-4v2Zm1 4a1 1 0 1 0-2 0v8a1 1 0 1 0 2 0v-8Zm4 0a1 1 0 1 0-2 0v8a1 1 0 1 0 2 0v-8Z"
clipRule="evenodd"
/>
</svg>
<span className="flex-1 ms-3 whitespace-nowrap">Trash</span>
</Link>
</li>
</ul>
<div className="mt-6 p-4 rounded-lg text-white">
{/* Cloud Icon + Title */}
<div className="flex items-center">
<svg
className="w-7 h-7 text-white dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M13.383 4.076a6.5 6.5 0 0 0-6.887 3.95A5 5 0 0 0 7 18h3v-4a2 2 0 0 1-1.414-3.414l2-2a2 2 0 0 1 2.828 0l2 2A2 2 0 0 1 14 14v4h4a4 4 0 0 0 .988-7.876 6.5 6.5 0 0 0-5.605-6.048Z" />
<path d="M12.707 9.293a1 1 0 0 0-1.414 0l-2 2a1 1 0 1 0 1.414 1.414l.293-.293V19a1 1 0 1 0 2 0v-6.586l.293.293a1 1 0 0 0 1.414-1.414l-2-2Z" />
</svg>
<span className="ml-2 font-semibold">My Storage</span>
</div>
{/* Usage Text & Progress Bar */}
<p className="mt-2 text-lg">Used: of 100GB</p>
<div className="w-full bg-white rounded-full h-2 mt-2">
<div
className="bg-blue-500 h-2 rounded-full"
style={{ width: "24%" }}
></div>
</div>
</div>
</div>
</aside>
</>
);
};
export default Sidebar;
+27 -1
View File
@@ -1,2 +1,28 @@
@import "tailwindcss"; @import "tailwindcss";
@import "flowbite/src/themes/default";
/* For WebKit-based browsers */
.custom-scrollbar::-webkit-scrollbar {
width: 15px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: transparent;
/* or a color of your choice */
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background-color: #a0aec0;
/* Customize thumb color */
border-radius: 4px;
border: 2px solid transparent;
/* Optional: creates padding around thumb */
background-clip: content-box;
}
/* For Firefox */
.custom-scrollbar {
scrollbar-width: auto;
/* "auto" or "thin" */
scrollbar-color: #37A0EA transparent;
/* thumb and track colors */
}
+2 -23
View File
@@ -1,5 +1,4 @@
import React from "react"; import React from "react";
import { FcGoogle } from "react-icons/fc";
import { FiEye, FiEyeOff } from "react-icons/fi"; import { FiEye, FiEyeOff } from "react-icons/fi";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -16,19 +15,7 @@ const Login = () => {
<h1 className="text-2xl font-bold mb-6 text-gray-900 text-center"> <h1 className="text-2xl font-bold mb-6 text-gray-900 text-center">
Log in Log in
</h1> </h1>
<button className="flex items-center justify-center w-full py-3 mb-4 border border-gray-300 rounded-lg hover:bg-gray-50">
<FcGoogle className="text-xl mr-2" />
<span className="text-gray-700 font-medium">
Continue with Google
</span>
</button>
<div className="flex items-center my-4">
<div className="flex-grow border-t border-gray-300" />
<span className="px-2 text-gray-500 text-sm">
Or login with email
</span>
<div className="flex-grow border-t border-gray-300" />
</div>
<div className="mb-4"> <div className="mb-4">
<div className="flex items-center"> <div className="flex items-center">
<input <input
@@ -38,14 +25,6 @@ const Login = () => {
className="w-full border border-gray-300 rounded-l-lg px-4 py-4 focus:outline-none focus:border-blue-500" className="w-full border border-gray-300 rounded-l-lg px-4 py-4 focus:outline-none focus:border-blue-500"
/> />
</div> </div>
<div className="mb-6">
<Link
to="#!"
className="text-sm text-blue-600 hover:underline inline-block text-center"
>
Login via OTP
</Link>
</div>
</div> </div>
<div className="mb-1"> <div className="mb-1">
<div className="relative"> <div className="relative">
@@ -58,7 +37,7 @@ const Login = () => {
<button <button
type="button" type="button"
onClick={togglePassword} onClick={togglePassword}
className="absolute right-2 top-2 text-gray-500 hover:text-gray-700" className="absolute right-2 top-4 text-2xl text-gray-500 hover:text-gray-700"
> >
{showPassword ? <FiEyeOff /> : <FiEye />} {showPassword ? <FiEyeOff /> : <FiEye />}
</button> </button>
+3 -3
View File
@@ -1,5 +1,5 @@
// eslint-disable-next-line no-unused-vars
import React, { useState } from "react"; import React, { useState } from "react";
import { FcGoogle } from "react-icons/fc";
import { FiEye, FiEyeOff } from "react-icons/fi"; import { FiEye, FiEyeOff } from "react-icons/fi";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -40,7 +40,7 @@ const SignUp = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword(!showPassword)} onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-3 text-gray-500 hover:text-gray-700" className="absolute right-3 top-4 text-2xl text-gray-500 hover:text-gray-700"
> >
{showPassword ? <FiEyeOff /> : <FiEye />} {showPassword ? <FiEyeOff /> : <FiEye />}
</button> </button>
@@ -56,7 +56,7 @@ const SignUp = () => {
<button <button
type="button" type="button"
onClick={() => setShowConfirmPassword(!showConfirmPassword)} onClick={() => setShowConfirmPassword(!showConfirmPassword)}
className="absolute right-3 top-3 text-gray-500 hover:text-gray-700" className="absolute right-3 top-4 text-2xl text-gray-500 hover:text-gray-700"
> >
{showConfirmPassword ? <FiEyeOff /> : <FiEye />} {showConfirmPassword ? <FiEyeOff /> : <FiEye />}
</button> </button>
+19 -25
View File
@@ -1,6 +1,5 @@
import React from "react"; import React from "react";
import Footer from "../components/Footer"; import Footer from "../components/Footer";
{ {
/* <img src="vector.png" alt="" className="h-100" /> */ /* <img src="vector.png" alt="" className="h-100" /> */
} }
@@ -10,31 +9,26 @@ const DrivethruLandingPage = () => {
<div className="min-h-screen bg-white overflow-hidden"> <div className="min-h-screen bg-white overflow-hidden">
<div className="bg-white min-h-screen flex items-center relative"> <div className="bg-white min-h-screen flex items-center relative">
<div className="container mx-auto px-6 relative z-10"> <div className="container mx-auto px-6 relative z-10">
<div className="flex flex-col md:flex-row items-center">
<div className="w-full bg-gray-100 shadow-md py-4 px-6 flex justify-between items-center mt-5"> <div className="hidden md:block md:w-1/2 lg:w-3/5"></div>
<h1 className="text-xl font-bold">Drive-thru</h1>
<div className="flex space-x-6">
<a href="#features" className="text-gray-700 hover:text-black">Key Features</a>
<a href="#how-it-works" className="text-gray-700 hover:text-black">How It Works</a>
</div>
</div>
<div className="flex flex-col md:flex-row items-center justify-between w-full min-h-screen">
{/* <div className="hidden md:block md:w-1/2 lg:w-3/5"></div> */}
<div className="flex items-center justify-center">
<img src="data:image/png;base64,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" alt="cloud image" className="flex justify-center my-6 mx-7 w-full h-auto" />
</div>
<div className="w-full mt-70 md:w-1/2 lg:w-2/5 max-w-lg bg-transparent"> <div className="w-full mt-70 md:w-1/2 lg:w-2/5 max-w-lg bg-transparent">
<div className="flex items-center mb-8"> <div className="flex items-center mb-8">
<div className="text-cyan-400 mr-3">
<img src="/image.png" alt="logo" className="h-auto w-12" /> <svg
className="w-12 h-12"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 2L2 12L12 22L22 12L12 2Z"
stroke="currentColor"
strokeWidth="3"
fill="none"
/>
</svg>
</div>
<h1 className="text-5xl font-bold text-black">Drive-thru</h1> <h1 className="text-5xl font-bold text-black">Drive-thru</h1>
</div> </div>
@@ -73,7 +67,7 @@ const DrivethruLandingPage = () => {
</div> </div>
{/* Features Card */} {/* Features Card */}
<div className="w-full md:w-1/2 lg:w-3/5 mb-12 md:mb-0"> <div className="w-full md:w-1/2 lg:w-3/5 mb-12 md:mb-0">
<div className="bg-blue-100 rounded-3xl p-8 md:p-10 shadow-lg" id="features"> <div className="bg-blue-100 rounded-3xl p-8 md:p-10 shadow-lg">
<h2 className="text-3xl font-bold mb-8">Key Features</h2> <h2 className="text-3xl font-bold mb-8">Key Features</h2>
<div className="space-y-6"> <div className="space-y-6">
@@ -182,7 +176,7 @@ const DrivethruLandingPage = () => {
{/* How It Works Card */} {/* How It Works Card */}
<div className="w-full md:w-1/2 lg:w-3/5"> <div className="w-full md:w-1/2 lg:w-3/5">
<div className="bg-blue-100 rounded-3xl p-8 md:p-10 shadow-lg" id="how-it-works"> <div className="bg-blue-100 rounded-3xl p-8 md:p-10 shadow-lg">
<h2 className="text-3xl font-bold mb-8">How It Works</h2> <h2 className="text-3xl font-bold mb-8">How It Works</h2>
<div className="space-y-6"> <div className="space-y-6">
+111
View File
@@ -0,0 +1,111 @@
import React from "react";
import Sidebar from "../../components/Sidebar";
import FileList from "../../components/FileList";
import FileUpload from "../../components/FileUpload";
import { FiPlus } from "react-icons/fi";
const Dashboard = () => {
const [files, setFiles] = React.useState([]);
React.useEffect(() => {
const fetchData = async () => {
const response = await fetch(
"http://192.168.29.61:8080/api/hdfs/listFiles?hdfsPath=/"
);
const data = await response.json();
setFiles(data);
};
fetchData();
}, []);
return (
<>
{/* <!-- Main modal --> */}
<div
id="static-modal"
data-modal-backdrop="static"
tabindex="-1"
aria-hidden="true"
class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full"
>
<div class="relative p-4 w-full max-w-170 h-150 flex items-center justify-center">
{/* <!-- Modal content --> */}
<div class="relative bg-white rounded-lg shadow-sm ">
{/* <!-- Modal header --> */}
<div class="flex items-center justify-between p-2 md:p-5 rounded-t dark:border-gray-600 border-gray-200">
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">
Static modal
</h3>
<button
type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
data-modal-hide="static-modal"
>
<svg
class="w-3 h-3"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 14 14"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
/>
</svg>
<span class="sr-only">Close modal</span>
</button>
</div>
{/* <!-- Modal body --> */}
<div class="p-4 md:p-5 space-y-4">
<FileUpload />
</div>
{/* <!-- Modal footer --> */}
{/* <div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b ">
<button
data-modal-hide="static-modal"
type="button"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
I accept
</button>
<button
data-modal-hide="static-modal"
type="button"
class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
>
Decline
</button>
</div> */}
</div>
</div>
</div>
<Sidebar />
<div className="p-4 sm:ml-64">
<div className="p-4 border-2 border-gray-200 border-dashed rounded-lg mt-14">
<div className="w-full flex justify-between items-center">
<h1 className="text-2xl font-bold mb-4">Dashboard</h1>
<button
data-modal-target="static-modal"
data-modal-toggle="static-modal"
class="block text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-2 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
type="button"
>
<FiPlus className="text-2xl" />
</button>
</div>
<FileList files={files}></FileList>
<section className="w-full flex justify-end items-center min-h-160">
{/* <!-- Modal toggle --> */}
</section>
</div>
</div>
</>
);
};
export default Dashboard;
@@ -0,0 +1,376 @@
import Footer from "../../components/Footer";
import React from "react";
import { useState, useEffect } from "react";
import { Link } from "react-router-dom";
const DrivethruLandingPage = () => {
const features = [
{
title: "Easy Upload & Access",
description: "Drag & drop, instant access.",
icon: (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l3 3m0 0l3-3m-3 3V10"
/>
</svg>
),
},
{
title: "Secure & Private",
description: "End-to-end encryption.",
icon: (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
),
},
{
title: "Seamless Sharing",
description: "Share files with one click.",
icon: (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"
/>
</svg>
),
},
{
title: "Access Anywhere",
description: "Works on all devices.",
icon: (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h.5A2.5 2.5 0 0020 5.5v-1.65"
/>
</svg>
),
},
];
const howItWorks = [
{
title: "Create an account",
description: "Sign up in seconds.",
icon: (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
),
},
{
title: "Upload files",
description: "Drag & drop or select from your device.",
icon: (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"
/>
</svg>
),
},
{
title: "Manage files",
description: "Rename, move, or delete easily.",
icon: (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
),
},
{
title: "Access anytime",
description: "Open files from any device.",
icon: (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
),
},
];
// UseEffect and handle....click function to handle set and handle the animation of features..
const [activeIndex, setActiveIndex] = useState(0);
const [isPaused, setIsPaused] = useState(false);
useEffect(() => {
if (!isPaused) {
const interval = setInterval(() => {
setActiveIndex((prevIndex) => (prevIndex + 1) % features.length);
}, 3000);
return () => clearInterval(interval);
}
}, [isPaused, features.length]);
// Handle user interaction
const handleFeatureClick = (index) => {
setActiveIndex(index);
setIsPaused(true);
setTimeout(() => setIsPaused(false), 1000);
};
const [activeIndex1, setActiveIndex1] = useState(0);
const [isPaused1, setIsPaused1] = useState(false);
useEffect(() => {
if (!isPaused1) {
const interval = setInterval(() => {
setActiveIndex1((prevIndex) => (prevIndex + 1) % howItWorks.length);
}, 3000);
return () => clearInterval(interval);
}
}, [isPaused1, howItWorks.length]);
const handleFeatureClick1 = (index) => {
setActiveIndex1(index);
setIsPaused1(true);
setTimeout(() => setIsPaused1(false), 1000);
};
return (
<div className="min-h-screen overflow-x-hidden bg-white">
{/* Hero Section */}
<div
id="about"
className="bg-gradient-to-r from-blue-50 to-white min-h-[90vh] flex items-center relative"
>
<div className="container mx-auto px-4 md:px-6 lg:px-8 relative z-10">
<div className="flex flex-col md:flex-row items-center gap-8 lg:gap-12">
{/* Left Side - Text Content */}
<div className="w-full md:w-1/2 text-center md:text-left order-1 md:order-1">
<div className="flex justify-center md:justify-start items-center mb-6 lg:mb-8">
<div className="text-cyan-400 mr-2 md:mr-3">
<svg
className="w-10 md:w-12 h-10 md:h-12"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 2L2 12L12 22L22 12L12 2Z"
stroke="currentColor"
strokeWidth="3"
fill="none"
/>
</svg>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-black">
Drive-thru
</h1>
</div>
<h2 className="text-xl md:text-2xl font-bold mb-4 md:mb-6 text-black">
Store, Access & Share Your Files Anytime, Anywhere!
</h2>
<p className="text-gray-800 mb-6 md:mb-10 text-base md:text-lg">
A simple, secure, and fast cloud storage solution for all your
files. Upload, organize, and access with ease.
</p>
{/* Buttons */}
<div className="flex flex-col sm:flex-row justify-center md:justify-start space-y-4 sm:space-y-0 sm:space-x-4">
<Link
to="/signup"
className="bg-emerald-500 hover:bg-emerald-600 text-white font-medium rounded-full px-6 py-4 md:px-8 md:py-6 transform hover:scale-105 transition-all duration-300 shadow-lg hover:shadow-xl"
>
Get Started
</Link>
<Link
to="/login"
className="bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-full px-6 py-4 md:px-8 md:py-6 transform hover:scale-105 transition-all duration-300 shadow-lg hover:shadow-xl"
>
Login
</Link>
</div>
</div>
{/* Right Side - Image */}
<div className="w-full md:w-1/2 flex justify-center order-2 md:order-1">
<div className="relative p-4 bg-gradient-to-r from-blue-50 to-emerald-50 rounded-2xl max-w-xs sm:max-w-lg md:max-w-md lg:max-w-lvh">
<img
src="/Dashboard.png"
alt="Drive-thru Dashboard Interface"
className="w-full rounded-xl shadow-2xl transition-shadow duration-300"
/>
<div className="absolute inset-0 bg-gradient-to-r from-blue-500/5 to-emerald-500/5 rounded-2xl pointer-events-none"></div>
</div>
</div>
</div>
</div>
</div>
{/* Features Section */}
<div
id="features"
className="w-full max-w-5xl mx-auto p-6 sm:p-8 bg-gray-100 rounded-lg shadow-lg"
>
<h2 className="text-3xl font-bold text-center mb-8">Key Features</h2>
<div className="flex flex-col-reverse md:flex-row items-center gap-8 lg:gap-12">
{/* Left Side - Image */}
<div className="w-full md:w-1/2 flex justify-center">
<img
src="/He.png"
alt="Feature Illustration"
className="w-full max-w-xs sm:max-w-sm md:max-w-md lg:max-w-lg object-contain rounded-lg shadow-md"
/>
</div>
{/* Right Side - Feature List */}
<div className="w-full md:w-1/2">
<div className="space-y-6">
{features.map((feature, index) => (
<div
key={index}
className={`p-5 border-2 rounded-lg cursor-pointer transition-all duration-500 ${
index === activeIndex
? "border-blue-500 bg-white shadow-lg scale-105"
: "border-gray-300"
}`}
onClick={() => handleFeatureClick(index)}
>
<div className="flex items-center space-x-4">
{feature.icon}
<h3 className="text-lg font-semibold">{feature.title}</h3>
</div>
{index === activeIndex && (
<p className="text-gray-600 mt-3 transition-opacity duration-500 opacity-100">
{feature.description}
</p>
)}
</div>
))}
</div>
</div>
</div>
</div>
{/* How It Works Section */}
<div
id="howItWorks"
className="w-full max-w-5xl mx-auto p-6 sm:p-8 bg-gray-100 rounded-lg shadow-lg"
>
<h2 className="text-3xl font-bold text-center mb-8">How It Works</h2>
<div className="flex flex-col md:flex-row items-center gap-8 lg:gap-12">
{/* Left Side - Feature List */}
<div className="w-full md:w-1/2">
<div className="space-y-6">
{howItWorks.map((howItWork, index) => (
<div
key={index}
className={`p-5 border-2 rounded-lg cursor-pointer transition-all duration-500 ${
index === activeIndex1
? "border-blue-500 bg-white shadow-lg scale-105"
: "border-gray-300"
}`}
onClick={() => handleFeatureClick1(index)}
>
<div className="flex items-center space-x-4">
{howItWork.icon}
<h3 className="text-lg font-semibold">{howItWork.title}</h3>
</div>
{index === activeIndex1 && (
<p className="text-gray-600 mt-3 transition-opacity duration-500 opacity-100">
{howItWork.description}
</p>
)}
</div>
))}
</div>
</div>
{/* Right Side - Image */}
<div className="w-full md:w-1/2 flex justify-center">
<img
src="/She.png"
alt="Feature Illustration"
className="w-full max-w-xs sm:max-w-sm md:max-w-md lg:max-w-lg object-contain rounded-lg shadow-md"
/>
</div>
</div>
</div>
<Footer />
</div>
);
};
export default DrivethruLandingPage;
@@ -0,0 +1,32 @@
import { Link } from "react-router-dom";
const NotFoundPage = () => {
return (
<div className="flex flex-col items-center justify-center h-screen bg-gray-100 p-4">
{/* Placeholder SVG - Replace this with your SVG */}
<img
src="/404.png"
style={{ width: "30%", height: "auto" }}
alt="404 Not Found"
></img>
{/* Page number and title */}
<h2 className="text-2xl font-bold mb-4 mt-4">Page Not Found</h2>
{/* Description text */}
<p className="text-center text-gray-700 mb-6">
Sorry, we couldn&apos;t find the page you were looking for. It may have
been moved or deleted.
</p>
{/* Call-to-action button */}
<Link
to="/"
className="px-6 py-2 bg-[#1877F2] text-white rounded hover:bg-blue-600 transition duration-200"
>
Go Home
</Link>
</div>
);
};
export default NotFoundPage;
View File
+34
View File
@@ -0,0 +1,34 @@
// utils/api.js
export const uploadFileToHDFS = async (
file,
hdfsPath,
uploadedFileName,
username
) => {
const formData = new FormData();
formData.append("file", file);
formData.append("hdfsPath", "/kalas");
formData.append("uploadedFileName", uploadedFileName);
formData.append("username", "kalas");
try {
const response = await fetch(
"http://192.168.29.61:8080/api/hdfs/uploadFile",
{
method: "POST",
body: formData,
}
);
if (response.ok) {
const data = await response.json(); // or response.json() if JSON is returned
console.log("Response:", data);
} else {
console.error("Upload failed with status:", response.status);
}
} catch (error) {
console.error("Error uploading file:", error);
alert("An error occurred while uploading the file.");
}
};
+8 -1
View File
@@ -4,6 +4,13 @@ import tailwindcss from '@tailwindcss/vite'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react(), tailwindcss(), plugins: [
react(),
tailwindcss(),
], ],
server: {
host: 'localhost',
port: 5173,
},
}) })
+6
View File
@@ -0,0 +1,6 @@
{
"name": "cc-mini",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}