├── .firebase ├── ai-mock-interview-yt-react-ts │ └── hosting │ │ ├── assets │ │ ├── img │ │ │ ├── bg.png │ │ │ ├── hero.jpg │ │ │ ├── logo │ │ │ │ ├── firebase.png │ │ │ │ ├── meet.png │ │ │ │ ├── microsoft.png │ │ │ │ ├── react.png │ │ │ │ ├── tailwindcss.png │ │ │ │ └── zoom.png │ │ │ └── office.jpg │ │ ├── index-IIY2ctNp.css │ │ ├── index-QXGEuDCU.js │ │ └── svg │ │ │ ├── logo.svg │ │ │ ├── not-found.svg │ │ │ └── vite.svg │ │ └── index.html └── hosting.LmZpcmViYXNlL2FpLW1vY2staW50ZXJ2aWV3LXl0LXJlYWN0LXRzL2hvc3Rpbmc.cache ├── .firebaserc ├── .gitignore ├── README.md ├── components.json ├── eslint.config.js ├── firebase.json ├── index.html ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public └── assets │ ├── img │ ├── bg.png │ ├── hero.jpg │ ├── logo │ │ ├── firebase.png │ │ ├── meet.png │ │ ├── microsoft.png │ │ ├── react.png │ │ ├── tailwindcss.png │ │ └── zoom.png │ └── office.jpg │ └── svg │ ├── logo.svg │ ├── not-found.svg │ └── vite.svg ├── src ├── App.tsx ├── assets │ └── react.svg ├── components │ ├── container.tsx │ ├── custom-bread-crumb.tsx │ ├── footer.tsx │ ├── form-mock-interview.tsx │ ├── generate.tsx │ ├── header.tsx │ ├── headings.tsx │ ├── logo-container.tsx │ ├── marquee-img.tsx │ ├── modal.tsx │ ├── navigation-routes.tsx │ ├── pin.tsx │ ├── profile-container.tsx │ ├── question-section.tsx │ ├── record-answer.tsx │ ├── save-modal.tsx │ ├── toggle-container.tsx │ ├── tooltip-button.tsx │ └── ui │ │ ├── accordion.tsx │ │ ├── alert.tsx │ │ ├── badge.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── dialog.tsx │ │ ├── form.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── separator.tsx │ │ ├── sheet.tsx │ │ ├── skeleton.tsx │ │ ├── sonner.tsx │ │ ├── tabs.tsx │ │ ├── textarea.tsx │ │ └── tooltip.tsx ├── config │ └── firebase.config.ts ├── handlers │ └── auth-handler.tsx ├── index.css ├── layouts │ ├── auth-layout.tsx │ ├── main-layout.tsx │ ├── protected-routes.tsx │ └── public-layout.tsx ├── lib │ ├── helpers.ts │ └── utils.ts ├── main.tsx ├── provider │ └── toast-provider.tsx ├── routes │ ├── create-edit-page.tsx │ ├── dashboard.tsx │ ├── feedback.tsx │ ├── home.tsx │ ├── loader-page.tsx │ ├── mock-interview-page.tsx │ ├── mock-load-page.tsx │ ├── sign-in.tsx │ └── sign-up.tsx ├── scripts │ └── index.ts ├── types │ └── index.ts └── vite-env.d.ts ├── tailwind.config.js ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/bg.png -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/hero.jpg -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/firebase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/firebase.png -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/meet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/meet.png -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/microsoft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/microsoft.png -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/react.png -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/tailwindcss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/tailwindcss.png -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/logo/zoom.png -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/office.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/.firebase/ai-mock-interview-yt-react-ts/hosting/assets/img/office.jpg -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/index-IIY2ctNp.css: -------------------------------------------------------------------------------- 1 | *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--background: 0 0% 100%;--foreground: 0 0% 3.9%;--card: 0 0% 100%;--card-foreground: 0 0% 3.9%;--popover: 0 0% 100%;--popover-foreground: 0 0% 3.9%;--primary: 0 0% 9%;--primary-foreground: 0 0% 98%;--secondary: 0 0% 96.1%;--secondary-foreground: 0 0% 9%;--muted: 0 0% 96.1%;--muted-foreground: 0 0% 45.1%;--accent: 0 0% 96.1%;--accent-foreground: 0 0% 9%;--destructive: 0 84.2% 60.2%;--destructive-foreground: 0 0% 98%;--border: 0 0% 89.8%;--input: 0 0% 89.8%;--ring: 0 0% 3.9%;--chart-1: 12 76% 61%;--chart-2: 173 58% 39%;--chart-3: 197 37% 24%;--chart-4: 43 74% 66%;--chart-5: 27 87% 67%;--radius: .5rem}*{border-color:hsl(var(--border))}body{background-color:hsl(var(--background));color:hsl(var(--foreground))}.text-outline{color:#fff;text-shadow:-1px -1px 0 rgba(0,0,0,.6),1px -1px 0 rgba(0,0,0,.6),-1px 1px 0 rgba(0,0,0,.6),1px 1px 0 rgba(0,0,0,.6)}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.inset-x-0{left:0;right:0}.inset-y-0{top:0;bottom:0}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.left-0{left:0}.left-4{left:1rem}.left-\[50\%\]{left:50%}.right-0{right:0}.right-4{right:1rem}.top-0{top:0}.top-4{top:1rem}.top-\[50\%\]{top:50%}.z-50{z-index:50}.col-span-1{grid-column:span 1 / span 1}.mx-12{margin-left:3rem;margin-right:3rem}.mx-auto{margin-left:auto;margin-right:auto}.my-12{margin-top:3rem;margin-bottom:3rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-6{margin-top:1.5rem;margin-bottom:1.5rem}.my-8{margin-top:2rem;margin-bottom:2rem}.-mt-3{margin-top:-.75rem}.mb-1{margin-bottom:.25rem}.mb-4{margin-bottom:1rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-24{height:6rem}.h-3{height:.75rem}.h-4{height:1rem}.h-44{height:11rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-9{height:2.25rem}.h-96{height:24rem}.h-\[1px\]{height:1px}.h-\[400px\]{height:400px}.h-\[420px\]{height:420px}.h-\[70vh\]{height:70vh}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.min-h-10{min-height:2.5rem}.min-h-24{min-height:6rem}.min-h-4{min-height:1rem}.min-h-5{min-height:1.25rem}.min-h-6{min-height:1.5rem}.min-h-96{min-height:24rem}.min-h-\[80px\]{min-height:80px}.w-10{width:2.5rem}.w-3{width:.75rem}.w-3\/4{width:75%}.w-4{width:1rem}.w-44{width:11rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-\[1px\]{width:1px}.w-full{width:100%}.w-screen{width:100vw}.min-w-10{min-width:2.5rem}.min-w-24{min-width:6rem}.min-w-4{min-width:1rem}.min-w-5{min-width:1.25rem}.min-w-6{min-width:1.5rem}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.translate-x-\[-50\%\]{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-\[-50\%\]{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-evenly{justify-content:space-evenly}.gap-1\.5{gap:.375rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-12>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(3rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(3rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:.75rem}.rounded-b-lg{border-bottom-right-radius:var(--radius);border-bottom-left-radius:var(--radius)}.rounded-t-lg{border-top-left-radius:var(--radius);border-top-right-radius:var(--radius)}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-destructive\/50{border-color:hsl(var(--destructive) / .5)}.border-input{border-color:hsl(var(--input))}.border-sky-200{--tw-border-opacity: 1;border-color:rgb(186 230 253 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-yellow-200{--tw-border-opacity: 1;border-color:rgb(254 240 138 / var(--tw-border-opacity, 1))}.bg-background{background-color:hsl(var(--background))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\/80{background-color:#000c}.bg-border{background-color:hsl(var(--border))}.bg-card{background-color:hsl(var(--card))}.bg-destructive{background-color:hsl(var(--destructive))}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-muted{background-color:hsl(var(--muted))}.bg-neutral-100{--tw-bg-opacity: 1;background-color:rgb(245 245 245 / var(--tw-bg-opacity, 1))}.bg-popover{background-color:hsl(var(--popover))}.bg-primary{background-color:hsl(var(--primary))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-secondary{background-color:hsl(var(--secondary))}.bg-sky-100{--tw-bg-opacity: 1;background-color:rgb(224 242 254 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/40{background-color:#fff6}.bg-white\/60{background-color:#fff9}.bg-yellow-100\/50{background-color:#fef9c380}.bg-yellow-50{--tw-bg-opacity: 1;background-color:rgb(254 252 232 / var(--tw-bg-opacity, 1))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-purple-50{--tw-gradient-from: #faf5ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(250 245 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-blue-50{--tw-gradient-to: #eff6ff var(--tw-gradient-to-position)}.to-gray-700{--tw-gradient-to: #374151 var(--tw-gradient-to-position)}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-24{padding-bottom:6rem}.pb-4{padding-bottom:1rem}.pt-0{padding-top:0}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[12px\]{font-size:12px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-card-foreground{color:hsl(var(--card-foreground))}.text-destructive{color:hsl(var(--destructive))}.text-destructive-foreground{color:hsl(var(--destructive-foreground))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-emerald-500{--tw-text-opacity: 1;color:rgb(16 185 129 / var(--tw-text-opacity, 1))}.text-foreground{color:hsl(var(--foreground))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-50{--tw-text-opacity: 1;color:rgb(249 250 251 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-muted-foreground{color:hsl(var(--muted-foreground))}.text-neutral-400{--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.text-neutral-500{--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.text-neutral-600{--tw-text-opacity: 1;color:rgb(82 82 82 / var(--tw-text-opacity, 1))}.text-neutral-800{--tw-text-opacity: 1;color:rgb(38 38 38 / var(--tw-text-opacity, 1))}.text-neutral-900{--tw-text-opacity: 1;color:rgb(23 23 23 / var(--tw-text-opacity, 1))}.text-pink-500{--tw-text-opacity: 1;color:rgb(236 72 153 / var(--tw-text-opacity, 1))}.text-popover-foreground{color:hsl(var(--popover-foreground))}.text-primary{color:hsl(var(--primary))}.text-primary-foreground{color:hsl(var(--primary-foreground))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-secondary-foreground{color:hsl(var(--secondary-foreground))}.text-sky-600{--tw-text-opacity: 1;color:rgb(2 132 199 / var(--tw-text-opacity, 1))}.text-sky-700{--tw-text-opacity: 1;color:rgb(3 105 161 / var(--tw-text-opacity, 1))}.text-sky-800{--tw-text-opacity: 1;color:rgb(7 89 133 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.text-yellow-700{--tw-text-opacity: 1;color:rgb(161 98 7 / var(--tw-text-opacity, 1))}.text-yellow-800{--tw-text-opacity: 1;color:rgb(133 77 14 / var(--tw-text-opacity, 1))}.underline-offset-4{text-underline-offset:4px}.opacity-20{opacity:.2}.opacity-70{opacity:.7}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-none{--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-gray-100{--tw-shadow-color: #f3f4f6;--tw-shadow: var(--tw-shadow-colored)}.outline{outline-style:solid}.ring-offset-background{--tw-ring-offset-color: hsl(var(--background))}.drop-shadow-md{--tw-drop-shadow: drop-shadow(0 4px 3px rgb(0 0 0 / .07)) drop-shadow(0 2px 2px rgb(0 0 0 / .06));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.grayscale{--tw-grayscale: grayscale(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur: blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.animate-in{animation-name:enter;animation-duration:.15s;--tw-enter-opacity: initial;--tw-enter-scale: initial;--tw-enter-rotate: initial;--tw-enter-translate-x: initial;--tw-enter-translate-y: initial}.fade-in-0{--tw-enter-opacity: 0}.zoom-in-95{--tw-enter-scale: .95}.duration-150{animation-duration:.15s}.duration-200{animation-duration:.2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.file\:border-0::file-selector-button{border-width:0px}.file\:bg-transparent::file-selector-button{background-color:transparent}.file\:text-sm::file-selector-button{font-size:.875rem;line-height:1.25rem}.file\:font-medium::file-selector-button{font-weight:500}.file\:text-foreground::file-selector-button{color:hsl(var(--foreground))}.placeholder\:text-muted-foreground::-moz-placeholder{color:hsl(var(--muted-foreground))}.placeholder\:text-muted-foreground::placeholder{color:hsl(var(--muted-foreground))}.hover\:border-emerald-400:hover{--tw-border-opacity: 1;border-color:rgb(52 211 153 / var(--tw-border-opacity, 1))}.hover\:bg-accent:hover{background-color:hsl(var(--accent))}.hover\:bg-destructive\/80:hover{background-color:hsl(var(--destructive) / .8)}.hover\:bg-destructive\/90:hover{background-color:hsl(var(--destructive) / .9)}.hover\:bg-emerald-50:hover{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.hover\:bg-emerald-800:hover{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-primary\/80:hover{background-color:hsl(var(--primary) / .8)}.hover\:bg-primary\/90:hover{background-color:hsl(var(--primary) / .9)}.hover\:bg-secondary\/80:hover{background-color:hsl(var(--secondary) / .8)}.hover\:text-accent-foreground:hover{color:hsl(var(--accent-foreground))}.hover\:text-emerald-500:hover{--tw-text-opacity: 1;color:rgb(16 185 129 / var(--tw-text-opacity, 1))}.hover\:text-emerald-900:hover{--tw-text-opacity: 1;color:rgb(6 78 59 / var(--tw-text-opacity, 1))}.hover\:text-foreground:hover{color:hsl(var(--foreground))}.hover\:text-gray-100:hover{--tw-text-opacity: 1;color:rgb(243 244 246 / var(--tw-text-opacity, 1))}.hover\:text-sky-500:hover{--tw-text-opacity: 1;color:rgb(14 165 233 / var(--tw-text-opacity, 1))}.hover\:text-yellow-500:hover{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:no-underline:hover{text-decoration-line:none}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-md:hover{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-ring:focus{--tw-ring-color: hsl(var(--ring))}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color: hsl(var(--ring))}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width: 2px}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group.toaster .group-\[\.toaster\]\:border-border{border-color:hsl(var(--border))}.group.toast .group-\[\.toast\]\:bg-muted{background-color:hsl(var(--muted))}.group.toast .group-\[\.toast\]\:bg-primary{background-color:hsl(var(--primary))}.group.toaster .group-\[\.toaster\]\:bg-background{background-color:hsl(var(--background))}.group.toast .group-\[\.toast\]\:text-muted-foreground{color:hsl(var(--muted-foreground))}.group.toast .group-\[\.toast\]\:text-primary-foreground{color:hsl(var(--primary-foreground))}.group.toaster .group-\[\.toaster\]\:text-foreground{color:hsl(var(--foreground))}.group.toaster .group-\[\.toaster\]\:shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.peer:disabled~.peer-disabled\:cursor-not-allowed{cursor:not-allowed}.peer:disabled~.peer-disabled\:opacity-70{opacity:.7}@keyframes accordion-up{0%{height:var(--radix-accordion-content-height)}to{height:0}}.data-\[state\=closed\]\:animate-accordion-up[data-state=closed]{animation:accordion-up .2s ease-out}@keyframes accordion-down{0%{height:0}to{height:var(--radix-accordion-content-height)}}.data-\[state\=open\]\:animate-accordion-down[data-state=open]{animation:accordion-down .2s ease-out}.data-\[state\=active\]\:bg-background[data-state=active]{background-color:hsl(var(--background))}.data-\[state\=active\]\:bg-emerald-200[data-state=active]{--tw-bg-opacity: 1;background-color:rgb(167 243 208 / var(--tw-bg-opacity, 1))}.data-\[state\=open\]\:bg-accent[data-state=open]{background-color:hsl(var(--accent))}.data-\[state\=open\]\:bg-secondary[data-state=open]{background-color:hsl(var(--secondary))}.data-\[state\=active\]\:text-foreground[data-state=active]{color:hsl(var(--foreground))}.data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:hsl(var(--muted-foreground))}.data-\[state\=active\]\:shadow-md[data-state=active]{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.data-\[state\=active\]\:shadow-sm[data-state=active]{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.data-\[state\=closed\]\:duration-300[data-state=closed]{transition-duration:.3s}.data-\[state\=open\]\:duration-500[data-state=open]{transition-duration:.5s}.data-\[state\=open\]\:animate-in[data-state=open]{animation-name:enter;animation-duration:.15s;--tw-enter-opacity: initial;--tw-enter-scale: initial;--tw-enter-rotate: initial;--tw-enter-translate-x: initial;--tw-enter-translate-y: initial}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation-name:exit;animation-duration:.15s;--tw-exit-opacity: initial;--tw-exit-scale: initial;--tw-exit-rotate: initial;--tw-exit-translate-x: initial;--tw-exit-translate-y: initial}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity: 0}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity: 0}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale: .95}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale: .95}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y: -.5rem}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x: .5rem}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x: -.5rem}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y: .5rem}.data-\[state\=closed\]\:slide-out-to-bottom[data-state=closed]{--tw-exit-translate-y: 100%}.data-\[state\=closed\]\:slide-out-to-left[data-state=closed]{--tw-exit-translate-x: -100%}.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed]{--tw-exit-translate-x: -50%}.data-\[state\=closed\]\:slide-out-to-right[data-state=closed]{--tw-exit-translate-x: 100%}.data-\[state\=closed\]\:slide-out-to-top[data-state=closed]{--tw-exit-translate-y: -100%}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y: -48%}.data-\[state\=open\]\:slide-in-from-bottom[data-state=open]{--tw-enter-translate-y: 100%}.data-\[state\=open\]\:slide-in-from-left[data-state=open]{--tw-enter-translate-x: -100%}.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open]{--tw-enter-translate-x: -50%}.data-\[state\=open\]\:slide-in-from-right[data-state=open]{--tw-enter-translate-x: 100%}.data-\[state\=open\]\:slide-in-from-top[data-state=open]{--tw-enter-translate-y: -100%}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y: -48%}.data-\[state\=closed\]\:duration-300[data-state=closed]{animation-duration:.3s}.data-\[state\=open\]\:duration-500[data-state=open]{animation-duration:.5s}.dark\:border-destructive:is(.dark *){border-color:hsl(var(--destructive))}@media (min-width: 640px){.sm\:max-w-sm{max-width:24rem}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}.sm\:gap-2\.5{gap:.625rem}.sm\:space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.sm\:rounded-lg{border-radius:var(--radius)}.sm\:text-left{text-align:left}}@media (min-width: 768px){.md\:col-span-2{grid-column:span 2 / span 2}.md\:col-span-3{grid-column:span 3 / span 3}.md\:block{display:block}.md\:flex{display:flex}.md\:grid{display:grid}.md\:hidden{display:none}.md\:h-32{height:8rem}.md\:w-96{width:24rem}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:items-center{align-items:center}.md\:justify-end{justify-content:flex-end}.md\:px-12{padding-left:3rem;padding-right:3rem}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:py-16{padding-top:4rem;padding-bottom:4rem}.md\:text-left{text-align:left}.md\:text-3xl{font-size:1.875rem;line-height:2.25rem}.md\:text-6xl{font-size:3.75rem;line-height:1}.md\:text-8xl{font-size:6rem;line-height:1}.md\:text-sm{font-size:.875rem;line-height:1.25rem}.md\:text-xl{font-size:1.25rem;line-height:1.75rem}}@media (min-width: 1280px){.xl\:mx-16{margin-left:4rem;margin-right:4rem}.xl\:h-52{height:13rem}.xl\:w-52{width:13rem}}.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div{--tw-translate-y: -3px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&\>svg\]\:absolute>svg{position:absolute}.\[\&\>svg\]\:left-4>svg{left:1rem}.\[\&\>svg\]\:top-4>svg{top:1rem}.\[\&\>svg\]\:h-3\.5>svg{height:.875rem}.\[\&\>svg\]\:w-3\.5>svg{width:.875rem}.\[\&\>svg\]\:text-destructive>svg{color:hsl(var(--destructive))}.\[\&\>svg\]\:text-foreground>svg{color:hsl(var(--foreground))}.\[\&\>svg\~\*\]\:pl-7>svg~*{padding-left:1.75rem}.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state=open]>svg{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&_p\]\:leading-relaxed p{line-height:1.625}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:1rem;height:1rem}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0} 2 | -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/svg/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/svg/not-found.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/assets/svg/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.firebase/ai-mock-interview-yt-react-ts/hosting/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /.firebase/hosting.LmZpcmViYXNlL2FpLW1vY2staW50ZXJ2aWV3LXl0LXJlYWN0LXRzL2hvc3Rpbmc.cache: -------------------------------------------------------------------------------- 1 | index.html,1737764222524,c47500ea142dc6c790bd4d5b38fbefdafa201c2f44aaefb2e7cf52b4533833c5 2 | assets/svg/logo.svg,1737764222526,0c2c0a42f97bd6e9e5f5ff1834abc43b89b544d312c80cc071a305d237addcbe 3 | assets/svg/vite.svg,1737764222525,d3bbbc44b3ea71906a72bf2ec1a4716903e2e3d9f85a5007205a65d1f12e2923 4 | assets/svg/not-found.svg,1737764222525,37942a939ec97cb7fa3eeee9f52c02865efe49afbe758a4d0551e8f9ec5a8874 5 | assets/index-IIY2ctNp.css,1737764222528,b317308a7bbcfbc0f62b6373e7ef95b7d22547a44b3a527853538d06d441ecf0 6 | assets/img/logo/react.png,1737764222533,758685d31559e371334b6ed138bebbc6f5c2c29522cf7b631ad3fcde0957bebd 7 | assets/img/logo/microsoft.png,1737764222534,7668a185fd4eaaafaa8ab5cdd4e02c14a66fe23c7920990cb2841c7413754ce1 8 | assets/img/logo/firebase.png,1737764222537,7ffa3968429c14f092e0a16e2ec972c6647abf92a6ca79cd35c6dd3d9d1cfe54 9 | assets/img/logo/zoom.png,1737764222532,2bf0dffee4f61396121c4b34cae3ead5167650f51a990f419673a7ef88cca2ab 10 | assets/img/logo/tailwindcss.png,1737764222533,91dc5f5f070942129d0da010cc74d913ac3183bdcf569418a46b96b4c9974722 11 | assets/img/logo/meet.png,1737764222536,777497010d68e25e0cd3a35c4271c835b7e8861c9b32ea6bcebb8b5b7d82551d 12 | assets/img/bg.png,1737764222547,896f58e79d70e7ef0403bb8d1e0d1972c60d6a83f959fc4361e3b2ce46ae6170 13 | assets/img/hero.jpg,1737764222541,b910eeea949488a622c64228b5195420636ba9a3548d69f5afbfaec4150378ba 14 | assets/img/office.jpg,1737764222531,72ee47a8f18dc3d88d0797aee2c3e2c265b86c824c66cb2965a62ce9679111a6 15 | assets/index-QXGEuDCU.js,1737764222527,2d0e84fffca18671ebae7f0a7fd41500b89528f9bea4b204127d8d3585af75a3 16 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "ai-mock-interview-yt-react-ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | # enivronment variables 27 | .env 28 | .env.* 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React + TypeScript + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | 10 | ## Expanding the ESLint configuration 11 | 12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: 13 | 14 | - Configure the top-level `parserOptions` property like this: 15 | 16 | ```js 17 | export default tseslint.config({ 18 | languageOptions: { 19 | // other options... 20 | parserOptions: { 21 | project: ['./tsconfig.node.json', './tsconfig.app.json'], 22 | tsconfigRootDir: import.meta.dirname, 23 | }, 24 | }, 25 | }) 26 | ``` 27 | 28 | - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` 29 | - Optionally add `...tseslint.configs.stylisticTypeChecked` 30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: 31 | 32 | ```js 33 | // eslint.config.js 34 | import react from 'eslint-plugin-react' 35 | 36 | export default tseslint.config({ 37 | // Set the react version 38 | settings: { react: { version: '18.3' } }, 39 | plugins: { 40 | // Add the react plugin 41 | react, 42 | }, 43 | rules: { 44 | // other rules... 45 | // Enable its recommended rules 46 | ...react.configs.recommended.rules, 47 | ...react.configs['jsx-runtime'].rules, 48 | }, 49 | }) 50 | ``` 51 | -------------------------------------------------------------------------------- /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.js", 8 | "css": "src/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | import tseslint from 'typescript-eslint' 6 | 7 | export default tseslint.config( 8 | { ignores: ['dist'] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ['**/*.{ts,tsx}'], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | 'react-hooks': reactHooks, 18 | 'react-refresh': reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | 'react-refresh/only-export-components': [ 23 | 'warn', 24 | { allowConstantExport: true }, 25 | ], 26 | }, 27 | }, 28 | ) 29 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "source": ".", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "frameworksBackend": { 10 | "region": "us-central1" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ai-mock-interview-react-type", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc -b && vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@clerk/clerk-react": "^5.22.6", 14 | "@google/generative-ai": "^0.21.0", 15 | "@hookform/resolvers": "^3.10.0", 16 | "@radix-ui/react-accordion": "^1.2.2", 17 | "@radix-ui/react-dialog": "^1.1.5", 18 | "@radix-ui/react-label": "^2.1.1", 19 | "@radix-ui/react-separator": "^1.1.1", 20 | "@radix-ui/react-slot": "^1.1.1", 21 | "@radix-ui/react-tabs": "^1.1.2", 22 | "@radix-ui/react-tooltip": "^1.1.7", 23 | "class-variance-authority": "^0.7.1", 24 | "clsx": "^2.1.1", 25 | "firebase": "^11.2.0", 26 | "lucide-react": "^0.474.0", 27 | "next-themes": "^0.4.4", 28 | "react": "^18.3.1", 29 | "react-dom": "^18.3.1", 30 | "react-fast-marquee": "^1.6.5", 31 | "react-hook-form": "^7.54.2", 32 | "react-hook-speech-to-text": "^0.8.0", 33 | "react-router-dom": "^7.1.3", 34 | "react-webcam": "^7.2.0", 35 | "sonner": "^1.7.2", 36 | "tailwind-merge": "^2.6.0", 37 | "tailwindcss-animate": "^1.0.7", 38 | "zod": "^3.24.1" 39 | }, 40 | "devDependencies": { 41 | "@eslint/js": "^9.17.0", 42 | "@types/node": "^22.10.10", 43 | "@types/react": "^18.3.18", 44 | "@types/react-dom": "^18.3.5", 45 | "@vitejs/plugin-react": "^4.3.4", 46 | "autoprefixer": "^10.4.20", 47 | "eslint": "^9.17.0", 48 | "eslint-plugin-react-hooks": "^5.0.0", 49 | "eslint-plugin-react-refresh": "^0.4.16", 50 | "globals": "^15.14.0", 51 | "postcss": "^8.5.1", 52 | "tailwindcss": "3.4.17", 53 | "typescript": "~5.6.2", 54 | "typescript-eslint": "^8.18.2", 55 | "vite": "^6.0.5" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/assets/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/bg.png -------------------------------------------------------------------------------- /public/assets/img/hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/hero.jpg -------------------------------------------------------------------------------- /public/assets/img/logo/firebase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/logo/firebase.png -------------------------------------------------------------------------------- /public/assets/img/logo/meet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/logo/meet.png -------------------------------------------------------------------------------- /public/assets/img/logo/microsoft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/logo/microsoft.png -------------------------------------------------------------------------------- /public/assets/img/logo/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/logo/react.png -------------------------------------------------------------------------------- /public/assets/img/logo/tailwindcss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/logo/tailwindcss.png -------------------------------------------------------------------------------- /public/assets/img/logo/zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/logo/zoom.png -------------------------------------------------------------------------------- /public/assets/img/office.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mahalakshmi-Design-Studioz/ai-mock-interview-react-vite-typescript-january-2025/15423dc005fcffd1d0393c0175dfeee1a9d0a650/public/assets/img/office.jpg -------------------------------------------------------------------------------- /public/assets/svg/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/svg/not-found.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /public/assets/svg/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; 2 | 3 | import { PublicLayout } from "@/layouts/public-layout"; 4 | import AuthenticationLayout from "@/layouts/auth-layout"; 5 | import ProtectRoutes from "@/layouts/protected-routes"; 6 | import { MainLayout } from "@/layouts/main-layout"; 7 | 8 | import HomePage from "@/routes/home"; 9 | import { SignInPage } from "./routes/sign-in"; 10 | import { SignUpPage } from "./routes/sign-up"; 11 | import { Generate } from "./components/generate"; 12 | import { Dashboard } from "./routes/dashboard"; 13 | import { CreateEditPage } from "./routes/create-edit-page"; 14 | import { MockLoadPage } from "./routes/mock-load-page"; 15 | import { MockInterviewPage } from "./routes/mock-interview-page"; 16 | import { Feedback } from "./routes/feedback"; 17 | 18 | const App = () => { 19 | return ( 20 | 21 | 22 | {/* public routes */} 23 | }> 24 | } /> 25 | 26 | 27 | {/* authentication layout */} 28 | }> 29 | } /> 30 | } /> 31 | 32 | 33 | {/* protected routes */} 34 | 37 | 38 | 39 | } 40 | > 41 | {/* add all the protect routes */} 42 | } path="/generate"> 43 | } /> 44 | } /> 45 | } /> 46 | } 49 | /> 50 | } /> 51 | 52 | 53 | 54 | 55 | ); 56 | }; 57 | 58 | export default App; 59 | -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/container.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | interface ContainerProps { 4 | children: React.ReactNode; 5 | className?: string; 6 | } 7 | 8 | export const Container = ({ children, className }: ContainerProps) => { 9 | return ( 10 |
13 | {children} 14 |
15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/custom-bread-crumb.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Breadcrumb, 3 | BreadcrumbItem, 4 | BreadcrumbLink, 5 | BreadcrumbList, 6 | BreadcrumbPage, 7 | BreadcrumbSeparator, 8 | } from "@/components/ui/breadcrumb"; 9 | import { Home } from "lucide-react"; 10 | import React from "react"; 11 | 12 | interface CustomBreadCrumbProps { 13 | breadCrumbPage: string; 14 | breadCrumpItems?: { link: string; label: string }[]; 15 | } 16 | 17 | export const CustomBreadCrumb = ({ 18 | breadCrumbPage, 19 | breadCrumpItems, 20 | }: CustomBreadCrumbProps) => { 21 | return ( 22 | 23 | 24 | 25 | 29 | 30 | Home 31 | 32 | 33 | 34 | {breadCrumpItems && 35 | breadCrumpItems.map((item, i) => ( 36 | 37 | 38 | 39 | 43 | {item.label} 44 | 45 | 46 | 47 | ))} 48 | 49 | 50 | {breadCrumbPage} 51 | 52 | 53 | 54 | ); 55 | }; 56 | -------------------------------------------------------------------------------- /src/components/footer.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { Facebook, Twitter, Instagram, Linkedin } from "lucide-react"; // Import Lucide icons 4 | import { Link } from "react-router-dom"; 5 | import { Container } from "@/components/container"; 6 | import { MainRoutes } from "@/lib/helpers"; 7 | 8 | interface SocialLinkProps { 9 | href: string; 10 | icon: React.ReactNode; 11 | hoverColor: string; 12 | } 13 | 14 | const SocialLink: React.FC = ({ href, icon, hoverColor }) => { 15 | return ( 16 | 22 | {icon} 23 | 24 | ); 25 | }; 26 | 27 | interface FooterLinkProps { 28 | to: string; 29 | children: React.ReactNode; 30 | } 31 | 32 | const FooterLink: React.FC = ({ to, children }) => { 33 | return ( 34 |
  • 35 | 39 | {children} 40 | 41 |
  • 42 | ); 43 | }; 44 | 45 | export const Footer = () => { 46 | return ( 47 |
    48 | 49 |
    50 | {/* First Column: Links */} 51 |
    52 |

    Quick Links

    53 |
      54 | {MainRoutes.map((route) => ( 55 | 56 | {route.label} 57 | 58 | ))} 59 |
    60 |
    61 | 62 | {/* Second Column: About Us */} 63 |
    64 |

    About Us

    65 |

    66 | We are committed to helping you unlock your full potential with 67 | AI-powered tools. Our platform offers a wide range of resources to 68 | improve your interview skills and chances of success. 69 |

    70 |
    71 | 72 | {/* Third Column: Services */} 73 |
    74 |

    Services

    75 |
      76 | 77 | Interview Preparation 78 | 79 | 80 | Career Coaching 81 | 82 | 83 | Resume Building 84 | 85 |
    86 |
    87 | 88 | {/* Fourth Column: Address and Social Media */} 89 |
    90 |

    Contact Us

    91 |

    123 AI Street, Tech City, 12345

    92 |
    93 | } 96 | hoverColor="text-blue-500" 97 | /> 98 | } 101 | hoverColor="text-blue-400" 102 | /> 103 | } 106 | hoverColor="text-pink-500" 107 | /> 108 | } 111 | hoverColor="text-blue-700" 112 | /> 113 |
    114 |
    115 |
    116 |
    117 |
    118 | ); 119 | }; 120 | -------------------------------------------------------------------------------- /src/components/form-mock-interview.tsx: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { zodResolver } from "@hookform/resolvers/zod"; 3 | import { FormProvider, useForm } from "react-hook-form"; 4 | 5 | import { Interview } from "@/types"; 6 | 7 | import { CustomBreadCrumb } from "./custom-bread-crumb"; 8 | import { useEffect, useState } from "react"; 9 | import { useNavigate } from "react-router-dom"; 10 | import { useAuth } from "@clerk/clerk-react"; 11 | import { toast } from "sonner"; 12 | import { Headings } from "./headings"; 13 | import { Button } from "./ui/button"; 14 | import { Loader, Trash2 } from "lucide-react"; 15 | import { Separator } from "./ui/separator"; 16 | import { 17 | FormControl, 18 | FormField, 19 | FormItem, 20 | FormLabel, 21 | FormMessage, 22 | } from "./ui/form"; 23 | import { Input } from "./ui/input"; 24 | import { Textarea } from "./ui/textarea"; 25 | import { chatSession } from "@/scripts"; 26 | import { 27 | addDoc, 28 | collection, 29 | doc, 30 | serverTimestamp, 31 | updateDoc, 32 | } from "firebase/firestore"; 33 | import { db } from "@/config/firebase.config"; 34 | 35 | interface FormMockInterviewProps { 36 | initialData: Interview | null; 37 | } 38 | 39 | const formSchema = z.object({ 40 | position: z 41 | .string() 42 | .min(1, "Position is required") 43 | .max(100, "Position must be 100 characters or less"), 44 | description: z.string().min(10, "Description is required"), 45 | experience: z.coerce 46 | .number() 47 | .min(0, "Experience cannot be empty or negative"), 48 | techStack: z.string().min(1, "Tech stack must be at least a character"), 49 | }); 50 | 51 | type FormData = z.infer; 52 | 53 | export const FormMockInterview = ({ initialData }: FormMockInterviewProps) => { 54 | const form = useForm({ 55 | resolver: zodResolver(formSchema), 56 | defaultValues: initialData || {}, 57 | }); 58 | 59 | const { isValid, isSubmitting } = form.formState; 60 | const [loading, setLoading] = useState(false); 61 | const navigate = useNavigate(); 62 | const { userId } = useAuth(); 63 | 64 | const title = initialData 65 | ? initialData.position 66 | : "Create a new mock interview"; 67 | 68 | const breadCrumpPage = initialData ? initialData?.position : "Create"; 69 | const actions = initialData ? "Save Changes" : "Create"; 70 | const toastMessage = initialData 71 | ? { title: "Updated..!", description: "Changes saved successfully..." } 72 | : { title: "Created..!", description: "New Mock Interview created..." }; 73 | 74 | const cleanAiResponse = (responseText: string) => { 75 | // Step 1: Trim any surrounding whitespace 76 | let cleanText = responseText.trim(); 77 | 78 | // Step 2: Remove any occurrences of "json" or code block symbols (``` or `) 79 | cleanText = cleanText.replace(/(json|```|`)/g, ""); 80 | 81 | // Step 3: Extract a JSON array by capturing text between square brackets 82 | const jsonArrayMatch = cleanText.match(/\[.*\]/s); 83 | if (jsonArrayMatch) { 84 | cleanText = jsonArrayMatch[0]; 85 | } else { 86 | throw new Error("No JSON array found in response"); 87 | } 88 | 89 | // Step 4: Parse the clean JSON text into an array of objects 90 | try { 91 | return JSON.parse(cleanText); 92 | } catch (error) { 93 | throw new Error("Invalid JSON format: " + (error as Error)?.message); 94 | } 95 | }; 96 | 97 | const generateAiResponse = async (data: FormData) => { 98 | const prompt = ` 99 | As an experienced prompt engineer, generate a JSON array containing 5 technical interview questions along with detailed answers based on the following job information. Each object in the array should have the fields "question" and "answer", formatted as follows: 100 | 101 | [ 102 | { "question": "", "answer": "" }, 103 | ... 104 | ] 105 | 106 | Job Information: 107 | - Job Position: ${data?.position} 108 | - Job Description: ${data?.description} 109 | - Years of Experience Required: ${data?.experience} 110 | - Tech Stacks: ${data?.techStack} 111 | 112 | The questions should assess skills in ${data?.techStack} development and best practices, problem-solving, and experience handling complex requirements. Please format the output strictly as an array of JSON objects without any additional labels, code blocks, or explanations. Return only the JSON array with questions and answers. 113 | `; 114 | 115 | const aiResult = await chatSession.sendMessage(prompt); 116 | const cleanedResponse = cleanAiResponse(aiResult.response.text()); 117 | 118 | return cleanedResponse; 119 | }; 120 | 121 | const onSubmit = async (data: FormData) => { 122 | try { 123 | setLoading(true); 124 | 125 | if (initialData) { 126 | // update 127 | if (isValid) { 128 | const aiResult = await generateAiResponse(data); 129 | 130 | await updateDoc(doc(db, "interviews", initialData?.id), { 131 | questions: aiResult, 132 | ...data, 133 | updatedAt: serverTimestamp(), 134 | }).catch((error) => console.log(error)); 135 | toast(toastMessage.title, { description: toastMessage.description }); 136 | } 137 | } else { 138 | // create a new mock interview 139 | if (isValid) { 140 | const aiResult = await generateAiResponse(data); 141 | 142 | await addDoc(collection(db, "interviews"), { 143 | ...data, 144 | userId, 145 | questions: aiResult, 146 | createdAt: serverTimestamp(), 147 | }); 148 | 149 | toast(toastMessage.title, { description: toastMessage.description }); 150 | } 151 | } 152 | 153 | navigate("/generate", { replace: true }); 154 | } catch (error) { 155 | console.log(error); 156 | toast.error("Error..", { 157 | description: `Something went wrong. Please try again later`, 158 | }); 159 | } finally { 160 | setLoading(false); 161 | } 162 | }; 163 | 164 | useEffect(() => { 165 | if (initialData) { 166 | form.reset({ 167 | position: initialData.position, 168 | description: initialData.description, 169 | experience: initialData.experience, 170 | techStack: initialData.techStack, 171 | }); 172 | } 173 | }, [initialData, form]); 174 | 175 | return ( 176 |
    177 | 181 | 182 |
    183 | 184 | 185 | {initialData && ( 186 | 189 | )} 190 |
    191 | 192 | 193 | 194 |
    195 | 196 | 197 |
    201 | ( 205 | 206 |
    207 | Job Role / Job Position 208 | 209 |
    210 | 211 | 218 | 219 |
    220 | )} 221 | /> 222 | 223 | ( 227 | 228 |
    229 | Job Description 230 | 231 |
    232 | 233 |