Skip to content

Commit

Permalink
feat: integrated razorpay
Browse files Browse the repository at this point in the history
  • Loading branch information
BRAVO68WEB committed Dec 27, 2023
1 parent 5c158d9 commit 5aa0692
Show file tree
Hide file tree
Showing 8 changed files with 361 additions and 33 deletions.
1 change: 1 addition & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { PlayCircleIcon, PlusCircleIcon } from '@heroicons/react/24/outline'
import Organisers from '@/components/Organisers'
import RegisterDialog from '@/components/RegisterDialog'
import { useState } from 'react'
import BookTicketDialog from '@/components/BookTicketDialog';

export default function Home() {
const [registerOpen, setRegisterOpen] = useState(false)
Expand Down
278 changes: 278 additions & 0 deletions components/BookTicketDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
'use client';
import { Fragment } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { useForm } from 'react-hook-form'
import {
RegisterForm,
registerFormSchema,
} from '@/validators/register.validator'
import { zodResolver } from '@hookform/resolvers/zod'
import toast from 'react-hot-toast'
import axios from 'axios'
import useRazorpay from 'react-razorpay'

export default function BookTicketDialog({
ticketType,
open,
setOpen,
}: {
ticketType: string,
open: boolean
setOpen: (val: boolean) => void
}) {
const [Razorpay] = useRazorpay();

const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm<RegisterForm>({
resolver: zodResolver(registerFormSchema),
})
const formSubmit = async (data: RegisterForm) => {
if (data.uni_id === '') data.uni_id = 'N/A'
if (data.uni_name === '') data.uni_name = 'N/A'

try {
const res = await axios.post(process.env.NEXT_PUBLIC_API_URL + '/order', {
ticket_type: ticketType,
ticket_data: data
})
const orderData = res.data
const options = {
key: process.env.NEXT_PUBLIC_RAZORPAY_KEY_ID!,
amount: orderData.amount,
currency: orderData.currency,
name: 'RCS CTF 2024',
description: 'RCS CTF 2024 Ticket',
image: 'https://rcs.encryptedge.in/favicon.ico',
order_id: orderData.id,
handler: async function (response: any) {
toast.success('Payment Recieved! Pease wait', {
position: 'top-right',
});

const verifyData = await axios.get(process.env.NEXT_PUBLIC_API_URL + '/check-pay/' + orderData.id)
if (verifyData.data === 'OK!') {
toast.success('Ticket Confirmed!', {
position: 'top-right',
});
} else {
toast.error('Ticket not verified!', {
position: 'top-right',
});
}
},
prefill: {
name: data.name,
email: data.email,
contact: data.contact_no
},
theme: {
color: "#531062",
},
}

const rzp1 = new Razorpay(options);

toast.success('Payment initiated, wait for 10-15 seconds after payment', {
position: 'top-right',
});

rzp1.on("payment.failed", function (response: any) {
toast.error('Payment Failed! reach out us with order id ' + response.error.metadata.order_id, {
duration: 30000
})
});

rzp1.open();
} catch (err) {
console.log(err)
toast.error('Error Submitting Form')
} finally {
setOpen(false)
reset()
}
}

return (
<Transition.Root show={open} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={setOpen}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>

<div className="fixed inset-0 z-10 w-screen overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative w-full transform overflow-hidden rounded-lg bg-black px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6">
<form
onSubmit={handleSubmit(formSubmit)}
className="space-y-6 "
action="#"
method="POST"
>
<div>
<label
htmlFor="name"
className="block text-sm font-medium leading-6 text-white"
>
Name
</label>
<div className="mt-2">
<input
id="name"
autoComplete="name"
{...register('name')}
className="block px-5 w-full rounded-md border-0 bg-white/5 py-1.5 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
/>
</div>
{errors.name && (
<div className="text-sm text-red-500">
{errors.name.message}
</div>
)}
</div>
<div>
<label
htmlFor="email"
className="block text-sm font-medium leading-6 text-white"
>
Email address
</label>
<div className="mt-2">
<input
id="email"
autoComplete="email"
type="email"
{...register('email')}
className="block px-5 w-full rounded-md border-0 bg-white/5 py-1.5 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
/>
</div>
{errors.email && (
<div className="text-sm text-red-500">
{errors.email.message}
</div>
)}
</div>
<div>
<label
htmlFor="contact_no"
className="block text-sm font-medium leading-6 text-white"
>
Contact Number
</label>
<div className="mt-2">
<input
id="contact_no"
autoComplete="contact_no"
{...register('contact_no')}
className="block px-5 w-full rounded-md border-0 bg-white/5 py-1.5 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
/>
</div>
{errors.contact_no && (
<div className="text-sm text-red-500">
{errors.contact_no.message}
</div>
)}
</div>
<div>
<label
htmlFor="uni_id"
className="block text-sm font-medium leading-6 text-white"
>
University Id
</label>
<div className="mt-2">
<input
id="uni_id"
{...register('uni_id')}
className="block px-5 w-full rounded-md border-0 bg-white/5 py-1.5 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
/>
</div>
{errors.uni_id && (
<div className="text-sm text-red-500">
{errors.uni_id.message}
</div>
)}
</div>
<div>
<label
htmlFor="uni_name"
className="block text-sm font-medium leading-6 text-white"
>
University Name
</label>
<div className="mt-2">
<input
id="uni_name"
{...register('uni_name')}
className="block px-5 w-full rounded-md border-0 bg-white/5 py-1.5 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
/>
</div>
{errors.uni_name && (
<div className="text-sm text-red-500">
{errors.uni_name.message}
</div>
)}
</div>
<div>
<label
htmlFor="where_you_reside"
className="block text-sm font-medium leading-6 text-white"
>
Where You Reside
</label>
<div className="mt-2">
<input
id="where_you_reside"
{...register(
'where_you_reside'
)}
className="block px-5 w-full rounded-md border-0 bg-white/5 py-1.5 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6"
/>
</div>
{errors.where_you_reside && (
<div className="text-sm text-red-500">
{
errors.where_you_reside
.message
}
</div>
)}
</div>

<div>
<button
type="submit"
className="flex w-full justify-center rounded-md bg-primary px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-primary/90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary"
>
Purchare Ticket
</button>
</div>
</form>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
)
}
63 changes: 38 additions & 25 deletions components/TicketSection/TicketCardLPU.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
import { toast } from 'react-hot-toast';
import React from 'react'
import Button from '../ui/Button'

function TicketCard() {
return (
<div className="card w-full max-w-sm bg-white text-black p-5">
<p className="font-bold text-4xl">
LPU <br />
Student Pass
</p>
<p className="mt-8 text-lg">
For the students of Lovely Professional University.
</p>
function TicketCard({
setTicketType,
setTicketBookingOpen
}: {
setTicketType: (val: string) => void,
setTicketBookingOpen: (val: boolean) => void
}) {
return (
<div className="card w-full max-w-sm bg-white text-black p-5">
<p className="font-bold text-4xl">
LPU <br />
Student Pass
</p>
<p className="mt-8 text-lg">
For the students of Lovely Professional University.
</p>

<div className="mt-8 text-lg">
<p className="text-primary">Includes: </p>
<div className="flex flex-col gap-2">
<p> - Welcome Kit Includes: 1 x Notepad-Pen, 1 x ID-Lanyard, Stickers</p>
<p> - Access to CTF</p>
<p> - Breakfast, Lunch, Dinner & Snacks</p>
<p> - Complimentry Swags</p>
<p> - Conference Attendee Certificate</p>
</div>
</div>
<div className="button mt-8">
<Button size={'full'}>Coming Soon</Button>
</div>
</div>
)
<div className="mt-8 text-lg">
<p className="text-primary">Includes: </p>
<div className="flex flex-col gap-2">
<p> - Welcome Kit Includes: 1 x Notepad-Pen, 1 x ID-Lanyard, Stickers</p>
<p> - Access to CTF</p>
<p> - Breakfast, Lunch, Dinner & Snacks</p>
<p> - Complimentry Swags</p>
<p> - Conference Attendee Certificate</p>
</div>
</div>
<div className="button mt-8">
<Button size={'full'} onClick={()=> {
setTicketType('student_pass')
setTicketBookingOpen(true)
toast.success('LPU Student Pass Selected', {
position: 'top-right',
});
}}>Coming Soon</Button>
</div>
</div>
)
}

export default TicketCard
17 changes: 15 additions & 2 deletions components/TicketSection/TicketCardProf.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import React from 'react'
import Button from '../ui/Button'
import toast from 'react-hot-toast'

function TicketCard() {
function TicketCard({
setTicketType,
setTicketBookingOpen
}: {
setTicketType: (val: string) => void,
setTicketBookingOpen: (val: boolean) => void
}) {
return (
<div className="card w-full max-w-sm bg-white text-black p-5">
<p className="font-bold text-4xl">
Expand All @@ -22,7 +29,13 @@ function TicketCard() {
</div>
</div>
<div className="button mt-8">
<Button size={'full'}>Coming Soon</Button>
<Button size={'full'} onClick={()=> {
setTicketType('professional_pass')
setTicketBookingOpen(true)
toast.success('Professional Pass Selected', {
position: 'top-right',
});
}}>Coming Soon</Button>
</div>
</div>
)
Expand Down
Loading

0 comments on commit 5aa0692

Please sign in to comment.