diff --git a/frontend/.gitignore b/.gitignore similarity index 85% rename from frontend/.gitignore rename to .gitignore index 0563835d..106a295f 100644 --- a/frontend/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies -/node_modules -/.pnp +node_modules +.pnp .pnp.js .yarn/install-state.gz @@ -10,11 +10,11 @@ /coverage # next.js -/.next/ -/out/ +.next/ +out/ # production -/build +build # misc .DS_Store @@ -33,4 +33,7 @@ yarn-error.log* # typescript *.tsbuildinfo -next-env.d.ts \ No newline at end of file +next-env.d.ts + +env +venv \ No newline at end of file diff --git a/frontend/.env b/frontend/.env new file mode 100644 index 00000000..e2fa391f --- /dev/null +++ b/frontend/.env @@ -0,0 +1,2 @@ +REACT_APP_BASE_URL=http://127.0.0.1:8000 + diff --git a/frontend/src/App.js b/frontend/src/App.js index 12636704..b44623c1 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,51 +1,79 @@ import './App.css'; import { BrowserRouter, Route, Routes } from "react-router-dom"; import Navbar from "./components/Navbar"; -import Home from "./pages/Home"; -import Search from './pages/Search'; +import React, { Suspense, useEffect, useState } from 'react'; import { DataProvider } from './context/DataContext'; -import ImageTree from './pages/3DTree'; -import React, { useEffect, useState } from 'react'; -import axios from 'axios'; import { ToastContainer, toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; +import { gql } from '@apollo/client'; +import { useQuery } from '@apollo/client'; + +// Lazy load components +const Home = React.lazy(() => import('./pages/Home')); +const Search = React.lazy(() => import('./pages/Search')); +const ImageTree = React.lazy(() => import('./pages/3DTree')); + +function generateQuery(depth) { + if (depth === 0) { + return ` + rollNo + name + parentId + picture + `; + } + return ` + rollNo + name + parentId + picture + children { + ${generateQuery(depth - 1)} + } + `; +} + +const GET_Query = gql` + query GetNestedTree { + studentTree { + ${generateQuery(10)} + } + } +`; function App() { const [data, setData] = useState([]); - const [error,seterror]=useState(false) - useEffect(() => { - const fetchData = async () => { - try { - const response = await axios.get(`https://devluplabs.iitj.ac.in/ftadmin/tree/`); - setData(response.data); - } catch (error) { - seterror(true) - } - }; - fetchData(); - }, []); - - if(error){ - toast.error("server error",{ - autoClose:20000 - }) - } -// console.log(window.location.pathname) + const [error, setError] = useState(false); + const { error: queryError, data: treeData } = useQuery(GET_Query); + + useEffect(() => { + if (treeData && treeData.studentTree) { + setData(treeData.studentTree); + } + if (queryError) { + setError(true); + toast.error("GraphQL query error", { + autoClose: 20000 + }); + } + }, [treeData, queryError]); + + // if (loading) return

Loading...

; + return ( - - - - - - - } /> - } /> - } /> - - - + + + + + Loading...}> + + } /> + } /> + } /> + + + + ); } diff --git a/frontend/src/assets/Style/team.css b/frontend/src/assets/Style/team.css index b447c86c..a387e084 100644 --- a/frontend/src/assets/Style/team.css +++ b/frontend/src/assets/Style/team.css @@ -1,4 +1,4 @@ -.modalme{ +.modalme { position: fixed; top: 0; left: 0; @@ -8,108 +8,127 @@ display: flex; justify-content: center; align-items: center; + z-index: 1000; } -.modal-contentme{ - padding: 20px; - border-radius: 5px; + +.modal-contentme { + padding: 30px; + border-radius: 10px; color: aliceblue; - font-weight: 900; - justify-content: center; + background: rgba(20, 94, 135, 0.85); + box-shadow: 0 8px 32px 0 rgba(243, 243, 243, 0.37); + max-width: 800px; + width: 90%; +} + +.team-header { + display: flex; + justify-content: space-between; align-items: center; - background: rgba(20, 94, 135, 0.75); -box-shadow: 0 8px 32px 0 rgba(243, 243, 243, 0.37); -border-radius: 10px; + margin-bottom: 20px; + border-bottom: 1px solid rgba(255, 255, 255, 0.2); + padding-bottom: 15px; +} + +.team-header h2 { + margin: 0; + font-size: 1.8rem; +} + +.team-members-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 25px; +} + +.team-member-card { + background: rgba(255, 255, 255, 0.1); + border-radius: 8px; + padding: 20px; + text-align: center; + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.team-member-card:hover { + transform: translateY(-5px); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); +} + +.team-member-card h3 { + margin: 0 0 5px 0; + font-size: 1.2rem; } -.iconsocialmedia{ + +.member-id { + color: rgba(255, 255, 255, 0.8); + margin-bottom: 15px; + font-size: 0.9rem; +} + +.iconsocialmedia { display: flex; justify-content: center; align-items: center; gap: 20px; - color:aliceblue; - } - .closeshomepro{ - position: relative; - top: 0px; - right:0px !important; - cursor: pointer; - color:aliceblue; - } + margin-top: 15px; +} + +.iconsocialmedia a { + transition: transform 0.2s ease; +} +.iconsocialmedia a:hover { + transform: scale(1.2); +} +.closeshomepro { + cursor: pointer; + color: aliceblue; + transition: transform 0.2s ease; +} -/* Popup.css */ -.modalhelp { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - backdrop-filter: blur(3px); - display: flex; - justify-content: center; - align-items: center; +.closeshomepro:hover { + transform: scale(1.1); + color: #a3a3a3; } .visible { - animation: movedown 1s forwards; + animation: movedown 0.5s forwards; } .notvisible { - animation: moveup 1s forwards; + animation: moveup 0.5s forwards; } @keyframes movedown { - 0% { - transform: translateY(-400px); - /* Start position: move up by 100px */ - } - - 60% { - transform: translateY(100px); - /* End position: move down to original position */ - } - - 100% { - transform: translateY(0); - /* End position: move down to original position */ - } + 0% { + transform: translateY(-400px); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } } @keyframes moveup { - 100% { - transform: translateY(-400px); - /* Start position: move up by 100px */ - } - - 0% { - transform: translateY(0); - /* End position: move down to original position */ - } -} - -.modal-contenthelp { - /* background-color: rgba(255, 255, 255, 0.338); */ - padding: 20px; - width: 400px; - border-radius: 5px; - box-shadow: 0 0 10px rgba(20, 20, 20, 0.3); - color: aliceblue; - font-weight: 900; - - background: rgba(14, 14, 14, 0.4); - box-shadow: 0 8px 32px 0 rgba(243, 243, 243, 0.37); - border-radius: 10px; -} - -.closes { - position: relative; - top: 0px; - right: 0px !important; - cursor: pointer; -} - -@media screen and (max-width: 600px) { - .modal-contenthelp { - width: 250px; - } -} \ No newline at end of file + 0% { + transform: translateY(0); + opacity: 1; + } + 100% { + transform: translateY(-400px); + opacity: 0; + } +} + +@media screen and (max-width: 768px) { + .team-members-grid { + grid-template-columns: 1fr; + } + + .modal-contentme { + width: 85%; + padding: 20px; + } +} diff --git a/frontend/src/assets/Style/tree.css b/frontend/src/assets/Style/tree.css index 62136dad..f1d78f1d 100644 --- a/frontend/src/assets/Style/tree.css +++ b/frontend/src/assets/Style/tree.css @@ -12,23 +12,7 @@ position: relative; display: block; } -.container_JYOTIN{ - border: 3px solid #ffffff; - box-shadow: 2px 2px 5px black; - /* padding: 10px 10px; */ - color: #ffffff; - font-family: arial, verdana, tahoma; - font-size: 20px; - display: inline-block; - border-radius: 20px; - transition: all 0.5s; - -webkit-transition: all 0.5s; - -moz-transition: all 0.5s; - cursor: pointer; - width: 100px; - height: 120px; - background-color: #3574b4; -} + .tree_ li { float: left; text-align: center; diff --git a/frontend/src/components/2DTree.jsx b/frontend/src/components/2DTree.jsx index 5ea4dd9b..e4eb901f 100644 --- a/frontend/src/components/2DTree.jsx +++ b/frontend/src/components/2DTree.jsx @@ -1,52 +1,115 @@ -import React, { useState } from 'react'; -import Tree from 'react-d3-tree'; -import '../assets/Style/home.css' -import { CircularProgressbar } from 'react-circular-progressbar'; -import 'react-circular-progressbar/dist/styles.css'; -import Profile from './Profile'; +import React, { useState, useRef, useEffect } from "react"; +import Tree from "react-d3-tree"; +import "../assets/Style/home.css"; +import { CircularProgressbar } from "react-circular-progressbar"; +import "react-circular-progressbar/dist/styles.css"; +// import Profile from "./Profile"; +import { useData } from "../context/DataContext"; +import { useNavigate } from "react-router-dom"; const TwoDTree = ({ data }) => { - const [roll, setroll] = useState() - const [showModal, setShowModal] = useState(false); + // const [roll, setroll] = useState(); + // const [showModal, setShowModal] = useState(false); + const [dimensions, setDimensions] = useState({ width: 800, height: 600 }); + const treeContainerRef = useRef(null); const value = 0.5; + const { search } = useData(); + const searchNode = useRef(); + const navigate = useNavigate(); - if (!data) return
+ useEffect(() => { + const setInitialDimensions = () => { + if (treeContainerRef.current) { + const { width, height } = + treeContainerRef.current.getBoundingClientRect(); + setDimensions({ width, height }); + } + }; - const new_data = [] + setInitialDimensions(); + window.addEventListener("resize", setInitialDimensions); + return () => window.removeEventListener("resize", setInitialDimensions); + }, []); + + useEffect(() => { + searchNode.current = document.getElementById(search); + // console.log(searchNode); + if (searchNode.current) { + // Trigger programmatic click + const clickEvent = new MouseEvent("click", { + bubbles: true, + cancelable: true, + view: window, + }); + searchNode.current.dispatchEvent(clickEvent); + } + },[search]) + + if (!data) + return ( +
+ +
+ ); + + const new_data = []; const all_parent = { - name: 'All', - children: [] - } - data.forEach(item => { + name: "All", + children: [], + }; + data.forEach((item) => { all_parent.children.push(item); }); - new_data.push(all_parent) + new_data.push(all_parent); + + // const handleNodeMouseOver = (nodeDatum) => { + // // console.log(search); + // if (nodeDatum.name !== "All") { + // setroll(nodeDatum); + // setShowModal(true); + // } + // }; + + // const handleNodeMouseOut = (nodeData) => { + // if (nodeData.name !== "All") { + // setShowModal(false); + // } + // }; + + const renderCustom = ({ nodeDatum, toggleNode }) => { + const str = nodeDatum.name; + const name = str.slice(0, 19) + ""; - const renderCustom = ({ nodeDatum, toggleNode, links }) => { - const str = nodeDatum.name - const name = str.slice(0, 19) + '' return ( handleNodeMouseOut(nodeDatum)} - onMouseOver={() => handleNodeMouseOver(nodeDatum)} + onClick={toggleNode} + // onMouseOut={() => handleNodeMouseOut(nodeDatum)} + // onMouseOver={() => handleNodeMouseOver(nodeDatum)} + id={nodeDatum.rollNo} > - - - {name} + { + console.log(nodeDatum.rollNo); + navigate(`/search?q=${window.btoa(nodeDatum.rollNo)}`); + } + }/> + + {name} + + ); + }; - ) - } const getLinkColor = (link) => { - if (link.source.name.includes('root')) { - return 'white'; + if (link.source.name.includes("root")) { + return "white"; } - return 'white'; + return "white"; }; const getLinkProps = (link) => ({ @@ -54,54 +117,36 @@ const TwoDTree = ({ data }) => { strokeWidth: 10, }); - const handleNodeMouseOver = (nodeDatum, event) => { - if (nodeDatum.name !== 'All') { - setroll(nodeDatum) - setShowModal(true) - - } - }; - const handleNodeMouseOut = (nodeData, event) => { - if (nodeData.name !== 'All') { - setShowModal(false) - } - }; - const dimensions = { - width: 800, - height: 600 - }; return ( <> - {showModal && ( - - )} - 'custom-link'} - renderCustomNodeElement={renderCustom} - transitionDuration={500} - shouldCollapseNeighborNodes={true} - separation={{ siblings: 2, nonSiblings: 2 }} - // renderCustomLinkElement={renderCustomLink} - - /> + {/* {showModal && } */} +
+ + renderCustom({ + ...rd3tProps, + toggleNode: () => { + rd3tProps.toggleNode(); + }, + }) + } + transitionDuration={500} + shouldCollapseNeighborNodes={true} + separation={{ siblings: 2, nonSiblings: 2 }} + /> +
- ) -} + ); +}; -export default TwoDTree +export default TwoDTree; diff --git a/frontend/src/components/Family.jsx b/frontend/src/components/Family.jsx index d677a15c..385b3a06 100644 --- a/frontend/src/components/Family.jsx +++ b/frontend/src/components/Family.jsx @@ -60,12 +60,12 @@ const IitjTree = ({ data }) => {