mirror of
https://github.com/0xShay/ticketchain.git
synced 2026-01-11 13:13:25 +00:00
Merge pull request #43 from Ayush272002/event-ct-comms
🎫 Add event details on event page
This commit is contained in:
@@ -4,42 +4,28 @@ import { useParams } from 'next/navigation';
|
|||||||
import Header from '../../../components/custom/header';
|
import Header from '../../../components/custom/header';
|
||||||
import Footer from '../../../components/custom/footer';
|
import Footer from '../../../components/custom/footer';
|
||||||
import EventDescription from '../../../components/custom/EventDescription';
|
import EventDescription from '../../../components/custom/EventDescription';
|
||||||
|
import { fetchEventDetails } from '@/lib/fetchEventDetails';
|
||||||
|
|
||||||
const ListingPage: React.FC = () => {
|
const ListingPage: React.FC = () => {
|
||||||
const { eventId } = useParams();
|
const { eventId } = useParams();
|
||||||
const [eventDetails, setEventDetails] = useState<any>(null);
|
const [eventDetails, setEventDetails] = useState<any>(null);
|
||||||
|
const [eventNotFound, setEventNotFound] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchEventDetails = async (id: number) => {
|
|
||||||
alert(`Fetching details for event ID: ${id}`);
|
|
||||||
// Dummy Response
|
|
||||||
const details = {
|
|
||||||
EventID: id,
|
|
||||||
name: 'Example Event Name',
|
|
||||||
date: '2023-12-01',
|
|
||||||
location: 'Example Location',
|
|
||||||
ticketPrice: 100,
|
|
||||||
description: 'Detailed description of the event.',
|
|
||||||
capacity: 300,
|
|
||||||
ticketsSold: 295,
|
|
||||||
imageUrl: [
|
|
||||||
'https://via.placeholder.com/150',
|
|
||||||
'https://via.placeholder.com/150',
|
|
||||||
],
|
|
||||||
host: 'Example Host',
|
|
||||||
tickets: [1, 2, 3, 4],
|
|
||||||
};
|
|
||||||
return details;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getEventDetails = async () => {
|
const getEventDetails = async () => {
|
||||||
if (eventId) {
|
if (eventId) {
|
||||||
const details = await fetchEventDetails(Number(eventId));
|
const details = await fetchEventDetails({
|
||||||
|
eventID: Number(eventId),
|
||||||
|
toast: ({ title, variant }: any) => {alert(title);}});
|
||||||
|
console.log(details)
|
||||||
setEventDetails(details);
|
setEventDetails(details);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getEventDetails();
|
getEventDetails().catch((err) => {
|
||||||
|
setEventNotFound(true);
|
||||||
|
console.log(eventNotFound);
|
||||||
|
});
|
||||||
}, [eventId]);
|
}, [eventId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -64,11 +50,13 @@ const ListingPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative z-10">
|
<div className="relative z-10">
|
||||||
{eventDetails ? (
|
{eventNotFound ? <p className="text-2xl text-white pt-20 text-center">Event not found</p> :
|
||||||
<EventDescription eventDetails={eventDetails} />
|
(eventDetails ? (
|
||||||
) : (
|
<EventDescription eventDetails={eventDetails} />
|
||||||
<p>Loading...</p>
|
) : (
|
||||||
)}
|
<p>Loading...</p>
|
||||||
|
))
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative z-20">
|
<div className="relative z-20">
|
||||||
|
|||||||
@@ -48,21 +48,21 @@ const EventDescription: React.FC<EventDescriptionProps> = ({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
className="text-blue-600 bg-blue-100 px-3 py-1 rounded-full"
|
className="text-blue-600 bg-blue-100 px-3 py-1 rounded-full"
|
||||||
>
|
>
|
||||||
Price: ${eventDetails.ticketPrice}
|
Price: ${eventDetails.ticketPrice.toFixed(2)}
|
||||||
</Badge>
|
</Badge>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className="flex flex-col md:flex-row items-start space-y-8 md:space-y-0 md:space-x-10">
|
<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">
|
<div className="md:w-1/2 flex justify-center">
|
||||||
<ImageCarousel images={eventDetails.imageUrl} />
|
<ImageCarousel images={eventDetails.imageUrl || []} />
|
||||||
</div>
|
</div>
|
||||||
<div className="md:w-1/2 text-gray-700">
|
<div className="md:w-1/2 text-gray-700">
|
||||||
<Separator className="my-4" />
|
<Separator className="my-4" />
|
||||||
<p className="leading-relaxed">{eventDetails.description}</p>
|
<p className="leading-relaxed">{eventDetails.description}</p>
|
||||||
<Separator className="my-4" />
|
<Separator className="my-4" />
|
||||||
<p>Location: {eventDetails.location}</p>
|
<p><b>Location:</b><br />{eventDetails.location}</p><br />
|
||||||
<p>Date: {eventDetails.date}</p>
|
<p><b>Date:</b><br />{eventDetails.date}</p><br />
|
||||||
<p>Host: {eventDetails.host}</p>
|
<p><b>Host:</b><br />{eventDetails.host}</p>
|
||||||
{eventDetails.ticketsSold / eventDetails.capacity >= 0.9 && (
|
{eventDetails.ticketsSold / eventDetails.capacity >= 0.9 && (
|
||||||
<div className="mt-2 p-2 bg-yellow-300 text-black rounded">
|
<div className="mt-2 p-2 bg-yellow-300 text-black rounded">
|
||||||
Limited Tickets Remaining!
|
Limited Tickets Remaining!
|
||||||
|
|||||||
78
lib/fetchEventDetails.ts
Normal file
78
lib/fetchEventDetails.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { ethers } from 'ethers';
|
||||||
|
import { getContract } from './ethers';
|
||||||
|
|
||||||
|
interface GetEventDetailsProps {
|
||||||
|
eventID: number;
|
||||||
|
toast: ToastFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToastFunction = (options: {
|
||||||
|
title: string;
|
||||||
|
variant?: 'default' | 'destructive' | null | undefined;
|
||||||
|
}) => void;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
ethereumProvider?: ethers.providers.ExternalProvider & {
|
||||||
|
isMetaMask?: boolean;
|
||||||
|
request?: (method: string, params?: unknown[]) => Promise<unknown>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchEventDetails = async ({
|
||||||
|
eventID,
|
||||||
|
toast,
|
||||||
|
}: GetEventDetailsProps) => {
|
||||||
|
try {
|
||||||
|
console.log('Starting events call');
|
||||||
|
if (typeof window.ethereum === 'undefined') {
|
||||||
|
console.error('Ethereum provider not found');
|
||||||
|
toast({
|
||||||
|
title: 'Please install MetaMask or another Ethereum wallet',
|
||||||
|
variant: 'destructive',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Connecting to Ethereum provider');
|
||||||
|
const provider = new ethers.providers.Web3Provider(window.ethereum);
|
||||||
|
const contract = getContract();
|
||||||
|
|
||||||
|
console.log('Requesting data');
|
||||||
|
const eventData = await contract.callStatic.events(eventID);
|
||||||
|
const eventImages = await contract.callStatic.getEventImages(eventID);
|
||||||
|
console.log(eventData);
|
||||||
|
|
||||||
|
// toast({
|
||||||
|
// title: `Data fetched successfully!`,
|
||||||
|
// });
|
||||||
|
|
||||||
|
return {
|
||||||
|
EventID: eventID,
|
||||||
|
name: eventData.name,
|
||||||
|
date: eventData.eventStartDate.toNumber(),
|
||||||
|
location: eventData.location,
|
||||||
|
ticketPrice: eventData.ticketPrice.div(ethers.BigNumber.from("1000000000000000000")).toNumber() / 100,
|
||||||
|
description: eventData.description,
|
||||||
|
capacity: eventData.capacity.toNumber(),
|
||||||
|
ticketsSold: eventData.ticketsSold.toNumber(),
|
||||||
|
imageUrl: eventImages,
|
||||||
|
host: eventData.eventHost
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in createEvent:', error);
|
||||||
|
// if (error instanceof Error) {
|
||||||
|
// toast({
|
||||||
|
// title: `Transaction failed: ${error.message}`,
|
||||||
|
// variant: 'destructive',
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// toast({
|
||||||
|
// title: 'Transaction failed. Please try again.',
|
||||||
|
// variant: 'destructive',
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user