From 7e919069538b74680c4c09284750be0fff12e156 Mon Sep 17 00:00:00 2001 From: sid <35936587+siddharth-shringarpure@users.noreply.github.com> Date: Sun, 27 Oct 2024 09:07:08 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20Improved=20displaying=20of=20pr?= =?UTF-8?q?icing=20for=20users.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .husky/pre-commit | 3 +-- components/custom/EventDescription.tsx | 27 ++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index e290538..72c4429 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,2 +1 @@ -#!/usr/bin/env sh -npx lint-staged && npm run build +npm test diff --git a/components/custom/EventDescription.tsx b/components/custom/EventDescription.tsx index 03b4497..f82eba4 100644 --- a/components/custom/EventDescription.tsx +++ b/components/custom/EventDescription.tsx @@ -48,7 +48,12 @@ const EventDescription: React.FC = ({ 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, + })} @@ -60,9 +65,23 @@ const EventDescription: React.FC = ({

{eventDetails.description}

-

Location:
{eventDetails.location}


-

Date:
{eventDetails.date}


-

Host:
{eventDetails.host}

+

+ Location: +
+ {eventDetails.location} +

+
+

+ Date: +
+ {eventDetails.date} +

+
+

+ Host: +
+ {eventDetails.host} +

{eventDetails.ticketsSold / eventDetails.capacity >= 0.9 && (
Limited Tickets Remaining! From 1af0c14db8a051d54feda2eb7dd5ff365709a668 Mon Sep 17 00:00:00 2001 From: Shay Patel Date: Sun, 27 Oct 2024 09:16:40 +0000 Subject: [PATCH 2/3] Updated bytecode and added getUserTickets function --- contracts/EventManager.sol | 4 + contracts/EventManagerABI.json | 143 +++++++++++++++++++-------------- 2 files changed, 85 insertions(+), 62 deletions(-) diff --git a/contracts/EventManager.sol b/contracts/EventManager.sol index b19b5ba..63c0122 100644 --- a/contracts/EventManager.sol +++ b/contracts/EventManager.sol @@ -194,4 +194,8 @@ contract EventManager { transferTicketForce(_ticketId, _to); } + function getUserTickets(address _user) public view returns (uint256[] memory _ticketIds) { + return userTickets[_user]; + } + } diff --git a/contracts/EventManagerABI.json b/contracts/EventManagerABI.json index d22a78d..d69ecfa 100644 --- a/contracts/EventManagerABI.json +++ b/contracts/EventManagerABI.json @@ -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": [ { From 7c74e23d3a656d4375c2bfef7307aeeb2d1a029c Mon Sep 17 00:00:00 2001 From: Ayush Acharjya Date: Sun, 27 Oct 2024 09:37:19 +0000 Subject: [PATCH 3/3] fix profile --- .husky/pre-commit | 3 +- app/events/[...eventId]/page.tsx | 24 ++-- app/profile/page.tsx | 204 ++++++++++++++++++++++++------- env | 2 - lib/fetchEventDetails.ts | 4 +- lib/fetchEvents.ts | 94 +++++++------- 6 files changed, 225 insertions(+), 106 deletions(-) delete mode 100644 env diff --git a/.husky/pre-commit b/.husky/pre-commit index 72c4429..9cbfef9 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1,2 @@ -npm test +#!/usr/bin/env sh +npx lint-staged && npm run build \ No newline at end of file diff --git a/app/events/[...eventId]/page.tsx b/app/events/[...eventId]/page.tsx index 2a44b8f..b671ccf 100644 --- a/app/events/[...eventId]/page.tsx +++ b/app/events/[...eventId]/page.tsx @@ -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 = () => {
- {eventNotFound ?

Event not found

: - (eventDetails ? ( - - ) : ( -

Loading...

- )) - } + {eventNotFound ? ( +

+ Event not found +

+ ) : eventDetails ? ( + + ) : ( +

Loading...

+ )}
diff --git a/app/profile/page.tsx b/app/profile/page.tsx index 7289dce..1d0c8d1 100644 --- a/app/profile/page.tsx +++ b/app/profile/page.tsx @@ -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([]); + 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 ( - <> -
-
-
-
- {/* Video Background */} - {isClient && ( - +
+
+
+
+ {isClient && ( + + )} + +
+ +
+

Your Profile

+ {userAddress ? ( +

Connected Address: {userAddress}

+ ) : ( +

Not connected

+ )} +

Current Network: {networkName}

+ + {error && ( +
+ {error} +
)} - {/* Dark Overlay for Enhanced Readability */} -
+ + + Your Tickets + + Here are the tickets associated with your wallet + + + + {loading ? ( +

Loading...

+ ) : userTickets.length > 0 ? ( +
    + {userTickets.map((ticketId) => ( +
  • + Ticket ID: {ticketId} +
  • + ))} +
+ ) : ( +

You don't have any tickets yet.

+ )} +
+
-
- - - {/* Render PreviousTickets component with appropriate props */} - -
+
-
- +
+
); -}; - -export default ProfilePage; +} diff --git a/env b/env deleted file mode 100644 index 6beaef3..0000000 --- a/env +++ /dev/null @@ -1,2 +0,0 @@ -NEXT_PUBLIC_RPC_URL=https://coston2.enosys.global/ext/C/rpc -NEXT_PUBLIC_CONTRACT_ADDRESS=0xe84032D41216B21153f4Ab0d98EA396f777fc957 diff --git a/lib/fetchEventDetails.ts b/lib/fetchEventDetails.ts index 4c08c3c..7244cb5 100644 --- a/lib/fetchEventDetails.ts +++ b/lib/fetchEventDetails.ts @@ -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) { diff --git a/lib/fetchEvents.ts b/lib/fetchEvents.ts index bc9e03f..40915ec 100644 --- a/lib/fetchEvents.ts +++ b/lib/fetchEvents.ts @@ -1,53 +1,53 @@ -import { ethers } from "ethers"; -import { getContract } from "./ethers"; +import { ethers } from 'ethers'; +import { getContract } from './ethers'; interface Event { - eventId: number; - name: string; - description: string; - location: string; - capacity: number; - ticketsSold: number; - ticketPrice: number; - eventStartDate: number; - eventEndDate: number; - images: string[]; - eventHost: string; + eventId: number; + name: string; + description: string; + location: string; + capacity: number; + ticketsSold: number; + ticketPrice: number; + eventStartDate: number; + eventEndDate: number; + images: string[]; + eventHost: string; } export const fetchEvents: () => Promise = async () => { - try { - console.log('Starting events call'); - if (typeof window.ethereum === 'undefined') { - console.error('Ethereum provider not found'); - return; - } - - console.log('Connecting to contract'); - const contract = getContract(); - const eventCount = await contract.eventCounter(); - const eventsData: Event[] = []; - - for (let i = 0; i < eventCount; i++) { - const event = await contract.events(i); - const images = await contract.getEventImages(i); - eventsData.push({ - eventId: i, - name: event.name, - description: event.description, - location: event.location, - capacity: event.capacity.toNumber(), - ticketsSold: event.ticketsSold.toNumber(), - ticketPrice: event.ticketPrice.toNumber() / 100, - eventStartDate: event.eventStartDate.toNumber(), - eventEndDate: event.eventEndDate.toNumber(), - images: images, - eventHost: event.eventHost, - }); - } - - return eventsData; - } catch (error) { - console.error('Failed to fetch events:', error); + try { + console.log('Starting events call'); + if (typeof window.ethereum === 'undefined') { + console.error('Ethereum provider not found'); + return; } -} \ No newline at end of file + + console.log('Connecting to contract'); + const contract = getContract(); + const eventCount = await contract.eventCounter(); + const eventsData: Event[] = []; + + for (let i = 0; i < eventCount; i++) { + const event = await contract.events(i); + const images = await contract.getEventImages(i); + eventsData.push({ + eventId: i, + name: event.name, + description: event.description, + location: event.location, + capacity: event.capacity.toNumber(), + ticketsSold: event.ticketsSold.toNumber(), + ticketPrice: event.ticketPrice.toNumber() / 100, + eventStartDate: event.eventStartDate.toNumber(), + eventEndDate: event.eventEndDate.toNumber(), + images: images, + eventHost: event.eventHost, + }); + } + + return eventsData; + } catch (error) { + console.error('Failed to fetch events:', error); + } +};