diff --git a/.gitignore b/.gitignore
index 8f322f0..45c1abc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,7 @@ yarn-error.log*
# local env files
.env*.local
+.env
# vercel
.vercel
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..df60d30
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,9 @@
+module.exports = {
+ semi: true,
+ singleQuote: true,
+ trailingComma: 'all',
+ bracketSameLine: true,
+ tabWidth: 2,
+ useTabs: false,
+ arrowParens: 'always',
+};
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..843f0c2
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,18 @@
+{
+ "[javascript]": {
+ "editor.formatOnSave": false
+ },
+ "eslint.alwaysShowStatus": true,
+ "javascript.validate.enable": false,
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "workbench.colorCustomizations": {
+ "titleBar.activeBackground": "#3770FF",
+ "titleBar.activeForeground": "#ffffff",
+ "titleBar.inactiveBackground": "#3770FF",
+ "titleBar.inactiveForeground": "#ffffff"
+ }
+ // Enables TypeScript check for all files, but instantly kills RAM so only enable when needed
+ // "typescript.tsserver.experimental.enableProjectDiagnostics": true
+}
diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx
index a3c8586..3dd02ca 100644
--- a/app/dashboard/page.tsx
+++ b/app/dashboard/page.tsx
@@ -1,10 +1,17 @@
-import StatusAlert from "@/components/ui/status-alert";
+import PageContent from '@/components/layouts/page-content';
+import DashboardFeatureList from '@/components/sections/dashboard-features-list';
+import DashboardRecentActivity from '@/components/sections/dashboard-recent-activity';
+import TopicSuggestions from '@/components/sections/topic-suggestions';
-const Dashboard: React.FunctionComponent = () =>{
- return(
-
-
-
- )
-}
-export default Dashboard;
\ No newline at end of file
+const Dashboard: React.FunctionComponent = () => {
+ return (
+
+
+
+ {/* */}
+ {/* */}
+
+
+ );
+};
+export default Dashboard;
diff --git a/app/globals.css b/app/globals.css
index bd6213e..af525c0 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,3 +1,29 @@
@tailwind base;
@tailwind components;
-@tailwind utilities;
\ No newline at end of file
+@tailwind utilities;
+
+body,
+html {
+ @apply text-neutral-800;
+}
+
+.view-container {
+ @apply box-border mx-auto;
+ @apply w-[1250px] max-2xl:w-[1200px] max-xl:w-[920px] max-lg:w-[720px] max-md:w-[600px] max-sm:w-[440px];
+}
+
+h1,
+h2,
+h3,
+h4 {
+ @apply tracking-tight;
+}
+
+.hide-scrollbar::-webkit-scrollbar {
+ width: 0; /* Remove scrollbar space */
+ background: transparent; /* Optional: just make scrollbar invisible */
+}
+
+.form-input-wrapper {
+ @apply grid grid-cols-1 gap-2 my-6;
+}
diff --git a/app/layout.tsx b/app/layout.tsx
index 7870e8b..a9fd906 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,16 +1,20 @@
-import './globals.css'
-import { Inter } from 'next/font/google'
+import Navbar from '@/components/sections/navbar';
+import './globals.css';
+import { Inter } from 'next/font/google';
-const inter = Inter({ subsets: ['latin'] })
+const inter = Inter({ subsets: ['latin'] });
export default function RootLayout({
children,
}: {
- children: React.ReactNode
+ children: React.ReactNode;
}) {
return (
- {children}
+
+
+ {children}
+
- )
+ );
}
diff --git a/app/page.tsx b/app/page.tsx
index 18f3e06..25d9f69 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,11 +1,15 @@
-import StatusAlert from "@/components/ui/status-alert";
+import PageContent from '@/components/layouts/page-content';
+import ViewContainer from '@/components/layouts/view-container';
+import StatusAlert from '@/components/ui/status-alert';
const App: React.FunctionComponent = () => {
return (
-
-
-
- )
-}
+
+
+
+
+
+ );
+};
-export default App;
\ No newline at end of file
+export default App;
diff --git a/app/qna/page.tsx b/app/qna/page.tsx
new file mode 100644
index 0000000..8a3880f
--- /dev/null
+++ b/app/qna/page.tsx
@@ -0,0 +1,120 @@
+'use client';
+import PageContent from '@/components/layouts/page-content';
+import ViewContainer from '@/components/layouts/view-container';
+
+import { Button } from '@/components/ui/button';
+
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from '@/components/ui/dialog';
+
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectTrigger,
+ SelectValue,
+} from '@/components/ui/select';
+
+import { Label } from '@/components/ui/label';
+import { useState } from 'react';
+import { fetchRecentQNASessions } from '@/middleware/qna/recent-sessions';
+import { RecentSessionsEmptyStateView } from '@/components/ui/empty-states';
+import { RecentQnASessionsList } from '@/components/sections/recent-qna-sessions-list';
+import { fetchTopics } from '@/middleware/qna/sessions';
+import { getTopicDepthLevels } from '@/common';
+
+const TopicBasedQNA: React.FunctionComponent = () => {
+ const [recentQNASessions, setRecentQNASessions] = useState<
+ Array
+ >(fetchRecentQNASessions());
+
+ const [userTopics, setUserTopics]
+ = useState>(fetchTopics());
+
+ return (
+
+
+
+ {'Your Q/A Sessions'}
+
+
+
+
+
+ {recentQNASessions.length ? (
+
+ ) : (
+
+ )}
+
+ );
+};
+
+export default TopicBasedQNA;
diff --git a/common/dashboard-feature-list.tsx b/common/dashboard-feature-list.tsx
new file mode 100644
index 0000000..d77b882
--- /dev/null
+++ b/common/dashboard-feature-list.tsx
@@ -0,0 +1,38 @@
+import { cn } from '@/lib/utils';
+import {
+ Briefcase,
+ FileSearch,
+ MessagesSquare,
+ PencilLine,
+ Video,
+} from 'lucide-react';
+
+const FeatureList: Array = [
+ {
+ featureName: 'Video Interview',
+ icon: ,
+ link: '#',
+ },
+ {
+ featureName: 'ATS Resume Review',
+ icon: ,
+ link: '#',
+ },
+ {
+ featureName: 'Topic Based Q/A',
+ icon: ,
+ link: '/qna',
+ },
+ {
+ featureName: 'Mock Aptitude',
+ icon: ,
+ link: '#',
+ },
+ {
+ featureName: 'Behavioural Rounds',
+ icon: ,
+ link: '#',
+ },
+];
+
+export { FeatureList };
diff --git a/common/environment-variables.ts b/common/environment-variables.ts
new file mode 100644
index 0000000..624606b
--- /dev/null
+++ b/common/environment-variables.ts
@@ -0,0 +1,6 @@
+const Environment = {
+ // env variable for checking development environment
+ ENVIRONMENT_TYPE: process.env.NEXT_PUBLIC_ENVIRONMENT_TYPE,
+};
+
+export { Environment };
diff --git a/common/index.ts b/common/index.ts
new file mode 100644
index 0000000..8da5c28
--- /dev/null
+++ b/common/index.ts
@@ -0,0 +1,10 @@
+/**
+ * method to return a list of levels, portraying topic depth/diversity
+ */
+function getTopicDepthLevels() {
+ return ['Basic', 'Intermediate', 'Advanced', 'Professional'];
+}
+
+export {
+ getTopicDepthLevels
+}
diff --git a/components.json b/components.json
index dd02d69..c8be6b2 100644
--- a/components.json
+++ b/components.json
@@ -13,4 +13,4 @@
"components": "@/components",
"utils": "@/lib/utils"
}
-}
\ No newline at end of file
+}
diff --git a/components/layouts/box-card-slider.tsx b/components/layouts/box-card-slider.tsx
new file mode 100644
index 0000000..ed988a6
--- /dev/null
+++ b/components/layouts/box-card-slider.tsx
@@ -0,0 +1,19 @@
+import { cn } from '@/lib/utils';
+
+const BoxCardSlider: React.FunctionComponent<
+ React.HTMLAttributes
+> = ({ className, children, ...props }) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default BoxCardSlider;
diff --git a/components/layouts/box-card.tsx b/components/layouts/box-card.tsx
new file mode 100644
index 0000000..ac068ea
--- /dev/null
+++ b/components/layouts/box-card.tsx
@@ -0,0 +1,20 @@
+import { ReactHTMLElement } from 'react';
+import { cn } from '@/lib/utils';
+
+const BoxCard: React.FunctionComponent<
+ React.HTMLAttributes
+> = ({ className, children, ...props }) => (
+
+ {children}
+
+);
+
+export { BoxCard };
diff --git a/components/layouts/page-content.tsx b/components/layouts/page-content.tsx
new file mode 100644
index 0000000..9b9b121
--- /dev/null
+++ b/components/layouts/page-content.tsx
@@ -0,0 +1,13 @@
+import { cn } from '@/lib/utils';
+
+const PageContent: React.FunctionComponent<
+ React.HTMLAttributes
+> = ({ className, children, ...props }) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default PageContent;
diff --git a/components/layouts/view-container.tsx b/components/layouts/view-container.tsx
new file mode 100644
index 0000000..d18ff9e
--- /dev/null
+++ b/components/layouts/view-container.tsx
@@ -0,0 +1,13 @@
+import { cn } from '@/lib/utils';
+
+const ViewContainer: React.FunctionComponent<
+ React.HTMLAttributes
+> = ({ children, className, ...props }) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default ViewContainer;
diff --git a/components/sections/dashboard-features-list/index.tsx b/components/sections/dashboard-features-list/index.tsx
new file mode 100644
index 0000000..d05bfdf
--- /dev/null
+++ b/components/sections/dashboard-features-list/index.tsx
@@ -0,0 +1,26 @@
+import BoxCardSlider from '@/components/layouts/box-card-slider';
+import ViewContainer from '@/components/layouts/view-container';
+import FeatureOption from '@/components/ui/feature-option';
+import { FeatureList } from '@/common/dashboard-feature-list';
+
+const DashboardFeatureList: React.FunctionComponent = () => {
+ return (
+
+
+ {'Start new activity'}
+
+ {FeatureList.map((featureItem, featureIndex) => (
+
+ ))}
+
+
+
+ );
+};
+
+export default DashboardFeatureList;
diff --git a/components/sections/dashboard-recent-activity/index.tsx b/components/sections/dashboard-recent-activity/index.tsx
new file mode 100644
index 0000000..ad5e73d
--- /dev/null
+++ b/components/sections/dashboard-recent-activity/index.tsx
@@ -0,0 +1,9 @@
+const DashboardRecentActivity: React.FunctionComponent = () => {
+ return (
+
+ {'DashboardRecentActivity'}
+
+ );
+};
+
+export default DashboardRecentActivity;
diff --git a/components/sections/navbar/index.tsx b/components/sections/navbar/index.tsx
new file mode 100644
index 0000000..6c9a3a4
--- /dev/null
+++ b/components/sections/navbar/index.tsx
@@ -0,0 +1,38 @@
+import { Button } from '@/components/ui/button';
+import { Moon } from 'lucide-react';
+import { Sun } from 'lucide-react';
+import ViewContainer from '@/components/layouts/view-container';
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
+import Link from 'next/link';
+import { cn } from '@/lib/utils';
+
+const Navbar: React.FunctionComponent = () => {
+ return (
+
+ );
+};
+
+export default Navbar;
diff --git a/components/sections/recent-qna-sessions-list/index.tsx b/components/sections/recent-qna-sessions-list/index.tsx
new file mode 100644
index 0000000..91bea70
--- /dev/null
+++ b/components/sections/recent-qna-sessions-list/index.tsx
@@ -0,0 +1,32 @@
+import ViewContainer from '@/components/layouts/view-container';
+import { fetchRecentQNASessions } from '@/middleware/qna/recent-sessions';
+import RecentSession from '@/components/ui/recent-session';
+import BoxCardSlider from '@/components/layouts/box-card-slider';
+
+const RecentQnASessionsList: React.FunctionComponent<{
+ data: Array;
+}> = ({ data }) => {
+ return (
+
+
+
+ {'Recent sessions'}
+
+
+ {data.map((recentSession, index) => {
+ return (
+
+ );
+ })}
+
+
+
+ );
+};
+
+export { RecentQnASessionsList };
diff --git a/components/sections/topic-suggestions/index.tsx b/components/sections/topic-suggestions/index.tsx
new file mode 100644
index 0000000..9797480
--- /dev/null
+++ b/components/sections/topic-suggestions/index.tsx
@@ -0,0 +1,5 @@
+const TopicSuggestions: React.FunctionComponent = () => {
+ return ;
+};
+
+export default TopicSuggestions;
diff --git a/components/ui/alert.tsx b/components/ui/alert.tsx
index 839e81f..720ff3f 100644
--- a/components/ui/alert.tsx
+++ b/components/ui/alert.tsx
@@ -1,23 +1,24 @@
-import * as React from "react"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from 'react';
+import { cva, type VariantProps } from 'class-variance-authority';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const alertVariants = cva(
- "relative w-full rounded-lg border border-neutral-200 p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-neutral-950 dark:border-neutral-800 dark:[&>svg]:text-neutral-50",
+ 'relative w-full rounded-lg border border-neutral-200 p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-neutral-950 dark:border-neutral-800 dark:[&>svg]:text-neutral-50',
{
variants: {
variant: {
- default: "bg-white text-neutral-950 dark:bg-neutral-950 dark:text-neutral-50",
+ default:
+ 'bg-white text-neutral-950 dark:bg-neutral-950 dark:text-neutral-50',
destructive:
- "border-red-500/50 text-red-500 dark:border-red-500 [&>svg]:text-red-500 dark:border-red-900/50 dark:text-red-900 dark:dark:border-red-900 dark:[&>svg]:text-red-900",
+ 'border-red-500/50 text-red-500 dark:border-red-500 [&>svg]:text-red-500 dark:border-red-900/50 dark:text-red-900 dark:dark:border-red-900 dark:[&>svg]:text-red-900',
},
},
defaultVariants: {
- variant: "default",
+ variant: 'default',
},
- }
-)
+ },
+);
const Alert = React.forwardRef<
HTMLDivElement,
@@ -29,8 +30,8 @@ const Alert = React.forwardRef<
className={cn(alertVariants({ variant }), className)}
{...props}
/>
-))
-Alert.displayName = "Alert"
+));
+Alert.displayName = 'Alert';
const AlertTitle = React.forwardRef<
HTMLParagraphElement,
@@ -38,11 +39,11 @@ const AlertTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-AlertTitle.displayName = "AlertTitle"
+));
+AlertTitle.displayName = 'AlertTitle';
const AlertDescription = React.forwardRef<
HTMLParagraphElement,
@@ -50,10 +51,10 @@ const AlertDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-AlertDescription.displayName = "AlertDescription"
+));
+AlertDescription.displayName = 'AlertDescription';
-export { Alert, AlertTitle, AlertDescription }
+export { Alert, AlertTitle, AlertDescription };
diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx
index 75a6e3f..e0e3191 100644
--- a/components/ui/avatar.tsx
+++ b/components/ui/avatar.tsx
@@ -1,9 +1,9 @@
-"use client"
+'use client';
-import * as React from "react"
-import * as AvatarPrimitive from "@radix-ui/react-avatar"
+import * as React from 'react';
+import * as AvatarPrimitive from '@radix-ui/react-avatar';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const Avatar = React.forwardRef<
React.ElementRef,
@@ -12,13 +12,13 @@ const Avatar = React.forwardRef<
-))
-Avatar.displayName = AvatarPrimitive.Root.displayName
+));
+Avatar.displayName = AvatarPrimitive.Root.displayName;
const AvatarImage = React.forwardRef<
React.ElementRef,
@@ -26,11 +26,11 @@ const AvatarImage = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-AvatarImage.displayName = AvatarPrimitive.Image.displayName
+));
+AvatarImage.displayName = AvatarPrimitive.Image.displayName;
const AvatarFallback = React.forwardRef<
React.ElementRef,
@@ -39,12 +39,12 @@ const AvatarFallback = React.forwardRef<
-))
-AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
+));
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
-export { Avatar, AvatarImage, AvatarFallback }
+export { Avatar, AvatarImage, AvatarFallback };
diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx
index fc34c82..0230617 100644
--- a/components/ui/badge.tsx
+++ b/components/ui/badge.tsx
@@ -1,27 +1,27 @@
-import * as React from "react"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from 'react';
+import { cva, type VariantProps } from 'class-variance-authority';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const badgeVariants = cva(
- "inline-flex items-center rounded-full border border-neutral-200 px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-neutral-950 focus:ring-offset-2 dark:border-neutral-800 dark:focus:ring-neutral-300",
+ 'inline-flex items-center rounded-full border border-neutral-200 px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-neutral-950 focus:ring-offset-2 dark:border-neutral-800 dark:focus:ring-neutral-300',
{
variants: {
variant: {
default:
- "border-transparent bg-neutral-900 text-neutral-50 hover:bg-neutral-900/80 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-50/80",
+ 'border-transparent bg-neutral-900 text-neutral-50 hover:bg-neutral-900/80 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-50/80',
secondary:
- "border-transparent bg-neutral-100 text-neutral-900 hover:bg-neutral-100/80 dark:bg-neutral-800 dark:text-neutral-50 dark:hover:bg-neutral-800/80",
+ 'border-transparent bg-neutral-100 text-neutral-900 hover:bg-neutral-100/80 dark:bg-neutral-800 dark:text-neutral-50 dark:hover:bg-neutral-800/80',
destructive:
- "border-transparent bg-red-500 text-neutral-50 hover:bg-red-500/80 dark:bg-red-900 dark:text-neutral-50 dark:hover:bg-red-900/80",
- outline: "text-neutral-950 dark:text-neutral-50",
+ 'border-transparent bg-red-500 text-neutral-50 hover:bg-red-500/80 dark:bg-red-900 dark:text-neutral-50 dark:hover:bg-red-900/80',
+ outline: 'text-neutral-950 dark:text-neutral-50',
},
},
defaultVariants: {
- variant: "default",
+ variant: 'default',
},
- }
-)
+ },
+);
export interface BadgeProps
extends React.HTMLAttributes,
@@ -30,7 +30,7 @@ export interface BadgeProps
function Badge({ className, variant, ...props }: BadgeProps) {
return (
- )
+ );
}
-export { Badge, badgeVariants }
+export { Badge, badgeVariants };
diff --git a/components/ui/button.tsx b/components/ui/button.tsx
index 2dcb43e..41330d2 100644
--- a/components/ui/button.tsx
+++ b/components/ui/button.tsx
@@ -1,56 +1,58 @@
-import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from 'react';
+import { Slot } from '@radix-ui/react-slot';
+import { cva, type VariantProps } from 'class-variance-authority';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const buttonVariants = cva(
- "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:ring-offset-neutral-950 dark:focus-visible:ring-neutral-300",
+ 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:ring-offset-neutral-950 dark:focus-visible:ring-neutral-300 ',
{
variants: {
variant: {
- default: "bg-neutral-900 text-neutral-50 hover:bg-neutral-900/90 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-50/90",
+ default:
+ 'bg-neutral-900 text-neutral-50 hover:bg-neutral-900/90 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-50/90',
destructive:
- "bg-red-500 text-neutral-50 hover:bg-red-500/90 dark:bg-red-900 dark:text-neutral-50 dark:hover:bg-red-900/90",
+ 'bg-red-500 text-neutral-50 hover:bg-red-500/90 dark:bg-red-900 dark:text-neutral-50 dark:hover:bg-red-900/90',
outline:
- "border border-neutral-200 bg-white hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50",
+ 'border border-neutral-200 bg-white hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50',
secondary:
- "bg-neutral-100 text-neutral-900 hover:bg-neutral-100/80 dark:bg-neutral-800 dark:text-neutral-50 dark:hover:bg-neutral-800/80",
- ghost: "hover:bg-neutral-100 hover:text-neutral-900 dark:hover:bg-neutral-800 dark:hover:text-neutral-50",
- link: "text-neutral-900 underline-offset-4 hover:underline dark:text-neutral-50",
+ 'bg-neutral-100 text-neutral-900 hover:bg-neutral-100/80 dark:bg-neutral-800 dark:text-neutral-50 dark:hover:bg-neutral-800/80',
+ ghost:
+ 'hover:bg-neutral-100 hover:text-neutral-900 dark:hover:bg-neutral-800 dark:hover:text-neutral-50',
+ link: 'text-neutral-900 underline-offset-4 hover:underline dark:text-neutral-50',
},
size: {
- default: "h-10 px-4 py-2",
- sm: "h-9 rounded-md px-3",
- lg: "h-11 rounded-md px-8",
- icon: "h-10 w-10",
+ default: 'h-10 px-4 py-2',
+ sm: 'h-9 rounded-md px-3',
+ lg: 'h-11 rounded-md px-8',
+ icon: 'h-10 w-10',
},
},
defaultVariants: {
- variant: "default",
- size: "default",
+ variant: 'default',
+ size: 'default',
},
- }
-)
+ },
+);
export interface ButtonProps
extends React.ButtonHTMLAttributes,
VariantProps {
- asChild?: boolean
+ asChild?: boolean;
}
const Button = React.forwardRef(
({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button"
+ const Comp = asChild ? Slot : 'button';
return (
- )
- }
-)
-Button.displayName = "Button"
+ );
+ },
+);
+Button.displayName = 'Button';
-export { Button, buttonVariants }
+export { Button, buttonVariants };
diff --git a/components/ui/card.tsx b/components/ui/card.tsx
index 5e82fbc..e80da95 100644
--- a/components/ui/card.tsx
+++ b/components/ui/card.tsx
@@ -1,6 +1,6 @@
-import * as React from "react"
+import * as React from 'react';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const Card = React.forwardRef<
HTMLDivElement,
@@ -9,13 +9,13 @@ const Card = React.forwardRef<
-))
-Card.displayName = "Card"
+));
+Card.displayName = 'Card';
const CardHeader = React.forwardRef<
HTMLDivElement,
@@ -23,11 +23,11 @@ const CardHeader = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-CardHeader.displayName = "CardHeader"
+));
+CardHeader.displayName = 'CardHeader';
const CardTitle = React.forwardRef<
HTMLParagraphElement,
@@ -36,13 +36,13 @@ const CardTitle = React.forwardRef<
-))
-CardTitle.displayName = "CardTitle"
+));
+CardTitle.displayName = 'CardTitle';
const CardDescription = React.forwardRef<
HTMLParagraphElement,
@@ -50,19 +50,19 @@ const CardDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-CardDescription.displayName = "CardDescription"
+));
+CardDescription.displayName = 'CardDescription';
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => (
-
-))
-CardContent.displayName = "CardContent"
+
+));
+CardContent.displayName = 'CardContent';
const CardFooter = React.forwardRef<
HTMLDivElement,
@@ -70,10 +70,17 @@ const CardFooter = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-CardFooter.displayName = "CardFooter"
+));
+CardFooter.displayName = 'CardFooter';
-export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
+export {
+ Card,
+ CardHeader,
+ CardFooter,
+ CardTitle,
+ CardDescription,
+ CardContent,
+};
diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx
new file mode 100644
index 0000000..de0cf17
--- /dev/null
+++ b/components/ui/dialog.tsx
@@ -0,0 +1,118 @@
+'use client';
+
+import * as React from 'react';
+import * as DialogPrimitive from '@radix-ui/react-dialog';
+import { X } from 'lucide-react';
+
+import { cn } from '@/lib/utils';
+
+const Dialog = DialogPrimitive.Root;
+
+const DialogTrigger = DialogPrimitive.Trigger;
+
+const DialogPortal = DialogPrimitive.Portal;
+
+const DialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
+
+const DialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+ Close
+
+
+
+));
+DialogContent.displayName = DialogPrimitive.Content.displayName;
+
+const DialogHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+);
+DialogHeader.displayName = 'DialogHeader';
+
+const DialogFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+);
+DialogFooter.displayName = 'DialogFooter';
+
+const DialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogTitle.displayName = DialogPrimitive.Title.displayName;
+
+const DialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogDescription.displayName = DialogPrimitive.Description.displayName;
+
+export {
+ Dialog,
+ DialogPortal,
+ DialogOverlay,
+ DialogTrigger,
+ DialogContent,
+ DialogHeader,
+ DialogFooter,
+ DialogTitle,
+ DialogDescription,
+};
diff --git a/components/ui/empty-states/index.tsx b/components/ui/empty-states/index.tsx
new file mode 100644
index 0000000..864cd8d
--- /dev/null
+++ b/components/ui/empty-states/index.tsx
@@ -0,0 +1 @@
+export { RecentSessionsEmptyStateView } from './no-recent-sessions';
diff --git a/components/ui/empty-states/no-recent-sessions.tsx b/components/ui/empty-states/no-recent-sessions.tsx
new file mode 100644
index 0000000..d5831de
--- /dev/null
+++ b/components/ui/empty-states/no-recent-sessions.tsx
@@ -0,0 +1,29 @@
+import ViewContainer from '@/components/layouts/view-container';
+import { cn } from '@/lib/utils';
+import Image from 'next/image';
+
+const RecentSessionsEmptyStateView: React.FunctionComponent = () => {
+ return (
+
+
+
+
+
+ No Recents
+ Start by creating a new session
+
+
+
+
+ );
+};
+
+export { RecentSessionsEmptyStateView };
diff --git a/components/ui/feature-option.tsx b/components/ui/feature-option.tsx
new file mode 100644
index 0000000..7def2a6
--- /dev/null
+++ b/components/ui/feature-option.tsx
@@ -0,0 +1,35 @@
+import { cn } from '@/lib/utils';
+import Link from 'next/link';
+import { BoxCard } from '../layouts/box-card';
+
+const FeatureOption: React.FunctionComponent = ({
+ featureName,
+ icon,
+ link,
+ className,
+ ...props
+}) => {
+ return (
+
+
+ {icon && (
+ {icon}
+ )}
+ {
+
+ {featureName}
+
+ }
+
+
+ );
+};
+
+export default FeatureOption;
diff --git a/components/ui/input.tsx b/components/ui/input.tsx
index 8f19870..71426e4 100644
--- a/components/ui/input.tsx
+++ b/components/ui/input.tsx
@@ -1,6 +1,6 @@
-import * as React from "react"
+import * as React from 'react';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
export interface InputProps
extends React.InputHTMLAttributes {}
@@ -11,15 +11,15 @@ const Input = React.forwardRef(
- )
- }
-)
-Input.displayName = "Input"
+ );
+ },
+);
+Input.displayName = 'Input';
-export { Input }
+export { Input };
diff --git a/components/ui/label.tsx b/components/ui/label.tsx
index 5341821..7114fb0 100644
--- a/components/ui/label.tsx
+++ b/components/ui/label.tsx
@@ -1,14 +1,14 @@
-"use client"
+'use client';
-import * as React from "react"
-import * as LabelPrimitive from "@radix-ui/react-label"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from 'react';
+import * as LabelPrimitive from '@radix-ui/react-label';
+import { cva, type VariantProps } from 'class-variance-authority';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const labelVariants = cva(
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
-)
+ 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
+);
const Label = React.forwardRef<
React.ElementRef,
@@ -20,7 +20,7 @@ const Label = React.forwardRef<
className={cn(labelVariants(), className)}
{...props}
/>
-))
-Label.displayName = LabelPrimitive.Root.displayName
+));
+Label.displayName = LabelPrimitive.Root.displayName;
-export { Label }
+export { Label };
diff --git a/components/ui/navigation-menu.tsx b/components/ui/navigation-menu.tsx
index fb60583..888638f 100644
--- a/components/ui/navigation-menu.tsx
+++ b/components/ui/navigation-menu.tsx
@@ -1,9 +1,9 @@
-import * as React from "react"
-import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
-import { cva } from "class-variance-authority"
-import { ChevronDown } from "lucide-react"
+import * as React from 'react';
+import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
+import { cva } from 'class-variance-authority';
+import { ChevronDown } from 'lucide-react';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const NavigationMenu = React.forwardRef<
React.ElementRef,
@@ -12,16 +12,15 @@ const NavigationMenu = React.forwardRef<
+ {...props}>
{children}
-))
-NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
+));
+NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
const NavigationMenuList = React.forwardRef<
React.ElementRef,
@@ -30,19 +29,19 @@ const NavigationMenuList = React.forwardRef<
-))
-NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
+));
+NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
-const NavigationMenuItem = NavigationMenuPrimitive.Item
+const NavigationMenuItem = NavigationMenuPrimitive.Item;
const navigationMenuTriggerStyle = cva(
- "group inline-flex h-10 w-max items-center justify-center rounded-md bg-white px-4 py-2 text-sm font-medium transition-colors hover:bg-neutral-100 hover:text-neutral-900 focus:bg-neutral-100 focus:text-neutral-900 focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-neutral-100/50 data-[state=open]:bg-neutral-100/50 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50 dark:data-[active]:bg-neutral-800/50 dark:data-[state=open]:bg-neutral-800/50"
-)
+ 'group inline-flex h-10 w-max items-center justify-center rounded-md bg-white px-4 py-2 text-sm font-medium transition-colors hover:bg-neutral-100 hover:text-neutral-900 focus:bg-neutral-100 focus:text-neutral-900 focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-neutral-100/50 data-[state=open]:bg-neutral-100/50 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50 dark:data-[active]:bg-neutral-800/50 dark:data-[state=open]:bg-neutral-800/50',
+);
const NavigationMenuTrigger = React.forwardRef<
React.ElementRef,
@@ -50,17 +49,17 @@ const NavigationMenuTrigger = React.forwardRef<
>(({ className, children, ...props }, ref) => (
- {children}{""}
+ className={cn(navigationMenuTriggerStyle(), 'group', className)}
+ {...props}>
+ {children}
+ {''}
-))
-NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
+));
+NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
const NavigationMenuContent = React.forwardRef<
React.ElementRef,
@@ -69,33 +68,33 @@ const NavigationMenuContent = React.forwardRef<
-))
-NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
+));
+NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
-const NavigationMenuLink = NavigationMenuPrimitive.Link
+const NavigationMenuLink = NavigationMenuPrimitive.Link;
const NavigationMenuViewport = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef
>(({ className, ...props }, ref) => (
-
+
-))
+));
NavigationMenuViewport.displayName =
- NavigationMenuPrimitive.Viewport.displayName
+ NavigationMenuPrimitive.Viewport.displayName;
const NavigationMenuIndicator = React.forwardRef<
React.ElementRef
,
@@ -104,16 +103,15 @@ const NavigationMenuIndicator = React.forwardRef<
+ {...props}>
-))
+));
NavigationMenuIndicator.displayName =
- NavigationMenuPrimitive.Indicator.displayName
+ NavigationMenuPrimitive.Indicator.displayName;
export {
navigationMenuTriggerStyle,
@@ -125,4 +123,4 @@ export {
NavigationMenuLink,
NavigationMenuIndicator,
NavigationMenuViewport,
-}
+};
diff --git a/components/ui/progress.tsx b/components/ui/progress.tsx
index 6d20844..d904893 100644
--- a/components/ui/progress.tsx
+++ b/components/ui/progress.tsx
@@ -1,9 +1,9 @@
-"use client"
+'use client';
-import * as React from "react"
-import * as ProgressPrimitive from "@radix-ui/react-progress"
+import * as React from 'react';
+import * as ProgressPrimitive from '@radix-ui/react-progress';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const Progress = React.forwardRef<
React.ElementRef,
@@ -12,17 +12,16 @@ const Progress = React.forwardRef<
+ {...props}>
-))
-Progress.displayName = ProgressPrimitive.Root.displayName
+));
+Progress.displayName = ProgressPrimitive.Root.displayName;
-export { Progress }
+export { Progress };
diff --git a/components/ui/recent-session.tsx b/components/ui/recent-session.tsx
new file mode 100644
index 0000000..fb08b7d
--- /dev/null
+++ b/components/ui/recent-session.tsx
@@ -0,0 +1,32 @@
+import { cn } from '@/lib/utils';
+import Link from 'next/link';
+import { MessageSquare } from 'lucide-react';
+import { BoxCard } from '../layouts/box-card';
+
+const RecentSession: React.FunctionComponent = ({
+ lastMessageContent,
+ title,
+ sessionID,
+}) => {
+ return (
+
+
+
+ {
+
+ {'...'}
+
+ {lastMessageContent}
+
+ }
+
+ {title}
+
+ );
+};
+
+export default RecentSession;
diff --git a/components/ui/select.tsx b/components/ui/select.tsx
index 5b91f13..f7252b7 100644
--- a/components/ui/select.tsx
+++ b/components/ui/select.tsx
@@ -1,16 +1,16 @@
-"use client"
+'use client';
-import * as React from "react"
-import * as SelectPrimitive from "@radix-ui/react-select"
-import { Check, ChevronDown } from "lucide-react"
+import * as React from 'react';
+import * as SelectPrimitive from '@radix-ui/react-select';
+import { Check, ChevronDown } from 'lucide-react';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
-const Select = SelectPrimitive.Root
+const Select = SelectPrimitive.Root;
-const SelectGroup = SelectPrimitive.Group
+const SelectGroup = SelectPrimitive.Group;
-const SelectValue = SelectPrimitive.Value
+const SelectValue = SelectPrimitive.Value;
const SelectTrigger = React.forwardRef<
React.ElementRef,
@@ -19,48 +19,45 @@ const SelectTrigger = React.forwardRef<
+ {...props}>
{children}
-))
-SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
+));
+SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
const SelectContent = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef
->(({ className, children, position = "popper", ...props }, ref) => (
+>(({ className, children, position = 'popper', ...props }, ref) => (
+ {...props}>
+ 'p-1',
+ position === 'popper' &&
+ 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]',
+ )}>
{children}
-))
-SelectContent.displayName = SelectPrimitive.Content.displayName
+));
+SelectContent.displayName = SelectPrimitive.Content.displayName;
const SelectLabel = React.forwardRef<
React.ElementRef,
@@ -68,11 +65,11 @@ const SelectLabel = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-SelectLabel.displayName = SelectPrimitive.Label.displayName
+));
+SelectLabel.displayName = SelectPrimitive.Label.displayName;
const SelectItem = React.forwardRef<
React.ElementRef,
@@ -81,11 +78,10 @@ const SelectItem = React.forwardRef<
+ {...props}>
@@ -94,8 +90,8 @@ const SelectItem = React.forwardRef<
{children}
-))
-SelectItem.displayName = SelectPrimitive.Item.displayName
+));
+SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef<
React.ElementRef,
@@ -103,11 +99,14 @@ const SelectSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-SelectSeparator.displayName = SelectPrimitive.Separator.displayName
+));
+SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
export {
Select,
@@ -118,4 +117,4 @@ export {
SelectLabel,
SelectItem,
SelectSeparator,
-}
+};
diff --git a/components/ui/status-alert.tsx b/components/ui/status-alert.tsx
index 60c189d..d2c1283 100644
--- a/components/ui/status-alert.tsx
+++ b/components/ui/status-alert.tsx
@@ -1,5 +1,5 @@
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
-import { Terminal } from "lucide-react";
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
+import { Terminal } from 'lucide-react';
const StatusAlert: React.FunctionComponent = () => {
return (
@@ -9,11 +9,9 @@ const StatusAlert: React.FunctionComponent = () => {
All systems running
-
- Dashboard UI going to be live soon.
-
+ Dashboard UI going to be live soon.
- )
-}
+ );
+};
-export default StatusAlert;
\ No newline at end of file
+export default StatusAlert;
diff --git a/components/ui/toast.tsx b/components/ui/toast.tsx
index bbd74c2..8ad760f 100644
--- a/components/ui/toast.tsx
+++ b/components/ui/toast.tsx
@@ -1,11 +1,11 @@
-import * as React from "react"
-import * as ToastPrimitives from "@radix-ui/react-toast"
-import { cva, type VariantProps } from "class-variance-authority"
-import { X } from "lucide-react"
+import * as React from 'react';
+import * as ToastPrimitives from '@radix-ui/react-toast';
+import { cva, type VariantProps } from 'class-variance-authority';
+import { X } from 'lucide-react';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
-const ToastProvider = ToastPrimitives.Provider
+const ToastProvider = ToastPrimitives.Provider;
const ToastViewport = React.forwardRef<
React.ElementRef,
@@ -14,29 +14,30 @@ const ToastViewport = React.forwardRef<
-))
-ToastViewport.displayName = ToastPrimitives.Viewport.displayName
+));
+ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
const toastVariants = cva(
- "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border border-neutral-200 p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full dark:border-neutral-800",
+ 'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border border-neutral-200 p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full dark:border-neutral-800',
{
variants: {
variant: {
- default: "border bg-white text-neutral-950 dark:bg-neutral-950 dark:text-neutral-50",
+ default:
+ 'border bg-white text-neutral-950 dark:bg-neutral-950 dark:text-neutral-50',
destructive:
- "destructive group border-red-500 bg-red-500 text-neutral-50 dark:border-red-900 dark:bg-red-900 dark:text-neutral-50",
+ 'destructive group border-red-500 bg-red-500 text-neutral-50 dark:border-red-900 dark:bg-red-900 dark:text-neutral-50',
},
},
defaultVariants: {
- variant: "default",
+ variant: 'default',
},
- }
-)
+ },
+);
const Toast = React.forwardRef<
React.ElementRef,
@@ -49,9 +50,9 @@ const Toast = React.forwardRef<
className={cn(toastVariants({ variant }), className)}
{...props}
/>
- )
-})
-Toast.displayName = ToastPrimitives.Root.displayName
+ );
+});
+Toast.displayName = ToastPrimitives.Root.displayName;
const ToastAction = React.forwardRef<
React.ElementRef,
@@ -60,13 +61,13 @@ const ToastAction = React.forwardRef<
-))
-ToastAction.displayName = ToastPrimitives.Action.displayName
+));
+ToastAction.displayName = ToastPrimitives.Action.displayName;
const ToastClose = React.forwardRef<
React.ElementRef,
@@ -75,16 +76,15 @@ const ToastClose = React.forwardRef<
+ {...props}>
-))
-ToastClose.displayName = ToastPrimitives.Close.displayName
+));
+ToastClose.displayName = ToastPrimitives.Close.displayName;
const ToastTitle = React.forwardRef<
React.ElementRef,
@@ -92,11 +92,11 @@ const ToastTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-ToastTitle.displayName = ToastPrimitives.Title.displayName
+));
+ToastTitle.displayName = ToastPrimitives.Title.displayName;
const ToastDescription = React.forwardRef<
React.ElementRef,
@@ -104,15 +104,15 @@ const ToastDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-ToastDescription.displayName = ToastPrimitives.Description.displayName
+));
+ToastDescription.displayName = ToastPrimitives.Description.displayName;
-type ToastProps = React.ComponentPropsWithoutRef
+type ToastProps = React.ComponentPropsWithoutRef;
-type ToastActionElement = React.ReactElement
+type ToastActionElement = React.ReactElement;
export {
type ToastProps,
@@ -124,4 +124,4 @@ export {
ToastDescription,
ToastClose,
ToastAction,
-}
+};
diff --git a/components/ui/toaster.tsx b/components/ui/toaster.tsx
index e223385..beb7f25 100644
--- a/components/ui/toaster.tsx
+++ b/components/ui/toaster.tsx
@@ -1,4 +1,4 @@
-"use client"
+'use client';
import {
Toast,
@@ -7,11 +7,11 @@ import {
ToastProvider,
ToastTitle,
ToastViewport,
-} from "@/components/ui/toast"
-import { useToast } from "@/components/ui/use-toast"
+} from '@/components/ui/toast';
+import { useToast } from '@/components/ui/use-toast';
export function Toaster() {
- const { toasts } = useToast()
+ const { toasts } = useToast();
return (
@@ -27,9 +27,9 @@ export function Toaster() {
{action}
- )
+ );
})}
- )
+ );
}
diff --git a/components/ui/use-toast.ts b/components/ui/use-toast.ts
index 90d8959..ba932c0 100644
--- a/components/ui/use-toast.ts
+++ b/components/ui/use-toast.ts
@@ -1,104 +1,101 @@
// Inspired by react-hot-toast library
-import * as React from "react"
+import * as React from 'react';
-import type {
- ToastActionElement,
- ToastProps,
-} from "@/components/ui/toast"
+import type { ToastActionElement, ToastProps } from '@/components/ui/toast';
-const TOAST_LIMIT = 1
-const TOAST_REMOVE_DELAY = 1000000
+const TOAST_LIMIT = 1;
+const TOAST_REMOVE_DELAY = 1000000;
type ToasterToast = ToastProps & {
- id: string
- title?: React.ReactNode
- description?: React.ReactNode
- action?: ToastActionElement
-}
+ id: string;
+ title?: React.ReactNode;
+ description?: React.ReactNode;
+ action?: ToastActionElement;
+};
const actionTypes = {
- ADD_TOAST: "ADD_TOAST",
- UPDATE_TOAST: "UPDATE_TOAST",
- DISMISS_TOAST: "DISMISS_TOAST",
- REMOVE_TOAST: "REMOVE_TOAST",
-} as const
+ ADD_TOAST: 'ADD_TOAST',
+ UPDATE_TOAST: 'UPDATE_TOAST',
+ DISMISS_TOAST: 'DISMISS_TOAST',
+ REMOVE_TOAST: 'REMOVE_TOAST',
+} as const;
-let count = 0
+let count = 0;
function genId() {
- count = (count + 1) % Number.MAX_VALUE
- return count.toString()
+ count = (count + 1) % Number.MAX_VALUE;
+ return count.toString();
}
-type ActionType = typeof actionTypes
+type ActionType = typeof actionTypes;
type Action =
| {
- type: ActionType["ADD_TOAST"]
- toast: ToasterToast
+ type: ActionType['ADD_TOAST'];
+ toast: ToasterToast;
}
| {
- type: ActionType["UPDATE_TOAST"]
- toast: Partial
+ type: ActionType['UPDATE_TOAST'];
+ toast: Partial;
}
| {
- type: ActionType["DISMISS_TOAST"]
- toastId?: ToasterToast["id"]
+ type: ActionType['DISMISS_TOAST'];
+ toastId?: ToasterToast['id'];
}
| {
- type: ActionType["REMOVE_TOAST"]
- toastId?: ToasterToast["id"]
- }
+ type: ActionType['REMOVE_TOAST'];
+ toastId?: ToasterToast['id'];
+ };
interface State {
- toasts: ToasterToast[]
+ toasts: ToasterToast[];
}
-const toastTimeouts = new Map>()
+const toastTimeouts = new Map>();
const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
- return
+ return;
}
const timeout = setTimeout(() => {
- toastTimeouts.delete(toastId)
+ toastTimeouts.delete(toastId);
dispatch({
- type: "REMOVE_TOAST",
+ type: 'REMOVE_TOAST',
toastId: toastId,
- })
- }, TOAST_REMOVE_DELAY)
+ });
+ }, TOAST_REMOVE_DELAY);
- toastTimeouts.set(toastId, timeout)
-}
+ toastTimeouts.set(toastId, timeout);
+};
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
- case "ADD_TOAST":
+ case 'ADD_TOAST':
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
- }
+ };
- case "UPDATE_TOAST":
+ case 'UPDATE_TOAST':
return {
...state,
toasts: state.toasts.map((t) =>
- t.id === action.toast.id ? { ...t, ...action.toast } : t
+ t.id === action.toast.id ? { ...t, ...action.toast } : t,
),
- }
+ };
- case "DISMISS_TOAST": {
- const { toastId } = action
+ case 'DISMISS_TOAST': {
+ const { toastId } = action;
// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
- addToRemoveQueue(toastId)
+ addToRemoveQueue(toastId);
} else {
state.toasts.forEach((toast) => {
- addToRemoveQueue(toast.id)
- })
+ addToRemoveQueue(toast.id);
+ });
}
return {
@@ -109,84 +106,84 @@ export const reducer = (state: State, action: Action): State => {
...t,
open: false,
}
- : t
+ : t,
),
- }
+ };
}
- case "REMOVE_TOAST":
+ case 'REMOVE_TOAST':
if (action.toastId === undefined) {
return {
...state,
toasts: [],
- }
+ };
}
return {
...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId),
- }
+ };
}
-}
+};
-const listeners: Array<(state: State) => void> = []
+const listeners: Array<(state: State) => void> = [];
-let memoryState: State = { toasts: [] }
+let memoryState: State = { toasts: [] };
function dispatch(action: Action) {
- memoryState = reducer(memoryState, action)
+ memoryState = reducer(memoryState, action);
listeners.forEach((listener) => {
- listener(memoryState)
- })
+ listener(memoryState);
+ });
}
-type Toast = Omit
+type Toast = Omit;
function toast({ ...props }: Toast) {
- const id = genId()
+ const id = genId();
const update = (props: ToasterToast) =>
dispatch({
- type: "UPDATE_TOAST",
+ type: 'UPDATE_TOAST',
toast: { ...props, id },
- })
- const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
+ });
+ const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id });
dispatch({
- type: "ADD_TOAST",
+ type: 'ADD_TOAST',
toast: {
...props,
id,
open: true,
onOpenChange: (open) => {
- if (!open) dismiss()
+ if (!open) dismiss();
},
},
- })
+ });
return {
id: id,
dismiss,
update,
- }
+ };
}
function useToast() {
- const [state, setState] = React.useState(memoryState)
+ const [state, setState] = React.useState(memoryState);
React.useEffect(() => {
- listeners.push(setState)
+ listeners.push(setState);
return () => {
- const index = listeners.indexOf(setState)
+ const index = listeners.indexOf(setState);
if (index > -1) {
- listeners.splice(index, 1)
+ listeners.splice(index, 1);
}
- }
- }, [state])
+ };
+ }, [state]);
return {
...state,
toast,
- dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
- }
+ dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }),
+ };
}
-export { useToast, toast }
+export { useToast, toast };
diff --git a/lib/utils.ts b/lib/utils.ts
index ec79801..9ad0df4 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -1,6 +1,6 @@
-import { type ClassValue, clsx } from "clsx"
-import { twMerge } from "tailwind-merge"
-
+import { type ClassValue, clsx } from 'clsx';
+import { twMerge } from 'tailwind-merge';
+
export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
+ return twMerge(clsx(inputs));
}
diff --git a/middleware/qna/recent-sessions.ts b/middleware/qna/recent-sessions.ts
new file mode 100644
index 0000000..eb61dc1
--- /dev/null
+++ b/middleware/qna/recent-sessions.ts
@@ -0,0 +1,16 @@
+import { Environment } from '@/common/environment-variables';
+import { populateRecentQNASessions } from '@/mocks/qna-session-mocks';
+
+function fetchRecentQNASessions() {
+ switch (Environment.ENVIRONMENT_TYPE) {
+ case 'development':
+ return populateRecentQNASessions;
+ case 'production':
+ // TODO: write fetchAPI instance for returning recent sessions via firestore
+ return [];
+ default:
+ return [];
+ }
+}
+
+export { fetchRecentQNASessions };
diff --git a/middleware/qna/sessions.ts b/middleware/qna/sessions.ts
new file mode 100644
index 0000000..f898b6e
--- /dev/null
+++ b/middleware/qna/sessions.ts
@@ -0,0 +1,16 @@
+import { Environment } from '@/common/environment-variables';
+import { populateTopics } from '@/mocks/qna-session-mocks';
+
+function fetchTopics() {
+ switch (Environment.ENVIRONMENT_TYPE) {
+ case 'development':
+ return populateTopics();
+ case 'production':
+ // TODO: Write fetch API method return data for user-topics from firestore
+ return [];
+ default:
+ return [];
+ }
+}
+
+export { fetchTopics };
diff --git a/mocks/qna-session-mocks.ts b/mocks/qna-session-mocks.ts
new file mode 100644
index 0000000..905c18c
--- /dev/null
+++ b/mocks/qna-session-mocks.ts
@@ -0,0 +1,64 @@
+const populateRecentQNASessions: Array = [
+ {
+ lastMessageContent: 'React Diffing Algorithm manages the changes',
+ title: 'Discussing how react diff works?',
+ sessionID: 'qna-9v38457t9857bt1',
+ },
+ {
+ lastMessageContent: 'React Diffing Algorithm manages the changes',
+ title: 'Discussing how react diff works?',
+ sessionID: 'qna-9v38457t9857bt2',
+ },
+ {
+ lastMessageContent: 'React Diffing Algorithm manages the changes',
+ title: 'Discussing how react diff works?',
+ sessionID: 'qna-9v38457t9857bt3',
+ },
+ {
+ lastMessageContent: 'React Diffing Algorithm manages the changes',
+ title: 'Discussing how react diff works?',
+ sessionID: 'qna-9v38457t9857bt4',
+ },
+ {
+ lastMessageContent: 'React Diffing Algorithm manages the changes',
+ title: 'Discussing how react diff works?',
+ sessionID: 'qna-9v38457t9857bt5',
+ },
+ {
+ lastMessageContent: 'React Diffing Algorithm manages the changes',
+ title: 'Discussing how react diff works?',
+ sessionID: 'qna-9v38457t9857bt6',
+ },
+ {
+ lastMessageContent: 'React Diffing Algorithm manages the changes',
+ title: 'Discussing how react diff works?',
+ sessionID: 'qna-9v38457t9857bt7',
+ },
+];
+
+function populateTopics(): Array {
+ return [
+ {
+ emoji: '🍕',
+ title: 'Frontend Engineering',
+ },
+ {
+ emoji: '⚙️',
+ title: 'Dynamic Programming',
+ },
+ {
+ emoji: '🧑🏽💻',
+ title: 'System Designing',
+ },
+ {
+ emoji: '🐍',
+ title: 'Python Programming',
+ },
+ {
+ emoji: '⚡️',
+ title: 'Javascript',
+ },
+ ];
+}
+
+export { populateRecentQNASessions, populateTopics };
diff --git a/next.config.js b/next.config.js
index 767719f..658404a 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,4 +1,4 @@
/** @type {import('next').NextConfig} */
-const nextConfig = {}
+const nextConfig = {};
-module.exports = nextConfig
+module.exports = nextConfig;
diff --git a/package-lock.json b/package-lock.json
index 5b56179..d296397 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
"dependencies": {
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-avatar": "^1.0.4",
- "@radix-ui/react-dialog": "^1.0.5",
+ "@radix-ui/react-dialog": "1.0.5",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-progress": "^1.0.3",
@@ -34,6 +34,7 @@
"eslint": "latest",
"eslint-config-next": "latest",
"postcss": "latest",
+ "prettier": "3.0.3",
"tailwindcss": "latest",
"typescript": "latest"
}
@@ -4154,6 +4155,21 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+ "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -7967,6 +7983,12 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
+ "prettier": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+ "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
+ "dev": true
+ },
"prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
diff --git a/package.json b/package.json
index 11bb080..35039aa 100644
--- a/package.json
+++ b/package.json
@@ -6,12 +6,14 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
- "lint": "next lint"
+ "lint": "next lint",
+ "lint-check": "prettier --check --ignore-path .gitignore .",
+ "lint-fix": "prettier --write --ignore-path .gitignore ."
},
"dependencies": {
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-avatar": "^1.0.4",
- "@radix-ui/react-dialog": "^1.0.5",
+ "@radix-ui/react-dialog": "1.0.5",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-progress": "^1.0.3",
@@ -35,6 +37,7 @@
"eslint": "latest",
"eslint-config-next": "latest",
"postcss": "latest",
+ "prettier": "3.0.3",
"tailwindcss": "latest",
"typescript": "latest"
}
diff --git a/postcss.config.js b/postcss.config.js
index 33ad091..12a703d 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {},
autoprefixer: {},
},
-}
+};
diff --git a/public/media/empty-state-graphic.svg b/public/media/empty-state-graphic.svg
new file mode 100644
index 0000000..4098597
--- /dev/null
+++ b/public/media/empty-state-graphic.svg
@@ -0,0 +1,7 @@
+
diff --git a/tailwind.config.js b/tailwind.config.js
index ae2ae4e..bde4049 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,36 +1,36 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
- darkMode: ["class"],
+ darkMode: ['class'],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
- ],
+ ],
theme: {
container: {
center: true,
- padding: "2rem",
+ padding: '2rem',
screens: {
- "2xl": "1400px",
+ '2xl': '1400px',
},
},
extend: {
keyframes: {
- "accordion-down": {
+ 'accordion-down': {
from: { height: 0 },
- to: { height: "var(--radix-accordion-content-height)" },
+ to: { height: 'var(--radix-accordion-content-height)' },
},
- "accordion-up": {
- from: { height: "var(--radix-accordion-content-height)" },
+ 'accordion-up': {
+ from: { height: 'var(--radix-accordion-content-height)' },
to: { height: 0 },
},
},
animation: {
- "accordion-down": "accordion-down 0.2s ease-out",
- "accordion-up": "accordion-up 0.2s ease-out",
+ 'accordion-down': 'accordion-down 0.2s ease-out',
+ 'accordion-up': 'accordion-up 0.2s ease-out',
},
},
},
- plugins: [require("tailwindcss-animate")],
-}
\ No newline at end of file
+ plugins: [require('tailwindcss-animate')],
+};
diff --git a/tailwind.config.ts b/tailwind.config.ts
index c7ead80..2686392 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -1,4 +1,4 @@
-import type { Config } from 'tailwindcss'
+import type { Config } from 'tailwindcss';
const config: Config = {
content: [
@@ -16,5 +16,5 @@ const config: Config = {
},
},
plugins: [],
-}
-export default config
+};
+export default config;
diff --git a/types/feature-card.d.ts b/types/feature-card.d.ts
new file mode 100644
index 0000000..173bc87
--- /dev/null
+++ b/types/feature-card.d.ts
@@ -0,0 +1,11 @@
+declare interface FeatureOptionInterface
+ extends React.HTMLAttributes {
+ featureName:
+ | 'Video Interview'
+ | 'ATS Resume Review'
+ | 'Topic Based Q/A'
+ | 'Mock Aptitude'
+ | 'Behavioural Rounds';
+ icon?: React.ReactNode;
+ link: string;
+}
diff --git a/types/qna-session.d.ts b/types/qna-session.d.ts
new file mode 100644
index 0000000..c5b1668
--- /dev/null
+++ b/types/qna-session.d.ts
@@ -0,0 +1,5 @@
+declare interface QNASessionCardInterface {
+ lastMessageContent: string;
+ title: string;
+ sessionID: string;
+}
diff --git a/types/user.d.ts b/types/user.d.ts
new file mode 100644
index 0000000..d6fbc94
--- /dev/null
+++ b/types/user.d.ts
@@ -0,0 +1,8 @@
+declare interface TopicInterface {
+ /**
+ * emoji defines the topic leadingicon
+ * @default "⚙️"
+ */
+ emoji: string | '⚙️';
+ title: string;
+}