-
Notifications
You must be signed in to change notification settings - Fork 3
feat: move playground
section to its own page to add the demo
#22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
aimensahnoun
merged 11 commits into
main
from
21-improve-the-uiux-of-the-example-ticketing-app
Nov 15, 2024
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
50dc477
refactor: move `playground` section to its own page to add the demo
aimensahnoun 05b37aa
refactor: group routes by type
aimensahnoun 622f1b4
feat: add featured events carousel
aimensahnoun 286c50e
feat: add event listings to landing page
aimensahnoun f7fe882
feat: event details page
aimensahnoun f1b5dd4
refactor: update ticketSelector
aimensahnoun 2fc4b2f
fix: simplify ticket store
aimensahnoun 1605ca0
feat: checkout flow
aimensahnoun 0dc7db0
chore: upgrade payment widget version
aimensahnoun 46b7157
feat: reroute to main page after purchase
aimensahnoun 61fe301
refactor: add aria tags to elements
aimensahnoun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,12 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = {}; | ||
const nextConfig = { | ||
images: { | ||
remotePatterns: [ | ||
{ | ||
hostname: "images.unsplash.com", | ||
}, | ||
], | ||
}, | ||
}; | ||
|
||
export default nextConfig; |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { CheckoutStepper } from "@/components/CheckoutStepper"; | ||
|
||
export default function CheckoutPage() { | ||
return ( | ||
<div className="container mx-auto px-4 py-8"> | ||
<h1 className="text-3xl font-bold mb-8">Checkout</h1> | ||
<CheckoutStepper /> | ||
</div> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { notFound } from "next/navigation"; | ||
import Image from "next/image"; | ||
import { CalendarIcon, MapPinIcon, Clock } from "lucide-react"; | ||
import { format } from "date-fns"; | ||
import { TicketSelector } from "@/components/TicketSelector"; | ||
import eventsData from "@/const/data.json"; | ||
|
||
async function getEventById(id: string) { | ||
// In a real app, this would be a DB or API call | ||
const event = eventsData.events.find((event) => event.id === id); | ||
if (!event) return null; | ||
return event; | ||
} | ||
aimensahnoun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export default async function EventDetailsPage({ | ||
params, | ||
}: { | ||
params: { id: string }; | ||
}) { | ||
const event = await getEventById(params.id); | ||
|
||
if (!event) { | ||
notFound(); | ||
} | ||
|
||
return ( | ||
<div className="min-h-screen bg-gray-50"> | ||
{/* Hero Section */} | ||
<div className="relative h-[400px] w-full"> | ||
<Image | ||
src={event.headerImage} | ||
alt={event.name} | ||
fill | ||
className="object-cover" | ||
priority | ||
/> | ||
<div className="absolute inset-0 bg-black/50" /> | ||
<div className="absolute bottom-8 left-8"> | ||
<span className="inline-block px-3 py-1 mb-4 text-sm font-medium text-white bg-[#099C77] rounded-full"> | ||
{event.type} | ||
</span> | ||
<h1 className="text-4xl font-bold text-white">{event.name}</h1> | ||
</div> | ||
</div> | ||
|
||
{/* Content Section */} | ||
<div className="container mx-auto px-4 py-8"> | ||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> | ||
{/* Main Content */} | ||
<div className="lg:col-span-2 space-y-8"> | ||
{/* Event Details */} | ||
<section className="bg-white rounded-xl p-6 shadow-sm"> | ||
<h2 className="text-2xl font-semibold mb-4">Event Details</h2> | ||
<div className="space-y-4"> | ||
<div className="flex items-center gap-3"> | ||
<CalendarIcon className="w-5 h-5 text-[#099C77]" /> | ||
<span> | ||
{format(new Date(event.dateTime), "MMMM d, yyyy")} | ||
</span> | ||
</div> | ||
<div className="flex items-center gap-3"> | ||
<Clock className="w-5 h-5 text-[#099C77]" /> | ||
<span> | ||
{format(new Date(event.dateTime), "h:mm a")} -{" "} | ||
{format(new Date(event.endDateTime), "h:mm a")} | ||
</span> | ||
aimensahnoun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</div> | ||
<div className="flex items-center gap-3"> | ||
<MapPinIcon className="w-5 h-5 text-[#099C77]" /> | ||
<span> | ||
{event.location.venue}, {event.location.city},{" "} | ||
{event.location.country} | ||
</span> | ||
</div> | ||
</div> | ||
</section> | ||
|
||
{/* About Section */} | ||
<section className="bg-white rounded-xl p-6 shadow-sm"> | ||
<h2 className="text-2xl font-semibold mb-4">About the Event</h2> | ||
<p className="text-gray-600">{event.organizer.description}</p> | ||
</section> | ||
|
||
{/* Organizer Section */} | ||
<section className="bg-white rounded-xl p-6 shadow-sm"> | ||
<h2 className="text-2xl font-semibold mb-4">Organizer</h2> | ||
<div className="flex items-center gap-4"> | ||
<div className="relative h-16 w-16 rounded-full overflow-hidden"> | ||
<Image | ||
src={event.organizer.logo} | ||
alt={event.organizer.name} | ||
fill | ||
className="object-cover" | ||
/> | ||
</div> | ||
<div> | ||
<h3 className="font-semibold">{event.organizer.name}</h3> | ||
<p className="text-sm text-gray-600">Event Organizer</p> | ||
</div> | ||
</div> | ||
</section> | ||
</div> | ||
|
||
{/* Ticket Selection Sidebar */} | ||
<div className="lg:col-span-1"> | ||
<TicketSelector event={event} /> | ||
</div> | ||
aimensahnoun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { EventShowcase } from "@/components/EventShowcase"; | ||
import { | ||
Carousel, | ||
CarouselContent, | ||
CarouselItem, | ||
} from "@/components/ui/carousel"; | ||
import eventData from "@/const/data.json"; | ||
import Image from "next/image"; | ||
import Link from "next/link"; | ||
|
||
export const metadata = { | ||
title: "Request Checkout Demo", | ||
description: | ||
"This is a demo of the Request Checkout widget. It is a pre-built component that abstracts all the complexities of blockchain transactions using Request Network, making it simple for businesses to handle crypto-to-crypto payments without deep technical knowledge", | ||
}; | ||
|
||
export default function DemoPage() { | ||
const events = eventData.events; | ||
const featuredEvents = events.filter((event) => event.featured); | ||
|
||
return ( | ||
<> | ||
<section className="flex flex-col gap-2"> | ||
{/* Featured Events Carousel */} | ||
<div className="mb-8"> | ||
<Carousel | ||
className="w-full" | ||
autoplay | ||
aria-label="Featured Events Slideshow" | ||
> | ||
<CarouselContent> | ||
{featuredEvents.map((event) => ( | ||
<CarouselItem key={event.id}> | ||
<Link | ||
href={`/events/${event.id}`} | ||
aria-label={`View details for ${event.name}`} | ||
> | ||
<div className="relative aspect-[3/1] w-full overflow-hidden rounded-lg"> | ||
<Image | ||
src={event.headerImage} | ||
alt={event.name} | ||
fill | ||
className="object-cover" | ||
/> | ||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent" /> | ||
<div className="absolute bottom-4 left-4 right-4 text-white"> | ||
<div className="mb-2"> | ||
<span className="inline-block px-2 py-1 text-xs font-semibold bg-white/20 rounded-full"> | ||
{event.type} | ||
</span> | ||
</div> | ||
<h2 className="text-2xl font-bold">{event.name}</h2> | ||
<p className="text-sm text-white/80">Featured Event</p> | ||
</div> | ||
</div> | ||
</Link> | ||
</CarouselItem> | ||
))} | ||
</CarouselContent> | ||
</Carousel> | ||
</div> | ||
<EventShowcase events={events} /> | ||
</section> | ||
</> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
"use client"; | ||
|
||
import { useTicketStore } from "@/store/ticketStore"; | ||
import { useEffect, useState } from "react"; | ||
|
||
export function CartReview() { | ||
const { tickets, incrementQuantity, decrementQuantity, clearTickets } = | ||
useTicketStore(); | ||
const [total, setTotal] = useState(0); | ||
|
||
useEffect(() => { | ||
const newTotal = Object.values(tickets).reduce( | ||
(sum, ticket) => sum + ticket.price * ticket.quantity, | ||
0 | ||
); | ||
setTotal(newTotal); | ||
}, [tickets]); | ||
aimensahnoun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
const groupedTickets = Object.entries(tickets).map(([key, ticket]) => ({ | ||
eventId: key.split("-")[0], | ||
...ticket, | ||
})); | ||
aimensahnoun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return ( | ||
<div | ||
className="bg-white rounded-xl p-6 shadow-sm" | ||
role="region" | ||
aria-label="Shopping Cart" | ||
> | ||
<div className="flex justify-between items-center mb-6"> | ||
<h2 className="text-2xl font-semibold">Cart Review</h2> | ||
{groupedTickets.length > 0 && ( | ||
<button | ||
onClick={clearTickets} | ||
className="text-red-500 hover:text-red-600 text-sm font-medium" | ||
aria-label="Clear all items from cart" | ||
> | ||
Clear Cart | ||
</button> | ||
)} | ||
</div> | ||
|
||
{groupedTickets.length === 0 ? ( | ||
<p className="text-gray-500">Your cart is empty</p> | ||
) : ( | ||
<div> | ||
<div className="max-h-[300px] overflow-y-auto space-y-4 pr-2"> | ||
{groupedTickets.map((ticket) => ( | ||
<div | ||
key={ticket.id} | ||
className="border border-gray-100 rounded-lg p-4 bg-gray-50" | ||
> | ||
<div className="flex justify-between items-start gap-4"> | ||
<div> | ||
<h3 className="font-medium text-gray-900">{ticket.name}</h3> | ||
<p className="text-[#099C77] font-medium"> | ||
${ticket.price.toFixed(2)} | ||
</p> | ||
</div> | ||
<div className="flex items-center gap-2"> | ||
<button | ||
onClick={() => decrementQuantity(ticket.id)} | ||
className="w-7 h-7 rounded-lg border border-gray-200 flex items-center justify-center text-gray-600 hover:border-[#099C77] hover:text-[#099C77] transition-colors" | ||
aria-label={`Decrease quantity for ${ticket.name}`} | ||
> | ||
- | ||
</button> | ||
<span | ||
className="w-8 text-center font-medium" | ||
aria-label={`${ticket.quantity} tickets selected`} | ||
> | ||
{ticket.quantity} | ||
</span> | ||
<button | ||
onClick={() => | ||
incrementQuantity(ticket.id, { | ||
id: ticket.id, | ||
name: ticket.name, | ||
price: ticket.price, | ||
description: "", | ||
available: 0, | ||
}) | ||
} | ||
aimensahnoun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
className="w-7 h-7 rounded-lg border border-gray-200 flex items-center justify-center text-gray-600 hover:border-[#099C77] hover:text-[#099C77] transition-colors" | ||
aria-label={`Increase quantity for ${ticket.name}`} | ||
> | ||
+ | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
|
||
<div className="mt-6 pt-6 border-t border-gray-200"> | ||
<div className="flex justify-between items-center"> | ||
<span className="font-medium text-gray-900">Total:</span> | ||
<span className="text-xl font-bold text-[#099C77]"> | ||
${total > 0 ? total.toFixed(2) : "0.00"} | ||
</span> | ||
</div> | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.