├── .env.example ├── .eslintrc.cjs ├── .gitignore ├── LICENSE ├── README.md ├── bun.lockb ├── components.json ├── next.config.js ├── package.json ├── postcss.config.cjs ├── prettier.config.js ├── prisma ├── schema.prisma └── seed.ts ├── public ├── 3D │ ├── island.glb │ ├── prizePoolPillar.glb │ ├── trident.glb │ └── zeusHF.glb ├── brochure.pdf ├── favicons │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ └── site.webmanifest ├── fonts │ ├── Herkules.ttf │ ├── Lagistha.ttf │ ├── NCLNeovibes-Demo.otf │ ├── RELIGATH-Demo.otf │ ├── anton.json │ ├── cinzel.json │ ├── geraldine.ttf │ ├── metal.json │ ├── puffy.json │ └── valty.otf ├── images │ ├── Size_Chart.jpeg │ ├── bg.jpg │ ├── bg1.png │ ├── bg2.jpg │ ├── blue-grainy.png │ ├── crown-gold.svg │ ├── crown-green.svg │ ├── max.webp │ ├── mid.webp │ ├── min.webp │ ├── noise.svg │ ├── sponsors │ │ ├── frame.png │ │ ├── inflow.png │ │ ├── niveus.png │ │ ├── paloalto.png │ │ └── rakuten.svg │ ├── thunderbolt.png │ ├── timeline_leaves.webp │ └── tracks │ │ ├── 1K │ │ ├── Poliigon_StoneQuartzite_8060.mtlx │ │ ├── Poliigon_StoneQuartzite_8060_ORM.png │ │ ├── marble_albedo.png │ │ ├── marble_ao.png │ │ ├── marble_displacement.tiff │ │ ├── marble_metallic.png │ │ ├── marble_normal.png │ │ └── marble_roughness.png │ │ ├── FinTech.png │ │ ├── Healthcare.png │ │ ├── Logistics.png │ │ ├── OpenInnovation.png │ │ ├── SustainableDev.png │ │ └── tracks-floor │ │ ├── rectangle-polished-tile_albedo.png │ │ ├── rectangle-polished-tile_ao.png │ │ ├── rectangle-polished-tile_height.png │ │ ├── rectangle-polished-tile_metallic.png │ │ ├── rectangle-polished-tile_normal-ogl.png │ │ ├── rectangle-polished-tile_preview.jpg │ │ └── rectangle-polished-tile_roughness.png ├── logos │ ├── FLC Logo - Full.png │ ├── NMAMITLogo.png │ ├── csi-logo.png │ ├── flcLogo.png │ ├── flc_logo_crop.png │ ├── logo.png │ └── logoWithBg.png └── textures │ └── cloudTexture.png ├── src ├── components │ ├── CountdownTimer.tsx │ ├── ResultsVisibilityToggle.tsx │ ├── TeamCSVDownloadModal.tsx │ ├── TrackPageVisits.tsx │ ├── about2 │ │ └── model.tsx │ ├── accordion │ │ └── index.tsx │ ├── admin │ │ ├── AddJudgePopup.tsx │ │ └── teamDetails │ │ │ └── index.tsx │ ├── appSettingValidator │ │ └── index.tsx │ ├── chat │ │ ├── chatButton.tsx │ │ ├── chatList.tsx │ │ ├── chatWindow.tsx │ │ ├── messageList.tsx │ │ ├── navbar.tsx │ │ └── noRoom.tsx │ ├── dashboard │ │ ├── AllocationTab.tsx │ │ ├── AnalyticsTab.tsx │ │ ├── CriteriaTab.tsx │ │ ├── FilterSheet.tsx │ │ ├── JuryTab.tsx │ │ ├── MemberDetailsDialog.tsx │ │ ├── Payments.tsx │ │ ├── QuickboardTab.tsx │ │ ├── RemarksTab.tsx │ │ ├── RolesTab.tsx │ │ ├── ScoreTab.tsx │ │ ├── TeamLeaderboard.tsx │ │ ├── TeamsTab.tsx │ │ └── selectionWindow.tsx │ ├── domains │ │ └── index.tsx │ ├── errorScreen.tsx │ ├── footer │ │ └── index.tsx │ ├── forms │ │ ├── createCollege │ │ │ ├── index.tsx │ │ │ └── states.ts │ │ ├── createTeam │ │ │ └── index.tsx │ │ ├── ideaSubmitForm │ │ │ └── index.tsx │ │ ├── paymentForm │ │ │ └── index.tsx │ │ ├── registerProfile │ │ │ └── index.tsx │ │ └── teamInfo │ │ │ ├── index.tsx │ │ │ └── teamInfo.tsx │ ├── hero │ │ ├── dustOverlay.tsx │ │ ├── index.tsx │ │ ├── zeusBackground.tsx │ │ └── zeusBust.tsx │ ├── judge │ │ ├── day1.tsx │ │ ├── day2.tsx │ │ ├── day3.tsx │ │ ├── teamRemarks.tsx │ │ └── tutorial.tsx │ ├── layout │ │ ├── backgroundGradient.tsx │ │ ├── backgroundWrapper.tsx │ │ ├── chatLayout.tsx │ │ ├── dashboardLayout.tsx │ │ └── index.tsx │ ├── marquee │ │ └── index.tsx │ ├── message │ │ ├── congratulationsMessage.tsx │ │ └── registrationsClosed.tsx │ ├── navbar │ │ ├── authButton.tsx │ │ ├── dashboardButton.tsx │ │ └── index.tsx │ ├── not-found │ │ └── index.tsx │ ├── notLoggedIn │ │ ├── index.tsx │ │ └── signInButton.tsx │ ├── organiser │ │ └── AuditLogViewer.tsx │ ├── organiserDashboard │ │ ├── analytics.tsx │ │ ├── filterSheet.tsx │ │ ├── githubSheet.tsx │ │ ├── judgePanel.tsx │ │ ├── judgesTable.tsx │ │ ├── volunteerPanel.tsx │ │ └── volunteerTable.tsx │ ├── participantsTable │ │ ├── index.tsx │ │ ├── topTeams.tsx │ │ └── topTeamsWithPdf.tsx │ ├── payment │ │ ├── index.tsx │ │ ├── success.tsx │ │ └── verify.tsx │ ├── pdf │ │ └── index.tsx │ ├── prizePool │ │ └── index.tsx │ ├── profile │ │ ├── createCollege.tsx │ │ ├── editProfileForm.tsx │ │ ├── ideaDetails.tsx │ │ ├── identityDetails.tsx │ │ ├── index.tsx │ │ ├── logout.tsx │ │ ├── manageAccount.tsx │ │ ├── personalDetails.tsx │ │ ├── profilePhoto.tsx │ │ └── teamDetails.tsx │ ├── progressBar.tsx │ ├── progressBarProvider │ │ └── index.tsx │ ├── progressProvider.tsx │ ├── registered │ │ ├── InTeam.tsx │ │ └── index.tsx │ ├── registrationProgress │ │ ├── fillDetails.tsx │ │ ├── formTeam.tsx │ │ └── index.tsx │ ├── spinner │ │ ├── index.tsx │ │ └── thunderSpinner.tsx │ ├── sponsors │ │ └── index.tsx │ ├── team │ │ └── teamList.tsx │ ├── teamDashboard │ │ └── finalParticipantsTable.tsx │ ├── timeline │ │ ├── eventObjects.tsx │ │ ├── helix.ts │ │ ├── island.tsx │ │ ├── model.tsx │ │ └── scene.tsx │ ├── tracks │ │ └── index.tsx │ ├── ui │ │ ├── accordion.tsx │ │ ├── alert-dialog.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── button.tsx │ │ ├── button │ │ │ └── index.tsx │ │ ├── card │ │ │ └── index.tsx │ │ ├── carousel.tsx │ │ ├── checkbox.tsx │ │ ├── command │ │ │ └── index.tsx │ │ ├── dialog.tsx │ │ ├── dragDrop.tsx │ │ ├── dropZone │ │ │ └── index.tsx │ │ ├── dropdown-menu.tsx │ │ ├── form │ │ │ └── index.tsx │ │ ├── input │ │ │ └── index.tsx │ │ ├── label.tsx │ │ ├── label │ │ │ └── index.tsx │ │ ├── modal │ │ │ └── index.tsx │ │ ├── monochrome-buttons.tsx │ │ ├── popover │ │ │ └── index.tsx │ │ ├── radio-group.tsx │ │ ├── scroll-area.tsx │ │ ├── sectionHeading │ │ │ └── index.tsx │ │ ├── select │ │ │ └── index.tsx │ │ ├── separator.tsx │ │ ├── sheet.tsx │ │ ├── skeleton.tsx │ │ ├── table │ │ │ └── index.tsx │ │ ├── tabs.tsx │ │ ├── textarea.tsx │ │ ├── toast.ts │ │ ├── toggle-group.tsx │ │ ├── toggle.tsx │ │ └── tooltip.tsx │ ├── validatorDashboard │ │ └── pdfModal.tsx │ └── videosubmission │ │ ├── index.tsx │ │ └── submitVideo.tsx ├── constants │ ├── events.ts │ └── index.tsx ├── env.js ├── hooks │ ├── useContainerSize.ts │ ├── useParallax.ts │ ├── usePusher.ts │ ├── useScroll.ts │ └── useWindowSize.ts ├── lib │ └── utils.ts ├── pages │ ├── 404.tsx │ ├── _app.tsx │ ├── api │ │ ├── auth │ │ │ └── [...nextauth].ts │ │ ├── image │ │ │ └── upload.ts │ │ ├── pdf │ │ │ └── upload.ts │ │ ├── schema.ts │ │ └── trpc │ │ │ └── [trpc].ts │ ├── chat │ │ └── index.tsx │ ├── contact │ │ └── index.tsx │ ├── dashboard │ │ ├── download.tsx │ │ ├── index.tsx │ │ ├── judge.tsx │ │ ├── organiser.tsx │ │ ├── super-validator.tsx │ │ ├── team.tsx │ │ ├── teams │ │ │ └── leaderboard.tsx │ │ └── validator.tsx │ ├── index.tsx │ ├── profile │ │ └── index.tsx │ ├── register │ │ └── index.tsx │ ├── results │ │ └── index.tsx │ ├── teams │ │ └── index.tsx │ ├── timeline │ │ └── index.tsx │ └── timer.tsx ├── server │ ├── api │ │ ├── root.ts │ │ ├── routers │ │ │ ├── analytics.ts │ │ │ ├── app.ts │ │ │ ├── auditlog.ts │ │ │ ├── chat.ts │ │ │ ├── college.ts │ │ │ ├── downloaddata.ts │ │ │ ├── github.ts │ │ │ ├── idea.ts │ │ │ ├── judges.ts │ │ │ ├── organiser.ts │ │ │ ├── payment.ts │ │ │ ├── remark.ts │ │ │ ├── super-validator.ts │ │ │ ├── team.ts │ │ │ ├── user.ts │ │ │ ├── validator.ts │ │ │ └── videoSubmission.ts │ │ └── trpc.ts │ ├── auth.ts │ ├── db.ts │ ├── pusher.ts │ └── schema │ │ └── zod-schema.ts ├── styles │ └── globals.css ├── types │ ├── app-settings.ts │ ├── index.d.ts │ └── role.ts └── utils │ ├── api.ts │ ├── cloudinary.ts │ ├── form.ts │ ├── generateUniqueId.ts │ ├── getRelativeCoordinates.ts │ ├── github.ts │ ├── helper.ts │ └── pusher.ts ├── start-database.sh ├── tailwind.config.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # Since the ".env" file is gitignored, you can use the ".env.example" file to 2 | # build a new ".env" file when you clone the repo. Keep this file up-to-date 3 | # when you add new variables to `.env`. 4 | 5 | # This file will be committed to version control, so make sure not to have any 6 | # secrets in it. If you are cloning this repo, create a copy of this file named 7 | # ".env" and populate it with your secrets. 8 | 9 | # When adding additional environment variables, the schema in "/src/env.js" 10 | # should be updated accordingly. 11 | 12 | GOOGLE_CLIENT_ID= 13 | GOOGLE_CLIENT_SECRET= 14 | NEXTAUTH_SECRET= 15 | NEXTAUTH_URL= 16 | NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME= 17 | NEXT_PUBLIC_CLOUDINARY_API_KEY= 18 | NEXT_PUBLIC_CLOUDINARY_API_SECRET= 19 | NEXT_PUBLIC_BASE_URL= 20 | DATABASE_URL= 21 | ORGANIZATION_NAME= 22 | GITHUB_PERSONAL_ACCESS_TOKEN= 23 | 24 | PUSHER_APP_ID= 25 | PUSHER_APP_SECRET= 26 | PUSHER_APP_KEY= 27 | PUSHER_APP_CLUSTER= 28 | NEXT_PUBLIC_PUSHER_APP_KEY= 29 | NEXT_PUBLIC_PUSHER_APP_CLUSTER= -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | const config = { 3 | parser: "@typescript-eslint/parser", 4 | parserOptions: { 5 | project: true, 6 | }, 7 | plugins: ["@typescript-eslint"], 8 | extends: [ 9 | "next/core-web-vitals", 10 | "plugin:@typescript-eslint/recommended-type-checked", 11 | "plugin:@typescript-eslint/stylistic-type-checked", 12 | ], 13 | rules: { 14 | // These opinionated rules are enabled in stylistic-type-checked above. 15 | // Feel free to reconfigure them to your own preference. 16 | "@typescript-eslint/array-type": "off", 17 | "@typescript-eslint/consistent-type-definitions": "off", 18 | "@typescript-eslint/no-unsafe-call": "off", 19 | "@typescript-eslint/no-unsafe-return": "off", 20 | "@typescript-eslint/no-unsafe-member-access": "off", 21 | "@typescript-eslint/consistent-type-imports": [ 22 | "warn", 23 | { 24 | prefer: "type-imports", 25 | fixStyle: "inline-type-imports", 26 | }, 27 | ], 28 | "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], 29 | "@typescript-eslint/require-await": "off", 30 | "@typescript-eslint/no-misused-promises": [ 31 | "error", 32 | { 33 | checksVoidReturn: { attributes: false }, 34 | }, 35 | ], 36 | }, 37 | }; 38 | 39 | module.exports = config; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # database 12 | /prisma/db.sqlite 13 | /prisma/db.sqlite-journal 14 | 15 | # next.js 16 | /.next/ 17 | /out/ 18 | next-env.d.ts 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | /misc 26 | *.pem 27 | 28 | # debug 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | .pnpm-debug.log* 33 | 34 | # local env files 35 | # do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables 36 | .env 37 | .env*.local 38 | 39 | # vercel 40 | .vercel 41 | 42 | # typescript 43 | *.tsbuildinfo 44 | pnpm-lock.yaml 45 | package-lock.json 46 | 47 | recycle-bin/ 48 | 49 | *.local.ts 50 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/bun.lockb -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/styles/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "~/components", 15 | "utils": "~/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful 3 | * for Docker builds. 4 | */ 5 | await import("./src/env.js"); 6 | 7 | /** @type {import("next").NextConfig} */ 8 | const config = { 9 | reactStrictMode: false, 10 | images: { 11 | remotePatterns: [ 12 | { 13 | protocol: "https", 14 | hostname: "res.cloudinary.com", 15 | }, 16 | { 17 | protocol: "https", 18 | hostname: "lh3.googleusercontent.com", 19 | }, 20 | { 21 | protocol: "https", 22 | hostname: "res.cloudinary.com", 23 | // pathname:"/" 24 | }, 25 | { 26 | protocol: "https", 27 | hostname: "i1.sndcdn.com", 28 | // pathname:"/" 29 | }, 30 | { 31 | protocol: "https", 32 | hostname: "img.freepik.com", 33 | // pathname:"/" 34 | }, 35 | { 36 | protocol: "https", 37 | hostname: "api.github.com", 38 | }, 39 | { 40 | protocol: "https", 41 | hostname: "github.com", 42 | }, 43 | ], 44 | }, 45 | 46 | /** 47 | * If you are using `appDir` then you must comment the below `i18n` config out. 48 | * 49 | * @see https://github.com/vercel/next.js/issues/41980 50 | */ 51 | 52 | i18n: { 53 | locales: ["en"], 54 | defaultLocale: "en", 55 | }, 56 | experimental: { 57 | turbo: { 58 | resolveAlias: { 59 | canvas: "./empty-module.ts", 60 | }, 61 | }, 62 | }, 63 | }; 64 | 65 | export default config; -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: { 3 | tailwindcss: {}, 4 | }, 5 | }; 6 | 7 | module.exports = config; 8 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */ 2 | const config = { 3 | plugins: ["prettier-plugin-tailwindcss"], 4 | }; 5 | 6 | export default config; 7 | -------------------------------------------------------------------------------- /public/3D/island.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/3D/island.glb -------------------------------------------------------------------------------- /public/3D/prizePoolPillar.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/3D/prizePoolPillar.glb -------------------------------------------------------------------------------- /public/3D/trident.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/3D/trident.glb -------------------------------------------------------------------------------- /public/3D/zeusHF.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/3D/zeusHF.glb -------------------------------------------------------------------------------- /public/brochure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/brochure.pdf -------------------------------------------------------------------------------- /public/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/favicons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/favicons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/favicons/favicon.ico -------------------------------------------------------------------------------- /public/favicons/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /public/fonts/Herkules.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/fonts/Herkules.ttf -------------------------------------------------------------------------------- /public/fonts/Lagistha.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/fonts/Lagistha.ttf -------------------------------------------------------------------------------- /public/fonts/NCLNeovibes-Demo.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/fonts/NCLNeovibes-Demo.otf -------------------------------------------------------------------------------- /public/fonts/RELIGATH-Demo.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/fonts/RELIGATH-Demo.otf -------------------------------------------------------------------------------- /public/fonts/geraldine.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/fonts/geraldine.ttf -------------------------------------------------------------------------------- /public/fonts/valty.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/fonts/valty.otf -------------------------------------------------------------------------------- /public/images/Size_Chart.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/Size_Chart.jpeg -------------------------------------------------------------------------------- /public/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/bg.jpg -------------------------------------------------------------------------------- /public/images/bg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/bg1.png -------------------------------------------------------------------------------- /public/images/bg2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/bg2.jpg -------------------------------------------------------------------------------- /public/images/blue-grainy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/blue-grainy.png -------------------------------------------------------------------------------- /public/images/max.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/max.webp -------------------------------------------------------------------------------- /public/images/mid.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/mid.webp -------------------------------------------------------------------------------- /public/images/min.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/min.webp -------------------------------------------------------------------------------- /public/images/noise.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/images/sponsors/frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/sponsors/frame.png -------------------------------------------------------------------------------- /public/images/sponsors/inflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/sponsors/inflow.png -------------------------------------------------------------------------------- /public/images/sponsors/niveus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/sponsors/niveus.png -------------------------------------------------------------------------------- /public/images/sponsors/paloalto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/sponsors/paloalto.png -------------------------------------------------------------------------------- /public/images/sponsors/rakuten.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 25 | -------------------------------------------------------------------------------- /public/images/thunderbolt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/thunderbolt.png -------------------------------------------------------------------------------- /public/images/timeline_leaves.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/timeline_leaves.webp -------------------------------------------------------------------------------- /public/images/tracks/1K/Poliigon_StoneQuartzite_8060_ORM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/1K/Poliigon_StoneQuartzite_8060_ORM.png -------------------------------------------------------------------------------- /public/images/tracks/1K/marble_albedo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/1K/marble_albedo.png -------------------------------------------------------------------------------- /public/images/tracks/1K/marble_ao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/1K/marble_ao.png -------------------------------------------------------------------------------- /public/images/tracks/1K/marble_displacement.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/1K/marble_displacement.tiff -------------------------------------------------------------------------------- /public/images/tracks/1K/marble_metallic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/1K/marble_metallic.png -------------------------------------------------------------------------------- /public/images/tracks/1K/marble_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/1K/marble_normal.png -------------------------------------------------------------------------------- /public/images/tracks/1K/marble_roughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/1K/marble_roughness.png -------------------------------------------------------------------------------- /public/images/tracks/FinTech.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/FinTech.png -------------------------------------------------------------------------------- /public/images/tracks/Healthcare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/Healthcare.png -------------------------------------------------------------------------------- /public/images/tracks/Logistics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/Logistics.png -------------------------------------------------------------------------------- /public/images/tracks/OpenInnovation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/OpenInnovation.png -------------------------------------------------------------------------------- /public/images/tracks/SustainableDev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/SustainableDev.png -------------------------------------------------------------------------------- /public/images/tracks/tracks-floor/rectangle-polished-tile_albedo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/tracks-floor/rectangle-polished-tile_albedo.png -------------------------------------------------------------------------------- /public/images/tracks/tracks-floor/rectangle-polished-tile_ao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/tracks-floor/rectangle-polished-tile_ao.png -------------------------------------------------------------------------------- /public/images/tracks/tracks-floor/rectangle-polished-tile_height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/tracks-floor/rectangle-polished-tile_height.png -------------------------------------------------------------------------------- /public/images/tracks/tracks-floor/rectangle-polished-tile_metallic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/tracks-floor/rectangle-polished-tile_metallic.png -------------------------------------------------------------------------------- /public/images/tracks/tracks-floor/rectangle-polished-tile_normal-ogl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/tracks-floor/rectangle-polished-tile_normal-ogl.png -------------------------------------------------------------------------------- /public/images/tracks/tracks-floor/rectangle-polished-tile_preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/tracks-floor/rectangle-polished-tile_preview.jpg -------------------------------------------------------------------------------- /public/images/tracks/tracks-floor/rectangle-polished-tile_roughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/images/tracks/tracks-floor/rectangle-polished-tile_roughness.png -------------------------------------------------------------------------------- /public/logos/FLC Logo - Full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/logos/FLC Logo - Full.png -------------------------------------------------------------------------------- /public/logos/NMAMITLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/logos/NMAMITLogo.png -------------------------------------------------------------------------------- /public/logos/csi-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/logos/csi-logo.png -------------------------------------------------------------------------------- /public/logos/flcLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/logos/flcLogo.png -------------------------------------------------------------------------------- /public/logos/flc_logo_crop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/logos/flc_logo_crop.png -------------------------------------------------------------------------------- /public/logos/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/logos/logo.png -------------------------------------------------------------------------------- /public/logos/logoWithBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/logos/logoWithBg.png -------------------------------------------------------------------------------- /public/textures/cloudTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Finite-Loop-Club-NMAMIT/hackfest-website/1d76cee74ca6cd848a3318d88102431f90266d85/public/textures/cloudTexture.png -------------------------------------------------------------------------------- /src/components/CountdownTimer.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import Spinner from "./spinner"; 3 | import { api } from "~/utils/api"; 4 | 5 | 6 | export const CountdownTimer = () => { 7 | const { data: appSettings } = api.appSettings.getAppSettings.useQuery(); 8 | const [timeLeft, setTimeLeft] = useState("Not started"); 9 | const [elapsedTime, setElapsedTime] = useState(""); // Add state for elapsed time 10 | 11 | // Safe conversion of date string/object to Date 12 | const toSafeDate = (date: unknown): Date | null => { 13 | if (!date) return null; 14 | 15 | try { 16 | const parsedDate = new Date(date as string | number | Date); 17 | return isNaN(parsedDate.getTime()) ? null : parsedDate; 18 | } catch { 19 | return null; 20 | } 21 | }; 22 | 23 | useEffect(() => { 24 | // Type-safe access to hackfestStarted value 25 | const hackfestStartTime = toSafeDate(appSettings?.isHackfestStarted); 26 | 27 | if (!hackfestStartTime) { 28 | setTimeLeft("Not started"); 29 | setElapsedTime(""); 30 | return; 31 | } 32 | 33 | const calculateTimeLeft = () => { 34 | const endTime = new Date(hackfestStartTime.getTime() + (36 * 60 * 60 * 1000)); 35 | const now = new Date(); 36 | const difference = endTime.getTime() - now.getTime(); 37 | 38 | // Calculate elapsed time 39 | const elapsedMs = now.getTime() - hackfestStartTime.getTime(); 40 | const elapsedHours = Math.floor(elapsedMs / (1000 * 60 * 60)); 41 | const elapsedMinutes = Math.floor((elapsedMs % (1000 * 60 * 60)) / (1000 * 60)); 42 | const elapsedSeconds = Math.floor((elapsedMs % (1000 * 60)) / 1000); 43 | setElapsedTime(`${elapsedHours}h ${elapsedMinutes}m ${elapsedSeconds}s`); 44 | 45 | if (difference <= 0) { 46 | setTimeLeft("Time's up!"); 47 | return; 48 | } 49 | 50 | const hours = Math.floor(difference / (1000 * 60 * 60)); 51 | const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60)); 52 | const seconds = Math.floor((difference % (1000 * 60)) / 1000); 53 | 54 | setTimeLeft(`${hours}h ${minutes}m ${seconds}s`); 55 | }; 56 | 57 | calculateTimeLeft(); 58 | const timer = setInterval(calculateTimeLeft, 1000); 59 | 60 | return () => clearInterval(timer); 61 | }, [appSettings?.isHackfestStarted]); 62 | 63 | return ( 64 |
65 | {!appSettings ? ( 66 |
67 |
Loading...
68 | 69 |
70 | ) : ( 71 |
72 |
73 | Time Remaining 74 |
75 |
76 | {timeLeft} 77 |
78 | {appSettings?.isHackfestStarted && ( 79 |
80 | Elapsed Time : {elapsedTime} 81 |
82 | )} 83 |
84 |
85 | Hackfest Timer 86 |
87 |
88 | )} 89 |
90 | ); 91 | }; 92 | 93 | export default CountdownTimer; 94 | -------------------------------------------------------------------------------- /src/components/about2/model.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import Image from "next/image"; 3 | import { useRouter } from "next/router"; 4 | 5 | const baseWidth = { 6 | sm: 640, 7 | md: 1100, 8 | lg: 1200, 9 | }; 10 | 11 | const Slab = ({ url, width }: { url: string; width: number }) => { 12 | const router = useRouter(); 13 | 14 | return ( 15 |
16 | About Us 17 | 30 |
31 | ); 32 | }; 33 | 34 | export const AboutUs = () => { 35 | const [config, setConfig] = useState({ 36 | width: baseWidth.lg, 37 | url: "/images/about_us_max.webp", 38 | }); 39 | 40 | useEffect(() => { 41 | const handleResize = () => { 42 | if (window.innerWidth < baseWidth.sm) { 43 | setConfig({ 44 | width: baseWidth.sm, 45 | url: "/images/min.webp", 46 | }); 47 | } else if (window.innerWidth < baseWidth.md) { 48 | setConfig({ 49 | width: baseWidth.md, 50 | url: "/images/mid.webp", 51 | }); 52 | } else { 53 | setConfig({ 54 | width: baseWidth.lg, 55 | url: "/images/max.webp", 56 | }); 57 | } 58 | }; 59 | handleResize(); 60 | window.addEventListener("resize", handleResize); 61 | return () => window.removeEventListener("resize", handleResize); 62 | }, []); 63 | 64 | return ( 65 |
66 |

67 | About 68 |

69 | 70 |
71 | ); 72 | }; 73 | -------------------------------------------------------------------------------- /src/components/accordion/index.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Accordion, 3 | AccordionContent, 4 | AccordionItem, 5 | AccordionTrigger, 6 | } from "../ui/accordion"; 7 | import Link from "next/link"; 8 | 9 | type FAQ = { question: string; answer: string }[]; 10 | function Accordian({ faqs }: { faqs: FAQ }) { 11 | return ( 12 |
13 | 14 | {faqs.map((faq, index) => ( 15 | 20 | 21 | {faq.question} 22 | 23 | 24 | {faq.answer} 25 | 26 | 27 | ))} 28 | 29 |
30 | ); 31 | } 32 | 33 | const faqs: FAQ = [ 34 | { 35 | question: "What is the registration charge?", 36 | answer: 37 | "The registration fee is ₹350/member which has to be paid after selection.", 38 | }, 39 | { 40 | question: "Will the be accomodation provided?", 41 | answer: "Yes, basic accomodation will be provided.", 42 | }, 43 | { 44 | question: "Will travel expensed be covered?", 45 | answer: "No, travel expenses will not be covered.", 46 | }, 47 | ]; 48 | export default function FAQSection() { 49 | return ( 50 |
51 |

52 | FAQ 53 |

54 | 55 | 56 | 57 | {/* Contact Card */} 58 |
59 |

60 | Have additional questions or facing any issues? 61 |

62 | 66 | Contact Us 67 | 68 |
69 |
70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /src/components/admin/teamDetails/index.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | import type { IdeaSubmission, Team, User } from "@prisma/client"; 3 | import { useState } from "react"; 4 | 5 | export default function TeamsList({ 6 | teams, 7 | }: { 8 | teams: { teamName: string; id: string }[] | undefined; 9 | }) { 10 | const [teamDetails, setTeamDetails] = useState< 11 | | (Team & { members: User[] } & { ideaSubmission: IdeaSubmission | null }) 12 | | null 13 | >(null); 14 | const handleTeamDetails = async (_teamId: string) => { 15 | // setTeamDetails(await getTeamDetailsById(_teamId)); 16 | }; 17 | return ( 18 | <> 19 |

Team Details

20 |
21 |
22 |

Teams

23 | {teams?.map((team) => { 24 | return ( 25 | 36 | ); 37 | })} 38 |
39 |
40 | {teamDetails ? ( 41 | <> 42 |

43 | Team Name: {teamDetails?.name} 44 |

45 |
46 |
47 |

Track: {teamDetails?.ideaSubmission?.track}

48 | 52 | View PPT 53 | 54 |
55 |
56 |
57 |

Members

58 | {teamDetails?.members.map((member, index) => { 59 | return ( 60 |
61 |

{member.name}

62 |

{member.email}

63 |
64 | ); 65 | })} 66 |
67 |
68 |

Team status

69 |

70 | Completed: {teamDetails?.isComplete} 71 |

72 |

73 | Idea Submitted:{" "} 74 | {teamDetails?.ideaSubmission?.pptUrl ? "Yes" : "No"} 75 |

76 |
77 |
78 |
79 | 80 | ) : ( 81 |

No Team Selected

82 | )} 83 |
84 |
85 | 86 | ); 87 | } 88 | -------------------------------------------------------------------------------- /src/components/appSettingValidator/index.tsx: -------------------------------------------------------------------------------- 1 | import { type inferRouterOutputs } from "@trpc/server"; 2 | import React, { createContext, useContext } from "react"; 3 | import { type appSettingsRouter } from "~/server/api/routers/app"; 4 | import { api } from "~/utils/api"; 5 | 6 | const AppSettingValidator = createContext<{ 7 | open: boolean; 8 | settings: inferRouterOutputs["getAppSettings"] | null; 9 | }>({ 10 | open: true, 11 | settings: null, 12 | }); 13 | 14 | function Provider({ 15 | value, 16 | children, 17 | }: { 18 | value?: boolean; 19 | children: React.ReactNode; 20 | }) { 21 | const settings = api.appSettings.getAppSettings.useQuery(); 22 | 23 | return ( 24 | 28 | {children} 29 | 30 | ); 31 | } 32 | 33 | function Active({ children }: { children: React.ReactNode }) { 34 | const ctx = useContext(AppSettingValidator); 35 | 36 | if (ctx.open) { 37 | return <>{children}; 38 | } 39 | return <>; 40 | } 41 | 42 | function FallBack({ children }: { children: React.ReactNode }) { 43 | const ctx = useContext(AppSettingValidator); 44 | 45 | if (!ctx.open) { 46 | return <>{children}; 47 | } else { 48 | return <>; 49 | } 50 | } 51 | 52 | export { AppSettingValidator as context, Provider, Active, FallBack }; -------------------------------------------------------------------------------- /src/components/chat/chatButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { MessageCircle } from 'lucide-react'; 4 | import { Button } from '~/components/ui/button'; 5 | 6 | export default function ChatButton() { 7 | 8 | return ( 9 |
10 | 22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/components/chat/chatWindow.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useSearchParams } from "next/navigation"; 3 | 4 | import NoRoom from "./noRoom"; 5 | import MessageList from "./messageList"; 6 | 7 | export default function ChatWindow() { 8 | const searchParams = useSearchParams().get("room"); 9 | 10 | if (searchParams === null) { 11 | return ; 12 | } else { 13 | return ; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/components/chat/navbar.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import React from "react"; 3 | import Link from "next/link"; 4 | 5 | import AuthButton from "../navbar/authButton"; 6 | 7 | export default function ChatNavbar() { 8 | return ( 9 |
10 | 11 | Hackfest Logo 18 | 19 | 20 |

Profile

21 | 22 | 23 |
24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /src/components/chat/noRoom.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useRouter } from 'next/router' 3 | 4 | import GradientBackground from '../layout/backgroundGradient' 5 | import { Button } from '../ui/button' 6 | 7 | export default function NoRoom() { 8 | const router = useRouter() 9 | 10 | return ( 11 | 12 |
13 |

Select a Chat to Start

14 |

Please use the chat feature responsibly and respectfully.

15 |
16 |
17 | 18 | 19 |
20 |
21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /src/components/dashboard/JuryTab.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import CriteriaTab from "./CriteriaTab"; 3 | import RemarksTab from "./RemarksTab"; 4 | import ScoreTab from "./ScoreTab"; 5 | 6 | export default function JuryTab() { 7 | const [activeSubTab, setActiveSubTab] = useState("criteria"); 8 | 9 | // Initialize from localStorage 10 | useEffect(() => { 11 | if (typeof window !== "undefined") { 12 | const storedTab = localStorage.getItem("jurySubTab"); 13 | if (storedTab && ["criteria", "remarks", "score"].includes(storedTab)) { 14 | setActiveSubTab(storedTab); 15 | } 16 | } 17 | }, []); 18 | 19 | // Save to localStorage when changed 20 | useEffect(() => { 21 | if (typeof window !== "undefined") { 22 | localStorage.setItem("jurySubTab", activeSubTab); 23 | } 24 | }, [activeSubTab]); 25 | 26 | return ( 27 |
28 | {/* Sub-tab Navigation */} 29 |
30 | 40 | 50 | 60 |
61 | 62 | {/* Sub-tab Content */} 63 | {activeSubTab === "criteria" && } 64 | {activeSubTab === "remarks" && } 65 | {activeSubTab === "score" && } 66 |
67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /src/components/dashboard/RolesTab.tsx: -------------------------------------------------------------------------------- 1 | import JudgePanel from "~/components/organiserDashboard/judgePanel"; 2 | import VolunteerPanel from "~/components/organiserDashboard/volunteerPanel"; 3 | import { type User } from "@prisma/client"; 4 | import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; 5 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs"; 6 | import { ResultsVisibilityToggle } from "~/components/ResultsVisibilityToggle"; 7 | 8 | interface RolesTabProps { 9 | users: User[] | undefined; 10 | } 11 | 12 | export default function RolesTab({ users }: RolesTabProps) { 13 | return ( 14 |
15 | 16 | 17 | Roles Management 18 | 19 | 20 | 21 | 22 | Judges 23 | Volunteers 24 | Settings 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |

Application Settings

47 | 48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /src/components/dashboard/TeamsTab.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | import { useState, useEffect } from "react"; 3 | import { api } from "~/utils/api"; 4 | import ParticipantsTable from "~/components/participantsTable"; 5 | import Spinner from "~/components/spinner"; 6 | import FilterSheet from "~/components/organiserDashboard/filterSheet"; 7 | import GithubSheet from "~/components/organiserDashboard/githubSheet"; 8 | import TeamLeaderboard from "./TeamLeaderboard"; 9 | 10 | export default function TeamsTab() { 11 | const res = api.team.getTeamsList.useQuery(); 12 | const top15 = api.team.top15.useQuery().data; 13 | const allTeams = res.data; 14 | const [selectedTeams, setSelectedTeams] = useState(top15); 15 | const [searchQuery, setSearchQuery] = useState(""); 16 | const [paymentQuery, setPaymentQuery] = useState("ALL"); 17 | const [top60Query, setTop60Query] = useState("TOP 60"); 18 | const [submissionQuery, setSubmissionQuery] = useState("ALL"); 19 | const [trackQuery, setTrackQuery] = useState("ALL"); 20 | 21 | const filterSheetProps = { 22 | searchQuery, paymentQuery, top60Query, submissionQuery, trackQuery, 23 | setSearchQuery, setPaymentQuery, setTop60Query, setSubmissionQuery, setTrackQuery, 24 | }; 25 | 26 | useEffect(() => { 27 | // ...existing filter effect code... 28 | }, [res.data, searchQuery, paymentQuery, top60Query, submissionQuery, trackQuery, allTeams]); 29 | 30 | return ( 31 |
32 |
33 |

Teams and Members

34 |
35 |
36 |
37 | 38 |
39 | {!res ? ( 40 | 41 | ) : ( 42 | // 43 | 44 | )} 45 |
46 |
47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /src/components/errorScreen.tsx: -------------------------------------------------------------------------------- 1 | import { Text } from "@react-three/drei"; 2 | import { useLoader } from "@react-three/fiber"; 3 | import { TextureLoader } from "three"; 4 | 5 | const ErrorScreen = () => { 6 | const texture = useLoader(TextureLoader, "/logos/logo.png"); 7 | 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 21 | Couldn't Load Timeline 22 | 23 | 30 | Please check your connection and try again 31 | 32 | 33 | ); 34 | }; 35 | 36 | export default ErrorScreen; 37 | -------------------------------------------------------------------------------- /src/components/forms/createCollege/states.ts: -------------------------------------------------------------------------------- 1 | import { States } from "@prisma/client"; 2 | 3 | export const states = [ 4 | { 5 | name: "Andhra Pradesh", 6 | key: States.ANDHRA_PRADESH, 7 | }, 8 | { 9 | name: "Arunachal Pradesh", 10 | key: States.ARUNACHAL_PRADESH, 11 | }, 12 | { 13 | name: "Assam", 14 | key: States.ASSAM, 15 | }, 16 | { 17 | name: "Bihar", 18 | key: States.BIHAR, 19 | }, 20 | { 21 | name: "Chhattisgarh", 22 | key: States.CHHATTISGARH, 23 | }, 24 | { 25 | name: "Goa", 26 | key: States.GOA, 27 | }, 28 | { 29 | name: "Gujarat", 30 | key: States.GUJARAT, 31 | }, 32 | { 33 | name: "Harayana", 34 | key: States.HARYANA, 35 | }, 36 | { 37 | name: "Himachal Pradesh", 38 | key: States.HIMACHAL_PRADESH, 39 | }, 40 | { 41 | name: "Jharkhand", 42 | key: States.JHARKHAND, 43 | }, 44 | { 45 | name: "Karnataka", 46 | key: States.KARNATAKA, 47 | }, 48 | { 49 | name: "Kerala", 50 | key: States.KERALA, 51 | }, 52 | { 53 | name: "Madhya Pradesh", 54 | key: States.MADHYA_PRADESH, 55 | }, 56 | { 57 | name: "Maharashtra", 58 | key: States.MAHARASHTRA, 59 | }, 60 | { 61 | name: "Manipur", 62 | key: States.MANIPUR, 63 | }, 64 | { 65 | name: "Meghalaya", 66 | key: States.MEGHALAYA, 67 | }, 68 | { 69 | name: "Mizoram", 70 | key: States.MIZORAM, 71 | }, 72 | { 73 | name: "Nagaland", 74 | key: States.NAGALAND, 75 | }, 76 | { 77 | name: "Odisha", 78 | key: States.ODISHA, 79 | }, 80 | { 81 | name: "Punjab", 82 | key: States.PUNJAB, 83 | }, 84 | { 85 | name: "Rajasthan", 86 | key: States.RAJASTHAN, 87 | }, 88 | { 89 | name: "Sikkim", 90 | key: States.SIKKIM, 91 | }, 92 | { 93 | name: "Tamil Nadu", 94 | key: States.TAMIL_NADU, 95 | }, 96 | { 97 | name: "Telangana", 98 | key: States.TELANGANA, 99 | }, 100 | { 101 | name: "Tripura", 102 | key: States.TRIPURA, 103 | }, 104 | { 105 | name: "Uttarakhand", 106 | key: States.UTTARAKHAND, 107 | }, 108 | { 109 | name: "Uttar Pradesh", 110 | key: States.UTTAR_PRADESH, 111 | }, 112 | { 113 | name: "West Bengal", 114 | key: States.WEST_BENGAL, 115 | }, 116 | { 117 | name: "Andaman and Nicobar Islands", 118 | key: States.ANDAMAN_NICOBAR, 119 | }, 120 | { 121 | name: "Chandigarh", 122 | key: States.CHANDIGARH, 123 | }, 124 | { 125 | name: "Dadra and Nagar Haveli and Daman and Diu", 126 | key: States.DADRA_NAGAR_HAVELI_DAMAN_DIU, 127 | }, 128 | { 129 | name: "Delhi", 130 | key: States.DELHI, 131 | }, 132 | { 133 | name: "Jammu and Kashmir", 134 | key: States.JAMMU_KASHMIR, 135 | }, 136 | { 137 | name: "Ladakh", 138 | key: States.LADAKH, 139 | }, 140 | { 141 | name: "Lakshadweep", 142 | key: States.LAKSHADWEEP, 143 | }, 144 | { 145 | name: "Puducherry", 146 | key: States.PUDUCHERRY, 147 | }, 148 | ]; 149 | -------------------------------------------------------------------------------- /src/components/forms/teamInfo/index.tsx: -------------------------------------------------------------------------------- 1 | import { type Progress } from "@prisma/client"; 2 | import { Loader2Icon } from "lucide-react"; 3 | import { useContext } from "react"; 4 | import { ProgressContext } from "~/components/progressProvider"; 5 | import { Card } from "~/components/ui/card"; 6 | import { api } from "~/utils/api"; 7 | import TeamInfo from "./teamInfo"; 8 | 9 | export default function TeamDetails({ 10 | teamid, 11 | userId, 12 | userProgress, 13 | userRefetch, 14 | userIsLeader, 15 | }: { 16 | teamid: string; 17 | userId: string; 18 | userProgress: Progress; 19 | userRefetch: () => void; 20 | userIsLeader: boolean; 21 | }) { 22 | const teamdata = api.team.getTeamDetailsById.useQuery({ 23 | teamId: teamid, 24 | }); 25 | const { currentState } = useContext(ProgressContext); 26 | if (currentState !== 1) return null; 27 | 28 | return ( 29 | <> 30 | {currentState === 1 && teamdata.isLoading && ( 31 | 32 | Loading... 33 | 34 | 35 | )} 36 | {!teamdata.isLoading && teamdata.data && ( 37 | 45 | )} 46 | 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /src/components/hero/dustOverlay.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef } from "react"; 2 | 3 | const DustOverlay = () => { 4 | const containerRef = useRef(null); 5 | const particlesRef = useRef([]); 6 | 7 | const createParticle = () => { 8 | if (!containerRef.current) return; 9 | 10 | const particle = document.createElement("div"); 11 | particle.className = "dust-particle"; 12 | 13 | const randomX = Math.random() * 100; 14 | const size = Math.random() * 2 + 1; // Smaller size for more subtle effect 15 | const duration = Math.random() * 4 + 6; 16 | 17 | particle.style.left = `${randomX}%`; 18 | particle.style.width = `${size}px`; 19 | particle.style.height = `${size}px`; 20 | particle.style.animationDuration = `${duration}s`; 21 | 22 | containerRef.current.appendChild(particle); 23 | particlesRef.current.push(particle); 24 | 25 | setTimeout(() => { 26 | if ( 27 | containerRef.current && 28 | particle.parentElement === containerRef.current 29 | ) { 30 | containerRef.current.removeChild(particle); 31 | particlesRef.current = particlesRef.current.filter( 32 | (p) => p !== particle, 33 | ); 34 | } 35 | }, duration * 1000); 36 | }; 37 | 38 | useEffect(() => { 39 | for (let i = 0; i < 100; i++) { 40 | createParticle(); 41 | } 42 | 43 | const particleInterval = setInterval(createParticle, 50); 44 | const container = containerRef.current; 45 | 46 | return () => { 47 | clearInterval(particleInterval); 48 | // Cleanup all particles safely 49 | if (container) { 50 | particlesRef.current.forEach((particle) => { 51 | if (particle.parentElement === container) { 52 | container.removeChild(particle); 53 | } 54 | }); 55 | particlesRef.current = []; 56 | } 57 | }; 58 | }, []); 59 | 60 | return ( 61 |
74 | 97 |
98 | ); 99 | }; 100 | 101 | export default DustOverlay; 102 | -------------------------------------------------------------------------------- /src/components/hero/index.tsx: -------------------------------------------------------------------------------- 1 | import dynamic from "next/dynamic"; 2 | import ZeusBackground from "./zeusBackground"; 3 | import { Canvas } from "@react-three/fiber"; 4 | import { Suspense, useEffect, useState } from "react"; 5 | import { useProgress, Html } from "@react-three/drei"; 6 | import { lagistha } from "~/pages/_app"; 7 | // import ZeusBust from "./zeusBust"; 8 | 9 | const ZeusBust = dynamic(() => import("./zeusBust"), { ssr: false }); 10 | // const City = dynamic(() => import("./city"), { ssr: false }); 11 | 12 | const Hero = ({ 13 | onLoaded, 14 | onProgress, 15 | }: { 16 | onLoaded: () => void; 17 | onProgress: (progress: number, component: string) => void; 18 | }) => { 19 | const [maxProgress, setMaxProgress] = useState(0); 20 | const { progress, errors, loaded, total } = useProgress(); 21 | 22 | console.warn(errors); 23 | console.warn(errors); 24 | 25 | useEffect(() => { 26 | // Only update if the new progress is higher than previous max 27 | if (progress > maxProgress) { 28 | setMaxProgress(progress); 29 | } 30 | }, [progress, maxProgress]); 31 | 32 | useEffect(() => { 33 | console.log("progress from hero", maxProgress); 34 | onProgress(maxProgress, "hero"); 35 | if (maxProgress === 100 && loaded == total) { 36 | console.log("Hero fully loaded"); 37 | onLoaded(); 38 | } 39 | }, [maxProgress, loaded, onLoaded, onProgress, total]); 40 | 41 | return ( 42 |
43 | 44 | 47 |
48 | Loading... {progress.toFixed(2)}% 49 |
50 | 51 | } 52 | > 53 | 54 | 55 |
56 |
57 | 58 |
59 |

63 | {"Hackfest"} 64 |

65 |

69 | TECH OLYMPUS 70 |

71 |
72 |
73 | ); 74 | }; 75 | 76 | export default Hero; 77 | 78 | // drop-shadow-[0_15px_20px_rgba(147,238,256,0.8)] 79 | -------------------------------------------------------------------------------- /src/components/hero/zeusBust.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Float, useGLTF } from "@react-three/drei"; 3 | import { useEffect, useState } from "react"; 4 | 5 | export default function ZeusBust() { 6 | const {scene} = useGLTF("/3D/zeusHF.glb"); 7 | const [scale, setScale] = useState([2.5, 2.5, 2.5]); 8 | const [rotation, setRotation] = useState([0, 0, 0]); 9 | 10 | useEffect(() => { 11 | const handleResize = () => { 12 | if (window.innerWidth <= 768) { 13 | setScale([1.5, 1.5, 1.5]); 14 | } else { 15 | setScale([2.5, 2.5, 2.5]); 16 | } 17 | }; 18 | 19 | const handleMouseMove = (event: MouseEvent) => { 20 | const { clientX, clientY } = event; 21 | const xRotation = (clientY / window.innerHeight - 0.5) * 0.2; 22 | const yRotation = (clientX / window.innerWidth - 0.5) * 0.2; 23 | setRotation([xRotation, 0 + yRotation * 10, 0]); 24 | }; 25 | 26 | window.addEventListener("resize", handleResize); 27 | window.addEventListener("mousemove", handleMouseMove); 28 | handleResize(); 29 | 30 | return () => { 31 | window.removeEventListener("resize", handleResize); 32 | window.removeEventListener("mousemove", handleMouseMove); 33 | }; 34 | }, []); 35 | return ( 36 | <> 37 | 38 | 39 | 40 | 46 | 47 | 48 | ); 49 | } 50 | 51 | useGLTF.preload("/3D/zeusHF.glb"); -------------------------------------------------------------------------------- /src/components/judge/teamRemarks.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | export default function TeamRemarks({ 3 | teamId, 4 | judgeDay, 5 | }: { 6 | teamId: string; 7 | judgeDay: string; 8 | }) { 9 | // const remarksByTeamQuery = api.judges.getRemarksByteam.useQuery({teamId: teamId}); 10 | // return( 11 | // <> 12 | // { 13 | // remarksByTeamQuery.status === "loading" && 14 | // } 15 | // { 16 | // remarksByTeamQuery.status === "success" && remarksByTeamQuery.data.map((remark,index) => ( 17 | //
18 | // 20 | // {remark.judge.type === 'DAY1' ? 'MENTOR' : 'JUDGE'} 21 | // 22 | // 23 | // {remark.remarks} 24 | // 25 | //
26 | // )) 27 | // } 28 | // 29 | // ) 30 | return <>; 31 | } 32 | -------------------------------------------------------------------------------- /src/components/judge/tutorial.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Joyride, { type Step, EVENTS, STATUS, type CallBackProps } from 'react-joyride'; 3 | import { useTheme } from 'next-themes'; 4 | 5 | interface TutorialProps { 6 | run: boolean; 7 | steps: Step[]; 8 | onComplete: () => void; 9 | continuous?: boolean; 10 | showSkipButton?: boolean; 11 | } 12 | 13 | const Tutorial: React.FC = ({ 14 | run, 15 | steps, 16 | onComplete, 17 | continuous = true, 18 | showSkipButton = true 19 | }) => { 20 | const { theme } = useTheme(); 21 | 22 | const handleCallback = (data: CallBackProps) => { 23 | const { status, type } = data; 24 | 25 | // End tutorial when it's finished or skipped 26 | if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status as typeof STATUS.FINISHED | typeof STATUS.SKIPPED)) { 27 | onComplete(); 28 | } 29 | 30 | // Handle case when target element is not found 31 | if (type === EVENTS.TARGET_NOT_FOUND) { 32 | // Fix the TypeScript error by safely stringifying the target 33 | const targetStr = typeof data.step?.target === 'string' 34 | ? data.step.target 35 | : 'Non-string target'; 36 | console.log(`Target not found: ${targetStr}`); 37 | } 38 | }; 39 | 40 | return ( 41 | 76 | ); 77 | }; 78 | 79 | export default Tutorial; 80 | -------------------------------------------------------------------------------- /src/components/layout/backgroundGradient.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "~/lib/utils"; 2 | 3 | // export const GradientBackground = ({ 4 | // children, 5 | // className, 6 | // }: { 7 | // children: React.ReactNode; 8 | // className?: string; 9 | // }) => { 10 | // return
{children}
; 11 | // }; 12 | 13 | export default function GradientBackground({ 14 | children, 15 | className, 16 | }: { 17 | children: React.ReactNode; 18 | className?: string; 19 | }) { 20 | return ( 21 |
22 | {children} 23 |
24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /src/components/layout/backgroundWrapper.tsx: -------------------------------------------------------------------------------- 1 | import type { PropsWithChildren } from "react"; 2 | 3 | export const BackgroundWrapper = ({ children }: PropsWithChildren) => { 4 | return ( 5 |
6 |
15 |
16 |
17 |
{children}
18 |
19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/layout/chatLayout.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unsafe-assignment */ 2 | import { cn } from "~/lib/utils"; 3 | import ChatNavbar from "../chat/navbar"; 4 | import ChatList from "../chat/chatList"; 5 | import ChatWindow from "../chat/chatWindow"; 6 | import { Toaster } from "sonner"; 7 | import { api } from "~/utils/api"; 8 | 9 | export default function ChatLayout({ 10 | className, 11 | }: { 12 | children?: React.ReactNode; 13 | className?: string; 14 | }) { 15 | const chatRoomQuery = api.chat.getChatRoomList.useQuery(); 16 | 17 | return ( 18 |
24 | 25 | 26 |
27 | {chatRoomQuery.status === "success" && ( 28 | 32 | )} 33 |
34 | 35 |
36 |
37 | {/* {children} */} 38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /src/components/layout/dashboardLayout.tsx: -------------------------------------------------------------------------------- 1 | import { Poppins } from "next/font/google"; 2 | import { Toaster } from "sonner"; 3 | import NotFound from "../not-found"; 4 | import { useSession } from "next-auth/react"; 5 | import Image from "next/image"; 6 | import Link from "next/link"; 7 | import { HomeIcon } from "@heroicons/react/24/outline"; 8 | 9 | const poppins = Poppins({ subsets: ["latin"], weight: ["400", "700"] }); 10 | 11 | const metadata = { 12 | title: "Hackfest - Dashboard", 13 | description: "Dashboard", 14 | icons: { 15 | icon: "/favicons/favicon.ico", 16 | shortcut: "/favicons/favicon.ico", 17 | apple: "/favicons/apple-touch-icon.png", 18 | }, 19 | }; 20 | 21 | export { metadata }; 22 | 23 | export default function DashboardLayout({ 24 | children, 25 | }: { 26 | children: React.ReactNode; 27 | }) { 28 | const user = useSession(); 29 | 30 | if (user !== null) { 31 | if (user?.data?.user.role !== "PARTICIPANT") { 32 | return ( 33 |
34 | 35 |
36 |
37 | Hackfest Logo 43 |
44 | 48 | 49 | 50 |
51 |
52 | {children} 53 |
54 |
55 | ); 56 | } else { 57 | return ; 58 | } 59 | } else { 60 | return ; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/components/layout/index.tsx: -------------------------------------------------------------------------------- 1 | import { Toaster } from "sonner"; 2 | import Navbar from "../navbar"; 3 | import Footer from "../footer"; 4 | import ProgressBarProvider from "../progressBarProvider"; 5 | import { useRouter } from "next/router"; 6 | import ChatButton from "../chat/chatButton"; 7 | export default function RootLayout(props: { children: React.ReactNode }) { 8 | const router = useRouter(); 9 | 10 | return ( 11 |
14 | 15 | 16 | 17 | {props.children} 18 | 19 |
20 | 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/components/marquee/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState, useRef } from "react"; 2 | 3 | const Marquee = () => { 4 | const [position, setPosition] = useState(0); 5 | const containerRef = useRef(null); 6 | const message = "EXTENDED! SUBMIT IDEAS BY 24 MAR"; 7 | const repetitions = 20; 8 | 9 | useEffect(() => { 10 | const container = containerRef.current; 11 | if (!container) return; 12 | 13 | const interval = setInterval(() => { 14 | setPosition((prevPosition) => { 15 | const messageWidth = container.firstElementChild?.clientWidth ?? 0; 16 | if (prevPosition <= -messageWidth) { 17 | return 0; 18 | } 19 | return prevPosition - 1; 20 | }); 21 | }, 20); 22 | 23 | return () => clearInterval(interval); 24 | }, []); 25 | 26 | return ( 27 |
28 |
33 | {Array.from({ length: repetitions }).map((_, index) => ( 34 | 35 | {message} 36 | 37 | 38 | ))} 39 |
40 |
41 | ); 42 | }; 43 | 44 | export default Marquee; 45 | -------------------------------------------------------------------------------- /src/components/message/congratulationsMessage.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useRouter } from "next/router"; 3 | import { Button } from "../ui/button"; 4 | 5 | export default function CongratulationMessage() { 6 | const router = useRouter(); 7 | 8 | return ( 9 |
10 |

11 | Idea Submitted! 12 |

13 |

14 | You have already submitted your idea. We wish you to be in the top 60 15 | teams. Keep an eye on your mail for further updates. 16 |

17 |

18 | Note: Top 60 teams will be announced on 27 March 2025{" "} 19 |

20 |
21 | 26 | 27 | 28 |
29 | 37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /src/components/message/registrationsClosed.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import type { Session } from "next-auth"; 3 | import { useRouter } from "next/router"; 4 | import { Button } from "../ui/button"; 5 | 6 | export default function RegistrationClosed({ 7 | session, 8 | message = "Registrations are now closed", 9 | heading = "Too Late!", 10 | }: { 11 | session: Session; 12 | message?: string; 13 | heading?: string; 14 | }) { 15 | const router = useRouter(); 16 | 17 | return ( 18 |
19 |
20 |

21 | {heading} 22 |

23 |

24 | Sorry{" "} 25 | 26 | {session.user?.name ?? "Tech Enthusiast"} 27 | {" "} 28 | 😞 . {message}. 29 |

30 | 39 |
40 |
41 | ); 42 | } -------------------------------------------------------------------------------- /src/components/navbar/authButton.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @next/next/no-html-link-for-pages */ 2 | import { signIn, useSession } from "next-auth/react"; 3 | import Image from "next/image"; 4 | import { Button } from "../ui/button"; 5 | import { FiLogIn } from "react-icons/fi"; 6 | import { RiErrorWarningFill } from "react-icons/ri"; 7 | import { 8 | Tooltip, 9 | TooltipContent, 10 | TooltipProvider, 11 | TooltipTrigger, 12 | } from "~/components/ui/tooltip"; 13 | import { cn } from "~/lib/utils"; 14 | 15 | const AuthButton = ({ className }: { className?: string }) => { 16 | const { data: session } = useSession(); 17 | return ( 18 |
19 | {session ? ( 20 | session.user.profileProgress === "FILL_DETAILS" ? ( 21 | 22 | 25 | 26 | ) : ( 27 | <> 28 |
29 | 30 | profile 37 | 38 | {session.user.profileProgress !== "COMPLETE" && ( 39 | 40 | 41 | 42 | 43 | 44 | 45 | {session.user.profileProgress === "FORM_TEAM" && 46 | "Pending Team deatils"} 47 | {session.user.profileProgress === "SUBMIT_IDEA" && 48 | "Pending Idea submission"} 49 | 50 | 51 | 52 | )} 53 |
54 | 55 | ) 56 | ) : ( 57 | 65 | )} 66 |
67 | ); 68 | }; 69 | 70 | export default AuthButton; 71 | -------------------------------------------------------------------------------- /src/components/navbar/dashboardButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useSession } from 'next-auth/react' 3 | import { LayoutDashboard } from 'lucide-react'; 4 | import { Button } from '@headlessui/react'; 5 | 6 | const DashboardButton = () => { 7 | const { data: session } = useSession(); 8 | 9 | if (!session?.user || session.user.role === 'PARTICIPANT') { 10 | return null; 11 | } 12 | 13 | const handleNavigation = () => { 14 | window.location.href = '/dashboard'; 15 | }; 16 | 17 | return ( 18 | 21 | ); 22 | } 23 | 24 | export default DashboardButton 25 | -------------------------------------------------------------------------------- /src/components/navbar/index.tsx: -------------------------------------------------------------------------------- 1 | import AuthButtons from "./authButton"; 2 | import { navLinks } from "~/constants"; 3 | import React, { useState } from "react"; 4 | import { MenuIcon, XIcon } from "lucide-react"; 5 | import Image from "next/image"; 6 | import Link from "next/link"; 7 | import DashButtom from "./dashboardButton"; 8 | 9 | const NavBar = () => { 10 | const [isOpen, setIsOpen] = useState(false); 11 | 12 | return ( 13 |
14 | 81 |
82 | ); 83 | }; 84 | 85 | export default NavBar; 86 | -------------------------------------------------------------------------------- /src/components/not-found/index.tsx: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | import { Button } from "../ui/button"; 3 | 4 | const NotFound = () => { 5 | const router = useRouter(); 6 | return ( 7 |
10 |
11 | 12 |
13 |
14 |

15 | Oops! 16 |

17 | 18 |

19 | You have discovered a page that doesn't exist. Time to head 20 | back. 21 |

22 | 23 | 26 |
27 |
28 |
29 | ); 30 | }; 31 | 32 | export default NotFound; 33 | -------------------------------------------------------------------------------- /src/components/notLoggedIn/index.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import SignInButton from "./signInButton"; 3 | import { usePathname } from "next/navigation"; 4 | import RootLayout from "../layout"; 5 | 6 | const NotLoggedIn = () => { 7 | const pathname = usePathname(); 8 | return ( 9 | 10 |
13 |
14 | 15 | {pathname === "/register" ? ( 16 | <> 17 |
18 |
19 |
20 | Hackfest_Logo 26 |
27 |
28 |
29 |

30 | Hey coder! 31 |

32 | 👋🏻 33 |
34 |

35 | Please sign in to register for{" "} 36 | Hackfest. Happy Coding. 37 |

38 | 39 |
40 |
41 | 42 | ) : ( 43 |
44 |
45 |

46 | Oops! 47 |

48 | 49 |

50 | The Gods are dissapointed. Please sign in to continue. 51 |

52 | 53 | 54 |
55 |
56 | )} 57 |
58 | 59 | ); 60 | }; 61 | 62 | export default NotLoggedIn; 63 | -------------------------------------------------------------------------------- /src/components/notLoggedIn/signInButton.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "../ui/button"; 2 | import { signIn } from "next-auth/react"; 3 | import { FiLogIn } from "react-icons/fi"; 4 | 5 | const SignInButton = () => { 6 | return ( 7 |
8 | 15 |
16 | ); 17 | }; 18 | 19 | export default SignInButton; 20 | -------------------------------------------------------------------------------- /src/components/organiserDashboard/analytics.tsx: -------------------------------------------------------------------------------- 1 | const Analytics = () => { 2 | return ( 3 |
4 | {/* Your analytics component content */} 5 |
6 | ); 7 | }; 8 | 9 | export default Analytics; 10 | -------------------------------------------------------------------------------- /src/components/payment/success.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useRouter } from "next/router"; 3 | import { Button } from "~/components/ui/button"; 4 | 5 | export default function PaymentSuccess() { 6 | const router = useRouter(); 7 | 8 | return ( 9 |
10 |

11 | Success 12 |

13 |

14 | Your payment was successful! We look forward to seeing you during{" "} 15 | Hackfest {"'"}25 on April 18th. Thank you for your participation! 16 |

17 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/components/payment/verify.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useRouter } from "next/router"; 3 | import { Button } from "~/components/ui/button"; 4 | 5 | export default function PaymentVerification() { 6 | const router = useRouter(); 7 | 8 | return ( 9 |
10 |

11 | Verification 12 |

13 |

14 | Your Transaction ID has been submitted successfully. Please wait for the 15 | verification of the same. 16 |

17 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/components/pdf/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Document, pdfjs, Thumbnail } from "react-pdf"; 3 | 4 | pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`; 5 | 6 | export default function PdfPreview({ 7 | className, 8 | height, 9 | width, 10 | file, 11 | pages, 12 | }: { 13 | className?: string; 14 | height?: number; 15 | width?: number; 16 | file: File | string; 17 | pages: Array; 18 | }) { 19 | return ( 20 | 21 | {pages.map((page) => { 22 | return ; 23 | })} 24 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/components/profile/identityDetails.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import { type inferRouterOutputs } from "@trpc/server"; 3 | import React from "react"; 4 | import { type userRouter } from "~/server/api/routers/user"; 5 | 6 | export default function IdentityDetails({ 7 | user, 8 | order, 9 | }: { 10 | user: inferRouterOutputs["getUserDetails"]; 11 | order: number; 12 | }) { 13 | return ( 14 |
18 |

Identify Proofs

19 |
20 |
21 |
22 | {user?.aadhaar && ( 23 | aadhaar 30 | )} 31 |
32 |

Aadhaar

33 |
34 |
35 |
36 | {user?.aadhaar && ( 37 | college ID 44 | )} 45 |
46 |

College ID

47 |
48 |
49 |
50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /src/components/profile/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { type inferRouterOutputs } from "@trpc/server"; 3 | import { type userRouter } from "~/server/api/routers/user"; 4 | 5 | import PersonalDeatils from "./personalDetails"; 6 | import TeamDetails from "./teamDetails"; 7 | import IdentityDetails from "./identityDetails"; 8 | import IdeaDetails from "./ideaDetails"; 9 | 10 | interface ProfileCardProps { 11 | user: inferRouterOutputs["getUserDetails"]; 12 | order: number[]; 13 | boysDormitory?: string | null; // Expect string | null | undefined 14 | girlsDormitory?: string | null; // Expect string | null | undefined 15 | arena?: string | null; // Expect string | null | undefined 16 | teamNo?: number; // Added teamNo prop 17 | } 18 | 19 | export default function ProfileCard({ 20 | user, 21 | order, 22 | boysDormitory, 23 | girlsDormitory, 24 | arena, 25 | teamNo, 26 | }: ProfileCardProps) { 27 | return ( 28 | <> 29 | 30 | 31 | {/* Pass allocation props and teamNo to TeamDetails */} 32 | 40 | 41 | {/* Removed the Allocation Details section from here */} 42 | 43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/components/profile/logout.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from "react"; 2 | import { signOut } from "next-auth/react"; 3 | import { LogOut } from "lucide-react"; 4 | import { Button } from "../ui/button"; 5 | import { usePathname } from "next/navigation"; 6 | 7 | export const LogoutButton: FC = () => { 8 | const path = usePathname(); 9 | 10 | return ( 11 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/profile/manageAccount.tsx: -------------------------------------------------------------------------------- 1 | import { LogOut } from "lucide-react"; 2 | import { Button } from "../ui/button"; 3 | import { signOut, useSession } from "next-auth/react"; 4 | 5 | 6 | export default function ManageAccount() { 7 | const { status, data } = useSession(); 8 | 9 | 10 | return ( 11 |
12 | {/* FIXME: switch account causes error for some reason. probably token thing */} 13 | {/* */} 33 | {status === "authenticated" && 34 | data.user.profileProgress !== "FILL_DETAILS" && ( 35 |

{data?.user.name}

36 | )} 37 |
38 | {/* */} 42 | 54 |
55 |
56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /src/components/profile/personalDetails.tsx: -------------------------------------------------------------------------------- 1 | import { Building2, Github, Mail, Phone } from "lucide-react"; 2 | import React from "react"; 3 | import { Input } from "../ui/input"; 4 | import { type inferRouterOutputs } from "@trpc/server"; 5 | import { type userRouter } from "~/server/api/routers/user"; 6 | import { FaHouseFlag } from "react-icons/fa6"; 7 | 8 | export default function PersonalDeatils({ 9 | user, 10 | order, 11 | }: { 12 | user: inferRouterOutputs["getUserDetails"]; 13 | order: number; 14 | }) { 15 | return ( 16 | <> 17 |
21 |

Personal Details

22 |
23 |
24 |
25 | 26 |
27 | 32 |
33 |
34 |
35 | 36 |
37 | 42 |
43 |
44 |
45 | 46 |
47 | 52 |
53 |
54 |
55 | 56 |
57 | 62 |
63 |
64 |
65 | 66 |
67 | 72 |
73 |
74 |
75 | 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /src/components/profile/profilePhoto.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import ManageAccount from "./manageAccount"; 3 | import { type Progress } from "@prisma/client"; 4 | 5 | export default function ProfilePhoto({ 6 | image, 7 | isLeader, 8 | progress, 9 | }: { 10 | image: string; 11 | isLeader: boolean; 12 | progress: Progress; 13 | }) { 14 | if (isLeader) { 15 | return ( 16 |
17 |
18 | profile 25 | profile 32 |
33 | {progress !== "FILL_DETAILS" && } 34 |
35 | ); 36 | } else { 37 | return ( 38 |
39 |
40 | profile 47 | profile 54 |
55 | {progress !== "FILL_DETAILS" && } 56 |
57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/components/progressBar.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | interface LoaderProps { 4 | progress: number; 5 | } 6 | 7 | const ProgressBar = ({ progress }: LoaderProps) => { 8 | const baseWidth = { 9 | sm: 240, 10 | md: 320, 11 | lg: 400, 12 | }; 13 | 14 | const [width, setWidth] = useState(baseWidth.lg); 15 | 16 | useEffect(() => { 17 | const handleResize = () => { 18 | if (window.innerWidth < 640) { 19 | setWidth(baseWidth.sm); 20 | } else if (window.innerWidth < 1024) { 21 | setWidth(baseWidth.md); 22 | } else { 23 | setWidth(baseWidth.lg); 24 | } 25 | }; 26 | 27 | handleResize(); 28 | window.addEventListener("resize", handleResize); 29 | return () => window.removeEventListener("resize", handleResize); 30 | }, [baseWidth.sm, baseWidth.md, baseWidth.lg]); 31 | 32 | return ( 33 |
37 |
38 |
42 |
43 | ); 44 | }; 45 | 46 | export default ProgressBar; 47 | -------------------------------------------------------------------------------- /src/components/progressBarProvider/index.tsx: -------------------------------------------------------------------------------- 1 | import { Next13ProgressBar } from "next13-progressbar"; 2 | 3 | const ProgressBarProvider = ({ children }: { children: React.ReactNode }) => { 4 | return ( 5 | <> 6 | {children} 7 | 13 | 14 | ); 15 | }; 16 | 17 | export default ProgressBarProvider; 18 | -------------------------------------------------------------------------------- /src/components/progressProvider.tsx: -------------------------------------------------------------------------------- 1 | import { type Dispatch, type ReactNode, createContext, useState } from "react"; 2 | 3 | // const ProgrssContext = createContext({currentStep: 1, maxStep: 1, setMaxStep: () => {}, setCurrentStep: () => {}}); 4 | export const ProgressContext = createContext<{ 5 | currentState: number; 6 | maxState: number; 7 | setCurrentState: Dispatch; 8 | setMaxState: Dispatch; 9 | }>({ 10 | currentState: 1, 11 | maxState: 1, 12 | setCurrentState: () => { 13 | return; 14 | }, 15 | setMaxState: () => { 16 | return; 17 | }, 18 | }); 19 | 20 | const ProgressProvider = ({ 21 | children, 22 | initialStep, 23 | }: { 24 | children: ReactNode; 25 | initialStep: number; 26 | }) => { 27 | const [currentState, setCurrentState] = useState(initialStep); 28 | const [maxState, setMaxState] = useState(initialStep); 29 | return ( 30 | 33 | {children} 34 | 35 | ); 36 | }; 37 | 38 | export default ProgressProvider; 39 | -------------------------------------------------------------------------------- /src/components/registered/index.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import Confetti from "react-dom-confetti"; 3 | 4 | const config = { 5 | angle: 290, 6 | spread: 300, 7 | startVelocity: 40, 8 | elementCount: 50, 9 | dragFriction: 0.11, 10 | duration: 3020, 11 | stagger: 3, 12 | width: "8px", 13 | height: "14px", 14 | perspective: "503px", 15 | colors: ["#f00", "#0f0", "#00f", "#FFC700", "#FF0000", "#2E3191", "#41BBC7"], 16 | }; 17 | 18 | const Registered = () => { 19 | const [show, setShow] = useState(false); 20 | 21 | const ConfettiExplosion = () => { 22 | setShow(true); 23 | setTimeout(() => setShow(false), 1000); 24 | }; 25 | 26 | useEffect(() => { 27 | ConfettiExplosion(); 28 | }, []); 29 | 30 | return ( 31 |
32 |

33 | Done! 34 |

35 | 36 |

37 | Successfully Registered! We hope to see you on Top 60 soon. 38 |

39 |

40 | Keep an eye on your mail for further updates.{" "} 41 |

42 |
43 | ); 44 | }; 45 | 46 | export default Registered; 47 | -------------------------------------------------------------------------------- /src/components/registrationProgress/fillDetails.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; 3 | import RegisterProfileForm from "../forms/registerProfile"; 4 | 5 | export default function FillDetails() { 6 | return ( 7 | 8 | 9 | 13 | Personal Details 14 | 15 | 16 | 17 |
18 | 19 |
20 |
21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/components/registrationProgress/formTeam.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; 3 | import RegisterTeamForm from "../forms/createTeam"; 4 | 5 | export default function FormTeam() { 6 | return ( 7 | 8 | 9 | 13 | Team Details 14 | 15 | 16 | 17 |
18 | 19 |
20 |
21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/components/spinner/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { BiLoaderAlt } from "react-icons/bi"; 3 | import { cva, type VariantProps } from "class-variance-authority"; 4 | 5 | const spinnerStyles = cva( 6 | "flex h-full w-full items-center justify-center mx-auto my-auto", 7 | { 8 | variants: { 9 | size: { 10 | small: "text-2xl", 11 | medium: "text-4xl ", 12 | large: "text-6xl", 13 | }, 14 | intent: { 15 | primary: "text-primary-500", 16 | secondary: "text-secondary-500", 17 | black: "text-black", 18 | white: "text-white", 19 | }, 20 | }, 21 | defaultVariants: { 22 | size: "medium", 23 | intent: "primary", 24 | }, 25 | }, 26 | ); 27 | 28 | export interface Props extends VariantProps { 29 | className?: string; 30 | } 31 | 32 | const Spinner = ({ size, intent, className }: Props) => { 33 | return ( 34 |
35 | 36 |
37 | ); 38 | }; 39 | 40 | export default Spinner; 41 | -------------------------------------------------------------------------------- /src/components/spinner/thunderSpinner.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react"; 2 | import { cn } from "~/lib/utils"; 3 | import RootLayout from "../layout"; 4 | import Image from "next/image"; 5 | import { useGSAP } from "@gsap/react"; 6 | import { gsap } from "gsap"; 7 | 8 | export default function TridentSpinner({ className, message = "is fetching your details" }: { className?: string; message?: string }) { 9 | const image = useRef(null); 10 | 11 | useGSAP(() => { 12 | if(image?.current){ 13 | const tl = gsap.timeline({repeat: -1}); 14 | tl.fromTo(image.current, {y: -100, opacity: 0}, {y: 0, opacity: 1, duration: 0.5, ease: "power1.out"}) 15 | .to(image.current, {y: -20, duration: 0.1, ease: "power1.in"}) 16 | .to(image.current, {y: 20, duration: 0.1, ease: "power1.out"}) 17 | .to(image.current, {y: -10, duration: 0.1, ease: "power1.in"}) 18 | .to(image.current, {y: 10, duration: 0.1, ease: "power1.out"}) 19 | .to(image.current, {y: 0, duration: 0.1, ease: "power1.in"}) 20 | .to(image.current, {y: -100, opacity: 0, duration: 0.5, ease: "power1.in"}); 21 | } 22 | }) 23 | 24 | return ( 25 | 26 |
27 |
33 | loading 40 |

41 | Iris {message} 42 |

43 |
44 |
45 |
46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /src/components/sponsors/index.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | const Sponsors = () => { 4 | return ( 5 |
9 |
10 |

Presented By

11 | nmamit 18 |
19 | 20 |
21 |

Powered By

22 |
23 | paloalto 30 | inflow 36 |
37 |
38 | 39 |
40 |
41 |

Co-Powered By

42 | paloalto 48 |
49 |
50 |
51 |

Sponsored By

52 | paloalto 58 |
59 |
60 |
61 | ); 62 | }; 63 | 64 | export default Sponsors; 65 | -------------------------------------------------------------------------------- /src/components/timeline/eventObjects.tsx: -------------------------------------------------------------------------------- 1 | import { useMemo } from "react"; 2 | import * as THREE from "three"; 3 | import { Text3D } from "@react-three/drei"; 4 | import { Model } from "./island"; 5 | import { events } from "~/constants/events"; 6 | 7 | type BoxProps = { 8 | position: THREE.Vector3; 9 | rotation: THREE.Euler; 10 | }; 11 | 12 | const EventObjects = ({ linePoints }: { linePoints: THREE.Vector3[] }) => { 13 | const boxes = useMemo(() => { 14 | const positions: BoxProps[] = []; 15 | const totalPoints = linePoints.length; 16 | 17 | for (let i = 0; i < 21; i++) { 18 | const index = Math.floor((totalPoints - 1) * (i / 20)); 19 | const point = linePoints[index]; 20 | 21 | if (point) { 22 | positions.push({ 23 | position: point, 24 | rotation: new THREE.Euler( 25 | 0, 26 | Math.atan2(point.x, point.z) + Math.PI, 27 | 0, 28 | ), 29 | }); 30 | } 31 | } 32 | 33 | return positions; 34 | }, [linePoints]); 35 | 36 | const formatText = (index: number) => { 37 | const event = events[index]; 38 | if (!event) return ""; 39 | 40 | return [`Day ${event.day}`, event.time, event.title].join("\n"); 41 | }; 42 | 43 | return ( 44 | <> 45 | {boxes.map((box, index) => ( 46 | 47 | 48 | 60 | {formatText(index)} 61 | 66 | 67 | 68 | 69 | ))} 70 | 71 | ); 72 | }; 73 | 74 | export default EventObjects; 75 | -------------------------------------------------------------------------------- /src/components/timeline/helix.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | 3 | export class HelixCurve extends THREE.Curve { 4 | radius: number; 5 | pitch: number; 6 | turns: number; 7 | constructor(radius: number, pitch: number, turns: number) { 8 | super(); 9 | this.radius = radius; 10 | this.pitch = pitch; 11 | this.turns = turns; 12 | } 13 | 14 | getPoint(t: number): THREE.Vector3 { 15 | const angle = 2 * Math.PI * this.turns * t; 16 | const x = this.radius * Math.sin(angle); 17 | const y = -this.pitch * t; 18 | const z = this.radius * Math.cos(angle); 19 | return new THREE.Vector3(x, y, z); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/timeline/island.tsx: -------------------------------------------------------------------------------- 1 | import { useMemo } from "react"; 2 | import { useLoader } from "@react-three/fiber"; 3 | import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js"; 4 | import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; 5 | 6 | export function Model(props: JSX.IntrinsicElements["group"]) { 7 | const gltf = useLoader(GLTFLoader, "/3D/island.glb", (loader) => { 8 | const dracoLoader = new DRACOLoader(); 9 | dracoLoader.setDecoderPath( 10 | "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", 11 | ); 12 | loader.setDRACOLoader(dracoLoader); 13 | }); 14 | 15 | const scene = useMemo(() => { 16 | return gltf.scene.clone(); 17 | }, [gltf]); 18 | 19 | return ; 20 | } 21 | -------------------------------------------------------------------------------- /src/components/timeline/model.tsx: -------------------------------------------------------------------------------- 1 | import { useGLTF } from "@react-three/drei"; 2 | 3 | export function Model(props: JSX.IntrinsicElements["group"]) { 4 | const { scene } = useGLTF("/3D/trident.glb"); 5 | 6 | return ; 7 | } 8 | useGLTF.preload("/3D/trident.glb"); -------------------------------------------------------------------------------- /src/components/timeline/scene.tsx: -------------------------------------------------------------------------------- 1 | import { PerspectiveCamera, useScroll } from "@react-three/drei"; 2 | import { useEffect, useMemo, useRef, useState } from "react"; 3 | import * as THREE from "three"; 4 | import { Model } from "./model"; 5 | import { HelixCurve } from "./helix"; 6 | import { useFrame } from "@react-three/fiber"; 7 | import EventObjects from "./eventObjects"; 8 | 9 | const TimeLineScene = () => { 10 | const cameraRef = useRef(null); 11 | const [points, setPoints] = useState([]); 12 | cameraRef.current?.lookAt(0, 0, 18); 13 | 14 | const helixCurveRef = useRef(new HelixCurve(6.5, 30, 4)); 15 | 16 | const scroll = useScroll(); 17 | 18 | useEffect(() => { 19 | const pointsArray: THREE.Vector3[] = []; 20 | const segments = 200; // Number of segments along the curve 21 | for (let i = 0; i <= segments; i++) { 22 | const t = i / segments; 23 | const point = helixCurveRef.current.getPoint(t); 24 | if (point && point instanceof THREE.Vector3) { 25 | pointsArray.push(point); 26 | } 27 | } 28 | setPoints(pointsArray); 29 | }, []); 30 | 31 | const curve = useMemo(() => { 32 | if (points && points.length > 1) { 33 | return new THREE.CatmullRomCurve3(points, false, "catmullrom", 0.5); 34 | } 35 | return new THREE.CatmullRomCurve3([], false, "catmullrom", 0.5); // Default empty curve if points are not set 36 | }, [points]); 37 | 38 | const linePoints = useMemo(() => { 39 | return points.length > 0 ? curve.getPoints(30000) : []; 40 | }, [curve, points]); 41 | 42 | 43 | const easedScrollRef = useRef(0); 44 | 45 | useFrame((_state) => { 46 | if (!linePoints.length) return; 47 | const scrollEasing = 0.92; // Adjust for different smoothing amounts 48 | easedScrollRef.current += 49 | (scroll.offset - easedScrollRef.current) * (1 - scrollEasing); 50 | const curPointIndex = Math.min( 51 | Math.round(easedScrollRef.current * linePoints.length), 52 | linePoints.length - 1, 53 | ); 54 | const curPoint = linePoints[curPointIndex]; 55 | if (!curPoint || !cameraRef.current) return; 56 | const angle = Math.atan2(curPoint.x, curPoint.z); 57 | const radius = 10.5; 58 | 59 | // Directly set camera position without interpolation 60 | if (cameraRef.current) { 61 | cameraRef.current.position.set( 62 | curPoint.x + (radius + 3) * Math.sin(angle), 63 | curPoint.y + 1, 64 | curPoint.z + (radius + 3) * Math.cos(angle), 65 | ); 66 | cameraRef.current.lookAt(0, curPoint.y + 1, 0); 67 | cameraRef.current.updateMatrix(); 68 | cameraRef.current.updateMatrixWorld(); 69 | } 70 | }); 71 | 72 | return ( 73 | <> 74 | 75 | 81 | 82 | 87 | 88 | {linePoints.length > 1 && } 89 | 90 | 91 | 92 | 93 | 94 | ); 95 | }; 96 | 97 | export default TimeLineScene; 98 | -------------------------------------------------------------------------------- /src/components/ui/accordion.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as AccordionPrimitive from "@radix-ui/react-accordion"; 3 | import { ChevronDown } from "lucide-react"; 4 | import { cn } from "~/lib/utils"; 5 | 6 | const Accordion = AccordionPrimitive.Root; 7 | 8 | const AccordionItem = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 17 | )); 18 | AccordionItem.displayName = "AccordionItem"; 19 | 20 | const AccordionTrigger = React.forwardRef< 21 | React.ElementRef, 22 | React.ComponentPropsWithoutRef 23 | >(({ className, children, ...props }, ref) => ( 24 | 25 | svg]:rotate-180", 29 | className, 30 | )} 31 | {...props} 32 | > 33 | {children} 34 | 35 | 36 | 37 | )); 38 | AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; 39 | 40 | const AccordionContent = React.forwardRef< 41 | React.ElementRef, 42 | React.ComponentPropsWithoutRef 43 | >(({ className, children, ...props }, ref) => ( 44 | 49 |
{children}
50 |
51 | )); 52 | 53 | AccordionContent.displayName = AccordionPrimitive.Content.displayName; 54 | 55 | export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; 56 | -------------------------------------------------------------------------------- /src/components/ui/avatar.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as AvatarPrimitive from "@radix-ui/react-avatar" 3 | 4 | import { cn } from "~/lib/utils" 5 | 6 | const Avatar = React.forwardRef< 7 | React.ElementRef, 8 | React.ComponentPropsWithoutRef 9 | >(({ className, ...props }, ref) => ( 10 | 18 | )) 19 | Avatar.displayName = AvatarPrimitive.Root.displayName 20 | 21 | const AvatarImage = React.forwardRef< 22 | React.ElementRef, 23 | React.ComponentPropsWithoutRef 24 | >(({ className, ...props }, ref) => ( 25 | 30 | )) 31 | AvatarImage.displayName = AvatarPrimitive.Image.displayName 32 | 33 | const AvatarFallback = React.forwardRef< 34 | React.ElementRef, 35 | React.ComponentPropsWithoutRef 36 | >(({ className, ...props }, ref) => ( 37 | 45 | )) 46 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName 47 | 48 | export { Avatar, AvatarImage, AvatarFallback } 49 | -------------------------------------------------------------------------------- /src/components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { cva, type VariantProps } from "class-variance-authority" 3 | import { cn } from "~/lib/utils" 4 | 5 | const badgeVariants = cva( 6 | "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", 7 | { 8 | variants: { 9 | variant: { 10 | default: 11 | "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", 12 | secondary: 13 | "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", 14 | destructive: 15 | "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", 16 | outline: "text-foreground", 17 | success: 18 | "border-transparent bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300", 19 | warning: 20 | "border-transparent bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300", 21 | }, 22 | }, 23 | defaultVariants: { 24 | variant: "default", 25 | }, 26 | } 27 | ) 28 | 29 | export interface BadgeProps 30 | extends React.HTMLAttributes, 31 | VariantProps {} 32 | 33 | function Badge({ className, variant, ...props }: BadgeProps) { 34 | return ( 35 |
36 | ) 37 | } 38 | 39 | export { Badge, badgeVariants } 40 | -------------------------------------------------------------------------------- /src/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Slot } from "@radix-ui/react-slot"; 3 | import { cva, type VariantProps } from "class-variance-authority"; 4 | 5 | import { cn } from "~/lib/utils"; 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", 9 | { 10 | variants: { 11 | variant: { 12 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 13 | destructive: 14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90", 15 | outline: 16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 17 | secondary: 18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 | ghost: "hover:bg-accent hover:text-accent-foreground", 20 | link: "text-primary underline-offset-4 hover:underline", 21 | }, 22 | size: { 23 | default: "h-10 px-4 py-2", 24 | sm: "h-9 rounded-md px-3", 25 | lg: "h-11 rounded-md px-8", 26 | icon: "h-10 w-10", 27 | }, 28 | }, 29 | defaultVariants: { 30 | variant: "default", 31 | size: "default", 32 | }, 33 | }, 34 | ); 35 | 36 | export interface ButtonProps 37 | extends React.ButtonHTMLAttributes, 38 | VariantProps { 39 | asChild?: boolean; 40 | } 41 | 42 | const Button = React.forwardRef( 43 | ({ className, variant, size, asChild = false, ...props }, ref) => { 44 | const Comp = asChild ? Slot : "button"; 45 | return ( 46 | 51 | ); 52 | }, 53 | ); 54 | Button.displayName = "Button"; 55 | 56 | export { Button, buttonVariants }; 57 | -------------------------------------------------------------------------------- /src/components/ui/button/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Slot } from "@radix-ui/react-slot"; 3 | import { cva, type VariantProps } from "class-variance-authority"; 4 | 5 | import { cn } from "~/lib/utils"; 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", 9 | { 10 | variants: { 11 | variant: { 12 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 13 | destructive: 14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90", 15 | outline: 16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 17 | secondary: 18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 | ghost: "hover:bg-accent hover:text-accent-foreground", 20 | link: "text-primary underline-offset-4 hover:underline", 21 | }, 22 | size: { 23 | default: "h-10 px-4 py-2", 24 | sm: "h-9 rounded-md px-3", 25 | lg: "h-11 rounded-md px-8", 26 | icon: "h-10 w-10", 27 | }, 28 | }, 29 | defaultVariants: { 30 | variant: "default", 31 | size: "default", 32 | }, 33 | }, 34 | ); 35 | 36 | export interface ButtonProps 37 | extends React.ButtonHTMLAttributes, 38 | VariantProps { 39 | asChild?: boolean; 40 | } 41 | 42 | const Button = React.forwardRef( 43 | ({ className, variant, size, asChild = false, ...props }, ref) => { 44 | const Comp = asChild ? Slot : "button"; 45 | return ( 46 | 51 | ); 52 | }, 53 | ); 54 | Button.displayName = "Button"; 55 | 56 | export { Button, buttonVariants }; 57 | -------------------------------------------------------------------------------- /src/components/ui/card/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "~/lib/utils"; 4 | 5 | const Card = React.forwardRef< 6 | HTMLDivElement, 7 | React.HTMLAttributes 8 | >(({ className, ...props }, ref) => ( 9 |
17 | )); 18 | Card.displayName = "Card"; 19 | 20 | const CardHeader = React.forwardRef< 21 | HTMLDivElement, 22 | React.HTMLAttributes 23 | >(({ className, ...props }, ref) => ( 24 |
29 | )); 30 | CardHeader.displayName = "CardHeader"; 31 | 32 | const CardTitle = React.forwardRef< 33 | HTMLParagraphElement, 34 | React.HTMLAttributes 35 | >(({ className, ...props }, ref) => ( 36 |

44 | )); 45 | CardTitle.displayName = "CardTitle"; 46 | 47 | const CardDescription = React.forwardRef< 48 | HTMLParagraphElement, 49 | React.HTMLAttributes 50 | >(({ className, ...props }, ref) => ( 51 |

56 | )); 57 | CardDescription.displayName = "CardDescription"; 58 | 59 | const CardContent = React.forwardRef< 60 | HTMLDivElement, 61 | React.HTMLAttributes 62 | >(({ className, ...props }, ref) => ( 63 |

64 | )); 65 | CardContent.displayName = "CardContent"; 66 | 67 | const CardFooter = React.forwardRef< 68 | HTMLDivElement, 69 | React.HTMLAttributes 70 | >(({ className, ...props }, ref) => ( 71 |
76 | )); 77 | CardFooter.displayName = "CardFooter"; 78 | 79 | export { 80 | Card, 81 | CardHeader, 82 | CardFooter, 83 | CardTitle, 84 | CardDescription, 85 | CardContent, 86 | }; 87 | -------------------------------------------------------------------------------- /src/components/ui/checkbox.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox" 5 | import { Check } from "lucide-react" 6 | 7 | import { cn } from "~/lib/utils" 8 | 9 | const Checkbox = React.forwardRef< 10 | React.ElementRef, 11 | React.ComponentPropsWithoutRef 12 | >(({ className, ...props }, ref) => ( 13 | 21 | 24 | 25 | 26 | 27 | )) 28 | Checkbox.displayName = CheckboxPrimitive.Root.displayName 29 | 30 | export { Checkbox } 31 | 32 | export function useCheckbox() { 33 | const [checked, setChecked] = React.useState(false) 34 | const checkboxRef = React.useRef(null) 35 | 36 | const toggle = () => { 37 | const checkbox = checkboxRef.current! 38 | checkbox.click() 39 | setChecked(checkbox.getAttribute("data-state") === "checked") 40 | } 41 | 42 | return { 43 | checked, 44 | checkboxRef, 45 | toggle, 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/components/ui/dragDrop.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import React, { useRef, useState } from "react"; 3 | import { RiImageAddLine } from "react-icons/ri"; 4 | 5 | export default function DragAndDropFile({ 6 | text, 7 | accept, 8 | onChange, 9 | }: { 10 | text?: string; 11 | accept?: string; 12 | onChange?: (file: File) => void; 13 | }) { 14 | const inputRef = useRef(null); 15 | const [fileUrl, setFileUrl] = useState(null); 16 | const [file, setFile] = useState(null); 17 | 18 | return ( 19 | <> 20 |
{ 23 | e.preventDefault(); 24 | e.stopPropagation(); 25 | }} 26 | onDrop={(e) => { 27 | e.preventDefault(); 28 | if (e.dataTransfer.files.length > 0) { 29 | const file = e.dataTransfer.files[0]; 30 | if (file && onChange) { 31 | onChange(file); 32 | setFile(file); 33 | setFileUrl(URL.createObjectURL(file)); 34 | } 35 | } 36 | }} 37 | onClick={() => { 38 | if (inputRef.current) { 39 | inputRef.current.click(); 40 | } 41 | }} 42 | > 43 | {fileUrl ? ( 44 |
45 |
46 | Preview 53 |
54 | {file !== null ? ( 55 |
56 | {text}:{" "} 57 |

{file.name}

58 |
59 | ) : ( 60 |

61 | {text}: file 62 |

63 | )} 64 |
65 | ) : ( 66 | <> 67 | {accept === "image/*" && } 68 |

74 | 75 | )} 76 |

77 | { 83 | const file = e.target.files?.[0]; 84 | if (file && onChange) { 85 | onChange(file); 86 | setFile(file); 87 | setFileUrl(URL.createObjectURL(file)); 88 | } 89 | }} 90 | /> 91 | 92 | ); 93 | } 94 | -------------------------------------------------------------------------------- /src/components/ui/input/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "~/lib/utils"; 4 | 5 | export type InputProps = React.InputHTMLAttributes; 6 | 7 | const Input = React.forwardRef( 8 | ({ className, type, ...props }, ref) => { 9 | return ( 10 | 19 | ); 20 | }, 21 | ); 22 | Input.displayName = "Input"; 23 | 24 | export { Input }; 25 | -------------------------------------------------------------------------------- /src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as LabelPrimitive from "@radix-ui/react-label" 5 | import { cva, type VariantProps } from "class-variance-authority" 6 | 7 | import { cn } from "~/lib/utils" 8 | 9 | const labelVariants = cva( 10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 11 | ) 12 | 13 | const Label = React.forwardRef< 14 | React.ElementRef, 15 | React.ComponentPropsWithoutRef & 16 | VariantProps 17 | >(({ className, ...props }, ref) => ( 18 | 23 | )) 24 | Label.displayName = LabelPrimitive.Root.displayName 25 | 26 | export { Label } 27 | -------------------------------------------------------------------------------- /src/components/ui/label/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as LabelPrimitive from "@radix-ui/react-label"; 3 | import { cva, type VariantProps } from "class-variance-authority"; 4 | 5 | import { cn } from "~/lib/utils"; 6 | 7 | const labelVariants = cva( 8 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", 9 | ); 10 | 11 | const Label = React.forwardRef< 12 | React.ElementRef, 13 | React.ComponentPropsWithoutRef & 14 | VariantProps 15 | >(({ className, ...props }, ref) => ( 16 | 21 | )); 22 | Label.displayName = LabelPrimitive.Root.displayName; 23 | 24 | export { Label }; 25 | -------------------------------------------------------------------------------- /src/components/ui/monochrome-buttons.tsx: -------------------------------------------------------------------------------- 1 | import { CheckIcon, XIcon } from "lucide-react"; 2 | 3 | interface MonochromeButtonProps { 4 | onClick: () => void; 5 | active: boolean; 6 | } 7 | 8 | export function TickButton({ onClick, active }: MonochromeButtonProps) { 9 | return ( 10 | 18 | ); 19 | } 20 | 21 | export function WrongButton({ onClick, active }: MonochromeButtonProps) { 22 | return ( 23 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /src/components/ui/popover/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as PopoverPrimitive from "@radix-ui/react-popover"; 3 | 4 | import { cn } from "~/lib/utils"; 5 | 6 | const Popover = PopoverPrimitive.Root; 7 | 8 | const PopoverTrigger = PopoverPrimitive.Trigger; 9 | 10 | const PopoverContent = React.forwardRef< 11 | React.ElementRef, 12 | React.ComponentPropsWithoutRef 13 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( 14 | 15 | 25 | 26 | )); 27 | PopoverContent.displayName = PopoverPrimitive.Content.displayName; 28 | 29 | export { Popover, PopoverTrigger, PopoverContent }; 30 | -------------------------------------------------------------------------------- /src/components/ui/radio-group.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"; 3 | import { Circle } from "lucide-react"; 4 | 5 | import { cn } from "~/lib/utils"; 6 | 7 | const RadioGroup = React.forwardRef< 8 | React.ElementRef, 9 | React.ComponentPropsWithoutRef 10 | >(({ className, ...props }, ref) => { 11 | return ( 12 | 17 | ); 18 | }); 19 | RadioGroup.displayName = RadioGroupPrimitive.Root.displayName; 20 | 21 | const RadioGroupItem = React.forwardRef< 22 | React.ElementRef, 23 | React.ComponentPropsWithoutRef 24 | >(({ className, ...props }, ref) => { 25 | return ( 26 | 34 | 35 | 36 | 37 | 38 | ); 39 | }); 40 | RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName; 41 | 42 | export { RadioGroup, RadioGroupItem }; 43 | -------------------------------------------------------------------------------- /src/components/ui/scroll-area.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; 3 | 4 | import { cn } from "~/lib/utils"; 5 | 6 | const ScrollArea = React.forwardRef< 7 | React.ElementRef, 8 | React.ComponentPropsWithoutRef 9 | >(({ className, children, ...props }, ref) => ( 10 | 15 | 16 | {children} 17 | 18 | 19 | 20 | 21 | )); 22 | ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName; 23 | 24 | const ScrollBar = React.forwardRef< 25 | React.ElementRef, 26 | React.ComponentPropsWithoutRef 27 | >(({ className, orientation = "vertical", ...props }, ref) => ( 28 | 41 | 42 | 43 | )); 44 | ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; 45 | 46 | export { ScrollArea, ScrollBar }; 47 | -------------------------------------------------------------------------------- /src/components/ui/sectionHeading/index.tsx: -------------------------------------------------------------------------------- 1 | export const SectionHeading: React.FC<{ 2 | title: string; 3 | classname?: string; 4 | }> = ({ title, classname }) => { 5 | return ( 6 |

12 | {title} 13 |

14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /src/components/ui/separator.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import { cn } from "~/lib/utils" 5 | 6 | interface SeparatorProps extends React.HTMLAttributes { 7 | orientation?: "horizontal" | "vertical" 8 | decorative?: boolean 9 | } 10 | 11 | const Separator = React.forwardRef( 12 | ( 13 | { className, orientation = "horizontal", decorative = true, ...props }, 14 | ref 15 | ) => { 16 | const ariaProps = decorative 17 | ? { "aria-hidden": true } 18 | : { role: "separator" } 19 | 20 | return ( 21 |
31 | ) 32 | } 33 | ) 34 | Separator.displayName = "Separator" 35 | 36 | export { Separator } 37 | -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "~/lib/utils"; 2 | 3 | type SkeletonProps = React.HTMLAttributes 4 | 5 | export function Skeleton({ className, ...props }: SkeletonProps) { 6 | return ( 7 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/components/ui/table/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "~/lib/utils"; 4 | 5 | const Table = React.forwardRef< 6 | HTMLTableElement, 7 | React.HTMLAttributes 8 | >(({ className, ...props }, ref) => ( 9 |
10 | 15 | 16 | )); 17 | Table.displayName = "Table"; 18 | 19 | const TableHeader = React.forwardRef< 20 | HTMLTableSectionElement, 21 | React.HTMLAttributes 22 | >(({ className, ...props }, ref) => ( 23 | 24 | )); 25 | TableHeader.displayName = "TableHeader"; 26 | 27 | const TableBody = React.forwardRef< 28 | HTMLTableSectionElement, 29 | React.HTMLAttributes 30 | >(({ className, ...props }, ref) => ( 31 | 36 | )); 37 | TableBody.displayName = "TableBody"; 38 | 39 | const TableFooter = React.forwardRef< 40 | HTMLTableSectionElement, 41 | React.HTMLAttributes 42 | >(({ className, ...props }, ref) => ( 43 | tr]:last:border-b-0", 47 | className, 48 | )} 49 | {...props} 50 | /> 51 | )); 52 | TableFooter.displayName = "TableFooter"; 53 | 54 | const TableRow = React.forwardRef< 55 | HTMLTableRowElement, 56 | React.HTMLAttributes 57 | >(({ className, ...props }, ref) => ( 58 | 66 | )); 67 | TableRow.displayName = "TableRow"; 68 | 69 | const TableHead = React.forwardRef< 70 | HTMLTableCellElement, 71 | React.ThHTMLAttributes 72 | >(({ className, ...props }, ref) => ( 73 |
81 | )); 82 | TableHead.displayName = "TableHead"; 83 | 84 | const TableCell = React.forwardRef< 85 | HTMLTableCellElement, 86 | React.TdHTMLAttributes 87 | >(({ className, ...props }, ref) => ( 88 | 93 | )); 94 | TableCell.displayName = "TableCell"; 95 | 96 | const TableCaption = React.forwardRef< 97 | HTMLTableCaptionElement, 98 | React.HTMLAttributes 99 | >(({ className, ...props }, ref) => ( 100 |
105 | )); 106 | TableCaption.displayName = "TableCaption"; 107 | 108 | export { 109 | Table, 110 | TableHeader, 111 | TableBody, 112 | TableFooter, 113 | TableHead, 114 | TableRow, 115 | TableCell, 116 | TableCaption, 117 | }; 118 | -------------------------------------------------------------------------------- /src/components/ui/tabs.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as TabsPrimitive from "@radix-ui/react-tabs" 3 | 4 | import { cn } from "~/lib/utils" 5 | 6 | const Tabs = TabsPrimitive.Root 7 | 8 | const TabsList = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 20 | )) 21 | TabsList.displayName = TabsPrimitive.List.displayName 22 | 23 | const TabsTrigger = React.forwardRef< 24 | React.ElementRef, 25 | React.ComponentPropsWithoutRef 26 | >(({ className, ...props }, ref) => ( 27 | 35 | )) 36 | TabsTrigger.displayName = TabsPrimitive.Trigger.displayName 37 | 38 | const TabsContent = React.forwardRef< 39 | React.ElementRef, 40 | React.ComponentPropsWithoutRef 41 | >(({ className, ...props }, ref) => ( 42 | 50 | )) 51 | TabsContent.displayName = TabsPrimitive.Content.displayName 52 | 53 | interface Tab { 54 | id: string; 55 | label: string; 56 | } 57 | 58 | interface DashboardTabsProps { 59 | tabs: Tab[]; 60 | activeTab: string; 61 | onTabChange: (tabId: string) => void; 62 | } 63 | 64 | export function DashboardTabs({ tabs, activeTab, onTabChange }: DashboardTabsProps) { 65 | return ( 66 |
67 | {tabs.map((tab) => ( 68 | 79 | ))} 80 |
81 | ); 82 | } 83 | 84 | export { Tabs, TabsList, TabsTrigger, TabsContent } 85 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "~/lib/utils"; 4 | 5 | export type TextareaProps = React.TextareaHTMLAttributes 6 | 7 | const Textarea = React.forwardRef( 8 | ({ className, ...props }, ref) => { 9 | return ( 10 |