Merge branch 'main' into contracts-merge

This commit is contained in:
2024-10-26 12:39:47 +01:00
committed by GitHub
38 changed files with 1590 additions and 117 deletions

View File

@@ -1,2 +1,2 @@
#!/usr/bin/env sh #!/usr/bin/env sh
npx lint-staged && npm run build npx lint-staged && npm run build

5
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

12
.idea/Event-Chain.iml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

65
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,65 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<HTMLCodeStyleSettings>
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
</HTMLCodeStyleSettings>
<JSCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
</JSCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<TypeScriptCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
</TypeScriptCodeStyleSettings>
<VueCodeStyleSettings>
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
</VueCodeStyleSettings>
<codeStyleSettings language="HTML">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="TypeScript">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="Vue">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Event-Chain.iml" filepath="$PROJECT_DIR$/.idea/Event-Chain.iml" />
</modules>
</component>
</project>

6
.idea/prettier.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PrettierConfiguration">
<option name="myConfigurationMode" value="AUTOMATIC" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

79
app/Home.tsx Normal file
View File

@@ -0,0 +1,79 @@
'use client';
import { useEffect, useState } from 'react';
import Header from '../components/custom/header';
import Footer from '../components/custom/footer';
import Test from '../components/scripts/Test';
import MetaMask from '../components/scripts/MetaMask';
export default function Home() {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return (
<>
<Header />
<div className="relative min-h-screen overflow-hidden">
{/* Video Background */}
{isClient && (
<video
autoPlay
loop
muted
className="absolute inset-0 w-full h-full object-cover z-0"
src="BGVid2.mp4"
>
Your browser does not support the video tag.
</video>
)}
{/* Dark Overlay for Enhanced Readability */}
<div className="absolute inset-0 bg-black opacity-50 z-10"></div>
{/* Page Content Over the Video */}
<div className="relative z-20 min-h-screen bg-gradient-to-b from-transparent to-gray-900 pt-16">
<div className="container mx-auto p-4">
<input
type="text"
placeholder="Search events..."
className="search-bar mt-4 p-2 border border-gray-300 rounded w-full max-w-md mx-auto"
/>
<main>
<section className="mb-8">
<h2 className="text-2xl font-semibold text-white mb-4">
Featured Events
</h2>
<p className="text-gray-300">
No events available at the moment.
</p>
</section>
<section>
<h2 className="text-2xl font-semibold text-white mb-4">
Upcoming Events
</h2>
<ul className="list-disc list-inside text-gray-300">
<li>Event 1 - Date</li>
<li>Event 2 - Date</li>
<li>Event 3 - Date</li>
</ul>
</section>
</main>
<Footer />
</div>
</div>
</div>
<main>
<section className="mb-8">
<Test />
</section>
<section className="mb-8">
<MetaMask />
</section>
<Footer />
</main>
</>
);
}

View File

@@ -0,0 +1,149 @@
'use client';
import React, { useEffect, useState } from 'react';
import Header from '../../components/custom/header';
import Footer from '../../components/custom/footer';
// Define the Event interface including new fields
interface Event {
EventID: number;
name: string;
date: string;
location: string;
ticketPrice: string;
description: string;
capacity: number;
ticketsSold: number;
imageUrl: string;
}
// Dummy function to fetch events
const fetchEvents = (): Event[] => {
return [
{
EventID: 1,
name: 'Rock Concert',
date: '2023-12-01',
location: 'New York City',
ticketPrice: '$99',
description: 'An exhilarating rock concert featuring famous bands.',
capacity: 5000,
ticketsSold: 4500,
imageUrl: 'https://via.placeholder.com/150',
},
{
EventID: 2,
name: 'Art Expo',
date: '2023-11-15',
location: 'San Francisco',
ticketPrice: '$55',
description: 'A showcase of modern art from around the world.',
capacity: 300,
ticketsSold: 260,
imageUrl: 'https://via.placeholder.com/150',
},
{
EventID: 3,
name: 'Tech Summit 2023',
date: '2023-12-10',
location: 'Chicago',
ticketPrice: '$250',
description: 'The leading tech summit with top industry speakers.',
capacity: 2000,
ticketsSold: 1800,
imageUrl: 'https://via.placeholder.com/150',
},
];
};
const TicketListing: React.FC = () => {
const [events, setEvents] = useState<Event[]>([]);
const [hoveredEventId, setHoveredEventId] = useState<number | null>(null);
useEffect(() => {
const eventsData = fetchEvents();
setEvents(eventsData);
}, []);
return (
<div className="relative min-h-screen overflow-hidden">
<Header />
{/* Video Background */}
<video
autoPlay
loop
muted
className="absolute inset-0 w-full h-full object-cover z-0"
src="BGVid1.mp4"
>
Your browser does not support the video tag.
</video>
{/* Overlay for Readability */}
<div className="absolute inset-0 bg-black opacity-50 z-10"></div>
{/* Main Content */}
<div className="relative z-20 container mx-auto p-4 pt-16">
<div className="mb-6">
<input
type="text"
placeholder="Search events..."
className="search-bar mt-4 p-2 border border-gray-300 rounded w-full max-w-md"
/>
<div className="flex mt-4 space-x-4">
<button className="bg-blue-500 text-white px-4 py-2 rounded">
Sort
</button>
<button className="bg-blue-500 text-white px-4 py-2 rounded">
Filter
</button>
</div>
</div>
<main>
<section>
<h2 className="text-2xl font-semibold text-white mb-4">
Available Events
</h2>
<div className="grid grid-cols-1 gap-6">
{events.map((event) => (
<div
key={event.EventID}
className="relative flex bg-white p-4 rounded-lg shadow-lg"
onMouseEnter={() => setHoveredEventId(event.EventID)}
onMouseLeave={() => setHoveredEventId(null)}
>
<img
src={event.imageUrl}
alt={event.name}
className="w-1/4 rounded-lg"
/>
<div className="ml-4 relative">
<h3 className="text-xl font-bold">{event.name}</h3>
<p className="text-gray-600">{event.date}</p>
<p className="text-gray-600">{event.location}</p>
<p className="text-gray-800 font-semibold">
{event.ticketPrice}
</p>
{event.ticketsSold / event.capacity >= 0.9 && (
<div className="mt-2 p-2 bg-yellow-300 text-black rounded">
Limited Tickets Remaining!
</div>
)}
</div>
<div className="absolute top-0 right-0 flex items-center space-x-2">
{hoveredEventId === event.EventID && (
<div className="top-0 left-4 w-full bg-white p-4 shadow-lg rounded-lg z-10">
<p>{event.description}</p>
</div>
)}
</div>
</div>
))}
</div>
</section>
</main>
</div>
<Footer />
</div>
);
};
export default TicketListing;

View File

@@ -0,0 +1,9 @@
import TicketListings from './TicketListings';
export default function Page() {
return (
<>
<TicketListings />
</>
);
}

View File

@@ -1,21 +1,26 @@
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import localFont from 'next/font/local'; // import localFont from 'next/font/local';
import './globals.css'; import './globals.css';
const geistSans = localFont({ import { Inter } from 'next/font/google';
src: './fonts/GeistVF.woff', import './globals.css';
variable: '--font-geist-sans',
weight: '100 900', const inter = Inter({ subsets: ['latin'] });
});
const geistMono = localFont({ // const geistSans = localFont({
src: './fonts/GeistMonoVF.woff', // src: './fonts/GeistVF.woff',
variable: '--font-geist-mono', // variable: '--font-geist-sans',
weight: '100 900', // weight: '100 900',
}); // });
// const geistMono = localFont({
// src: './fonts/GeistMonoVF.woff',
// variable: '--font-geist-mono',
// weight: '100 900',
// });
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Create Next App', title: 'Ticket Chain',
description: 'Generated by create next app', description: 'A blockchain-based ticketing system.',
}; };
export default function RootLayout({ export default function RootLayout({
@@ -25,11 +30,7 @@ export default function RootLayout({
}>) { }>) {
return ( return (
<html lang="en"> <html lang="en">
<body <body className={inter.className}>{children}</body>
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html> </html>
); );
} }

View File

@@ -1,101 +1,9 @@
import Image from 'next/image'; import Home from './Home';
export default function Home() { export default function Page() {
return ( 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"> <Home />
<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">
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>
); );
} }

View File

@@ -0,0 +1,64 @@
'use client';
import React from 'react';
import {
Card,
CardHeader,
CardContent,
CardFooter,
} from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
import { Button } from '@/components/ui/button';
import { CheckCircle } from 'lucide-react';
interface props {
ticketTitle: string;
eventDate: string;
ticketID: string;
}
const ConfirmationTicket = ({ ticketTitle, eventDate, ticketID }: props) => {
return (
<Card
className="max-w-md mx-auto bg-blue-900 text-blue-100 rounded-xl shadow-md p-6
transition-all duration-300 hover:shadow-[0px_0px_20px_5px_rgba(59,130,246,0.5)]"
>
<CardHeader className="flex flex-col items-center space-y-4">
<CheckCircle className="text-green-400 w-10 h-10" />
<h1 className="text-2xl font-semibold text-blue-50">
Ticket Confirmed!
</h1>
<Badge
variant="outline"
className="text-blue-200 bg-blue-800 px-3 py-1 rounded-full"
>
#{ticketID}
</Badge>
</CardHeader>
<CardContent className="text-center">
<Separator className="my-4 border-blue-700" />
<h2 className="text-lg font-medium">{ticketTitle}</h2>
<p className="text-blue-300 mt-2">Event Date: {eventDate}</p>
<Separator className="my-4 border-blue-700" />
</CardContent>
<CardFooter className="flex flex-col items-center space-y-3">
<Button
variant="default"
className="w-full bg-blue-700 text-blue-100 font-semibold rounded-lg hover:bg-blue-600"
>
View Ticket
</Button>
<Button
variant="outline"
className="w-full text-blue-200 border-blue-700 hover:bg-blue-800"
>
Download PDF
</Button>
</CardFooter>
</Card>
);
};
export default ConfirmationTicket;

18
components/EventPage.tsx Normal file
View File

@@ -0,0 +1,18 @@
import React from 'react';
const EventPage = () => {
return (
// <>Header</>
// <EventDescription>
// <Footer>
<div
className="relative bg-black-100 flex
justify-center items-center, flex-col overflow-hidden
mx-auto sm:px-10 px-5"
>
<div className="max-w-7xl w-full"></div>
</div>
);
};
export default EventPage;

93
components/Profile.tsx Normal file
View File

@@ -0,0 +1,93 @@
'use client';
import * as React from 'react';
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { motion } from 'framer-motion';
// Dark theme and animation setup
const cardVariants = {
hidden: { opacity: 0, y: 10 },
visible: { opacity: 1, y: 0 },
};
const Profile = () => {
return (
<motion.div
initial="hidden"
animate="visible"
variants={cardVariants}
transition={{ duration: 0.5, ease: 'easeOut' }}
>
<Card className="w-[350px] bg-[#1e2a3a] text-white shadow-lg">
<CardHeader>
<motion.div
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1, duration: 0.5 }}
>
<CardTitle className="text-lg font-semibold">Profile</CardTitle>
</motion.div>
</CardHeader>
<CardContent>
<form>
<div className="grid w-full items-center gap-4">
<motion.div
className="flex flex-col space-y-1.5"
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.2, duration: 0.4 }}
>
<Label htmlFor="name" className="text-gray-300">
Name
</Label>
<Input
id="name"
placeholder="Name"
className="bg-[#2b3a4a] text-white placeholder-gray-400"
/>
</motion.div>
<motion.div
className="flex flex-col space-y-1.5"
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.3, duration: 0.4 }}
>
<Label htmlFor="framework" className="text-gray-300">
MetaMask Public Key
</Label>
<Input
id="name"
placeholder="Key"
className="bg-[#2b3a4a] text-white placeholder-gray-400"
/>
</motion.div>
</div>
</form>
</CardContent>
<CardFooter className="flex justify-between">
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4, duration: 0.4 }}
>
<Button className="bg-[#365b85] text-white hover:bg-[#2b4a70]">
Save
</Button>
</motion.div>
</CardFooter>
</Card>
</motion.div>
);
};
export default Profile;
// return <EventDescription/>
// return <ConfirmationTicket ticketTitle='taylor swift' ticketID='2' eventDate='27th september'/>;
// return <Profile/>;

View File

@@ -0,0 +1,7 @@
import React from 'react';
const WalletAdapter = () => {
return <div>WalletAdapter</div>;
};
export default WalletAdapter;

View File

@@ -0,0 +1,7 @@
import React from 'react';
const BuyTicket = () => {
return <div>BuyTicket</div>;
};
export default BuyTicket;

View File

@@ -0,0 +1,61 @@
'use client';
import React from 'react';
import {
Card,
CardHeader,
CardContent,
CardFooter,
} from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
import ImageCarousel from './ImageCarousel';
import TicketButton from './TicketButton';
const EventDescription = () => {
return (
<Card className="pt-10 pb-16 px-6 bg-gradient-to-r from-blue-50 to-gray-50 rounded-xl shadow-lg max-w-4xl mx-auto">
<CardHeader className="flex flex-col items-start space-y-4">
<h1 className="text-3xl font-semibold text-gray-800">TicketTitle</h1>
<Badge
variant="outline"
className="text-blue-600 bg-blue-100 px-3 py-1 rounded-full"
>
Price: $99
</Badge>
</CardHeader>
<CardContent className="flex flex-col md:flex-row items-start space-y-8 md:space-y-0 md:space-x-10">
<div className="md:w-1/2 flex justify-center">
<ImageCarousel />
</div>
<div className="md:w-1/2 text-gray-700">
<Separator className="my-4" />
<p className="leading-relaxed">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem
ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum
dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</p>
<Separator className="my-4" />
</div>
</CardContent>
<CardFooter className="flex flex-col md:flex-row items-center justify-between space-y-4 md:space-y-0">
<Button
variant="default"
className="w-full md:w-auto bg-gradient-to-r from-blue-500 to-purple-600 text-white font-semibold rounded-lg hover:from-blue-600 hover:to-purple-700"
>
Buy now Using MetaMask
</Button>
<div className="relative md:left-5">
<TicketButton />
</div>
</CardFooter>
</Card>
);
};
export default EventDescription;

View File

@@ -0,0 +1,33 @@
import * as React from 'react';
import { Card, CardContent } from '@/components/ui/card';
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from '@/components/ui/carousel';
export default function ImageCarousel() {
return (
<Carousel className="w-full max-w-xs">
<CarouselContent>
{/* map your images here from the page */}
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index}>
<div className="p-1">
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-4xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
);
}

View File

@@ -0,0 +1,53 @@
'use client';
import React, { useState } from 'react';
import { Button } from '../ui/button'; // Adjust import path to where your shadcn Button component is located
interface NumberPickerProps {
initialCount?: number;
min?: number;
max?: number;
onChange?: (count: number) => void;
}
const NumberPicker: React.FC<NumberPickerProps> = ({
initialCount = 1,
min = 1,
max = 10,
onChange,
}) => {
const [count, setCount] = useState<number>(initialCount);
const increment = () => {
if (count < max) {
const newCount = count + 1;
setCount(newCount);
if (onChange) {
onChange(newCount);
}
}
};
const decrement = () => {
if (count > min) {
const newCount = count - 1;
setCount(newCount);
if (onChange) {
onChange(newCount);
}
}
};
return (
<div className="flex items-center space-x-2">
<Button variant="outline" onClick={decrement} disabled={count === min}>
-
</Button>
<span className="text-center w-8">{count}</span>
<Button variant="outline" onClick={increment} disabled={count === max}>
+
</Button>
</div>
);
};
export default NumberPicker;

View File

@@ -0,0 +1,12 @@
import React from 'react';
const Footer = () => {
return (
<footer className="text-center mt-8">
<p className="text-gray-500">
&copy; 2024 Ticket Chain. All rights reserved.
</p>
</footer>
);
};
export default Footer;

View File

@@ -0,0 +1,72 @@
'use client';
import React, { useState } from 'react';
import Link from 'next/link';
import MetaMask from '../scripts/MetaMask';
const Header = () => {
const [mouseX, setMouseX] = useState(-1);
const [mouseY, setMouseY] = useState(-1);
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
setMouseX(e.clientX);
setMouseY(e.clientY);
};
const handleMouseLeave = () => {
setMouseX(-1);
setMouseY(-1);
};
return (
<div
className="fixed top-0 left-0 right-0 backdrop-blur-md bg-opacity-60 z-50"
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
>
<div
className="absolute inset-0 pointer-events-none"
style={{
border: '1px solid transparent',
background:
mouseX >= 0 && mouseY >= 0
? `radial-gradient(circle at ${mouseX}px ${mouseY}px, rgba(255, 255, 255, 0.4), transparent 20%)`
: 'none',
backgroundClip: 'padding-box, border-box',
}}
></div>
<div className="container mx-auto px-6 py-4 flex justify-between items-center">
<h1 className="text-2xl font-Ariel-bold text-white">TicketChain</h1>
<nav className="nav">
<ul className="flex space-x-6">
<li>
<Link href="/" legacyBehavior>
<a className="text-white hover:text-blue-500 transition-colors duration-300">
Home
</a>
</Link>
</li>
<li>
<Link href="/TicketListings" legacyBehavior>
<a className="text-white hover:text-blue-500 transition-colors duration-300">
Events
</a>
</Link>
</li>
<li>
<Link href="/contact" legacyBehavior>
<a className="text-white hover:text-blue-500 transition-colors duration-300">
Contact
</a>
</Link>
</li>
<li>
<MetaMask />
</li>
</ul>
</nav>
</div>
</div>
);
};
export default Header;

View File

@@ -0,0 +1,117 @@
'use client';
import React, { useEffect, useState } from 'react';
import { useSDK, MetaMaskProvider } from '@metamask/sdk-react';
import { Button } from '@/components/ui/button';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
function WalletIcon(props: React.SVGProps<SVGSVGElement>) {
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="M21 12V7H5a2 2 0 0 1 0-4h14v4" />
<path d="M3 5v14a2 2 0 0 0 2 2h16v-5" />
<path d="M18 12a2 2 0 0 0 0 4h4v-4Z" />
</svg>
);
}
function formatAddress(address: string | undefined): string {
if (!address) return '';
return `${address.slice(0, 6)}...${address.slice(-4)}`;
}
function MetaMaskConnect() {
const { sdk, connected, connecting, account } = useSDK();
const [metaMaskInstalled, setMetaMaskInstalled] = useState(false);
const isMetaMaskInstalled = () =>
typeof window !== 'undefined' && typeof window.ethereum !== 'undefined';
useEffect(() => {
if (isMetaMaskInstalled()) {
setMetaMaskInstalled(true);
}
}, []);
const connect = async () => {
try {
await sdk?.connect();
} catch (err) {
console.warn(`No accounts found`, err);
}
};
const disconnect = () => {
if (sdk) {
sdk.terminate();
}
};
if (!metaMaskInstalled) {
return (
<Button
onClick={() =>
window.open('https://metamask.io/download.html', '_blank')
}
className="bg-gradient-to-r from-blue-500 to-indigo-700"
>
Install MetaMask
</Button>
);
}
return (
<div className="relative">
{connected ? (
<Popover>
<PopoverTrigger asChild>
<Button>{formatAddress(account)}</Button>
</PopoverTrigger>
<PopoverContent className="w-44">
<button
onClick={disconnect}
className="w-full px-4 py-2 text-left text-destructive hover:bg-muted"
>
Disconnect
</button>
</PopoverContent>
</Popover>
) : (
<Button disabled={connecting} onClick={connect}>
<WalletIcon className="mr-2 h-4 w-4" /> Connect Wallet
</Button>
)}
</div>
);
}
export default function MetaMaskConnectWrapper() {
return (
<MetaMaskProvider
debug={false}
sdkOptions={{
dappMetadata: {
name: 'My dApp',
url: typeof window !== 'undefined' ? window.location.href : '',
},
}}
>
<MetaMaskConnect />
</MetaMaskProvider>
);
}

View File

@@ -0,0 +1,16 @@
'use client';
import React, { useEffect } from 'react';
const Test = () => {
useEffect(() => {
console.log('Print some shit');
}, []);
return (
<div>
<p>Hellao!</p>
</div>
);
};
export default Test;

36
components/ui/badge.tsx Normal file
View File

@@ -0,0 +1,36 @@
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';
const badgeVariants = cva(
'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
{
variants: {
variant: {
default:
'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
secondary:
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
destructive:
'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
outline: 'text-foreground',
},
},
defaultVariants: {
variant: 'default',
},
}
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
);
}
export { Badge, badgeVariants };

View File

@@ -5,7 +5,7 @@ import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
const buttonVariants = cva( const buttonVariants = cva(
'inline-flex items-center justify-center 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', '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: { variants: {
variant: { variant: {

83
components/ui/card.tsx Normal file
View File

@@ -0,0 +1,83 @@
import * as React from 'react';
import { cn } from '@/lib/utils';
const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
'rounded-xl border bg-card text-card-foreground shadow',
className
)}
{...props}
/>
));
Card.displayName = 'Card';
const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn('flex flex-col space-y-1.5 p-6', className)}
{...props}
/>
));
CardHeader.displayName = 'CardHeader';
const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn('font-semibold leading-none tracking-tight', className)}
{...props}
/>
));
CardTitle.displayName = 'CardTitle';
const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn('text-sm text-muted-foreground', className)}
{...props}
/>
));
CardDescription.displayName = 'CardDescription';
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
));
CardContent.displayName = 'CardContent';
const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn('flex items-center p-6 pt-0', className)}
{...props}
/>
));
CardFooter.displayName = 'CardFooter';
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
};

262
components/ui/carousel.tsx Normal file
View File

@@ -0,0 +1,262 @@
'use client';
import * as React from 'react';
import { ArrowLeftIcon, ArrowRightIcon } from '@radix-ui/react-icons';
import useEmblaCarousel, {
type UseEmblaCarouselType,
} from 'embla-carousel-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
type CarouselApi = UseEmblaCarouselType[1];
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
type CarouselOptions = UseCarouselParameters[0];
type CarouselPlugin = UseCarouselParameters[1];
type CarouselProps = {
opts?: CarouselOptions;
plugins?: CarouselPlugin;
orientation?: 'horizontal' | 'vertical';
setApi?: (api: CarouselApi) => void;
};
type CarouselContextProps = {
carouselRef: ReturnType<typeof useEmblaCarousel>[0];
api: ReturnType<typeof useEmblaCarousel>[1];
scrollPrev: () => void;
scrollNext: () => void;
canScrollPrev: boolean;
canScrollNext: boolean;
} & CarouselProps;
const CarouselContext = React.createContext<CarouselContextProps | null>(null);
function useCarousel() {
const context = React.useContext(CarouselContext);
if (!context) {
throw new Error('useCarousel must be used within a <Carousel />');
}
return context;
}
const Carousel = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & CarouselProps
>(
(
{
orientation = 'horizontal',
opts,
setApi,
plugins,
className,
children,
...props
},
ref
) => {
const [carouselRef, api] = useEmblaCarousel(
{
...opts,
axis: orientation === 'horizontal' ? 'x' : 'y',
},
plugins
);
const [canScrollPrev, setCanScrollPrev] = React.useState(false);
const [canScrollNext, setCanScrollNext] = React.useState(false);
const onSelect = React.useCallback((api: CarouselApi) => {
if (!api) {
return;
}
setCanScrollPrev(api.canScrollPrev());
setCanScrollNext(api.canScrollNext());
}, []);
const scrollPrev = React.useCallback(() => {
api?.scrollPrev();
}, [api]);
const scrollNext = React.useCallback(() => {
api?.scrollNext();
}, [api]);
const handleKeyDown = React.useCallback(
(event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === 'ArrowLeft') {
event.preventDefault();
scrollPrev();
} else if (event.key === 'ArrowRight') {
event.preventDefault();
scrollNext();
}
},
[scrollPrev, scrollNext]
);
React.useEffect(() => {
if (!api || !setApi) {
return;
}
setApi(api);
}, [api, setApi]);
React.useEffect(() => {
if (!api) {
return;
}
onSelect(api);
api.on('reInit', onSelect);
api.on('select', onSelect);
return () => {
api?.off('select', onSelect);
};
}, [api, onSelect]);
return (
<CarouselContext.Provider
value={{
carouselRef,
api: api,
opts,
orientation:
orientation || (opts?.axis === 'y' ? 'vertical' : 'horizontal'),
scrollPrev,
scrollNext,
canScrollPrev,
canScrollNext,
}}
>
<div
ref={ref}
onKeyDownCapture={handleKeyDown}
className={cn('relative', className)}
role="region"
aria-roledescription="carousel"
{...props}
>
{children}
</div>
</CarouselContext.Provider>
);
}
);
Carousel.displayName = 'Carousel';
const CarouselContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
const { carouselRef, orientation } = useCarousel();
return (
<div ref={carouselRef} className="overflow-hidden">
<div
ref={ref}
className={cn(
'flex',
orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',
className
)}
{...props}
/>
</div>
);
});
CarouselContent.displayName = 'CarouselContent';
const CarouselItem = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
const { orientation } = useCarousel();
return (
<div
ref={ref}
role="group"
aria-roledescription="slide"
className={cn(
'min-w-0 shrink-0 grow-0 basis-full',
orientation === 'horizontal' ? 'pl-4' : 'pt-4',
className
)}
{...props}
/>
);
});
CarouselItem.displayName = 'CarouselItem';
const CarouselPrevious = React.forwardRef<
HTMLButtonElement,
React.ComponentProps<typeof Button>
>(({ className, variant = 'outline', size = 'icon', ...props }, ref) => {
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
return (
<Button
ref={ref}
variant={variant}
size={size}
className={cn(
'absolute h-8 w-8 rounded-full',
orientation === 'horizontal'
? '-left-12 top-1/2 -translate-y-1/2'
: '-top-12 left-1/2 -translate-x-1/2 rotate-90',
className
)}
disabled={!canScrollPrev}
onClick={scrollPrev}
{...props}
>
<ArrowLeftIcon className="h-4 w-4" />
<span className="sr-only">Previous slide</span>
</Button>
);
});
CarouselPrevious.displayName = 'CarouselPrevious';
const CarouselNext = React.forwardRef<
HTMLButtonElement,
React.ComponentProps<typeof Button>
>(({ className, variant = 'outline', size = 'icon', ...props }, ref) => {
const { orientation, scrollNext, canScrollNext } = useCarousel();
return (
<Button
ref={ref}
variant={variant}
size={size}
className={cn(
'absolute h-8 w-8 rounded-full',
orientation === 'horizontal'
? '-right-12 top-1/2 -translate-y-1/2'
: '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',
className
)}
disabled={!canScrollNext}
onClick={scrollNext}
{...props}
>
<ArrowRightIcon className="h-4 w-4" />
<span className="sr-only">Next slide</span>
</Button>
);
});
CarouselNext.displayName = 'CarouselNext';
export {
type CarouselApi,
Carousel,
CarouselContent,
CarouselItem,
CarouselPrevious,
CarouselNext,
};

22
components/ui/input.tsx Normal file
View File

@@ -0,0 +1,22 @@
import * as React from 'react';
import { cn } from '@/lib/utils';
const Input = React.forwardRef<
HTMLInputElement,
React.InputHTMLAttributes<HTMLInputElement>
>(({ 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-sm 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',
className
)}
ref={ref}
{...props}
/>
);
});
Input.displayName = 'Input';
export { Input };

26
components/ui/label.tsx Normal file
View File

@@ -0,0 +1,26 @@
'use client';
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';
const labelVariants = cva(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
);
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
));
Label.displayName = LabelPrimitive.Root.displayName;
export { Label };

33
components/ui/popover.tsx Normal file
View File

@@ -0,0 +1,33 @@
'use client';
import * as React from 'react';
import * as PopoverPrimitive from '@radix-ui/react-popover';
import { cn } from '@/lib/utils';
const Popover = PopoverPrimitive.Root;
const PopoverTrigger = PopoverPrimitive.Trigger;
const PopoverAnchor = PopoverPrimitive.Anchor;
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
));
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };

164
components/ui/select.tsx Normal file
View File

@@ -0,0 +1,164 @@
'use client';
import * as React from 'react';
import {
CaretSortIcon,
CheckIcon,
ChevronDownIcon,
ChevronUpIcon,
} from '@radix-ui/react-icons';
import * as SelectPrimitive from '@radix-ui/react-select';
import { cn } from '@/lib/utils';
const Select = SelectPrimitive.Root;
const SelectGroup = SelectPrimitive.Group;
const SelectValue = SelectPrimitive.Value;
const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
className
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<CaretSortIcon className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton
ref={ref}
className={cn(
'flex cursor-default items-center justify-center py-1',
className
)}
{...props}
>
<ChevronUpIcon />
</SelectPrimitive.ScrollUpButton>
));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton
ref={ref}
className={cn(
'flex cursor-default items-center justify-center py-1',
className
)}
{...props}
>
<ChevronDownIcon />
</SelectPrimitive.ScrollDownButton>
));
SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName;
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = 'popper', ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
className
)}
position={position}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
'p-1',
position === 'popper' &&
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
));
SelectContent.displayName = SelectPrimitive.Content.displayName;
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={cn('px-2 py-1.5 text-sm font-semibold', className)}
{...props}
/>
));
SelectLabel.displayName = SelectPrimitive.Label.displayName;
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item
ref={ref}
className={cn(
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className
)}
{...props}
>
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<CheckIcon className="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
));
SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn('-mx-1 my-1 h-px bg-muted', className)}
{...props}
/>
));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
SelectScrollUpButton,
SelectScrollDownButton,
};

View File

@@ -0,0 +1,31 @@
'use client';
import * as React from 'react';
import * as SeparatorPrimitive from '@radix-ui/react-separator';
import { cn } from '@/lib/utils';
const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(
(
{ className, orientation = 'horizontal', decorative = true, ...props },
ref
) => (
<SeparatorPrimitive.Root
ref={ref}
decorative={decorative}
orientation={orientation}
className={cn(
'shrink-0 bg-border',
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
className
)}
{...props}
/>
)
);
Separator.displayName = SeparatorPrimitive.Root.displayName;
export { Separator };

BIN
public/BGVid1.mp4 Normal file

Binary file not shown.

BIN
public/BGVid2.mp4 Normal file

Binary file not shown.

View File

@@ -10,6 +10,10 @@ const config: Config = {
theme: { theme: {
extend: { extend: {
colors: { colors: {
black: {
DEFAULT: '#000',
100: '#000319',
},
background: 'hsl(var(--background))', background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))', foreground: 'hsl(var(--foreground))',
card: { card: {