diff --git a/next.config.ts b/next.config.ts index 632c71d..07f645e 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,25 +1,30 @@ -import type { NextConfig } from "next"; - -const nextConfig: NextConfig = { +const nextConfig = { eslint: { - ignoreDuringBuilds: true, + ignoreDuringBuilds: true, }, + images: { remotePatterns: [ - { protocol: "https", - hostname: "res.cloudinary.com", + hostname: "res.cloudinary.com", + }, + { + protocol: "https", + hostname: "picsum.photos", }, - { protocol: "https", hostname: "picsum.photos" }, ], }, - async headers() { + + async headers() { return [ { - source: '/team/:path*', + source: "/team/:path*", headers: [ - { key: 'Access-Control-Allow-Origin', value: '*' }, + { + key: "Access-Control-Allow-Origin", + value: "*", + }, ], }, ]; diff --git a/package-lock.json b/package-lock.json index 48f8728..979315a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,19 +15,21 @@ "@tsparticles/react": "^3.0.0", "@tsparticles/slim": "^3.9.1", "cloudinary": "^2.7.0", - "framer-motion": "^12.23.24", + "clsx": "^2.1.1", + "framer-motion": "^12.25.0", "gl-matrix": "^3.4.4", "gsap": "^3.13.0", "lucide-react": "^0.548.0", "mongoose": "^8.19.1", "motion": "^12.23.24", - "next": "15.5.4", + "next": "^16.1.1", "react": "19.1.0", "react-awesome-reveal": "^4.3.1", "react-dom": "19.1.0", "react-icons": "^5.5.0", "react-type-animation": "^3.2.0", - "react-typed": "^2.0.12" + "react-typed": "^2.0.12", + "tailwind-merge": "^3.4.0" }, "devDependencies": { "@eslint/eslintrc": "^3", @@ -1100,9 +1102,9 @@ } }, "node_modules/@next/env": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.4.tgz", - "integrity": "sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.1.tgz", + "integrity": "sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -1116,9 +1118,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.4.tgz", - "integrity": "sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.1.tgz", + "integrity": "sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA==", "cpu": [ "arm64" ], @@ -1132,9 +1134,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.4.tgz", - "integrity": "sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.1.tgz", + "integrity": "sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw==", "cpu": [ "x64" ], @@ -1148,9 +1150,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.4.tgz", - "integrity": "sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.1.tgz", + "integrity": "sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ==", "cpu": [ "arm64" ], @@ -1164,9 +1166,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.4.tgz", - "integrity": "sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.1.tgz", + "integrity": "sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg==", "cpu": [ "arm64" ], @@ -1180,9 +1182,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.4.tgz", - "integrity": "sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.1.tgz", + "integrity": "sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ==", "cpu": [ "x64" ], @@ -1196,9 +1198,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.4.tgz", - "integrity": "sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.1.tgz", + "integrity": "sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA==", "cpu": [ "x64" ], @@ -1212,9 +1214,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.4.tgz", - "integrity": "sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.1.tgz", + "integrity": "sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA==", "cpu": [ "arm64" ], @@ -1228,9 +1230,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.4.tgz", - "integrity": "sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.1.tgz", + "integrity": "sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw==", "cpu": [ "x64" ], @@ -3223,6 +3225,15 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.14", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", + "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/bidi-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", @@ -3427,6 +3438,15 @@ "node": ">=9" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4491,13 +4511,13 @@ } }, "node_modules/framer-motion": { - "version": "12.23.24", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz", - "integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==", + "version": "12.25.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.25.0.tgz", + "integrity": "sha512-mlWqd0rApIjeyhTCSNCqPYsUAEhkcUukZxH3ke6KbstBRPcxhEpuIjmiUQvB+1E9xkEm5SpNHBgHCapH/QHTWg==", "license": "MIT", "dependencies": { - "motion-dom": "^12.23.23", - "motion-utils": "^12.23.6", + "motion-dom": "^12.24.11", + "motion-utils": "^12.24.10", "tslib": "^2.4.0" }, "peerDependencies": { @@ -6060,18 +6080,18 @@ } }, "node_modules/motion-dom": { - "version": "12.23.23", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", - "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==", + "version": "12.24.11", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.24.11.tgz", + "integrity": "sha512-DlWOmsXMJrV8lzZyd+LKjG2CXULUs++bkq8GZ2Sr0R0RRhs30K2wtY+LKiTjhmJU3W61HK+rB0GLz6XmPvTA1A==", "license": "MIT", "dependencies": { - "motion-utils": "^12.23.6" + "motion-utils": "^12.24.10" } }, "node_modules/motion-utils": { - "version": "12.23.6", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", - "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", + "version": "12.24.10", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.24.10.tgz", + "integrity": "sha512-x5TFgkCIP4pPsRLpKoI86jv/q8t8FQOiM/0E8QKBzfMozWHfkKap2gA1hOki+B5g3IsBNpxbUnfOum1+dgvYww==", "license": "MIT" }, "node_modules/mpath": { @@ -6153,13 +6173,14 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.4.tgz", - "integrity": "sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/next/-/next-16.1.1.tgz", + "integrity": "sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w==", "license": "MIT", "dependencies": { - "@next/env": "15.5.4", + "@next/env": "16.1.1", "@swc/helpers": "0.5.15", + "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" @@ -6168,18 +6189,18 @@ "next": "dist/bin/next" }, "engines": { - "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.5.4", - "@next/swc-darwin-x64": "15.5.4", - "@next/swc-linux-arm64-gnu": "15.5.4", - "@next/swc-linux-arm64-musl": "15.5.4", - "@next/swc-linux-x64-gnu": "15.5.4", - "@next/swc-linux-x64-musl": "15.5.4", - "@next/swc-win32-arm64-msvc": "15.5.4", - "@next/swc-win32-x64-msvc": "15.5.4", - "sharp": "^0.34.3" + "@next/swc-darwin-arm64": "16.1.1", + "@next/swc-darwin-x64": "16.1.1", + "@next/swc-linux-arm64-gnu": "16.1.1", + "@next/swc-linux-arm64-musl": "16.1.1", + "@next/swc-linux-x64-gnu": "16.1.1", + "@next/swc-linux-x64-musl": "16.1.1", + "@next/swc-win32-arm64-msvc": "16.1.1", + "@next/swc-win32-x64-msvc": "16.1.1", + "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -7444,6 +7465,16 @@ "react": ">=17.0" } }, + "node_modules/tailwind-merge": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", + "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "4.1.14", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.14.tgz", diff --git a/package.json b/package.json index 6371f3c..5dffc79 100644 --- a/package.json +++ b/package.json @@ -16,19 +16,21 @@ "@tsparticles/react": "^3.0.0", "@tsparticles/slim": "^3.9.1", "cloudinary": "^2.7.0", - "framer-motion": "^12.23.24", + "clsx": "^2.1.1", + "framer-motion": "^12.25.0", "gl-matrix": "^3.4.4", "gsap": "^3.13.0", "lucide-react": "^0.548.0", "mongoose": "^8.19.1", "motion": "^12.23.24", - "next": "15.5.4", + "next": "^16.1.1", "react": "19.1.0", "react-awesome-reveal": "^4.3.1", "react-dom": "19.1.0", "react-icons": "^5.5.0", "react-type-animation": "^3.2.0", - "react-typed": "^2.0.12" + "react-typed": "^2.0.12", + "tailwind-merge": "^3.4.0" }, "devDependencies": { "@eslint/eslintrc": "^3", diff --git a/src/app/components/Home.jsx b/src/app/components/Home.jsx index ec035a2..d8167e8 100644 --- a/src/app/components/Home.jsx +++ b/src/app/components/Home.jsx @@ -241,11 +241,10 @@ import { Canvas } from "@react-three/fiber"; import { OrbitControls } from "@react-three/drei"; import { Sphere, Line } from "@react-three/drei"; -import { useRef } from "react"; +import { useRef, useMemo } from "react"; import { useFrame } from "@react-three/fiber"; import { EffectComposer, Bloom } from "@react-three/postprocessing"; import { motion } from "framer-motion"; -import { ReactTyped } from "react-typed"; import Navbar from "./Navbar"; const Glow = ({ className = "" }) => ( @@ -255,20 +254,24 @@ const Glow = ({ className = "" }) => ( /> ); -function AnimatedNeuralNode({ position, color, size = 0.08 }) { +// Navbar placeholder + + +function AnimatedNeuralNode({ position, color, size = 0.08, delay = 0 }) { const ref = useRef(); useFrame((state) => { if (ref.current) { - // Subtle pulsing animation - ref.current.scale.x = 1 + Math.sin(state.clock.elapsedTime * 2) * 0.1; - ref.current.scale.y = 1 + Math.sin(state.clock.elapsedTime * 2) * 0.1; - ref.current.scale.z = 1 + Math.sin(state.clock.elapsedTime * 2) * 0.1; + // Subtle pulsing animation with individual delay + const time = state.clock.elapsedTime + delay; + ref.current.scale.x = 1 + Math.sin(time * 2) * 0.15; + ref.current.scale.y = 1 + Math.sin(time * 2) * 0.15; + ref.current.scale.z = 1 + Math.sin(time * 2) * 0.15; } }); return ( - + ); } - +// Add this component after the imports +function ElectricCircuitBackground() { + return ( + + {/* Main circuit grid */} + + + {/* Floating circuit lines */} + {Array.from({ length: 20 }).map((_, i) => { + const x = (Math.random() - 0.5) * 40; + const y = (Math.random() - 0.5) * 40; + const length = 3 + Math.random() * 5; + + return ( + + ); + })} + + {/* Circuit nodes */} + {Array.from({ length: 30 }).map((_, i) => ( + + + + ))} + + ); +} function NeuralStructure({ position = [0, 0, 0], color = "#00faff", - nodeCount = 18, // Fixed node count instead of random + structureIndex = 0, }) { - const nodes = useRef([]); - - if (nodes.current.length === 0) { + // Generate fixed node positions based on structure index + const nodes = useMemo(() => { + const nodePositions = []; + const nodeCount = 12; + const radius = 1.2; + + // Create a spherical distribution of nodes for (let i = 0; i < nodeCount; i++) { - nodes.current.push([ - (Math.random() - 0.5) * 3, - (Math.random() - 0.5) * 3, - (Math.random() - 0.5) * 3, + const phi = Math.acos(-1 + (2 * i) / nodeCount); + const theta = Math.sqrt(nodeCount * Math.PI) * phi + structureIndex; + + nodePositions.push([ + radius * Math.cos(theta) * Math.sin(phi), + radius * Math.sin(theta) * Math.sin(phi), + radius * Math.cos(phi), ]); } - } + return nodePositions; + }, [structureIndex]); - const connections = []; - for (let i = 0; i < nodeCount; i++) { - const connectionCount = 2 + Math.floor(Math.random() * 2); - const connectedIndices = new Set(); - - while (connectedIndices.size < connectionCount) { - const targetIndex = Math.floor(Math.random() * nodeCount); - if (targetIndex !== i) { - connectedIndices.add(targetIndex); + // Generate fixed connections + const connections = useMemo(() => { + const conns = []; + const nodeCount = nodes.length; + + for (let i = 0; i < nodeCount; i++) { + // Connect to nearest neighbors + const distances = nodes.map((node, j) => ({ + index: j, + distance: Math.hypot( + node[0] - nodes[i][0], + node[1] - nodes[i][1], + node[2] - nodes[i][2] + ), + })); + + distances.sort((a, b) => a.distance - b.distance); + + // Connect to 3 nearest neighbors + for (let j = 1; j <= 3 && j < distances.length; j++) { + const targetIndex = distances[j].index; + if (i < targetIndex) { // Avoid duplicate connections + conns.push([i, targetIndex]); + } } } - - connectedIndices.forEach((targetIndex) => { - connections.push([i, targetIndex]); - }); - } + return conns; + }, [nodes]); return ( - {nodes.current.map((pos, i) => ( - + {nodes.map((pos, i) => ( + ))} {connections.map(([start, end], i) => ( ))} @@ -335,100 +410,221 @@ function NeuralStructure({ } export default function Home() { - const structures = []; const colors = [ - "#00faff", - "#00d9ff", - "#00bfff", - "#1e90ff", - "#007fff", - "#4dffff", + "#00faff", // Cyan + "#00d9ff", // Light blue + "#00bfff", // Sky blue + "#1e90ff", // Dodger blue + "#007fff", // Azure + "#4dffff", // Electric cyan ]; - // Fixed number of structures (18 as requested between 12-24) - const fixedStructureCount = 18; - - for (let i = 0; i < fixedStructureCount; i++) { - structures.push({ - position: [ - (Math.random() - 0.5) * 15, - (Math.random() - 0.5) * 15, - (Math.random() - 0.5) * 15, - ], + // Fixed positions covering entire viewport in 3D space + const structures = useMemo(() => { + const positions = [ + // Top row - Front layer + [-8, 5, 2], + [-4, 6, 2], + [0, 5.5, 2], + [4, 6, 2], + [8, 5, 2], + + // Middle-top row + [-7, 3, 0], + [-3.5, 3.5, 0], + [0, 3, 0], + [3.5, 3.5, 0], + [7, 3, 0], + + // Center row + [-8, 0, -1], + [-4, 0, -1], + [0, 0, -1], + [4, 0, -1], + [8, 0, -1], + + // Middle-bottom row + [-7, -3, 0], + [-3.5, -3.5, 0], + [0, -3, 0], + [3.5, -3.5, 0], + [7, -3, 0], + + // Bottom row - Front layer + [-8, -5, 2], + [-4, -6, 2], + [0, -5.5, 2], + [4, -6, 2], + [8, -5, 2], + + // Back layer scattered + [-6, 4, -4], + [6, 4, -4], + [-6, -4, -4], + [6, -4, -4], + [0, 5, -4], + [0, -5, -4], + + + ]; + + return positions.map((position, i) => ({ + position, color: colors[i % colors.length], - nodeCount: 18, // Fixed node count for all structures - }); - } + structureIndex: i, + })); + }, []); + function CyberGridBackground() { + const gridRef = useRef(); + + useFrame((state) => { + if (gridRef.current) { + // Subtle movement + gridRef.current.position.x = Math.sin(state.clock.elapsedTime * 0.1) * 0.5; + gridRef.current.position.y = Math.cos(state.clock.elapsedTime * 0.08) * 0.5; + } + }); + + return ( + + {/* Main grid plane */} + + + + + + {/* Vertical grid lines */} + + + + + + {/* Glowing data points */} + {Array.from({ length: 50 }).map((_, i) => ( + + + + + ))} + + ); +} return (
- {/* Content Section - Now scrollable on mobile */} + {/* Content Section */}
-
+
- - MACHINE LEARNING FOR EVERYONE (ML4E) - + + MACHINE LEARNING FOR EVERYONE + + + + (ML4E) + - - - + + THE OFFICIAL MACHINE LEARNING CLUB OF NIT ROURKELA + +
- {/* Canvas with fixed height and proper z-index */} + {/* 3D Canvas */}
- + - - + + + + {structures.map((props, i) => ( ))} 768} - minDistance={8} // Prevent zoom out - maxDistance={12} // Prevent zoom in - touches={{ - ONE: null, - TWO: null - }} + enableRotate={false} + minPolarAngle={Math.PI / 2} + maxPolarAngle={Math.PI / 2} + minDistance={10} + maxDistance={14} />
- - {/* Add some scrollable content to demonstrate scrolling */} -
); diff --git a/src/app/components/Navbar.jsx b/src/app/components/Navbar.jsx index 5776cf4..1b40a9c 100644 --- a/src/app/components/Navbar.jsx +++ b/src/app/components/Navbar.jsx @@ -51,7 +51,7 @@ const DIRECT_LINKS = { Projects: "/projects", Achievements: "/achievements", Events: "/events", - Contact: "/contact", + Contact: "#contact", }; export default function Navbar() { diff --git a/src/app/globals.css b/src/app/globals.css index 206accb..5b8fc67 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -72,3 +72,6 @@ body { .pointer-events-none > .breath { animation: soft-breath 5.5s ease-in-out infinite; } +html { + scroll-behavior: smooth; +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 4a4d176..76e9b11 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; import { roboto,orbitron } from "./font"; +import Footer from "./components/Footer"; const geistSans = Geist({ @@ -30,6 +31,7 @@ export default function RootLayout({ className={`${geistSans.variable} ${geistMono.variable} ${roboto.variable} ${orbitron.variable} antialiased`} > {children} +
); diff --git a/src/app/onlineresources/page.jsx b/src/app/onlineresources/page.jsx deleted file mode 100644 index d8605a2..0000000 --- a/src/app/onlineresources/page.jsx +++ /dev/null @@ -1,5 +0,0 @@ -export default function OnlineResourcesPage() { - return ( -

Online Resources Page

- ); -} diff --git a/src/app/onlineresources/page.tsx b/src/app/onlineresources/page.tsx new file mode 100644 index 0000000..9402c51 --- /dev/null +++ b/src/app/onlineresources/page.tsx @@ -0,0 +1,300 @@ +"use client"; + +import React, { useState, useRef } from "react"; +import { + BookOpen, + Youtube, + ExternalLink, + Download, + PlayCircle, + X, + FileText +} from "lucide-react"; +import Navbar from "../components/Navbar"; +import { motion, AnimatePresence } from "framer-motion"; +import NeuralBackground from "@/app/components/NeuralBackground"; +import { resources, ResourceItem } from "../../data/resources"; // Import the data + +// --- 1. Custom Bento Card --- +interface BentoCardProps { + item: ResourceItem; + onClick: () => void; +} + +const BentoCard = ({ item, onClick }: BentoCardProps) => { + const divRef = useRef(null); + const [position, setPosition] = useState({ x: 0, y: 0 }); + + const handleMouseMove = (e: React.MouseEvent) => { + if (!divRef.current) return; + const rect = divRef.current.getBoundingClientRect(); + setPosition({ x: e.clientX - rect.left, y: e.clientY - rect.top }); + }; + + return ( + + {/* Animated gradient overlay */} + + {/* Spotlight Effect */} + + + + {/* Card Content */} +
+
+ + {item.type === 'book' ? ( + + ) : ( + + )} + + + + +
+ +
+

{item.title}

+

{item.author}

+
+ + {item.type === 'book' ? 'PDF' : 'Playlist'} + +
+
+
+ + {/* Overlay (Appears on Hover) */} + + + {item.type === 'book' ? : } + {item.type === 'book' ? "Read Now" : "Watch Now"} + + +
+ ); +}; + +// --- 2. Resource Modal --- +interface ResourceModalProps { + resource: ResourceItem; + onClose: () => void; +} + +const ResourceModal = ({ resource, onClose }: ResourceModalProps) => { + if (!resource) return null; + + return ( + + + + + {/* Animated background gradient */} + + + + + +
+ + {resource.type === 'book' ? : } + + + +

{resource.title}

+

{resource.author}

+
+ + + {resource.description} + + + + {/* Primary Action: Read or Watch */} + + {resource.type === 'book' ? : } + {resource.type === 'book' ? 'Read Now' : 'Watch on YouTube'} + + + {/* Secondary Action: Download (Only for books) */} + {resource.type === 'book' && resource.downloadUrl && ( + + + + )} + +
+
+
+ ); +}; + +// --- 3. Main Page Component --- +export default function OnlineResources() { + const [selectedResource, setSelectedResource] = useState(null); + + return ( +
+ + + + {/* FOOTER REMOVAL HACK */} + + +
+ + {/* Header */} + +

+ Library +

+

+ Essential readings and curated playlists for the ML4E team. +

+
+ + {/* BENTO GRID LAYOUT */} +
+ {resources.map((res) => ( + setSelectedResource(res)} + /> + ))} +
+ +
+ + {/* Modal Overlay */} + + {selectedResource && ( + setSelectedResource(null)} + /> + )} + +
+ ); +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index bebfa14..fa31ff9 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -182,7 +182,6 @@ export default function App() { {showHome && ( <> -
)}
diff --git a/src/app/projects/page.tsx b/src/app/projects/page.tsx index ae14542..1d95bb0 100644 --- a/src/app/projects/page.tsx +++ b/src/app/projects/page.tsx @@ -7,7 +7,6 @@ import { Orbitron, JetBrains_Mono } from "next/font/google"; import { FaGithub } from "react-icons/fa"; import { FiArrowUpRight } from "react-icons/fi"; import NeuralBackground from "@/app/components/NeuralBackground"; -import { TypeAnimation } from "react-type-animation"; import { motion, AnimatePresence } from "framer-motion"; import DescriptionModal from "@/app/components/DescriptionModal"; import Navbar from "../components/Navbar"; @@ -41,6 +40,8 @@ type MenuItem = { description: string; }; +type AnimationType = "fastTyping" | "fadeIn" | "staggeredFade"; + const DUMMY_PROJECTS: Project[] = []; const cardThemes = [ @@ -115,6 +116,97 @@ const truncateDescription = (description?: string, wordLimit: number = 40): { tr }; }; +// === OPTION 1: Fade-in Typing Animation (Very Fast) === +const FastTypingText = ({ text, className = "", delay = 0 }: { text: string, className?: string, delay?: number }) => { + const [displayedText, setDisplayedText] = useState(""); + + useEffect(() => { + if (!text) return; + + const timer = setTimeout(() => { + // Fast typing effect - shows all text almost instantly with slight character-by-character feel + let currentIndex = 0; + const speed = 10; // Very fast (lower = faster) + + const typeCharacter = () => { + if (currentIndex <= text.length) { + setDisplayedText(text.substring(0, currentIndex)); + currentIndex++; + setTimeout(typeCharacter, speed); + } + }; + + typeCharacter(); + }, delay * 1000); + + return () => clearTimeout(timer); + }, [text, delay]); + + return {displayedText}; +}; + +// === OPTION 2: Simple Fade In Animation === +const FadeInText = ({ text, className = "", delay = 0 }: { text: string, className?: string, delay?: number }) => { + return ( + + {text} + + ); +}; + +// === OPTION 3: Staggered Fade In (Character by Character) === +const StaggeredFadeText = ({ text, className = "", delay = 0 }: { text: string, className?: string, delay?: number }) => { + const characters = text.split(''); + + return ( + + {characters.map((char, index) => ( + + {char} + + ))} + + ); +}; + +// === ANIMATED TEXT COMPONENT (Handles all animation types) === +const AnimatedText = ({ + text, + className = "", + delay = 0, + animationType = "fastTyping" +}: { + text: string, + className?: string, + delay?: number, + animationType?: AnimationType +}) => { + if (animationType === "fastTyping") { + return ; + } else if (animationType === "fadeIn") { + return ; + } else if (animationType === "staggeredFade") { + return ; + } + + // Default fallback + return ; +}; + // === MAIN COMPONENT === export default function ViewProjectsPage() { const [projects, setProjects] = useState([]); @@ -123,6 +215,9 @@ export default function ViewProjectsPage() { const [activeIndex, setActiveIndex] = useState(0); const [selectedProject, setSelectedProject] = useState(null); const [expandedDescriptions, setExpandedDescriptions] = useState>(new Set()); + + // Animation type - choose one + const animationType: AnimationType = "fadeIn"; // === FETCH PROJECTS FROM BACKEND === useEffect(() => { @@ -243,31 +338,30 @@ export default function ViewProjectsPage() { transition={{ duration: 0.8, delay: 0.4 }} viewport={{ once: true }} > - {/* === PROJECT TITLE - Typing Effect === */} + {/* === PROJECT TITLE - Fast Animation === */} - - {/* === DESCRIPTION BOX - Typing Effect === */} + {/* === DESCRIPTION BOX - Fast Animation === */} {project.description && ( setSelectedProject(project)} initial={{ opacity: 0, y: 10 }} whileInView={{ opacity: 1, y: 0 }} - transition={{ duration: 0.6, delay: 0.6 }} + transition={{ duration: 0.3, delay: 0.3 }} viewport={{ once: true }} > {/* Window Header Style Dots */} @@ -277,19 +371,13 @@ export default function ViewProjectsPage() { - {/* Typing Animation Description */} + {/* Animated Description */}
- {/* View More for Description */} @@ -322,20 +410,31 @@ export default function ViewProjectsPage() {

{displayedTech.map((tech, techIndex) => ( - {tech} - + ))} {remainingTech > 0 && ( - + )}
@@ -352,27 +451,35 @@ export default function ViewProjectsPage() { viewport={{ once: true }} > {project.deployedLink && ( - View Project - + )} {project.githubLink && ( - - + )} @@ -382,7 +489,7 @@ export default function ViewProjectsPage() {
- {/* === DESCRIPTION MODAL - Updated to include Tech Stack === */} + {/* === DESCRIPTION MODAL === */} {selectedProject && ( { await mongoose.connect(process.env.MongoURL, { dbName: "achievementDB", }); + console.log("✅ Connected to Achievements MongoDB"); } catch (error) { console.error("❌ MongoDB Achievements connection error:", error); diff --git a/tsconfig.json b/tsconfig.json index c7f3597..c4081af 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -11,7 +15,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -19,9 +23,21 @@ } ], "paths": { - "@/*": ["./src/*"] + "@/*": [ + "./src/*" + ] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/app/components/Home.jsx", "src/app/components/Navbar.jsx"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "src/app/components/Home.jsx", + "src/app/components/Navbar.jsx", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] }