Merge branch 'main' of https://hackethon.ai/hack/HackXlbef/FreeBug
commit
cc39f23efd
@ -0,0 +1,27 @@ |
|||||||
|
import string |
||||||
|
import hashlib |
||||||
|
import random |
||||||
|
import os |
||||||
|
from PyPDF2 import PdfReader |
||||||
|
|
||||||
|
FILE_NAME = 'manjil.pdf' |
||||||
|
FILE_PATH = os.path.join(os.getcwd(), FILE_NAME) |
||||||
|
|
||||||
|
def random_string_generator(string_length: int) -> str: |
||||||
|
letters = string.ascii_letters |
||||||
|
random_string = ''.join(random.choice(letters) for i in range(string_length)) |
||||||
|
return random_string |
||||||
|
|
||||||
|
def hash_string(string_value: str) ->str: |
||||||
|
return hashlib.sha256(string_value.encode('utf-8')).hexdigest() |
||||||
|
|
||||||
|
def read_pdf_human_readable(file_path: str) -> list[str]: |
||||||
|
pdf_page_text_contents: list = [] |
||||||
|
reader: PdfReader = PdfReader(file_path) |
||||||
|
for i, page in enumerate(reader.pages): |
||||||
|
text: str = page.extract_text() |
||||||
|
if text: |
||||||
|
pdf_page_text_contents.append(text.strip()) |
||||||
|
return pdf_page_text_contents |
||||||
|
|
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
{ |
||||||
|
"extends": ["next/core-web-vitals", "next/typescript"] |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. |
||||||
|
|
||||||
|
# dependencies |
||||||
|
/node_modules |
||||||
|
/.pnp |
||||||
|
.pnp.js |
||||||
|
.yarn/install-state.gz |
||||||
|
|
||||||
|
# testing |
||||||
|
/coverage |
||||||
|
|
||||||
|
# next.js |
||||||
|
/.next/ |
||||||
|
/out/ |
||||||
|
|
||||||
|
# production |
||||||
|
/build |
||||||
|
|
||||||
|
# misc |
||||||
|
.DS_Store |
||||||
|
*.pem |
||||||
|
|
||||||
|
# debug |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
|
||||||
|
# local env files |
||||||
|
.env*.local |
||||||
|
|
||||||
|
# vercel |
||||||
|
.vercel |
||||||
|
|
||||||
|
# typescript |
||||||
|
*.tsbuildinfo |
||||||
|
next-env.d.ts |
@ -0,0 +1,36 @@ |
|||||||
|
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). |
||||||
|
|
||||||
|
## Getting Started |
||||||
|
|
||||||
|
First, run the development server: |
||||||
|
|
||||||
|
```bash |
||||||
|
npm run dev |
||||||
|
# or |
||||||
|
yarn dev |
||||||
|
# or |
||||||
|
pnpm dev |
||||||
|
# or |
||||||
|
bun dev |
||||||
|
``` |
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. |
||||||
|
|
||||||
|
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. |
||||||
|
|
||||||
|
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. |
||||||
|
|
||||||
|
## Learn More |
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources: |
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. |
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. |
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! |
||||||
|
|
||||||
|
## Deploy on Vercel |
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. |
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"$schema": "https://ui.shadcn.com/schema.json", |
||||||
|
"style": "new-york", |
||||||
|
"rsc": true, |
||||||
|
"tsx": true, |
||||||
|
"tailwind": { |
||||||
|
"config": "tailwind.config.ts", |
||||||
|
"css": "src/app/globals.css", |
||||||
|
"baseColor": "gray", |
||||||
|
"cssVariables": true, |
||||||
|
"prefix": "" |
||||||
|
}, |
||||||
|
"aliases": { |
||||||
|
"components": "@/components", |
||||||
|
"utils": "@/lib/utils", |
||||||
|
"ui": "@/components/ui", |
||||||
|
"lib": "@/lib", |
||||||
|
"hooks": "@/hooks" |
||||||
|
}, |
||||||
|
"iconLibrary": "lucide" |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
/** @type {import('next').NextConfig} */ |
||||||
|
const nextConfig = {}; |
||||||
|
|
||||||
|
export default nextConfig; |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,33 @@ |
|||||||
|
{ |
||||||
|
"name": "edu-connect", |
||||||
|
"version": "0.1.0", |
||||||
|
"private": true, |
||||||
|
"scripts": { |
||||||
|
"dev": "next dev", |
||||||
|
"build": "next build", |
||||||
|
"start": "next start", |
||||||
|
"lint": "next lint" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"@radix-ui/react-navigation-menu": "^1.2.3", |
||||||
|
"@radix-ui/react-slot": "^1.1.1", |
||||||
|
"class-variance-authority": "^0.7.1", |
||||||
|
"clsx": "^2.1.1", |
||||||
|
"lucide-react": "^0.471.0", |
||||||
|
"next": "14.2.23", |
||||||
|
"react": "^18", |
||||||
|
"react-dom": "^18", |
||||||
|
"tailwind-merge": "^2.6.0", |
||||||
|
"tailwindcss-animate": "^1.0.7" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@types/node": "^20", |
||||||
|
"@types/react": "^18", |
||||||
|
"@types/react-dom": "^18", |
||||||
|
"eslint": "^8", |
||||||
|
"eslint-config-next": "14.2.23", |
||||||
|
"postcss": "^8", |
||||||
|
"tailwindcss": "^3.4.1", |
||||||
|
"typescript": "^5" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
/** @type {import('postcss-load-config').Config} */ |
||||||
|
const config = { |
||||||
|
plugins: { |
||||||
|
tailwindcss: {}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default config; |
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,78 @@ |
|||||||
|
@tailwind base; |
||||||
|
@tailwind components; |
||||||
|
@tailwind utilities; |
||||||
|
|
||||||
|
body { |
||||||
|
font-family: Arial, Helvetica, sans-serif; |
||||||
|
} |
||||||
|
|
||||||
|
@layer utilities { |
||||||
|
.text-balance { |
||||||
|
text-wrap: balance; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@layer base { |
||||||
|
:root { |
||||||
|
--background: 0 0% 100%; |
||||||
|
--foreground: 224 71.4% 4.1%; |
||||||
|
--card: 0 0% 100%; |
||||||
|
--card-foreground: 224 71.4% 4.1%; |
||||||
|
--popover: 0 0% 100%; |
||||||
|
--popover-foreground: 224 71.4% 4.1%; |
||||||
|
--primary: 220.9 39.3% 11%; |
||||||
|
--primary-foreground: 210 20% 98%; |
||||||
|
--secondary: 220 14.3% 95.9%; |
||||||
|
--secondary-foreground: 220.9 39.3% 11%; |
||||||
|
--muted: 220 14.3% 95.9%; |
||||||
|
--muted-foreground: 220 8.9% 46.1%; |
||||||
|
--accent: 220 14.3% 95.9%; |
||||||
|
--accent-foreground: 220.9 39.3% 11%; |
||||||
|
--destructive: 0 84.2% 60.2%; |
||||||
|
--destructive-foreground: 210 20% 98%; |
||||||
|
--border: 220 13% 91%; |
||||||
|
--input: 220 13% 91%; |
||||||
|
--ring: 224 71.4% 4.1%; |
||||||
|
--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: 0.5rem; |
||||||
|
} |
||||||
|
.dark { |
||||||
|
--background: 224 71.4% 4.1%; |
||||||
|
--foreground: 210 20% 98%; |
||||||
|
--card: 224 71.4% 4.1%; |
||||||
|
--card-foreground: 210 20% 98%; |
||||||
|
--popover: 224 71.4% 4.1%; |
||||||
|
--popover-foreground: 210 20% 98%; |
||||||
|
--primary: 210 20% 98%; |
||||||
|
--primary-foreground: 220.9 39.3% 11%; |
||||||
|
--secondary: 215 27.9% 16.9%; |
||||||
|
--secondary-foreground: 210 20% 98%; |
||||||
|
--muted: 215 27.9% 16.9%; |
||||||
|
--muted-foreground: 217.9 10.6% 64.9%; |
||||||
|
--accent: 215 27.9% 16.9%; |
||||||
|
--accent-foreground: 210 20% 98%; |
||||||
|
--destructive: 0 62.8% 30.6%; |
||||||
|
--destructive-foreground: 210 20% 98%; |
||||||
|
--border: 215 27.9% 16.9%; |
||||||
|
--input: 215 27.9% 16.9%; |
||||||
|
--ring: 216 12.2% 83.9%; |
||||||
|
--chart-1: 220 70% 50%; |
||||||
|
--chart-2: 160 60% 45%; |
||||||
|
--chart-3: 30 80% 55%; |
||||||
|
--chart-4: 280 65% 60%; |
||||||
|
--chart-5: 340 75% 55%; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@layer base { |
||||||
|
* { |
||||||
|
@apply border-border; |
||||||
|
} |
||||||
|
body { |
||||||
|
@apply bg-background text-foreground; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
import type { Metadata } from "next"; |
||||||
|
import localFont from "next/font/local"; |
||||||
|
import "./globals.css"; |
||||||
|
import { NavigationMenuWithIcons } from "@/components/common/Navbar/navMenu"; |
||||||
|
import Footer from "@/components/common/Footer/footer"; |
||||||
|
|
||||||
|
const geistSans = localFont({ |
||||||
|
src: "./fonts/GeistVF.woff", |
||||||
|
variable: "--font-geist-sans", |
||||||
|
weight: "100 900", |
||||||
|
}); |
||||||
|
const geistMono = localFont({ |
||||||
|
src: "./fonts/GeistMonoVF.woff", |
||||||
|
variable: "--font-geist-mono", |
||||||
|
weight: "100 900", |
||||||
|
}); |
||||||
|
|
||||||
|
export const metadata: Metadata = { |
||||||
|
title: "Create Next App", |
||||||
|
description: "Generated by create next app", |
||||||
|
}; |
||||||
|
|
||||||
|
export default function RootLayout({ |
||||||
|
children, |
||||||
|
}: Readonly<{ |
||||||
|
children: React.ReactNode; |
||||||
|
}>) { |
||||||
|
return ( |
||||||
|
<html lang="en"> |
||||||
|
<body |
||||||
|
className={`${geistSans.variable} ${geistMono.variable} antialiased`} |
||||||
|
> |
||||||
|
<NavigationMenuWithIcons /> |
||||||
|
{children} |
||||||
|
<Footer /> |
||||||
|
</body> |
||||||
|
</html> |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
import Image from "next/image"; |
||||||
|
|
||||||
|
export default function Home() { |
||||||
|
return ( |
||||||
|
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> |
||||||
|
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start"> |
||||||
|
<Image |
||||||
|
className="dark:invert" |
||||||
|
src="https://nextjs.org/icons/next.svg" |
||||||
|
alt="Next.js logo" |
||||||
|
width={180} |
||||||
|
height={38} |
||||||
|
priority |
||||||
|
/> |
||||||
|
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]"> |
||||||
|
<li className="mb-2"> |
||||||
|
Get started by editing{" "} |
||||||
|
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold"> |
||||||
|
src/app/page.tsx |
||||||
|
</code> |
||||||
|
. |
||||||
|
</li> |
||||||
|
<li>Save and see your changes instantly.</li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
<div className="flex gap-4 items-center flex-col sm:flex-row"> |
||||||
|
<a |
||||||
|
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5" |
||||||
|
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<Image |
||||||
|
className="dark:invert" |
||||||
|
src="https://nextjs.org/icons/vercel.svg" |
||||||
|
alt="Vercel logomark" |
||||||
|
width={20} |
||||||
|
height={20} |
||||||
|
/> |
||||||
|
Deploy now |
||||||
|
</a> |
||||||
|
<a |
||||||
|
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44" |
||||||
|
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
Read our docs |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</main> |
||||||
|
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center"> |
||||||
|
<a |
||||||
|
className="flex items-center gap-2 hover:underline hover:underline-offset-4" |
||||||
|
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<Image |
||||||
|
aria-hidden |
||||||
|
src="https://nextjs.org/icons/file.svg" |
||||||
|
alt="File icon" |
||||||
|
width={16} |
||||||
|
height={16} |
||||||
|
/> |
||||||
|
Learn |
||||||
|
</a> |
||||||
|
<a |
||||||
|
className="flex items-center gap-2 hover:underline hover:underline-offset-4" |
||||||
|
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<Image |
||||||
|
aria-hidden |
||||||
|
src="https://nextjs.org/icons/window.svg" |
||||||
|
alt="Window icon" |
||||||
|
width={16} |
||||||
|
height={16} |
||||||
|
/> |
||||||
|
Examples |
||||||
|
</a> |
||||||
|
<a |
||||||
|
className="flex items-center gap-2 hover:underline hover:underline-offset-4" |
||||||
|
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<Image |
||||||
|
aria-hidden |
||||||
|
src="https://nextjs.org/icons/globe.svg" |
||||||
|
alt="Globe icon" |
||||||
|
width={16} |
||||||
|
height={16} |
||||||
|
/> |
||||||
|
Go to nextjs.org → |
||||||
|
</a> |
||||||
|
</footer> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
|
||||||
|
import { Input } from "@/components/ui/input" |
||||||
|
import { Button } from "@/components/ui/button" |
||||||
|
import Link from "next/link" |
||||||
|
import { Facebook, Instagram, Linkedin, Twitter } from "lucide-react" |
||||||
|
|
||||||
|
|
||||||
|
export default function Footer() { |
||||||
|
return ( |
||||||
|
<section className="w-full py-12 md:py-24 lg:py-32 bg-zinc-900 dark:bg-zinc-100"> |
||||||
|
<div className="container px-4 md:px-6 flex flex-col items-center text-center"> |
||||||
|
<h2 className="text-2xl font-bold tracking-tighter sm:text-3xl md:text-4xl lg:text-5xl/none text-white"> |
||||||
|
Stay Connected |
||||||
|
</h2> |
||||||
|
<p className="mx-auto max-w-[700px] text-zinc-100 md:text-lg dark:text-zinc-800"> |
||||||
|
Subscribe to our newsletter and follow us on our social media. |
||||||
|
</p> |
||||||
|
<div className="w-full max-w-md space-y-2 my-4"> |
||||||
|
<form className="flex space-x-2"> |
||||||
|
<Input type="email" placeholder="Enter your email" className="max-w-lg flex-1 text-zinc-900 bg-white" /> |
||||||
|
<Button type="submit" variant="outline" className="text-white border-white"> |
||||||
|
Subscribe |
||||||
|
</Button> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
<div className="flex justify-center space-x-4"> |
||||||
|
<Link href="#" aria-label="Facebook page" className="text-white" prefetch={false}> |
||||||
|
<Facebook className="h-6 w-6" /> |
||||||
|
</Link> |
||||||
|
<Link href="#" aria-label="Twitter profile" className="text-white" prefetch={false}> |
||||||
|
<Twitter className="h-6 w-6" /> |
||||||
|
</Link> |
||||||
|
<Link href="#" aria-label="Instagram profile" className="text-white" prefetch={false}> |
||||||
|
<Instagram className="h-6 w-6" /> |
||||||
|
</Link> |
||||||
|
<Link href="#" aria-label="LinkedIn profile" className="text-white" prefetch={false}> |
||||||
|
<Linkedin className="h-6 w-6" /> |
||||||
|
</Link> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</section> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
// function FacebookIcon(props) {
|
||||||
|
// return (
|
||||||
|
// <svg
|
||||||
|
// {...props}
|
||||||
|
// xmlns="http://www.w3.org/2000/svg"
|
||||||
|
// width="24"
|
||||||
|
// height="24"
|
||||||
|
// viewBox="0 0 24 24"
|
||||||
|
// fill="none"
|
||||||
|
// stroke="currentColor"
|
||||||
|
// strokeWidth="2"
|
||||||
|
// strokeLinecap="round"
|
||||||
|
// strokeLinejoin="round"
|
||||||
|
// >
|
||||||
|
// <path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" />
|
||||||
|
// </svg>
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
@ -0,0 +1,129 @@ |
|||||||
|
import * as React from "react" |
||||||
|
import Link from "next/link" |
||||||
|
import { Home, Settings, Book, FileText, Bell, User } from "lucide-react" |
||||||
|
|
||||||
|
import { |
||||||
|
NavigationMenu, |
||||||
|
NavigationMenuContent, |
||||||
|
NavigationMenuItem, |
||||||
|
NavigationMenuLink, |
||||||
|
NavigationMenuList, |
||||||
|
NavigationMenuTrigger, |
||||||
|
navigationMenuTriggerStyle, |
||||||
|
} from "@/components/ui/navigation-menu" |
||||||
|
import { cn } from "@/lib/utils" |
||||||
|
|
||||||
|
const components = [ |
||||||
|
{ |
||||||
|
title: "Dashboard", |
||||||
|
href: "/dashboard", |
||||||
|
description: "Overview of your account and key metrics", |
||||||
|
icon: Home |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "Settings", |
||||||
|
href: "/settings", |
||||||
|
description: "Manage your account preferences and configuration", |
||||||
|
icon: Settings |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "Documentation", |
||||||
|
href: "/docs", |
||||||
|
description: "Detailed guides and API references", |
||||||
|
icon: Book |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "Reports", |
||||||
|
href: "/reports", |
||||||
|
description: "View and generate activity reports", |
||||||
|
icon: FileText |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "Notifications", |
||||||
|
href: "/notifications", |
||||||
|
description: "Manage your alerts and notifications", |
||||||
|
icon: Bell |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "Profile", |
||||||
|
href: "/profile", |
||||||
|
description: "View and edit your profile information", |
||||||
|
icon: User |
||||||
|
}, |
||||||
|
] |
||||||
|
|
||||||
|
export function NavigationMenuWithIcons() { |
||||||
|
return ( |
||||||
|
<NavigationMenu> |
||||||
|
<NavigationMenuList> |
||||||
|
<NavigationMenuItem> |
||||||
|
<NavigationMenuTrigger> |
||||||
|
<Home className="mr-2 h-4 w-4" /> |
||||||
|
Menu |
||||||
|
</NavigationMenuTrigger> |
||||||
|
<NavigationMenuContent> |
||||||
|
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> |
||||||
|
{components.map((component) => ( |
||||||
|
<ListItem |
||||||
|
key={component.title} |
||||||
|
title={component.title} |
||||||
|
href={component.href} |
||||||
|
icon={component.icon} |
||||||
|
> |
||||||
|
{component.description} |
||||||
|
</ListItem> |
||||||
|
))} |
||||||
|
</ul> |
||||||
|
</NavigationMenuContent> |
||||||
|
</NavigationMenuItem> |
||||||
|
|
||||||
|
<NavigationMenuItem> |
||||||
|
<Link href="/docs" legacyBehavior passHref> |
||||||
|
<NavigationMenuLink className={navigationMenuTriggerStyle()}> |
||||||
|
<Book className="mr-2 h-4 w-4" /> |
||||||
|
Documentation |
||||||
|
</NavigationMenuLink> |
||||||
|
</Link> |
||||||
|
</NavigationMenuItem> |
||||||
|
|
||||||
|
<NavigationMenuItem> |
||||||
|
<Link href="/profile" legacyBehavior passHref> |
||||||
|
<NavigationMenuLink className={navigationMenuTriggerStyle()}> |
||||||
|
<User className="mr-2 h-4 w-4" /> |
||||||
|
Profile |
||||||
|
</NavigationMenuLink> |
||||||
|
</Link> |
||||||
|
</NavigationMenuItem> |
||||||
|
</NavigationMenuList> |
||||||
|
</NavigationMenu> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const ListItem = React.forwardRef< |
||||||
|
React.ElementRef<"a">, |
||||||
|
React.ComponentPropsWithoutRef<"a"> & { icon?: React.ElementType } |
||||||
|
>(({ className, title, children, icon: Icon, ...props }, ref) => { |
||||||
|
return ( |
||||||
|
<li> |
||||||
|
<NavigationMenuLink asChild> |
||||||
|
<a |
||||||
|
ref={ref} |
||||||
|
className={cn( |
||||||
|
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", |
||||||
|
className |
||||||
|
)} |
||||||
|
{...props} |
||||||
|
> |
||||||
|
<div className="flex items-center text-sm font-medium leading-none"> |
||||||
|
{Icon && <Icon className="mr-2 h-4 w-4" />} |
||||||
|
{title} |
||||||
|
</div> |
||||||
|
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground mt-2"> |
||||||
|
{children} |
||||||
|
</p> |
||||||
|
</a> |
||||||
|
</NavigationMenuLink> |
||||||
|
</li> |
||||||
|
) |
||||||
|
}) |
||||||
|
ListItem.displayName = "ListItem" |
@ -0,0 +1,57 @@ |
|||||||
|
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" |
||||||
|
|
||||||
|
const buttonVariants = cva( |
||||||
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", |
||||||
|
{ |
||||||
|
variants: { |
||||||
|
variant: { |
||||||
|
default: |
||||||
|
"bg-primary text-primary-foreground shadow hover:bg-primary/90", |
||||||
|
destructive: |
||||||
|
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", |
||||||
|
outline: |
||||||
|
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", |
||||||
|
secondary: |
||||||
|
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", |
||||||
|
ghost: "hover:bg-accent hover:text-accent-foreground", |
||||||
|
link: "text-primary underline-offset-4 hover:underline", |
||||||
|
}, |
||||||
|
size: { |
||||||
|
default: "h-9 px-4 py-2", |
||||||
|
sm: "h-8 rounded-md px-3 text-xs", |
||||||
|
lg: "h-10 rounded-md px-8", |
||||||
|
icon: "h-9 w-9", |
||||||
|
}, |
||||||
|
}, |
||||||
|
defaultVariants: { |
||||||
|
variant: "default", |
||||||
|
size: "default", |
||||||
|
}, |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
export interface ButtonProps |
||||||
|
extends React.ButtonHTMLAttributes<HTMLButtonElement>, |
||||||
|
VariantProps<typeof buttonVariants> { |
||||||
|
asChild?: boolean |
||||||
|
} |
||||||
|
|
||||||
|
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( |
||||||
|
({ className, variant, size, asChild = false, ...props }, ref) => { |
||||||
|
const Comp = asChild ? Slot : "button" |
||||||
|
return ( |
||||||
|
<Comp |
||||||
|
className={cn(buttonVariants({ variant, size, className }))} |
||||||
|
ref={ref} |
||||||
|
{...props} |
||||||
|
/> |
||||||
|
) |
||||||
|
} |
||||||
|
) |
||||||
|
Button.displayName = "Button" |
||||||
|
|
||||||
|
export { Button, buttonVariants } |
@ -0,0 +1,22 @@ |
|||||||
|
import * as React from "react" |
||||||
|
|
||||||
|
import { cn } from "@/lib/utils" |
||||||
|
|
||||||
|
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>( |
||||||
|
({ className, type, ...props }, ref) => { |
||||||
|
return ( |
||||||
|
<input |
||||||
|
type={type} |
||||||
|
className={cn( |
||||||
|
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", |
||||||
|
className |
||||||
|
)} |
||||||
|
ref={ref} |
||||||
|
{...props} |
||||||
|
/> |
||||||
|
) |
||||||
|
} |
||||||
|
) |
||||||
|
Input.displayName = "Input" |
||||||
|
|
||||||
|
export { Input } |
@ -0,0 +1,128 @@ |
|||||||
|
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" |
||||||
|
|
||||||
|
const NavigationMenu = React.forwardRef< |
||||||
|
React.ElementRef<typeof NavigationMenuPrimitive.Root>, |
||||||
|
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root> |
||||||
|
>(({ className, children, ...props }, ref) => ( |
||||||
|
<NavigationMenuPrimitive.Root |
||||||
|
ref={ref} |
||||||
|
className={cn( |
||||||
|
"relative z-10 flex max-w-max flex-1 items-center justify-center", |
||||||
|
className |
||||||
|
)} |
||||||
|
{...props} |
||||||
|
> |
||||||
|
{children} |
||||||
|
<NavigationMenuViewport /> |
||||||
|
</NavigationMenuPrimitive.Root> |
||||||
|
)) |
||||||
|
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName |
||||||
|
|
||||||
|
const NavigationMenuList = React.forwardRef< |
||||||
|
React.ElementRef<typeof NavigationMenuPrimitive.List>, |
||||||
|
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List> |
||||||
|
>(({ className, ...props }, ref) => ( |
||||||
|
<NavigationMenuPrimitive.List |
||||||
|
ref={ref} |
||||||
|
className={cn( |
||||||
|
"group flex flex-1 list-none items-center justify-center space-x-1", |
||||||
|
className |
||||||
|
)} |
||||||
|
{...props} |
||||||
|
/> |
||||||
|
)) |
||||||
|
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName |
||||||
|
|
||||||
|
const NavigationMenuItem = NavigationMenuPrimitive.Item |
||||||
|
|
||||||
|
const navigationMenuTriggerStyle = cva( |
||||||
|
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50" |
||||||
|
) |
||||||
|
|
||||||
|
const NavigationMenuTrigger = React.forwardRef< |
||||||
|
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>, |
||||||
|
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger> |
||||||
|
>(({ className, children, ...props }, ref) => ( |
||||||
|
<NavigationMenuPrimitive.Trigger |
||||||
|
ref={ref} |
||||||
|
className={cn(navigationMenuTriggerStyle(), "group", className)} |
||||||
|
{...props} |
||||||
|
> |
||||||
|
{children}{" "} |
||||||
|
<ChevronDown |
||||||
|
className="relative top-[1px] ml-1 h-3 w-3 transition duration-300 group-data-[state=open]:rotate-180" |
||||||
|
aria-hidden="true" |
||||||
|
/> |
||||||
|
</NavigationMenuPrimitive.Trigger> |
||||||
|
)) |
||||||
|
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName |
||||||
|
|
||||||
|
const NavigationMenuContent = React.forwardRef< |
||||||
|
React.ElementRef<typeof NavigationMenuPrimitive.Content>, |
||||||
|
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content> |
||||||
|
>(({ className, ...props }, ref) => ( |
||||||
|
<NavigationMenuPrimitive.Content |
||||||
|
ref={ref} |
||||||
|
className={cn( |
||||||
|
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ", |
||||||
|
className |
||||||
|
)} |
||||||
|
{...props} |
||||||
|
/> |
||||||
|
)) |
||||||
|
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName |
||||||
|
|
||||||
|
const NavigationMenuLink = NavigationMenuPrimitive.Link |
||||||
|
|
||||||
|
const NavigationMenuViewport = React.forwardRef< |
||||||
|
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>, |
||||||
|
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport> |
||||||
|
>(({ className, ...props }, ref) => ( |
||||||
|
<div className={cn("absolute left-0 top-full flex justify-center")}> |
||||||
|
<NavigationMenuPrimitive.Viewport |
||||||
|
className={cn( |
||||||
|
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]", |
||||||
|
className |
||||||
|
)} |
||||||
|
ref={ref} |
||||||
|
{...props} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
)) |
||||||
|
NavigationMenuViewport.displayName = |
||||||
|
NavigationMenuPrimitive.Viewport.displayName |
||||||
|
|
||||||
|
const NavigationMenuIndicator = React.forwardRef< |
||||||
|
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>, |
||||||
|
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator> |
||||||
|
>(({ className, ...props }, ref) => ( |
||||||
|
<NavigationMenuPrimitive.Indicator |
||||||
|
ref={ref} |
||||||
|
className={cn( |
||||||
|
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in", |
||||||
|
className |
||||||
|
)} |
||||||
|
{...props} |
||||||
|
> |
||||||
|
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" /> |
||||||
|
</NavigationMenuPrimitive.Indicator> |
||||||
|
)) |
||||||
|
NavigationMenuIndicator.displayName = |
||||||
|
NavigationMenuPrimitive.Indicator.displayName |
||||||
|
|
||||||
|
export { |
||||||
|
navigationMenuTriggerStyle, |
||||||
|
NavigationMenu, |
||||||
|
NavigationMenuList, |
||||||
|
NavigationMenuItem, |
||||||
|
NavigationMenuContent, |
||||||
|
NavigationMenuTrigger, |
||||||
|
NavigationMenuLink, |
||||||
|
NavigationMenuIndicator, |
||||||
|
NavigationMenuViewport, |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
import { clsx, type ClassValue } from "clsx" |
||||||
|
import { twMerge } from "tailwind-merge" |
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) { |
||||||
|
return twMerge(clsx(inputs)) |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
import type { Config } from "tailwindcss"; |
||||||
|
|
||||||
|
const config: Config = { |
||||||
|
darkMode: ["class"], |
||||||
|
content: [ |
||||||
|
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}", |
||||||
|
"./src/components/**/*.{js,ts,jsx,tsx,mdx}", |
||||||
|
"./src/app/**/*.{js,ts,jsx,tsx,mdx}", |
||||||
|
], |
||||||
|
theme: { |
||||||
|
extend: { |
||||||
|
colors: { |
||||||
|
background: 'hsl(var(--background))', |
||||||
|
foreground: 'hsl(var(--foreground))', |
||||||
|
card: { |
||||||
|
DEFAULT: 'hsl(var(--card))', |
||||||
|
foreground: 'hsl(var(--card-foreground))' |
||||||
|
}, |
||||||
|
popover: { |
||||||
|
DEFAULT: 'hsl(var(--popover))', |
||||||
|
foreground: 'hsl(var(--popover-foreground))' |
||||||
|
}, |
||||||
|
primary: { |
||||||
|
DEFAULT: 'hsl(var(--primary))', |
||||||
|
foreground: 'hsl(var(--primary-foreground))' |
||||||
|
}, |
||||||
|
secondary: { |
||||||
|
DEFAULT: 'hsl(var(--secondary))', |
||||||
|
foreground: 'hsl(var(--secondary-foreground))' |
||||||
|
}, |
||||||
|
muted: { |
||||||
|
DEFAULT: 'hsl(var(--muted))', |
||||||
|
foreground: 'hsl(var(--muted-foreground))' |
||||||
|
}, |
||||||
|
accent: { |
||||||
|
DEFAULT: 'hsl(var(--accent))', |
||||||
|
foreground: 'hsl(var(--accent-foreground))' |
||||||
|
}, |
||||||
|
destructive: { |
||||||
|
DEFAULT: 'hsl(var(--destructive))', |
||||||
|
foreground: 'hsl(var(--destructive-foreground))' |
||||||
|
}, |
||||||
|
border: 'hsl(var(--border))', |
||||||
|
input: 'hsl(var(--input))', |
||||||
|
ring: 'hsl(var(--ring))', |
||||||
|
chart: { |
||||||
|
'1': 'hsl(var(--chart-1))', |
||||||
|
'2': 'hsl(var(--chart-2))', |
||||||
|
'3': 'hsl(var(--chart-3))', |
||||||
|
'4': 'hsl(var(--chart-4))', |
||||||
|
'5': 'hsl(var(--chart-5))' |
||||||
|
} |
||||||
|
}, |
||||||
|
borderRadius: { |
||||||
|
lg: 'var(--radius)', |
||||||
|
md: 'calc(var(--radius) - 2px)', |
||||||
|
sm: 'calc(var(--radius) - 4px)' |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
plugins: [require("tailwindcss-animate")], |
||||||
|
}; |
||||||
|
export default config; |
@ -0,0 +1,26 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"lib": ["dom", "dom.iterable", "esnext"], |
||||||
|
"allowJs": true, |
||||||
|
"skipLibCheck": true, |
||||||
|
"strict": true, |
||||||
|
"noEmit": true, |
||||||
|
"esModuleInterop": true, |
||||||
|
"module": "esnext", |
||||||
|
"moduleResolution": "bundler", |
||||||
|
"resolveJsonModule": true, |
||||||
|
"isolatedModules": true, |
||||||
|
"jsx": "preserve", |
||||||
|
"incremental": true, |
||||||
|
"plugins": [ |
||||||
|
{ |
||||||
|
"name": "next" |
||||||
|
} |
||||||
|
], |
||||||
|
"paths": { |
||||||
|
"@/*": ["./src/*"] |
||||||
|
} |
||||||
|
}, |
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], |
||||||
|
"exclude": ["node_modules"] |
||||||
|
} |
Loading…
Reference in new issue