mirror of
https://github.com/0xShay/ticketchain.git
synced 2026-01-11 21:23:24 +00:00
Merge pull request #46 from Ayush272002/bug-usd
Fetch events on homepage and abstract out files
This commit is contained in:
@@ -6,6 +6,7 @@ import Header from '../../components/custom/header';
|
|||||||
import Footer from '../../components/custom/footer';
|
import Footer from '../../components/custom/footer';
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
import { getContract } from '@/lib/ethers';
|
import { getContract } from '@/lib/ethers';
|
||||||
|
import { fetchEvents } from '@/lib/fetchEvents';
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
@@ -40,32 +41,9 @@ const EventsPage: React.FC = () => {
|
|||||||
const [showFilterMenu, setShowFilterMenu] = useState<boolean>(false);
|
const [showFilterMenu, setShowFilterMenu] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchEvents = async () => {
|
const getEvents = async () => {
|
||||||
try {
|
try {
|
||||||
const provider = new ethers.providers.Web3Provider(window.ethereum!);
|
const eventsData: Event[] = (await fetchEvents())!;
|
||||||
const contract = getContract().connect(provider);
|
|
||||||
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: parseFloat(
|
|
||||||
ethers.utils.formatEther(event.ticketPrice)
|
|
||||||
),
|
|
||||||
eventStartDate: event.eventStartDate.toNumber(),
|
|
||||||
eventEndDate: event.eventEndDate.toNumber(),
|
|
||||||
images: images,
|
|
||||||
eventHost: event.eventHost,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setEvents(eventsData);
|
setEvents(eventsData);
|
||||||
setFilteredEvents(eventsData);
|
setFilteredEvents(eventsData);
|
||||||
@@ -87,7 +65,7 @@ const EventsPage: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchEvents();
|
getEvents();
|
||||||
}, [initialQuery]);
|
}, [initialQuery]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -172,7 +150,7 @@ const EventsPage: React.FC = () => {
|
|||||||
<div className="absolute inset-0 bg-black opacity-50 z-10"></div>
|
<div className="absolute inset-0 bg-black opacity-50 z-10"></div>
|
||||||
|
|
||||||
<div className="relative z-20 container mx-auto p-4 pt-16">
|
<div className="relative z-20 container mx-auto p-4 pt-16">
|
||||||
<Suspense fallback={<p>Loading...</p>}>
|
<Suspense fallback={<div className="mt-4 text-2xl text-white">Loading...</div>}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Search events..."
|
placeholder="Search events..."
|
||||||
@@ -291,7 +269,7 @@ const EventsPage: React.FC = () => {
|
|||||||
</p>
|
</p>
|
||||||
<p className="text-gray-600">{event.location}</p>
|
<p className="text-gray-600">{event.location}</p>
|
||||||
<p className="text-gray-800 font-semibold">
|
<p className="text-gray-800 font-semibold">
|
||||||
${event.ticketPrice} FLR
|
${event.ticketPrice}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-gray-600">Host: {event.eventHost}</p>
|
<p className="text-gray-600">Host: {event.eventHost}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
70
app/page.tsx
70
app/page.tsx
@@ -7,6 +7,7 @@ import { Input } from '@/components/ui/input';
|
|||||||
import FeaturedEvent from '@/components/custom/FeaturedEvent';
|
import FeaturedEvent from '@/components/custom/FeaturedEvent';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { FlipWords } from '@/components/ui/flip-words';
|
import { FlipWords } from '@/components/ui/flip-words';
|
||||||
|
import { fetchEvents } from '@/lib/fetchEvents';
|
||||||
|
|
||||||
// profile
|
// profile
|
||||||
// profile props
|
// profile props
|
||||||
@@ -15,12 +16,22 @@ import { FlipWords } from '@/components/ui/flip-words';
|
|||||||
export default function Home() {
|
export default function Home() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isClient, setIsClient] = useState(false);
|
const [isClient, setIsClient] = useState(false);
|
||||||
|
const [events, setEvents] = useState<any>([]);
|
||||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsClient(true);
|
setIsClient(true);
|
||||||
|
fetchEvents().then(eventsData => {
|
||||||
|
eventsData = eventsData?.sort((a, b) => (a.ticketsSold - b.ticketsSold));
|
||||||
|
setEvents(eventsData || []);
|
||||||
|
})
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("events updated");
|
||||||
|
console.log(events);
|
||||||
|
}, [events])
|
||||||
|
|
||||||
function searchForEvents() {
|
function searchForEvents() {
|
||||||
if (inputRef.current?.value === '') {
|
if (inputRef.current?.value === '') {
|
||||||
alert('Please enter a search term.');
|
alert('Please enter a search term.');
|
||||||
@@ -54,6 +65,10 @@ export default function Home() {
|
|||||||
'gathering',
|
'gathering',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const handleEventClick = (eventId: number) => {
|
||||||
|
router.push(`/events/${eventId}`);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
@@ -102,46 +117,21 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
<main>
|
<main>
|
||||||
<section className="mb-8 mt-4 mx-auto grid grid-cols-4 col-span-4 gap-4 place-content-center">
|
<section className="mb-8 mt-4 mx-auto grid grid-cols-4 col-span-4 gap-4 place-content-center">
|
||||||
<FeaturedEvent
|
{ events.map((ev: any, index: number) => {
|
||||||
name="FAB XO Halloween"
|
return <>
|
||||||
description="Halloween is upon us and is one of the biggest nights of the FAB XO calendar. Fancy dress is encouraged! So have your fancy dress ready and we look forward to seeing who have the best fancy dress on the night! As a special treat we will be serving our very own witches brew!!!"
|
<a onClick={() => { handleEventClick(ev.eventId) }}>
|
||||||
location="Birmingham, UK"
|
<FeaturedEvent
|
||||||
eventStartDate={1729980000}
|
key={ev.eventId}
|
||||||
eventHost="0x225C73C8c536C4F5335a2C1abECa95b0f221eeF6"
|
name={ev.name}
|
||||||
imageURL="https://www.guildofstudents.com/asset/Event/7572/Halloween-Fab-XO-Web-Event.jpg"
|
description={ev.description}
|
||||||
/>
|
location={ev.location}
|
||||||
<FeaturedEvent
|
eventStartDate={ev.eventStartDate}
|
||||||
name="Halls Halloween Spooktacular"
|
eventHost={ev.eventHost}
|
||||||
description="Put on your spookiest costume and head on down to Pritchatts Park and join your Event Activators for our ResLife SPOOKTACULAR on Wednesday 30th October 5-8pm."
|
imageURL={ev.images[0] || ""}
|
||||||
location="Birmingham, UK"
|
/>
|
||||||
eventStartDate={1730307600}
|
</a>
|
||||||
eventHost="0x225C73C8c536C4F5335a2C1abECa95b0f221eeF6"
|
</>
|
||||||
imageURL="https://www.guildofstudents.com/asset/Event/41187/Spooktacular-Web-Event-2024.png"
|
}) }
|
||||||
/>
|
|
||||||
<FeaturedEvent
|
|
||||||
name="Halls Halloween Spooktacular"
|
|
||||||
description="Put on your spookiest costume and head on down to Pritchatts Park and join your Event Activators for our ResLife SPOOKTACULAR on Wednesday 30th October 5-8pm."
|
|
||||||
location="Birmingham, UK"
|
|
||||||
eventStartDate={1730307600}
|
|
||||||
eventHost="0x225C73C8c536C4F5335a2C1abECa95b0f221eeF6"
|
|
||||||
imageURL="https://www.guildofstudents.com/asset/Event/41187/Spooktacular-Web-Event-2024.png"
|
|
||||||
/>
|
|
||||||
<FeaturedEvent
|
|
||||||
name="Halls Halloween Spooktacular"
|
|
||||||
description="Put on your spookiest costume and head on down to Pritchatts Park and join your Event Activators for our ResLife SPOOKTACULAR on Wednesday 30th October 5-8pm."
|
|
||||||
location="Birmingham, UK"
|
|
||||||
eventStartDate={1730307600}
|
|
||||||
eventHost="0x225C73C8c536C4F5335a2C1abECa95b0f221eeF6"
|
|
||||||
imageURL="https://www.guildofstudents.com/asset/Event/41187/Spooktacular-Web-Event-2024.png"
|
|
||||||
/>
|
|
||||||
<FeaturedEvent
|
|
||||||
name="Housing Fair"
|
|
||||||
description="We’re hosting a Housing Fair, so make sure you save the date! Whether you’re living in student accommodation or the local community, this will be a great place to start as you begin thinking about where you’ll be living next year."
|
|
||||||
location="Birmingham, UK"
|
|
||||||
eventStartDate={1730804400}
|
|
||||||
eventHost="0x225C73C8c536C4F5335a2C1abECa95b0f221eeF6"
|
|
||||||
imageURL="https://www.guildofstudents.com/asset/Event/41111/Housing-Fair-Web-Event.png"
|
|
||||||
/>
|
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ const eventSchema = z
|
|||||||
.refine(Number.isInteger, { message: 'Capacity must be an integer' }),
|
.refine(Number.isInteger, { message: 'Capacity must be an integer' }),
|
||||||
ticketPrice: z
|
ticketPrice: z
|
||||||
.number({ invalid_type_error: 'Ticket price must be a number' })
|
.number({ invalid_type_error: 'Ticket price must be a number' })
|
||||||
.min(0, { message: 'Ticket price must be at least 0' })
|
.min(0, { message: 'Ticket price must be at least 0' }),
|
||||||
.refine(Number.isInteger, { message: 'Ticket price must be in cents' }),
|
|
||||||
location: z.string().min(1, { message: 'Location is required' }),
|
location: z.string().min(1, { message: 'Location is required' }),
|
||||||
eventStartTime: z.preprocess(
|
eventStartTime: z.preprocess(
|
||||||
(val) =>
|
(val) =>
|
||||||
@@ -128,9 +127,8 @@ const EventForm = ({ onSubmit }: EventFormProps) => {
|
|||||||
|
|
||||||
{/* Ticket Price Field */}
|
{/* Ticket Price Field */}
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="ticketPrice">Ticket Price (in USD cents)</Label>
|
<Label htmlFor="ticketPrice">Ticket Price (in USD)</Label>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
|
||||||
id="ticketPrice"
|
id="ticketPrice"
|
||||||
{...register('ticketPrice', { valueAsNumber: true })}
|
{...register('ticketPrice', { valueAsNumber: true })}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export const createEvent = async ({
|
|||||||
description,
|
description,
|
||||||
location,
|
location,
|
||||||
capacity,
|
capacity,
|
||||||
ethers.utils.parseEther(ticketPrice.toString()),
|
Math.floor(ticketPrice * 100),
|
||||||
Math.floor(startDate.getTime() / 1000),
|
Math.floor(startDate.getTime() / 1000),
|
||||||
Math.floor(endDate.getTime() / 1000),
|
Math.floor(endDate.getTime() / 1000),
|
||||||
images
|
images
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const fetchEventDetails = async ({
|
|||||||
name: eventData.name,
|
name: eventData.name,
|
||||||
date: eventData.eventStartDate.toNumber(),
|
date: eventData.eventStartDate.toNumber(),
|
||||||
location: eventData.location,
|
location: eventData.location,
|
||||||
ticketPrice: eventData.ticketPrice.div(ethers.BigNumber.from("1000000000000000000")).toNumber() / 100,
|
ticketPrice: eventData.ticketPrice.toNumber() / 100,
|
||||||
description: eventData.description,
|
description: eventData.description,
|
||||||
capacity: eventData.capacity.toNumber(),
|
capacity: eventData.capacity.toNumber(),
|
||||||
ticketsSold: eventData.ticketsSold.toNumber(),
|
ticketsSold: eventData.ticketsSold.toNumber(),
|
||||||
|
|||||||
53
lib/fetchEvents.ts
Normal file
53
lib/fetchEvents.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchEvents: () => Promise<Event[] | undefined> = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user