Skip to content

Commit 9b48697

Browse files
committedAug 22, 2023
payment
1 parent ab16424 commit 9b48697

File tree

5 files changed

+163
-26
lines changed

5 files changed

+163
-26
lines changed
 

‎components/form/responses.tsx

+14-2
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ export default function ResponsesForms({ dataForm }: { dataForm: any }) {
166166
.reverse()
167167
.map((response, index) => (
168168
<div
169-
className="flex w-full flex-col items-start gap-4 rounded-md border border-dashed border-slate-300 p-4 dark:border-slate-700"
169+
className={cn(
170+
"flex w-full flex-col items-start gap-4 rounded-md border border-dashed border-slate-300 p-4 dark:border-slate-700"
171+
// response.paymentStatut === "complete" ? "bg-emerald-50/50 dark:bg-emerald-500/5" : ""
172+
)}
170173
key={index}
171174
>
172175
<Accordion
@@ -175,7 +178,16 @@ export default function ResponsesForms({ dataForm }: { dataForm: any }) {
175178
className="w-full border-b border-dashed border-slate-300 dark:border-slate-700"
176179
>
177180
<AccordionItem value="response" className="border-none">
178-
<AccordionTrigger>View response</AccordionTrigger>
181+
<AccordionTrigger>
182+
<div className="flex items-center justify-start gap-2">
183+
View response
184+
{response.paymentStatut === "complete" ? (
185+
<span className="bg-green-100 text-green-800 text-xs font-medium mr-2 px-2.5 py-0.5 rounded dark:bg-green-900 dark:text-green-300">
186+
PAID ( {dataForm.amountNotchPay} EURO )
187+
</span>
188+
) : null}
189+
</div>
190+
</AccordionTrigger>
179191
<AccordionContent>
180192
<div className="flex w-full flex-col items-start gap-2 ">
181193
{response.responses.map((answer, answerIndex) => (

‎components/form/settings.tsx

+6-19
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { useGetDocumentFromUser } from "@/firebase/firestore/getDocumentFromUser
1717
import { useGetFavoriteCode } from "@/firebase/firestore/getFavoriteCode"
1818
import { useGetIsPrivateCodeFromUser } from "@/firebase/firestore/getIsPrivateCodeFromUser"
1919
import { useUpdateFormDocument } from "@/firebase/firestore/updateFormDocument"
20-
import usePaymentInitialization from "@/notchpay/initializePayment.js"
2120
import copyToClipboard from "@/utils/copyToClipboard.js"
2221
import embedProject from "@/utils/embedStackblitzProject"
2322
import indentCode from "@/utils/indentCode.js"
@@ -106,8 +105,6 @@ export default function SettingsForms({ dataForm }: { dataForm: any }) {
106105
const { user, userPseudo } = useAuthContext()
107106
const router = useRouter()
108107

109-
const { initializePayment, isLoading, isError } = usePaymentInitialization()
110-
111108
const { toast } = useToast()
112109

113110
const notifyUrlCopied = () =>
@@ -148,15 +145,15 @@ export default function SettingsForms({ dataForm }: { dataForm: any }) {
148145
is: true,
149146
then: (schema) =>
150147
schema
151-
.matches(/^b\./, 'Public NotchPay API key must start with "b."')
148+
.matches(/^pk\./, 'Public NotchPay API key must start with "b."')
152149
.required("Public NotchPay API key is required"),
153150
}),
154151
amountNotchPay: yup.number().when("acceptPayment", {
155152
is: true,
156153
then: (schema) =>
157154
schema
158-
.typeError("Amount for NotchPay must be a valid number")
159155
.min(2, "Amount for NotchPay must be greater than 2")
156+
.typeError("Amount for NotchPay must be a valid number")
160157
.required("Amount for NotchPay is required"),
161158
}),
162159
})
@@ -354,12 +351,7 @@ export default function SettingsForms({ dataForm }: { dataForm: any }) {
354351
</p>
355352
</div>
356353
<Separator className="opacity-50" />
357-
<div
358-
className="flex w-full flex-col items-start gap-2"
359-
style={{
360-
opacity: checkboxAcceptPayment ? "1" : "0.2",
361-
}}
362-
>
354+
<div className="flex w-full flex-col items-start gap-2">
363355
<div className="flex w-full flex-col items-start gap-1">
364356
<Label>Public NotchPay API key</Label>
365357
<p className="text-left text-sm">
@@ -373,7 +365,7 @@ export default function SettingsForms({ dataForm }: { dataForm: any }) {
373365
</p>
374366
</div>
375367
<Input
376-
placeholder="b.xxxxxxx...xxxxxxxx"
368+
placeholder="pk.xxxxxxx...xxxxxxxx"
377369
{...register("publicNotchPayApiKey")}
378370
/>
379371
<p className="text-sm text-red-500">
@@ -382,12 +374,7 @@ export default function SettingsForms({ dataForm }: { dataForm: any }) {
382374
)}
383375
</p>
384376
</div>
385-
<div
386-
className="flex w-full flex-col items-start gap-2"
387-
style={{
388-
opacity: checkboxAcceptPayment ? "1" : "0.2",
389-
}}
390-
>
377+
<div className="flex w-full flex-col items-start gap-2">
391378
<Label>Amount ( in EURO ) </Label>
392379
<Input placeholder="2 EURO" {...register("amountNotchPay")} />
393380
<p className="text-sm text-red-500">
@@ -438,7 +425,7 @@ export default function SettingsForms({ dataForm }: { dataForm: any }) {
438425
</Button>
439426
{isSuccessUpdateForm && (
440427
<div
441-
className="flex w-full items-center rounded-lg bg-green-50 p-4 text-green-800 dark:bg-gray-800 dark:text-green-400"
428+
className="flex mt-2 w-full items-center rounded-lg bg-green-50 p-4 text-green-800 dark:bg-gray-800 dark:text-green-400"
442429
role="alert"
443430
>
444431
<Check className="h-4 w-4" />

‎notchpay/initializePayment.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default function usePaymentInitialization() {
77
const [isLoading, setIsLoading] = useState(false)
88
const [isError, setIsError] = useState(false)
99

10-
const initializePayment = async (email, amount, description, publicKey) => {
10+
const initializePayment = async (email, amount, description, publicKey, callback) => {
1111
setIsLoading(true)
1212
setIsError(false)
1313

@@ -16,8 +16,7 @@ export default function usePaymentInitialization() {
1616
currency: "EUR",
1717
amount,
1818
description,
19-
callback: "http://localhost:3000/donation",
20-
// callback: "https://sharuco.lndev.me/donation",
19+
callback,
2120
}
2221

2322
try {

‎pages/donation.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ export default function Donation() {
7979
emailToUse,
8080
parseInt(price),
8181
"Donation for Sharuco",
82-
process.env.NEXT_PUBLIC_NOTCH_PAY_PUBLIC_KEY_TEST
82+
process.env.NEXT_PUBLIC_NOTCH_PAY_PUBLIC_KEY,
83+
"https://sharuco.lndev.me/donation"
8384
)
8485
reset({
8586
price: 0,

‎pages/form/view/[form]/index.tsx

+139-1
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ import { useGetDocumentFromUser } from "@/firebase/firestore/getDocumentFromUser
1717
import { useGetFavoriteCode } from "@/firebase/firestore/getFavoriteCode"
1818
import { useGetIsPrivateCodeFromUser } from "@/firebase/firestore/getIsPrivateCodeFromUser"
1919
import { useUpdateFormDocument } from "@/firebase/firestore/updateFormDocument"
20+
import usePaymentInitialization from "@/notchpay/initializePayment.js"
2021
import copyToClipboard from "@/utils/copyToClipboard.js"
2122
import embedProject from "@/utils/embedStackblitzProject"
2223
import indentCode from "@/utils/indentCode.js"
2324
import linearizeCode from "@/utils/linearizeCode"
2425
import { yupResolver } from "@hookform/resolvers/yup"
2526
import sdk, { Project } from "@stackblitz/sdk"
2627
import algoliasearch from "algoliasearch"
28+
import axios from "axios"
2729
import hljs from "highlight.js"
2830
import {
2931
Check,
@@ -127,6 +129,7 @@ export default function FormViewPage() {
127129
text: yup.string().required("This field is required"),
128130
})
129131
),
132+
paymentStatut: yup.string(),
130133
})
131134

132135
const ALGOLIA_INDEX_NAME = "forms"
@@ -158,14 +161,17 @@ export default function FormViewPage() {
158161
}: any = useUpdateFormDocument("forms")
159162

160163
const onSubmit = async (data) => {
164+
setPaymentDone(false)
161165
let updatedFormData: {
162166
responses: any[]
167+
paymentStatut?: string
163168
} = {
164169
responses: [
165170
...dataForm?.data?.responses,
166171
{
167172
idResponse: moment().valueOf() + uid(),
168173
createdAt: moment().valueOf(),
174+
paymentStatut: data.paymentStatut ? data.paymentStatut : "",
169175
responses: [
170176
...data.responses.map((response: any, index: number) => {
171177
return {
@@ -178,7 +184,7 @@ export default function FormViewPage() {
178184
},
179185
],
180186
}
181-
//console.log("updatedFormData", updatedFormData)
187+
// console.log("updatedFormData", updatedFormData)
182188

183189
const id = searchParams.get("form")
184190

@@ -204,6 +210,74 @@ export default function FormViewPage() {
204210
window.location.href = dataForm.data.redirectOnCompletion
205211
}
206212

213+
// payment
214+
215+
const [paymentDone, setPaymentDone] = useState(false)
216+
217+
const checkPaymentStatus = async () => {
218+
const transactionReference = localStorage.getItem("transaction-reference")
219+
const CAPTURE_URL = `https://api.notchpay.co/payments/${transactionReference}`
220+
221+
if (!transactionReference) {
222+
return
223+
}
224+
225+
try {
226+
const response = await axios.get(CAPTURE_URL, {
227+
headers: {
228+
Accept: "application/json",
229+
Authorization: process.env.NEXT_PUBLIC_NOTCH_PAY_PUBLIC_KEY,
230+
},
231+
})
232+
const paymentStatus = response.data.transaction.status
233+
234+
if (paymentStatus === "complete") {
235+
localStorage.removeItem("transaction-reference")
236+
setValue("paymentStatut", "complete")
237+
setPaymentDone(true)
238+
}
239+
} catch (error) {}
240+
}
241+
242+
useEffect(() => {
243+
if (window.location.search.includes("?reference=")) {
244+
checkPaymentStatus()
245+
}
246+
}, [])
247+
248+
const {
249+
initializePayment,
250+
isLoading: isLoadingPayment,
251+
isError: isErrorPayment,
252+
} = usePaymentInitialization()
253+
254+
const schemaPayment = yup.object().shape({
255+
email: yup.string().email().required(),
256+
})
257+
258+
const {
259+
register: registerPayment,
260+
handleSubmit: handleSubmitPayment,
261+
reset: resetPayment,
262+
formState: { errors: errorsPayment },
263+
} = useForm({
264+
resolver: yupResolver(schemaPayment),
265+
})
266+
267+
const onSubmitPayment = async (data) => {
268+
const { email } = data
269+
initializePayment(
270+
email,
271+
dataForm?.data?.amountNotchPay,
272+
"Sharuco Form Payment",
273+
dataForm?.data?.publicNotchPayApiKey,
274+
`https://sharuco.lndev.me/form/view/${searchParams.get("form")}`
275+
)
276+
resetPayment({
277+
email: "",
278+
})
279+
}
280+
207281
return (
208282
<Layout>
209283
<Head>
@@ -251,6 +325,70 @@ export default function FormViewPage() {
251325
</div>
252326
<Separator className="mx-auto my-8 sm:w-2/3" />
253327
<div className="mx-auto w-full space-y-6 lg:w-2/3">
328+
{dataForm?.data?.acceptPayment && !paymentDone && (
329+
<div className="px-4 py-6 bg-emerald-50/50 dark:bg-emerald-500/5 rounded-xl border border-[#11B981] flex flex-col sm:flex-row items-start gap-4">
330+
<a href="https://notchpay.co/" className="w-12 shrink-0">
331+
<img
332+
src="/partner/notchpay-favicon.svg"
333+
alt="notchpay"
334+
/>
335+
</a>
336+
<div className="w-full flex flex-col items-start gap-2">
337+
<p>
338+
This form accepts a payment at the rate of{" "}
339+
<span className="font-bold">
340+
{dataForm?.data?.amountNotchPay} Euro
341+
</span>{" "}
342+
, If you make it this will be notified to the
343+
administrator of this form.
344+
</p>
345+
<div className="w-full flex flex-col sm:flex-row items-start gap-2">
346+
<div className="w-full flex flex-col items-start gap-2">
347+
<Input
348+
className="w-full"
349+
placeholder="Enter your email"
350+
{...registerPayment("email")}
351+
/>
352+
<p className="text-sm text-red-500">
353+
{errorsPayment.email && (
354+
<>{errorsPayment.email.message}</>
355+
)}
356+
</p>
357+
</div>
358+
<Button
359+
className="shrink-0 w-full sm:w-fit"
360+
disabled={isLoadingPayment}
361+
onClick={
362+
!isLoadingPayment
363+
? handleSubmitPayment(onSubmitPayment)
364+
: undefined
365+
}
366+
>
367+
{isLoadingPayment && (
368+
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
369+
)}
370+
Pay {dataForm?.data?.amountNotchPay} EURO
371+
</Button>
372+
</div>
373+
</div>
374+
</div>
375+
)}
376+
{paymentDone ? (
377+
<div className="px-4 py-6 bg-emerald-50/50 dark:bg-emerald-500/5 rounded-xl border border-[#11B981] flex flex-col sm:flex-row items-start gap-4">
378+
<a href="https://notchpay.co/" className="w-12 shrink-0">
379+
<img
380+
src="/partner/notchpay-favicon.svg"
381+
alt="notchpay"
382+
/>
383+
</a>
384+
<div className="w-full flex flex-col items-start font-bold gap-2">
385+
<p>Your payment has been made successfully !</p>
386+
<p>
387+
Fill out this form now without reloading the page !
388+
</p>
389+
</div>
390+
</div>
391+
) : null}
254392
{dataForm?.data?.questions.map((question, index) => {
255393
return (
256394
<div

0 commit comments

Comments
 (0)
Please sign in to comment.