mirror of
https://github.com/0xShay/ticketchain.git
synced 2026-01-11 13:13:25 +00:00
Merge branch 'main' of https://github.com/Ayush272002/ticketchain into Polishing&Glazing
This commit is contained in:
@@ -16,15 +16,17 @@ const ListingPage: React.FC = () => {
|
||||
if (eventId) {
|
||||
const details = await fetchEventDetails({
|
||||
eventID: Number(eventId),
|
||||
toast: ({ title, variant }: any) => {alert(title);}});
|
||||
console.log(details)
|
||||
toast: ({ title, variant }: any) => {
|
||||
alert(title);
|
||||
},
|
||||
});
|
||||
console.log(details);
|
||||
setEventDetails(details);
|
||||
}
|
||||
};
|
||||
|
||||
getEventDetails().catch((err) => {
|
||||
setEventNotFound(true);
|
||||
console.log(eventNotFound);
|
||||
});
|
||||
}, [eventId]);
|
||||
|
||||
@@ -50,13 +52,15 @@ const ListingPage: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="relative z-10">
|
||||
{eventNotFound ? <p className="text-2xl text-white pt-20 text-center">Event not found</p> :
|
||||
(eventDetails ? (
|
||||
{eventNotFound ? (
|
||||
<p className="text-2xl text-white pt-20 text-center">
|
||||
Event not found
|
||||
</p>
|
||||
) : eventDetails ? (
|
||||
<EventDescription eventDetails={eventDetails} />
|
||||
) : (
|
||||
<p>Loading...</p>
|
||||
))
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="relative z-20">
|
||||
|
||||
@@ -1,63 +1,179 @@
|
||||
'use client';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ethers } from 'ethers';
|
||||
import Header from '../../components/custom/header';
|
||||
import Footer from '../../components/custom/footer';
|
||||
import Profile from '@/components/custom/Profile';
|
||||
import PreviousTickets from '@/components/PreviousTickets';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card';
|
||||
import EventManagerABI from '../../contracts/EventManagerABI.json';
|
||||
|
||||
const ProfilePage: React.FC = () => {
|
||||
const RPC_URL = process.env.NEXT_PUBLIC_RPC_URL;
|
||||
const CONTRACT_ADDRESS = process.env.NEXT_PUBLIC_CONTRACT_ADDRESS;
|
||||
|
||||
if (!RPC_URL || !CONTRACT_ADDRESS) {
|
||||
console.error(
|
||||
'Missing environment variables. Please check your .env.local file.'
|
||||
);
|
||||
}
|
||||
|
||||
export default function ProfilePage() {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const [isAuth, setAuth] = useState(false);
|
||||
const [userTickets, setUserTickets] = useState<number[]>([]);
|
||||
const [userAddress, setUserAddress] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [networkName, setNetworkName] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
// This ensures the component renders only on the client side
|
||||
setIsClient(true);
|
||||
checkNetwork();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {});
|
||||
const checkNetwork = async () => {
|
||||
if (typeof window.ethereum !== 'undefined') {
|
||||
try {
|
||||
const provider = new ethers.providers.Web3Provider(window.ethereum);
|
||||
const network = await provider.getNetwork();
|
||||
console.log('Network:', network);
|
||||
setNetworkName(network.name);
|
||||
} catch (error) {
|
||||
console.error('Failed to get network:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const connectWallet = async () => {
|
||||
setLoading(true);
|
||||
setError('');
|
||||
if (typeof window.ethereum !== 'undefined') {
|
||||
try {
|
||||
await window.ethereum.request({ method: 'eth_requestAccounts' });
|
||||
const provider = new ethers.providers.Web3Provider(window.ethereum);
|
||||
const signer = provider.getSigner();
|
||||
const address = await signer.getAddress();
|
||||
setUserAddress(address);
|
||||
await fetchUserTickets(address);
|
||||
} catch (error) {
|
||||
console.error('Failed to connect wallet:', error);
|
||||
setError('Failed to connect wallet. Please try again.');
|
||||
}
|
||||
} else {
|
||||
setError('Please install MetaMask!');
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const fetchUserTickets = async (address: string) => {
|
||||
if (!RPC_URL || !CONTRACT_ADDRESS) {
|
||||
setError('Missing configuration. Please contact support.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
|
||||
const contract = new ethers.Contract(
|
||||
CONTRACT_ADDRESS,
|
||||
EventManagerABI,
|
||||
provider
|
||||
);
|
||||
|
||||
console.log('Fetching tickets for address:', address);
|
||||
|
||||
const tickets = await contract.getUserTickets(address);
|
||||
console.log('Raw tickets data:', tickets);
|
||||
|
||||
if (Array.isArray(tickets)) {
|
||||
const ticketNumbers = tickets.map((ticket: ethers.BigNumber) =>
|
||||
ticket.toNumber()
|
||||
);
|
||||
console.log('Processed ticket numbers:', ticketNumbers);
|
||||
setUserTickets(ticketNumbers);
|
||||
} else {
|
||||
console.error('Unexpected response from getUserTickets:', tickets);
|
||||
setError('Unexpected response from contract. Please try again.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch user tickets:', error);
|
||||
setError(`Failed to fetch user tickets: ${(error as Error).message}`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative min-h-screen overflow-hidden bg-black">
|
||||
<Header />
|
||||
<div className="relative z-20 container mx-auto p-4 pt-16">
|
||||
<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" // Ensure the video file is placed in the public folder
|
||||
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>
|
||||
|
||||
<div className="relative flex flex-col space-y-10 mt-20 z-20 ml-10">
|
||||
<Profile profileKey="38902kj2-8hf082gb0f20g02h082" />
|
||||
<div className="relative z-20 text-white">
|
||||
<h1 className="text-4xl font-bold mb-4">Your Profile</h1>
|
||||
{userAddress ? (
|
||||
<p className="mb-4">Connected Address: {userAddress}</p>
|
||||
) : (
|
||||
<p className="mb-4">Not connected</p>
|
||||
)}
|
||||
<p className="mb-4">Current Network: {networkName}</p>
|
||||
|
||||
{/* Render PreviousTickets component with appropriate props */}
|
||||
<PreviousTickets
|
||||
name="Sample Event"
|
||||
status={true}
|
||||
description="Description of the event"
|
||||
capacity={100}
|
||||
ticketPrice={50}
|
||||
eventStartDate={new Date('2024-11-01T10:00:00')}
|
||||
eventHost="Host Name"
|
||||
/>
|
||||
{error && (
|
||||
<div className="bg-red-500 text-white p-2 rounded mb-4">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Card className="bg-gray-800 text-white">
|
||||
<CardHeader>
|
||||
<CardTitle>Your Tickets</CardTitle>
|
||||
<CardDescription>
|
||||
Here are the tickets associated with your wallet
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{loading ? (
|
||||
<p>Loading...</p>
|
||||
) : userTickets.length > 0 ? (
|
||||
<ul>
|
||||
{userTickets.map((ticketId) => (
|
||||
<li key={ticketId} className="mb-2">
|
||||
Ticket ID: {ticketId}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p>You don't have any tickets yet.</p>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Button className="mt-4" onClick={connectWallet} disabled={loading}>
|
||||
{loading
|
||||
? 'Connecting...'
|
||||
: userAddress
|
||||
? 'Refresh Tickets'
|
||||
: 'Connect Wallet'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfilePage;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,12 @@ const EventDescription: React.FC<EventDescriptionProps> = ({
|
||||
variant="outline"
|
||||
className="text-light-purple bg-blue-100 px-3 py-1 rounded-full"
|
||||
>
|
||||
Price: ${eventDetails.ticketPrice.toFixed(2)}
|
||||
{/*Show price and format by separating triplets of digits*/}
|
||||
Price: $
|
||||
{eventDetails.ticketPrice.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Badge>
|
||||
</CardHeader>
|
||||
|
||||
@@ -60,9 +65,23 @@ const EventDescription: React.FC<EventDescriptionProps> = ({
|
||||
<Separator className="my-4" />
|
||||
<p className="leading-relaxed">{eventDetails.description}</p>
|
||||
<Separator className="my-4" />
|
||||
<p><b>Location:</b><br />{eventDetails.location}</p><br />
|
||||
<p><b>Date:</b><br />{eventDetails.date}</p><br />
|
||||
<p><b>Host:</b><br />{eventDetails.host}</p>
|
||||
<p>
|
||||
<b>Location:</b>
|
||||
<br />
|
||||
{eventDetails.location}
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<b>Date:</b>
|
||||
<br />
|
||||
{eventDetails.date}
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<b>Host:</b>
|
||||
<br />
|
||||
{eventDetails.host}
|
||||
</p>
|
||||
{eventDetails.ticketsSold / eventDetails.capacity >= 0.9 && (
|
||||
<div className="mt-2 p-2 bg-yellow-300 text-black rounded">
|
||||
Limited Tickets Remaining!
|
||||
|
||||
@@ -194,4 +194,8 @@ contract EventManager {
|
||||
transferTicketForce(_ticketId, _to);
|
||||
}
|
||||
|
||||
function getUserTickets(address _user) public view returns (uint256[] memory _ticketIds) {
|
||||
return userTickets[_user];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
[
|
||||
{
|
||||
"inputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
@@ -152,25 +147,6 @@
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_cents",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "centsToFlare",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_flr",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
@@ -225,6 +201,66 @@
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_ticketId",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferTicket",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_ticketId",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferTicketFrom",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_cents",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "centsToFlare",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_flr",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "eventCounter",
|
||||
@@ -269,9 +305,9 @@
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"internalType": "uint64",
|
||||
"name": "ticketsSold",
|
||||
"type": "uint256"
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
@@ -419,6 +455,25 @@
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getUserTickets",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256[]",
|
||||
"name": "_ticketIds",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "ticketCounter",
|
||||
@@ -461,42 +516,6 @@
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_ticketId",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferTicket",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_ticketId",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferTicketFrom",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
|
||||
@@ -58,8 +58,8 @@ export const fetchEventDetails = async ({
|
||||
capacity: eventData.capacity.toNumber(),
|
||||
ticketsSold: eventData.ticketsSold.toNumber(),
|
||||
imageUrl: eventImages,
|
||||
host: eventData.eventHost
|
||||
}
|
||||
host: eventData.eventHost,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error in createEvent:', error);
|
||||
// if (error instanceof Error) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ethers } from "ethers";
|
||||
import { getContract } from "./ethers";
|
||||
import { ethers } from 'ethers';
|
||||
import { getContract } from './ethers';
|
||||
|
||||
interface Event {
|
||||
eventId: number;
|
||||
@@ -50,4 +50,4 @@ export const fetchEvents: () => Promise<Event[] | undefined> = async () => {
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch events:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user