Skip to content

Commit 7a15dac

Browse files
committed
feat: add QR code and event edit pages
1 parent cbfaeaa commit 7a15dac

File tree

4 files changed

+359
-0
lines changed

4 files changed

+359
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Skeleton } from "@/components/ui/skeleton"
2+
import { Card, CardContent, CardHeader } from "@/components/ui/card"
3+
4+
export default function EditEventLoading() {
5+
return (
6+
<div className="container mx-auto py-6 space-y-6">
7+
<div>
8+
<Skeleton className="h-10 w-[150px] mb-2" />
9+
<Skeleton className="h-5 w-[250px]" />
10+
</div>
11+
12+
<Card>
13+
<CardHeader>
14+
<Skeleton className="h-6 w-[150px]" />
15+
</CardHeader>
16+
<CardContent className="space-y-6">
17+
<div className="space-y-2">
18+
<Skeleton className="h-5 w-[100px]" />
19+
<Skeleton className="h-10 w-full" />
20+
</div>
21+
22+
<div className="space-y-2">
23+
<Skeleton className="h-5 w-[120px]" />
24+
<Skeleton className="h-24 w-full" />
25+
</div>
26+
27+
<div className="grid grid-cols-2 gap-4">
28+
<div className="space-y-2">
29+
<Skeleton className="h-5 w-[80px]" />
30+
<Skeleton className="h-10 w-full" />
31+
</div>
32+
<div className="space-y-2">
33+
<Skeleton className="h-5 w-[100px]" />
34+
<Skeleton className="h-10 w-full" />
35+
</div>
36+
</div>
37+
38+
<div className="space-y-2">
39+
<Skeleton className="h-5 w-[150px]" />
40+
<Skeleton className="h-10 w-full" />
41+
</div>
42+
43+
<div className="flex justify-end space-x-2">
44+
<Skeleton className="h-10 w-[100px]" />
45+
<Skeleton className="h-10 w-[100px]" />
46+
</div>
47+
</CardContent>
48+
</Card>
49+
</div>
50+
)
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Metadata } from 'next'
2+
import { notFound } from 'next/navigation'
3+
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
4+
import { cookies } from 'next/headers'
5+
import { EventForm } from '@/components/events/event-form'
6+
7+
export const metadata: Metadata = {
8+
title: 'Edit Event | Cloud Burst',
9+
description: 'Edit your event details',
10+
}
11+
12+
interface PageProps {
13+
params: {
14+
id: string
15+
}
16+
}
17+
18+
export default async function EditEventPage({ params }: PageProps) {
19+
const { id } = params
20+
21+
const cookieStore = cookies()
22+
const supabase = createServerComponentClient({ cookies: () => cookieStore })
23+
24+
// Get current session
25+
const { data: { session } } = await supabase.auth.getSession()
26+
if (!session) notFound()
27+
28+
// Get event details
29+
const { data: event } = await supabase
30+
.from('events')
31+
.select('*')
32+
.eq('id', id)
33+
.single()
34+
35+
if (!event) notFound()
36+
37+
// Check if user has permission to edit this event
38+
const { data: profile } = await supabase
39+
.from('profiles')
40+
.select('role')
41+
.eq('id', session.user.id)
42+
.single()
43+
44+
const isAdmin = profile?.role === 'admin' || profile?.role === 'super_admin'
45+
const isOwner = event.organizer_id === session.user.id
46+
47+
if (!isAdmin && !isOwner) {
48+
// User doesn't have permission to edit this event
49+
notFound()
50+
}
51+
52+
return (
53+
<div className="container mx-auto py-6 space-y-6">
54+
<div>
55+
<h1 className="text-3xl font-bold tracking-tight">Edit Event</h1>
56+
<p className="text-muted-foreground">
57+
Update your event details and settings
58+
</p>
59+
</div>
60+
61+
<EventForm
62+
initialData={event}
63+
userId={session.user.id}
64+
mode="edit"
65+
/>
66+
</div>
67+
)
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Skeleton } from "@/components/ui/skeleton"
2+
import { Card, CardContent, CardHeader } from "@/components/ui/card"
3+
4+
export default function QRCodeLoading() {
5+
return (
6+
<div className="container mx-auto py-6 space-y-6">
7+
<div className="flex items-center justify-between">
8+
<div>
9+
<Skeleton className="h-10 w-[200px] mb-2" />
10+
<Skeleton className="h-5 w-[250px]" />
11+
</div>
12+
<Skeleton className="h-9 w-[120px]" />
13+
</div>
14+
15+
<div className="grid md:grid-cols-2 gap-6">
16+
<Card>
17+
<CardHeader>
18+
<Skeleton className="h-6 w-[150px] mb-2" />
19+
<Skeleton className="h-4 w-[250px]" />
20+
</CardHeader>
21+
<CardContent className="flex justify-center py-6">
22+
<Skeleton className="h-[300px] w-[300px]" />
23+
</CardContent>
24+
</Card>
25+
26+
<Card>
27+
<CardHeader>
28+
<Skeleton className="h-6 w-[180px] mb-2" />
29+
<Skeleton className="h-4 w-[220px]" />
30+
</CardHeader>
31+
<CardContent>
32+
<div className="space-y-4">
33+
<div>
34+
<Skeleton className="h-6 w-[180px] mb-2" />
35+
<Skeleton className="h-4 w-full" />
36+
<Skeleton className="h-4 w-3/4" />
37+
</div>
38+
39+
<Skeleton className="h-px w-full" />
40+
41+
<div>
42+
<Skeleton className="h-6 w-[160px] mb-2" />
43+
<Skeleton className="h-4 w-full" />
44+
<Skeleton className="h-4 w-2/3" />
45+
</div>
46+
47+
<Skeleton className="h-px w-full" />
48+
49+
<div>
50+
<Skeleton className="h-6 w-[140px] mb-2" />
51+
<Skeleton className="h-4 w-full" />
52+
<Skeleton className="h-4 w-full" />
53+
</div>
54+
55+
<Skeleton className="h-px w-full" />
56+
57+
<div>
58+
<Skeleton className="h-6 w-[170px] mb-2" />
59+
<Skeleton className="h-4 w-full" />
60+
<Skeleton className="h-4 w-1/2" />
61+
</div>
62+
</div>
63+
</CardContent>
64+
</Card>
65+
</div>
66+
</div>
67+
)
68+
}
+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import { Metadata } from 'next'
2+
import { notFound } from 'next/navigation'
3+
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
4+
import { cookies } from 'next/headers'
5+
import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from "@/components/ui/card"
6+
import { Separator } from "@/components/ui/separator"
7+
import { QRCodeDisplay } from '@/components/events/qr-code-display'
8+
import { Button } from '@/components/ui/button'
9+
import Link from 'next/link'
10+
import { ArrowLeft, Printer, Share2, Download, Info } from 'lucide-react'
11+
12+
export const metadata: Metadata = {
13+
title: 'Event QR Code | Cloud Burst',
14+
description: 'QR code for your event',
15+
}
16+
17+
interface PageProps {
18+
params: {
19+
id: string
20+
}
21+
}
22+
23+
export default async function EventQRCodePage({ params }: PageProps) {
24+
const { id } = params
25+
26+
const cookieStore = cookies()
27+
const supabase = createServerComponentClient({ cookies: () => cookieStore })
28+
29+
// Get current session
30+
const { data: { session } } = await supabase.auth.getSession()
31+
if (!session) notFound()
32+
33+
// Get event details
34+
const { data: event } = await supabase
35+
.from('events')
36+
.select('*')
37+
.eq('id', id)
38+
.single()
39+
40+
if (!event) notFound()
41+
42+
return (
43+
<div className="container max-w-6xl mx-auto py-6 px-4 sm:px-6">
44+
<div className="flex items-center justify-between mb-8">
45+
<div>
46+
<h1 className="text-3xl font-bold tracking-tight">Event QR Code</h1>
47+
<p className="text-muted-foreground mt-1">
48+
QR code for {event.name}
49+
</p>
50+
</div>
51+
<Button variant="outline" asChild>
52+
<Link href={`/protected/events/${id}`}>
53+
<ArrowLeft className="mr-2 h-4 w-4" />
54+
Back to Event
55+
</Link>
56+
</Button>
57+
</div>
58+
59+
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
60+
{/* QR Code Card */}
61+
<Card className="lg:col-span-5 border">
62+
<CardHeader className="pb-2">
63+
<CardTitle>Event QR Code</CardTitle>
64+
<CardDescription>
65+
Scan to access the event gallery
66+
</CardDescription>
67+
</CardHeader>
68+
<CardContent>
69+
<div className="border rounded-lg p-6 mb-4 bg-black text-white">
70+
<div className="text-lg font-medium mb-2">{event.name} QR Code</div>
71+
<div className="text-sm text-gray-300 mb-4">Scan this code to access the event gallery</div>
72+
<div className="flex justify-center">
73+
<QRCodeDisplay
74+
eventId={id}
75+
eventName={event.name}
76+
size={280}
77+
/>
78+
</div>
79+
</div>
80+
<div className="flex gap-4">
81+
<Button variant="outline" className="flex-1">
82+
<Download className="h-4 w-4 mr-2" />
83+
Download
84+
</Button>
85+
<Button variant="secondary" className="flex-1">
86+
<Share2 className="h-4 w-4 mr-2" />
87+
Share
88+
</Button>
89+
</div>
90+
</CardContent>
91+
</Card>
92+
93+
{/* Usage Instructions */}
94+
<div className="lg:col-span-7">
95+
<Card className="border h-full">
96+
<CardHeader className="pb-2">
97+
<CardTitle>How to Use This QR Code</CardTitle>
98+
<CardDescription>
99+
Tips for maximizing engagement with your event QR code
100+
</CardDescription>
101+
</CardHeader>
102+
<CardContent className="p-6">
103+
<div className="grid grid-cols-2 gap-6 mb-6">
104+
<div className="border rounded-lg p-6 bg-blue-50/10 hover:bg-blue-50/20 transition-colors">
105+
<div className="flex flex-col items-center text-center h-full">
106+
<div className="flex items-center justify-center w-16 h-16 rounded-full bg-gray-900 mb-4">
107+
<Printer className="h-7 w-7 text-blue-400" />
108+
</div>
109+
<h3 className="font-medium text-base mb-3">Display at Event</h3>
110+
<p className="text-sm text-muted-foreground">
111+
Print and place at entrances, photo booths, and tables.
112+
</p>
113+
</div>
114+
</div>
115+
116+
<div className="border rounded-lg p-6 bg-blue-50/10 hover:bg-blue-50/20 transition-colors">
117+
<div className="flex flex-col items-center text-center h-full">
118+
<div className="flex items-center justify-center w-16 h-16 rounded-full bg-gray-900 mb-4">
119+
<Share2 className="h-7 w-7 text-blue-400" />
120+
</div>
121+
<h3 className="font-medium text-base mb-3">Include in Materials</h3>
122+
<p className="text-sm text-muted-foreground">
123+
Add to programs, invitations, and digital communications.
124+
</p>
125+
</div>
126+
</div>
127+
128+
<div className="border rounded-lg p-6 bg-blue-50/10 hover:bg-blue-50/20 transition-colors">
129+
<div className="flex flex-col items-center text-center h-full">
130+
<div className="flex items-center justify-center w-16 h-16 rounded-full bg-gray-900 mb-4">
131+
<Download className="h-7 w-7 text-blue-400" />
132+
</div>
133+
<h3 className="font-medium text-base mb-3">Easy Access</h3>
134+
<p className="text-sm text-muted-foreground">
135+
Attendees can scan to instantly access the event gallery.
136+
</p>
137+
</div>
138+
</div>
139+
140+
<div className="border rounded-lg p-6 bg-blue-50/10 hover:bg-blue-50/20 transition-colors">
141+
<div className="flex flex-col items-center text-center h-full">
142+
<div className="flex items-center justify-center w-16 h-16 rounded-full bg-gray-900 mb-4">
143+
<Info className="h-7 w-7 text-blue-400" />
144+
</div>
145+
<h3 className="font-medium text-base mb-3">No Account Required</h3>
146+
<p className="text-sm text-muted-foreground">
147+
Anyone can view and upload photos without registration.
148+
</p>
149+
</div>
150+
</div>
151+
</div>
152+
153+
<div className="border border-blue-800 bg-blue-950/50 rounded-lg p-4">
154+
<div className="flex items-start">
155+
<div className="flex items-center justify-center w-10 h-10 rounded-full bg-blue-900 mr-4 flex-shrink-0">
156+
<Info className="h-5 w-5 text-blue-400" />
157+
</div>
158+
<div>
159+
<h3 className="font-medium text-blue-300 mb-2">Pro Tip</h3>
160+
<p className="text-sm text-blue-400">
161+
For maximum engagement, announce the QR code during your event and explain how attendees can use it to view and share photos. Consider offering a small incentive for those who upload photos.
162+
</p>
163+
</div>
164+
</div>
165+
</div>
166+
</CardContent>
167+
</Card>
168+
</div>
169+
</div>
170+
</div>
171+
)
172+
}

0 commit comments

Comments
 (0)