Merge branch 'main' of https://github.com/AshwaniNITR/ML4EWeb1
This commit is contained in:
@@ -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: "*",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
143
package-lock.json
generated
143
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 (
|
||||
<Sphere ref={ref} args={[size, 64, 64]} position={position}>
|
||||
<Sphere ref={ref} args={[size, 32, 32]} position={position}>
|
||||
<meshStandardMaterial
|
||||
color={color}
|
||||
emissive={color}
|
||||
@@ -278,55 +281,127 @@ function AnimatedNeuralNode({ position, color, size = 0.08 }) {
|
||||
</Sphere>
|
||||
);
|
||||
}
|
||||
|
||||
// Add this component after the imports
|
||||
function ElectricCircuitBackground() {
|
||||
return (
|
||||
<group position={[0, 0, -10]}>
|
||||
{/* Main circuit grid */}
|
||||
<gridHelper
|
||||
args={[50, 100, '#00faff', '#00a8ff']}
|
||||
rotation={[0, 0, Math.PI / 4]}
|
||||
/>
|
||||
|
||||
{/* 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 (
|
||||
<Line
|
||||
key={i}
|
||||
points={[
|
||||
[x, y, 0],
|
||||
[x + length, y + (Math.random() - 0.5) * 2, 0]
|
||||
]}
|
||||
color="#00faff"
|
||||
lineWidth={0.5}
|
||||
transparent
|
||||
opacity={0.3 + Math.random() * 0.3}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Circuit nodes */}
|
||||
{Array.from({ length: 30 }).map((_, i) => (
|
||||
<Sphere
|
||||
key={`node-${i}`}
|
||||
args={[0.05, 16, 16]}
|
||||
position={[
|
||||
(Math.random() - 0.5) * 40,
|
||||
(Math.random() - 0.5) * 40,
|
||||
0
|
||||
]}
|
||||
>
|
||||
<meshBasicMaterial color="#00faff" toneMapped={false} />
|
||||
</Sphere>
|
||||
))}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
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 (
|
||||
<group position={position}>
|
||||
{nodes.current.map((pos, i) => (
|
||||
<AnimatedNeuralNode key={i} position={pos} color={color} />
|
||||
{nodes.map((pos, i) => (
|
||||
<AnimatedNeuralNode
|
||||
key={i}
|
||||
position={pos}
|
||||
color={color}
|
||||
delay={i * 0.1}
|
||||
/>
|
||||
))}
|
||||
|
||||
{connections.map(([start, end], i) => (
|
||||
<Line
|
||||
key={i}
|
||||
points={[nodes.current[start], nodes.current[end]]}
|
||||
points={[nodes[start], nodes[end]]}
|
||||
color={color}
|
||||
lineWidth={1}
|
||||
lineWidth={1.5}
|
||||
transparent
|
||||
opacity={0.6}
|
||||
opacity={0.4}
|
||||
toneMapped={false}
|
||||
/>
|
||||
))}
|
||||
@@ -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 (
|
||||
<group ref={gridRef} position={[0, 0, -8]}>
|
||||
{/* Main grid plane */}
|
||||
<mesh rotation={[-Math.PI / 2, 0, 0]}>
|
||||
<planeGeometry args={[60, 60, 60, 60]} />
|
||||
<meshBasicMaterial
|
||||
color="#001122"
|
||||
wireframe
|
||||
wireframeLinewidth={1}
|
||||
transparent
|
||||
opacity={0.2}
|
||||
/>
|
||||
</mesh>
|
||||
|
||||
{/* Vertical grid lines */}
|
||||
<mesh rotation={[0, 0, 0]} position={[0, 0, 0]}>
|
||||
<planeGeometry args={[60, 60, 60, 60]} />
|
||||
<meshBasicMaterial
|
||||
color="#003344"
|
||||
wireframe
|
||||
wireframeLinewidth={1}
|
||||
transparent
|
||||
opacity={0.15}
|
||||
/>
|
||||
</mesh>
|
||||
|
||||
{/* Glowing data points */}
|
||||
{Array.from({ length: 50 }).map((_, i) => (
|
||||
<mesh
|
||||
key={i}
|
||||
position={[
|
||||
(Math.random() - 0.5) * 50,
|
||||
(Math.random() - 0.5) * 50,
|
||||
(Math.random() - 0.5) * 10
|
||||
]}
|
||||
>
|
||||
<sphereGeometry args={[0.03, 8, 8]} />
|
||||
<meshBasicMaterial
|
||||
color="#00faff"
|
||||
toneMapped={false}
|
||||
transparent
|
||||
opacity={0.6}
|
||||
/>
|
||||
</mesh>
|
||||
))}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-screen min-h-screen border-t border-cyan-500/20 bg-[#0b1117] overflow-y-auto">
|
||||
<Navbar/>
|
||||
|
||||
{/* Content Section - Now scrollable on mobile */}
|
||||
{/* Content Section */}
|
||||
<div className="relative min-h-screen">
|
||||
<div className="absolute inset-0 flex md:left-10 items-center justify-center z-10 pointer-events-none">
|
||||
<div className="absolute inset-0 flex md:left-10 items-center justify-center z-10 pointer-events-none pt-20">
|
||||
<Glow />
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.9 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 1, ease: "easeOut" }}
|
||||
className="px-8 py-6 rounded-2xl bg-white/10 backdrop-blur-lg border border-white/20 shadow-lg text-center pointer-events-auto mx-4"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 1.5, ease: "easeOut", delay: 0.5 }}
|
||||
className="px-8 py-6 rounded-2xl bg-slate-900/40 backdrop-blur-xl border border-cyan-500/30 shadow-2xl text-center pointer-events-auto mx-4 max-w-4xl"
|
||||
>
|
||||
<motion.h1
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 1, ease: "easeOut" }}
|
||||
className="text-4xl md:text-8xl font-bold text-cyan-200 drop-shadow-[0_0_15px_#00faff] special-font"
|
||||
<motion.div
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={{
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.3,
|
||||
delayChildren: 0.2
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<b>MACHINE LEARNING FOR EVERYONE</b> (<b>ML4E</b>)
|
||||
</motion.h1>
|
||||
<motion.h1
|
||||
variants={{
|
||||
hidden: { opacity: 0, y: -20 },
|
||||
visible: { opacity: 1, y: 0, transition: { duration: 0.8, ease: "easeOut" } }
|
||||
}}
|
||||
className="text-3xl md:text-7xl font-bold text-cyan-200 drop-shadow-[0_0_20px_#00faff] mb-4 special-font"
|
||||
style={{ fontFamily: "Orbitron, sans-serif" }}
|
||||
>
|
||||
<b>MACHINE LEARNING FOR EVERYONE</b>
|
||||
</motion.h1>
|
||||
|
||||
<motion.div
|
||||
variants={{
|
||||
hidden: { opacity: 0, scale: 0.9 },
|
||||
visible: { opacity: 1, scale: 1, transition: { duration: 0.8, ease: "easeOut" } }
|
||||
}}
|
||||
className="text-2xl md:text-5xl font-bold text-cyan-300 drop-shadow-[0_0_15px_#00d9ff] mb-4"
|
||||
style={{ fontFamily: "Orbitron, sans-serif" }}
|
||||
>
|
||||
(ML4E)
|
||||
</motion.div>
|
||||
|
||||
<motion.p
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.5, duration: 1, ease: "easeOut" }}
|
||||
className="mt-2 text-lg md:text-2xl text-blue-300 drop-shadow-[0_0_10px_#00d9ff]"
|
||||
style={{ fontFamily: "Roboto, sans-serif" }}
|
||||
>
|
||||
<ReactTyped
|
||||
strings={["THE OFFICIAL MACHINE LEARNING CLUB OF NIT ROURKELA"]}
|
||||
typeSpeed={50}
|
||||
backSpeed={30}
|
||||
backDelay={1500}
|
||||
loop={false}
|
||||
showCursor={true}
|
||||
/>
|
||||
</motion.p>
|
||||
<motion.p
|
||||
variants={{
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: { opacity: 1, y: 0, transition: { duration: 0.8, ease: "easeOut" } }
|
||||
}}
|
||||
className="mt-2 text-base md:text-xl text-blue-300 drop-shadow-[0_0_10px_#00d9ff]"
|
||||
style={{ fontFamily: "Roboto, sans-serif" }}
|
||||
>
|
||||
THE OFFICIAL MACHINE LEARNING CLUB OF NIT ROURKELA
|
||||
</motion.p>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* Canvas with fixed height and proper z-index */}
|
||||
{/* 3D Canvas */}
|
||||
<div className="fixed inset-0 z-0">
|
||||
<Canvas camera={{ position: [0, 0, 10], fov: 30 }}>
|
||||
<Canvas camera={{ position: [0, 0, 15], fov: 60 }}>
|
||||
<color attach="background" args={["#000000"]} />
|
||||
<ambientLight intensity={0.3} />
|
||||
<pointLight position={[10, 10, 10]} intensity={2} />
|
||||
<CyberGridBackground />
|
||||
<ambientLight intensity={0.5} />
|
||||
<pointLight position={[10, 10, 10]} intensity={1.5} />
|
||||
<pointLight position={[-10, -10, -10]} intensity={0.8} color="#00faff" />
|
||||
|
||||
{structures.map((props, i) => (
|
||||
<NeuralStructure key={i} {...props} />
|
||||
))}
|
||||
|
||||
<OrbitControls
|
||||
enableZoom={false} // Disabled zoom completely
|
||||
autoRotate={false} // Disabled auto rotation
|
||||
enableZoom={false}
|
||||
autoRotate={false}
|
||||
enablePan={false}
|
||||
enableRotate={window.innerWidth > 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}
|
||||
/>
|
||||
|
||||
<EffectComposer>
|
||||
<Bloom
|
||||
intensity={2.5}
|
||||
intensity={2}
|
||||
kernelSize={3}
|
||||
luminanceThreshold={0.1}
|
||||
luminanceSmoothing={0.9}
|
||||
@@ -436,9 +632,6 @@ export default function Home() {
|
||||
</EffectComposer>
|
||||
</Canvas>
|
||||
</div>
|
||||
|
||||
{/* Add some scrollable content to demonstrate scrolling */}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -51,7 +51,7 @@ const DIRECT_LINKS = {
|
||||
Projects: "/projects",
|
||||
Achievements: "/achievements",
|
||||
Events: "/events",
|
||||
Contact: "/contact",
|
||||
Contact: "#contact",
|
||||
};
|
||||
|
||||
export default function Navbar() {
|
||||
|
||||
@@ -72,3 +72,6 @@ body {
|
||||
.pointer-events-none > .breath {
|
||||
animation: soft-breath 5.5s ease-in-out infinite;
|
||||
}
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
@@ -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}
|
||||
<Footer/>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
export default function OnlineResourcesPage() {
|
||||
return (
|
||||
<h1 className="text-center text-black mt-20">Online Resources Page</h1>
|
||||
);
|
||||
}
|
||||
300
src/app/onlineresources/page.tsx
Normal file
300
src/app/onlineresources/page.tsx
Normal file
@@ -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<HTMLDivElement>(null);
|
||||
const [position, setPosition] = useState({ x: 0, y: 0 });
|
||||
|
||||
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (!divRef.current) return;
|
||||
const rect = divRef.current.getBoundingClientRect();
|
||||
setPosition({ x: e.clientX - rect.left, y: e.clientY - rect.top });
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
layoutId={item.id}
|
||||
ref={divRef}
|
||||
onClick={onClick}
|
||||
onMouseMove={handleMouseMove}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.4, ease: "easeOut" }}
|
||||
whileHover={{ scale: 1.02, boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.5)" }}
|
||||
className={`relative overflow-hidden rounded-3xl border border-slate-800 bg-gradient-to-br from-[#0b0d14] to-[#050608] group cursor-pointer ${item.span}`}
|
||||
>
|
||||
{/* Animated gradient overlay */}
|
||||
<motion.div
|
||||
className="absolute inset-0 opacity-0 group-hover:opacity-20 transition-opacity duration-500"
|
||||
style={{
|
||||
background: `linear-gradient(135deg, ${item.color.replace('rgb', 'rgba').replace(')', ', 0.2)')}, transparent 70%)`,
|
||||
}}
|
||||
/>
|
||||
{/* Spotlight Effect */}
|
||||
<motion.div
|
||||
className="pointer-events-none absolute -inset-px opacity-0 transition duration-300 group-hover:opacity-100 z-10"
|
||||
style={{
|
||||
background: `radial-gradient(600px circle at ${position.x}px ${position.y}px, ${item.color.replace('rgb', 'rgba').replace(')', ', 0.15)')}, transparent 40%)`,
|
||||
}}
|
||||
/>
|
||||
<motion.div
|
||||
className="pointer-events-none absolute -inset-px rounded-3xl opacity-0 transition duration-300 group-hover:opacity-100 z-10"
|
||||
style={{
|
||||
background: `radial-gradient(600px circle at ${position.x}px ${position.y}px, ${item.color}, transparent 40%)`,
|
||||
maskImage: "linear-gradient(black, black) content-box, linear-gradient(black, black)",
|
||||
WebkitMaskImage: "linear-gradient(black, black) content-box, linear-gradient(black, black)",
|
||||
maskComposite: "exclude",
|
||||
WebkitMaskComposite: "xor",
|
||||
padding: "2px",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Card Content */}
|
||||
<div className="relative h-full p-6 flex flex-col justify-between z-0 transition-all duration-300 group-hover:blur-[2px] group-hover:opacity-40">
|
||||
<div className="flex justify-between items-start">
|
||||
<motion.div
|
||||
className="w-12 h-12 rounded-2xl flex items-center justify-center border border-white/10 shadow-lg"
|
||||
style={{ backgroundColor: item.color.replace('rgb', 'rgba').replace(')', ', 0.15)') }}
|
||||
whileHover={{ scale: 1.1, rotate: 5 }}
|
||||
transition={{ type: "spring", stiffness: 400, damping: 10 }}
|
||||
>
|
||||
{item.type === 'book' ? (
|
||||
<BookOpen size={24} style={{ color: item.color }} />
|
||||
) : (
|
||||
<Youtube size={24} style={{ color: item.color }} />
|
||||
)}
|
||||
</motion.div>
|
||||
<motion.div whileHover={{ scale: 1.2, opacity: 1 }} transition={{ duration: 0.2 }}>
|
||||
<ExternalLink className="w-5 h-5 text-slate-600 group-hover:text-slate-400 transition-colors" />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-slate-100 mb-1 leading-tight group-hover:text-white transition-colors">{item.title}</h3>
|
||||
<p className="text-xs font-mono text-slate-400 mb-2 group-hover:text-slate-300 transition-colors">{item.author}</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[10px] uppercase tracking-wider px-2 py-1 rounded bg-slate-800 text-slate-400 border border-slate-700">
|
||||
{item.type === 'book' ? 'PDF' : 'Playlist'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Overlay (Appears on Hover) */}
|
||||
<motion.div
|
||||
className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-20"
|
||||
initial={{ opacity: 0 }}
|
||||
whileHover={{ opacity: 1 }}
|
||||
>
|
||||
<motion.div
|
||||
className="px-6 py-3 rounded-full bg-white/10 backdrop-blur-md border border-white/20 text-white font-bold flex items-center gap-2 shadow-2xl"
|
||||
initial={{ scale: 0.8, y: 10 }}
|
||||
whileHover={{ scale: 1, y: 0 }}
|
||||
transition={{ type: "spring", stiffness: 400, damping: 15 }}
|
||||
>
|
||||
{item.type === 'book' ? <BookOpen size={18} /> : <PlayCircle size={18} />}
|
||||
<span>{item.type === 'book' ? "Read Now" : "Watch Now"}</span>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
// --- 2. Resource Modal ---
|
||||
interface ResourceModalProps {
|
||||
resource: ResourceItem;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const ResourceModal = ({ resource, onClose }: ResourceModalProps) => {
|
||||
if (!resource) return null;
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-[100] flex items-center justify-center px-4"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
onClick={onClose}
|
||||
className="absolute inset-0 bg-black/80 backdrop-blur-xl"
|
||||
/>
|
||||
|
||||
<motion.div
|
||||
layoutId={resource.id}
|
||||
initial={{ scale: 0.9, opacity: 0, y: 20 }}
|
||||
animate={{ scale: 1, opacity: 1, y: 0 }}
|
||||
exit={{ scale: 0.9, opacity: 0, y: 20 }}
|
||||
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
||||
className="relative w-full max-w-lg bg-gradient-to-br from-[#0f111a] to-[#050608] border-2 border-slate-700 rounded-3xl p-8 shadow-2xl overflow-hidden z-50"
|
||||
>
|
||||
{/* Animated background gradient */}
|
||||
<motion.div
|
||||
className="absolute inset-0 opacity-10"
|
||||
animate={{
|
||||
background: [
|
||||
`radial-gradient(circle at 0% 0%, ${resource.color}, transparent 50%)`,
|
||||
`radial-gradient(circle at 100% 100%, ${resource.color}, transparent 50%)`,
|
||||
`radial-gradient(circle at 0% 0%, ${resource.color}, transparent 50%)`,
|
||||
]
|
||||
}}
|
||||
transition={{ duration: 5, repeat: Infinity, ease: "linear" }}
|
||||
/>
|
||||
<motion.button
|
||||
onClick={onClose}
|
||||
className="absolute top-4 right-4 p-2 text-slate-400 hover:text-white bg-white/5 hover:bg-white/10 rounded-full z-10 transition-colors"
|
||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
>
|
||||
<X size={20} />
|
||||
</motion.button>
|
||||
|
||||
<div className="flex flex-col gap-5 relative z-10">
|
||||
<motion.div
|
||||
className="w-16 h-16 rounded-2xl flex items-center justify-center border border-white/10 bg-slate-800/50 shadow-lg"
|
||||
initial={{ scale: 0, rotate: -180 }}
|
||||
animate={{ scale: 1, rotate: 0 }}
|
||||
transition={{ type: "spring", stiffness: 200, damping: 15, delay: 0.1 }}
|
||||
style={{ backgroundColor: resource.color.replace('rgb', 'rgba').replace(')', ', 0.15)') }}
|
||||
>
|
||||
{resource.type === 'book' ? <FileText size={32} style={{ color: resource.color }} /> : <Youtube size={32} style={{ color: resource.color }} />}
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.2 }}
|
||||
>
|
||||
<h2 className="text-3xl font-bold text-white mb-2">{resource.title}</h2>
|
||||
<p className="text-sm text-slate-400 font-mono">{resource.author}</p>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="p-5 rounded-2xl bg-slate-900/50 backdrop-blur-sm border border-slate-800 text-slate-300 text-sm leading-relaxed"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.3 }}
|
||||
>
|
||||
{resource.description}
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="flex gap-3 mt-4"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.4 }}
|
||||
>
|
||||
{/* Primary Action: Read or Watch */}
|
||||
<motion.a
|
||||
href={resource.link}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="flex-1 flex items-center justify-center gap-2 bg-slate-100 text-black font-bold py-3 rounded-xl hover:bg-white transition-all shadow-lg"
|
||||
whileHover={{ scale: 1.05, boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.3)" }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
{resource.type === 'book' ? <BookOpen size={18} /> : <PlayCircle size={18} />}
|
||||
{resource.type === 'book' ? 'Read Now' : 'Watch on YouTube'}
|
||||
</motion.a>
|
||||
|
||||
{/* Secondary Action: Download (Only for books) */}
|
||||
{resource.type === 'book' && resource.downloadUrl && (
|
||||
<motion.a
|
||||
href={resource.downloadUrl}
|
||||
download
|
||||
className="px-5 bg-slate-800 text-white rounded-xl border border-slate-700 hover:bg-slate-700 flex items-center justify-center transition-colors"
|
||||
title="Download PDF"
|
||||
whileHover={{ scale: 1.1, rotate: 5 }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
>
|
||||
<Download size={20} />
|
||||
</motion.a>
|
||||
)}
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
// --- 3. Main Page Component ---
|
||||
export default function OnlineResources() {
|
||||
const [selectedResource, setSelectedResource] = useState<ResourceItem | null>(null);
|
||||
|
||||
return (
|
||||
<main className="relative min-h-screen w-full bg-[#020617] text-slate-200">
|
||||
<NeuralBackground />
|
||||
<Navbar />
|
||||
|
||||
{/* FOOTER REMOVAL HACK */}
|
||||
<style jsx global>{`
|
||||
footer, .footer, [data-testid="footer"] { display: none !important; }
|
||||
`}</style>
|
||||
|
||||
<div className="relative z-10 pt-32 pb-20 px-4 sm:px-8 pl-24 md:pl-32 max-w-7xl mx-auto">
|
||||
|
||||
{/* Header */}
|
||||
<motion.div
|
||||
className="mb-12"
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, ease: "easeOut" }}
|
||||
>
|
||||
<h1 className="text-4xl md:text-6xl font-bold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-white via-slate-200 to-slate-400 mb-4">
|
||||
Library
|
||||
</h1>
|
||||
<p className="text-slate-400 text-lg max-w-xl">
|
||||
Essential readings and curated playlists for the ML4E team.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
{/* BENTO GRID LAYOUT */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4 auto-rows-[180px]">
|
||||
{resources.map((res) => (
|
||||
<BentoCard
|
||||
key={res.id}
|
||||
item={res}
|
||||
onClick={() => setSelectedResource(res)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Modal Overlay */}
|
||||
<AnimatePresence mode="wait">
|
||||
{selectedResource && (
|
||||
<ResourceModal
|
||||
resource={selectedResource}
|
||||
onClose={() => setSelectedResource(null)}
|
||||
/>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -182,7 +182,6 @@ export default function App() {
|
||||
{showHome && (
|
||||
<>
|
||||
<Home />
|
||||
<Footer />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -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 <span className={className}>{displayedText}</span>;
|
||||
};
|
||||
|
||||
// === OPTION 2: Simple Fade In Animation ===
|
||||
const FadeInText = ({ text, className = "", delay = 0 }: { text: string, className?: string, delay?: number }) => {
|
||||
return (
|
||||
<motion.span
|
||||
className={className}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.3, delay: delay, ease: "easeOut" }}
|
||||
>
|
||||
{text}
|
||||
</motion.span>
|
||||
);
|
||||
};
|
||||
|
||||
// === 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 (
|
||||
<span className={className}>
|
||||
{characters.map((char, index) => (
|
||||
<motion.span
|
||||
key={index}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{
|
||||
duration: 0.05,
|
||||
delay: delay + (index * 0.01), // Very fast staggered effect
|
||||
ease: "easeOut"
|
||||
}}
|
||||
>
|
||||
{char}
|
||||
</motion.span>
|
||||
))}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
// === 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 <FastTypingText text={text} className={className} delay={delay} />;
|
||||
} else if (animationType === "fadeIn") {
|
||||
return <FadeInText text={text} className={className} delay={delay} />;
|
||||
} else if (animationType === "staggeredFade") {
|
||||
return <StaggeredFadeText text={text} className={className} delay={delay} />;
|
||||
}
|
||||
|
||||
// Default fallback
|
||||
return <FadeInText text={text} className={className} delay={delay} />;
|
||||
};
|
||||
|
||||
// === MAIN COMPONENT ===
|
||||
export default function ViewProjectsPage() {
|
||||
const [projects, setProjects] = useState<Project[]>([]);
|
||||
@@ -123,6 +215,9 @@ export default function ViewProjectsPage() {
|
||||
const [activeIndex, setActiveIndex] = useState(0);
|
||||
const [selectedProject, setSelectedProject] = useState<Project | null>(null);
|
||||
const [expandedDescriptions, setExpandedDescriptions] = useState<Set<string>>(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 === */}
|
||||
<motion.div
|
||||
className="w-full text-center"
|
||||
initial={{ opacity: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
transition={{ duration: 0.2, delay: 0.5 }}
|
||||
transition={{ duration: 0.1, delay: 0.3 }}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
<TypeAnimation
|
||||
sequence={[project.name || "Untitled Project"]}
|
||||
wrapper="h2"
|
||||
speed={90}
|
||||
className={`text-3xl font-bold text-white font-[Orbitron] `}
|
||||
cursor={false}
|
||||
<AnimatedText
|
||||
text={project.name || "Untitled Project"}
|
||||
className={`text-3xl font-bold text-white font-[Orbitron]`}
|
||||
delay={0.3}
|
||||
animationType={animationType}
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
{/* === DESCRIPTION BOX - Typing Effect === */}
|
||||
{/* === DESCRIPTION BOX - Fast Animation === */}
|
||||
{project.description && (
|
||||
<motion.div
|
||||
className="bg-slate-800/60 backdrop-blur-md rounded-lg border border-slate-700 w-full cursor-pointer hover:border-cyan-600/50 transition-all overflow-hidden"
|
||||
onClick={() => 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() {
|
||||
<span className="block w-3 h-3 rounded-full bg-green-500"></span>
|
||||
</div>
|
||||
|
||||
{/* Typing Animation Description */}
|
||||
{/* Animated Description */}
|
||||
<div className="p-6">
|
||||
<TypeAnimation
|
||||
sequence={[
|
||||
isDescriptionExpanded ? project.description : truncatedDesc,
|
||||
500
|
||||
]}
|
||||
wrapper="p"
|
||||
speed={30}
|
||||
<AnimatedText
|
||||
text={isDescriptionExpanded ? project.description : truncatedDesc}
|
||||
className={`text-gray-300 text-base ${jetbrainsMono.className}`}
|
||||
style={{ whiteSpace: "pre-line" }}
|
||||
repeat={0}
|
||||
cursor={false}
|
||||
delay={0.4}
|
||||
animationType={animationType}
|
||||
/>
|
||||
|
||||
{/* View More for Description */}
|
||||
@@ -322,20 +410,31 @@ export default function ViewProjectsPage() {
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2 justify-start">
|
||||
{displayedTech.map((tech, techIndex) => (
|
||||
<span
|
||||
<motion.span
|
||||
key={techIndex}
|
||||
className="px-3 py-1 bg-slate-700/50 rounded-full text-sm text-cyan-200 border border-cyan-500/30"
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
transition={{
|
||||
duration: 0.3,
|
||||
delay: 0.7 + (techIndex * 0.05)
|
||||
}}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
{tech}
|
||||
</span>
|
||||
</motion.span>
|
||||
))}
|
||||
{remainingTech > 0 && (
|
||||
<button
|
||||
<motion.button
|
||||
onClick={() => setSelectedProject(project)}
|
||||
className="px-3 py-1 bg-cyan-600/20 rounded-full text-sm text-cyan-300 border border-cyan-400/30 hover:bg-cyan-600/30 transition-colors"
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.3, delay: 0.9 }}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
+{remainingTech} more
|
||||
</button>
|
||||
</motion.button>
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -352,27 +451,35 @@ export default function ViewProjectsPage() {
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
{project.deployedLink && (
|
||||
<a
|
||||
<motion.a
|
||||
href={project.deployedLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{ color: theme.accent }}
|
||||
className="flex items-center gap-2 text-lg hover:underline"
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.3, delay: 0.9 }}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
View Project
|
||||
<FiArrowUpRight />
|
||||
</a>
|
||||
</motion.a>
|
||||
)}
|
||||
{project.githubLink && (
|
||||
<a
|
||||
<motion.a
|
||||
href={project.githubLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-2xl hover:scale-110 transition-transform"
|
||||
style={{ color: theme.accent }}
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.3, delay: 1.0 }}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
<FaGithub />
|
||||
</a>
|
||||
</motion.a>
|
||||
)}
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
@@ -382,7 +489,7 @@ export default function ViewProjectsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* === DESCRIPTION MODAL - Updated to include Tech Stack === */}
|
||||
{/* === DESCRIPTION MODAL === */}
|
||||
<AnimatePresence>
|
||||
{selectedProject && (
|
||||
<DescriptionModal
|
||||
|
||||
128
src/data/resources.ts
Normal file
128
src/data/resources.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
// src/data/resources.ts
|
||||
|
||||
export interface ResourceItem {
|
||||
id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
type: "book" | "video";
|
||||
size?: string;
|
||||
description: string;
|
||||
link: string;
|
||||
downloadUrl?: string;
|
||||
color: string;
|
||||
span: string;
|
||||
}
|
||||
|
||||
export const resources: ResourceItem[] = [
|
||||
// --- BOOKS (4 Items) ---
|
||||
{
|
||||
id: "book-math",
|
||||
title: "Mathematics for Machine Learning",
|
||||
author: "Deisenroth, Faisal, Ong",
|
||||
type: "book",
|
||||
size: "17 MB",
|
||||
description: "The fundamental mathematical tools needed to understand machine learning.",
|
||||
link: "/books/mathematics-for-machine-learning.pdf",
|
||||
downloadUrl: "/books/mathematics-for-machine-learning.pdf",
|
||||
color: "rgb(132, 0, 255)", // Purple
|
||||
span: "md:col-span-1 md:row-span-2",
|
||||
},
|
||||
{
|
||||
id: "book-bishop",
|
||||
title: "Pattern Recognition & ML",
|
||||
author: "Christopher Bishop",
|
||||
type: "book",
|
||||
size: "17 MB",
|
||||
description: "A comprehensive guide to pattern recognition. The classic textbook.",
|
||||
link: "/books/pattern-recognition-and-machine-learning.pdf",
|
||||
downloadUrl: "/books/pattern-recognition-and-machine-learning.pdf",
|
||||
color: "rgb(6, 182, 212)", // Cyan
|
||||
span: "md:col-span-1 md:row-span-2",
|
||||
},
|
||||
{
|
||||
id: "book-geron",
|
||||
title: "Hands-On Machine Learning",
|
||||
author: "Aurélien Géron",
|
||||
type: "book",
|
||||
size: "19 MB",
|
||||
description: "Learn Scikit-Learn, Keras, and TensorFlow with practical examples.",
|
||||
link: "/books/hands-on-machine-learning.pdf",
|
||||
downloadUrl: "/books/hands-on-machine-learning.pdf",
|
||||
color: "rgb(255, 165, 0)", // Orange
|
||||
span: "md:col-span-1 md:row-span-2",
|
||||
},
|
||||
{
|
||||
id: "book-goodfellow",
|
||||
title: "Deep Learning",
|
||||
author: "Ian Goodfellow et al.",
|
||||
type: "book",
|
||||
size: "25 MB",
|
||||
description: "The Bible of Deep Learning. Covers theoretical foundations and modern architectures.",
|
||||
link: "/books/deep-learning.pdf",
|
||||
downloadUrl: "/books/deep-learning.pdf",
|
||||
color: "rgb(236, 72, 153)", // Pink
|
||||
span: "md:col-span-1 md:row-span-2",
|
||||
},
|
||||
|
||||
// --- VIDEOS (6 Items) ---
|
||||
{
|
||||
id: "vid-custom",
|
||||
title: "ML Essentials Playlist",
|
||||
author: "Rishi Das (NITR)",
|
||||
type: "video",
|
||||
description: "Curated collection of essential lectures for the team.",
|
||||
link: "https://youtube.com/playlist?list=PLKnIA16_Rmvbr7zKYQuBfsVkjoLcJgxHH&si=gRTfZe-hSD7WySmJ",
|
||||
color: "rgb(59, 130, 246)", // Blue
|
||||
span: "md:col-span-2 md:row-span-1",
|
||||
},
|
||||
{
|
||||
id: "vid-karpathy",
|
||||
title: "Neural Networks: Zero to Hero",
|
||||
author: "Andrej Karpathy",
|
||||
type: "video",
|
||||
description: "The best deep learning course available online. Builds everything from scratch.",
|
||||
link: "https://youtube.com/playlist?list=PLAqhIrjkxbuWI23v9cThsA9GvCAUhRvKZ&si=2kNG0A4Au3P4FFGu",
|
||||
color: "rgb(239, 68, 68)", // Red
|
||||
span: "md:col-span-1 md:row-span-1",
|
||||
},
|
||||
{
|
||||
id: "vid-cs229",
|
||||
title: "CS229: Machine Learning",
|
||||
author: "Stanford University",
|
||||
type: "video",
|
||||
description: "The legendary course that started it all. Deep dive into theory.",
|
||||
link: "https://youtube.com/playlist?list=PLoROMvodv4rMFqRtEuo6SGjY4XbRIVRd4&si=Dxd5SNKqosiMF43I",
|
||||
color: "rgb(16, 185, 129)", // Emerald
|
||||
span: "md:col-span-1 md:row-span-1",
|
||||
},
|
||||
{
|
||||
id: "vid-cs230",
|
||||
title: "CS230: Deep Learning",
|
||||
author: "Stanford University",
|
||||
type: "video",
|
||||
description: "Learn the foundations of Deep Learning, understand how to build neural networks.",
|
||||
link: "https://youtube.com/playlist?list=PLoROMvodv4rPLKxIpqhjhPgdQy7imNkDn&si=vYrxzQmrpR9mdeap",
|
||||
color: "rgb(139, 92, 246)", // Violet
|
||||
span: "md:col-span-2 md:row-span-1",
|
||||
},
|
||||
{
|
||||
id: "vid-huggingface",
|
||||
title: "Hugging Face Course",
|
||||
author: "Hugging Face",
|
||||
type: "video",
|
||||
description: "Master NLP and Transformers using the Hugging Face ecosystem.",
|
||||
link: "https://youtube.com/playlist?list=PLqzoL9-eJTNBZDG8jaNuhap1C9q6VHyVa&si=RQ8G8NEnshebHShB",
|
||||
color: "rgb(250, 204, 21)", // Yellow
|
||||
span: "md:col-span-1 md:row-span-1",
|
||||
},
|
||||
{
|
||||
id: "vid-cs231n",
|
||||
title: "CS231n: Vision",
|
||||
author: "Stanford University",
|
||||
type: "video",
|
||||
description: "Convolutional Neural Networks for Visual Recognition.",
|
||||
link: "https://youtube.com/playlist?list=PLC1qU-LWwrF64f4QKQT-Vg5Wr4qEE1Zxk&si=_fL7EVbhxugqrQiP",
|
||||
color: "rgb(236, 72, 153)", // Pink
|
||||
span: "md:col-span-1 md:row-span-1",
|
||||
}
|
||||
];
|
||||
@@ -24,6 +24,7 @@ const connectToAchievementsDB = async () => {
|
||||
await mongoose.connect(process.env.MongoURL, {
|
||||
dbName: "achievementDB",
|
||||
});
|
||||
|
||||
console.log("✅ Connected to Achievements MongoDB");
|
||||
} catch (error) {
|
||||
console.error("❌ MongoDB Achievements connection error:", error);
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user