updated SignIn and App.js to ShadCN basics

This commit is contained in:
Josh 2025-04-30 13:31:26 +00:00
parent 91066a3cb6
commit 48ccf2e1dc
5 changed files with 529 additions and 103 deletions

487
package-lock.json generated
View File

@ -12,7 +12,7 @@
"@radix-ui/react-dialog": "^1.0.0", "@radix-ui/react-dialog": "^1.0.0",
"@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-progress": "^1.1.2",
"@radix-ui/react-tabs": "^1.0.3", "@radix-ui/react-tabs": "^1.1.9",
"axios": "^1.7.9", "axios": "^1.7.9",
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"chart.js": "^4.4.7", "chart.js": "^4.4.7",
@ -37,7 +37,8 @@
"react-spinners": "^0.15.0", "react-spinners": "^0.15.0",
"sqlite": "^5.1.1", "sqlite": "^5.1.1",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7",
"tailwind-merge": "^3.0.2", "tailwind-merge": "^3.2.0",
"tailwindcss-animate": "^1.0.7",
"web-vitals": "^4.2.4", "web-vitals": "^4.2.4",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },
@ -3161,15 +3162,15 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@radix-ui/react-collection": { "node_modules/@radix-ui/react-collection": {
"version": "1.1.2", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.4.tgz",
"integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==", "integrity": "sha512-cv4vSf7HttqXilDnAnvINd53OTl1/bjUYVZrkFnA7nwmY9Ob2POUy0WY0sfqBAe1s5FyKsyceQlqiEGPYNTadg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.1", "@radix-ui/react-context": "1.1.2",
"@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-primitive": "2.1.0",
"@radix-ui/react-slot": "1.1.2" "@radix-ui/react-slot": "1.2.0"
}, },
"peerDependencies": { "peerDependencies": {
"@types/react": "*", "@types/react": "*",
@ -3186,6 +3187,77 @@
} }
} }
}, },
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-primitive": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.0.tgz",
"integrity": "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-slot": "1.2.0"
},
"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"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz",
"integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==",
"license": "MIT",
"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"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-compose-refs": { "node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
@ -3253,9 +3325,9 @@
} }
}, },
"node_modules/@radix-ui/react-direction": { "node_modules/@radix-ui/react-direction": {
"version": "1.1.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
"integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"@types/react": "*", "@types/react": "*",
@ -3457,20 +3529,20 @@
} }
}, },
"node_modules/@radix-ui/react-roving-focus": { "node_modules/@radix-ui/react-roving-focus": {
"version": "1.1.2", "version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.7.tgz",
"integrity": "sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==", "integrity": "sha512-C6oAg451/fQT3EGbWHbCQjYTtbyjNO1uzQgMzwyivcHT3GKNEmu1q3UuREhN+HzHAVtv3ivMVK08QlC+PkYw9Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@radix-ui/primitive": "1.1.1", "@radix-ui/primitive": "1.1.2",
"@radix-ui/react-collection": "1.1.2", "@radix-ui/react-collection": "1.1.4",
"@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.1", "@radix-ui/react-context": "1.1.2",
"@radix-ui/react-direction": "1.1.0", "@radix-ui/react-direction": "1.1.1",
"@radix-ui/react-id": "1.1.0", "@radix-ui/react-id": "1.1.1",
"@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-primitive": "2.1.0",
"@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-callback-ref": "1.1.1",
"@radix-ui/react-use-controllable-state": "1.1.0" "@radix-ui/react-use-controllable-state": "1.2.2"
}, },
"peerDependencies": { "peerDependencies": {
"@types/react": "*", "@types/react": "*",
@ -3487,6 +3559,150 @@
} }
} }
}, },
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/primitive": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz",
"integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==",
"license": "MIT"
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-id": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
"integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-primitive": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.0.tgz",
"integrity": "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-slot": "1.2.0"
},
"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"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-slot": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz",
"integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==",
"license": "MIT",
"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"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-controllable-state": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
"integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-effect-event": "0.0.2",
"@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-layout-effect": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-slot": { "node_modules/@radix-ui/react-slot": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz",
@ -3506,19 +3722,19 @@
} }
}, },
"node_modules/@radix-ui/react-tabs": { "node_modules/@radix-ui/react-tabs": {
"version": "1.1.3", "version": "1.1.9",
"resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.3.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.9.tgz",
"integrity": "sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng==", "integrity": "sha512-KIjtwciYvquiW/wAFkELZCVnaNLBsYNhTNcvl+zfMAbMhRkcvNuCLXDDd22L0j7tagpzVh/QwbFpwAATg7ILPw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@radix-ui/primitive": "1.1.1", "@radix-ui/primitive": "1.1.2",
"@radix-ui/react-context": "1.1.1", "@radix-ui/react-context": "1.1.2",
"@radix-ui/react-direction": "1.1.0", "@radix-ui/react-direction": "1.1.1",
"@radix-ui/react-id": "1.1.0", "@radix-ui/react-id": "1.1.1",
"@radix-ui/react-presence": "1.1.2", "@radix-ui/react-presence": "1.1.4",
"@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-primitive": "2.1.0",
"@radix-ui/react-roving-focus": "1.1.2", "@radix-ui/react-roving-focus": "1.1.7",
"@radix-ui/react-use-controllable-state": "1.1.0" "@radix-ui/react-use-controllable-state": "1.2.2"
}, },
"peerDependencies": { "peerDependencies": {
"@types/react": "*", "@types/react": "*",
@ -3535,6 +3751,159 @@
} }
} }
}, },
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/primitive": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz",
"integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==",
"license": "MIT"
},
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-context": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-id": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
"integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-presence": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz",
"integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-use-layout-effect": "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"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-primitive": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.0.tgz",
"integrity": "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-slot": "1.2.0"
},
"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"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-slot": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz",
"integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==",
"license": "MIT",
"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"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-controllable-state": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
"integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-effect-event": "0.0.2",
"@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-layout-effect": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-callback-ref": { "node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
@ -3568,6 +3937,39 @@
} }
} }
}, },
"node_modules/@radix-ui/react-use-effect-event": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
"integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-effect-event/node_modules/@radix-ui/react-use-layout-effect": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-escape-keydown": { "node_modules/@radix-ui/react-use-escape-keydown": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
@ -17873,9 +18275,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/tailwind-merge": { "node_modules/tailwind-merge": {
"version": "3.0.2", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.0.2.tgz", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.2.0.tgz",
"integrity": "sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==", "integrity": "sha512-FQT/OVqCD+7edmmJpsgCsY820RTD5AkBryuG5IUqR5YQZSdj5xlH5nLgH7YPths7WsLPSpSBNneJdM8aS8aeFA==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "github", "type": "github",
@ -17919,6 +18321,15 @@
"node": ">=14.0.0" "node": ">=14.0.0"
} }
}, },
"node_modules/tailwindcss-animate": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
"integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
"license": "MIT",
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders"
}
},
"node_modules/tailwindcss/node_modules/lilconfig": { "node_modules/tailwindcss/node_modules/lilconfig": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",

View File

@ -7,7 +7,7 @@
"@radix-ui/react-dialog": "^1.0.0", "@radix-ui/react-dialog": "^1.0.0",
"@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-progress": "^1.1.2",
"@radix-ui/react-tabs": "^1.0.3", "@radix-ui/react-tabs": "^1.1.9",
"axios": "^1.7.9", "axios": "^1.7.9",
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"chart.js": "^4.4.7", "chart.js": "^4.4.7",
@ -32,7 +32,8 @@
"react-spinners": "^0.15.0", "react-spinners": "^0.15.0",
"sqlite": "^5.1.1", "sqlite": "^5.1.1",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7",
"tailwind-merge": "^3.0.2", "tailwind-merge": "^3.2.0",
"tailwindcss-animate": "^1.0.7",
"web-vitals": "^4.2.4", "web-vitals": "^4.2.4",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },

View File

@ -1,4 +1,3 @@
// App.js
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-dom'; import { Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-dom';
import SessionExpiredHandler from './components/SessionExpiredHandler.js'; import SessionExpiredHandler from './components/SessionExpiredHandler.js';
@ -12,35 +11,36 @@ import FinancialProfileForm from './components/FinancialProfileForm.js';
import MilestoneTracker from "./components/MilestoneTracker.js"; import MilestoneTracker from "./components/MilestoneTracker.js";
import Paywall from "./components/Paywall.js"; import Paywall from "./components/Paywall.js";
import OnboardingContainer from './components/PremiumOnboarding/OnboardingContainer.js'; import OnboardingContainer from './components/PremiumOnboarding/OnboardingContainer.js';
// NEW: import your MultiScenarioView component
import MultiScenarioView from './components/MultiScenarioView.js'; import MultiScenarioView from './components/MultiScenarioView.js';
import './App.css';
function App() { function App() {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const [isAuthenticated, setIsAuthenticated] = useState(() => !!localStorage.getItem('token')); const [isAuthenticated, setIsAuthenticated] = useState(() => {
return !!localStorage.getItem('token');
});
// Any paths that are specifically “premium” (where you might not want to show an Upgrade CTA). // Hide the Upgrade CTA on these paths:
const premiumPaths = [ const premiumPaths = [
'/milestone-tracker', '/milestone-tracker',
'/paywall', '/paywall',
'/financial-profile', '/financial-profile',
'/multi-scenario', // ADDED here so the CTA is hidden on the multi-scenario page '/multi-scenario',
]; ];
const showPremiumCTA = !premiumPaths.includes(location.pathname); const showPremiumCTA = !premiumPaths.includes(location.pathname);
return ( return (
<div className="App"> <div className="flex min-h-screen flex-col bg-gray-50 text-gray-800">
<header className="app-header"> {/* Header */}
<h1>AptivaAI - Career Guidance Platform (beta)</h1> <header className="flex items-center justify-between border-b bg-white px-6 py-4 shadow-sm">
<h1 className="text-lg font-semibold">
AptivaAI - Career Guidance Platform (beta)
</h1>
{showPremiumCTA && ( {showPremiumCTA && (
<button <button
className="premium-cta" className="rounded bg-blue-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700"
onClick={() => navigate('/paywall')} onClick={() => navigate('/paywall')}
> >
Upgrade to Premium Upgrade to Premium
@ -48,30 +48,36 @@ function App() {
)} )}
</header> </header>
<Routes> {/* Main Content */}
<Route path="/" element={<Navigate to="/signin" />} /> <main className="flex-1 p-6">
<Route path="/signin" element={<SignIn setIsAuthenticated={setIsAuthenticated} />} /> <Routes>
<Route path="/signup" element={<SignUp />} /> <Route path="/" element={<Navigate to="/signin" />} />
<Route path="/paywall" element={<Paywall />} /> <Route
path="/signin"
element={<SignIn setIsAuthenticated={setIsAuthenticated} />}
/>
<Route path="/signup" element={<SignUp />} />
<Route path="/paywall" element={<Paywall />} />
{isAuthenticated && ( {isAuthenticated && (
<> <>
<Route path="/getting-started" element={<GettingStarted />} /> <Route path="/getting-started" element={<GettingStarted />} />
<Route path="/interest-inventory" element={<InterestInventory />} /> <Route path="/interest-inventory" element={<InterestInventory />} />
<Route path="/dashboard" element={<Dashboard />} /> <Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<UserProfile />} /> <Route path="/profile" element={<UserProfile />} />
<Route path="/milestone-tracker" element={<MilestoneTracker />} /> <Route path="/milestone-tracker" element={<MilestoneTracker />} />
<Route path="/financial-profile" element={<FinancialProfileForm />} /> <Route path="/financial-profile" element={<FinancialProfileForm />} />
<Route path="/premium-onboarding" element={<OnboardingContainer />} /> <Route path="/premium-onboarding" element={<OnboardingContainer />} />
<Route path="/multi-scenario" element={<MultiScenarioView />} />
</>
)}
{/* NEW multi-scenario route */} {/* Fallback */}
<Route path="/multi-scenario" element={<MultiScenarioView />} /> <Route path="*" element={<Navigate to="/signin" />} />
</> </Routes>
)} </main>
<Route path="*" element={<Navigate to="/signin" />} />
</Routes>
{/* Session Handler */}
<SessionExpiredHandler /> <SessionExpiredHandler />
</div> </div>
); );

View File

@ -1,18 +1,14 @@
import React, { useRef, useState } from 'react'; import React, { useRef, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import './SignIn.css';
function SignIn({ setIsAuthenticated }) { function SignIn({ setIsAuthenticated }) {
console.log('SignIn component loaded');
const navigate = useNavigate(); const navigate = useNavigate();
const usernameRef = useRef(''); const usernameRef = useRef('');
const passwordRef = useRef(''); const passwordRef = useRef('');
const [error, setError] = useState(''); // Still needs state for UI updates const [error, setError] = useState('');
const handleSignIn = async (event) => { const handleSignIn = async (event) => {
event.preventDefault(); event.preventDefault();
setError(''); setError('');
const username = usernameRef.current.value; const username = usernameRef.current.value;
@ -22,13 +18,11 @@ function SignIn({ setIsAuthenticated }) {
setError('Please enter both username and password'); setError('Please enter both username and password');
return; return;
} }
try { try {
// Make a POST request to the backend for authentication
const response = await fetch('https://dev1.aptivaai.com/api/signin', { const response = await fetch('https://dev1.aptivaai.com/api/signin', {
method: 'POST', method: 'POST',
headers: { headers: { 'Content-Type': 'application/json' },
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }), body: JSON.stringify({ username, password }),
}); });
@ -38,46 +32,60 @@ function SignIn({ setIsAuthenticated }) {
} }
const data = await response.json(); const data = await response.json();
console.log('SignIn response data:', data);
const { token, userId } = data; const { token, userId } = data;
localStorage.setItem('token', token); localStorage.setItem('token', token);
localStorage.setItem('userId', userId); localStorage.setItem('userId', userId);
console.log('Token and userId saved in localStorage');
console.log('SignIn response data:', data);
// Call setIsAuthenticated(true) to update the state
setIsAuthenticated(true); setIsAuthenticated(true);
navigate('/getting-started'); // Redirect to GettingStarted after SignIn navigate('/getting-started');
} catch (error) { } catch (error) {
console.error('Sign-In Error:', error.message); setError(error.message);
setError(error.message); // Display error message to the user
} }
}; };
return ( return (
<div className="signin-container"> <div className="flex min-h-screen flex-col items-center justify-center bg-gray-100 p-4">
<div className="signin-form"> <div className="w-full max-w-sm rounded-md bg-white p-6 shadow-md">
<h1>Sign In</h1> <h1 className="mb-6 text-center text-2xl font-semibold">Sign In</h1>
{error && <p className="error-message">{error}</p>}
<form onSubmit={handleSignIn}> {error && (
<p className="mb-4 rounded bg-red-50 p-2 text-sm text-red-600">
{error}
</p>
)}
<form onSubmit={handleSignIn} className="flex flex-col space-y-4">
<input <input
type="text" type="text"
placeholder="Username" placeholder="Username"
ref={usernameRef} // Use ref instead of state ref={usernameRef}
className="signin-input" className="w-full rounded border border-gray-300 p-2 focus:border-blue-500 focus:outline-none"
/> />
<input <input
type="password" type="password"
placeholder="Password" placeholder="Password"
ref={passwordRef} // Use ref instead of state ref={passwordRef}
className="signin-input" className="w-full rounded border border-gray-300 p-2 focus:border-blue-500 focus:outline-none"
/> />
<button type="submit" className="signin-button"> <button
type="submit"
// Make the button auto-sized, centered, and ensure text is centered
className="mx-auto rounded bg-blue-600 px-6 py-2 text-center text-white transition-colors hover:bg-blue-700 focus:outline-none"
>
Sign In Sign In
</button> </button>
</form> </form>
<p>Dont have an account? <Link to="/signup">Sign Up</Link></p>
<p className="mt-4 text-center text-sm text-gray-600">
Dont have an account?{' '}
<Link
to="/signup"
className="font-medium text-blue-600 hover:text-blue-500"
>
Sign Up
</Link>
</p>
</div> </div>
</div> </div>
); );

Binary file not shown.