From 719335242fe7e72afe62ce4658d2121fed2124e9 Mon Sep 17 00:00:00 2001 From: Achmad Wahyu Date: Thu, 30 Dec 2021 08:48:07 +0700 Subject: [PATCH 01/26] feat: added confirm remix outlet component --- app/routes/dashboard/purchase/confirm.tsx | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 app/routes/dashboard/purchase/confirm.tsx diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx new file mode 100644 index 0000000..5800a7f --- /dev/null +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -0,0 +1,83 @@ +/* This example requires Tailwind CSS v2.0+ */ +import { Fragment, useState } from 'react' +import { Dialog, Transition } from '@headlessui/react' +import { CheckIcon } from '@heroicons/react/outline' + +export default function Example() { + const [open, setOpen] = useState(true) + + return ( + + +
+ + + + + {/* This element is to trick the browser into centering the modal contents. */} + + +
+
+
+
+
+ + Payment successful + +
+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. + Consequatur amet labore. +

+
+
+
+
+ +
+
+
+
+
+
+ ) +} From bf09fc82ec4b788a7eaa0dfea9e8526910f00076 Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Fri, 31 Dec 2021 17:24:32 +0700 Subject: [PATCH 02/26] refactor: move contents from confirm component to component --- .../purchase/confirm/$transactionId.tsx | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 app/routes/dashboard/purchase/confirm/$transactionId.tsx diff --git a/app/routes/dashboard/purchase/confirm/$transactionId.tsx b/app/routes/dashboard/purchase/confirm/$transactionId.tsx new file mode 100644 index 0000000..2d402fe --- /dev/null +++ b/app/routes/dashboard/purchase/confirm/$transactionId.tsx @@ -0,0 +1,85 @@ +/* This example requires Tailwind CSS v2.0+ */ +import { Fragment, useState } from 'react' +import { Dialog, Transition } from '@headlessui/react' +import { CheckIcon } from '@heroicons/react/outline' + +export default function Example() { + const [open, setOpen] = useState(true) + + return ( + + +
+ + + + + {/* This element is to trick the browser into centering the modal contents. */} + + +
+
+
+
+
+ + Data transaksi tersimpan + +
+

+ Silakan klik tombol di bawah ini untuk mengirimkan pesan + WhatsApp kepada kami. Setelah itu, tolong lampirkan bukti + transfer berupa foto atau file PDF ke nomor WhatsApp + tersebut. Terima kasih. +

+
+
+
+
+ +
+
+
+
+
+
+ ) +} From 16dae95803f3eb4b05ed75216a4948c8325af00b Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Fri, 31 Dec 2021 17:26:40 +0700 Subject: [PATCH 03/26] feat: added remix's outlet component to render component --- app/routes/dashboard/purchase/confirm.tsx | 84 +---------------------- 1 file changed, 3 insertions(+), 81 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index 5800a7f..3478bdd 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -1,83 +1,5 @@ -/* This example requires Tailwind CSS v2.0+ */ -import { Fragment, useState } from 'react' -import { Dialog, Transition } from '@headlessui/react' -import { CheckIcon } from '@heroicons/react/outline' +import { Outlet } from 'remix' -export default function Example() { - const [open, setOpen] = useState(true) - - return ( - - -
- - - - - {/* This element is to trick the browser into centering the modal contents. */} - - -
-
-
-
-
- - Payment successful - -
-

- Lorem ipsum dolor sit amet consectetur adipisicing elit. - Consequatur amet labore. -

-
-
-
-
- -
-
-
-
-
-
- ) +export default function Confirm() { + return } From 043a1ffdd49aac2e03b2f7b93b16a86ad330b521 Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sat, 1 Jan 2022 21:14:53 +0700 Subject: [PATCH 04/26] feat: write transaction information into database upon form submission --- app/routes/dashboard/purchase/confirm.tsx | 83 ++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index 3478bdd..07421d5 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -1,4 +1,85 @@ -import { Outlet } from 'remix' +import { Outlet, redirect } from 'remix' +import type { ActionFunction, LoaderFunction } from 'remix' +import type { Subscription, User } from '@prisma/client' +import { validatePhoneNumber, validateRequired } from '~/utils/validators' +import { auth } from '~/services/auth.server' +import { db } from '~/utils/db.server' + +interface TransactionFields { + userId: string + subscriptionId: string + bankName: string + bankAccountNumber: string + bankAccountName: string + amount: number + status: string +} + +type ActionData = { + formError?: string + fieldErrors?: { + name: string | undefined + phoneNumber: string | undefined + bankName: string | undefined + bankAccountNumber: string | undefined + bankAccountName: string | undefined + amount: number | undefined + paymentTime: string | undefined + } + fields: TransactionFields +} + +export const action: ActionFunction = async ({ request }) => { + const user = await auth.isAuthenticated(request, { + failureRedirect: '/login', + }) + + const form = await request.formData() + const name = form.get('name') + const phoneNumber = form.get('phoneNumber') + const bankName = form.get('bankName') + const bankAccountNumber = form.get('bankAccountNumber') + const bankAccountName = form.get('bankAccountName') + const amount = form.get('amount') + const paymentTime = form.get('paymentTime') + + if ( + typeof name !== 'string' || + typeof phoneNumber !== 'string' || + typeof bankName !== 'string' || + typeof bankAccountNumber !== 'string' || + typeof bankAccountName !== 'string' || + typeof amount !== 'number' || + typeof paymentTime !== 'string' + ) { + return { formError: 'Form not submitted correctly.' } + } + + const fieldErrors = { + name: validateRequired('Nama Lengkap', name), + phoneNumber: validatePhoneNumber('Nomor WhatsApp', phoneNumber), + bankName: validateRequired('Nomor WhatsApp', bankName), + bankAccountNumber: validateRequired('Nama Bank', bankAccountNumber), + bankAccountName: validateRequired('Nomor Rekening', bankAccountName), + amount: validateRequired('Nominal', amount), + paymentTime: validateRequired('Nominal', paymentTime), + } + + const fields: TransactionFields = { + userId: user.id, + subscriptionId: '123', //should create assign subcription first? + bankName, + bankAccountName, + bankAccountNumber, + amount, + status: 'SUBMITTED', + } + if (Object.values(fieldErrors).some(Boolean)) { + return { fieldErrors, fields } + } + + const transaction = await db.transaction.create({ data: fields }) +} export default function Confirm() { return From 283a8f68bea32f0dc2cfd85a849bcbd567fafa7d Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sat, 8 Jan 2022 01:23:57 +0700 Subject: [PATCH 05/26] feat: compose whatsapp message --- .../purchase/confirm/$transactionId.tsx | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm/$transactionId.tsx b/app/routes/dashboard/purchase/confirm/$transactionId.tsx index 2d402fe..5a2b349 100644 --- a/app/routes/dashboard/purchase/confirm/$transactionId.tsx +++ b/app/routes/dashboard/purchase/confirm/$transactionId.tsx @@ -1,11 +1,56 @@ /* This example requires Tailwind CSS v2.0+ */ import { Fragment, useState } from 'react' +import { useLoaderData, redirect } from 'remix' +import type { LoaderFunction } from 'remix' import { Dialog, Transition } from '@headlessui/react' import { CheckIcon } from '@heroicons/react/outline' +import { getTransactionDetails } from '~/models/transaction' +import { getUser } from '~/models/user' + +type LoaderData = { + transactionId: string + authorPhoneNumber: string +} + +export const loader: LoaderFunction = async ({ params }) => { + const { transactionId } = params + + if (!transactionId) { + return redirect('/dashboard/transactions') + } + + const transaction = await getTransactionDetails(transactionId) + + if (!transaction) { + throw new Response('Transaction not found', { + status: 404, + }) + } + + const author = await getUser(transaction.authorId) + + if (!author) { + throw new Response('Author not found', { + status: 404, + }) + } + + const data = { + transactionId: transaction.id, + authorPhoneNumber: author.phoneNumber, + } + + return data +} export default function Example() { + const { transactionId, authorPhoneNumber } = useLoaderData() const [open, setOpen] = useState(true) + const formattedPhoneNumber = authorPhoneNumber.replace('08', '628') + + const whatsappLink = `https://api.whatsapp.com/send?phone=${formattedPhoneNumber}&text=%5BKelas%20Tahun%20Prasekolahku%5D%0A%0AKlik%20di%20sini%20untuk%20verifikasi%20pembayaran%0Ahttps%3A%2F%2Frbagi.id%2Fverify%2F${transactionId}%0A%0ABerikut%20terlampir%20foto%2Ffile%20bukti%20pembayaran%20saya%3A` + return ( setOpen(false)} > - Kirim Pesan WhatsApp + Kirim Pesan WhatsApp From ef048ae11c7a6e6c28d48619d10572486b805f50 Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sat, 8 Jan 2022 12:14:03 +0700 Subject: [PATCH 06/26] fix: update transaction fields --- app/routes/dashboard/purchase/confirm.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index 07421d5..9280610 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -7,7 +7,8 @@ import { db } from '~/utils/db.server' interface TransactionFields { userId: string - subscriptionId: string + courseId: string + authorId: string bankName: string bankAccountNumber: string bankAccountName: string @@ -67,7 +68,8 @@ export const action: ActionFunction = async ({ request }) => { const fields: TransactionFields = { userId: user.id, - subscriptionId: '123', //should create assign subcription first? + courseId: '123', + authorId: '123', bankName, bankAccountName, bankAccountNumber, @@ -79,6 +81,14 @@ export const action: ActionFunction = async ({ request }) => { } const transaction = await db.transaction.create({ data: fields }) + + if (!transaction) { + throw new Response('Error while creating new transaction', { + status: 500, + }) + } + + return redirect(`/dashboard/transactions/${transaction.id}`) } export default function Confirm() { From e15b3c70853b782b10329303d9382c923ac6932c Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sun, 9 Jan 2022 00:19:14 +0700 Subject: [PATCH 07/26] feat: added getFirstCourse --- app/models/course.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 app/models/course.ts diff --git a/app/models/course.ts b/app/models/course.ts new file mode 100644 index 0000000..46662f4 --- /dev/null +++ b/app/models/course.ts @@ -0,0 +1,5 @@ +import { db } from '~/utils/db.server' + +export async function getFirstCourse() { + return await db.course.findFirst() +} From 0c3d6ee437ef9902d5c74343184dda4edfd7721a Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sun, 9 Jan 2022 00:21:24 +0700 Subject: [PATCH 08/26] fix: remove formattedPhoneNumber for authorPhoneNumber --- app/routes/dashboard/purchase/confirm/$transactionId.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm/$transactionId.tsx b/app/routes/dashboard/purchase/confirm/$transactionId.tsx index 5a2b349..f780189 100644 --- a/app/routes/dashboard/purchase/confirm/$transactionId.tsx +++ b/app/routes/dashboard/purchase/confirm/$transactionId.tsx @@ -47,9 +47,7 @@ export default function Example() { const { transactionId, authorPhoneNumber } = useLoaderData() const [open, setOpen] = useState(true) - const formattedPhoneNumber = authorPhoneNumber.replace('08', '628') - - const whatsappLink = `https://api.whatsapp.com/send?phone=${formattedPhoneNumber}&text=%5BKelas%20Tahun%20Prasekolahku%5D%0A%0AKlik%20di%20sini%20untuk%20verifikasi%20pembayaran%0Ahttps%3A%2F%2Frbagi.id%2Fverify%2F${transactionId}%0A%0ABerikut%20terlampir%20foto%2Ffile%20bukti%20pembayaran%20saya%3A` + const whatsappLink = `https://api.whatsapp.com/send?phone=${authorPhoneNumber}&text=%5BKelas%20Tahun%20Prasekolahku%5D%0A%0AKlik%20di%20sini%20untuk%20verifikasi%20pembayaran%0Ahttps%3A%2F%2Frbagi.id%2Fverify%2F${transactionId}%0A%0ABerikut%20terlampir%20foto%2Ffile%20bukti%20pembayaran%20saya%3A` return ( From 46847b57d74ddd8130960c5bedc5cf5bd13af1c2 Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sun, 9 Jan 2022 00:27:39 +0700 Subject: [PATCH 09/26] feat: added getFirstCourse and debugging action onSubmit --- app/routes/dashboard/purchase/confirm.tsx | 79 +++++++++++++++++++++-- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index 9280610..a6e5646 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -1,9 +1,10 @@ -import { Outlet, redirect } from 'remix' +import { Form, Outlet, redirect } from 'remix' import type { ActionFunction, LoaderFunction } from 'remix' import type { Subscription, User } from '@prisma/client' import { validatePhoneNumber, validateRequired } from '~/utils/validators' import { auth } from '~/services/auth.server' import { db } from '~/utils/db.server' +import { getFirstCourse } from '~/models/course' interface TransactionFields { userId: string @@ -31,10 +32,21 @@ type ActionData = { } export const action: ActionFunction = async ({ request }) => { + console.log('action called') const user = await auth.isAuthenticated(request, { failureRedirect: '/login', }) + console.log('user: ', user) + const course = await getFirstCourse() + console.log('course: ', course) + + if (!course) { + throw new Response('Course not found', { + status: 404, + }) + } + const form = await request.formData() const name = form.get('name') const phoneNumber = form.get('phoneNumber') @@ -43,7 +55,8 @@ export const action: ActionFunction = async ({ request }) => { const bankAccountName = form.get('bankAccountName') const amount = form.get('amount') const paymentTime = form.get('paymentTime') - + const parsedAmount: number = amount ? parseInt(amount, 10) : 0 + console.log('parsedAmount types: ', typeof parsedAmount) if ( typeof name !== 'string' || typeof phoneNumber !== 'string' || @@ -63,13 +76,13 @@ export const action: ActionFunction = async ({ request }) => { bankAccountNumber: validateRequired('Nama Bank', bankAccountNumber), bankAccountName: validateRequired('Nomor Rekening', bankAccountName), amount: validateRequired('Nominal', amount), - paymentTime: validateRequired('Nominal', paymentTime), + paymentTime: validateRequired('Tanggal dan Waktu Pembayaran', paymentTime), } const fields: TransactionFields = { userId: user.id, - courseId: '123', - authorId: '123', + courseId: course.id, + authorId: course.authorId, bankName, bankAccountName, bankAccountNumber, @@ -79,8 +92,10 @@ export const action: ActionFunction = async ({ request }) => { if (Object.values(fieldErrors).some(Boolean)) { return { fieldErrors, fields } } + console.log('fields: ', fields) const transaction = await db.transaction.create({ data: fields }) + console.log('transaction: ', transaction) if (!transaction) { throw new Response('Error while creating new transaction', { @@ -88,9 +103,59 @@ export const action: ActionFunction = async ({ request }) => { }) } - return redirect(`/dashboard/transactions/${transaction.id}`) + return redirect(`/dashboard/purchase/confirm/${transaction.id}`) } export default function Confirm() { - return + return ( + <> + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + ) } From 4da8947a4116911726390d3209f10c768b32af0b Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sun, 9 Jan 2022 12:28:09 +0700 Subject: [PATCH 10/26] fix: added asertion to amount and paymentTime --- app/routes/dashboard/purchase/confirm.tsx | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index a6e5646..ec17879 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -14,6 +14,7 @@ interface TransactionFields { bankAccountNumber: string bankAccountName: string amount: number + datetime: Date status: string } @@ -32,14 +33,11 @@ type ActionData = { } export const action: ActionFunction = async ({ request }) => { - console.log('action called') const user = await auth.isAuthenticated(request, { failureRedirect: '/login', }) - console.log('user: ', user) const course = await getFirstCourse() - console.log('course: ', course) if (!course) { throw new Response('Course not found', { @@ -53,17 +51,19 @@ export const action: ActionFunction = async ({ request }) => { const bankName = form.get('bankName') const bankAccountNumber = form.get('bankAccountNumber') const bankAccountName = form.get('bankAccountName') - const amount = form.get('amount') - const paymentTime = form.get('paymentTime') - const parsedAmount: number = amount ? parseInt(amount, 10) : 0 - console.log('parsedAmount types: ', typeof parsedAmount) + const amount: string = form.get('amount') as string + const paymentTime: string = form.get('paymentTime') as string + + const parsedAmount: number = parseInt(amount, 10) as number + const formattedPaymentTime: Date = new Date(paymentTime) + if ( typeof name !== 'string' || typeof phoneNumber !== 'string' || typeof bankName !== 'string' || typeof bankAccountNumber !== 'string' || typeof bankAccountName !== 'string' || - typeof amount !== 'number' || + typeof amount !== 'string' || typeof paymentTime !== 'string' ) { return { formError: 'Form not submitted correctly.' } @@ -86,16 +86,15 @@ export const action: ActionFunction = async ({ request }) => { bankName, bankAccountName, bankAccountNumber, - amount, + amount: parsedAmount, + datetime: formattedPaymentTime, status: 'SUBMITTED', } if (Object.values(fieldErrors).some(Boolean)) { return { fieldErrors, fields } } - console.log('fields: ', fields) const transaction = await db.transaction.create({ data: fields }) - console.log('transaction: ', transaction) if (!transaction) { throw new Response('Error while creating new transaction', { From d75f808b6eb0c49656de16ae84d758bc76335f45 Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sun, 9 Jan 2022 12:32:02 +0700 Subject: [PATCH 11/26] feat: set not found error case redirect to dashboard --- app/routes/dashboard/purchase/confirm.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index ec17879..1d6fa03 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -40,9 +40,7 @@ export const action: ActionFunction = async ({ request }) => { const course = await getFirstCourse() if (!course) { - throw new Response('Course not found', { - status: 404, - }) + return redirect('/dashboard') } const form = await request.formData() @@ -97,9 +95,7 @@ export const action: ActionFunction = async ({ request }) => { const transaction = await db.transaction.create({ data: fields }) if (!transaction) { - throw new Response('Error while creating new transaction', { - status: 500, - }) + return redirect('/dashboard') } return redirect(`/dashboard/purchase/confirm/${transaction.id}`) From 19084c484f8e4e96a20a5474ee1fbc61d24b2fa8 Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sun, 9 Jan 2022 12:45:28 +0700 Subject: [PATCH 12/26] refactor: remove unused type definition and change page name --- app/routes/dashboard/purchase/confirm.tsx | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index 1d6fa03..8f4cc02 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -18,20 +18,6 @@ interface TransactionFields { status: string } -type ActionData = { - formError?: string - fieldErrors?: { - name: string | undefined - phoneNumber: string | undefined - bankName: string | undefined - bankAccountNumber: string | undefined - bankAccountName: string | undefined - amount: number | undefined - paymentTime: string | undefined - } - fields: TransactionFields -} - export const action: ActionFunction = async ({ request }) => { const user = await auth.isAuthenticated(request, { failureRedirect: '/login', @@ -101,7 +87,7 @@ export const action: ActionFunction = async ({ request }) => { return redirect(`/dashboard/purchase/confirm/${transaction.id}`) } -export default function Confirm() { +export default function PurchaseConfirm() { return ( <> From 818f41cd5b07a3896248fa5256bff861ebc995f3 Mon Sep 17 00:00:00 2001 From: AchmadWahyu Date: Sun, 9 Jan 2022 12:47:02 +0700 Subject: [PATCH 13/26] style: remove unused imports --- app/routes/dashboard/purchase/confirm.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index 8f4cc02..0a4005a 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -1,6 +1,5 @@ import { Form, Outlet, redirect } from 'remix' -import type { ActionFunction, LoaderFunction } from 'remix' -import type { Subscription, User } from '@prisma/client' +import type { ActionFunction } from 'remix' import { validatePhoneNumber, validateRequired } from '~/utils/validators' import { auth } from '~/services/auth.server' import { db } from '~/utils/db.server' From eaa9da2407a7ebb02385d27e0097593df2eefcdd Mon Sep 17 00:00:00 2001 From: Zain Fathoni Date: Sun, 9 Jan 2022 15:15:14 +0800 Subject: [PATCH 14/26] test: decrease code coverage threshold --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index e29bd47..39f7e4b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -8,7 +8,7 @@ module.exports = { coverageThreshold: { global: { statements: 5, - branches: 5, + branches: 4, functions: 2, lines: 5, }, From 7d1e0e2cdfc207829bba11b645d8426385f2757e Mon Sep 17 00:00:00 2001 From: Zain Fathoni Date: Mon, 10 Jan 2022 09:20:04 +0800 Subject: [PATCH 15/26] test: remove routes from code coverage collection for now until Remix officially provides routes testing infrastructure --- jest.config.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jest.config.js b/jest.config.js index 39f7e4b..ae93338 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,16 +1,16 @@ module.exports = { ...require('./test/jest-common'), collectCoverageFrom: [ - './app/(components|models|routes|services|utils)/**/*.(ts|tsx|js|jsx)', - '!./app/(components|models|routes|services|utils)/**/__tests__/**/*.test.(ts|tsx|js|jsx)', - '!./app/(components|models|routes|services|utils)/**/__mocks__/**/*.(ts|tsx|js|jsx)', + './app/(components|models|services|utils)/**/*.(ts|tsx|js|jsx)', + '!./app/(components|models|services|utils)/**/__tests__/**/*.test.(ts|tsx|js|jsx)', + '!./app/(components|models|services|utils)/**/__mocks__/**/*.(ts|tsx|js|jsx)', ], coverageThreshold: { global: { - statements: 5, - branches: 4, - functions: 2, - lines: 5, + statements: 13, + branches: 10, + functions: 4, + lines: 13, }, }, transform: { From bb894a71b00c4d728fa54f35b29b2d63f2bd8bc4 Mon Sep 17 00:00:00 2001 From: Zain Fathoni Date: Fri, 25 Feb 2022 20:21:34 +0800 Subject: [PATCH 16/26] feat: add a CTA button in the Purchase index page --- app/routes/dashboard/purchase/index.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/routes/dashboard/purchase/index.tsx b/app/routes/dashboard/purchase/index.tsx index 24480dc..83839e8 100644 --- a/app/routes/dashboard/purchase/index.tsx +++ b/app/routes/dashboard/purchase/index.tsx @@ -1,3 +1,6 @@ +import { Link } from 'remix' +import { STEPS } from '~/utils/constants' + export default function Payment() { return (
@@ -40,11 +43,19 @@ export default function Payment() {
Setelah melakukan transfer, simpan bukti transfer dalam bentuk file gambar atau PDF, lalu klik tombol{' '} - Konfirmasi Pembayaran di bawah ini. + Saya sudah transfer di bawah ini.
+
+ + Saya sudah transfer + +
) } From 64a377ad7b1e7e636d5de3d6a66b6b6d35f160eb Mon Sep 17 00:00:00 2001 From: Zain Fathoni Date: Sat, 26 Feb 2022 09:03:04 +0800 Subject: [PATCH 17/26] fix: strip leading plus from the phone number to comply with WhatsApp --- .../dashboard/purchase/confirm/$transactionId.tsx | 12 ++++++++++-- app/utils/misc.ts | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/routes/dashboard/purchase/confirm/$transactionId.tsx b/app/routes/dashboard/purchase/confirm/$transactionId.tsx index f780189..2d001a7 100644 --- a/app/routes/dashboard/purchase/confirm/$transactionId.tsx +++ b/app/routes/dashboard/purchase/confirm/$transactionId.tsx @@ -6,6 +6,7 @@ import { Dialog, Transition } from '@headlessui/react' import { CheckIcon } from '@heroicons/react/outline' import { getTransactionDetails } from '~/models/transaction' import { getUser } from '~/models/user' +import { stripLeadingPlus } from '~/utils/misc' type LoaderData = { transactionId: string @@ -46,8 +47,9 @@ export const loader: LoaderFunction = async ({ params }) => { export default function Example() { const { transactionId, authorPhoneNumber } = useLoaderData() const [open, setOpen] = useState(true) + const normalizedAuthorPhoneNumber = stripLeadingPlus(authorPhoneNumber) - const whatsappLink = `https://api.whatsapp.com/send?phone=${authorPhoneNumber}&text=%5BKelas%20Tahun%20Prasekolahku%5D%0A%0AKlik%20di%20sini%20untuk%20verifikasi%20pembayaran%0Ahttps%3A%2F%2Frbagi.id%2Fverify%2F${transactionId}%0A%0ABerikut%20terlampir%20foto%2Ffile%20bukti%20pembayaran%20saya%3A` + const whatsappLink = `https://api.whatsapp.com/send?phone=${normalizedAuthorPhoneNumber}&text=%5BKelas%20Tahun%20Prasekolahku%5D%0A%0AKlik%20di%20sini%20untuk%20verifikasi%20pembayaran%0Ahttps%3A%2F%2Frbagi.id%2Fverify%2F${transactionId}%0A%0ABerikut%20terlampir%20foto%2Ffile%20bukti%20pembayaran%20saya%3A` return ( @@ -115,7 +117,13 @@ export default function Example() { type="button" className="inline-flex justify-center w-full rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:text-sm" > - Kirim Pesan WhatsApp + + Kirim Pesan WhatsApp + diff --git a/app/utils/misc.ts b/app/utils/misc.ts index 1726727..1a01039 100644 --- a/app/utils/misc.ts +++ b/app/utils/misc.ts @@ -18,3 +18,7 @@ function getRequiredEnvVarFromObj( export function getRequiredServerEnvVar(key: string, devValue?: string) { return getRequiredEnvVarFromObj(process.env, key, devValue) } + +export function stripLeadingPlus(str: string) { + return str.replace(/^\+/, '') +} From c51b1cc86b793031cfec0380f2eb024901c6d9d1 Mon Sep 17 00:00:00 2001 From: Zain Fathoni Date: Sat, 26 Feb 2022 11:00:55 +0800 Subject: [PATCH 18/26] feat: move the confirmation dialog into the /verify pathname --- app/routes/dashboard/purchase.tsx | 2 +- app/routes/dashboard/purchase/confirm.tsx | 5 ++--- .../purchase/{pending-verification.tsx => verify.tsx} | 6 +++++- .../purchase/{confirm => verify}/$transactionId.tsx | 2 +- app/utils/constants.ts | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) rename app/routes/dashboard/purchase/{pending-verification.tsx => verify.tsx} (58%) rename app/routes/dashboard/purchase/{confirm => verify}/$transactionId.tsx (99%) diff --git a/app/routes/dashboard/purchase.tsx b/app/routes/dashboard/purchase.tsx index 44c5b12..b0df4a8 100644 --- a/app/routes/dashboard/purchase.tsx +++ b/app/routes/dashboard/purchase.tsx @@ -20,7 +20,7 @@ export const loader: LoaderFunction = async ({ request }) => { } export default function Purchase() { - const { pathname } = useMatches()?.at(-1) ?? {} + const { pathname } = useMatches()?.at(3) ?? {} const currentStepIdx = STEPS.findIndex((step) => step.pathname === pathname) return ( diff --git a/app/routes/dashboard/purchase/confirm.tsx b/app/routes/dashboard/purchase/confirm.tsx index 0a4005a..797663d 100644 --- a/app/routes/dashboard/purchase/confirm.tsx +++ b/app/routes/dashboard/purchase/confirm.tsx @@ -1,4 +1,4 @@ -import { Form, Outlet, redirect } from 'remix' +import { Form, redirect } from 'remix' import type { ActionFunction } from 'remix' import { validatePhoneNumber, validateRequired } from '~/utils/validators' import { auth } from '~/services/auth.server' @@ -83,13 +83,12 @@ export const action: ActionFunction = async ({ request }) => { return redirect('/dashboard') } - return redirect(`/dashboard/purchase/confirm/${transaction.id}`) + return redirect(`/dashboard/purchase/verify/${transaction.id}`) } export default function PurchaseConfirm() { return ( <> -