mirror of
https://github.com/0xShay/ticketchain.git
synced 2026-01-11 21:23:24 +00:00
@@ -2,6 +2,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import Header from '../components/custom/header';
|
||||
import Footer from '../components/custom/footer';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
||||
export default function Home() {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
@@ -33,12 +34,15 @@ export default function Home() {
|
||||
{/* 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
|
||||
<div className="flex items-center justify-center">
|
||||
<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"
|
||||
className="search-bar mt-4 p-2 border bg-white bg-opacity-25 border-gray-300 rounded-xl w-full max-w-5xl text-white"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<br></br>
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold text-white mb-4">
|
||||
Featured Events
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
const Footer = () => {
|
||||
return (
|
||||
<footer className="text-center mt-8">
|
||||
<p className="text-gray-500">
|
||||
<p className="text-light-purple text-opacity-75">
|
||||
© 2024 TicketChain. All rights reserved.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
@@ -35,26 +35,39 @@ const Header = () => {
|
||||
}}
|
||||
></div>
|
||||
<div className="container mx-auto px-6 py-4 flex justify-between items-center">
|
||||
<h1 className="text-2xl font-semibold text-white">TicketChain</h1>
|
||||
<Link href="/" legacyBehavior>
|
||||
<a className="text-2xl font-semibold text-white hover:text-light-purple hover:text-opacity-75 transition-colors duration-300">
|
||||
TicketChain
|
||||
</a>
|
||||
</Link>
|
||||
<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">
|
||||
<a
|
||||
className="text-white hover:text-light-purple hover:text-opacity-75 transition-colors duration-300"
|
||||
style={{ textShadow: '1px 1px 2px rgba(0, 0, 0, 0.5)' }}
|
||||
>
|
||||
Home
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/events" legacyBehavior>
|
||||
<a className="text-white hover:text-blue-500 transition-colors duration-300">
|
||||
<a
|
||||
className="text-white hover:text-light-purple hover:text-opacity-75 transition-colors duration-300"
|
||||
style={{ textShadow: '1px 1px 2px rgba(0, 0, 0, 0.5)' }}
|
||||
>
|
||||
Events
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/contact" legacyBehavior>
|
||||
<a className="text-white hover:text-blue-500 transition-colors duration-300">
|
||||
<a
|
||||
className="text-white hover:text-light-purple hover:text-opacity-75 transition-colors duration-300"
|
||||
style={{ textShadow: '1px 1px 2px rgba(0, 0, 0, 0.5)' }}
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
@@ -37,20 +37,16 @@ function formatAddress(address: string | undefined): string {
|
||||
|
||||
function MetaMaskConnect() {
|
||||
const { sdk, connected, connecting, account } = useSDK();
|
||||
const [metaMaskInstalled, setMetaMaskInstalled] = useState(false);
|
||||
|
||||
const isMetaMaskInstalled = () =>
|
||||
typeof window !== 'undefined' && typeof window.ethereum !== 'undefined';
|
||||
const [isConnected, setIsConnected] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isMetaMaskInstalled()) {
|
||||
setMetaMaskInstalled(true);
|
||||
}
|
||||
}, []);
|
||||
setIsConnected(connected);
|
||||
}, [connected]);
|
||||
|
||||
const connect = async () => {
|
||||
try {
|
||||
await sdk?.connect();
|
||||
setIsConnected(true);
|
||||
} catch (err) {
|
||||
console.warn(`No accounts found`, err);
|
||||
}
|
||||
@@ -59,40 +55,35 @@ function MetaMaskConnect() {
|
||||
const disconnect = () => {
|
||||
if (sdk) {
|
||||
sdk.terminate();
|
||||
setIsConnected(false);
|
||||
}
|
||||
};
|
||||
|
||||
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 ? (
|
||||
{isConnected ? (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button>{formatAddress(account)}</Button>
|
||||
<Button variant="link" className="text-white">
|
||||
{formatAddress(account)}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-44">
|
||||
<button
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={disconnect}
|
||||
className="w-full px-4 py-2 text-left text-destructive hover:bg-muted"
|
||||
className="w-full px-4 py-2 text-left hover:bg-muted hover:text-destructive"
|
||||
>
|
||||
Disconnect
|
||||
</button>
|
||||
</Button>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
) : (
|
||||
<Button disabled={connecting} onClick={connect}>
|
||||
<Button
|
||||
disabled={connecting}
|
||||
onClick={connect}
|
||||
className="bg-light-purple bg-opacity-75 hover:bg-purple border-0 hover:border-0"
|
||||
>
|
||||
<WalletIcon className="mr-2 h-4 w-4" /> Connect Wallet
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -27,7 +27,8 @@ contract EventManager {
|
||||
uint256 capacity;
|
||||
uint256 ticketsSold;
|
||||
uint256 ticketPrice; // in USD cents
|
||||
uint256 eventDate;
|
||||
uint256 eventStartDate;
|
||||
uint256 eventEndDate;
|
||||
string[] images; // array of image URLs
|
||||
uint256[] tickets;
|
||||
address payable eventHost;
|
||||
@@ -39,7 +40,7 @@ contract EventManager {
|
||||
uint256 eventId;
|
||||
}
|
||||
|
||||
event EventCreated(uint256 eventId, string name, uint256 eventDate);
|
||||
event EventCreated(uint256 eventId, string name, uint256 eventStartDate);
|
||||
event TicketPurchased(uint256 ticketId, uint256 eventId, address buyer, uint256 price);
|
||||
event TicketTransferred(uint256 ticketId, address from, address to);
|
||||
event TicketTransferApproved(uint256 ticketId, address owner, address trustee);
|
||||
@@ -91,10 +92,10 @@ contract EventManager {
|
||||
return centsToFlare(events[_eventId].ticketPrice);
|
||||
}
|
||||
|
||||
function createEvent(string memory _name, string memory _description, string memory _location, uint256 _capacity, uint256 _ticketPrice, uint256 _eventDate, string[] memory _images) public returns (uint256 _eventId) {
|
||||
events[eventCounter] = Event(_name, _description, _location, _capacity, 0, _ticketPrice, _eventDate, _images, new uint256[](0), payable(msg.sender));
|
||||
function createEvent(string memory _name, string memory _description, string memory _location, uint256 _capacity, uint256 _ticketPrice, uint256 _eventStartDate, uint256 _eventEndDate, string[] memory _images) public returns (uint256 _eventId) {
|
||||
events[eventCounter] = Event(_name, _description, _location, _capacity, 0, _ticketPrice, _eventStartDate, _eventEndDate, _images, new uint256[](0), payable(msg.sender));
|
||||
eventCounter++;
|
||||
emit EventCreated(eventCounter - 1, _name, _eventDate);
|
||||
emit EventCreated(eventCounter - 1, _name, _eventStartDate);
|
||||
return eventCounter - 1;
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ contract EventManager {
|
||||
|
||||
function buyTicket(uint256 _eventId) public payable returns (uint256 _ticketId) {
|
||||
require(_eventId < eventCounter, "Invalid event ID");
|
||||
require(events[_eventId].eventDate > block.timestamp, "Event has already passed");
|
||||
require(events[_eventId].eventStartDate > block.timestamp, "Event has already passed");
|
||||
require(events[_eventId].tickets.length < events[_eventId].capacity, "Event is full");
|
||||
|
||||
uint256 ticketCost = getEventPriceFlare(_eventId); // Get ticket price in FLR
|
||||
@@ -143,7 +144,7 @@ contract EventManager {
|
||||
|
||||
function transferTicketForce(uint256 _ticketId, address _to) private {
|
||||
require(_ticketId < ticketCounter, "Invalid ticket ID");
|
||||
require(events[tickets[_ticketId].eventId].eventDate > block.timestamp, "Event has already passed");
|
||||
require(events[tickets[_ticketId].eventId].eventStartDate > block.timestamp, "Event has already passed");
|
||||
|
||||
address prevHolder = tickets[_ticketId].holder;
|
||||
|
||||
|
||||
108
package-lock.json
generated
108
package-lock.json
generated
@@ -4976,7 +4976,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@@ -13017,6 +13016,7 @@
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz",
|
||||
"integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
@@ -13379,6 +13379,7 @@
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz",
|
||||
"integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
@@ -24012,111 +24013,6 @@
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-arm64": {
|
||||
"version": "14.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.13.tgz",
|
||||
"integrity": "sha512-IkAmQEa2Htq+wHACBxOsslt+jMoV3msvxCn0WFSfJSkv/scy+i/EukBKNad36grRxywaXUYJc9mxEGkeIs8Bzg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-x64": {
|
||||
"version": "14.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.13.tgz",
|
||||
"integrity": "sha512-Dv1RBGs2TTjkwEnFMVL5XIfJEavnLqqwYSD6LXgTPdEy/u6FlSrLBSSfe1pcfqhFEXRAgVL3Wpjibe5wXJzWog==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-gnu": {
|
||||
"version": "14.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.13.tgz",
|
||||
"integrity": "sha512-yB1tYEFFqo4ZNWkwrJultbsw7NPAAxlPXURXioRl9SdW6aIefOLS+0TEsKrWBtbJ9moTDgU3HRILL6QBQnMevg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-musl": {
|
||||
"version": "14.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.13.tgz",
|
||||
"integrity": "sha512-v5jZ/FV/eHGoWhMKYrsAweQ7CWb8xsWGM/8m1mwwZQ/sutJjoFaXchwK4pX8NqwImILEvQmZWyb8pPTcP7htWg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-arm64-msvc": {
|
||||
"version": "14.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.13.tgz",
|
||||
"integrity": "sha512-uP1XkqCqV2NVH9+g2sC7qIw+w2tRbcMiXFEbMihkQ8B1+V6m28sshBwAB0SDmOe0u44ne1vFU66+gx/28RsBVQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-ia32-msvc": {
|
||||
"version": "14.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.13.tgz",
|
||||
"integrity": "sha512-V26ezyjPqQpDBV4lcWIh8B/QICQ4v+M5Bo9ykLN+sqeKKBxJVDpEc6biDVyluTXTC40f5IqCU0ttth7Es2ZuMw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-x64-msvc": {
|
||||
"version": "14.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.13.tgz",
|
||||
"integrity": "sha512-WwzOEAFBGhlDHE5Z73mNU8CO8mqMNLqaG+AO9ETmzdCQlJhVtWZnOl2+rqgVQS+YHunjOWptdFmNfbpwcUuEsw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,12 @@ const config: Config = {
|
||||
DEFAULT: '#000',
|
||||
100: '#000319',
|
||||
},
|
||||
'darkest-purple': '#240046',
|
||||
'darker-purple': '#3C096C',
|
||||
'dark-purple': '#5A189A',
|
||||
purple: '#7B2CBF',
|
||||
'light-purple': '#9D4EDD',
|
||||
|
||||
background: 'hsl(var(--background))',
|
||||
foreground: 'hsl(var(--foreground))',
|
||||
card: {
|
||||
|
||||
@@ -14,7 +14,8 @@ describe('EventManager', function () {
|
||||
const EVENT_LOCATION = 'London, UK';
|
||||
const EVENT_CAPACITY = 100;
|
||||
const EVENT_TICKET_PRICE = 1000; // 10 USD in cents
|
||||
const EVENT_DATE = Math.floor(Date.now() / 1000) + 86400; // 1 day from now
|
||||
const EVENT_START_DATE = Math.floor(Date.now() / 1000) + 86400; // 1 day from now
|
||||
const EVENT_END_DATE = Math.floor(Date.now() / 1000) + 172800; // 2 days from now
|
||||
const EVENT_IMAGES = ['image1.jpg', 'image2.jpg'];
|
||||
|
||||
beforeEach(async function () {
|
||||
@@ -32,7 +33,8 @@ describe('EventManager', function () {
|
||||
EVENT_LOCATION,
|
||||
EVENT_CAPACITY,
|
||||
EVENT_TICKET_PRICE,
|
||||
EVENT_DATE,
|
||||
EVENT_START_DATE,
|
||||
EVENT_END_DATE,
|
||||
EVENT_IMAGES
|
||||
);
|
||||
}
|
||||
@@ -47,7 +49,8 @@ describe('EventManager', function () {
|
||||
expect(event.location).to.equal(EVENT_LOCATION);
|
||||
expect(event.capacity).to.equal(EVENT_CAPACITY);
|
||||
expect(event.ticketPrice).to.equal(EVENT_TICKET_PRICE);
|
||||
expect(event.eventDate).to.equal(EVENT_DATE);
|
||||
expect(event.eventStartDate).to.equal(EVENT_START_DATE);
|
||||
expect(event.eventEndDate).to.equal(EVENT_END_DATE);
|
||||
expect(event.eventHost).to.equal(owner.address);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user