feat: complete premium NEET/JEE platform with admin, student dashboards, and upgraded branding

This commit is contained in:
2026-06-24 13:47:25 +05:30
parent 6764521f83
commit ce01795aa9
44 changed files with 3131 additions and 76 deletions

526
package-lock.json generated
View File

@@ -8,15 +8,22 @@
"name": "pragativeer-v2", "name": "pragativeer-v2",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"clsx": "^2.1.1",
"framer-motion": "^12.41.0",
"lucide-react": "^1.21.0",
"next": "16.2.9", "next": "16.2.9",
"react": "19.2.4", "react": "19.2.4",
"react-dom": "19.2.4" "react-dom": "19.2.4",
"react-katex": "^3.1.0",
"recharts": "^3.9.0",
"tailwind-merge": "^3.6.0"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/postcss": "^4", "@tailwindcss/postcss": "^4",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^19", "@types/react": "^19",
"@types/react-dom": "^19", "@types/react-dom": "^19",
"@types/react-katex": "^3.0.4",
"eslint": "^9", "eslint": "^9",
"eslint-config-next": "16.2.9", "eslint-config-next": "16.2.9",
"tailwindcss": "^4", "tailwindcss": "^4",
@@ -1246,6 +1253,42 @@
"node": ">=12.4.0" "node": ">=12.4.0"
} }
}, },
"node_modules/@reduxjs/toolkit": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz",
"integrity": "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==",
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.0.0",
"@standard-schema/utils": "^0.3.0",
"immer": "^11.0.0",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
"reselect": "^5.1.0"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@reduxjs/toolkit/node_modules/immer": {
"version": "11.1.8",
"resolved": "https://registry.npmjs.org/immer/-/immer-11.1.8.tgz",
"integrity": "sha512-/tbkHMW7y10Lx6i1crLjD4/OhNkRG+Fo7byZHtah0547nIeXYcpIXaUh0IAQY6gO5459qpGGYapcEOHtFXkIuA==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/@rtsao/scc": { "node_modules/@rtsao/scc": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
@@ -1253,6 +1296,18 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@standard-schema/spec": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
"license": "MIT"
},
"node_modules/@standard-schema/utils": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
"integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
"license": "MIT"
},
"node_modules/@swc/helpers": { "node_modules/@swc/helpers": {
"version": "0.5.15", "version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -1544,6 +1599,69 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@types/d3-array": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
"integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
"license": "MIT"
},
"node_modules/@types/d3-color": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
"integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
"license": "MIT"
},
"node_modules/@types/d3-ease": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
"integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
"license": "MIT"
},
"node_modules/@types/d3-interpolate": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
"integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
"license": "MIT",
"dependencies": {
"@types/d3-color": "*"
}
},
"node_modules/@types/d3-path": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
"integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
"license": "MIT"
},
"node_modules/@types/d3-scale": {
"version": "4.0.9",
"resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
"integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
"license": "MIT",
"dependencies": {
"@types/d3-time": "*"
}
},
"node_modules/@types/d3-shape": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz",
"integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==",
"license": "MIT",
"dependencies": {
"@types/d3-path": "*"
}
},
"node_modules/@types/d3-time": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
"integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
"license": "MIT"
},
"node_modules/@types/d3-timer": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
"integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
"license": "MIT"
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.9", "version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
@@ -1579,7 +1697,7 @@
"version": "19.2.17", "version": "19.2.17",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz",
"integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"csstype": "^3.2.2" "csstype": "^3.2.2"
@@ -1595,6 +1713,22 @@
"@types/react": "^19.2.0" "@types/react": "^19.2.0"
} }
}, },
"node_modules/@types/react-katex": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/react-katex/-/react-katex-3.0.4.tgz",
"integrity": "sha512-aLkykKzSKLpXI6REJ3uClao6P47HAFfR1gcHOZwDeTuALsyjgMhz+oynLV4gX0kiJVnvHrBKF/TLXqyNTpHDUg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/use-sync-external-store": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
"integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.62.0", "version": "8.62.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.62.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.62.0.tgz",
@@ -2680,6 +2814,15 @@
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
"license": "MIT" "license": "MIT"
}, },
"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": { "node_modules/color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -2700,6 +2843,15 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"license": "MIT",
"engines": {
"node": ">= 12"
}
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -2733,9 +2885,130 @@
"version": "3.2.3", "version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"dev": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/d3-array": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
"integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
"license": "ISC",
"dependencies": {
"internmap": "1 - 2"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-color": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-ease": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-format": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
"integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-interpolate": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
"license": "ISC",
"dependencies": {
"d3-color": "1 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-path": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
"integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-scale": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
"license": "ISC",
"dependencies": {
"d3-array": "2.10.0 - 3",
"d3-format": "1 - 3",
"d3-interpolate": "1.2.0 - 3",
"d3-time": "2.1.1 - 3",
"d3-time-format": "2 - 4"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-shape": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
"integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
"license": "ISC",
"dependencies": {
"d3-path": "^3.1.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-time": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
"integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
"license": "ISC",
"dependencies": {
"d3-array": "2 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-time-format": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
"license": "ISC",
"dependencies": {
"d3-time": "1 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-timer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
"integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/damerau-levenshtein": { "node_modules/damerau-levenshtein": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -2815,6 +3088,12 @@
} }
} }
}, },
"node_modules/decimal.js-light": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
"integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
"license": "MIT"
},
"node_modules/deep-is": { "node_modules/deep-is": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -3122,6 +3401,16 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/es-toolkit": {
"version": "1.48.1",
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.48.1.tgz",
"integrity": "sha512-wfnXlwd5I75eXRtdD2vuEs50xHHESECDsGD7yiQnfFVNoa5522NwXEbmgo98LfiukSQHs+mBM7/YG3qKJB9/mQ==",
"license": "MIT",
"workspaces": [
"docs",
"benchmarks"
]
},
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -3551,6 +3840,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/eventemitter3": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
"integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
"license": "MIT"
},
"node_modules/fast-deep-equal": { "node_modules/fast-deep-equal": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -3692,6 +3987,33 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/framer-motion": {
"version": "12.41.0",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.41.0.tgz",
"integrity": "sha512-OHAMNiCEON1RDBlRGuulsN5AD8ptMjvk5QWfFmYmBLPZ3zFGIJe60kQucQQf4cez1OzQmjYBWDY+dYfISkUdqg==",
"license": "MIT",
"dependencies": {
"motion-dom": "^12.41.0",
"motion-utils": "^12.39.0",
"tslib": "^2.4.0"
},
"peerDependencies": {
"@emotion/is-prop-valid": "*",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@emotion/is-prop-valid": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -4010,6 +4332,16 @@
"node": ">= 4" "node": ">= 4"
} }
}, },
"node_modules/immer": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz",
"integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -4052,6 +4384,15 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/internmap": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/is-array-buffer": { "node_modules/is-array-buffer": {
"version": "3.0.5", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
@@ -4529,7 +4870,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
@@ -4618,6 +4958,22 @@
"node": ">=4.0" "node": ">=4.0"
} }
}, },
"node_modules/katex": {
"version": "0.16.47",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
],
"license": "MIT",
"dependencies": {
"commander": "^8.3.0"
},
"bin": {
"katex": "cli.js"
}
},
"node_modules/keyv": { "node_modules/keyv": {
"version": "4.5.4", "version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -4950,7 +5306,6 @@
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0" "js-tokens": "^3.0.0 || ^4.0.0"
@@ -4969,6 +5324,15 @@
"yallist": "^3.0.2" "yallist": "^3.0.2"
} }
}, },
"node_modules/lucide-react": {
"version": "1.21.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.21.0.tgz",
"integrity": "sha512-reEZMXq8Qdd5jg5XYkQ5TR1fB/GiQ7ih4vcrthYDtgjSDwh0i6/YLiGjsWsIwgN49gpAnd4J2elSNzncMEEUUQ==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.30.21", "version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -5036,6 +5400,21 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/motion-dom": {
"version": "12.41.0",
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.41.0.tgz",
"integrity": "sha512-Lk3J39fOGg6xNr1KRZsN6usDyBf8aP7MEbUPez1VCughHt79OrP7VGqNrPyFL0riaT7WS8t9DRw1M3BHtM/xKw==",
"license": "MIT",
"dependencies": {
"motion-utils": "^12.39.0"
}
},
"node_modules/motion-utils": {
"version": "12.39.0",
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz",
"integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==",
"license": "MIT"
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -5198,7 +5577,6 @@
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@@ -5497,7 +5875,6 @@
"version": "15.8.1", "version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"loose-envify": "^1.4.0", "loose-envify": "^1.4.0",
@@ -5561,9 +5938,89 @@
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/react-katex": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/react-katex/-/react-katex-3.1.0.tgz",
"integrity": "sha512-At9uLOkC75gwn2N+ZXc5HD8TlATsB+3Hkp9OGs6uA8tM3dwZ3Wljn74Bk3JyHFPgSnesY/EMrIAB1WJwqZqejA==",
"license": "MIT",
"dependencies": {
"katex": "^0.16.0"
},
"peerDependencies": {
"prop-types": "^15.8.1",
"react": ">=15.3.2 <20"
}
},
"node_modules/react-redux": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz",
"integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==",
"license": "MIT",
"dependencies": {
"@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0"
},
"peerDependencies": {
"@types/react": "^18.2.25 || ^19",
"react": "^18.0 || ^19",
"redux": "^5.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/recharts": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/recharts/-/recharts-3.9.0.tgz",
"integrity": "sha512-dCEcE9y20c8H2tkVeByrAXhhnBJk6/QLbxKmn+dJUptOfc5NMjwRh1jo0vZPRLD+5dMrHrP+hPEsfbGBMfnf5Q==",
"license": "MIT",
"workspaces": [
"www"
],
"dependencies": {
"@reduxjs/toolkit": "^1.9.0 || 2.x.x",
"clsx": "^2.1.1",
"decimal.js-light": "^2.5.1",
"es-toolkit": "^1.39.3",
"eventemitter3": "^5.0.1",
"immer": "^10.1.1",
"react-redux": "8.x.x || 9.x.x",
"reselect": "5.2.0",
"tiny-invariant": "^1.3.3",
"use-sync-external-store": "^1.2.2",
"victory-vendor": "^37.0.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/redux": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"license": "MIT"
},
"node_modules/redux-thunk": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
"license": "MIT",
"peerDependencies": {
"redux": "^5.0.0"
}
},
"node_modules/reflect.getprototypeof": { "node_modules/reflect.getprototypeof": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -5608,6 +6065,12 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/reselect": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.2.0.tgz",
"integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==",
"license": "MIT"
},
"node_modules/resolve": { "node_modules/resolve": {
"version": "2.0.0-next.7", "version": "2.0.0-next.7",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
@@ -6180,6 +6643,16 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/tailwind-merge": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz",
"integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/tailwindcss": { "node_modules/tailwindcss": {
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.1.tgz", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.1.tgz",
@@ -6201,6 +6674,12 @@
"url": "https://opencollective.com/webpack" "url": "https://opencollective.com/webpack"
} }
}, },
"node_modules/tiny-invariant": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
"license": "MIT"
},
"node_modules/tinyglobby": { "node_modules/tinyglobby": {
"version": "0.2.17", "version": "0.2.17",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
@@ -6541,6 +7020,37 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/use-sync-external-store": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/victory-vendor": {
"version": "37.3.6",
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz",
"integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==",
"license": "MIT AND ISC",
"dependencies": {
"@types/d3-array": "^3.0.3",
"@types/d3-ease": "^3.0.0",
"@types/d3-interpolate": "^3.0.1",
"@types/d3-scale": "^4.0.2",
"@types/d3-shape": "^3.1.0",
"@types/d3-time": "^3.0.0",
"@types/d3-timer": "^3.0.0",
"d3-array": "^3.1.6",
"d3-ease": "^3.0.1",
"d3-interpolate": "^3.0.1",
"d3-scale": "^4.0.2",
"d3-shape": "^3.1.0",
"d3-time": "^3.0.0",
"d3-timer": "^3.0.1"
}
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@@ -9,15 +9,22 @@
"lint": "eslint" "lint": "eslint"
}, },
"dependencies": { "dependencies": {
"clsx": "^2.1.1",
"framer-motion": "^12.41.0",
"lucide-react": "^1.21.0",
"next": "16.2.9", "next": "16.2.9",
"react": "19.2.4", "react": "19.2.4",
"react-dom": "19.2.4" "react-dom": "19.2.4",
"react-katex": "^3.1.0",
"recharts": "^3.9.0",
"tailwind-merge": "^3.6.0"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/postcss": "^4", "@tailwindcss/postcss": "^4",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^19", "@types/react": "^19",
"@types/react-dom": "^19", "@types/react-dom": "^19",
"@types/react-katex": "^3.0.4",
"eslint": "^9", "eslint": "^9",
"eslint-config-next": "16.2.9", "eslint-config-next": "16.2.9",
"tailwindcss": "^4", "tailwindcss": "^4",

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 494 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 460 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.4 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
public/course_business.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 KiB

BIN
public/course_design.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 KiB

BIN
public/course_tech.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

24
src/app/about/page.tsx Normal file
View File

@@ -0,0 +1,24 @@
import { Button } from "@/components/ui/button"
import Link from "next/link"
import { ArrowLeft } from "lucide-react"
export default function AboutPage() {
return (
<div className="min-h-screen bg-background text-foreground flex flex-col">
<header className="border-b border-border bg-background px-6 py-4 flex items-center justify-between sticky top-0 z-10">
<Link href="/" className="text-muted-foreground hover:text-foreground flex items-center gap-2 transition-colors font-medium">
<ArrowLeft size={16} /> Back to Home
</Link>
</header>
<main className="flex-1 flex flex-col items-center justify-center p-8 text-center animate-in fade-in duration-700">
<h1 className="text-5xl font-bold tracking-tighter mb-6">About PragatiVeer</h1>
<p className="text-xl text-muted-foreground max-w-2xl leading-relaxed mb-8">
We are a team of educators and engineers dedicated to re-engineering NEET/JEE preparation through the power of Artificial Intelligence.
</p>
<Link href="/signup">
<Button size="lg" className="rounded-full font-bold px-8 shadow-xl">Join the Revolution</Button>
</Link>
</main>
</div>
)
}

View File

@@ -0,0 +1,87 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Activity, BrainCircuit, Zap, Server, ShieldCheck } from "lucide-react"
export default function AgentsPage() {
const agents = [
{ name: "DPP Generator Node", status: "Healthy", latency: "140ms", tokens: "4.2M", successRate: "99.9%" },
{ name: "Tutor Agent (Physics)", status: "Healthy", latency: "320ms", tokens: "8.1M", successRate: "98.5%" },
{ name: "Tutor Agent (Chem/Bio)", status: "Healthy", latency: "290ms", tokens: "6.5M", successRate: "99.1%" },
{ name: "Evaluator Node", status: "Under Load", latency: "850ms", tokens: "12.4M", successRate: "97.2%" },
]
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div>
<h1 className="text-3xl font-bold tracking-tight">AI Agents Monitor</h1>
<p className="text-muted-foreground mt-1">Real-time telemetry for internal LLM orchestration nodes.</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Card className="border-border bg-secondary/10">
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Global API Status</CardTitle>
</CardHeader>
<CardContent>
<div className="text-3xl font-bold flex items-center gap-3">
<div className="size-3 rounded-full bg-[#00F0FF] animate-pulse"></div> Operational
</div>
</CardContent>
</Card>
<Card className="border-border bg-secondary/10">
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Total Tokens Used (24h)</CardTitle>
</CardHeader>
<CardContent>
<div className="text-3xl font-bold text-primary">31.2M</div>
</CardContent>
</Card>
<Card className="border-border bg-secondary/10">
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Avg Generation Latency</CardTitle>
</CardHeader>
<CardContent>
<div className="text-3xl font-bold">400ms</div>
</CardContent>
</Card>
</div>
<h2 className="text-xl font-bold pt-4 border-b border-border pb-2">Active Microservices</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{agents.map((agent, i) => (
<Card key={i} className={`border ${agent.status === 'Healthy' ? 'border-border' : 'border-yellow-500/50 shadow-[0_0_15px_-5px_rgba(234,179,8,0.3)]'} bg-background`}>
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-lg font-bold flex items-center gap-2">
<BrainCircuit className="text-[#00F0FF]" size={20} /> {agent.name}
</CardTitle>
<div className={`px-2.5 py-0.5 rounded-full text-xs font-bold ${agent.status === 'Healthy' ? 'bg-[#00F0FF]/10 text-[#00F0FF]' : 'bg-yellow-500/10 text-yellow-500 animate-pulse'}`}>
{agent.status}
</div>
</CardHeader>
<CardContent>
<div className="grid grid-cols-3 gap-4 mt-4">
<div className="space-y-1">
<div className="text-xs text-muted-foreground flex items-center gap-1"><Zap size={12}/> Latency</div>
<div className="font-mono text-lg">{agent.latency}</div>
</div>
<div className="space-y-1">
<div className="text-xs text-muted-foreground flex items-center gap-1"><Server size={12}/> Tokens</div>
<div className="font-mono text-lg">{agent.tokens}</div>
</div>
<div className="space-y-1">
<div className="text-xs text-muted-foreground flex items-center gap-1"><ShieldCheck size={12}/> Success</div>
<div className="font-mono text-lg">{agent.successRate}</div>
</div>
</div>
<div className="w-full bg-secondary h-1.5 rounded-full mt-6 overflow-hidden">
<div
className={`h-full ${agent.status === 'Healthy' ? 'bg-[#00F0FF]' : 'bg-yellow-500'}`}
style={{ width: agent.successRate }}
></div>
</div>
</CardContent>
</Card>
))}
</div>
</div>
)
}

62
src/app/admin/layout.tsx Normal file
View File

@@ -0,0 +1,62 @@
"use client"
import { ReactNode } from "react"
import { LayoutDashboard, Users, Database, Terminal, Settings } from "lucide-react"
import Link from "next/link"
import Image from "next/image"
import { usePathname } from "next/navigation"
export default function AdminLayout({ children }: { children: ReactNode }) {
const pathname = usePathname()
return (
<div className="flex h-screen bg-background overflow-hidden text-foreground selection:bg-[#00F0FF]/20">
{/* Sidebar */}
<aside className="w-64 border-r border-border bg-secondary/10 flex flex-col hidden md:flex">
<div className="p-6 border-b border-border">
<Link href="/admin" className="block relative h-16 w-full hover:opacity-90 transition-opacity">
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
alt="PragatiVeer Admin" fill className="object-contain object-left scale-135 origin-left dark:hidden" priority
/>
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
alt="PragatiVeer Admin" fill className="object-contain object-left scale-135 origin-left hidden dark:block" priority
/>
</Link>
<div className="mt-3 text-xs font-bold uppercase tracking-widest text-[#00F0FF]">Admin Panel</div>
</div>
<nav className="flex-1 px-4 space-y-1.5 mt-6">
<NavItem href="/admin" icon={<LayoutDashboard size={18} />} label="Command Center" active={pathname === "/admin"} />
<NavItem href="/admin/questions" icon={<Database size={18} />} label="Question Bank" active={pathname.startsWith("/admin/questions")} />
<NavItem href="/admin/agents" icon={<Terminal size={18} />} label="AI Agents" active={pathname.startsWith("/admin/agents")} />
<NavItem href="/admin/students" icon={<Users size={18} />} label="Students" active={pathname.startsWith("/admin/students")} />
</nav>
<div className="p-4 border-t border-border">
<NavItem href="/admin/settings" icon={<Settings size={18} />} label="System Settings" active={pathname.startsWith("/admin/settings")} />
</div>
</aside>
{/* Main Content */}
<main className="flex-1 overflow-y-auto bg-background">
{children}
</main>
</div>
)
}
function NavItem({ href, icon, label, active }: { href: string, icon: React.ReactNode, label: string, active?: boolean }) {
return (
<Link
href={href}
className={`flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-300 ${
active
? "bg-[#00F0FF]/10 text-[#00F0FF] font-medium border border-[#00F0FF]/20"
: "text-muted-foreground hover:bg-secondary hover:text-foreground font-medium"
}`}
>
{icon}
<span className="text-sm">{label}</span>
</Link>
)
}

200
src/app/admin/page.tsx Normal file
View File

@@ -0,0 +1,200 @@
"use client"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Terminal, Users, Database, Activity, RefreshCw } from "lucide-react"
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area } from 'recharts'
const data = [
{ name: 'Mon', accuracy: 88, tokens: 1.2 },
{ name: 'Tue', accuracy: 90, tokens: 1.5 },
{ name: 'Wed', accuracy: 89, tokens: 1.8 },
{ name: 'Thu', accuracy: 92, tokens: 2.1 },
{ name: 'Fri', accuracy: 95, tokens: 2.4 },
{ name: 'Sat', accuracy: 94, tokens: 2.2 },
{ name: 'Sun', accuracy: 96, tokens: 2.8 },
];
export default function AdminDashboard() {
return (
<div className="p-8 max-w-7xl mx-auto space-y-8 animate-in fade-in duration-500">
<header className="flex items-center justify-between border-b border-border pb-6">
<div>
<h1 className="text-3xl font-bold tracking-tighter text-foreground">Command Center</h1>
<p className="text-muted-foreground mt-1 font-medium">Real-time system monitoring and agent status.</p>
</div>
<Button variant="outline" className="gap-2 border-[#00F0FF]/50 text-[#00F0FF] bg-[#00F0FF]/5 hover:bg-[#00F0FF]/10 hover:text-[#00F0FF] rounded-xl font-medium shadow-[0_0_15px_-5px_#00F0FF]">
<RefreshCw size={16} /> Refresh Data
</Button>
</header>
{/* KPI Stats */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<Card className="bg-secondary/10 border-border/50 rounded-2xl">
<CardHeader className="pb-2 flex flex-row items-center justify-between">
<CardTitle className="text-sm font-medium text-muted-foreground">Total Revenue</CardTitle>
<div className="p-2 bg-primary/20 text-primary rounded-lg"><Activity size={16}/></div>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">₹12.4M</div>
<p className="text-xs text-primary mt-1 font-medium">+14.2% from last month</p>
</CardContent>
</Card>
<Card className="bg-secondary/10 border-border/50 rounded-2xl">
<CardHeader className="pb-2 flex flex-row items-center justify-between">
<CardTitle className="text-sm font-medium text-muted-foreground">Active Students</CardTitle>
<div className="p-2 bg-secondary text-foreground rounded-lg"><Users size={16}/></div>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">45,231</div>
<p className="text-xs text-muted-foreground mt-1 font-medium">+2,401 this week</p>
</CardContent>
</Card>
<Card className="bg-[#00F0FF]/5 border-[#00F0FF]/30 shadow-[0_0_20px_-10px_#00F0FF] rounded-2xl">
<CardHeader className="pb-2 flex flex-row items-center justify-between">
<CardTitle className="text-sm font-medium text-muted-foreground">AI Agent Accuracy</CardTitle>
<div className="p-2 bg-[#00F0FF]/20 text-[#00F0FF] rounded-lg"><Terminal size={16}/></div>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-[#00F0FF]">96.4%</div>
<p className="text-xs text-[#00F0FF]/70 mt-1 font-medium">Based on 1.2M interactions</p>
</CardContent>
</Card>
<Card className="bg-secondary/10 border-border/50 rounded-2xl">
<CardHeader className="pb-2 flex flex-row items-center justify-between">
<CardTitle className="text-sm font-medium text-muted-foreground">Question Bank</CardTitle>
<div className="p-2 bg-secondary text-foreground rounded-lg"><Database size={16}/></div>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">142k</div>
<p className="text-xs text-muted-foreground mt-1 font-medium">1.2k added today</p>
</CardContent>
</Card>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Charts */}
<Card className="lg:col-span-2 bg-background border-border rounded-3xl">
<CardHeader>
<CardTitle>AI Token Usage vs Accuracy</CardTitle>
</CardHeader>
<CardContent className="h-[300px] w-full">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={data} margin={{ top: 10, right: 30, left: 0, bottom: 0 }}>
<defs>
<linearGradient id="colorTokens" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#00F0FF" stopOpacity={0.3}/>
<stop offset="95%" stopColor="#00F0FF" stopOpacity={0}/>
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke="#262626" vertical={false} />
<XAxis dataKey="name" stroke="#737373" fontSize={12} tickLine={false} axisLine={false} />
<YAxis stroke="#737373" fontSize={12} tickLine={false} axisLine={false} tickFormatter={(value) => `${value}M`} />
<Tooltip
contentStyle={{ backgroundColor: '#0a0a0a', borderColor: '#262626', borderRadius: '12px' }}
itemStyle={{ color: '#00F0FF', fontWeight: 'bold' }}
/>
<Area type="monotone" dataKey="tokens" stroke="#00F0FF" strokeWidth={3} fillOpacity={1} fill="url(#colorTokens)" />
</AreaChart>
</ResponsiveContainer>
</CardContent>
</Card>
{/* Live Agent Status */}
<Card className="bg-background border-border flex flex-col rounded-3xl">
<CardHeader>
<CardTitle>Live Agent Status</CardTitle>
</CardHeader>
<CardContent className="flex-1 overflow-y-auto pr-2 space-y-4">
<div className="flex items-center justify-between p-4 rounded-2xl border border-border bg-secondary/10">
<div className="flex items-center gap-4">
<div className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-emerald-500"></span>
</div>
<div>
<h4 className="text-sm font-bold">DPP Generator</h4>
<p className="text-xs text-muted-foreground font-mono mt-1">Latency: 142ms</p>
</div>
</div>
<Badge variant="outline" className="text-emerald-500 border-emerald-500/30 bg-emerald-500/10 font-bold">Healthy</Badge>
</div>
<div className="flex items-center justify-between p-4 rounded-2xl border border-border bg-secondary/10">
<div className="flex items-center gap-4">
<div className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-emerald-500"></span>
</div>
<div>
<h4 className="text-sm font-bold">Tutor Agent</h4>
<p className="text-xs text-muted-foreground font-mono mt-1">Latency: 840ms</p>
</div>
</div>
<Badge variant="outline" className="text-emerald-500 border-emerald-500/30 bg-emerald-500/10 font-bold">Healthy</Badge>
</div>
<div className="flex items-center justify-between p-4 rounded-2xl border border-amber-500/30 bg-amber-500/5">
<div className="flex items-center gap-4">
<div className="relative flex h-3 w-3">
<span className="relative inline-flex rounded-full h-3 w-3 bg-amber-500"></span>
</div>
<div>
<h4 className="text-sm font-bold text-amber-500">Evaluator Node</h4>
<p className="text-xs text-amber-500/70 font-mono mt-1">Latency: 2100ms</p>
</div>
</div>
<Badge variant="outline" className="text-amber-500 border-amber-500/30 bg-amber-500/10 font-bold">Degraded</Badge>
</div>
</CardContent>
</Card>
</div>
{/* Question Bank Manager Preview */}
<Card className="bg-background border-border rounded-3xl">
<CardHeader className="flex flex-row items-center justify-between">
<div>
<CardTitle>Recent Question Uploads</CardTitle>
</div>
<Button size="sm" className="bg-[#00F0FF] text-black hover:bg-[#00F0FF]/90 font-bold rounded-xl h-10 px-4">Add Question</Button>
</CardHeader>
<CardContent>
<div className="rounded-2xl border border-border overflow-hidden">
<table className="w-full text-sm text-left">
<thead className="bg-secondary/50 text-muted-foreground font-medium border-b border-border">
<tr>
<th className="px-5 py-4">ID</th>
<th className="px-5 py-4">Subject</th>
<th className="px-5 py-4">Topic</th>
<th className="px-5 py-4">Preview</th>
<th className="px-5 py-4 text-right">Actions</th>
</tr>
</thead>
<tbody className="divide-y divide-border">
<tr className="hover:bg-secondary/20 transition-colors">
<td className="px-5 py-4 font-mono text-muted-foreground font-medium">#Q-8942</td>
<td className="px-5 py-4"><Badge variant="outline" className="bg-background">Physics</Badge></td>
<td className="px-5 py-4 font-medium">Thermodynamics</td>
<td className="px-5 py-4 text-muted-foreground truncate max-w-[300px]">An ideal gas undergoes an isothermal expansion...</td>
<td className="px-5 py-4 text-right">
<Button variant="ghost" size="sm" className="text-[#00F0FF] hover:text-[#00F0FF] hover:bg-[#00F0FF]/10 font-bold rounded-lg">Edit</Button>
</td>
</tr>
<tr className="hover:bg-secondary/20 transition-colors">
<td className="px-5 py-4 font-mono text-muted-foreground font-medium">#Q-8941</td>
<td className="px-5 py-4"><Badge variant="outline" className="bg-background">Math</Badge></td>
<td className="px-5 py-4 font-medium">Calculus</td>
<td className="px-5 py-4 text-muted-foreground truncate max-w-[300px]">Evaluate the integral of e^x sin(x) dx...</td>
<td className="px-5 py-4 text-right">
<Button variant="ghost" size="sm" className="text-[#00F0FF] hover:text-[#00F0FF] hover:bg-[#00F0FF]/10 font-bold rounded-lg">Edit</Button>
</td>
</tr>
</tbody>
</table>
</div>
</CardContent>
</Card>
</div>
)
}

View File

@@ -0,0 +1,102 @@
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Search, Plus, Filter, MoreHorizontal, Edit, Trash } from "lucide-react"
export default function QuestionsPage() {
const questions = [
{ id: "Q-NEET-2026-001", subject: "Physics", chapter: "Thermodynamics", type: "MCQ", difficulty: "Hard", status: "Active" },
{ id: "Q-NEET-2026-002", subject: "Chemistry", chapter: "Organic Chemistry", type: "Assertion/Reason", difficulty: "Medium", status: "Active" },
{ id: "Q-JEE-2026-003", subject: "Mathematics", chapter: "Calculus", type: "Numerical", difficulty: "Expert", status: "Review" },
{ id: "Q-NEET-2026-004", subject: "Biology", chapter: "Genetics", type: "MCQ", difficulty: "Easy", status: "Active" },
{ id: "Q-JEE-2026-005", subject: "Physics", chapter: "Mechanics", type: "MCQ", difficulty: "Medium", status: "Draft" },
]
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="flex justify-between items-center">
<div>
<h1 className="text-3xl font-bold tracking-tight">Question Bank</h1>
<p className="text-muted-foreground mt-1">Manage and curate the global repository for NEET/JEE.</p>
</div>
<div className="flex gap-4">
<Button variant="outline" className="border-border hover:bg-secondary"><Filter size={16} className="mr-2"/> Filter</Button>
<Button className="bg-[#00F0FF] text-background hover:bg-[#00F0FF]/90 font-bold"><Plus size={16} className="mr-2"/> Add Question</Button>
</div>
</div>
<div className="bg-secondary/10 border border-border rounded-xl overflow-hidden backdrop-blur-sm">
<div className="p-4 border-b border-border flex items-center gap-4">
<div className="relative flex-1 max-w-md">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" size={16} />
<input
type="text"
placeholder="Search by ID, concept, or chapter..."
className="w-full bg-background border border-border rounded-lg pl-10 pr-4 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#00F0FF]"
/>
</div>
</div>
<div className="overflow-x-auto">
<table className="w-full text-left text-sm whitespace-nowrap">
<thead className="bg-secondary/30 text-muted-foreground border-b border-border">
<tr>
<th className="px-6 py-4 font-semibold">Question ID</th>
<th className="px-6 py-4 font-semibold">Subject</th>
<th className="px-6 py-4 font-semibold">Chapter</th>
<th className="px-6 py-4 font-semibold">Type</th>
<th className="px-6 py-4 font-semibold">Difficulty</th>
<th className="px-6 py-4 font-semibold">Status</th>
<th className="px-6 py-4 font-semibold text-right">Actions</th>
</tr>
</thead>
<tbody className="divide-y divide-border">
{questions.map((q) => (
<tr key={q.id} className="hover:bg-secondary/20 transition-colors">
<td className="px-6 py-4 font-mono font-medium">{q.id}</td>
<td className="px-6 py-4">
<Badge variant="outline" className="bg-background">{q.subject}</Badge>
</td>
<td className="px-6 py-4">{q.chapter}</td>
<td className="px-6 py-4 text-muted-foreground">{q.type}</td>
<td className="px-6 py-4">
<Badge className={
q.difficulty === "Expert" ? "bg-red-500/10 text-red-500 border-red-500/20" :
q.difficulty === "Hard" ? "bg-orange-500/10 text-orange-500 border-orange-500/20" :
q.difficulty === "Medium" ? "bg-yellow-500/10 text-yellow-500 border-yellow-500/20" :
"bg-green-500/10 text-green-500 border-green-500/20"
} variant="outline">
{q.difficulty}
</Badge>
</td>
<td className="px-6 py-4">
<Badge className={
q.status === "Active" ? "bg-[#00F0FF]/10 text-[#00F0FF] border-[#00F0FF]/20" :
q.status === "Review" ? "bg-yellow-500/10 text-yellow-500 border-yellow-500/20" :
"bg-muted/50 text-muted-foreground border-border"
} variant="outline">
{q.status}
</Badge>
</td>
<td className="px-6 py-4 text-right">
<div className="flex justify-end gap-2 text-muted-foreground">
<button className="p-1.5 hover:text-[#00F0FF] hover:bg-secondary rounded"><Edit size={16} /></button>
<button className="p-1.5 hover:text-red-500 hover:bg-secondary rounded"><Trash size={16} /></button>
<button className="p-1.5 hover:text-foreground hover:bg-secondary rounded"><MoreHorizontal size={16} /></button>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="p-4 border-t border-border flex justify-between items-center text-sm text-muted-foreground">
<span>Showing 1 to 5 of 12,405 entries</span>
<div className="flex gap-2">
<Button variant="outline" size="sm" disabled>Previous</Button>
<Button variant="outline" size="sm">Next</Button>
</div>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,69 @@
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
export default function SettingsPage() {
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-4xl">
<div>
<h1 className="text-3xl font-bold tracking-tight">System Settings</h1>
<p className="text-muted-foreground mt-1">Configure global application variables and security protocols.</p>
</div>
<div className="space-y-6">
<Card className="border-border bg-secondary/10">
<CardHeader>
<CardTitle>AI Inference Configuration</CardTitle>
<CardDescription>Manage the underlying LLM models and API keys for the AI agents.</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-bold">Primary Model Name</label>
<input type="text" defaultValue="gemini-1.5-pro-experimental" className="w-full bg-background border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#00F0FF]" />
</div>
<div className="space-y-2">
<label className="text-sm font-bold">OpenAI API Key (Fallback)</label>
<input type="password" defaultValue="sk-........................" className="w-full bg-background border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#00F0FF]" />
</div>
<Button className="bg-[#00F0FF] text-background hover:bg-[#00F0FF]/90 font-bold">Save Configuration</Button>
</CardContent>
</Card>
<Card className="border-border bg-secondary/10">
<CardHeader>
<CardTitle>Platform Maintenance</CardTitle>
<CardDescription>Global toggles for site availability.</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-center justify-between p-4 bg-background border border-border rounded-xl">
<div>
<div className="font-bold">Maintenance Mode</div>
<div className="text-sm text-muted-foreground">Disable all student access and show maintenance screen.</div>
</div>
<div className="h-6 w-11 rounded-full bg-secondary border border-border relative cursor-pointer">
<div className="absolute left-1 top-1 size-4 bg-muted-foreground rounded-full"></div>
</div>
</div>
<div className="flex items-center justify-between p-4 bg-background border border-border rounded-xl">
<div>
<div className="font-bold">Allow New Registrations</div>
<div className="text-sm text-muted-foreground">Open the `/signup` route for new users.</div>
</div>
<div className="h-6 w-11 rounded-full bg-primary border border-primary relative cursor-pointer shadow-[0_0_10px_var(--color-primary)]">
<div className="absolute right-1 top-1 size-4 bg-primary-foreground rounded-full"></div>
</div>
</div>
</CardContent>
</Card>
<Card className="border-red-500/20 bg-red-500/5">
<CardHeader>
<CardTitle className="text-red-500">Danger Zone</CardTitle>
</CardHeader>
<CardContent>
<Button className="bg-red-500 text-white hover:bg-red-600 font-bold">Purge Generated Cache</Button>
</CardContent>
</Card>
</div>
</div>
)
}

View File

@@ -0,0 +1,79 @@
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Search, Download, MoreVertical } from "lucide-react"
export default function StudentsPage() {
const students = [
{ id: "STU-001", name: "Rahul Sharma", email: "rahul@example.com", tier: "AI Pro", target: "NEET", joined: "Oct 12, 2025", tests: 42 },
{ id: "STU-002", name: "Priya Patel", email: "priya@example.com", tier: "Basic", target: "JEE Main", joined: "Nov 05, 2025", tests: 14 },
{ id: "STU-003", name: "Amit Kumar", email: "amit@example.com", tier: "AI Pro", target: "JEE Adv", joined: "Dec 01, 2025", tests: 89 },
{ id: "STU-004", name: "Sneha Reddy", email: "sneha@example.com", tier: "AI Pro", target: "NEET", joined: "Dec 15, 2025", tests: 34 },
{ id: "STU-005", name: "Vikram Singh", email: "vikram@example.com", tier: "Basic", target: "NEET", joined: "Jan 10, 2026", tests: 5 },
]
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="flex justify-between items-center">
<div>
<h1 className="text-3xl font-bold tracking-tight">Student Directory</h1>
<p className="text-muted-foreground mt-1">Manage users, view engagement, and handle subscriptions.</p>
</div>
<Button variant="outline" className="border-border hover:bg-secondary"><Download size={16} className="mr-2"/> Export CSV</Button>
</div>
<div className="bg-secondary/10 border border-border rounded-xl overflow-hidden backdrop-blur-sm">
<div className="p-4 border-b border-border flex items-center gap-4">
<div className="relative flex-1 max-w-md">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" size={16} />
<input
type="text"
placeholder="Search by name, email, or ID..."
className="w-full bg-background border border-border rounded-lg pl-10 pr-4 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-primary"
/>
</div>
</div>
<div className="overflow-x-auto">
<table className="w-full text-left text-sm whitespace-nowrap">
<thead className="bg-secondary/30 text-muted-foreground border-b border-border">
<tr>
<th className="px-6 py-4 font-semibold">Student</th>
<th className="px-6 py-4 font-semibold">Plan Tier</th>
<th className="px-6 py-4 font-semibold">Target Exam</th>
<th className="px-6 py-4 font-semibold">Tests Taken</th>
<th className="px-6 py-4 font-semibold">Joined Date</th>
<th className="px-6 py-4 font-semibold text-right"></th>
</tr>
</thead>
<tbody className="divide-y divide-border">
{students.map((s) => (
<tr key={s.id} className="hover:bg-secondary/20 transition-colors">
<td className="px-6 py-4">
<div className="font-bold">{s.name}</div>
<div className="text-muted-foreground text-xs">{s.email}</div>
</td>
<td className="px-6 py-4">
<Badge className={
s.tier === "AI Pro" ? "bg-[#00F0FF]/10 text-[#00F0FF] border-[#00F0FF]/20 font-bold" : "bg-secondary text-foreground border-border"
} variant="outline">
{s.tier}
</Badge>
</td>
<td className="px-6 py-4 font-medium">{s.target}</td>
<td className="px-6 py-4 font-mono">{s.tests}</td>
<td className="px-6 py-4 text-muted-foreground">{s.joined}</td>
<td className="px-6 py-4 text-right">
<button className="p-1.5 hover:text-foreground hover:bg-secondary rounded"><MoreVertical size={16} /></button>
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="p-4 border-t border-border text-sm text-muted-foreground text-center">
Showing top 5 active students out of 12,400 total.
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,9 @@
import { ReactNode } from "react"
export default function CBTLayout({ children }: { children: ReactNode }) {
return (
<div className="min-h-screen bg-background text-foreground flex flex-col selection:bg-primary/20">
{children}
</div>
)
}

View File

@@ -0,0 +1,139 @@
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Clock, Flag, ChevronLeft, ChevronRight, Pause, MoreVertical } from "lucide-react"
import Image from "next/image"
export default function CBTExamPage({ params }: { params: { examId: string } }) {
return (
<>
<header className="border-b border-border bg-background px-6 py-4 flex items-center justify-between sticky top-0 z-10">
<div className="flex items-center gap-4">
<div className="relative h-14 w-56 shrink-0">
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
alt="PragatiVeer"
fill
className="object-contain object-left scale-135 origin-left dark:hidden"
priority
/>
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
alt="PragatiVeer"
fill
className="object-contain object-left scale-135 origin-left hidden dark:block"
priority
/>
</div>
<div className="h-6 w-px bg-border hidden md:block"></div>
<div className="hidden md:block">
<h1 className="font-semibold text-sm">AITS Full Syllabus Test 4</h1>
<p className="text-xs text-muted-foreground font-medium mt-0.5">Physics • Section A</p>
</div>
</div>
<div className="flex items-center gap-3 md:gap-6">
<div className="flex items-center gap-2 bg-secondary/50 px-3 py-1.5 md:px-4 md:py-2 rounded-xl font-mono text-base md:text-lg tracking-wider font-medium text-foreground">
<Clock size={18} className="text-muted-foreground" />
02:45:12
</div>
<Button variant="outline" size="sm" className="gap-2 rounded-xl hidden md:flex">
<Pause size={14} /> Pause
</Button>
<Button size="sm" className="rounded-xl">Submit Exam</Button>
</div>
</header>
<div className="flex flex-1 overflow-hidden relative">
{/* Main Question Area */}
<main className="flex-1 overflow-y-auto p-6 lg:p-12 pb-24 lg:pb-12">
<div className="max-w-3xl mx-auto space-y-8">
<div className="flex items-center justify-between border-b border-border pb-4">
<Badge variant="secondary" className="px-3 py-1 text-sm bg-secondary text-secondary-foreground font-medium rounded-lg">Question 12</Badge>
<div className="flex items-center gap-3">
<span className="text-xs font-semibold uppercase tracking-wider text-muted-foreground bg-secondary/30 px-2 py-1 rounded-md">+4 / -1</span>
<Button variant="ghost" size="icon" className="h-8 w-8 text-muted-foreground hover:text-foreground rounded-lg">
<Flag size={16} />
</Button>
</div>
</div>
<div className="prose prose-neutral dark:prose-invert max-w-none text-lg leading-loose text-foreground">
<p>
A solid cylinder of mass <span className="font-mono text-primary bg-secondary/50 px-1.5 py-0.5 rounded-md text-base">M</span> and radius <span className="font-mono text-primary bg-secondary/50 px-1.5 py-0.5 rounded-md text-base">R</span> is rolling without slipping down an inclined plane of angle <span className="font-mono text-primary bg-secondary/50 px-1.5 py-0.5 rounded-md text-base">θ</span>.
What is the minimum coefficient of static friction <span className="font-mono text-primary bg-secondary/50 px-1.5 py-0.5 rounded-md text-base">μ_s</span> required to prevent slipping?
</p>
</div>
<div className="space-y-3 mt-8">
{['(1/3) tan θ', '(2/3) tan θ', '(1/2) tan θ', 'tan θ'].map((option, idx) => (
<button
key={idx}
className="w-full text-left p-4 rounded-xl border border-border bg-background hover:border-primary/50 hover:bg-secondary/20 transition-all duration-300 flex items-center gap-4 group focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
>
<div className="flex-shrink-0 size-8 rounded-lg border border-border flex items-center justify-center font-medium text-muted-foreground group-hover:border-primary/50 group-hover:text-primary group-hover:bg-primary/5 transition-colors">
{String.fromCharCode(65 + idx)}
</div>
<span className="text-base font-medium">{option}</span>
</button>
))}
</div>
</div>
</main>
{/* Side Panel for Question Grid */}
<aside className="w-80 border-l border-border bg-secondary/10 flex flex-col hidden lg:flex">
<div className="p-5 border-b border-border flex items-center justify-between bg-background">
<h3 className="font-semibold text-sm tracking-tight uppercase text-muted-foreground">Question Palette</h3>
<Button variant="ghost" size="icon" className="h-8 w-8 rounded-lg"><MoreVertical size={16}/></Button>
</div>
<div className="flex-1 overflow-y-auto p-5">
<div className="mb-8 space-y-3 bg-background border border-border p-4 rounded-xl">
<div className="flex items-center justify-between text-xs font-medium text-muted-foreground">
<div className="flex items-center gap-2"><div className="size-3.5 rounded-full bg-primary shadow-sm"></div> Answered <span className="text-foreground ml-1">(11)</span></div>
<div className="flex items-center gap-2"><div className="size-3.5 rounded-full border-2 border-border bg-background"></div> Not Visited <span className="text-foreground ml-1">(28)</span></div>
</div>
<div className="flex items-center justify-between text-xs font-medium text-muted-foreground">
<div className="flex items-center gap-2"><div className="size-3.5 rounded-full bg-destructive shadow-sm"></div> Not Answered <span className="text-foreground ml-1">(4)</span></div>
<div className="flex items-center gap-2"><div className="size-3.5 rounded-full bg-amber-500 shadow-sm"></div> Marked <span className="text-foreground ml-1">(2)</span></div>
</div>
</div>
<div className="space-y-6">
<div>
<h4 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-4 flex items-center gap-2">
<span className="h-px bg-border flex-1"></span> Physics <span className="h-px bg-border flex-1"></span>
</h4>
<div className="grid grid-cols-5 gap-2.5">
{Array.from({length: 20}).map((_, i) => (
<button
key={i}
className={`size-11 rounded-lg flex items-center justify-center text-sm font-medium transition-all duration-200 border focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary
${i === 11 ? 'ring-2 ring-primary ring-offset-2 ring-offset-background border-transparent bg-background shadow-sm' : ''}
${i < 5 ? 'bg-primary border-primary text-primary-foreground shadow-sm' : ''}
${i >= 5 && i < 7 ? 'bg-destructive border-destructive text-destructive-foreground shadow-sm' : ''}
${i === 7 ? 'bg-amber-500 border-amber-500 text-amber-50-foreground shadow-sm' : ''}
${i > 11 ? 'bg-background border-border text-muted-foreground hover:border-primary/50 hover:text-foreground' : ''}
`}
>
{i + 1}
</button>
))}
</div>
</div>
</div>
</div>
<div className="p-5 border-t border-border bg-background grid grid-cols-2 gap-3">
<Button variant="outline" className="rounded-xl w-full gap-1.5 h-12"><ChevronLeft size={16}/> Previous</Button>
<Button className="rounded-xl w-full gap-1.5 h-12 shadow-sm">Save & Next <ChevronRight size={16}/></Button>
</div>
</aside>
{/* Mobile bottom nav */}
<div className="lg:hidden absolute bottom-0 left-0 right-0 p-4 border-t border-border bg-background/95 backdrop-blur-sm grid grid-cols-2 gap-3">
<Button variant="outline" className="rounded-xl w-full gap-1.5 h-12"><ChevronLeft size={16}/> Previous</Button>
<Button className="rounded-xl w-full gap-1.5 h-12 shadow-sm">Save & Next <ChevronRight size={16}/></Button>
</div>
</div>
</>
)
}

48
src/app/contact/page.tsx Normal file
View File

@@ -0,0 +1,48 @@
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import Link from "next/link"
import { ArrowLeft, Mail, MapPin, Phone } from "lucide-react"
export default function ContactPage() {
return (
<div className="min-h-screen bg-background text-foreground flex flex-col">
<header className="border-b border-border bg-background px-6 py-4 flex items-center justify-between sticky top-0 z-10">
<Link href="/" className="text-muted-foreground hover:text-foreground flex items-center gap-2 transition-colors font-medium">
<ArrowLeft size={16} /> Back to Home
</Link>
</header>
<main className="flex-1 flex flex-col items-center justify-center p-8 animate-in fade-in duration-700">
<h1 className="text-5xl font-bold tracking-tighter mb-4 text-center">Contact Us</h1>
<p className="text-lg text-muted-foreground max-w-2xl text-center mb-12">
Have a question or need support? We're here to help you ace your preparation.
</p>
<Card className="w-full max-w-md bg-secondary/10 border-border backdrop-blur-md rounded-3xl">
<CardHeader>
<CardTitle>Send us a message</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-bold">Your Email</label>
<input type="email" placeholder="student@example.com" className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all" />
</div>
<div className="space-y-2">
<label className="text-sm font-bold">Message</label>
<textarea rows={4} placeholder="How can we help?" className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"></textarea>
</div>
<Button className="w-full rounded-xl h-12 font-bold text-base">Send Message</Button>
<div className="pt-6 border-t border-border mt-6 space-y-3">
<div className="flex items-center gap-3 text-sm text-muted-foreground font-medium">
<Mail size={16} className="text-primary" /> support@pragativeer.com
</div>
<div className="flex items-center gap-3 text-sm text-muted-foreground font-medium">
<MapPin size={16} className="text-primary" /> Tech Hub, Bengaluru, India
</div>
</div>
</CardContent>
</Card>
</main>
</div>
)
}

View File

@@ -0,0 +1,63 @@
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
import { LineChart, Activity, BrainCircuit } from "lucide-react"
export default function AnalyticsPage() {
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-6xl mx-auto">
<div>
<h1 className="text-3xl font-bold tracking-tight">Performance Analytics</h1>
<p className="text-muted-foreground mt-1 font-medium">Deep AI-driven insights into your study patterns and test trajectories.</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<Card className="col-span-1 lg:col-span-2 border-border shadow-sm bg-background">
<CardHeader>
<CardTitle className="flex items-center gap-2"><LineChart className="text-[#00F0FF]" size={20} /> Projected Score Trajectory</CardTitle>
<CardDescription>Your mock scores over the last 6 months projected towards the final exam.</CardDescription>
</CardHeader>
<CardContent className="h-64 flex items-center justify-center border-t border-border mt-4">
{/* Placeholder for an actual chart library like Recharts */}
<div className="text-center text-muted-foreground">
<Activity size={48} className="mx-auto mb-4 opacity-20" />
<p className="font-medium">Data gathering in progress...</p>
<p className="text-sm mt-1">Complete 2 more CBTs to unlock predictive graphing.</p>
</div>
</CardContent>
</Card>
<div className="space-y-6">
<Card className="border-[#00F0FF]/30 bg-[#00F0FF]/5">
<CardHeader className="pb-2">
<CardTitle className="text-lg flex items-center gap-2"><BrainCircuit size={18} className="text-[#00F0FF]"/> AI Diagnosis</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm text-foreground/80 leading-relaxed font-medium">
Our models detect a consistent <strong>14% accuracy drop</strong> in physics questions involving Calculus. We are adjusting your upcoming DPPs to focus heavily on integration applications in kinematics.
</p>
</CardContent>
</Card>
<Card className="border-border shadow-sm">
<CardHeader className="pb-2">
<CardTitle className="text-lg">Subject Mastery</CardTitle>
</CardHeader>
<CardContent className="space-y-4 pt-2">
<div>
<div className="flex justify-between text-sm mb-1 font-medium"><span>Biology</span> <span className="text-emerald-500">89%</span></div>
<div className="h-2 w-full bg-secondary rounded-full overflow-hidden"><div className="h-full bg-emerald-500 w-[89%]"></div></div>
</div>
<div>
<div className="flex justify-between text-sm mb-1 font-medium"><span>Chemistry</span> <span className="text-amber-500">68%</span></div>
<div className="h-2 w-full bg-secondary rounded-full overflow-hidden"><div className="h-full bg-amber-500 w-[68%]"></div></div>
</div>
<div>
<div className="flex justify-between text-sm mb-1 font-medium"><span>Physics</span> <span className="text-destructive">42%</span></div>
<div className="h-2 w-full bg-secondary rounded-full overflow-hidden"><div className="h-full bg-destructive w-[42%]"></div></div>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,84 @@
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Activity, Clock, PlayCircle, Search } from "lucide-react"
export default function CBTPage() {
const upcomingExams = [
{ title: "AITS Full Syllabus Test 4", date: "Tomorrow, 10:00 AM", duration: "180 Min", marks: 720 },
{ title: "Part Test 3: Mechanics", date: "Oct 24, 2026", duration: "180 Min", marks: 720 },
{ title: "Weekly Revision Test", date: "Oct 28, 2026", duration: "90 Min", marks: 360 },
]
const pastExams = [
{ title: "AITS Full Syllabus Test 3", date: "Oct 15, 2026", score: 645, total: 720, percentile: "99.4" },
{ title: "Part Test 2: Electromagnetism", date: "Oct 08, 2026", score: 680, total: 720, percentile: "99.8" },
]
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-6xl mx-auto">
<div className="flex justify-between items-end">
<div>
<h1 className="text-3xl font-bold tracking-tight">Computer Based Tests (CBT)</h1>
<p className="text-muted-foreground mt-1 font-medium">Real exam environment simulations to conquer NEET/JEE.</p>
</div>
<div className="relative w-64">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" size={16} />
<input type="text" placeholder="Search exams..." className="w-full pl-10 pr-4 py-2 bg-background border border-border rounded-xl text-sm focus:ring-2 focus:ring-[#00F0FF] outline-none" />
</div>
</div>
<div className="space-y-6">
<h2 className="text-xl font-bold border-b border-border pb-2 flex items-center gap-2">
<Clock size={20} className="text-[#00F0FF]" /> Upcoming & Active Exams
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{upcomingExams.map((exam, i) => (
<Card key={i} className="hover:border-[#00F0FF]/50 hover:shadow-[0_0_15px_-5px_#00F0FF] transition-all group">
<CardContent className="p-6">
<Badge variant="outline" className="mb-4 bg-[#00F0FF]/10 text-[#00F0FF] border-[#00F0FF]/20">Mock Test</Badge>
<h3 className="font-bold text-lg leading-tight mb-2 group-hover:text-[#00F0FF] transition-colors">{exam.title}</h3>
<div className="text-sm text-muted-foreground space-y-1 mb-6">
<div className="font-medium text-foreground">{exam.date}</div>
<div>{exam.duration} • {exam.marks} Marks</div>
</div>
<Button className="w-full gap-2 rounded-xl bg-secondary text-foreground hover:bg-[#00F0FF] hover:text-background transition-colors font-bold">
<PlayCircle size={16} /> Start Exam
</Button>
</CardContent>
</Card>
))}
</div>
</div>
<div className="space-y-6 pt-8">
<h2 className="text-xl font-bold border-b border-border pb-2 flex items-center gap-2">
<Activity size={20} className="text-muted-foreground" /> Past Attempts
</h2>
<div className="space-y-4">
{pastExams.map((exam, i) => (
<Card key={i} className="bg-secondary/20">
<CardContent className="p-4 flex items-center justify-between">
<div>
<h3 className="font-bold">{exam.title}</h3>
<p className="text-sm text-muted-foreground font-medium">{exam.date}</p>
</div>
<div className="flex items-center gap-8">
<div className="text-right">
<div className="text-sm text-muted-foreground font-bold uppercase tracking-wider">Score</div>
<div className="font-bold text-lg"><span className="text-foreground">{exam.score}</span><span className="text-muted-foreground">/{exam.total}</span></div>
</div>
<div className="text-right">
<div className="text-sm text-muted-foreground font-bold uppercase tracking-wider">Percentile</div>
<div className="font-bold text-lg text-[#00F0FF]">{exam.percentile}</div>
</div>
<Button variant="outline" className="rounded-xl border-border hover:bg-secondary">Review Analysis</Button>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,56 @@
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { BrainCircuit, Play, CheckCircle2, ChevronRight } from "lucide-react"
export default function DPPPage() {
const dpps = [
{ title: "Rotational Dynamics: Top Overturning", subject: "Physics", count: 15, status: "Pending", priority: "High" },
{ title: "Chemical Kinetics: First Order Reactions", subject: "Chemistry", count: 20, status: "Pending", priority: "Medium" },
{ title: "Genetics: Mendelian Inheritance", subject: "Biology", count: 25, status: "Completed", score: "23/25" },
{ title: "Calculus: Definite Integration", subject: "Mathematics", count: 15, status: "Completed", score: "14/15" },
]
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-5xl mx-auto">
<div className="flex justify-between items-center p-8 bg-gradient-to-r from-secondary/50 to-background border border-border rounded-2xl shadow-sm">
<div>
<h1 className="text-3xl font-bold tracking-tight mb-2">Daily Practice Problems (DPP)</h1>
<p className="text-muted-foreground font-medium max-w-xl">
Hyper-personalized problem sets generated daily by our AI Evaluator to target your specific weak areas based on past exam performance.
</p>
</div>
<Button size="lg" className="h-14 px-8 rounded-xl bg-[#00F0FF] text-background hover:bg-[#00F0FF]/90 font-bold shadow-[0_0_20px_-5px_#00F0FF]">
<BrainCircuit className="mr-2" /> Generate Custom DPP
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{dpps.map((dpp, i) => (
<Card key={i} className={`group cursor-pointer transition-all hover:shadow-md ${dpp.status === 'Completed' ? 'opacity-70 hover:opacity-100 bg-secondary/10' : 'hover:border-[#00F0FF]/50 bg-background'}`}>
<CardContent className="p-6 flex items-center justify-between">
<div className="flex gap-4">
<div className={`mt-1 flex-shrink-0 ${dpp.status === 'Completed' ? 'text-green-500' : 'text-foreground'}`}>
{dpp.status === 'Completed' ? <CheckCircle2 size={24} /> : <div className="size-6 rounded-full border-2 border-muted-foreground group-hover:border-[#00F0FF] transition-colors flex items-center justify-center"></div>}
</div>
<div>
<div className="text-xs font-bold uppercase tracking-wider text-[#00F0FF] mb-1">{dpp.subject}</div>
<h3 className="font-bold text-lg leading-tight group-hover:text-[#00F0FF] transition-colors">{dpp.title}</h3>
<div className="text-sm text-muted-foreground mt-2 font-medium">
{dpp.count} Questions • {dpp.status === 'Completed' ? `Score: ${dpp.score}` : `${dpp.priority} Priority`}
</div>
</div>
</div>
<div className="text-muted-foreground group-hover:text-foreground transition-colors pl-4">
{dpp.status === 'Completed' ? (
<Button variant="ghost" size="sm" className="font-bold">Review</Button>
) : (
<Button variant="secondary" size="icon" className="rounded-full group-hover:bg-[#00F0FF] group-hover:text-background transition-colors"><Play size={16} className="ml-1" /></Button>
)}
</div>
</CardContent>
</Card>
))}
</div>
</div>
)
}

View File

@@ -0,0 +1,123 @@
"use client"
import { ReactNode, useState, useEffect, useRef } from "react"
import { BookOpen, LayoutDashboard, Settings, FileText, Activity, LineChart, Trophy, LogOut, User, ChevronUp } from "lucide-react"
import Link from "next/link"
import Image from "next/image"
import { usePathname } from "next/navigation"
export default function DashboardLayout({ children }: { children: ReactNode }) {
const pathname = usePathname()
const [dropdownOpen, setDropdownOpen] = useState(false)
const dropdownRef = useRef<HTMLDivElement>(null)
// Close dropdown when clicking outside
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setDropdownOpen(false)
}
}
document.addEventListener("mousedown", handleClickOutside)
return () => document.removeEventListener("mousedown", handleClickOutside)
}, [])
return (
<div className="flex h-screen bg-background overflow-hidden text-foreground selection:bg-primary/20">
{/* Sidebar */}
<aside className="w-64 border-r border-border bg-background flex flex-col hidden md:flex">
<div className="p-6">
<Link href="/dashboard" className="block relative h-16 w-full hover:opacity-90 transition-opacity">
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
alt="PragatiVeer"
fill
className="object-contain object-left scale-135 origin-left dark:hidden"
priority
/>
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
alt="PragatiVeer"
fill
className="object-contain object-left scale-135 origin-left hidden dark:block"
priority
/>
</Link>
</div>
<nav className="flex-1 px-4 space-y-1.5 mt-4 overflow-y-auto">
<NavItem href="/dashboard" icon={<LayoutDashboard size={18} />} label="Overview" active={pathname === "/dashboard"} />
<NavItem href="/dashboard/cbt" icon={<Activity size={18} />} label="Exams (CBT)" active={pathname.startsWith("/dashboard/cbt")} />
<NavItem href="/dashboard/dpp" icon={<FileText size={18} />} label="Daily Practice" active={pathname.startsWith("/dashboard/dpp")} />
<NavItem href="/dashboard/materials" icon={<BookOpen size={18} />} label="Study Materials" active={pathname.startsWith("/dashboard/materials")} />
<div className="pt-4 pb-2">
<p className="px-3 text-xs font-bold uppercase tracking-widest text-muted-foreground">AI Intelligence</p>
</div>
<NavItem href="/dashboard/analytics" icon={<LineChart size={18} />} label="Performance Analytics" active={pathname.startsWith("/dashboard/analytics")} />
<NavItem href="/dashboard/rank-predictor" icon={<Trophy size={18} />} label="Rank Predictor" active={pathname.startsWith("/dashboard/rank-predictor")} />
</nav>
<div className="p-4 border-t border-border space-y-2">
<NavItem href="/dashboard/settings" icon={<Settings size={18} />} label="Settings" active={pathname.startsWith("/dashboard/settings")} />
{/* Functional User Dropdown */}
<div className="relative mt-2" ref={dropdownRef}>
{dropdownOpen && (
<div className="absolute bottom-full left-0 w-full mb-2 bg-background border border-border rounded-xl shadow-lg shadow-black/10 overflow-hidden animate-in fade-in slide-in-from-bottom-2 duration-200 z-50">
<div className="px-4 py-3 border-b border-border">
<p className="text-sm font-bold text-foreground">Demo Student</p>
<p className="text-xs text-muted-foreground truncate">demo@pragativeer.com</p>
</div>
<div className="p-1">
<Link href="/dashboard/settings" className="flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-secondary rounded-lg transition-colors">
<User size={16} /> Edit Profile
</Link>
<Link href="/" className="flex items-center gap-2 px-3 py-2 text-sm text-red-500 hover:bg-red-500/10 rounded-lg transition-colors font-medium mt-1">
<LogOut size={16} /> Log out
</Link>
</div>
</div>
)}
<button
onClick={() => setDropdownOpen(!dropdownOpen)}
className="w-full flex items-center justify-between p-2 rounded-xl hover:bg-secondary/50 transition-colors border border-transparent hover:border-border"
>
<div className="flex items-center gap-3">
<div className="h-8 w-8 rounded-full bg-[#00F0FF]/20 text-[#00F0FF] flex items-center justify-center font-bold text-sm shadow-[0_0_10px_-2px_#00F0FF]">
DS
</div>
<div className="text-left">
<p className="text-sm font-bold leading-none">Demo Student</p>
<p className="text-xs text-[#00F0FF] font-medium mt-1">AI Pro Plan</p>
</div>
</div>
<ChevronUp size={16} className={`text-muted-foreground transition-transform ${dropdownOpen ? "rotate-180" : ""}`} />
</button>
</div>
</div>
</aside>
{/* Main Content */}
<main className="flex-1 overflow-y-auto">
{children}
</main>
</div>
)
}
function NavItem({ href, icon, label, active }: { href: string, icon: React.ReactNode, label: string, active?: boolean }) {
return (
<Link
href={href}
className={`flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-300 ${
active
? "bg-secondary text-foreground font-medium border border-border"
: "text-muted-foreground hover:bg-secondary/50 hover:text-foreground border border-transparent"
}`}
>
{icon}
<span className="text-sm">{label}</span>
</Link>
)
}

View File

@@ -0,0 +1,69 @@
import { Card, CardContent } from "@/components/ui/card"
import { Folder, FileText, Download, PlaySquare } from "lucide-react"
export default function MaterialsPage() {
const folders = [
{ name: "Physics Formula Sheets", items: 12, color: "text-blue-500" },
{ name: "Organic Chem Mind Maps", items: 8, color: "text-emerald-500" },
{ name: "Biology NCERT Highlights", items: 22, color: "text-rose-500" },
{ name: "Past Year Papers (2015-2025)", items: 10, color: "text-amber-500" },
]
const recentFiles = [
{ name: "Kinematics 1D & 2D Rapid Revision.pdf", type: "PDF", size: "2.4 MB" },
{ name: "S-Block Elements Trick Video.mp4", type: "Video", size: "45 MB" },
{ name: "Human Reproduction Master Notes.pdf", type: "PDF", size: "8.1 MB" },
]
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-6xl mx-auto">
<div>
<h1 className="text-3xl font-bold tracking-tight">Study Materials</h1>
<p className="text-muted-foreground mt-1 font-medium">High-yield notes, mind maps, and video lectures.</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{folders.map((folder, i) => (
<Card key={i} className="hover:bg-secondary/50 cursor-pointer transition-colors border-border shadow-none">
<CardContent className="p-6">
<Folder size={40} className={`${folder.color} mb-4`} />
<h3 className="font-bold">{folder.name}</h3>
<p className="text-sm text-muted-foreground mt-1 font-medium">{folder.items} Files</p>
</CardContent>
</Card>
))}
</div>
<div className="pt-6">
<h2 className="text-xl font-bold border-b border-border pb-2 mb-4">Recently Accessed</h2>
<div className="bg-secondary/10 border border-border rounded-xl overflow-hidden">
<table className="w-full text-left text-sm">
<thead className="bg-secondary/30 text-muted-foreground border-b border-border">
<tr>
<th className="px-6 py-4 font-semibold">File Name</th>
<th className="px-6 py-4 font-semibold">Type</th>
<th className="px-6 py-4 font-semibold">Size</th>
<th className="px-6 py-4 font-semibold text-right">Download</th>
</tr>
</thead>
<tbody className="divide-y divide-border">
{recentFiles.map((file, i) => (
<tr key={i} className="hover:bg-secondary/20 transition-colors cursor-pointer group">
<td className="px-6 py-4 font-medium flex items-center gap-3">
{file.type === 'PDF' ? <FileText size={18} className="text-red-400" /> : <PlaySquare size={18} className="text-blue-400" />}
{file.name}
</td>
<td className="px-6 py-4 text-muted-foreground">{file.type}</td>
<td className="px-6 py-4 text-muted-foreground">{file.size}</td>
<td className="px-6 py-4 text-right">
<button className="p-2 hover:text-[#00F0FF] hover:bg-secondary rounded-lg transition-colors inline-block"><Download size={18} /></button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
)
}

149
src/app/dashboard/page.tsx Normal file
View File

@@ -0,0 +1,149 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Activity, BrainCircuit, ArrowRight, Clock } from "lucide-react"
export default function DashboardPage() {
return (
<div className="p-8 max-w-6xl mx-auto space-y-10 animate-in fade-in duration-500 slide-in-from-bottom-4">
<header className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight">Welcome back, Student</h1>
<p className="text-muted-foreground mt-1 font-medium">Here is your daily AI-curated study plan.</p>
</div>
<Button size="lg" className="gap-2 shadow-sm">
<BrainCircuit size={18} />
Generate AI Plan
</Button>
</header>
{/* AI Predicted Weak Areas */}
<section>
<div className="flex items-center justify-between mb-5">
<h2 className="text-xl font-semibold tracking-tight">AI Focus Areas</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Card className="border-t-4 border-t-destructive">
<CardHeader className="pb-2">
<CardTitle className="text-lg">Rotational Motion</CardTitle>
<CardDescription>Physics</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center justify-between text-sm">
<span className="text-muted-foreground">Mastery</span>
<span className="font-medium text-destructive">42%</span>
</div>
<div className="w-full bg-secondary rounded-full h-1.5 mt-2 overflow-hidden">
<div className="bg-destructive h-1.5 rounded-full w-[42%]"></div>
</div>
</CardContent>
</Card>
<Card className="border-t-4 border-t-amber-500">
<CardHeader className="pb-2">
<CardTitle className="text-lg">Chemical Kinetics</CardTitle>
<CardDescription>Chemistry</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center justify-between text-sm">
<span className="text-muted-foreground">Mastery</span>
<span className="font-medium text-amber-500">68%</span>
</div>
<div className="w-full bg-secondary rounded-full h-1.5 mt-2 overflow-hidden">
<div className="bg-amber-500 h-1.5 rounded-full w-[68%]"></div>
</div>
</CardContent>
</Card>
<Card className="border-t-4 border-t-emerald-500">
<CardHeader className="pb-2">
<CardTitle className="text-lg">Genetics</CardTitle>
<CardDescription>Biology</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center justify-between text-sm">
<span className="text-muted-foreground">Mastery</span>
<span className="font-medium text-emerald-500">89%</span>
</div>
<div className="w-full bg-secondary rounded-full h-1.5 mt-2 overflow-hidden">
<div className="bg-emerald-500 h-1.5 rounded-full w-[89%]"></div>
</div>
</CardContent>
</Card>
</div>
</section>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Dynamic DPP Modules */}
<section>
<div className="flex items-center justify-between mb-5">
<h2 className="text-xl font-semibold tracking-tight">Today's DPPs</h2>
<Button variant="ghost" size="sm" className="text-muted-foreground font-medium">View All</Button>
</div>
<div className="space-y-4">
<Card className="hover:border-primary/30 hover:shadow-md cursor-pointer transition-all duration-300 group">
<CardContent className="p-5 flex items-center justify-between">
<div className="flex gap-4 items-center">
<div className="p-3 bg-secondary rounded-xl text-foreground">
<BrainCircuit size={20} />
</div>
<div>
<h3 className="font-medium text-base group-hover:text-primary transition-colors">Physics: Rotational Dynamics</h3>
<p className="text-sm text-muted-foreground mt-0.5">20 Questions • High Priority</p>
</div>
</div>
<Button variant="outline" size="sm" className="gap-2 rounded-xl group-hover:bg-primary group-hover:text-primary-foreground group-hover:border-primary transition-all">
Start <ArrowRight size={14} />
</Button>
</CardContent>
</Card>
<Card className="hover:border-primary/30 hover:shadow-md cursor-pointer transition-all duration-300 group">
<CardContent className="p-5 flex items-center justify-between">
<div className="flex gap-4 items-center">
<div className="p-3 bg-secondary rounded-xl text-foreground">
<Activity size={20} />
</div>
<div>
<h3 className="font-medium text-base group-hover:text-primary transition-colors">Biology: Human Physiology</h3>
<p className="text-sm text-muted-foreground mt-0.5">30 Questions • Revision</p>
</div>
</div>
<Button variant="outline" size="sm" className="gap-2 rounded-xl group-hover:bg-primary group-hover:text-primary-foreground group-hover:border-primary transition-all">
Start <ArrowRight size={14} />
</Button>
</CardContent>
</Card>
</div>
</section>
{/* Upcoming CBTs */}
<section>
<div className="flex items-center justify-between mb-5">
<h2 className="text-xl font-semibold tracking-tight">Upcoming CBTs</h2>
</div>
<Card className="overflow-hidden">
<div className="p-6 border-b border-border flex items-center justify-between bg-background">
<div>
<div className="flex items-center gap-3 mb-2">
<Badge variant="outline" className="border-primary/20 bg-primary/5 text-primary">Mock Test</Badge>
<span className="text-xs text-muted-foreground font-semibold uppercase tracking-wider">Tomorrow, 10:00 AM</span>
</div>
<h3 className="font-semibold text-lg tracking-tight">AITS Full Syllabus Test 4</h3>
<p className="text-sm text-muted-foreground flex items-center gap-1.5 mt-1.5">
<Clock size={14} /> 180 Minutes • 720 Marks
</p>
</div>
<Button variant="secondary" className="rounded-xl font-medium">Remind Me</Button>
</div>
<div className="p-5 bg-secondary/50 flex items-center justify-between transition-colors hover:bg-secondary/70">
<div>
<h3 className="font-medium text-sm text-foreground">Part Test 3: Mechanics</h3>
<p className="text-xs text-muted-foreground mt-0.5 font-medium">Oct 24, 2026</p>
</div>
<Button variant="ghost" size="sm" className="h-8 text-xs font-medium">Details</Button>
</div>
</Card>
</section>
</div>
</div>
)
}

View File

@@ -0,0 +1,50 @@
import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Trophy, TrendingUp, AlertTriangle } from "lucide-react"
export default function RankPredictorPage() {
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-4xl mx-auto">
<div className="text-center max-w-2xl mx-auto mb-10">
<div className="inline-flex items-center justify-center p-4 bg-[#00F0FF]/10 rounded-full mb-6">
<Trophy size={40} className="text-[#00F0FF]" />
</div>
<h1 className="text-4xl font-bold tracking-tight mb-4">Rank Predictor AI</h1>
<p className="text-muted-foreground text-lg font-medium">
Our proprietary neural network analyzes your CBT scores against 100,000+ past successful candidates to predict your All India Rank.
</p>
</div>
<Card className="border-border shadow-lg bg-background overflow-hidden relative">
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-[#00F0FF] to-blue-600"></div>
<CardContent className="p-10 text-center">
<div className="text-sm font-bold uppercase tracking-widest text-muted-foreground mb-4">Estimated NEET (UG) AIR</div>
<div className="text-7xl font-black tracking-tighter bg-clip-text text-transparent bg-gradient-to-br from-foreground to-muted-foreground mb-8">
~14,500
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-left">
<div className="p-4 bg-secondary/30 rounded-xl border border-border flex items-start gap-3">
<TrendingUp className="text-emerald-500 mt-0.5" size={20} />
<div>
<div className="font-bold">On the Right Track</div>
<div className="text-sm text-muted-foreground mt-1">Your biology and chemistry scores are securing a top 20k finish.</div>
</div>
</div>
<div className="p-4 bg-secondary/30 rounded-xl border border-border flex items-start gap-3">
<AlertTriangle className="text-amber-500 mt-0.5" size={20} />
<div>
<div className="font-bold">Physics Bottleneck</div>
<div className="text-sm text-muted-foreground mt-1">Pushing Physics beyond 120 marks will breach the top 5k rank.</div>
</div>
</div>
</div>
<Button size="lg" className="mt-8 bg-foreground text-background hover:bg-foreground/90 font-bold rounded-xl px-8">
Recalculate with Latest Mock
</Button>
</CardContent>
</Card>
</div>
)
}

View File

@@ -0,0 +1,68 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
export default function SettingsPage() {
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-4xl mx-auto">
<div>
<h1 className="text-3xl font-bold tracking-tight">Account Settings</h1>
<p className="text-muted-foreground mt-1 font-medium">Manage your personal details and platform preferences.</p>
</div>
<div className="space-y-6">
<Card className="border-border bg-background shadow-sm">
<CardHeader>
<CardTitle>Profile Details</CardTitle>
<CardDescription>Update your personal information.</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<label className="text-sm font-bold">First Name</label>
<input type="text" defaultValue="Demo" className="w-full bg-secondary/50 border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#00F0FF]" />
</div>
<div className="space-y-2">
<label className="text-sm font-bold">Last Name</label>
<input type="text" defaultValue="Student" className="w-full bg-secondary/50 border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#00F0FF]" />
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-bold">Email Address</label>
<input type="email" defaultValue="demo@pragativeer.com" disabled className="w-full bg-secondary border border-border rounded-lg px-4 py-2 text-sm text-muted-foreground cursor-not-allowed" />
</div>
<Button className="bg-foreground text-background hover:bg-foreground/90 font-bold mt-2">Save Changes</Button>
</CardContent>
</Card>
<Card className="border-border bg-background shadow-sm">
<CardHeader>
<CardTitle>Academic Preferences</CardTitle>
<CardDescription>Tailor the AI to your specific exam targets.</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="space-y-3">
<label className="text-sm font-bold">Target Examination</label>
<div className="flex gap-4">
<label className="flex items-center gap-2 cursor-pointer p-4 border border-[#00F0FF] bg-[#00F0FF]/5 rounded-xl flex-1">
<input type="radio" name="target" defaultChecked className="accent-[#00F0FF] w-4 h-4" />
<span className="font-bold">NEET (UG)</span>
</label>
<label className="flex items-center gap-2 cursor-pointer p-4 border border-border bg-secondary/20 hover:bg-secondary/50 rounded-xl flex-1 transition-colors">
<input type="radio" name="target" className="accent-[#00F0FF] w-4 h-4" />
<span className="font-bold">JEE Main & Adv</span>
</label>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-bold">Target Year</label>
<select className="w-full bg-secondary/50 border border-border rounded-lg px-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-[#00F0FF] appearance-none font-medium">
<option>2026</option>
<option>2027</option>
</select>
</div>
</CardContent>
</Card>
</div>
</div>
)
}

View File

@@ -0,0 +1,9 @@
import { ReactNode } from "react"
export default function DPplayout({ children }: { children: ReactNode }) {
return (
<div className="min-h-screen bg-background text-foreground selection:bg-primary/20">
{children}
</div>
)
}

View File

@@ -0,0 +1,133 @@
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { ArrowLeft, Sparkles, Send, CheckCircle2, MessageSquare, ThumbsUp, ThumbsDown } from "lucide-react"
import Link from "next/link"
import Image from "next/image"
export default function DPplayoutPage({ params }: { params: { dppId: string } }) {
return (
<div className="max-w-5xl mx-auto h-screen flex flex-col">
<header className="h-16 border-b border-border bg-background flex items-center justify-between px-6 sticky top-0 z-10">
<div className="flex items-center gap-4">
<Link href="/dashboard" className="text-muted-foreground hover:text-foreground transition-colors p-2 hover:bg-secondary rounded-lg shrink-0">
<ArrowLeft size={20} />
</Link>
<div className="flex items-center gap-3">
<div className="relative h-14 w-56 hidden md:block shrink-0">
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
alt="PragatiVeer"
fill
className="object-contain object-left scale-135 origin-left dark:hidden"
/>
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
alt="PragatiVeer"
fill
className="object-contain object-left scale-135 origin-left hidden dark:block"
/>
</div>
<div className="h-5 w-px bg-border hidden md:block"></div>
<Badge variant="outline" className="border-primary/20 text-primary bg-primary/5 uppercase tracking-widest text-[10px]">AI Review</Badge>
<h1 className="font-semibold text-sm tracking-tight">Rotational Dynamics DPP #4</h1>
</div>
</div>
<div className="flex items-center gap-3">
<span className="text-sm font-medium text-muted-foreground bg-secondary px-3 py-1.5 rounded-lg">Score: <span className="text-emerald-500 font-bold ml-1">14/20</span></span>
</div>
</header>
<main className="flex-1 overflow-y-auto p-6 md:p-10 space-y-10">
<div className="bg-secondary/20 border border-border rounded-3xl p-6 md:p-10 shadow-sm">
<div className="flex items-center justify-between mb-6">
<h2 className="text-lg font-semibold flex items-center gap-2">
<CheckCircle2 size={20} className="text-emerald-500" />
Question 3
</h2>
<Badge variant="outline" className="bg-background text-muted-foreground border-border">Medium Difficulty</Badge>
</div>
<div className="prose prose-neutral dark:prose-invert max-w-none text-lg leading-relaxed mb-8">
<p>
Two identical solid spheres roll down two different inclined planes of the same height but different angles of inclination.
Which sphere reaches the bottom with greater speed?
</p>
</div>
<div className="p-5 rounded-2xl border border-emerald-500/30 bg-emerald-500/5 flex items-center gap-4">
<div className="size-8 rounded-full bg-emerald-500 text-primary-foreground flex items-center justify-center font-bold text-sm shadow-sm">C</div>
<span className="font-medium text-foreground">They reach with the same speed.</span>
<span className="ml-auto text-xs font-bold text-emerald-600 dark:text-emerald-400 uppercase tracking-wider bg-emerald-500/10 px-3 py-1 rounded-full">Your Answer</span>
</div>
</div>
{/* AI Solution Breakdown */}
<div className="space-y-8 bg-background p-6 md:p-10 rounded-3xl border border-border shadow-sm">
<div className="flex items-center gap-3 border-b border-border pb-6">
<div className="p-2.5 bg-primary text-primary-foreground rounded-xl shadow-sm">
<Sparkles size={20} />
</div>
<h3 className="font-semibold text-xl tracking-tight">AI Step-by-Step Solution</h3>
</div>
<div className="ml-5 pl-8 border-l-2 border-border/50 space-y-10 py-4">
<div className="relative">
<div className="absolute -left-[41px] top-1 size-5 rounded-full bg-background border-4 border-primary ring-4 ring-background"></div>
<h4 className="font-semibold text-base mb-2 text-foreground">Step 1: Energy Conservation</h4>
<p className="text-muted-foreground text-base leading-relaxed">
By the law of conservation of mechanical energy, the potential energy at the top is converted into translational and rotational kinetic energy at the bottom.
</p>
<div className="mt-4 p-5 rounded-2xl bg-secondary/50 font-mono text-sm overflow-x-auto text-foreground border border-border/50">
mgh = ½mv² + ½Iω²
</div>
</div>
<div className="relative">
<div className="absolute -left-[41px] top-1 size-5 rounded-full bg-background border-4 border-muted ring-4 ring-background"></div>
<h4 className="font-semibold text-base mb-2 text-foreground">Step 2: Moment of Inertia</h4>
<p className="text-muted-foreground text-base leading-relaxed">
For a solid sphere, the moment of inertia <span className="font-mono bg-secondary px-1.5 py-0.5 rounded-md text-foreground">I = ⅖mr²</span>. Substitute this and <span className="font-mono bg-secondary px-1.5 py-0.5 rounded-md text-foreground">ω = v/r</span> into the energy equation.
</p>
<div className="mt-4 p-5 rounded-2xl bg-secondary/50 font-mono text-sm overflow-x-auto text-foreground border border-border/50 leading-loose">
mgh = ½mv² + ½(⅖mr²)(v²/r²) <br/>
mgh = ½mv² + ⅕mv² <br/>
gh = 7/10 v²
</div>
</div>
<div className="relative">
<div className="absolute -left-[41px] top-1 size-5 rounded-full bg-background border-4 border-muted ring-4 ring-background"></div>
<h4 className="font-semibold text-base mb-2 text-foreground">Step 3: Final Velocity</h4>
<p className="text-muted-foreground text-base leading-relaxed">
Solving for <span className="font-mono bg-secondary px-1.5 py-0.5 rounded-md text-foreground">v</span>, we get:
</p>
<div className="mt-4 p-5 rounded-2xl bg-secondary/50 font-mono text-sm overflow-x-auto text-foreground border border-border/50">
v = √(10gh/7)
</div>
<p className="text-muted-foreground text-base leading-relaxed mt-5 bg-secondary/20 p-4 rounded-xl border-l-2 border-primary">
The final speed depends only on height <span className="font-mono bg-secondary px-1.5 py-0.5 rounded-md text-foreground">h</span> and acceleration due to gravity <span className="font-mono bg-secondary px-1.5 py-0.5 rounded-md text-foreground">g</span>. It is independent of the angle of inclination. Therefore, both spheres reach the bottom with the same speed.
</p>
</div>
</div>
<div className="ml-12 pt-4 flex items-center gap-3">
<Button variant="outline" size="sm" className="rounded-xl text-muted-foreground hover:text-foreground"><ThumbsUp size={14} className="mr-2"/> Helpful</Button>
<Button variant="outline" size="sm" className="rounded-xl text-muted-foreground hover:text-foreground"><ThumbsDown size={14} className="mr-2"/> Not Helpful</Button>
</div>
</div>
</main>
<div className="p-6 border-t border-border bg-background/80 backdrop-blur-md">
<div className="max-w-3xl mx-auto relative group">
<input
type="text"
placeholder="Ask AI a follow-up question about this solution..."
className="w-full bg-secondary/50 border border-border rounded-2xl pl-6 pr-16 py-4 text-base focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all group-hover:border-primary/30"
/>
<Button size="icon" className="absolute right-2 top-2 rounded-xl h-11 w-11 shadow-sm transition-transform active:scale-95">
<Send size={18} />
</Button>
</div>
</div>
</div>
)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -1,26 +1,113 @@
@import "tailwindcss"; @import "tailwindcss";
@theme {
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--radius-xl: 0.75rem;
--radius-2xl: 1rem;
}
:root { :root {
--background: #ffffff; --background: #ffffff;
--foreground: #171717; --foreground: #171717;
} --border: #e5e5e5;
--input: #e5e5e5;
--ring: #171717;
@theme inline { --primary: #171717;
--color-background: var(--background); --primary-foreground: #fafafa;
--color-foreground: var(--foreground); --secondary: #f5f5f5;
--font-sans: var(--font-geist-sans); --secondary-foreground: #171717;
--font-mono: var(--font-geist-mono); --accent: #f5f5f5;
--accent-foreground: #171717;
--muted: #f5f5f5;
--muted-foreground: #737373;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { :root {
--background: #0a0a0a; --background: #0a0a0a;
--foreground: #ededed; --foreground: #ededed;
--border: #1f1f1f;
--input: #1f1f1f;
--ring: #D1FF4D;
--primary: #D1FF4D;
--primary-foreground: #0a0a0a;
--secondary: #171717;
--secondary-foreground: #ededed;
--accent: #00F0FF;
--accent-foreground: #0a0a0a;
--muted: #171717;
--muted-foreground: #a3a3a3;
} }
} }
body { body {
background: var(--background); background: var(--background);
color: var(--foreground); color: var(--foreground);
font-family: Arial, Helvetica, sans-serif; font-family: var(--font-sans), Arial, Helvetica, sans-serif;
@apply antialiased selection:bg-primary/20;
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
.bg-grid {
background-size: 40px 40px;
background-image: linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
}
.animate-gradient {
background-size: 200% auto;
animation: gradient-shift 4s linear infinite;
}
.animate-marquee {
animation: marquee 30s linear infinite;
}
.animate-shine {
animation: shine 3s infinite linear;
}
}
@keyframes gradient-shift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
@keyframes marquee {
0% { transform: translateX(0%); }
100% { transform: translateX(-50%); }
}
@keyframes shine {
0% { transform: translateX(-100%) skewX(-15deg); }
30% { transform: translateX(200%) skewX(-15deg); }
100% { transform: translateX(200%) skewX(-15deg); }
} }

1
src/app/icon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -13,8 +13,9 @@ const geistMono = Geist_Mono({
}); });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Create Next App", title: "PragatiVeer - AI Powered NEET/JEE Preparation",
description: "Generated by create next app", description: "Experience the most accurate Computer-Based Test simulator combined with adaptive Daily Practice Problems generated specifically for your weak areas in real-time.",
keywords: "NEET, JEE, Prep, AI, CBT, DPP, Online Test, Study",
}; };
export default function RootLayout({ export default function RootLayout({

101
src/app/login/page.tsx Normal file
View File

@@ -0,0 +1,101 @@
"use client"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { ArrowLeft, Eye, EyeOff } from "lucide-react"
import Link from "next/link"
import Image from "next/image"
import { useState } from "react"
export default function LoginPage() {
const [showPassword, setShowPassword] = useState(false)
return (
<div className="min-h-screen bg-background flex flex-col items-center justify-center p-6 selection:bg-[#00F0FF]/20">
<Link href="/" className="absolute top-8 left-8 text-muted-foreground hover:text-foreground flex items-center gap-2 transition-colors font-medium">
<ArrowLeft size={16} /> Back to Home
</Link>
<div className="w-full max-w-md space-y-8 animate-in fade-in slide-in-from-bottom-8 duration-700">
<div className="flex justify-center mb-8">
<div className="relative h-20 w-72">
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
alt="PragatiVeer" fill className="object-contain scale-135 dark:hidden" priority
/>
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
alt="PragatiVeer" fill className="object-contain scale-135 hidden dark:block" priority
/>
</div>
</div>
<Card className="border-border bg-secondary/10 backdrop-blur-xl shadow-2xl shadow-[#00F0FF]/5 rounded-[2rem] overflow-hidden">
<CardHeader className="text-center pb-2">
<CardTitle className="text-2xl font-bold tracking-tight">Welcome back</CardTitle>
<CardDescription className="text-muted-foreground">Enter your credentials to access your dashboard.</CardDescription>
</CardHeader>
<CardContent className="space-y-6 pt-4">
<div className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-bold text-foreground">Email</label>
<input
type="email"
defaultValue="demo@pragativeer.com"
placeholder="student@example.com"
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-[#00F0FF] focus:border-transparent transition-all"
/>
</div>
<div className="space-y-2">
<div className="flex items-center justify-between">
<label className="text-sm font-bold text-foreground">Password</label>
<Link href="#" className="text-xs font-bold text-[#00F0FF] hover:text-[#00F0FF]/80 transition-colors">Forgot password?</Link>
</div>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
defaultValue="pragativeer2026"
placeholder="••••••••"
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-[#00F0FF] focus:border-transparent transition-all pr-10"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors"
>
{showPassword ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
</div>
</div>
</div>
<Link href="/dashboard" className="block">
<Button className="w-full rounded-xl h-12 font-bold text-base bg-foreground text-background hover:bg-foreground/90 transition-all shadow-[0_0_15px_-5px_#00F0FF]">
Sign In
</Button>
</Link>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t border-border"></span>
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background/80 px-2 text-muted-foreground font-bold tracking-widest backdrop-blur-md">Or continue with</span>
</div>
</div>
<Link href="/dashboard" className="block">
<Button variant="outline" className="w-full rounded-xl h-12 font-bold bg-background border-border hover:bg-secondary/50 transition-all flex items-center justify-center gap-2">
<svg viewBox="0 0 24 24" className="h-5 w-5"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/><path d="M1 1h22v22H1z" fill="none"/></svg>
Google
</Button>
</Link>
</CardContent>
</Card>
<p className="text-center text-sm text-muted-foreground font-medium">
Don't have an account? <Link href="/signup" className="font-bold text-foreground hover:text-primary transition-colors">Sign up</Link>
</p>
</div>
</div>
)
}

View File

@@ -1,65 +1,531 @@
import Image from "next/image"; "use client"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Card, CardContent } from "@/components/ui/card"
import { BrainCircuit, Activity, Zap, CheckCircle2, Shield, ArrowRight, Play, BookOpen, LineChart, Trophy, Sparkles, MessageSquare } from "lucide-react"
import Image from "next/image"
import Link from "next/link"
import { motion, useScroll, useTransform, Variants } from "framer-motion"
import { useRef } from "react"
export default function MarketingPage() {
const containerRef = useRef(null)
const { scrollYProgress } = useScroll({
target: containerRef,
offset: ["start start", "end start"]
})
// Slower background parallax
const yBg = useTransform(scrollYProgress, [0, 1], ["0%", "50%"])
// Stagger variants for the features
const containerVariants: Variants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.2
}
}
}
const itemVariants: Variants = {
hidden: { opacity: 0, y: 30 },
visible: {
opacity: 1,
y: 0,
transition: { type: "spring", stiffness: 100, damping: 12 }
}
}
export default function Home() {
return ( return (
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black"> <div ref={containerRef} className="min-h-screen bg-background text-foreground overflow-x-hidden selection:bg-primary/20 relative">
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
<Image {/* Animated Deep Background */}
className="dark:invert" <div className="fixed inset-0 z-0 pointer-events-none bg-grid opacity-30"></div>
src="/next.svg" <div className="fixed inset-0 z-0 pointer-events-none" style={{ background: 'radial-gradient(circle at 50% 0%, rgba(209, 255, 77, 0.05) 0%, transparent 50%)' }}></div>
alt="Next.js logo" <div className="fixed inset-0 z-0 pointer-events-none" style={{ background: 'radial-gradient(circle at 100% 50%, rgba(0, 240, 255, 0.03) 0%, transparent 40%)' }}></div>
width={100}
height={20} {/* Floating Orbs (Using Framer Motion) */}
priority <motion.div
/> className="fixed top-1/4 left-1/4 size-[400px] rounded-full bg-primary/20 blur-[120px] pointer-events-none mix-blend-screen -z-10"
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left"> animate={{ x: [0, 50, -20, 0], y: [0, -30, 40, 0] }}
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50"> transition={{ duration: 15, repeat: Infinity, ease: "linear" }}
To get started, edit the page.tsx file. />
</h1> <motion.div
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400"> className="fixed bottom-1/4 right-1/4 size-[500px] rounded-full bg-[#00F0FF]/10 blur-[150px] pointer-events-none mix-blend-screen -z-10"
Looking for a starting point or more instructions? Head over to{" "} animate={{ x: [0, -60, 30, 0], y: [0, 40, -50, 0] }}
<a transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" />
className="font-medium text-zinc-950 dark:text-zinc-50"
> {/* Navigation */}
Templates <nav className="fixed top-0 w-full z-50 bg-background/50 backdrop-blur-xl border-b border-border/50">
</a>{" "} <div className="max-w-7xl mx-auto px-6 h-20 flex items-center justify-between">
or the{" "} <Link href="/" className="relative h-14 w-60 hover:opacity-90 transition-opacity block">
<a <Image
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
className="font-medium text-zinc-950 dark:text-zinc-50" alt="PragatiVeer" fill className="object-contain object-left scale-135 origin-left dark:hidden" priority
>
Learning
</a>{" "}
center.
</p>
</div>
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
<a
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/> />
Deploy Now <Image
</a> src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
<a alt="PragatiVeer" fill className="object-contain object-left scale-135 origin-left hidden dark:block" priority
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]" />
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" </Link>
target="_blank" <div className="hidden md:flex items-center gap-8 text-sm font-medium text-muted-foreground">
rel="noopener noreferrer" <Link href="#features" className="hover:text-foreground transition-colors">Features</Link>
> <Link href="#pricing" className="hover:text-foreground transition-colors">Pricing</Link>
Documentation <Link href="/about" className="hover:text-foreground transition-colors">About</Link>
</a> </div>
<div className="flex items-center gap-4">
<Link href="/login" className="text-sm font-bold hover:text-primary transition-colors hidden sm:block">Log in</Link>
<Link href="/signup">
<Button className="rounded-full font-bold px-6 shadow-[0_0_15px_-5px_var(--color-primary)] hover:shadow-[0_0_25px_-5px_var(--color-primary)] transition-all">Get Started</Button>
</Link>
</div>
</div> </div>
</nav>
<main className="relative z-10 pt-32 pb-24">
{/* Hero Section */}
<section className="px-6 max-w-7xl mx-auto text-center space-y-8 pt-12 pb-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<Badge variant="outline" className="border-primary/50 text-primary bg-primary/10 px-4 py-1.5 rounded-full text-xs font-bold tracking-widest uppercase shadow-[0_0_15px_-5px_var(--color-primary)] mb-6">
The Next Evolution of Prep
</Badge>
</motion.div>
<motion.h1
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.8, type: "spring" }}
className="text-6xl md:text-8xl font-bold tracking-tighter max-w-5xl mx-auto leading-[1.1]"
>
NEET/JEE Prep, <br className="hidden md:block" />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary via-[#00F0FF] to-primary animate-gradient pb-2 drop-shadow-[0_0_20px_rgba(209,255,77,0.3)]">Re-engineered by AI.</span>
</motion.h1>
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.8, delay: 0.2 }}
className="text-xl md:text-2xl text-muted-foreground max-w-2xl mx-auto leading-relaxed font-medium"
>
Experience the most accurate CBT simulator combined with adaptive DPPs generated specifically for your weak areas in real-time.
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.4 }}
className="flex flex-col sm:flex-row items-center justify-center gap-4 pt-8"
>
<Link href="/signup">
<Button size="lg" className="group rounded-full h-14 px-8 text-base font-bold shadow-[0_0_40px_-10px_var(--color-primary)] hover:shadow-[0_0_60px_-10px_var(--color-primary)] transition-all w-full sm:w-auto relative overflow-hidden">
<span className="relative z-10 flex items-center">Start Free Trial <ArrowRight className="ml-2 group-hover:translate-x-1 transition-transform" size={18} /></span>
<div className="absolute inset-0 -translate-x-full animate-shine bg-gradient-to-r from-transparent via-white/20 to-transparent z-0"></div>
</Button>
</Link>
<Link href="/signup">
<Button size="lg" variant="outline" className="rounded-full h-14 px-8 text-base border-border bg-background/50 backdrop-blur-sm w-full sm:w-auto hover:bg-secondary/50 transition-colors group">
<Play className="mr-2 group-hover:scale-110 transition-transform text-[#00F0FF]" size={18} fill="currentColor" /> Watch Demo
</Button>
</Link>
</motion.div>
{/* Dashboard Preview Mockup */}
<motion.div
initial={{ opacity: 0, y: 40, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
transition={{ duration: 1, delay: 0.6, type: "spring" }}
className="relative max-w-5xl mx-auto mt-20 rounded-[2rem] border border-border/60 bg-secondary/5 backdrop-blur-xl shadow-[0_0_50px_-15px_rgba(0,240,255,0.15)] overflow-hidden"
>
{/* Top Window Chrome Bar */}
<div className="flex items-center justify-between px-6 py-4 border-b border-border/50 bg-background/50">
<div className="flex items-center gap-2">
<div className="size-3 rounded-full bg-red-500/80"></div>
<div className="size-3 rounded-full bg-yellow-500/80"></div>
<div className="size-3 rounded-full bg-green-500/80"></div>
</div>
<div className="hidden sm:flex items-center bg-background/80 border border-border/50 px-6 py-1.5 rounded-full text-xs font-mono text-muted-foreground w-80 justify-center gap-2">
<div className="size-2 rounded-full bg-[#00F0FF] animate-pulse"></div>
pragativeer.ai/dashboard/student
</div>
<div className="flex items-center gap-2">
<Badge variant="outline" className="border-[#00F0FF]/30 text-[#00F0FF] bg-[#00F0FF]/5 px-2 py-0.5 rounded-md text-[10px] uppercase tracking-wider font-bold">
AI Active
</Badge>
</div>
</div>
{/* Dashboard Inner Screen */}
<div className="grid grid-cols-1 md:grid-cols-4 min-h-[480px]">
{/* Mock Sidebar */}
<div className="md:col-span-1 border-r border-border/50 p-6 space-y-6 hidden md:block bg-background/20">
<div className="space-y-2">
<div className="flex items-center gap-3 px-3 py-2.5 rounded-xl bg-primary/10 text-primary border border-primary/20 text-sm font-semibold">
<Activity size={18} />
Overview
</div>
<div className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-muted-foreground hover:bg-secondary/30 hover:text-foreground text-sm font-semibold transition-all">
<Play size={18} className="text-muted-foreground" />
Exams (CBT)
</div>
<div className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-muted-foreground hover:bg-secondary/30 hover:text-foreground text-sm font-semibold transition-all">
<BrainCircuit size={18} />
Daily Practice
</div>
<div className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-muted-foreground hover:bg-secondary/30 hover:text-foreground text-sm font-semibold transition-all">
<BookOpen size={18} />
Study Materials
</div>
</div>
<div className="pt-6 border-t border-border/50">
<p className="px-3 text-[10px] font-bold uppercase tracking-widest text-muted-foreground mb-3">AI Intelligence</p>
<div className="space-y-2">
<div className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-muted-foreground hover:bg-secondary/30 hover:text-foreground text-sm font-semibold transition-all">
<LineChart size={18} />
Analytics
</div>
<div className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-muted-foreground hover:bg-secondary/30 hover:text-foreground text-sm font-semibold transition-all">
<Trophy size={18} />
Rank Predictor
</div>
</div>
</div>
</div>
{/* Mock Main Content Area */}
<div className="md:col-span-3 p-6 md:p-8 space-y-6 text-left">
{/* Greeting & Header */}
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div>
<h3 className="text-xl font-bold tracking-tight">Welcome, Demo Student</h3>
<p className="text-xs text-muted-foreground font-medium mt-1">Your adaptive NEET path is optimized. Next review in 2 hours.</p>
</div>
<div className="flex items-center gap-2 bg-secondary/30 border border-border/50 px-3 py-1.5 rounded-xl text-xs font-semibold">
<span className="size-2 rounded-full bg-emerald-500 shadow-[0_0_8px_#10b981]"></span>
Subscription: <span className="text-primary font-bold ml-1">AI Pro Plan</span>
</div>
</div>
{/* Dashboard Grid Cards */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
{/* Card 1: Weakness Analysis */}
<div className="bg-background/40 border border-border/50 rounded-2xl p-5 space-y-4 shadow-sm hover:border-[#00F0FF]/30 transition-all duration-300 relative group">
<div className="flex items-center justify-between">
<h4 className="text-xs font-bold uppercase tracking-widest text-muted-foreground">Focus Topic</h4>
<Badge variant="outline" className="border-primary/30 text-primary bg-primary/5 rounded-md text-[10px] font-bold">Physics</Badge>
</div>
<div className="space-y-2">
<div className="flex justify-between text-sm font-bold">
<span>Rotational Dynamics</span>
<span className="text-primary">42% Mastery</span>
</div>
<div className="h-2 bg-secondary rounded-full overflow-hidden">
<div className="h-full bg-primary rounded-full w-[42%] shadow-[0_0_10px_var(--color-primary)]"></div>
</div>
</div>
<p className="text-xs text-muted-foreground leading-relaxed">
<strong className="text-foreground font-semibold">AI recommendation:</strong> Solve 5 intermediate DPP questions on Moment of Inertia to unlock the next level and boost your expected score.
</p>
</div>
{/* Card 2: Live Score & AIR Rank Predictor */}
<div className="bg-background/40 border border-border/50 rounded-2xl p-5 space-y-4 shadow-sm hover:border-[#00F0FF]/30 transition-all duration-300 relative group">
<div className="flex items-center justify-between">
<h4 className="text-xs font-bold uppercase tracking-widest text-[#00F0FF]">Rank Simulator</h4>
<Badge variant="outline" className="border-[#00F0FF]/30 text-[#00F0FF] bg-[#00F0FF]/5 rounded-md text-[10px] font-bold">NEET Target</Badge>
</div>
<div className="flex items-end justify-between">
<div>
<p className="text-[10px] font-bold text-muted-foreground uppercase">Estimated AIR</p>
<p className="text-3xl font-bold tracking-tight text-[#00F0FF] drop-shadow-[0_0_8px_rgba(0,240,255,0.3)]">1,240</p>
</div>
<div className="text-right">
<p className="text-[10px] font-bold text-muted-foreground uppercase">Expected Score</p>
<p className="text-xl font-bold tracking-tight text-foreground">685 <span className="text-xs font-medium text-muted-foreground">/ 720</span></p>
</div>
</div>
{/* Mini Sparkline Chart representation */}
<div className="flex items-center gap-1 h-8 pt-2">
{[30, 45, 35, 55, 70, 60, 85].map((val, i) => (
<div
key={i}
className="flex-1 bg-[#00F0FF]/20 hover:bg-[#00F0FF]/60 transition-colors rounded-t"
style={{ height: `${val}%` }}
></div>
))}
</div>
</div>
</div>
{/* AI Tutor Consultation Interface */}
<div className="bg-secondary/20 border border-border/40 rounded-2xl p-5 flex gap-4 items-start relative overflow-hidden">
<div className="size-10 rounded-xl bg-primary text-primary-foreground flex items-center justify-center font-bold text-sm shadow-[0_0_15px_-3px_var(--color-primary)] shrink-0 mt-1">
<Sparkles size={20} className="animate-pulse" />
</div>
<div className="space-y-3 text-left w-full">
<div className="flex items-center justify-between w-full">
<h4 className="text-sm font-bold text-foreground">AI Tutor Agent</h4>
<span className="text-[10px] font-mono text-muted-foreground">Response generated instantly</span>
</div>
<div className="text-xs text-muted-foreground leading-relaxed max-w-xl">
"I have analyzed your last CBT physics test. You excelled in Mechanics but hesitated on electromagnetic induction questions, spending an average of 42 seconds longer per problem. I have generated a custom 10-question DPP focusing exclusively on induction. Let's tackle it now."
</div>
<div className="flex items-center gap-2 pt-1">
<Link href="/dashboard/dpp">
<Button size="sm" className="h-8 rounded-lg px-4 text-xs font-bold">
Start Custom DPP
</Button>
</Link>
<Button size="sm" variant="outline" className="h-8 rounded-lg px-4 text-xs border-border bg-background/50">
<MessageSquare size={12} className="mr-1.5 text-[#00F0FF]" /> Ask AI to explain
</Button>
</div>
</div>
</div>
</div>
</div>
</motion.div>
</section>
{/* Infinite Trust Bar */}
<section className="mt-32 border-y border-border/50 bg-secondary/10 backdrop-blur-sm overflow-hidden py-8 relative">
<div className="absolute left-0 top-0 bottom-0 w-32 bg-gradient-to-r from-background to-transparent z-10"></div>
<div className="absolute right-0 top-0 bottom-0 w-32 bg-gradient-to-l from-background to-transparent z-10"></div>
<div className="flex w-[200%] animate-marquee opacity-70 hover:opacity-100 transition-opacity">
{/* First Set */}
<div className="flex-1 flex justify-around items-center px-4">
<div className="flex items-center gap-3 font-bold text-xl tracking-tight"><Shield size={28} className="text-[#00F0FF] drop-shadow-[0_0_10px_rgba(0,240,255,0.5)]" /> NTA Compliant</div>
<div className="flex items-center gap-3 font-bold text-xl tracking-tight"><Activity size={28} className="text-primary drop-shadow-[0_0_10px_var(--color-primary)]" /> 99.9% Uptime</div>
<div className="flex items-center gap-3 font-bold text-xl tracking-tight"><BrainCircuit size={28} className="text-[#00F0FF] drop-shadow-[0_0_10px_rgba(0,240,255,0.5)]" /> 10M+ AI Models</div>
<div className="flex items-center gap-3 font-bold text-xl tracking-tight"><CheckCircle2 size={28} className="text-primary drop-shadow-[0_0_10px_var(--color-primary)]" /> 50k+ Selections</div>
</div>
{/* Duplicate Set for seamless scroll */}
<div className="flex-1 flex justify-around items-center px-4">
<div className="flex items-center gap-3 font-bold text-xl tracking-tight"><Shield size={28} className="text-[#00F0FF] drop-shadow-[0_0_10px_rgba(0,240,255,0.5)]" /> NTA Compliant</div>
<div className="flex items-center gap-3 font-bold text-xl tracking-tight"><Activity size={28} className="text-primary drop-shadow-[0_0_10px_var(--color-primary)]" /> 99.9% Uptime</div>
<div className="flex items-center gap-3 font-bold text-xl tracking-tight"><BrainCircuit size={28} className="text-[#00F0FF] drop-shadow-[0_0_10px_rgba(0,240,255,0.5)]" /> 10M+ AI Models</div>
<div className="flex items-center gap-3 font-bold text-xl tracking-tight"><CheckCircle2 size={28} className="text-primary drop-shadow-[0_0_10px_var(--color-primary)]" /> 50k+ Selections</div>
</div>
</div>
</section>
{/* Animated DPP Engine Section */}
<section id="features" className="py-32 px-6 max-w-7xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.8 }}
className="text-center mb-20"
>
<h2 className="text-4xl md:text-6xl font-bold tracking-tighter mb-6">Adaptive Engine</h2>
<p className="text-muted-foreground text-xl max-w-2xl mx-auto">Our AI analyzes every keystroke and hesitation to generate the exact problems you need to solve next.</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "-50px" }}
className="grid grid-cols-1 md:grid-cols-3 gap-8"
>
<motion.div variants={itemVariants}>
<Card className="bg-secondary/10 backdrop-blur-xl border-border/50 hover:border-primary/50 transition-all duration-300 rounded-[2rem] h-full shadow-lg group">
<CardContent className="p-8 relative overflow-hidden">
<div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-opacity transform group-hover:scale-110 group-hover:-rotate-12 duration-500">
<Activity size={120} />
</div>
<div className="size-14 rounded-2xl bg-primary/20 text-primary flex items-center justify-center mb-8 shadow-[0_0_20px_-5px_var(--color-primary)]">
<Activity size={28} />
</div>
<h3 className="text-2xl font-bold mb-4 tracking-tight">Real-time Analysis</h3>
<p className="text-muted-foreground leading-relaxed text-lg">
Every test attempt updates your knowledge graph instantly, identifying micro-concepts where you struggle.
</p>
</CardContent>
</Card>
</motion.div>
<motion.div variants={itemVariants}>
<Card className="bg-[#00F0FF]/5 backdrop-blur-xl border-[#00F0FF]/20 hover:border-[#00F0FF]/60 transition-all duration-300 rounded-[2rem] h-full shadow-[0_0_30px_-15px_#00F0FF] group">
<CardContent className="p-8 relative overflow-hidden">
<div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-opacity transform group-hover:scale-110 group-hover:rotate-12 duration-500">
<BrainCircuit size={120} />
</div>
<div className="size-14 rounded-2xl bg-[#00F0FF]/20 text-[#00F0FF] flex items-center justify-center mb-8 shadow-[0_0_20px_-5px_#00F0FF]">
<BrainCircuit size={28} />
</div>
<h3 className="text-2xl font-bold mb-4 tracking-tight">Dynamic Generation</h3>
<p className="text-muted-foreground leading-relaxed text-lg">
Custom problems are generated on the fly, matching the exact difficulty and NTA pattern required for growth.
</p>
</CardContent>
</Card>
</motion.div>
<motion.div variants={itemVariants}>
<Card className="bg-secondary/10 backdrop-blur-xl border-border/50 hover:border-primary/50 transition-all duration-300 rounded-[2rem] h-full shadow-lg group">
<CardContent className="p-8 relative overflow-hidden">
<div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-opacity transform group-hover:scale-110 group-hover:-rotate-12 duration-500">
<Zap size={120} />
</div>
<div className="size-14 rounded-2xl bg-primary/20 text-primary flex items-center justify-center mb-8 shadow-[0_0_20px_-5px_var(--color-primary)]">
<Zap size={28} />
</div>
<h3 className="text-2xl font-bold mb-4 tracking-tight">Instant Resolution</h3>
<p className="text-muted-foreground leading-relaxed text-lg">
Get interactive, step-by-step AI breakdowns for every wrong answer. Ask follow-up questions until you master it.
</p>
</CardContent>
</Card>
</motion.div>
</motion.div>
</section>
{/* Animated Pricing */}
<section id="pricing" className="py-24 px-6 max-w-7xl mx-auto relative">
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 size-[600px] bg-primary/5 blur-[120px] rounded-full pointer-events-none -z-10"></div>
<motion.div
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
className="text-center mb-20"
>
<h2 className="text-4xl md:text-6xl font-bold tracking-tighter mb-6">Simple, Transparent Pricing</h2>
<p className="text-muted-foreground text-xl max-w-2xl mx-auto">Unlock the ultimate unfair advantage for your NEET/JEE preparation.</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-5xl mx-auto">
<motion.div
initial={{ opacity: 0, x: -50 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, type: "spring" }}
>
<Card className="bg-background/80 backdrop-blur-md border-border p-10 rounded-[2.5rem] flex flex-col hover:border-border/80 transition-colors h-full z-10 relative shadow-xl">
<h3 className="text-3xl font-bold mb-2">Basic</h3>
<p className="text-muted-foreground mb-8 text-lg">Perfect for self-paced revision.</p>
<div className="text-6xl font-bold tracking-tighter mb-10">₹999<span className="text-xl text-muted-foreground font-medium">/mo</span></div>
<ul className="space-y-5 mb-10 flex-1 font-medium text-lg">
<li className="flex items-center gap-4"><CheckCircle2 size={24} className="text-primary" /> 10 Full Syllabus CBTs</li>
<li className="flex items-center gap-4"><CheckCircle2 size={24} className="text-primary" /> Standard Question Bank</li>
<li className="flex items-center gap-4"><CheckCircle2 size={24} className="text-primary" /> Basic Analytics</li>
</ul>
<Link href="/signup">
<Button variant="outline" size="lg" className="w-full rounded-2xl h-16 border-border font-bold text-lg hover:bg-secondary/50">Choose Basic</Button>
</Link>
</Card>
</motion.div>
<motion.div
initial={{ opacity: 0, x: 50 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, type: "spring", delay: 0.1 }}
className="relative"
>
<Card className="bg-secondary/30 backdrop-blur-xl border-primary p-10 rounded-[2.5rem] flex flex-col shadow-[0_0_60px_-15px_var(--color-primary)] hover:shadow-[0_0_80px_-15px_var(--color-primary)] transition-all h-full overflow-hidden">
<div className="absolute inset-0 -translate-x-full animate-shine bg-gradient-to-r from-transparent via-white/10 to-transparent z-0 pointer-events-none"></div>
<div className="absolute top-0 right-10 transform -translate-y-1/2 z-20">
<Badge className="bg-primary text-primary-foreground font-bold px-5 py-2 text-sm rounded-full shadow-[0_0_15px_-2px_var(--color-primary)]">MOST POPULAR</Badge>
</div>
<div className="relative z-10 flex flex-col h-full">
<h3 className="text-3xl font-bold mb-2">AI Pro</h3>
<p className="text-muted-foreground mb-8 text-lg">The complete AI-driven preparation system.</p>
<div className="text-6xl font-bold tracking-tighter mb-10 text-primary drop-shadow-[0_0_10px_var(--color-primary)]">₹2499<span className="text-xl text-foreground font-medium">/mo</span></div>
<ul className="space-y-5 mb-10 flex-1 font-medium text-lg">
<li className="flex items-center gap-4"><CheckCircle2 size={24} className="text-[#00F0FF]" /> Unlimited Dynamic CBTs</li>
<li className="flex items-center gap-4"><CheckCircle2 size={24} className="text-[#00F0FF]" /> Adaptive AI DPPs</li>
<li className="flex items-center gap-4"><CheckCircle2 size={24} className="text-[#00F0FF]" /> Interactive AI Tutor (24/7)</li>
<li className="flex items-center gap-4"><CheckCircle2 size={24} className="text-[#00F0FF]" /> Predictive Rank Analytics</li>
</ul>
<Link href="/signup">
<Button size="lg" className="w-full rounded-2xl h-16 font-bold text-lg bg-primary text-primary-foreground hover:bg-primary/90 shadow-[0_0_20px_-5px_var(--color-primary)] transition-all">Get AI Pro</Button>
</Link>
</div>
</Card>
</motion.div>
</div>
</section>
</main> </main>
{/* Global Footer (Static) */}
<footer className="relative z-10 bg-background/90 backdrop-blur-md border-t border-border pt-16 pb-8">
<div className="max-w-7xl mx-auto px-6">
<div className="grid grid-cols-1 md:grid-cols-4 gap-12 mb-16">
<div className="md:col-span-1 space-y-4">
<div className="relative h-16 w-64 mb-6">
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
alt="PragatiVeer" fill className="object-contain object-left scale-135 origin-left dark:hidden"
/>
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
alt="PragatiVeer" fill className="object-contain object-left scale-135 origin-left hidden dark:block"
/>
</div>
<p className="text-sm text-muted-foreground font-medium leading-relaxed">
Re-engineering NEET & JEE preparation with adaptive AI models. Learn faster, rank higher.
</p>
<div className="flex items-center gap-4 pt-2">
<Link href="#" className="text-muted-foreground hover:text-foreground transition-colors">
<svg viewBox="0 0 24 24" width="20" height="20" stroke="currentColor" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"><path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"></path></svg>
</Link>
<Link href="#" className="text-muted-foreground hover:text-foreground transition-colors">
<svg viewBox="0 0 24 24" width="20" height="20" stroke="currentColor" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
</Link>
<Link href="#" className="text-muted-foreground hover:text-foreground transition-colors">
<svg viewBox="0 0 24 24" width="20" height="20" stroke="currentColor" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>
</Link>
</div>
</div>
<div>
<h4 className="font-bold mb-6 tracking-tight text-foreground">Product</h4>
<ul className="space-y-3 text-sm font-medium text-muted-foreground">
<li><Link href="#features" className="hover:text-primary transition-colors">Features</Link></li>
<li><Link href="#pricing" className="hover:text-primary transition-colors">Pricing</Link></li>
<li><Link href="/dashboard" className="hover:text-primary transition-colors">Student Dashboard</Link></li>
<li><Link href="/admin" className="hover:text-[#00F0FF] transition-colors">Admin Panel</Link></li>
</ul>
</div>
<div>
<h4 className="font-bold mb-6 tracking-tight text-foreground">Company</h4>
<ul className="space-y-3 text-sm font-medium text-muted-foreground">
<li><Link href="/about" className="hover:text-primary transition-colors">About Us</Link></li>
<li><Link href="/contact" className="hover:text-primary transition-colors">Contact</Link></li>
<li><Link href="#" className="hover:text-primary transition-colors">Careers</Link></li>
</ul>
</div>
<div>
<h4 className="font-bold mb-6 tracking-tight text-foreground">Legal</h4>
<ul className="space-y-3 text-sm font-medium text-muted-foreground">
<li><Link href="#" className="hover:text-primary transition-colors">Privacy Policy</Link></li>
<li><Link href="#" className="hover:text-primary transition-colors">Terms of Service</Link></li>
</ul>
</div>
</div>
<div className="border-t border-border pt-8 flex flex-col md:flex-row items-center justify-between gap-4">
<p className="text-sm text-muted-foreground font-medium">© {new Date().getFullYear()} PragatiVeer. All rights reserved.</p>
<div className="flex items-center gap-2 text-sm text-muted-foreground font-medium">
Made with <div className="size-2 rounded-full bg-primary animate-pulse"></div> by AI Agents
</div>
</div>
</div>
</footer>
</div> </div>
); )
} }

114
src/app/signup/page.tsx Normal file
View File

@@ -0,0 +1,114 @@
"use client"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { ArrowLeft, Eye, EyeOff } from "lucide-react"
import Link from "next/link"
import Image from "next/image"
import { useState } from "react"
export default function SignupPage() {
const [showPassword, setShowPassword] = useState(false)
return (
<div className="min-h-screen bg-background flex flex-col items-center justify-center p-6 selection:bg-primary/20">
<Link href="/" className="absolute top-8 left-8 text-muted-foreground hover:text-foreground flex items-center gap-2 transition-colors font-medium">
<ArrowLeft size={16} /> Back to Home
</Link>
<div className="w-full max-w-md space-y-8 animate-in fade-in slide-in-from-bottom-8 duration-700">
<div className="flex justify-center mb-8">
<div className="relative h-20 w-72">
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
alt="PragatiVeer" fill className="object-contain scale-135 dark:hidden" priority
/>
<Image
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
alt="PragatiVeer" fill className="object-contain scale-135 hidden dark:block" priority
/>
</div>
</div>
<Card className="border-border bg-secondary/10 backdrop-blur-xl shadow-[0_0_50px_-20px_var(--color-primary)] rounded-[2rem] overflow-hidden">
<CardHeader className="text-center pb-2">
<CardTitle className="text-2xl font-bold tracking-tight">Create an account</CardTitle>
<CardDescription className="text-muted-foreground">Start your AI-powered preparation journey today.</CardDescription>
</CardHeader>
<CardContent className="space-y-6 pt-4">
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<label className="text-sm font-bold text-foreground">First Name</label>
<input
type="text"
placeholder="John"
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
/>
</div>
<div className="space-y-2">
<label className="text-sm font-bold text-foreground">Last Name</label>
<input
type="text"
placeholder="Doe"
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
/>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-bold text-foreground">Email</label>
<input
type="email"
placeholder="student@example.com"
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
/>
</div>
<div className="space-y-2">
<label className="text-sm font-bold text-foreground">Password</label>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
placeholder="••••••••"
className="w-full bg-background border border-border rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all pr-10"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors"
>
{showPassword ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
</div>
</div>
</div>
<Link href="/dashboard" className="block">
<Button className="w-full rounded-xl h-12 font-bold text-base bg-primary text-primary-foreground hover:bg-primary/90 transition-all shadow-[0_0_20px_-5px_var(--color-primary)]">
Create Account
</Button>
</Link>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t border-border"></span>
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background/80 px-2 text-muted-foreground font-bold tracking-widest backdrop-blur-md">Or continue with</span>
</div>
</div>
<Link href="/dashboard" className="block">
<Button variant="outline" className="w-full rounded-xl h-12 font-bold bg-background border-border hover:bg-secondary/50 transition-all flex items-center justify-center gap-2">
<svg viewBox="0 0 24 24" className="h-5 w-5"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/><path d="M1 1h22v22H1z" fill="none"/></svg>
Google
</Button>
</Link>
</CardContent>
</Card>
<p className="text-center text-sm text-muted-foreground font-medium">
Already have an account? <Link href="/login" className="font-bold text-foreground hover:text-primary transition-colors">Log in</Link>
</p>
</div>
</div>
)
}

View File

@@ -0,0 +1,26 @@
import * as React from "react"
import { cn } from "@/lib/utils"
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement> {
variant?: "default" | "secondary" | "outline" | "destructive";
}
function Badge({ className, variant = "default", ...props }: BadgeProps) {
return (
<div
className={cn(
"inline-flex items-center rounded-md px-2.5 py-0.5 text-xs font-medium uppercase tracking-wider transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80": variant === "default",
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80": variant === "secondary",
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80": variant === "destructive",
"border border-border text-foreground": variant === "outline",
},
className
)}
{...props}
/>
)
}
export { Badge }

View File

@@ -0,0 +1,37 @@
import * as React from "react"
import { cn } from "@/lib/utils"
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "default" | "outline" | "ghost" | "secondary" | "link";
size?: "default" | "sm" | "lg" | "icon";
asChild?: boolean;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant = "default", size = "default", ...props }, ref) => {
return (
<button
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-xl text-sm font-medium ring-offset-background transition-all duration-300 ease-in-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
"bg-primary text-primary-foreground hover:bg-primary/90 hover:scale-[1.02] active:scale-[0.98]": variant === "default",
"bg-secondary text-secondary-foreground hover:bg-secondary/80": variant === "secondary",
"border border-border bg-background hover:bg-accent hover:text-accent-foreground": variant === "outline",
"hover:bg-accent hover:text-accent-foreground": variant === "ghost",
"text-primary underline-offset-4 hover:underline": variant === "link",
"h-10 px-4 py-2": size === "default",
"h-9 rounded-xl px-3": size === "sm",
"h-11 rounded-2xl px-8": size === "lg",
"h-10 w-10": size === "icon",
},
className
)}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button }

View File

@@ -0,0 +1,72 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-2xl border border-border bg-background text-foreground shadow-sm transition-all duration-300 hover:shadow-md",
className
)}
{...props}
/>
)
)
Card.displayName = "Card"
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
)
)
CardHeader.displayName = "CardHeader"
const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn(
"font-semibold leading-none tracking-tight text-lg",
className
)}
{...props}
/>
)
)
CardTitle.displayName = "CardTitle"
const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
)
)
CardDescription.displayName = "CardDescription"
const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
)
)
CardContent.displayName = "CardContent"
const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
)
)
CardFooter.displayName = "CardFooter"
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

6
src/lib/utils.ts Normal file
View File

@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}