diff --git a/package.json b/package.json index f9255c3..7b6b6ed 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "build": "next build", "start": "next start", "lint": "next lint", - "ui:add": "bunx --bun shadcn-ui@latest add" + "ui:add": "bun x --bun shadcn-ui@latest add" }, "dependencies": { "@hookform/resolvers": "^3.3.4", diff --git a/src/app/badge/page.jsx b/src/app/event/[name]/badge/components/badge-3d.jsx similarity index 93% rename from src/app/badge/page.jsx rename to src/app/event/[name]/badge/components/badge-3d.jsx index 86694c9..a632bff 100644 --- a/src/app/badge/page.jsx +++ b/src/app/event/[name]/badge/components/badge-3d.jsx @@ -31,7 +31,7 @@ useTexture.preload( "https://github.com/user-attachments/assets/999b5d58-ac8a-4c20-8fc6-74e8ab7876e7", ); -export default function App() { +export default function Badge3D({ attendee }) { const { debug } = useControls({ debug: false }); return ( @@ -42,7 +42,7 @@ export default function App() { gravity={[0, -40, 0]} timeStep={1 / 60} > - + @@ -79,7 +79,7 @@ export default function App() { ); } -function BadgeTexture() { +function BadgeTexture({ attendee }) { // const viewport = useThree((state) => state.viewport); return ( @@ -105,19 +105,31 @@ function BadgeTexture() { bevelSize={0} font="/Geist_Regular.json" height={0} - position={[0.9, 2, 0]} + position={[1.05, 2.1, 0]} rotation={[0, Math.PI, Math.PI]} - size={0.2} - letterSpacing={-0.03} + size={0.15} + letterSpacing={-0.02} > - hyamero + {attendee.firstName} + {attendee.lastName} + + - {/* */} - + diff --git a/src/app/event/[name]/badge/components/badge-showcase.tsx b/src/app/event/[name]/badge/components/badge-showcase.tsx new file mode 100644 index 0000000..d0a5985 --- /dev/null +++ b/src/app/event/[name]/badge/components/badge-showcase.tsx @@ -0,0 +1,48 @@ +"use client"; + +import useMediaQuery from "@/hooks/use-media-query"; +import Badge3D from "./badge-3d"; +import { db } from "@/config/firebase"; +import { doc } from "firebase/firestore"; +import type { Attendee } from "@/lib/types"; +import { usePathname, useSearchParams } from "next/navigation"; +import { useDocumentOnce } from "react-firebase-hooks/firestore"; +import Loading from "../../loading"; + +export default function BadgeShowcase() { + const isDesktop = useMediaQuery("(min-width: 768px)"); + + const pathname = usePathname(); + const searchParams = useSearchParams(); + const certId = searchParams.get("id"); + + const [attendeeValue, attendeeLoading] = useDocumentOnce( + doc(db, `${pathname.split("/")[2]}/data/certificates/${certId}`), + ); + + const attendee = { + ...attendeeValue?.data(), + id: attendeeValue?.id, + } as Attendee; + + if (attendeeLoading) return ; + + if (!attendee.email) + return ( +
+

Certificate not found

+
+ ); + + return ( + <> + {isDesktop ? ( + + ) : ( +
+

Badge 2D

+
+ )} + + ); +} diff --git a/src/app/event/[name]/badge/page.tsx b/src/app/event/[name]/badge/page.tsx new file mode 100644 index 0000000..5ecdb3d --- /dev/null +++ b/src/app/event/[name]/badge/page.tsx @@ -0,0 +1,13 @@ +import { doc, getDoc } from "firebase/firestore"; +import BadgeShowcase from "./components/badge-showcase"; +import { db } from "@/config/firebase"; +import EventNotFound from "../../components/event-not-found"; + +export default async function Badge({ params }: { params: { name: string } }) { + const docRef = doc(db, params.name, "data"); + const docSnap = await getDoc(docRef); + + if (!docSnap.exists()) return ; + + return ; +} diff --git a/src/app/event/components/event-landing.tsx b/src/app/event/components/event-landing.tsx index 43eae2c..71e7d50 100644 --- a/src/app/event/components/event-landing.tsx +++ b/src/app/event/components/event-landing.tsx @@ -20,8 +20,16 @@ import { FormDescription, FormField, FormItem, + FormLabel, FormMessage, } from "@/components/ui/form"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; export type EventDetails = { title: string; @@ -40,6 +48,8 @@ const formSchema = z.object({ message: "This field has to be filled", }) .email("This is not a valid email"), + + type: z.enum(["badge", "cert"]), }); export default function EventLanding({ @@ -53,6 +63,7 @@ export default function EventLanding({ resolver: zodResolver(formSchema), defaultValues: { email: "dale@ban.com", + type: "badge", }, }); @@ -70,7 +81,7 @@ export default function EventLanding({ let message = "⚠️ Certificate Not Found"; querySnapshot.forEach((doc) => { if (doc.data().email) { - push(`/event/${eventCode}/cert?id=${doc.id}`); + push(`/event/${eventCode}/${values.type}?id=${doc.id}`); message = "✅ Certificate found!"; return; } @@ -119,13 +130,41 @@ export default function EventLanding({ )} /> - +
+ ( + + Select type + + + + )} + /> + +
diff --git a/src/app/page.tsx b/src/app/page.tsx index 7343d4b..4db0ee3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -16,7 +16,7 @@ export default async function Home() { )} > - + ✨ Experimental: Visit 3D Badge diff --git a/src/components/event-buttons.tsx b/src/components/event-buttons.tsx index 2c11194..104d725 100644 --- a/src/components/event-buttons.tsx +++ b/src/components/event-buttons.tsx @@ -78,7 +78,7 @@ export function EventButtons() { const SearchEventForm = ({}) => { const router = useRouter(); - const [event, setEvent] = useState(""); + const [event, setEvent] = useState("hacking-ai"); const [loading, setLoading] = useState(false); const handleSubmit = (e: FormEvent) => { diff --git a/src/components/magicui/retro-grid.tsx b/src/components/magicui/retro-grid.tsx index f389b16..d7d3610 100644 --- a/src/components/magicui/retro-grid.tsx +++ b/src/components/magicui/retro-grid.tsx @@ -4,7 +4,7 @@ export default function RetroGrid({ className }: { className?: string }) { return (