Se realiza merge con integracion de roberto y memo
This commit is contained in:
22
bun.lock
22
bun.lock
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"configVersion": 1,
|
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "acad-ia-2",
|
"name": "acad-ia-2",
|
||||||
@@ -12,6 +11,7 @@
|
|||||||
"@radix-ui/react-select": "^2.2.6",
|
"@radix-ui/react-select": "^2.2.6",
|
||||||
"@radix-ui/react-separator": "^1.1.8",
|
"@radix-ui/react-separator": "^1.1.8",
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
"@radix-ui/react-tooltip": "^1.2.8",
|
"@radix-ui/react-tooltip": "^1.2.8",
|
||||||
"@stepperize/react": "^5.1.9",
|
"@stepperize/react": "^5.1.9",
|
||||||
"@tailwindcss/vite": "^4.0.6",
|
"@tailwindcss/vite": "^4.0.6",
|
||||||
@@ -248,6 +248,8 @@
|
|||||||
|
|
||||||
"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
|
"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
|
||||||
|
|
||||||
|
"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
|
||||||
|
|
||||||
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
|
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
|
||||||
|
|
||||||
"@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
|
"@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
|
||||||
@@ -256,6 +258,8 @@
|
|||||||
|
|
||||||
"@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
|
"@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
|
||||||
|
|
||||||
"@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
|
"@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
|
||||||
|
|
||||||
"@radix-ui/react-context": ["@radix-ui/react-context@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw=="],
|
"@radix-ui/react-context": ["@radix-ui/react-context@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw=="],
|
||||||
@@ -264,6 +268,8 @@
|
|||||||
|
|
||||||
"@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
|
"@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
|
||||||
|
|
||||||
"@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
|
"@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
|
||||||
|
|
||||||
"@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
|
"@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
|
||||||
@@ -290,6 +296,8 @@
|
|||||||
|
|
||||||
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
|
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
|
||||||
|
|
||||||
"@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="],
|
"@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="],
|
||||||
|
|
||||||
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
|
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
|
||||||
@@ -1316,6 +1324,12 @@
|
|||||||
|
|
||||||
"@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
"@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-collection/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-collection/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||||
|
|
||||||
"@radix-ui/react-dialog/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
|
"@radix-ui/react-dialog/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
|
||||||
|
|
||||||
"@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
|
"@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
|
||||||
@@ -1422,6 +1436,12 @@
|
|||||||
|
|
||||||
"@radix-ui/react-portal/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
"@radix-ui/react-portal/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-roving-focus/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-scroll-area/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tabs/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||||
|
|
||||||
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||||
|
|
||||||
"@tanstack/devtools/@tanstack/devtools-client/@tanstack/devtools-event-client": ["@tanstack/devtools-event-client@0.3.5", "", {}, "sha512-RL1f5ZlfZMpghrCIdzl6mLOFLTuhqmPNblZgBaeKfdtk5rfbjykurv+VfYydOFXj0vxVIoA2d/zT7xfD7Ph8fw=="],
|
"@tanstack/devtools/@tanstack/devtools-client/@tanstack/devtools-event-client": ["@tanstack/devtools-event-client@0.3.5", "", {}, "sha512-RL1f5ZlfZMpghrCIdzl6mLOFLTuhqmPNblZgBaeKfdtk5rfbjykurv+VfYydOFXj0vxVIoA2d/zT7xfD7Ph8fw=="],
|
||||||
|
|||||||
7849
package-lock.json
generated
Normal file
7849
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@
|
|||||||
"@radix-ui/react-select": "^2.2.6",
|
"@radix-ui/react-select": "^2.2.6",
|
||||||
"@radix-ui/react-separator": "^1.1.8",
|
"@radix-ui/react-separator": "^1.1.8",
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
"@radix-ui/react-tooltip": "^1.2.8",
|
"@radix-ui/react-tooltip": "^1.2.8",
|
||||||
"@stepperize/react": "^5.1.9",
|
"@stepperize/react": "^5.1.9",
|
||||||
"@tailwindcss/vite": "^4.0.6",
|
"@tailwindcss/vite": "^4.0.6",
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import * as AvatarPrimitive from "@radix-ui/react-avatar"
|
"use client"
|
||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import * as AvatarPrimitive from "@radix-ui/react-avatar"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { Slot } from "@radix-ui/react-slot"
|
|
||||||
import { cva } from "class-variance-authority"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Slot } from "@radix-ui/react-slot"
|
||||||
import type {VariantProps} from "class-variance-authority";
|
import { cva, type VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
|||||||
56
src/components/ui/scroll-area.tsx
Normal file
56
src/components/ui/scroll-area.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function ScrollArea({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<ScrollAreaPrimitive.Root
|
||||||
|
data-slot="scroll-area"
|
||||||
|
className={cn("relative", className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ScrollAreaPrimitive.Viewport
|
||||||
|
data-slot="scroll-area-viewport"
|
||||||
|
className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ScrollAreaPrimitive.Viewport>
|
||||||
|
<ScrollBar />
|
||||||
|
<ScrollAreaPrimitive.Corner />
|
||||||
|
</ScrollAreaPrimitive.Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ScrollBar({
|
||||||
|
className,
|
||||||
|
orientation = "vertical",
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
|
||||||
|
return (
|
||||||
|
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
||||||
|
data-slot="scroll-area-scrollbar"
|
||||||
|
orientation={orientation}
|
||||||
|
className={cn(
|
||||||
|
"flex touch-none p-px transition-colors select-none",
|
||||||
|
orientation === "vertical" &&
|
||||||
|
"h-full w-2.5 border-l border-l-transparent",
|
||||||
|
orientation === "horizontal" &&
|
||||||
|
"h-2.5 flex-col border-t border-t-transparent",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ScrollAreaPrimitive.ScrollAreaThumb
|
||||||
|
data-slot="scroll-area-thumb"
|
||||||
|
className="bg-border relative flex-1 rounded-full"
|
||||||
|
/>
|
||||||
|
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ScrollArea, ScrollBar }
|
||||||
114
src/components/ui/table.tsx
Normal file
114
src/components/ui/table.tsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="table-container"
|
||||||
|
className="relative w-full overflow-x-auto"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
data-slot="table"
|
||||||
|
className={cn("w-full caption-bottom text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
||||||
|
return (
|
||||||
|
<thead
|
||||||
|
data-slot="table-header"
|
||||||
|
className={cn("[&_tr]:border-b", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
||||||
|
return (
|
||||||
|
<tbody
|
||||||
|
data-slot="table-body"
|
||||||
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
||||||
|
return (
|
||||||
|
<tfoot
|
||||||
|
data-slot="table-footer"
|
||||||
|
className={cn(
|
||||||
|
"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
||||||
|
return (
|
||||||
|
<tr
|
||||||
|
data-slot="table-row"
|
||||||
|
className={cn(
|
||||||
|
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
||||||
|
return (
|
||||||
|
<th
|
||||||
|
data-slot="table-head"
|
||||||
|
className={cn(
|
||||||
|
"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
||||||
|
return (
|
||||||
|
<td
|
||||||
|
data-slot="table-cell"
|
||||||
|
className={cn(
|
||||||
|
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableCaption({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"caption">) {
|
||||||
|
return (
|
||||||
|
<caption
|
||||||
|
data-slot="table-caption"
|
||||||
|
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Table,
|
||||||
|
TableHeader,
|
||||||
|
TableBody,
|
||||||
|
TableFooter,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableCaption,
|
||||||
|
}
|
||||||
64
src/components/ui/tabs.tsx
Normal file
64
src/components/ui/tabs.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Tabs({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Root
|
||||||
|
data-slot="tabs"
|
||||||
|
className={cn("flex flex-col gap-2", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsList({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.List>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.List
|
||||||
|
data-slot="tabs-list"
|
||||||
|
className={cn(
|
||||||
|
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsTrigger({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Trigger
|
||||||
|
data-slot="tabs-trigger"
|
||||||
|
className={cn(
|
||||||
|
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsContent({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Content
|
||||||
|
data-slot="tabs-content"
|
||||||
|
className={cn("flex-1 outline-none", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
||||||
@@ -12,10 +12,21 @@ import { Route as rootRouteImport } from './routes/__root'
|
|||||||
import { Route as LoginRouteImport } from './routes/login'
|
import { Route as LoginRouteImport } from './routes/login'
|
||||||
import { Route as DashboardRouteImport } from './routes/dashboard'
|
import { Route as DashboardRouteImport } from './routes/dashboard'
|
||||||
import { Route as IndexRouteImport } from './routes/index'
|
import { Route as IndexRouteImport } from './routes/index'
|
||||||
|
import { Route as Planes2IndexRouteImport } from './routes/planes2/index'
|
||||||
|
import { Route as MateriasIndexRouteImport } from './routes/materias/index'
|
||||||
import { Route as DemoTanstackQueryRouteImport } from './routes/demo/tanstack-query'
|
import { Route as DemoTanstackQueryRouteImport } from './routes/demo/tanstack-query'
|
||||||
|
import { Route as Planes2PlanIdRouteRouteImport } from './routes/planes2/$planId/route'
|
||||||
import { Route as PlanesListaRouteRouteImport } from './routes/planes/_lista/route'
|
import { Route as PlanesListaRouteRouteImport } from './routes/planes/_lista/route'
|
||||||
|
import { Route as Planes2PlanIdIndexRouteImport } from './routes/planes2/$planId/index'
|
||||||
import { Route as PlanesPlanIdIndexRouteImport } from './routes/planes/$planId/index'
|
import { Route as PlanesPlanIdIndexRouteImport } from './routes/planes/$planId/index'
|
||||||
|
import { Route as Planes2PlanIdMateriasRouteImport } from './routes/planes2/$planId/materias'
|
||||||
|
import { Route as Planes2PlanIdMapaRouteImport } from './routes/planes2/$planId/mapa'
|
||||||
|
import { Route as Planes2PlanIdIaplanRouteImport } from './routes/planes2/$planId/iaplan'
|
||||||
|
import { Route as Planes2PlanIdHistorialRouteImport } from './routes/planes2/$planId/historial'
|
||||||
|
import { Route as Planes2PlanIdFlujoRouteImport } from './routes/planes2/$planId/flujo'
|
||||||
|
import { Route as Planes2PlanIdDocumentoRouteImport } from './routes/planes2/$planId/documento'
|
||||||
import { Route as PlanesListaNuevoRouteImport } from './routes/planes/_lista/nuevo'
|
import { Route as PlanesListaNuevoRouteImport } from './routes/planes/_lista/nuevo'
|
||||||
|
import { Route as MateriasMateriaIdMateriaIdRouteImport } from './routes/materias/$materiaId/$materiaId'
|
||||||
import { Route as PlanesPlanIdAsignaturasListaRouteRouteImport } from './routes/planes/$planId/asignaturas/_lista/route'
|
import { Route as PlanesPlanIdAsignaturasListaRouteRouteImport } from './routes/planes/$planId/asignaturas/_lista/route'
|
||||||
import { Route as PlanesPlanIdAsignaturasAsignaturaIdRouteRouteImport } from './routes/planes/$planId/asignaturas/$asignaturaId/route'
|
import { Route as PlanesPlanIdAsignaturasAsignaturaIdRouteRouteImport } from './routes/planes/$planId/asignaturas/$asignaturaId/route'
|
||||||
import { Route as PlanesPlanIdAsignaturasListaNuevaRouteImport } from './routes/planes/$planId/asignaturas/_lista/nueva'
|
import { Route as PlanesPlanIdAsignaturasListaNuevaRouteImport } from './routes/planes/$planId/asignaturas/_lista/nueva'
|
||||||
@@ -35,26 +46,82 @@ const IndexRoute = IndexRouteImport.update({
|
|||||||
path: '/',
|
path: '/',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const Planes2IndexRoute = Planes2IndexRouteImport.update({
|
||||||
|
id: '/planes2/',
|
||||||
|
path: '/planes2/',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
|
const MateriasIndexRoute = MateriasIndexRouteImport.update({
|
||||||
|
id: '/materias/',
|
||||||
|
path: '/materias/',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const DemoTanstackQueryRoute = DemoTanstackQueryRouteImport.update({
|
const DemoTanstackQueryRoute = DemoTanstackQueryRouteImport.update({
|
||||||
id: '/demo/tanstack-query',
|
id: '/demo/tanstack-query',
|
||||||
path: '/demo/tanstack-query',
|
path: '/demo/tanstack-query',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const Planes2PlanIdRouteRoute = Planes2PlanIdRouteRouteImport.update({
|
||||||
|
id: '/planes2/$planId',
|
||||||
|
path: '/planes2/$planId',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const PlanesListaRouteRoute = PlanesListaRouteRouteImport.update({
|
const PlanesListaRouteRoute = PlanesListaRouteRouteImport.update({
|
||||||
id: '/planes/_lista',
|
id: '/planes/_lista',
|
||||||
path: '/planes',
|
path: '/planes',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const Planes2PlanIdIndexRoute = Planes2PlanIdIndexRouteImport.update({
|
||||||
|
id: '/',
|
||||||
|
path: '/',
|
||||||
|
getParentRoute: () => Planes2PlanIdRouteRoute,
|
||||||
|
} as any)
|
||||||
const PlanesPlanIdIndexRoute = PlanesPlanIdIndexRouteImport.update({
|
const PlanesPlanIdIndexRoute = PlanesPlanIdIndexRouteImport.update({
|
||||||
id: '/planes/$planId/',
|
id: '/planes/$planId/',
|
||||||
path: '/planes/$planId/',
|
path: '/planes/$planId/',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const Planes2PlanIdMateriasRoute = Planes2PlanIdMateriasRouteImport.update({
|
||||||
|
id: '/materias',
|
||||||
|
path: '/materias',
|
||||||
|
getParentRoute: () => Planes2PlanIdRouteRoute,
|
||||||
|
} as any)
|
||||||
|
const Planes2PlanIdMapaRoute = Planes2PlanIdMapaRouteImport.update({
|
||||||
|
id: '/mapa',
|
||||||
|
path: '/mapa',
|
||||||
|
getParentRoute: () => Planes2PlanIdRouteRoute,
|
||||||
|
} as any)
|
||||||
|
const Planes2PlanIdIaplanRoute = Planes2PlanIdIaplanRouteImport.update({
|
||||||
|
id: '/iaplan',
|
||||||
|
path: '/iaplan',
|
||||||
|
getParentRoute: () => Planes2PlanIdRouteRoute,
|
||||||
|
} as any)
|
||||||
|
const Planes2PlanIdHistorialRoute = Planes2PlanIdHistorialRouteImport.update({
|
||||||
|
id: '/historial',
|
||||||
|
path: '/historial',
|
||||||
|
getParentRoute: () => Planes2PlanIdRouteRoute,
|
||||||
|
} as any)
|
||||||
|
const Planes2PlanIdFlujoRoute = Planes2PlanIdFlujoRouteImport.update({
|
||||||
|
id: '/flujo',
|
||||||
|
path: '/flujo',
|
||||||
|
getParentRoute: () => Planes2PlanIdRouteRoute,
|
||||||
|
} as any)
|
||||||
|
const Planes2PlanIdDocumentoRoute = Planes2PlanIdDocumentoRouteImport.update({
|
||||||
|
id: '/documento',
|
||||||
|
path: '/documento',
|
||||||
|
getParentRoute: () => Planes2PlanIdRouteRoute,
|
||||||
|
} as any)
|
||||||
const PlanesListaNuevoRoute = PlanesListaNuevoRouteImport.update({
|
const PlanesListaNuevoRoute = PlanesListaNuevoRouteImport.update({
|
||||||
id: '/nuevo',
|
id: '/nuevo',
|
||||||
path: '/nuevo',
|
path: '/nuevo',
|
||||||
getParentRoute: () => PlanesListaRouteRoute,
|
getParentRoute: () => PlanesListaRouteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
const MateriasMateriaIdMateriaIdRoute =
|
||||||
|
MateriasMateriaIdMateriaIdRouteImport.update({
|
||||||
|
id: '/materias/$materiaId/$materiaId',
|
||||||
|
path: '/materias/$materiaId/$materiaId',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const PlanesPlanIdAsignaturasListaRouteRoute =
|
const PlanesPlanIdAsignaturasListaRouteRoute =
|
||||||
PlanesPlanIdAsignaturasListaRouteRouteImport.update({
|
PlanesPlanIdAsignaturasListaRouteRouteImport.update({
|
||||||
id: '/planes/$planId/asignaturas/_lista',
|
id: '/planes/$planId/asignaturas/_lista',
|
||||||
@@ -79,9 +146,20 @@ export interface FileRoutesByFullPath {
|
|||||||
'/dashboard': typeof DashboardRoute
|
'/dashboard': typeof DashboardRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/planes': typeof PlanesListaRouteRouteWithChildren
|
'/planes': typeof PlanesListaRouteRouteWithChildren
|
||||||
|
'/planes2/$planId': typeof Planes2PlanIdRouteRouteWithChildren
|
||||||
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
||||||
|
'/materias': typeof MateriasIndexRoute
|
||||||
|
'/planes2': typeof Planes2IndexRoute
|
||||||
|
'/materias/$materiaId/$materiaId': typeof MateriasMateriaIdMateriaIdRoute
|
||||||
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
||||||
|
'/planes2/$planId/documento': typeof Planes2PlanIdDocumentoRoute
|
||||||
|
'/planes2/$planId/flujo': typeof Planes2PlanIdFlujoRoute
|
||||||
|
'/planes2/$planId/historial': typeof Planes2PlanIdHistorialRoute
|
||||||
|
'/planes2/$planId/iaplan': typeof Planes2PlanIdIaplanRoute
|
||||||
|
'/planes2/$planId/mapa': typeof Planes2PlanIdMapaRoute
|
||||||
|
'/planes2/$planId/materias': typeof Planes2PlanIdMateriasRoute
|
||||||
'/planes/$planId': typeof PlanesPlanIdIndexRoute
|
'/planes/$planId': typeof PlanesPlanIdIndexRoute
|
||||||
|
'/planes2/$planId/': typeof Planes2PlanIdIndexRoute
|
||||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
||||||
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||||
@@ -92,8 +170,18 @@ export interface FileRoutesByTo {
|
|||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/planes': typeof PlanesListaRouteRouteWithChildren
|
'/planes': typeof PlanesListaRouteRouteWithChildren
|
||||||
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
||||||
|
'/materias': typeof MateriasIndexRoute
|
||||||
|
'/planes2': typeof Planes2IndexRoute
|
||||||
|
'/materias/$materiaId/$materiaId': typeof MateriasMateriaIdMateriaIdRoute
|
||||||
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
||||||
|
'/planes2/$planId/documento': typeof Planes2PlanIdDocumentoRoute
|
||||||
|
'/planes2/$planId/flujo': typeof Planes2PlanIdFlujoRoute
|
||||||
|
'/planes2/$planId/historial': typeof Planes2PlanIdHistorialRoute
|
||||||
|
'/planes2/$planId/iaplan': typeof Planes2PlanIdIaplanRoute
|
||||||
|
'/planes2/$planId/mapa': typeof Planes2PlanIdMapaRoute
|
||||||
|
'/planes2/$planId/materias': typeof Planes2PlanIdMateriasRoute
|
||||||
'/planes/$planId': typeof PlanesPlanIdIndexRoute
|
'/planes/$planId': typeof PlanesPlanIdIndexRoute
|
||||||
|
'/planes2/$planId': typeof Planes2PlanIdIndexRoute
|
||||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
||||||
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||||
@@ -104,9 +192,20 @@ export interface FileRoutesById {
|
|||||||
'/dashboard': typeof DashboardRoute
|
'/dashboard': typeof DashboardRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/planes/_lista': typeof PlanesListaRouteRouteWithChildren
|
'/planes/_lista': typeof PlanesListaRouteRouteWithChildren
|
||||||
|
'/planes2/$planId': typeof Planes2PlanIdRouteRouteWithChildren
|
||||||
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
||||||
|
'/materias/': typeof MateriasIndexRoute
|
||||||
|
'/planes2/': typeof Planes2IndexRoute
|
||||||
|
'/materias/$materiaId/$materiaId': typeof MateriasMateriaIdMateriaIdRoute
|
||||||
'/planes/_lista/nuevo': typeof PlanesListaNuevoRoute
|
'/planes/_lista/nuevo': typeof PlanesListaNuevoRoute
|
||||||
|
'/planes2/$planId/documento': typeof Planes2PlanIdDocumentoRoute
|
||||||
|
'/planes2/$planId/flujo': typeof Planes2PlanIdFlujoRoute
|
||||||
|
'/planes2/$planId/historial': typeof Planes2PlanIdHistorialRoute
|
||||||
|
'/planes2/$planId/iaplan': typeof Planes2PlanIdIaplanRoute
|
||||||
|
'/planes2/$planId/mapa': typeof Planes2PlanIdMapaRoute
|
||||||
|
'/planes2/$planId/materias': typeof Planes2PlanIdMateriasRoute
|
||||||
'/planes/$planId/': typeof PlanesPlanIdIndexRoute
|
'/planes/$planId/': typeof PlanesPlanIdIndexRoute
|
||||||
|
'/planes2/$planId/': typeof Planes2PlanIdIndexRoute
|
||||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||||
'/planes/$planId/asignaturas/_lista': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
'/planes/$planId/asignaturas/_lista': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
||||||
'/planes/$planId/asignaturas/_lista/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
'/planes/$planId/asignaturas/_lista/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||||
@@ -118,9 +217,20 @@ export interface FileRouteTypes {
|
|||||||
| '/dashboard'
|
| '/dashboard'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/planes'
|
| '/planes'
|
||||||
|
| '/planes2/$planId'
|
||||||
| '/demo/tanstack-query'
|
| '/demo/tanstack-query'
|
||||||
|
| '/materias'
|
||||||
|
| '/planes2'
|
||||||
|
| '/materias/$materiaId/$materiaId'
|
||||||
| '/planes/nuevo'
|
| '/planes/nuevo'
|
||||||
|
| '/planes2/$planId/documento'
|
||||||
|
| '/planes2/$planId/flujo'
|
||||||
|
| '/planes2/$planId/historial'
|
||||||
|
| '/planes2/$planId/iaplan'
|
||||||
|
| '/planes2/$planId/mapa'
|
||||||
|
| '/planes2/$planId/materias'
|
||||||
| '/planes/$planId'
|
| '/planes/$planId'
|
||||||
|
| '/planes2/$planId/'
|
||||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||||
| '/planes/$planId/asignaturas'
|
| '/planes/$planId/asignaturas'
|
||||||
| '/planes/$planId/asignaturas/nueva'
|
| '/planes/$planId/asignaturas/nueva'
|
||||||
@@ -131,8 +241,18 @@ export interface FileRouteTypes {
|
|||||||
| '/login'
|
| '/login'
|
||||||
| '/planes'
|
| '/planes'
|
||||||
| '/demo/tanstack-query'
|
| '/demo/tanstack-query'
|
||||||
|
| '/materias'
|
||||||
|
| '/planes2'
|
||||||
|
| '/materias/$materiaId/$materiaId'
|
||||||
| '/planes/nuevo'
|
| '/planes/nuevo'
|
||||||
|
| '/planes2/$planId/documento'
|
||||||
|
| '/planes2/$planId/flujo'
|
||||||
|
| '/planes2/$planId/historial'
|
||||||
|
| '/planes2/$planId/iaplan'
|
||||||
|
| '/planes2/$planId/mapa'
|
||||||
|
| '/planes2/$planId/materias'
|
||||||
| '/planes/$planId'
|
| '/planes/$planId'
|
||||||
|
| '/planes2/$planId'
|
||||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||||
| '/planes/$planId/asignaturas'
|
| '/planes/$planId/asignaturas'
|
||||||
| '/planes/$planId/asignaturas/nueva'
|
| '/planes/$planId/asignaturas/nueva'
|
||||||
@@ -142,9 +262,20 @@ export interface FileRouteTypes {
|
|||||||
| '/dashboard'
|
| '/dashboard'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/planes/_lista'
|
| '/planes/_lista'
|
||||||
|
| '/planes2/$planId'
|
||||||
| '/demo/tanstack-query'
|
| '/demo/tanstack-query'
|
||||||
|
| '/materias/'
|
||||||
|
| '/planes2/'
|
||||||
|
| '/materias/$materiaId/$materiaId'
|
||||||
| '/planes/_lista/nuevo'
|
| '/planes/_lista/nuevo'
|
||||||
|
| '/planes2/$planId/documento'
|
||||||
|
| '/planes2/$planId/flujo'
|
||||||
|
| '/planes2/$planId/historial'
|
||||||
|
| '/planes2/$planId/iaplan'
|
||||||
|
| '/planes2/$planId/mapa'
|
||||||
|
| '/planes2/$planId/materias'
|
||||||
| '/planes/$planId/'
|
| '/planes/$planId/'
|
||||||
|
| '/planes2/$planId/'
|
||||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||||
| '/planes/$planId/asignaturas/_lista'
|
| '/planes/$planId/asignaturas/_lista'
|
||||||
| '/planes/$planId/asignaturas/_lista/nueva'
|
| '/planes/$planId/asignaturas/_lista/nueva'
|
||||||
@@ -155,7 +286,11 @@ export interface RootRouteChildren {
|
|||||||
DashboardRoute: typeof DashboardRoute
|
DashboardRoute: typeof DashboardRoute
|
||||||
LoginRoute: typeof LoginRoute
|
LoginRoute: typeof LoginRoute
|
||||||
PlanesListaRouteRoute: typeof PlanesListaRouteRouteWithChildren
|
PlanesListaRouteRoute: typeof PlanesListaRouteRouteWithChildren
|
||||||
|
Planes2PlanIdRouteRoute: typeof Planes2PlanIdRouteRouteWithChildren
|
||||||
DemoTanstackQueryRoute: typeof DemoTanstackQueryRoute
|
DemoTanstackQueryRoute: typeof DemoTanstackQueryRoute
|
||||||
|
MateriasIndexRoute: typeof MateriasIndexRoute
|
||||||
|
Planes2IndexRoute: typeof Planes2IndexRoute
|
||||||
|
MateriasMateriaIdMateriaIdRoute: typeof MateriasMateriaIdMateriaIdRoute
|
||||||
PlanesPlanIdIndexRoute: typeof PlanesPlanIdIndexRoute
|
PlanesPlanIdIndexRoute: typeof PlanesPlanIdIndexRoute
|
||||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute: typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute: typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||||
PlanesPlanIdAsignaturasListaRouteRoute: typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
PlanesPlanIdAsignaturasListaRouteRoute: typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
||||||
@@ -184,6 +319,20 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof IndexRouteImport
|
preLoaderRoute: typeof IndexRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/planes2/': {
|
||||||
|
id: '/planes2/'
|
||||||
|
path: '/planes2'
|
||||||
|
fullPath: '/planes2'
|
||||||
|
preLoaderRoute: typeof Planes2IndexRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
|
'/materias/': {
|
||||||
|
id: '/materias/'
|
||||||
|
path: '/materias'
|
||||||
|
fullPath: '/materias'
|
||||||
|
preLoaderRoute: typeof MateriasIndexRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/demo/tanstack-query': {
|
'/demo/tanstack-query': {
|
||||||
id: '/demo/tanstack-query'
|
id: '/demo/tanstack-query'
|
||||||
path: '/demo/tanstack-query'
|
path: '/demo/tanstack-query'
|
||||||
@@ -191,6 +340,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof DemoTanstackQueryRouteImport
|
preLoaderRoute: typeof DemoTanstackQueryRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/planes2/$planId': {
|
||||||
|
id: '/planes2/$planId'
|
||||||
|
path: '/planes2/$planId'
|
||||||
|
fullPath: '/planes2/$planId'
|
||||||
|
preLoaderRoute: typeof Planes2PlanIdRouteRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/planes/_lista': {
|
'/planes/_lista': {
|
||||||
id: '/planes/_lista'
|
id: '/planes/_lista'
|
||||||
path: '/planes'
|
path: '/planes'
|
||||||
@@ -198,6 +354,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof PlanesListaRouteRouteImport
|
preLoaderRoute: typeof PlanesListaRouteRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/planes2/$planId/': {
|
||||||
|
id: '/planes2/$planId/'
|
||||||
|
path: '/'
|
||||||
|
fullPath: '/planes2/$planId/'
|
||||||
|
preLoaderRoute: typeof Planes2PlanIdIndexRouteImport
|
||||||
|
parentRoute: typeof Planes2PlanIdRouteRoute
|
||||||
|
}
|
||||||
'/planes/$planId/': {
|
'/planes/$planId/': {
|
||||||
id: '/planes/$planId/'
|
id: '/planes/$planId/'
|
||||||
path: '/planes/$planId'
|
path: '/planes/$planId'
|
||||||
@@ -205,6 +368,48 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof PlanesPlanIdIndexRouteImport
|
preLoaderRoute: typeof PlanesPlanIdIndexRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/planes2/$planId/materias': {
|
||||||
|
id: '/planes2/$planId/materias'
|
||||||
|
path: '/materias'
|
||||||
|
fullPath: '/planes2/$planId/materias'
|
||||||
|
preLoaderRoute: typeof Planes2PlanIdMateriasRouteImport
|
||||||
|
parentRoute: typeof Planes2PlanIdRouteRoute
|
||||||
|
}
|
||||||
|
'/planes2/$planId/mapa': {
|
||||||
|
id: '/planes2/$planId/mapa'
|
||||||
|
path: '/mapa'
|
||||||
|
fullPath: '/planes2/$planId/mapa'
|
||||||
|
preLoaderRoute: typeof Planes2PlanIdMapaRouteImport
|
||||||
|
parentRoute: typeof Planes2PlanIdRouteRoute
|
||||||
|
}
|
||||||
|
'/planes2/$planId/iaplan': {
|
||||||
|
id: '/planes2/$planId/iaplan'
|
||||||
|
path: '/iaplan'
|
||||||
|
fullPath: '/planes2/$planId/iaplan'
|
||||||
|
preLoaderRoute: typeof Planes2PlanIdIaplanRouteImport
|
||||||
|
parentRoute: typeof Planes2PlanIdRouteRoute
|
||||||
|
}
|
||||||
|
'/planes2/$planId/historial': {
|
||||||
|
id: '/planes2/$planId/historial'
|
||||||
|
path: '/historial'
|
||||||
|
fullPath: '/planes2/$planId/historial'
|
||||||
|
preLoaderRoute: typeof Planes2PlanIdHistorialRouteImport
|
||||||
|
parentRoute: typeof Planes2PlanIdRouteRoute
|
||||||
|
}
|
||||||
|
'/planes2/$planId/flujo': {
|
||||||
|
id: '/planes2/$planId/flujo'
|
||||||
|
path: '/flujo'
|
||||||
|
fullPath: '/planes2/$planId/flujo'
|
||||||
|
preLoaderRoute: typeof Planes2PlanIdFlujoRouteImport
|
||||||
|
parentRoute: typeof Planes2PlanIdRouteRoute
|
||||||
|
}
|
||||||
|
'/planes2/$planId/documento': {
|
||||||
|
id: '/planes2/$planId/documento'
|
||||||
|
path: '/documento'
|
||||||
|
fullPath: '/planes2/$planId/documento'
|
||||||
|
preLoaderRoute: typeof Planes2PlanIdDocumentoRouteImport
|
||||||
|
parentRoute: typeof Planes2PlanIdRouteRoute
|
||||||
|
}
|
||||||
'/planes/_lista/nuevo': {
|
'/planes/_lista/nuevo': {
|
||||||
id: '/planes/_lista/nuevo'
|
id: '/planes/_lista/nuevo'
|
||||||
path: '/nuevo'
|
path: '/nuevo'
|
||||||
@@ -212,6 +417,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof PlanesListaNuevoRouteImport
|
preLoaderRoute: typeof PlanesListaNuevoRouteImport
|
||||||
parentRoute: typeof PlanesListaRouteRoute
|
parentRoute: typeof PlanesListaRouteRoute
|
||||||
}
|
}
|
||||||
|
'/materias/$materiaId/$materiaId': {
|
||||||
|
id: '/materias/$materiaId/$materiaId'
|
||||||
|
path: '/materias/$materiaId/$materiaId'
|
||||||
|
fullPath: '/materias/$materiaId/$materiaId'
|
||||||
|
preLoaderRoute: typeof MateriasMateriaIdMateriaIdRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/planes/$planId/asignaturas/_lista': {
|
'/planes/$planId/asignaturas/_lista': {
|
||||||
id: '/planes/$planId/asignaturas/_lista'
|
id: '/planes/$planId/asignaturas/_lista'
|
||||||
path: '/planes/$planId/asignaturas'
|
path: '/planes/$planId/asignaturas'
|
||||||
@@ -247,6 +459,29 @@ const PlanesListaRouteRouteChildren: PlanesListaRouteRouteChildren = {
|
|||||||
const PlanesListaRouteRouteWithChildren =
|
const PlanesListaRouteRouteWithChildren =
|
||||||
PlanesListaRouteRoute._addFileChildren(PlanesListaRouteRouteChildren)
|
PlanesListaRouteRoute._addFileChildren(PlanesListaRouteRouteChildren)
|
||||||
|
|
||||||
|
interface Planes2PlanIdRouteRouteChildren {
|
||||||
|
Planes2PlanIdDocumentoRoute: typeof Planes2PlanIdDocumentoRoute
|
||||||
|
Planes2PlanIdFlujoRoute: typeof Planes2PlanIdFlujoRoute
|
||||||
|
Planes2PlanIdHistorialRoute: typeof Planes2PlanIdHistorialRoute
|
||||||
|
Planes2PlanIdIaplanRoute: typeof Planes2PlanIdIaplanRoute
|
||||||
|
Planes2PlanIdMapaRoute: typeof Planes2PlanIdMapaRoute
|
||||||
|
Planes2PlanIdMateriasRoute: typeof Planes2PlanIdMateriasRoute
|
||||||
|
Planes2PlanIdIndexRoute: typeof Planes2PlanIdIndexRoute
|
||||||
|
}
|
||||||
|
|
||||||
|
const Planes2PlanIdRouteRouteChildren: Planes2PlanIdRouteRouteChildren = {
|
||||||
|
Planes2PlanIdDocumentoRoute: Planes2PlanIdDocumentoRoute,
|
||||||
|
Planes2PlanIdFlujoRoute: Planes2PlanIdFlujoRoute,
|
||||||
|
Planes2PlanIdHistorialRoute: Planes2PlanIdHistorialRoute,
|
||||||
|
Planes2PlanIdIaplanRoute: Planes2PlanIdIaplanRoute,
|
||||||
|
Planes2PlanIdMapaRoute: Planes2PlanIdMapaRoute,
|
||||||
|
Planes2PlanIdMateriasRoute: Planes2PlanIdMateriasRoute,
|
||||||
|
Planes2PlanIdIndexRoute: Planes2PlanIdIndexRoute,
|
||||||
|
}
|
||||||
|
|
||||||
|
const Planes2PlanIdRouteRouteWithChildren =
|
||||||
|
Planes2PlanIdRouteRoute._addFileChildren(Planes2PlanIdRouteRouteChildren)
|
||||||
|
|
||||||
interface PlanesPlanIdAsignaturasListaRouteRouteChildren {
|
interface PlanesPlanIdAsignaturasListaRouteRouteChildren {
|
||||||
PlanesPlanIdAsignaturasListaNuevaRoute: typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
PlanesPlanIdAsignaturasListaNuevaRoute: typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||||
}
|
}
|
||||||
@@ -267,7 +502,11 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
DashboardRoute: DashboardRoute,
|
DashboardRoute: DashboardRoute,
|
||||||
LoginRoute: LoginRoute,
|
LoginRoute: LoginRoute,
|
||||||
PlanesListaRouteRoute: PlanesListaRouteRouteWithChildren,
|
PlanesListaRouteRoute: PlanesListaRouteRouteWithChildren,
|
||||||
|
Planes2PlanIdRouteRoute: Planes2PlanIdRouteRouteWithChildren,
|
||||||
DemoTanstackQueryRoute: DemoTanstackQueryRoute,
|
DemoTanstackQueryRoute: DemoTanstackQueryRoute,
|
||||||
|
MateriasIndexRoute: MateriasIndexRoute,
|
||||||
|
Planes2IndexRoute: Planes2IndexRoute,
|
||||||
|
MateriasMateriaIdMateriaIdRoute: MateriasMateriaIdMateriaIdRoute,
|
||||||
PlanesPlanIdIndexRoute: PlanesPlanIdIndexRoute,
|
PlanesPlanIdIndexRoute: PlanesPlanIdIndexRoute,
|
||||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute:
|
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute:
|
||||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute,
|
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute,
|
||||||
|
|||||||
227
src/routes/materias/$materiaId/$materiaId.tsx
Normal file
227
src/routes/materias/$materiaId/$materiaId.tsx
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
import { createFileRoute, Link } from '@tanstack/react-router'
|
||||||
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||||
|
import { Badge } from '@/components/ui/badge'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Separator } from '@/components/ui/separator'
|
||||||
|
import {
|
||||||
|
ArrowLeft,
|
||||||
|
GraduationCap,
|
||||||
|
BookOpen,
|
||||||
|
Sparkles,
|
||||||
|
FileText,
|
||||||
|
History,
|
||||||
|
} from 'lucide-react'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/materias/$materiaId/$materiaId')({
|
||||||
|
component: MateriaDetailPage,
|
||||||
|
})
|
||||||
|
|
||||||
|
function MateriaDetailPage() {
|
||||||
|
const { materiaId } = Route.useParams()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full">
|
||||||
|
{/* ================= HEADER ================= */}
|
||||||
|
<section className="bg-gradient-to-b from-[#0b1d3a] to-[#0e2a5c] text-white">
|
||||||
|
<div className="max-w-7xl mx-auto px-6 py-10">
|
||||||
|
<Link
|
||||||
|
to="/materias"
|
||||||
|
className="flex items-center gap-2 text-sm text-blue-200 hover:text-white mb-4"
|
||||||
|
>
|
||||||
|
<ArrowLeft className="w-4 h-4" />
|
||||||
|
Volver al plan
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<div className="flex items-start justify-between gap-6">
|
||||||
|
<div className="space-y-3">
|
||||||
|
<Badge className="bg-blue-900/50 border border-blue-700">
|
||||||
|
IA-401
|
||||||
|
</Badge>
|
||||||
|
|
||||||
|
<h1 className="text-3xl font-bold">
|
||||||
|
Inteligencia Artificial Aplicada
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap gap-4 text-sm text-blue-200">
|
||||||
|
<span className="flex items-center gap-1">
|
||||||
|
<GraduationCap className="w-4 h-4" />
|
||||||
|
Ingeniería en Sistemas Computacionales
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>Facultad de Ingeniería</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-sm text-blue-300">
|
||||||
|
Pertenece al plan:{' '}
|
||||||
|
<span className="underline cursor-pointer">
|
||||||
|
Licenciatura en Ingeniería en Sistemas Computacionales 2024
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2 items-end">
|
||||||
|
<Badge variant="secondary">8 créditos</Badge>
|
||||||
|
<Badge variant="secondary">7° semestre</Badge>
|
||||||
|
<Badge variant="secondary">Sistemas Inteligentes</Badge>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ================= TABS ================= */}
|
||||||
|
<section className="bg-white border-b">
|
||||||
|
<div className="max-w-7xl mx-auto px-6">
|
||||||
|
<Tabs defaultValue="datos">
|
||||||
|
<TabsList className="h-auto bg-transparent p-0 gap-6">
|
||||||
|
<TabsTrigger value="datos">Datos generales</TabsTrigger>
|
||||||
|
<TabsTrigger value="contenido">Contenido temático</TabsTrigger>
|
||||||
|
<TabsTrigger value="bibliografia">Bibliografía</TabsTrigger>
|
||||||
|
<TabsTrigger value="ia">IA de la materia</TabsTrigger>
|
||||||
|
<TabsTrigger value="sep">Documento SEP</TabsTrigger>
|
||||||
|
<TabsTrigger value="historial">Historial</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<Separator className="mt-2" />
|
||||||
|
|
||||||
|
{/* ================= TAB: DATOS GENERALES ================= */}
|
||||||
|
<TabsContent value="datos">
|
||||||
|
<DatosGenerales />
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="contenido">
|
||||||
|
<EmptyTab title="Contenido temático" />
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="bibliografia">
|
||||||
|
<EmptyTab title="Bibliografía" />
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="ia">
|
||||||
|
<EmptyTab title="IA de la materia" />
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="sep">
|
||||||
|
<EmptyTab title="Documento SEP" />
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="historial">
|
||||||
|
<EmptyTab title="Historial" />
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================= TAB CONTENT ================= */
|
||||||
|
|
||||||
|
function DatosGenerales() {
|
||||||
|
return (
|
||||||
|
<div className="max-w-5xl mx-auto py-10 space-y-6">
|
||||||
|
<HeaderTab />
|
||||||
|
|
||||||
|
<InfoCard
|
||||||
|
title="Objetivo General"
|
||||||
|
content="Formar profesionales capaces de diseñar, implementar y evaluar sistemas de inteligencia artificial que resuelvan problemas complejos del mundo real."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InfoCard
|
||||||
|
title="Competencias a Desarrollar"
|
||||||
|
content={
|
||||||
|
<ul className="list-disc list-inside space-y-1">
|
||||||
|
<li>Diseñar algoritmos de machine learning</li>
|
||||||
|
<li>Implementar redes neuronales profundas</li>
|
||||||
|
<li>Evaluar modelos de IA considerando métricas</li>
|
||||||
|
<li>Aplicar principios éticos en sistemas inteligentes</li>
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InfoCard
|
||||||
|
title="Justificación"
|
||||||
|
content="La inteligencia artificial es una de las tecnologías más disruptivas del siglo XXI..."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InfoCard
|
||||||
|
title="Requisitos y Seriación"
|
||||||
|
content="Programación Avanzada (PA-301), Matemáticas Discretas (MAT-201)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InfoCard
|
||||||
|
title="Estrategias Didácticas"
|
||||||
|
content={
|
||||||
|
<ul className="list-disc list-inside space-y-1">
|
||||||
|
<li>Aprendizaje basado en proyectos</li>
|
||||||
|
<li>Talleres prácticos con datasets reales</li>
|
||||||
|
<li>Estudios de caso</li>
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InfoCard
|
||||||
|
title="Sistema de Evaluación"
|
||||||
|
content={
|
||||||
|
<ul className="list-disc list-inside space-y-1">
|
||||||
|
<li>Exámenes parciales: 30%</li>
|
||||||
|
<li>Proyecto integrador: 35%</li>
|
||||||
|
<li>Prácticas de laboratorio: 20%</li>
|
||||||
|
<li>Participación: 15%</li>
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InfoCard
|
||||||
|
title="Perfil del Docente"
|
||||||
|
content="Profesional con maestría o doctorado en áreas afines a IA, con experiencia mínima de 3 años."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function HeaderTab() {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<h2 className="text-xl font-semibold">Datos Generales</h2>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Información basada en la plantilla SEP Licenciatura
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button size="sm">Guardar todo</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function InfoCard({
|
||||||
|
title,
|
||||||
|
content,
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
content: React.ReactNode
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CardTitle className="text-base flex items-center gap-2">
|
||||||
|
{title}
|
||||||
|
<Badge variant="outline">Obligatorio</Badge>
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<CardContent className="text-sm text-muted-foreground">
|
||||||
|
{content}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function EmptyTab({ title }: { title: string }) {
|
||||||
|
return (
|
||||||
|
<div className="py-16 text-center text-muted-foreground">
|
||||||
|
{title} (pendiente)
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
144
src/routes/materias/index.tsx
Normal file
144
src/routes/materias/index.tsx
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Card, CardContent } from '@/components/ui/card'
|
||||||
|
import {
|
||||||
|
BookOpen,
|
||||||
|
Sparkles,
|
||||||
|
FileText,
|
||||||
|
Library,
|
||||||
|
LayoutTemplate,
|
||||||
|
History,
|
||||||
|
ArrowRight,
|
||||||
|
GraduationCap,
|
||||||
|
} from 'lucide-react'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/materias/')({
|
||||||
|
component: MateriasLandingPage,
|
||||||
|
})
|
||||||
|
|
||||||
|
function MateriasLandingPage() {
|
||||||
|
return (
|
||||||
|
<div className="w-full">
|
||||||
|
{/* ================= HERO ================= */}
|
||||||
|
<section className="bg-gradient-to-b from-[#0b1d3a] to-[#0e2a5c] text-white">
|
||||||
|
<div className="max-w-7xl mx-auto px-6 py-28">
|
||||||
|
<div className="flex items-center gap-2 mb-6 text-sm text-blue-200">
|
||||||
|
<GraduationCap className="w-5 h-5 text-yellow-400" />
|
||||||
|
<span>SISTEMA DE GESTIÓN CURRICULAR</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className="text-5xl font-bold mb-6">
|
||||||
|
Universidad La Salle
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p className="max-w-xl text-lg text-blue-100 mb-10">
|
||||||
|
Diseña, documenta y mejora programas de estudio con herramientas
|
||||||
|
de inteligencia artificial integradas y cumplimiento normativo SEP.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
className="bg-yellow-400 text-black hover:bg-yellow-300 font-semibold"
|
||||||
|
>
|
||||||
|
Ver materia de ejemplo
|
||||||
|
<ArrowRight className="ml-2 h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ================= FEATURES ================= */}
|
||||||
|
<section className="bg-white py-24">
|
||||||
|
<div className="max-w-7xl mx-auto px-6">
|
||||||
|
<h2 className="text-center text-2xl font-semibold mb-14">
|
||||||
|
Características principales
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="grid gap-8 md:grid-cols-3">
|
||||||
|
<FeatureCard
|
||||||
|
icon={<BookOpen />}
|
||||||
|
title="Gestión de Materias"
|
||||||
|
description="Edita datos generales, contenido temático y bibliografía con una interfaz intuitiva."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FeatureCard
|
||||||
|
icon={<Sparkles />}
|
||||||
|
title="IA Integrada"
|
||||||
|
description="Usa inteligencia artificial para mejorar objetivos, competencias y alinear con perfiles de egreso."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FeatureCard
|
||||||
|
icon={<FileText />}
|
||||||
|
title="Documentos SEP"
|
||||||
|
description="Genera automáticamente documentos oficiales para la Secretaría de Educación Pública."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FeatureCard
|
||||||
|
icon={<Library />}
|
||||||
|
title="Biblioteca Digital"
|
||||||
|
description="Busca y vincula recursos del repositorio de Biblioteca La Salle directamente."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FeatureCard
|
||||||
|
icon={<LayoutTemplate />}
|
||||||
|
title="Plantillas Flexibles"
|
||||||
|
description="Adapta la estructura de materias según plantillas SEP o institucionales."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FeatureCard
|
||||||
|
icon={<History />}
|
||||||
|
title="Historial Completo"
|
||||||
|
description="Rastrea todos los cambios con historial detallado por usuario y fecha."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ================= CTA ================= */}
|
||||||
|
<section className="bg-gray-50 py-20">
|
||||||
|
<div className="max-w-3xl mx-auto text-center px-6">
|
||||||
|
<h3 className="text-xl font-semibold mb-4">
|
||||||
|
Explora la vista de detalle de materia
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p className="text-muted-foreground mb-8">
|
||||||
|
Navega por las diferentes pestañas para ver cómo funciona el sistema
|
||||||
|
de gestión curricular.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Button size="lg" className="bg-[#0e2a5c] hover:bg-[#0b1d3a]">
|
||||||
|
Ir a Inteligencia Artificial Aplicada
|
||||||
|
<ArrowRight className="ml-2 h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================= FEATURE CARD ================= */
|
||||||
|
|
||||||
|
function FeatureCard({
|
||||||
|
icon,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
}: {
|
||||||
|
icon: React.ReactNode
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Card className="border border-gray-200 shadow-sm">
|
||||||
|
<CardContent className="p-6 space-y-4">
|
||||||
|
<div className="w-10 h-10 rounded-md bg-yellow-100 text-yellow-600 flex items-center justify-center">
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 className="font-semibold">{title}</h4>
|
||||||
|
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
137
src/routes/planes2/$planId/MateriaCard.tsx
Normal file
137
src/routes/planes2/$planId/MateriaCard.tsx
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
import * as Dialog from '@radix-ui/react-dialog';
|
||||||
|
import { Pencil, X, Info } from 'lucide-react';
|
||||||
|
export type Materia = {
|
||||||
|
id: string;
|
||||||
|
clave: string;
|
||||||
|
nombre: string;
|
||||||
|
creditos: number;
|
||||||
|
hd: number; // Horas Docente
|
||||||
|
hi: number; // Horas Independientes
|
||||||
|
tipo: 'Obligatoria' | 'Optativa' | 'Especialidad';
|
||||||
|
ciclo: number;
|
||||||
|
linea: string;
|
||||||
|
estado: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MateriaCardProps {
|
||||||
|
materia: Materia;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MateriaCard({ materia }: MateriaCardProps) {
|
||||||
|
return (
|
||||||
|
<Dialog.Root>
|
||||||
|
{/* Trigger: La tarjeta en sí misma */}
|
||||||
|
<Dialog.Trigger asChild>
|
||||||
|
<div className="group relative flex flex-col p-2 mb-2 rounded-lg border border-slate-200 bg-white hover:border-emerald-500 hover:shadow-md transition-all cursor-pointer select-none">
|
||||||
|
{/* Header de la tarjeta */}
|
||||||
|
<div className="flex justify-between items-start mb-1">
|
||||||
|
<span className="text-[9px] font-mono font-bold text-slate-400 uppercase">{materia.clave}</span>
|
||||||
|
<div className="flex gap-1">
|
||||||
|
<span className="px-1.5 py-0.5 rounded-full bg-emerald-100 text-emerald-700 text-[8px] font-bold uppercase">
|
||||||
|
{materia.tipo === 'Obligatoria' ? 'OB' : 'OP'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Nombre */}
|
||||||
|
<h4 className="text-[11px] font-semibold text-slate-800 leading-tight mb-2 min-h-[2rem]">
|
||||||
|
{materia.nombre}
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
{/* Footer de la tarjeta (Créditos y Horas) */}
|
||||||
|
<div className="flex justify-between items-center text-[9px] text-slate-500 border-t pt-1 border-slate-50">
|
||||||
|
<span>{materia.creditos} cr</span>
|
||||||
|
<div className="flex gap-1">
|
||||||
|
<span>HD:{materia.hd}</span>
|
||||||
|
<span>HI:{materia.hi}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Overlay de Hover (Opcional: un iconito de editar) */}
|
||||||
|
<div className="absolute top-1 right-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
|
<Pencil className="w-3 h-3 text-emerald-600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog.Trigger>
|
||||||
|
|
||||||
|
{/* Modal / Portal */}
|
||||||
|
<Dialog.Portal>
|
||||||
|
<Dialog.Overlay className="fixed inset-0 bg-black/40 backdrop-blur-sm z-50 animate-in fade-in" />
|
||||||
|
<Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-md bg-white rounded-xl shadow-2xl p-6 z-50 border border-slate-200 animate-in zoom-in-95">
|
||||||
|
|
||||||
|
<div className="flex justify-between items-center mb-6">
|
||||||
|
<Dialog.Title className="text-lg font-bold text-slate-800">Editar Materia</Dialog.Title>
|
||||||
|
<Dialog.Close className="text-slate-400 hover:text-slate-600 transition-colors">
|
||||||
|
<X className="w-5 h-5" />
|
||||||
|
</Dialog.Close>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form className="space-y-4">
|
||||||
|
{/* Clave y Nombre */}
|
||||||
|
<div className="grid grid-cols-3 gap-4">
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs font-bold text-slate-600 uppercase">Clave</label>
|
||||||
|
<input
|
||||||
|
defaultValue={materia.clave}
|
||||||
|
className="px-3 py-2 rounded-lg border border-slate-300 focus:ring-2 focus:ring-emerald-500 outline-none text-sm font-mono"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2 flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs font-bold text-slate-600 uppercase">Nombre</label>
|
||||||
|
<input
|
||||||
|
defaultValue={materia.nombre}
|
||||||
|
className="px-3 py-2 rounded-lg border border-slate-300 focus:ring-2 focus:ring-emerald-500 outline-none text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Créditos y Horas */}
|
||||||
|
<div className="grid grid-cols-3 gap-4">
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs font-bold text-slate-600 uppercase italic">Créditos</label>
|
||||||
|
<input type="number" defaultValue={materia.creditos} className="px-3 py-2 rounded-lg border border-slate-300 text-sm" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs font-bold text-slate-600 uppercase italic">HD (Hrs Docente)</label>
|
||||||
|
<input type="number" defaultValue={materia.hd} className="px-3 py-2 rounded-lg border border-slate-300 text-sm" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs font-bold text-slate-600 uppercase italic">HI (Hrs Indep.)</label>
|
||||||
|
<input type="number" defaultValue={materia.hi} className="px-3 py-2 rounded-lg border border-slate-300 text-sm" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Ciclo y Línea */}
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs font-bold text-slate-600 uppercase">Ciclo</label>
|
||||||
|
<select className="px-3 py-2 rounded-lg border border-slate-300 text-sm bg-white">
|
||||||
|
<option>Ciclo {materia.ciclo}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs font-bold text-slate-600 uppercase">Línea Curricular</label>
|
||||||
|
<select className="px-3 py-2 rounded-lg border border-slate-300 text-sm bg-white">
|
||||||
|
<option>{materia.linea}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Botones de acción */}
|
||||||
|
<div className="flex justify-end gap-3 pt-6">
|
||||||
|
<Dialog.Close className="px-4 py-2 rounded-lg text-sm font-semibold text-slate-600 hover:bg-slate-100 transition-colors">
|
||||||
|
Cancelar
|
||||||
|
</Dialog.Close>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="px-6 py-2 rounded-lg text-sm font-semibold bg-emerald-700 text-white hover:bg-emerald-800 transition-colors shadow-sm"
|
||||||
|
>
|
||||||
|
Guardar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog.Portal>
|
||||||
|
</Dialog.Root>
|
||||||
|
);
|
||||||
|
}
|
||||||
131
src/routes/planes2/$planId/documento.tsx
Normal file
131
src/routes/planes2/$planId/documento.tsx
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import {
|
||||||
|
FileText,
|
||||||
|
Download,
|
||||||
|
RefreshCcw,
|
||||||
|
ExternalLink,
|
||||||
|
CheckCircle2,
|
||||||
|
Clock,
|
||||||
|
FileJson
|
||||||
|
} from "lucide-react"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Card, CardContent } from "@/components/ui/card"
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/planes2/$planId/documento')({
|
||||||
|
component: RouteComponent,
|
||||||
|
})
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-6 p-6 bg-slate-50/30 min-h-screen">
|
||||||
|
|
||||||
|
{/* HEADER DE ACCIONES */}
|
||||||
|
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-xl font-bold text-slate-800">Documento del Plan</h1>
|
||||||
|
<p className="text-sm text-muted-foreground">Vista previa y descarga del documento oficial</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button variant="outline" size="sm" className="gap-2">
|
||||||
|
<RefreshCcw size={16} /> Regenerar
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" size="sm" className="gap-2">
|
||||||
|
<Download size={16} /> Descargar Word
|
||||||
|
</Button>
|
||||||
|
<Button size="sm" className="gap-2 bg-teal-700 hover:bg-teal-800">
|
||||||
|
<Download size={16} /> Descargar PDF
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* TARJETAS DE ESTADO */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
|
<StatusCard
|
||||||
|
icon={<CheckCircle2 className="text-green-500" />}
|
||||||
|
label="Estado"
|
||||||
|
value="Generado"
|
||||||
|
/>
|
||||||
|
<StatusCard
|
||||||
|
icon={<Clock className="text-blue-500" />}
|
||||||
|
label="Última generación"
|
||||||
|
value="28 Ene 2024, 11:30"
|
||||||
|
/>
|
||||||
|
<StatusCard
|
||||||
|
icon={<FileJson className="text-orange-500" />}
|
||||||
|
label="Versión"
|
||||||
|
value="v1.2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CONTENEDOR DEL DOCUMENTO (Visor) */}
|
||||||
|
<Card className="border-slate-200 shadow-sm overflow-hidden">
|
||||||
|
<div className="bg-slate-100/50 p-2 border-b flex justify-between items-center px-4">
|
||||||
|
<div className="flex items-center gap-2 text-xs text-slate-500 font-medium">
|
||||||
|
<FileText size={14} />
|
||||||
|
Plan_Estudios_ISC_2024.pdf
|
||||||
|
</div>
|
||||||
|
<Button variant="ghost" size="sm" className="text-xs gap-1 h-7">
|
||||||
|
Abrir en nueva pestaña <ExternalLink size={12} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CardContent className="p-0 bg-slate-200/50 flex justify-center py-8 min-h-[800px]">
|
||||||
|
{/* SIMULACIÓN DE HOJA DE PAPEL */}
|
||||||
|
<div className="bg-white w-full max-w-[800px] shadow-2xl p-12 md:p-16 min-h-[1000px] border relative">
|
||||||
|
|
||||||
|
{/* Contenido del Plan */}
|
||||||
|
<div className="text-center mb-12">
|
||||||
|
<p className="text-xs uppercase tracking-widest text-slate-400 font-bold mb-1">Universidad Tecnológica</p>
|
||||||
|
<h2 className="text-2xl font-bold text-slate-800">Plan de Estudios 2024</h2>
|
||||||
|
<h3 className="text-lg text-teal-700 font-semibold">Ingeniería en Sistemas Computacionales</h3>
|
||||||
|
<p className="text-xs text-slate-500 mt-1">Facultad de Ingeniería</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-8 text-slate-700">
|
||||||
|
<section>
|
||||||
|
<h4 className="font-bold text-sm mb-2">1. Objetivo General</h4>
|
||||||
|
<p className="text-sm leading-relaxed text-justify">
|
||||||
|
Formar profesionales altamente capacitados en el desarrollo de soluciones tecnológicas innovadoras, con sólidos conocimientos en programación, bases de datos, redes y seguridad informática.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h4 className="font-bold text-sm mb-2">2. Perfil de Ingreso</h4>
|
||||||
|
<p className="text-sm leading-relaxed text-justify">
|
||||||
|
Egresados de educación media superior con conocimientos básicos de matemáticas, razonamiento lógico y habilidades de comunicación. Interés por la tecnología y la resolución de problemas.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h4 className="font-bold text-sm mb-2">3. Perfil de Egreso</h4>
|
||||||
|
<p className="text-sm leading-relaxed text-justify">
|
||||||
|
Profesional capaz de diseñar, desarrollar e implementar sistemas de software de calidad, administrar infraestructuras de red y liderar proyectos tecnológicos multidisciplinarios.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Marca de agua o decoración lateral (opcional) */}
|
||||||
|
<div className="absolute top-0 left-0 w-1 h-full bg-slate-100" />
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Componente pequeño para las tarjetas de estado superior
|
||||||
|
function StatusCard({ icon, label, value }: { icon: React.ReactNode, label: string, value: string }) {
|
||||||
|
return (
|
||||||
|
<Card className="bg-white border-slate-200">
|
||||||
|
<CardContent className="p-4 flex items-center gap-4">
|
||||||
|
<div className="p-2 rounded-full bg-slate-50 border">
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-[10px] uppercase font-bold text-slate-400 tracking-tight">{label}</p>
|
||||||
|
<p className="text-sm font-semibold text-slate-700">{value}</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
134
src/routes/planes2/$planId/flujo.tsx
Normal file
134
src/routes/planes2/$planId/flujo.tsx
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import { CheckCircle2, Circle, Clock } from "lucide-react"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
|
import { Textarea } from "@/components/ui/textarea"
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/planes2/$planId/flujo')({
|
||||||
|
component: RouteComponent,
|
||||||
|
})
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-6 p-6">
|
||||||
|
{/* Header Informativo (Opcional, si no viene del layout padre) */}
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold italic">Flujo de Aprobación</h1>
|
||||||
|
<p className="text-sm text-muted-foreground">Gestiona el proceso de revisión y aprobación del plan</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||||
|
|
||||||
|
{/* LADO IZQUIERDO: Timeline del Flujo */}
|
||||||
|
<div className="lg:col-span-2 space-y-4">
|
||||||
|
|
||||||
|
{/* Estado: Completado */}
|
||||||
|
<div className="relative flex gap-4 pb-4">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="rounded-full bg-green-100 p-1 text-green-600">
|
||||||
|
<CheckCircle2 className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
<div className="w-px flex-1 bg-green-200 mt-2" />
|
||||||
|
</div>
|
||||||
|
<Card className="flex-1">
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between py-3">
|
||||||
|
<div>
|
||||||
|
<CardTitle className="text-lg">Borrador</CardTitle>
|
||||||
|
<p className="text-xs text-muted-foreground">14 de enero de 2024</p>
|
||||||
|
</div>
|
||||||
|
<Badge variant="secondary" className="bg-green-100 text-green-700">Completado</Badge>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="text-sm border-t pt-3">
|
||||||
|
<p className="font-semibold text-muted-foreground mb-2">Comentarios</p>
|
||||||
|
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
|
||||||
|
<li>Documento inicial creado</li>
|
||||||
|
<li>Estructura base definida</li>
|
||||||
|
</ul>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Estado: En Curso (Actual) */}
|
||||||
|
<div className="relative flex gap-4 pb-4">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="rounded-full bg-blue-100 p-1 text-blue-600 ring-2 ring-blue-500 ring-offset-2">
|
||||||
|
<Clock className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
<div className="w-px flex-1 bg-slate-200 mt-2" />
|
||||||
|
</div>
|
||||||
|
<Card className="flex-1 border-blue-500 bg-blue-50/10">
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between py-3">
|
||||||
|
<div>
|
||||||
|
<CardTitle className="text-lg text-blue-700">En Revisión</CardTitle>
|
||||||
|
<p className="text-xs text-muted-foreground">19 de febrero de 2024</p>
|
||||||
|
</div>
|
||||||
|
<Badge variant="default" className="bg-blue-500">En curso</Badge>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="text-sm border-t border-blue-100 pt-3">
|
||||||
|
<p className="font-semibold text-muted-foreground mb-2">Comentarios</p>
|
||||||
|
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
|
||||||
|
<li>Revisión de objetivo general pendiente</li>
|
||||||
|
<li>Mapa curricular aprobado preliminarmente</li>
|
||||||
|
</ul>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Estado: Pendiente */}
|
||||||
|
<div className="relative flex gap-4 pb-4">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="rounded-full bg-slate-100 p-1 text-slate-400">
|
||||||
|
<Circle className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Card className="flex-1 opacity-60 grayscale-[0.5]">
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between py-3">
|
||||||
|
<CardTitle className="text-lg">Revisión Expertos</CardTitle>
|
||||||
|
<Badge variant="outline">Pendiente</Badge>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* LADO DERECHO: Formulario de Transición */}
|
||||||
|
<div className="lg:col-span-1">
|
||||||
|
<Card className="sticky top-6">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-lg">Transición de Estado</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-6">
|
||||||
|
<div className="flex items-center justify-between p-3 bg-slate-50 rounded-lg text-sm border">
|
||||||
|
<div className="text-center">
|
||||||
|
<p className="text-xs text-muted-foreground">Estado actual</p>
|
||||||
|
<p className="font-bold">En Revisión</p>
|
||||||
|
</div>
|
||||||
|
<div className="h-px flex-1 bg-slate-300 mx-4" />
|
||||||
|
<div className="text-center">
|
||||||
|
<p className="text-xs text-muted-foreground">Siguiente</p>
|
||||||
|
<p className="font-bold text-primary">Revisión Expertos</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<label className="text-sm font-medium">Comentario de transición</label>
|
||||||
|
<Textarea
|
||||||
|
placeholder="Agrega un comentario para la transición..."
|
||||||
|
className="min-h-[120px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button className="w-full bg-teal-600 hover:bg-teal-700">
|
||||||
|
Avanzar a Revisión Expertos
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
142
src/routes/planes2/$planId/historial.tsx
Normal file
142
src/routes/planes2/$planId/historial.tsx
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import {
|
||||||
|
GitBranch,
|
||||||
|
Edit3,
|
||||||
|
PlusCircle,
|
||||||
|
FileText,
|
||||||
|
RefreshCw,
|
||||||
|
User
|
||||||
|
} from "lucide-react"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Card, CardContent } from "@/components/ui/card"
|
||||||
|
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/planes2/$planId/historial')({
|
||||||
|
component: RouteComponent,
|
||||||
|
})
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
const historyEvents = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
type: 'Cambio de estado',
|
||||||
|
user: 'Dr. Juan Pérez',
|
||||||
|
description: 'Plan pasado de Borrador a En Revisión',
|
||||||
|
date: 'Hace 2 días',
|
||||||
|
icon: <GitBranch className="h-4 w-4" />,
|
||||||
|
details: { from: 'Borrador', to: 'En Revisión' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
type: 'Edición',
|
||||||
|
user: 'Lic. María García',
|
||||||
|
description: 'Actualizado perfil de egreso',
|
||||||
|
date: 'Hace 3 días',
|
||||||
|
icon: <Edit3 className="h-4 w-4" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
type: 'Reorganización',
|
||||||
|
user: 'Ing. Carlos López',
|
||||||
|
description: 'Movida materia BD102 de ciclo 3 a ciclo 4',
|
||||||
|
date: 'Hace 5 días',
|
||||||
|
icon: <RefreshCw className="h-4 w-4" />,
|
||||||
|
details: { from: 'Ciclo 3', to: 'Ciclo 4' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
type: 'Creación',
|
||||||
|
user: 'Dr. Juan Pérez',
|
||||||
|
description: 'Añadida nueva materia: Inteligencia Artificial',
|
||||||
|
date: 'Hace 1 semana',
|
||||||
|
icon: <PlusCircle className="h-4 w-4" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
type: 'Documento',
|
||||||
|
user: 'Lic. María García',
|
||||||
|
description: 'Generado documento oficial v1.0',
|
||||||
|
date: 'Hace 1 semana',
|
||||||
|
icon: <FileText className="h-4 w-4" />,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-6 max-w-5xl mx-auto">
|
||||||
|
<div className="mb-8">
|
||||||
|
<h1 className="text-xl font-bold text-slate-800">Historial de Cambios</h1>
|
||||||
|
<p className="text-sm text-muted-foreground">Registro de todas las modificaciones realizadas al plan</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative space-y-0">
|
||||||
|
{/* Línea vertical de fondo */}
|
||||||
|
<div className="absolute left-9 top-0 bottom-0 w-px bg-slate-200" />
|
||||||
|
|
||||||
|
{historyEvents.map((event) => (
|
||||||
|
<div key={event.id} className="relative flex gap-6 pb-8 group">
|
||||||
|
|
||||||
|
{/* Indicador con Icono */}
|
||||||
|
<div className="relative z-10 flex h-18 flex-col items-center">
|
||||||
|
<div className="flex h-[42px] w-[42px] items-center justify-center rounded-full border-4 border-white bg-slate-100 text-slate-600 shadow-sm group-hover:bg-teal-50 group-hover:text-teal-600 transition-colors">
|
||||||
|
{event.icon}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Tarjeta de Contenido */}
|
||||||
|
<Card className="flex-1 shadow-none border-slate-200 hover:border-teal-200 transition-colors">
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-2 mb-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-bold text-slate-800 text-sm">{event.type}</span>
|
||||||
|
<Badge variant="outline" className="text-[10px] font-normal py-0">
|
||||||
|
{event.date}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
||||||
|
<Avatar className="h-5 w-5 border">
|
||||||
|
<AvatarFallback className="text-[8px] bg-slate-50"><User size={10}/></AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
{event.user}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-sm text-slate-600 mb-3">{event.description}</p>
|
||||||
|
|
||||||
|
{/* Badges de transición (si existen) */}
|
||||||
|
{event.details && (
|
||||||
|
<div className="flex items-center gap-2 mt-2">
|
||||||
|
<Badge variant="secondary" className="bg-orange-50 text-orange-700 hover:bg-orange-50 border-orange-100 text-[10px]">
|
||||||
|
{event.details.from}
|
||||||
|
</Badge>
|
||||||
|
<span className="text-slate-400 text-xs">→</span>
|
||||||
|
<Badge variant="secondary" className="bg-green-50 text-green-700 hover:bg-green-50 border-green-100 text-[10px]">
|
||||||
|
{event.details.to}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Evento inicial de creación */}
|
||||||
|
<div className="relative flex gap-6 group">
|
||||||
|
<div className="relative z-10 flex items-center">
|
||||||
|
<div className="flex h-[42px] w-[42px] items-center justify-center rounded-full border-4 border-white bg-teal-600 text-white shadow-sm">
|
||||||
|
<PlusCircle className="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Card className="flex-1 bg-teal-50/30 border-teal-100 shadow-none">
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="flex items-center justify-between mb-1">
|
||||||
|
<span className="font-bold text-teal-900 text-sm">Creación</span>
|
||||||
|
<span className="text-[10px] text-teal-600 font-medium">14 Ene 2024</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-teal-800/80">Plan de estudios creado</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
118
src/routes/planes2/$planId/iaplan.tsx
Normal file
118
src/routes/planes2/$planId/iaplan.tsx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import { Sparkles, Send, Paperclip, Target, UserCheck, Lightbulb, FileText } from "lucide-react"
|
||||||
|
import { useState } from 'react' // Importamos useState
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Input } from "@/components/ui/input"
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area"
|
||||||
|
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
|
||||||
|
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/planes2/$planId/iaplan')({
|
||||||
|
component: RouteComponent,
|
||||||
|
})
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
// 1. Estado para el texto del input
|
||||||
|
const [inputValue, setInputValue] = useState('')
|
||||||
|
|
||||||
|
// 2. Estado para la lista de mensajes (iniciamos con los de la imagen)
|
||||||
|
const [messages, setMessages] = useState([
|
||||||
|
{ id: 1, role: 'ai', text: 'Hola, soy tu asistente de IA para el diseño del plan de estudios...' },
|
||||||
|
{ id: 2, role: 'user', text: 'jkasakj' },
|
||||||
|
{ id: 3, role: 'ai', text: 'Entendido. Estoy procesando tu solicitud.' },
|
||||||
|
])
|
||||||
|
|
||||||
|
// 3. Función para enviar el mensaje
|
||||||
|
const handleSend = () => {
|
||||||
|
if (!inputValue.trim()) return
|
||||||
|
|
||||||
|
// Agregamos el mensaje del usuario
|
||||||
|
const newMessage = {
|
||||||
|
id: Date.now(),
|
||||||
|
role: 'user',
|
||||||
|
text: inputValue
|
||||||
|
}
|
||||||
|
|
||||||
|
setMessages([...messages, newMessage])
|
||||||
|
setInputValue('') // Limpiamos el input
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-[calc(100vh-200px)] gap-6 p-4">
|
||||||
|
<div className="flex flex-col flex-1 bg-slate-50/50 rounded-xl border relative overflow-hidden">
|
||||||
|
|
||||||
|
<ScrollArea className="flex-1 p-6">
|
||||||
|
<div className="space-y-6 max-w-3xl mx-auto">
|
||||||
|
{/* 4. Mapeamos los mensajes dinámicamente */}
|
||||||
|
{messages.map((msg) => (
|
||||||
|
<div key={msg.id} className={`flex ${msg.role === 'user' ? 'flex-row-reverse' : 'flex-row'} gap-3`}>
|
||||||
|
{msg.role === 'ai' && (
|
||||||
|
<Avatar className="h-8 w-8 border bg-teal-50">
|
||||||
|
<AvatarFallback className="text-teal-600"><Sparkles size={16}/></AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className={msg.role === 'ai' ? 'space-y-2' : ''}>
|
||||||
|
{msg.role === 'ai' && <p className="text-xs font-bold text-teal-700 uppercase tracking-wider">Asistente IA</p>}
|
||||||
|
<div className={`p-4 rounded-2xl text-sm shadow-sm ${
|
||||||
|
msg.role === 'user'
|
||||||
|
? 'bg-teal-600 text-white rounded-tr-none'
|
||||||
|
: 'bg-white border text-slate-700 rounded-tl-none'
|
||||||
|
}`}>
|
||||||
|
{msg.text}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
|
|
||||||
|
{/* 5. Input vinculado al estado */}
|
||||||
|
<div className="p-4 bg-white border-t">
|
||||||
|
<div className="max-w-4xl mx-auto flex gap-2 items-center bg-slate-50 border rounded-lg px-3 py-1 shadow-sm focus-within:ring-1 focus-within:ring-teal-500 transition-all">
|
||||||
|
<Input
|
||||||
|
value={inputValue}
|
||||||
|
onChange={(e) => setInputValue(e.target.value)}
|
||||||
|
onKeyDown={(e) => e.key === 'Enter' && handleSend()} // Enviar con Enter
|
||||||
|
className="border-none bg-transparent focus-visible:ring-0 text-sm"
|
||||||
|
placeholder='Escribe tu solicitud... Usa ":" para mencionar campos'
|
||||||
|
/>
|
||||||
|
<Button variant="ghost" size="icon" className="text-slate-400">
|
||||||
|
<Paperclip size={18} />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleSend}
|
||||||
|
size="icon"
|
||||||
|
className="bg-teal-600 hover:bg-teal-700 h-8 w-8"
|
||||||
|
>
|
||||||
|
<Send size={16} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Panel lateral (se mantiene igual) */}
|
||||||
|
<div className="w-72 space-y-4">
|
||||||
|
<div className="flex items-center gap-2 text-orange-500 font-semibold text-sm mb-4">
|
||||||
|
<Lightbulb size={18} />
|
||||||
|
Acciones rápidas
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<ActionButton icon={<Target className="text-teal-500" size={18} />} text="Mejorar objetivo general" />
|
||||||
|
<ActionButton icon={<UserCheck className="text-slate-500" size={18} />} text="Redactar perfil de egreso" />
|
||||||
|
<ActionButton icon={<Lightbulb className="text-blue-500" size={18} />} text="Sugerir competencias" />
|
||||||
|
<ActionButton icon={<FileText className="text-teal-500" size={18} />} text="Justificar pertinencia" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ActionButton({ icon, text }: { icon: React.ReactNode, text: string }) {
|
||||||
|
return (
|
||||||
|
<Button variant="outline" className="w-full justify-start gap-3 h-auto py-3 px-4 text-sm font-normal hover:bg-slate-50 border-slate-200 shadow-sm text-slate-700">
|
||||||
|
{icon}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
41
src/routes/planes2/$planId/index.tsx
Normal file
41
src/routes/planes2/$planId/index.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/planes2/$planId/')({
|
||||||
|
component: DatosGenerales,
|
||||||
|
})
|
||||||
|
|
||||||
|
function DatosGenerales() {
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<Card title="Objetivo General">
|
||||||
|
Formar profesionales altamente capacitados...
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card title="Perfil de Ingreso">
|
||||||
|
Egresados de educación media superior...
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card title="Perfil de Egreso">
|
||||||
|
Profesional capaz de diseñar...
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card title="Competencias Genéricas">
|
||||||
|
Pensamiento crítico, comunicación efectiva...
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CustomCardProps {
|
||||||
|
title: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Card({ title, children }: CustomCardProps) {
|
||||||
|
return (
|
||||||
|
<div className="rounded-lg border bg-white p-4">
|
||||||
|
<h3 className="font-semibold mb-2">{title}</h3>
|
||||||
|
<p className="text-sm text-gray-600">{children}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
123
src/routes/planes2/$planId/mapa.tsx
Normal file
123
src/routes/planes2/$planId/mapa.tsx
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import { MateriaCard } from './MateriaCard';
|
||||||
|
import type { Materia } from './MateriaCard'; // Agregamos 'type' aquí
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/planes2/$planId/mapa')({
|
||||||
|
component: MapaCurricular,
|
||||||
|
})
|
||||||
|
|
||||||
|
const CICLOS = ["Ciclo 1", "Ciclo 2", "Ciclo 3", "Ciclo 4", "Ciclo 5", "Ciclo 6", "Ciclo 7", "Ciclo 8", "Ciclo 9"];
|
||||||
|
const LINEAS = ["Formación Básica", "Ciencias de la Computación", "Desarrollo de Software", "Redes y Seguridad", "Gestión y Profesionalización"];
|
||||||
|
|
||||||
|
// Ejemplo de materia
|
||||||
|
const MATERIAS: Materia[] = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
clave: 'MAT101',
|
||||||
|
nombre: 'Cálculo Diferencial',
|
||||||
|
creditos: 8,
|
||||||
|
hd: 4,
|
||||||
|
hi: 4,
|
||||||
|
ciclo: 1,
|
||||||
|
linea: 'Formación Básica',
|
||||||
|
tipo: 'Obligatoria',
|
||||||
|
estado: 'Aprobada',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
clave: 'FIS101',
|
||||||
|
nombre: 'Física Mecánica',
|
||||||
|
creditos: 6,
|
||||||
|
hd: 3,
|
||||||
|
hi: 3,
|
||||||
|
ciclo: 1,
|
||||||
|
linea: 'Formación Básica',
|
||||||
|
tipo: 'Obligatoria',
|
||||||
|
estado: 'Aprobada',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
clave: 'PRO101',
|
||||||
|
nombre: 'Fundamentos de Programación',
|
||||||
|
creditos: 8,
|
||||||
|
hd: 4,
|
||||||
|
hi: 4,
|
||||||
|
ciclo: 1,
|
||||||
|
linea: 'Ciencias de la Computación',
|
||||||
|
tipo: 'Obligatoria',
|
||||||
|
estado: 'Revisada',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
clave: 'EST101',
|
||||||
|
nombre: 'Estructura de Datos',
|
||||||
|
creditos: 6,
|
||||||
|
hd: 3,
|
||||||
|
hi: 3,
|
||||||
|
ciclo: 2,
|
||||||
|
linea: 'Ciencias de la Computación',
|
||||||
|
tipo: 'Obligatoria',
|
||||||
|
estado: 'Borrador',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function MapaCurricular() {
|
||||||
|
return (
|
||||||
|
<div className="p-4 overflow-x-auto">
|
||||||
|
<h2 className="text-xl font-semibold mb-6">Mapa Curricular</h2>
|
||||||
|
|
||||||
|
{/* Contenedor de la Grid */}
|
||||||
|
<div
|
||||||
|
className="grid min-w-[1200px] border-l border-t border-slate-200"
|
||||||
|
style={{
|
||||||
|
// 1 columna para nombres de líneas + 9 ciclos
|
||||||
|
gridTemplateColumns: '200px repeat(9, 1fr)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Header: Espacio vacío + Ciclos */}
|
||||||
|
<div className="bg-slate-50 p-2 border-r border-b border-slate-200 font-medium text-sm text-slate-500">
|
||||||
|
Línea Curricular
|
||||||
|
</div>
|
||||||
|
{CICLOS.map((ciclo) => (
|
||||||
|
<div key={ciclo} className="bg-slate-50 p-2 border-r border-b border-slate-200 text-center font-medium text-sm text-slate-500">
|
||||||
|
{ciclo}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Filas por cada Línea Curricular */}
|
||||||
|
{LINEAS.map((linea) => (
|
||||||
|
<>
|
||||||
|
{/* Nombre de la línea (Primera columna) */}
|
||||||
|
<div className="bg-slate-50 p-3 border-r border-b border-slate-200 flex items-center text-xs font-bold uppercase text-slate-600">
|
||||||
|
{linea}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Celdas para cada ciclo en esta línea */}
|
||||||
|
{[1, 2, 3, 4, 5, 6, 7, 8, 9].map((numCiclo) => (
|
||||||
|
<div
|
||||||
|
key={`${linea}-${numCiclo}`}
|
||||||
|
className="p-2 border-r border-b border-slate-100 min-h-[120px] bg-white/50"
|
||||||
|
>
|
||||||
|
{/* Filtrar materias que pertenecen a esta posición */}
|
||||||
|
{MATERIAS.filter(m => m.linea === linea && m.ciclo === numCiclo).map((materia) => (
|
||||||
|
<MateriaCard key={materia.id} materia={materia} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sección de materias sin asignar (como en tu imagen) */}
|
||||||
|
<div className="mt-8">
|
||||||
|
<h3 className="text-sm font-bold text-slate-500 mb-3 uppercase tracking-wider">Materias sin asignar</h3>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<div className="p-3 border rounded-lg bg-slate-50 border-dashed border-slate-300 w-48 text-[10px]">
|
||||||
|
<div className="font-bold">Inglés Técnico</div>
|
||||||
|
<div className="text-slate-500">4 cr • HD: 2 • HI: 2</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
219
src/routes/planes2/$planId/materias.tsx
Normal file
219
src/routes/planes2/$planId/materias.tsx
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Input } from '@/components/ui/input'
|
||||||
|
import { Badge } from '@/components/ui/badge'
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from '@/components/ui/table'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/planes2/$planId/materias')({
|
||||||
|
component: Materias,
|
||||||
|
})
|
||||||
|
|
||||||
|
type Materia = {
|
||||||
|
id: string;
|
||||||
|
clave: string
|
||||||
|
nombre: string
|
||||||
|
creditos: number
|
||||||
|
hd: number
|
||||||
|
hi: number
|
||||||
|
ciclo: string
|
||||||
|
linea: string
|
||||||
|
tipo: 'Obligatoria' | 'Optativa' | 'Troncal'
|
||||||
|
estado: 'Aprobada' | 'Revisada' | 'Borrador'
|
||||||
|
}
|
||||||
|
|
||||||
|
const MATERIAS: Materia[] = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
clave: 'MAT101',
|
||||||
|
nombre: 'Cálculo Diferencial',
|
||||||
|
creditos: 8,
|
||||||
|
hd: 4,
|
||||||
|
hi: 4,
|
||||||
|
ciclo: 'Ciclo 1',
|
||||||
|
linea: 'Formación Básica',
|
||||||
|
tipo: 'Obligatoria',
|
||||||
|
estado: 'Aprobada',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
clave: 'FIS101',
|
||||||
|
nombre: 'Física Mecánica',
|
||||||
|
creditos: 6,
|
||||||
|
hd: 3,
|
||||||
|
hi: 3,
|
||||||
|
ciclo: 'Ciclo 1',
|
||||||
|
linea: 'Formación Básica',
|
||||||
|
tipo: 'Obligatoria',
|
||||||
|
estado: 'Aprobada',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
clave: 'PRO101',
|
||||||
|
nombre: 'Fundamentos de Programación',
|
||||||
|
creditos: 8,
|
||||||
|
hd: 4,
|
||||||
|
hi: 4,
|
||||||
|
ciclo: 'Ciclo 1',
|
||||||
|
linea: 'Ciencias de la Computación',
|
||||||
|
tipo: 'Obligatoria',
|
||||||
|
estado: 'Revisada',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
clave: 'EST101',
|
||||||
|
nombre: 'Estructura de Datos',
|
||||||
|
creditos: 6,
|
||||||
|
hd: 3,
|
||||||
|
hi: 3,
|
||||||
|
ciclo: 'Ciclo 2',
|
||||||
|
linea: 'Ciencias de la Computación',
|
||||||
|
tipo: 'Obligatoria',
|
||||||
|
estado: 'Borrador',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function Materias() {
|
||||||
|
const [search, setSearch] = useState('')
|
||||||
|
const [filtro, setFiltro] = useState<'Todas' | Materia['tipo']>('Todas')
|
||||||
|
|
||||||
|
const materiasFiltradas = MATERIAS.filter((m) => {
|
||||||
|
const okFiltro = filtro === 'Todas' || m.tipo === filtro
|
||||||
|
const okSearch =
|
||||||
|
m.nombre.toLowerCase().includes(search.toLowerCase()) ||
|
||||||
|
m.clave.toLowerCase().includes(search.toLowerCase())
|
||||||
|
|
||||||
|
return okFiltro && okSearch
|
||||||
|
})
|
||||||
|
|
||||||
|
const totalCreditos = materiasFiltradas.reduce(
|
||||||
|
(acc, m) => acc + m.creditos,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex justify-between items-start">
|
||||||
|
<div>
|
||||||
|
<h2 className="text-xl font-semibold">Materias del Plan</h2>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{materiasFiltradas.length} materias · {totalCreditos} créditos
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button variant="outline">Clonar de mi Facultad</Button>
|
||||||
|
<Button variant="outline">Clonar de otra Facultad</Button>
|
||||||
|
<Button className="bg-emerald-700 hover:bg-emerald-800">
|
||||||
|
+ Nueva Materia
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Buscador y filtros */}
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<Input
|
||||||
|
placeholder="Buscar por nombre o clave..."
|
||||||
|
value={search}
|
||||||
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
|
className="w-64"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{['Todas', 'Obligatoria', 'Optativa', 'Troncal'].map((t) => (
|
||||||
|
<Button
|
||||||
|
key={t}
|
||||||
|
variant={filtro === t ? 'secondary' : 'ghost'}
|
||||||
|
size="sm"
|
||||||
|
onClick={() => setFiltro(t as any)}
|
||||||
|
>
|
||||||
|
{t === 'Obligatoria' ? 'Obligatorias' : t}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Tabla */}
|
||||||
|
<div className="rounded-md border">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Clave</TableHead>
|
||||||
|
<TableHead>Nombre</TableHead>
|
||||||
|
<TableHead className="text-center">Créditos</TableHead>
|
||||||
|
<TableHead className="text-center">HD</TableHead>
|
||||||
|
<TableHead className="text-center">HI</TableHead>
|
||||||
|
<TableHead>Ciclo</TableHead>
|
||||||
|
<TableHead>Línea</TableHead>
|
||||||
|
<TableHead>Tipo</TableHead>
|
||||||
|
<TableHead>Estado</TableHead>
|
||||||
|
<TableHead className="text-center">Acciones</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
|
||||||
|
<TableBody>
|
||||||
|
{materiasFiltradas.map((m) => (
|
||||||
|
<TableRow key={m.clave}>
|
||||||
|
<TableCell className="text-muted-foreground">
|
||||||
|
{m.clave}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">{m.nombre}</TableCell>
|
||||||
|
<TableCell className="text-center">{m.creditos}</TableCell>
|
||||||
|
<TableCell className="text-center">{m.hd}</TableCell>
|
||||||
|
<TableCell className="text-center">{m.hi}</TableCell>
|
||||||
|
<TableCell>{m.ciclo}</TableCell>
|
||||||
|
<TableCell>{m.linea}</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
<Badge variant="secondary">{m.tipo}</Badge>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className={
|
||||||
|
m.estado === 'Aprobada'
|
||||||
|
? 'bg-emerald-100 text-emerald-700'
|
||||||
|
: m.estado === 'Revisada'
|
||||||
|
? 'bg-blue-100 text-blue-700'
|
||||||
|
: 'bg-gray-100 text-gray-500'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{m.estado}
|
||||||
|
</Badge>
|
||||||
|
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell className="text-center">
|
||||||
|
<Button variant="ghost" size="icon">
|
||||||
|
✏️
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{materiasFiltradas.length === 0 && (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
colSpan={10}
|
||||||
|
className="text-center py-6 text-muted-foreground"
|
||||||
|
>
|
||||||
|
No se encontraron materias
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
118
src/routes/planes2/$planId/route.tsx
Normal file
118
src/routes/planes2/$planId/route.tsx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import { createFileRoute, Outlet, Link } from '@tanstack/react-router'
|
||||||
|
import { ChevronLeft, GraduationCap, Clock, Hash, CalendarDays, Rocket, BookOpen, CheckCircle2 } from "lucide-react"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/planes2/$planId')({
|
||||||
|
component: PlanLayout,
|
||||||
|
})
|
||||||
|
|
||||||
|
function PlanLayout() {
|
||||||
|
const { planId } = Route.useParams()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-white">
|
||||||
|
{/* 1. Header Superior con Sombra (Volver a planes) */}
|
||||||
|
<div className="border-b bg-white/50 backdrop-blur-sm sticky top-0 z-20 shadow-sm">
|
||||||
|
<div className="px-6 py-2">
|
||||||
|
<Link
|
||||||
|
to="/planes2"
|
||||||
|
className="flex items-center gap-1 text-xs text-gray-500 hover:text-gray-800 transition-colors w-fit"
|
||||||
|
>
|
||||||
|
<ChevronLeft size={14} /> Volver a planes
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 2. Contenido Principal con Padding */}
|
||||||
|
<div className="p-8 max-w-[1600px] mx-auto space-y-8">
|
||||||
|
|
||||||
|
{/* Header del Plan y Badges */}
|
||||||
|
<div className="flex flex-col md:flex-row justify-between items-start gap-4">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-3xl font-bold tracking-tight text-slate-900">Plan de Estudios 2024</h1>
|
||||||
|
<p className="text-lg text-slate-500 font-medium mt-1">
|
||||||
|
Ingeniería en Sistemas Computacionales
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Badges de la derecha */}
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Badge variant="secondary" className="bg-blue-50 text-blue-700 border-blue-100 gap-1 px-3">
|
||||||
|
<Rocket size={12} /> Ingeniería
|
||||||
|
</Badge>
|
||||||
|
<Badge variant="secondary" className="bg-orange-50 text-orange-700 border-orange-100 gap-1 px-3">
|
||||||
|
<BookOpen size={12} /> Licenciatura
|
||||||
|
</Badge>
|
||||||
|
<Badge className="bg-teal-50 text-teal-700 border-teal-200 gap-1 px-3 hover:bg-teal-100">
|
||||||
|
<CheckCircle2 size={12} /> En Revisión
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 3. Cards de Información (Nivel, Duración, etc.) */}
|
||||||
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||||
|
<InfoCard icon={<GraduationCap className="text-slate-400" />} label="Nivel" value="Superior" />
|
||||||
|
<InfoCard icon={<Clock className="text-slate-400" />} label="Duración" value="9 Semestres" />
|
||||||
|
<InfoCard icon={<Hash className="text-slate-400" />} label="Créditos" value="320" />
|
||||||
|
<InfoCard icon={<CalendarDays className="text-slate-400" />} label="Creación" value="14 ene 2024" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 4. Navegación de Tabs */}
|
||||||
|
<div className="border-b overflow-x-auto scrollbar-hide">
|
||||||
|
<nav className="flex gap-8 min-w-max">
|
||||||
|
<Tab to="/planes2/$planId" params={{ planId }}>Datos Generales</Tab>
|
||||||
|
<Tab to="/planes2/$planId/mapa" params={{ planId }}>Mapa Curricular</Tab>
|
||||||
|
<Tab to="/planes2/$planId/materias" params={{ planId }}>Materias</Tab>
|
||||||
|
<Tab to="/planes2/$planId/flujo" params={{ planId }}>Flujo y Estados</Tab>
|
||||||
|
<Tab to="/planes2/$planId/iaplan" params={{ planId }}>IA del Plan</Tab>
|
||||||
|
<Tab to="/planes2/$planId/documento" params={{ planId }}>Documento</Tab>
|
||||||
|
<Tab to="/planes2/$planId/historial" params={{ planId }}>Historial</Tab>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 5. Contenido del Tab */}
|
||||||
|
<main className="pt-2 animate-in fade-in duration-500">
|
||||||
|
<Outlet />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub-componente para las tarjetas de información
|
||||||
|
function InfoCard({ icon, label, value }: { icon: React.ReactNode, label: string, value: string }) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-4 bg-slate-50/50 border border-slate-200/60 p-4 rounded-xl shadow-sm">
|
||||||
|
<div className="p-2 bg-white rounded-lg border shadow-sm">
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-[10px] uppercase font-bold text-slate-400 tracking-wider leading-none mb-1">{label}</p>
|
||||||
|
<p className="text-sm font-semibold text-slate-700">{value}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Tab({
|
||||||
|
to,
|
||||||
|
params,
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
to: string;
|
||||||
|
params?: any;
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={to}
|
||||||
|
params={params}
|
||||||
|
className="pb-3 text-sm font-medium text-slate-500 border-b-2 border-transparent hover:text-slate-800 transition-all"
|
||||||
|
activeProps={{
|
||||||
|
className: 'border-teal-600 text-teal-700 font-bold',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user