NextJS Templates
Tutorial Aplikasi Penagihan dengan Next.js, Vercel & Back4app
26 mnt
dalam tutorial ini, kita akan membangun sebuah aplikasi penagihan menggunakan next js sebagai frontend, back4app sebagai backend, dan layanan tambahan seperti clerk untuk otentikasi, stripe untuk pembayaran, dan resend untuk notifikasi email panduan ini akan menjelaskan cara mengatur otentikasi, manajemen faktur, pemrosesan pembayaran, dan penyebaran di vercel 1\ prasyarat sebelum memulai, pastikan anda memiliki hal hal berikut akun back4app ( daftar di sini https //www back4app com/ ) akun clerk ( clerk io https //clerk dev/ ) untuk otentikasi akun stripe ( stripe com https //stripe com/ ) untuk pemrosesan pembayaran akun resend ( resend io https //resend io/ ) untuk notifikasi email node js dan npm terinstal ( instalasi node js https //nodejs org/ ) 2\ mengatur backend (back4app) 2 1 buat proyek baru di back4app masuk ke back4app dan buat proyek baru navigasikan ke data browser dan buat kelas kelas berikut 2 2 model data (kelas) 2 2 1 pengguna (ditangani secara otomatis oleh clerk) objectid username email 2 2 2 organisasi buat kelas bernama organisasi tambahkan kolom berikut nama (string) nama organisasi ownerid (pointer< user>) mengarah ke kelas user (dibuat secara otomatis oleh clerk) anggota (array\<pointer< user>>) sebuah array pengguna yang menjadi bagian dari organisasi ini 2 2 3 pelanggan buat kelas bernama pelanggan tambahkan kolom kolom ini nama (string) nama pelanggan email (string) email pelanggan organizationid (pointer) organisasi tempat pelanggan ini berada 2 2 4 faktur buat kelas bernama faktur tambahkan kolom kolom ini nomorfaktur (string) pengidentifikasi faktur yang unik idpelanggan (pointer) menghubungkan ke pelanggan idorganisasi (pointer) menghubungkan ke organisasi jumlah (number) total jumlah untuk faktur status (string) opsi termasuk 'draft', 'sent', 'paid', dan 'overdue' tanggaljatuhtempo (date) tanggal jatuh tempo faktur item (array) daftar item dalam faktur 2 2 5 pembayaran buat kelas bernama pembayaran tambahkan kolom kolom ini idfaktur (pointer) menghubungkan ke faktur terkait jumlah (number) jumlah pembayaran idsesistripe (string) id sesi stripe status (string) status pembayaran (misalnya, 'pending', 'successful', 'failed') 3\ menyiapkan frontend (next js) 3 1 buat proyek next js mulailah dengan menyiapkan proyek next js anda dengan typescript, tailwind css, dan komponen shadcn/ui npx create next app\@latest invoicing app typescript cd invoicing app npm install tailwindcss postcss autoprefixer npx tailwindcss init 3 2 siapkan tailwind css konfigurasikan tailwind dengan memperbarui tailwind config js dan menambahkan gaya ke globals css di tailwind config js module exports = { content \[ ' /pages/ / {js,ts,jsx,tsx}', ' /components/ / {js,ts,jsx,tsx}', ], theme { extend {}, }, plugins \[], }; di styles/globals css @tailwind base; @tailwind components; @tailwind utilities; 3 3 instal parse sdk dan layanan tambahan instal dependensi yang diperlukan untuk parse, clerk, stripe, dan resend npm install parse @clerk/clerk next stripe resend 3 4 inisialisasi parse sdk di next js di pages/ app tsx , inisialisasi parse sdk dengan kredensial back4app anda import { clerkprovider } from '@clerk/clerk react'; import parse from 'parse'; parse initialize('your app id', 'your javascript key'); parse serverurl = 'https //parseapi back4app com'; function myapp({ component, pageprops }) { return ( \<clerkprovider> \<component { pageprops} /> \</clerkprovider> ); } export default myapp; ganti 'your app id' dan 'your javascript key' dengan kredensial back4app anda 4\ mengimplementasikan autentikasi pengguna 4 1 integrasi clerk untuk autentikasi siapkan clerk untuk autentikasi pergi ke dasbor clerk, buat aplikasi, dan ambil kunci api anda perbarui env local file anda dengan kunci clerk next public clerk frontend api=your clerk frontend api clerk api key=your clerk api key sekarang buat pages/sign in tsx dan pages/sign up tsx untuk fungsionalitas masuk dan daftar menggunakan komponen clerk di pages/sign in tsx import { signin } from '@clerk/clerk react'; export default function signinpage() { return \<signin />; } di pages/sign up tsx import { signup } from '@clerk/clerk react'; export default function signuppage() { return \<signup />; } 5\ manajemen organisasi dan pelanggan 5 1 buat organisasi pengguna dapat membuat organisasi yang mereka miliki buat halaman pages/organizations/new\ tsx untuk membuat organisasi baru import { usestate } from 'react'; import parse from 'parse'; export default function neworganization() { const \[name, setname] = usestate(''); const handlecreateorganization = async () => { const organization = parse object extend('organization'); const organization = new organization(); organization set('name', name); organization set('ownerid', parse user current()); try { await organization save(); alert('organization created successfully!'); } catch (error) { console error('error creating organization ', error); } }; return ( \<div> \<h1>create new organization\</h1> \<input type="text" value={name} onchange={(e) => setname(e target value)} placeholder="organization name" /> \<button onclick={handlecreateorganization}>create\</button> \</div> ); } 5 2 mengelola pelanggan buat halaman manajemen pelanggan pages/customers/new\ tsx untuk menambahkan pelanggan baru import { usestate } from 'react'; import parse from 'parse'; export default function newcustomer() { const \[name, setname] = usestate(''); const \[email, setemail] = usestate(''); const handlecreatecustomer = async () => { const customer = parse object extend('customer'); const customer = new customer(); customer set('name', name); customer set('email', email); customer set('organizationid', parse user current() get('organizationid')); try { await customer save(); alert('customer created successfully!'); } catch (error) { console error('error creating customer ', error); } }; return ( \<div> \<h1>create new customer\</h1> \<input type="text" value={name} onchange={(e) => setname(e target value)} placeholder="customer name" /> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="customer email" /> \<button onclick={handlecreatecustomer}>create\</button> \</div> ); } 6\ manajemen faktur 6 1 buat faktur buat halaman pembuatan faktur pages/invoices/new\ tsx untuk menghasilkan faktur baru import { usestate } from 'react'; import parse from 'parse'; export default function newinvoice() { const \[invoicenumber, setinvoicenumber] = usestate(''); const \[amount, setamount] = usestate(0); const handlecreateinvoice = async () => { const invoice = parse object extend('invoice'); const invoice = new invoice(); invoice set('invoicenumber', invoicenumber); invoice set('amount', amount); invoice set('organizationid', parse user current() get('organizationid')); try { await invoice save(); alert('invoice created successfully!'); } catch (error) { console error('error creating invoice ', error); } }; return ( \<div> \<h1>create new invoice\</h1> \<input type="text" value={invoicenumber} onchange={(e) => setinvoicenumber(e target value)} placeholder="invoice number" /> \<input type="number" value={amount} onchange={(e) => setamount(parsefloat(e target value))} placeholder="amount" /> \<button onclick={handlecreateinvoice}>create\</button> \</div> ); } 6 2 melihat faktur buat halaman pages/invoices/index tsx untuk melihat semua faktur dengan opsi pengurutan dan penyaringan import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function invoiceslist() { const \[invoices, setinvoices] = usestate(\[]); useeffect(() => { const fetchinvoices = async () => { const invoice = parse object extend('invoice'); const query = new parse query(invoice); const results = await query find(); setinvoices(results); }; fetchinvoices(); }, \[]); return ( \<div> \<h1>invoices\</h1> {invoices map(invoice => ( \<div key={invoice id}> \<h2>invoice #{invoice get('invoicenumber')}\</h2> \<p>amount ${invoice get('amount')}\</p> \<p>status {invoice get('status')}\</p> \</div> ))} \</div> ); } 7\ pemrosesan pembayaran (integrasi stripe) 7 1 siapkan stripe checkout untuk memproses pembayaran, integrasikan stripe di pages/invoices/\[id] tsx , implementasikan pembuatan tautan pembayaran menggunakan stripe checkout import { userouter } from 'next/router'; import { useeffect, usestate } from 'react'; import stripe from 'stripe'; export default function invoicedetail() { const router = userouter(); const { id } = router query; const \[invoice, setinvoice] = usestate(null); useeffect(() => { if (!id) return; const fetchinvoice = async () => { const invoice = parse object extend('invoice'); const query = new parse query(invoice); query equalto('objectid', id); const result = await query first(); setinvoice(result); }; fetchinvoice(); }, \[id]); const handlepayinvoice = async () => { const stripe = new stripe(process env stripe secret key); const session = await stripe checkout sessions create({ payment method types \['card'], line items \[ { price data { currency 'usd', product data { name `invoice #${invoice get('invoicenumber')}` }, unit amount invoice get('amount') 100, }, quantity 1, }, ], mode 'payment', success url window\ location origin + '/success', cancel url window\ location origin + '/cancel', }); window\ location href = session url; }; if (!invoice) return \<div>loading \</div>; return ( \<div> \<h1>invoice #{invoice get('invoicenumber')}\</h1> \<p>amount ${invoice get('amount')}\</p> \<button onclick={handlepayinvoice}>pay now\</button> \</div> ); } 8\ notifikasi email (integrasi kirim ulang) 8 1 mengirim email faktur atur resend untuk mengirim email faktur kepada klien import { resend } from 'resend'; export default async function sendinvoiceemail(invoiceid) { const resend = new resend(process env resend api key); const invoice = await fetchinvoicedetails(invoiceid); // function to fetch invoice details const customer = await fetchcustomerdetails(invoice customerid); await resend sendemail({ from 'no reply\@invoicingapp com', to customer email, subject `invoice #${invoice invoicenumber}`, html `\<h1>invoice #${invoice invoicenumber}\</h1>\<p>amount ${invoice amount}\</p>`, }); } 9\ penyebaran di vercel untuk menyebarkan aplikasi di vercel, instal vercel cli dan lakukan penyebaran npm install g vercel vercel konfigurasikan variabel lingkungan untuk clerk, stripe, resend, dan back4app di dasbor vercel sebelum penyebaran 10\ kesimpulan dalam tutorial ini, kami membangun sebuah aplikasi faktur yang lengkap dengan next js, terintegrasi dengan back4app untuk backend, clerk untuk otentikasi, stripe untuk pembayaran, dan resend untuk notifikasi email kami membahas manajemen pengguna dan organisasi, pembuatan faktur, pemrosesan pembayaran, dan penyebaran