Quickstarters
How to Build an E-Commerce Backend?
85 mnt
dalam tutorial praktis ini, anda akan membuat aplikasi e commerce full stack yang kokoh dari awal menggunakan backend as a service sepanjang jalan, anda akan menguasai autentikasi pengguna yang aman, memastikan hanya pembeli dan admin yang berwenang yang dapat mengakses model data yang intuitif, dirancang untuk mendukung katalog produk, profil pelanggan, dan riwayat pesanan api restful dan real time, sehingga frontend anda selalu tetap sinkron dengan inventaris, keranjang, dan status checkout pipa penyebaran otomatis, memungkinkan anda untuk mendorong pembaruan dengan percaya diri dan mengembalikan jika ada yang tidak beres pada akhirnya, anda tidak hanya akan memiliki toko online yang siap produksi tetapi juga pengetahuan arsitektur untuk memperluas, menskalakan, dan mengamankan aplikasi web apa pun jelajahi aplikasi e commerce yang sudah jadi dalam aksi di aplikasi e commerce web mari kita mulai! poin penting pengaturan backend cepat luncurkan dan konfigurasikan model data e commerce lengkap dalam hitungan menit dengan platform low code back4app alur pengguna yang aman terapkan pendaftaran, login, dan logout yang kuat menggunakan cloud code dan token sesi pengembangan berbasis api akses data anda melalui endpoint rest/graphql yang dihasilkan secara otomatis dan parse sdk untuk klien mana pun logika bisnis dalam cloud code sentralisasi operasi inti—crud produk, manajemen keranjang, dan checkout—sambil menegakkan izin penerapan frontend tercontainerisasi kemasi dan terapkan toko next js anda di penerapan web back4app untuk hosting yang konsisten dan dapat diskalakan prasyarat dan pengaturan lingkungan untuk mengikuti tutorial ini, pastikan anda memiliki hal hal berikut akun back4app anda dapat mendaftar secara gratis di situs web back4app https //www back4app com/signup node js terinstal, memungkinkan anda untuk mengelola ketergantungan dengan npm atau yarn pemahaman tentang javascript untuk menulis kode cloud kustom dan memanfaatkan sdk back4app pemahaman dasar tentang konsep e commerce seperti otentikasi pengguna, manajemen katalog produk, dan pemrosesan pesanan git untuk kontrol versi, sehingga anda dapat melacak perubahan, mengembalikan jika perlu, dan berkolaborasi dengan lancar memastikan anda memiliki item di atas akan membantu anda memaksimalkan kemampuan back4app dan menerapkan fitur e commerce kunci tanpa terjebak membuat dan mengonfigurasi akun back4app anda untuk mulai mengatur backend e commerce anda di back4app, kunjungi back4app https //www back4app com dan klik daftar masukkan alamat email anda, pilih kata sandi yang kuat, dan berikan detail yang diperlukan setelah anda memverifikasi email anda, anda akan mendapatkan akses ke dasbor back4app halaman pendaftaran back4app di dalam dasbor, pilih buat aplikasi baru atau bangun aplikasi baru dan beri nama proyek anda—sesuatu yang deskriptif sehingga anda dapat dengan mudah menemukannya nanti konfirmasi pilihan anda, lalu tunggu proses pembuatan aplikasi selesai dasbor proyek akan menampilkan kelas, analitik, dan konfigurasi membuat aplikasi back4app dengan langkah langkah ini, anda telah membuat platform e commerce di bagian selanjutnya, anda akan merancang skema data anda dan mempersiapkan manajemen produk, penanganan pesanan, dan otentikasi pengguna merancang skema data e commerce anda untuk menerapkan backend yang dapat diskalakan dan dapat dipelihara untuk platform e commerce anda, anda akan mengorganisir data anda di sekitar tujuh tabel inti pengguna , pembeli , penjual , produk , keranjang , pesanan , dan detailpesanan setiap tabel memiliki peran yang terfokus dalam mendukung fungsionalitas keseluruhan sistem, dan bersama sama mereka membentuk skema yang dinormalisasi dan efisien mulailah dengan tabel user yang berfungsi sebagai dasar untuk semua identitas pengguna setiap orang di platform anda—terlepas dari perannya—akan melakukan autentikasi menggunakan tabel ini sertakan bidang seperti username , password , dan email untuk menangani login dasar tambahkan emailverified untuk melacak status verifikasi, dan authdata jika anda berencana untuk mendukung login pihak ketiga atau alur oauth untuk membedakan antara pembeli dan penjual, definisikan bidang usertype bidang ini memungkinkan anda untuk mengontrol akses, mengelola tampilan, dan memisahkan fungsionalitas berdasarkan peran pengguna sambil tetap mempertahankan sistem login yang tunggal dan konsisten alih alih mencampur semua jenis pengguna dalam satu tabel, buat tabel terpisah buyer dan seller yang merujuk user melalui bidang userid ini memungkinkan anda untuk menyimpan data spesifik peran tanpa membebani tabel pengguna inti tabel buyer dapat menyimpan bidang terkait pembelian seperti paymentinfo dan shippingaddress , yang penting untuk proses checkout dan pengiriman sebaliknya, tabel seller melacak atribut yang relevan bagi pedagang, seperti storename , bio , dan phonenumber dengan pemisahan ini, anda dapat dengan mudah mengelola dan menanyakan pembeli dan penjual secara independen, sambil tetap menghubungkan mereka kembali ke identitas bersama mereka di user tabel produk anda adalah tempat di mana barang yang dijual disimpan setiap produk harus mencakup informasi deskriptif dasar seperti nama, deskripsi rinci, dan satu atau lebih gambar untuk manajemen harga dan inventaris, anda juga ingin menyertakan bidang untuk harga, status ketersediaan melalui boolean isactive , dan jumlah stok di bawah quantityavailable yang penting, setiap produk harus terhubung dengan penjual yang mencantumkannya untuk membangun hubungan itu, tambahkan sellerid kunci asing yang merujuk ke tabel seller struktur ini memastikan bahwa setiap item dalam katalog anda terikat pada pedagang yang terverifikasi dan membuat penyaringan spesifik penjual menjadi sederhana untuk menangani perilaku sebelum pembelian, perkenalkan tabel cart setiap keranjang milik seorang pengguna, jadi sertakan bidang userid yang menghubungkan kembali ke user simpan array item keranjang, masing masing mewakili produk yang ingin dibeli pengguna, bersama dengan metadata yang anda butuhkan seperti jumlah atau opsi yang dipilih melacak totalprice keranjang memungkinkan anda untuk dengan cepat menampilkan ringkasan checkout tanpa menghitung ulang nilai pada setiap permintaan pengaturan ini mendukung fungsionalitas keranjang dasar dan menyederhanakan ketahanan sesi jika anda menemukan struktur array terbatas—terutama jika anda perlu mencatat data tingkat item yang lebih kompleks—anda selalu dapat merombak item ke dalam tabel terpisah nanti ketika seorang pembeli melakukan pemesanan, anda akan mencatat transaksi di tabel order setiap pesanan terikat pada buyerid , yang merujuk ke tabel buyer untuk memastikan pembeli valid dan terotorisasi selain tautan ini, simpan orderdate , status orderstatus , dan total nilai moneter di bawah bidang total ini memberi anda ringkasan yang jelas tentang pembelian dan mendukung alur kerja seperti pelacakan dan pemenuhan pesanan karena setiap pesanan dapat berisi beberapa produk, anda akan memerlukan tabel orderdetails untuk mengelola item baris individu tabel ini menghubungkan setiap item kembali ke pesanan induknya melalui orderid , dan ke produk yang dibeli menggunakan productid untuk mencatat dengan akurat keadaan pembelian, sertakan quantity yang dibeli dan unitprice pada saat penjualan memisahkan detail pesanan dengan cara ini memungkinkan anda untuk membuat laporan, menghasilkan faktur, dan menangani pengembalian atau penyesuaian dengan presisi skema ini, dengan pemisahan kepentingan yang bersih dan integritas relasional, membentuk dasar yang kuat untuk sistem e commerce anda dengan model data sekarang selaras dengan alur kerja dunia nyata platform anda, anda siap untuk mulai mengimplementasikannya di backend anda mulailah dengan menyiapkan user , buyer , dan seller tabel, dan bangun dari sana menyiapkan kelas di dashboard ikuti langkah langkah di bawah ini untuk membuat dan menghubungkan entitas anda di back4app anda akan mendefinisikan kelas untuk user , buyer , seller , cart , product , order , dan orderdetails , kemudian menetapkan pointer untuk mewakili hubungan seperti pewarisan, satu ke banyak, dan banyak ke banyak akses database browser buka dashboard aplikasi anda dan buat kelas baru bernama user klik pada database dari menu sebelah kiri back4app dashboard membuat kelas “user” back4app secara otomatis membuat kelas user kelas user dilengkapi dengan kolom kolom berikut username password email dll untuk menambahkan kolom usertype , pilih tambahkan kolom baru add new column berikan nama kolom, jenis data, nilai default, dll add usertype column catatan di parse, setiap kelas mencakup objectid default, yang berfungsi sebagai kunci utama ini berarti objectid akan secara efektif berfungsi sebagai userid dalam model relasional anda membuat kelas “pembeli” untuk membuat kelas pembeli, kembali ke database browser dan pilih add class create new class pilih custom dan beri nama pembeli add buyer class tambahkan kolom pointer yang disebut user , yang menunjuk ke kelas user create userid class ini mensimulasikan “pewarisan” dengan merujuk pada objectid pengguna dasar 3\ tambahkan kolom berikut alamatpengiriman (string) infopembayaran (string) ketika anda membuat objek pembeli baru, anda akan menghubungkannya ke catatan pengguna yang ada dengan mengatur buyer user ke objectid pengguna tersebut membuat kelas “penjual” ulangi proses yang sama untuk membuat kelas penjual tambahkan kolom pointer bernama user yang merujuk ke kelas user tambahkan kolom tambahan ini namatoko (string) bio (string) nomortelepon (number) membuat kelas “produk” pilih buat kelas lagi, beri nama produk tambahkan kolom penunjuk yang disebut penjual yang menunjuk ke kelas penjual (ini menegakkan hubungan satu ke banyak di mana satu penjual dapat memiliki banyak produk) tambahkan kolom berikut nama (string) deskripsi (string) harga (number) jumlahtersedia (number) aktif (boolean) gambar (array) menyimpan objek yang mewakili gambar produk membuat kelas “keranjang” klik buat kelas , beri nama kelas keranjang tambahkan kolom penunjuk yang disebut pengguna yang menunjuk ke kelas pengguna (ini menghubungkan setiap keranjang ke pengguna tertentu) kemudian tambahkan kolom berikut untuk mewakili item dalam keranjang item (array) menyimpan objek yang mewakili setiap item keranjang setiap item dapat berupa objek seperti { produk penunjuk ke produk, jumlah number } totalharga (number) membuat kelas “pesanan” buat kelas baru bernama order tambahkan kolom pointer yang disebut buyer yang menunjuk ke kelas buyer (menunjukkan satu pembeli dapat memiliki banyak pesanan) sertakan kolom kolom ini orderdate (tanggal atau string, tergantung pada preferensi anda) orderstatus (string) membuat kelas “orderdetails” akhirnya, buat kelas bernama orderdetails tambahkan dua kolom pointer order → merujuk ke order product → merujuk ke product kemudian, tambahkan kolom yang tersisa quantity (angka) unitprice (angka) pengaturan ini memungkinkan hubungan banyak ke banyak antara order dan product melalui orderdetails , karena setiap pesanan dapat mencakup beberapa produk, dan setiap produk dapat muncul dalam beberapa pesanan memvisualisasikan hubungan berikut adalah diagram entitas hubungan (erd) yang disederhanakan yang mencerminkan kelas kelas dan pointer mereka dbschema2 setelah kelas kelas ini ada, anda dapat menangani pendaftaran dan login melalui kelas user , membuat catatan pembeli atau penjual khusus untuk berbagai jenis pengguna, dan menyimpan informasi produk atau pesanan dengan referensi kunci asing yang jelas dengan menyusun database anda dengan cara ini, anda mendapatkan desain yang bersih dan dapat dipelihara untuk aplikasi e commerce apa pun dengan skema anda yang sudah ada, anda siap untuk mengatur otentikasi dan otorisasi untuk membatasi siapa yang dapat mencantumkan produk, melakukan pemesanan, atau melakukan tugas administratif langkah selanjutnya akan menunjukkan kepada anda cara mengonfigurasi alur pendaftaran dan login yang aman yang dibangun di atas peran dan kelas yang baru saja anda definisikan mengimplementasikan otentikasi dengan back4app otentikasi yang aman adalah pusat dari setiap platform e commerce, membantu anda melindungi akun pengguna, detail pembayaran, dan data pribadi back4app menyederhanakan ini dengan berbagai metode—dari kombinasi nama pengguna/kata sandi klasik hingga login sosial atau alur berbasis token—memastikan anda dapat menawarkan pengalaman yang sederhana dan aman kepada pembeli anda untuk mengatur otentikasi dalam aplikasi e commerce anda, anda akan memanfaatkan kode cloud kode cloud memperluas kemampuan backend anda dengan memungkinkan anda menulis logika bisnis kustom tanpa harus menghosting server anda sendiri ini berarti anda dapat memvalidasi pesanan, menghitung biaya, atau memicu notifikasi pada peristiwa tertentu—sepenuhnya dalam infrastruktur back4app ini adalah cara yang ideal untuk menangani transaksi sensitif atau proses data yang memerlukan kontrol ketat dan eksekusi cepat untuk mengaktifkan kode cloud di back4app, buka dasbor aplikasi anda dan temukan bagian kode cloud find cloud code ketika anda mengklik kode cloud , anda akan melihat sebuah main js di mana anda dapat mulai mengimplementasikan fungsi kustom cloud code untuk menerapkan alur otentikasi di back4app, anda perlu menerapkan beberapa fungsi di kode cloud anda untuk mendaftar pengguna, masuk pengguna, dan keluar pengguna daftar pengguna baru (pembeli secara default) untuk mendaftar pengguna baru, gunakan metode pendaftaran parse atur bidang standar seperti username , password , dan email , dan sertakan bidang kustom untuk menunjukkan peran baik buyer atau seller secara default, pengguna baru diberikan peran buyer sampai mereka memilih untuk mengubahnya untuk memulai, buat file auth js di direktori cloud kode anda dan tambahkan blok kode di bawah ini parse cloud define('signupuser', async (request) => { const { name, password, confirmpassword, email, shippingaddress, paymentinfo } = request params; // validate password match if (password !== confirmpassword) { throw new error('passwords do not match'); } const user = new parse user(); user set('username', name); user set('password', password); user set('email', email); user set('usertype', "buyer"); try { // sign up the user const signedupuser = await user signup(); console log('user registered ', signedupuser id); // create a buyer record linked to the new user const buyer = parse object extend('buyer'); const buyer = new buyer(); buyer set('user', signedupuser); buyer set('shippingaddress', shippingaddress); buyer set('paymentinfo', paymentinfo); const savedbuyer = await buyer save(); console log('buyer created ', savedbuyer id); return { success true, message 'user registered and buyer created', userid signedupuser id, buyerid savedbuyer id }; } catch (error) { console error('sign up failed ', error); throw new error('sign up failed ' + error message); } }); fungsi cloud ini menangani pendaftaran pengguna untuk pembeli ini memvalidasi input, membuat pengguna parse baru, menetapkan peran ( buyer ), dan menyimpan data spesifik pembeli dalam kelas pembeli terpisah masuk pengguna untuk mengautentikasi pengguna, panggil parse user login metode bawaan parse dan kembalikan token sesi ke klien tambahkan kode berikut ke auth js file anda untuk menerapkan logika ini di backend kode cloud anda parse cloud define("loginuser", async (request) => { const { email, password } = request params; try { const user = await parse user login(email, password); // example block users with disabled flag if (user get("isdisabled")) { throw new parse error(403, "account is disabled"); } return { sessiontoken user getsessiontoken(), userid user id, }; } catch (error) { throw new parse error(101, "invalid credentials"); } }); fungsi ini mengambil email dan kata sandi dari klien, mencoba mengautentikasi pengguna, dan mengembalikan token sesi jika berhasil jika akun ditandai sebagai dinonaktifkan, akses diblokir dan melemparkan kesalahan yang jelas keluar untuk mengimplementasikan fungsi keluar untuk backend anda, tambahkan blok kode di bawah ini ke auth js file parse cloud define('logoutuser', async (request) => { const sessiontoken = request headers\['x parse session token']; if (!sessiontoken) { throw new error('session token required'); } const sessionquery = new parse query(' session'); sessionquery equalto('sessiontoken', sessiontoken); const session = await sessionquery first({ usemasterkey true }); if (session) { await session destroy({ usemasterkey true }); } return { success true, message 'session invalidated' }; }); ini dengan aman mengakhiri sesi di backend, mencegah penggunaan lebih lanjut dari token dengan fungsi cloud code ini, anda sekarang memiliki sistem otentikasi yang aman yang mendaftarkan pengguna dengan logika berbasis peran mengautentikasi dan mengotorisasi akses menggunakan token sesi menghubungkan akun pengguna ke catatan spesifik pembeli mendukung alur login dan logout yang bersih memanfaatkan alat verifikasi sesi dan email bawaan back4app membangun logika bisnis untuk aplikasi ecommerce anda untuk mengelola pengguna, produk, keranjang, dan transaksi di platform e commerce anda, anda akan mendefinisikan serangkaian fungsi cloud code di back4app fungsi fungsi ini memungkinkan anda untuk membuat, membaca, memperbarui, dan menghapus (crud) sumber daya seperti penjual, produk, dan pesanan sambil mempertahankan kontrol akses yang aman yang terkait dengan peran pengguna di bawah ini adalah serangkaian fungsi cloud yang menunjukkan cara bekerja dengan entitas kunci penjual , produk , keranjang , pesanan , dan detailpesanan setiap fungsi menangani operasi backend tertentu dan memastikan bahwa izin ditegakkan melalui validasi pengguna dan pemeriksaan peran penjual buat profil penjual untuk pengguna yang ingin menawarkan produk di platform membuat penjual fungsi ini memperbarui peran pengguna saat ini menjadi penjual dan membuat sebuah penjual dengan informasi toko untuk mengimplementasikan ini dalam kode cloud anda, pertama buat sebuah seller js file dan tambahkan blok kode di bawah ini parse cloud define('createseller', async (request) => { const currentuser = request user; // get the current logged in user if (!currentuser) { throw new error('user is not logged in'); } try { // check and update the user type const usertype = currentuser get('usertype'); if (usertype === 'buyer') { currentuser set('usertype', 'seller'); await currentuser save(); } // create the seller object const { businessname, bio, phone } = request params; const seller = parse object extend('seller'); const seller = new seller(); seller set('user', currentuser); seller set('storename', businessname); seller set('bio', bio); seller set('phonenumber', number(phone)); const newseller = await seller save(); console log('seller created ', newseller id); return { success true, message 'seller account created', sellerid newseller id }; } catch (error) { console error('error creating seller ', error); throw new error('error creating seller ' + error message); } }); ini memastikan bahwa hanya pengguna yang terautentikasi yang dapat menjadi penjual, dan menghubungkan penjual dengan pengguna yang sesuai melalui pointer produk produk terdaftar oleh penjual dan dapat dijelajahi, ditanyakan, dan dibeli oleh pembeli fungsi fungsi ini memungkinkan penjual untuk membuat, mengambil, memperbarui, dan menghapus produk mereka, serta memberikan akses produk kepada pembeli membuat produk fungsi ini menambahkan produk baru untuk penjual yang masuk dan melampirkan hingga tiga gambar produk untuk mengimplementasikannya dalam kode cloud anda, buat sebuah product js file dan tambahkan blok kode di bawah ini parse cloud define("addproduct", async (request) => { // destructure parameters sent from the client const { name, description, price, quantityavailable, isactive, imagefiles } = request params; // optional check if user is logged in (request user is available when an active session exists) const currentuser = request user; if (!currentuser) { throw new error("unauthorized you must be logged in to add a product "); } // ensure the user is indeed a seller by checking their usertype const usertype = currentuser get("usertype"); if (usertype != "seller") { throw new error("this user is not a seller "); } const seller = parse object extend("seller"); const query = new parse query(seller); query equalto("userid", currentuser); // match the pointer field in seller const sellerobj = await query first({ usemasterkey true }); if (!sellerobj) { throw new error("no matching 'seller' object found for this user "); } if(!array isarray(imagefiles) || imagefiles length > 3) { throw new error("a maximum of 3 images are provided"); } // create the new product object const product = parse object extend("product"); const product = new product(); product set("seller", sellerobj); // pointer to the seller product set("name", name); product set("description", description); product set("price", number(price)); product set("quantityavailable", number(quantityavailable)); product set("isactive", isactive); product set("images", imagefiles); // save the product to the database try { const savedproduct = await product save(null, { usemasterkey true }); return savedproduct; } catch (error) { throw new error(`could not create product ${error message}`); } }); fungsi ini memeriksa bahwa pengguna telah masuk dan memiliki peran penjual, bahwa objek seller yang sesuai ada, dan bahwa tidak lebih dari tiga gambar yang diajukan setelah divalidasi, ia menyimpan produk dan menghubungkannya dengan penjual mengambil semua produk fungsi ini mengambil semua produk dalam sistem, yang dapat digunakan untuk membangun etalase publik untuk menerapkan ini dalam kode cloud anda, tambahkan blok kode di bawah ini ke file products js anda parse cloud define("fetchallproducts", async (request) => { try { const product = parse object extend("product"); const query = new parse query(product); const products = await query find({ usemasterkey true }); // return products in a json friendly format return products map((product) => ({ id product id, sellerid product get("seller")? id, name product get("name"), description product get("description"), price product get("price"), quantityavailable product get("quantityavailable"), isactive product get("isactive"), createdat product createdat, updatedat product updatedat, })); } catch (error) { throw new error(`error fetching products ${error message}`); } }); fungsi ini mengambil produk dengan flag usemasterkey dan memformatnya untuk konsumsi frontend mengambil satu produk gunakan fungsi ini saat menampilkan informasi produk yang detail kepada pembeli untuk menerapkan ini dalam kode cloud anda, tambahkan blok kode di bawah ini ke dalam products js file parse cloud define("getsingleproduct", async (request) => { const { productid } = request params; const currentuser = request user; // ensure user is logged in if (!currentuser) { throw new error("you must be logged in to retrieve product information "); } if (!productid) { throw new error("missing required parameter productid "); } // query the product class const product = parse object extend("product"); const query = new parse query(product); query equalto("objectid", productid); try { const product = await query first({ usemasterkey true }); if (!product) { throw new error("product not found "); } // return a json friendly object return { objectid product id, name product get("name"), description product get("description"), price product get("price"), quantityavailable product get("quantityavailable"), isactive product get("isactive"), // optionally return more fields like images, category, etc }; } catch (error) { throw new error(`error fetching product ${error message}`); } }); fungsi ini mengembalikan detail lengkap produk untuk satu item ini memverifikasi bahwa productid yang valid telah diteruskan dan memastikan pemohon sudah masuk menanyakan produk penjual fungsi ini memungkinkan penjual untuk mengambil semua produk mereka sendiri untuk mengimplementasikan ini dalam kode cloud anda, tambahkan blok kode di bawah ini ke products js file parse cloud define("getsellerproducts", async (request) => { const currentuser = request user; // ensure the user is logged in if (!currentuser) { throw new error("you must be logged in to fetch seller products "); } // if your schema depends on verifying the user is truly a seller, you can check usertype const usertype = currentuser get("usertype"); if (usertype !== "seller") { throw new error("only sellers can view their own products "); } // if you want to retrieve products for the currently logged in seller // fetch the seller record that points to currentuser const seller = parse object extend("seller"); const sellerquery = new parse query(seller); sellerquery equalto("user", currentuser); const sellerrecord = await sellerquery first({ usemasterkey true }); if (!sellerrecord) { throw new error("no matching seller record found for the current user "); } // finally, fetch all products pointing to this seller const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("seller", sellerrecord); productquery limit(1000); // adjust or paginate as needed try { const products = await productquery find({ usemasterkey true }); // return a more friendly json structure return products map((prod) => ({ objectid prod id, name prod get("name"), description prod get("description"), price prod get("price"), quantityavailable prod get("quantityavailable"), isactive prod get("isactive"), createdat prod createdat, updatedat prod updatedat, })); } catch (error) { throw new error(`error fetching seller products ${error message}`); } }); fungsi ini mengonfirmasi bahwa pengguna adalah penjual, menemukan penjual yang terkait, dan mengquery kelas produk menggunakan pointer ke penjual penjual menggunakan ini untuk mengambil semua produk mereka sendiri menghapus produk fungsi ini memastikan hanya penjual yang membuat produk yang dapat menghapusnya untuk menerapkan ini dalam kode cloud anda, tambahkan blok kode di bawah ini ke file products js anda parse cloud define("deleteproduct", async (request) => { const { productid } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to delete a product "); } const usertype = currentuser get("usertype"); if (usertype !== "seller") { throw new error("only sellers can delete products "); } if (!productid) { throw new error("missing required parameter productid "); } // 1 find the seller record for the current user const seller = parse object extend("seller"); const sellerquery = new parse query(seller); sellerquery equalto("user", currentuser); const sellerrecord = await sellerquery first({ usemasterkey true }); if (!sellerrecord) { throw new error("no matching seller record found for the current user "); } // 2 fetch the product with a query that ensures the user owns it const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("objectid", productid); productquery equalto("seller", sellerrecord); // must match the correct seller const product = await productquery first({ usemasterkey true }); if (!product) { throw new error("product not found or you do not have permission to delete it "); } // 3 destroy the product try { await product destroy({ usemasterkey true }); return { message "product deleted successfully ", productid }; } catch (error) { throw new error(`error deleting product ${error message}`); } }); fungsi ini mengonfirmasi kepemilikan pengguna dan kemudian menghapus produk dari database memperbarui produk izinkan penjual untuk memodifikasi detail produk menggunakan fungsi ini untuk mengimplementasikannya dalam kode cloud anda, tambahkan blok kode di bawah ini ke dalam products js file parse cloud define("updateproduct", async (request) => { const { productid, name, description, price, quantityavailable, isactive } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to update a product "); } const usertype = currentuser get("usertype"); if (usertype !== "seller") { throw new error("only sellers can update products "); } if (!productid) { throw new error("missing required parameter productid "); } // 1 find the seller record for the current user const seller = parse object extend("seller"); const sellerquery = new parse query(seller); sellerquery equalto("user", currentuser); const sellerrecord = await sellerquery first({ usemasterkey true }); if (!sellerrecord) { throw new error("no matching seller record found for the current user "); } // 2 fetch the product const product = parse object extend("product"); const query = new parse query(product); query equalto("objectid", productid); query equalto("seller", sellerrecord); // must match the seller to ensure ownership const product = await query first({ usemasterkey true }); if (!product) { throw new error("product not found or you do not have permission to modify it "); } // 3 update product fields if (name !== undefined) product set("name", name); if (description !== undefined) product set("description", description); if (price !== undefined) product set("price", price); if (quantityavailable !== undefined) product set("quantityavailable", quantityavailable); if (isactive !== undefined) product set("isactive", isactive); // 4 save changes try { const updatedproduct = await product save(null, { usemasterkey true }); return { objectid updatedproduct id, name updatedproduct get("name"), description updatedproduct get("description"), price updatedproduct get("price"), quantityavailable updatedproduct get("quantityavailable"), isactive updatedproduct get("isactive"), }; } catch (error) { throw new error(`error updating product ${error message}`); } }); ini memastikan pengguna adalah penjual, mengonfirmasi kepemilikan produk, dan hanya memperbarui bidang yang disediakan dalam permintaan keranjang fungsi keranjang memungkinkan pembeli untuk mengelola item yang mereka rencanakan untuk dibeli fungsi fungsi ini termasuk menambahkan ke keranjang, memperbarui jumlah, melihat isi, dan menghapus item menambahkan ke keranjang fungsi ini menambahkan produk ke keranjang pembeli atau memperbarui jumlah jika sudah ada untuk mengimplementasikannya, buat file cart js dan tambahkan blok kode di bawah ini parse cloud define("addtocart", async (request) => { const { productid, quantity } = request params; // ensure there is a currently logged in user const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to modify the cart "); } if (!productid || !quantity) { throw new error("missing required parameters productid and quantity "); } // 1 fetch or create the user's cart const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", currentuser); let cart = await cartquery first({ usemasterkey true }); if (!cart) { cart = new cart(); cart set("user", currentuser); cart set("items", \[]); // initialize empty array cart set("totalprice", 0); // initialize price } // 2 fetch the product for price details (or any other attributes you need) const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("objectid", productid); const product = await productquery first({ usemasterkey true }); if (!product) { throw new error("product not found "); } const productprice = product get("price") || 0; // 3 insert or update the item in the cart const cartitems = cart get("items") || \[]; // check if this product is already in the cart const existingitemindex = cartitems findindex( (item) => item product objectid === productid ); if (existingitemindex >= 0) { // if product is already in cart, update the quantity cartitems\[existingitemindex] quantity += quantity; } else { // otherwise, add a new entry cartitems push({ product { type "pointer", classname "product", objectid productid, }, quantity quantity }); } // 4 recalculate total price // e g , summation of productprice quantity for each cart item let total = 0; for (const item of cartitems) { if (item product objectid === productid) { // use productprice from the newly fetched product total += productprice item quantity; } else { // this is a simplified approach ideally, you'd also store a price attribute on each item // or re fetch each product's price // for demonstration, we'll just skip them } } cart set("items", cartitems); cart set("totalprice", total); // 5 save the cart object try { const savedcart = await cart save(null, { usemasterkey true }); return { message "cart updated successfully", cartid savedcart id, items savedcart get("items"), totalprice savedcart get("totalprice"), }; } catch (error) { throw new error(`error saving cart ${error message}`); } }); ini memastikan pengguna terautentikasi, memvalidasi produk, memperbarui daftar item, dan menghitung ulang total harga keranjang mengambil keranjang ambil isi keranjang pengguna saat ini, termasuk detail produk dan subtotal untuk mengimplementasikan ini, tambahkan blok kode di bawah ini ke cart js file parse cloud define("getcart", async (request) => { if (!request user) throw "user must be logged in "; const user = request user; const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", user); cartquery include("items product"); // deep include const cart = await cartquery first(); if (!cart) return { items \[], totalprice 0 }; const items = cart get("items") || \[]; const parseditems = \[]; for (const item of items) { const product = item product; parseditems push({ productid product id, name product get("name"), price product get("price"), image product get("image")? url() || null, quantity item quantity, subtotal product get("price") item quantity, }); } return { cartid cart id, items parseditems, totalprice cart get("totalprice") || 0, }; }); fungsi ini menggunakan include("items product") untuk mengambil data produk bersarang dalam satu kueri mengedit keranjang perbarui jumlah item dalam keranjang atau hapus sepenuhnya jika jumlah baru adalah nol untuk mengimplementasikan ini, tambahkan blok kode di bawah ini ke cart js file parse cloud define("updatecart", async (request) => { const { productid, newquantity } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to update the cart "); } if (!productid || newquantity === undefined) { throw new error("missing required parameters productid and newquantity "); } // fetch or create the user's cart const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", currentuser); let cart = await cartquery first({ usemasterkey true }); if (!cart) { // if there's no existing cart, create one cart = new cart(); cart set("user", currentuser); cart set("items", \[]); cart set("totalprice", 0); } let cartitems = cart get("items") || \[]; // find the item matching the productid const itemindex = cartitems findindex( (item) => item product id === productid ); if (itemindex === 1) { throw new error("product not found in cart please add it first "); } // if newquantity <= 0, remove the item from the cart if (newquantity <= 0) { cartitems splice(itemindex, 1); } else { // otherwise, update the quantity cartitems\[itemindex] quantity = newquantity; } // recalculate total by fetching current prices from each product let total = 0; if (cartitems length > 0) { const product = parse object extend("product"); // for each item in the cart, fetch the product to get its price for (const item of cartitems) { const productquery = new parse query(product); productquery equalto("objectid", item product objectid); const product = await productquery first({ usemasterkey true }); if (product) { const productprice = product get("price") || 0; total += productprice item quantity; } } } // update and save the cart cart set("items", cartitems); cart set("totalprice", total); try { const updatedcart = await cart save(null, { usemasterkey true }); return { message "cart updated successfully", cartid updatedcart id, items updatedcart get("items"), totalprice updatedcart get("totalprice"), }; } catch (error) { throw new error(`error updating cart ${error message}`); } }); ini memvalidasi ulang semua harga produk selama pembaruan untuk memastikan akurasi total menghapus dari keranjang fungsi ini menghapus produk dari keranjang pengguna untuk mengimplementasikannya, tambahkan blok kode di bawah ini ke cart js file parse cloud define("removefromcart", async (request) => { const { productid } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to remove items from the cart "); } if (!productid) { throw new error("missing required parameter productid "); } // fetch the user's cart const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", currentuser); const cart = await cartquery first({ usemasterkey true }); if (!cart) { throw new error("no existing cart found for this user "); } let cartitems = cart get("items") || \[]; // filter out the item with the specified productid const filtereditems = cartitems filter( (item) => item product id !== productid ); // if nothing changed, the product wasn't in the cart if (filtereditems length === cartitems length) { throw new error("product not found in cart "); } // recalculate the cart total let total = 0; if (filtereditems length > 0) { const product = parse object extend("product"); for (const item of filtereditems) { const productquery = new parse query(product); productquery equalto("objectid", item product objectid); const product = await productquery first({ usemasterkey true }); if (product) { const productprice = product get("price") || 0; total += productprice item quantity; } } } // update and save the cart cart set("items", filtereditems); cart set("totalprice", total); try { const updatedcart = await cart save(null, { usemasterkey true }); return { message "item removed from cart", cartid updatedcart id, items updatedcart get("items"), totalprice updatedcart get("totalprice"), }; } catch (error) { throw new error(`error removing item from cart ${error message}`); } }); ini menyaring item dari array keranjang dan menghitung ulang total sebelum menyimpan pesanan fungsi fungsi ini mengelola proses pemesanan—dari membuat pesanan hingga mengambil riwayat pesanan penjual membuat pesanan fungsi ini mengubah keranjang pembeli menjadi pesanan resmi untuk mengimplementasikannya, buatlah sebuah order js file dan tambahkan blok kode di bawah ini parse cloud define("createorder", async (request) => { const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to place an order "); } // ensure the user is a buyer (assumes buyer class with user pointer) const buyer = parse object extend("buyer"); const buyerquery = new parse query(buyer); buyerquery equalto("user", currentuser); const buyer = await buyerquery first({ usemasterkey true }); if (!buyer) { throw new error("only buyers can place orders "); } // retrieve the cart for the user const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", buyer get("user")); // assuming the user pointer is stored in buyer const cart = await cartquery first({ usemasterkey true }); if (!cart || !cart get("items") || cart get("items") length === 0) { throw new error("cart is empty"); } const items = cart get("items"); let totalamount = 0; // adjust stock and calculate total order price const orderdetails = \[]; for (const item of items) { const productid = item product id; const quantity = item quantity; const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("objectid", productid); const product = await productquery first({ usemasterkey true }); if (!product) { throw new error(`product with id ${productid} not found`); } const availablequantity = product get("quantityavailable"); if (availablequantity < quantity) { throw new error(`not enough stock for product ${product get("name")}`); } // reduce the product quantity product set("quantityavailable", availablequantity quantity); await product save(null, { usemasterkey true }); const unitprice = product get("price"); totalamount += unitprice quantity; // prepare order detail entry orderdetails push({ product, quantity, unitprice }); } // create the new order object const order = parse object extend("order"); const order = new order(); order set("buyer", buyer); // set the buyer pointer order set("total", totalamount); // set the total amount order set("orderstatus", "pending"); // set the order status order set("orderdate", new date()); // set the order date // save the order to the database try { const savedorder = await order save(null, { usemasterkey true }); // create orderdetails for each item const orderdetails = parse object extend("orderdetails"); for (const detail of orderdetails) { const orderdetail = new orderdetails(); orderdetail set("order", savedorder); orderdetail set("product", detail product); orderdetail set("quantity", detail quantity); orderdetail set("unitprice", detail unitprice); await orderdetail save(null, { usemasterkey true }); } // optionally, clear the cart after saving the order cart set("items", \[]); await cart save(null, { usemasterkey true }); return savedorder; } catch (error) { throw new error(`could not create order ${error message}`); } }); ini memvalidasi pembeli, memeriksa ketersediaan stok, mengurangi inventaris produk, menyimpan kedua pesanan dan detailpesanan , dan mengosongkan keranjang setelah pesanan berhasil mengambil pesanan penjual fungsi ini mengambil semua pesanan yang mencakup produk yang dijual oleh penjual saat ini untuk mengimplementasikannya, tambahkan blok kode di bawah ini ke dalam order js file parse cloud define("getsellerorders", async (request) => { const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to view your orders "); } if (currentuser get("usertype") !== "seller") { throw new error("only sellers can access this endpoint "); } try { const seller = parse object extend("seller"); const seller = await new parse query(seller) equalto("userid", currentuser) first({ usemasterkey true }); if (!seller) { throw new error("seller profile not found "); } // find products by this seller const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("seller", seller); const products = await productquery find({ usemasterkey true }); if (!products || products length === 0) { return \[]; } // get product ids const productids = products map(product => product id); // find order details containing these products const orderdetails = parse object extend("orderdetails"); const orderdetailsquery = new parse query(orderdetails); orderdetailsquery containedin("product", products); const orderdetails = await orderdetailsquery find({ usemasterkey true }); if (!orderdetails || orderdetails length === 0) { return \[]; } const orderids = \[ new set(orderdetails map(detail => detail get("order") id))]; // query orders for these ids const order = parse object extend("order"); const orderquery = new parse query(order); orderquery containedin("objectid", orderids); orderquery include("buyer"); const orders = await orderquery find({ usemasterkey true }); // return the orders return orders map(order => ({ id order id, total order get("total"), status order get("orderstatus"), date order get("orderdate"), buyer order get("buyer") })); } catch (error) { throw new error(`could not fetch orders ${error message}`); } }); ini menemukan produk yang dimiliki oleh penjual, menanyakan orderdetails untuk produk tersebut, mengambil pesanan yang sesuai, dan mengembalikan struktur yang disederhanakan termasuk informasi pembeli memperbarui status pesanan fungsi ini mengubah status pesanan antara “menunggu” dan “selesai ” untuk mengimplementasikannya, tambahkan blok kode di bawah ini ke file order js anda parse cloud define("updateorder", async (request) => { const { orderid } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to view your orders "); } if (currentuser get("usertype") !== "seller") { throw new error("only sellers can access this endpoint "); } // validate the input parameter if (!orderid) { throw new error("missing required field orderid"); } try { // find the order with the specified orderid const order = parse object extend("order"); const query = new parse query(order); query equalto("objectid", orderid); const order = await query first({ usemasterkey true }); if (!order) { throw new error("order not found"); } // check current status // update the order status if (order get("orderstatus") === "completed") { order set("orderstatus", "pending"); } else { order set("orderstatus", "completed"); } // save the updated order await order save(null, { usemasterkey true }); return { success true, message "order status updated to completed" }; } catch (error) { throw new error(`could not update order status ${error message}`); } }); ini memastikan hanya penjual yang dapat melakukan tindakan ini dan bahwa pesanan ada sebelum memperbarui status fungsi backend ini memberikan aplikasi e commerce anda kemampuan untuk mengelola semua operasi inti—daftar produk, keranjang pembeli, pesanan, dan inventaris penjual—secara aman langsung di dalam back4app menggunakan cloud code untuk memastikan anda dapat mengakses fungsi cloud ini secara eksternal, anda perlu mendaftarkan semua file kode cloud anda di main js file, anda dapat melakukannya dengan menambahkan blok kode di bawah ini ke dalam main js file //main js require(" /auth js") require(" /cart js") require(" /order js") require(" /product js") require(" /seller js") pembuatan frontend untuk membangun etalase e commerce anda secara visual, anda akan menggunakan v0 dev untuk melakukan ini, mulailah dengan mengunjungi v0 dev http //v0 dev buat akun jika anda belum memilikinya setelah akun anda disiapkan, anda dapat mulai membuat frontend anda untuk membuat frontend anda, masukkan prompt di bawah ini create an e commerce web application with authentication features and a buyer and seller feature prompt ini akan membangun aplikasi e commerce next js dengan fitur yang diminta create ecommerce app dengan menggunakan fitur pratinjau, anda dapat menavigasi melalui aplikasi untuk memastikan semuanya berfungsi seperti yang diharapkan jika ada beberapa komplikasi atau anda ingin menambahkan lebih banyak fitur, anda dapat memberikan prompt lain dan v0 akan memodifikasi aplikasi sebagai contoh, berikan prompt the seller can create, add, delete and update products prompt ini akan memodifikasi aplikasi, membuat halaman di mana penjual dapat melakukan operasi crud modify ecommerce app akhirnya, berikan prompt do not sort products by categories and remove the categories page and input fields, remove the second and third step from the process of becoming a seller and add a bio input field to the first step, users should only sign in with email, and enhance the seller functionality to fully support product management (crud operations) prompt ini akan membuat editan terakhir pada aplikasi untuk mendapatkan pratinjau aplikasi yang dimodifikasi, klik pada tombol lihat di bagian yang disorot dalam gambar di atas setelah anda yakin aplikasi tersebut adalah yang anda inginkan, langkah selanjutnya adalah membawa proyek ke perangkat lokal anda untuk melakukan ini, klik tombol unduh yang dihasilkan v0 dengan respons prompt tombol unduh mengklik tombol tersebut akan menampilkan menu dropdown dengan tautan dan tombol unduh zip menu dropdown selanjutnya, klik tombol unduh zip setelah anda selesai mengunduh zip, buka terminal anda dan buat folder baru bernama ecommerce app di direktori yang anda pilih mkdir ecommerce app sekarang ekstrak konten dari folder zip ke dalam folder ecommerce app arahkan ke direktori ecommerce app di terminal anda dan instal dependensi yang diperlukan untuk melakukan ini, jalankan perintah berikut cd ecommerce app npm install setelah menginstal dependensi, jalankan perintah npm run dev di terminal anda untuk melihat proyek di server localhost anda mengintegrasikan frontend anda dengan backend anda untuk menghubungkan frontend anda dengan fungsi cloud code di backend back4app anda, anda akan menggunakan parse javascript sdk sdk memungkinkan anda untuk mengautentikasi pengguna, memanggil fungsi backend, dan berinteraksi dengan model data aplikasi anda dengan aman dan efisien untuk mengatur sdk, jalankan perintah berikut di direktori proyek anda di terminal npm install parse kemudian buat file lib/parse js untuk mengonfigurasi koneksi di file ini, masukkan blok kode di bawah ini import parse from "parse/dist/parse min js"; parse initialize("your app id", "your javascript key"); parse serverurl = "https //parseapi back4app com"; export default parse; ganti your app id dan your javascript key dengan kredensial yang ditemukan di dasbor back4app anda di bawah app settings konfigurasi dasar ini memastikan sdk tahu bagaimana cara terhubung ke proyek spesifik anda sekarang anda telah menghubungkan frontend anda ke backend anda, anda dapat mulai menulis fungsi untuk memanggil fungsi kode cloud yang telah anda definisikan di aplikasi back4app anda autentikasi di klien bagian ini menunjukkan cara menangani pendaftaran pengguna, login, dan logout di frontend anda menggunakan parse sdk setiap fungsi sesuai dengan fungsi cloud code atau metode sdk yang telah anda implementasikan di backend back4app anda di aplikasi anda, direktori app/auth/register menyimpan logika untuk mendaftar pengguna di page tsx definisikan state formdata ini state ini akan menyimpan kredensial yang diperlukan untuk mendaftar pengguna state formdata harus terlihat seperti ini const \[formdata, setformdata] = usestate({ name "", email "", password "", confirmpassword "", shippingaddress "", paymentinfo "", }); dengan kredensial yang dimasukkan ke dalam formdata , anda dapat memanggil signupuser fungsi cloud yang anda definisikan di aplikasi back4app anda pastikan untuk mengimpor parse dari lib/parse js import parse from "@/lib/parse"; const handlesubmit = async(e react formevent) => { e preventdefault(); try { const response = await parse cloud run("signupuser", { name formdata name, email formdata email, password formdata password, confirmpassword formdata confirmpassword, shippingaddress formdata shippingaddress, paymentinfo formdata paymentinfo, }); console log("signup successful ", response); } catch (error any) { console error("signup failed ", error); } } fungsi ini akan dijalankan ketika anda mengirimkan formulir pendaftaran ini memanggil signupuser fungsi cloud yang didefinisikan dalam cloud code fungsi ini mengirimkan kredensial pengguna dan data spesifik pembeli (seperti informasi pengiriman dan pembayaran) akhirnya, ia mencatat respons jika operasi berhasil atau mencetak kesalahan jika gagal masuk pengguna untuk masuk sebagai pengguna, gunakan fungsi kode cloud loginuser di backend anda arahkan ke direktori app/auth/login di aplikasi anda di dalam file page tsx , v0 akan membuat status yang berisi kredensial pengguna yang anda perlukan untuk masuk, yang perlu anda lakukan adalah mengirimkan kredensial tersebut ke fungsi loginuser sebagai contoh import parse from "@/lib/parse"; const handlesubmit = async (e react formevent) => { e preventdefault(); setisloading(true); try { const result = await parse cloud run("loginuser", { email, password }); // log in using returned session token await parse user become(result sessiontoken); console log("user logged in with session ", result sessiontoken); setisloading(false); router push("/"); // proceed to app } catch (error) { console error("login failed ", error); } }; fungsi ini memanggil fungsi cloud loginuser , mengirimkan kredensial login pengguna ke server setelah menerima token sesi yang valid sebagai respons, ia menggunakan parse user become untuk mengautentikasi klien dan menetapkan sesi sebagai milik pengguna yang telah masuk keluar dari pengguna untuk keluar dari pengguna dengan aman, anda akan memanggil kedua parse user logout() dan fungsi cloud code kustom anda logoutuser ini memastikan token sesi dihapus baik di klien maupun dinyatakan tidak valid di server anda akan menemukan tombol keluar di komponen header anda komponen ini akan berada di folder components di direktori root di dalam komponen, definisikan fungsi ini const handlelogout = async () => { const sessiontoken = parse user current()? get("sessiontoken"); if (sessiontoken) { await parse user become(sessiontoken); // ensures proper context await parse cloud run("logoutuser"); // delete the session on server } await parse user logout(); // clear the local session }; fungsi ini akan mengeluarkan pengguna dan menghapus sesi baik di klien maupun server di bagian jsx dari komponen, ikat fungsi ke tombol keluar menggunakan event onclick sebagai contoh \<dropdownmenuitem onclick={handlelogout}> logout \</dropdownmenuitem> pendaftaran penjual bagian ini menunjukkan fungsi untuk membiarkan pembeli meningkatkan akun mereka dan mendaftar sebagai penjual di aplikasi anda, navigasikan ke direktori app/seller/register di direktori ini, anda akan menemukan file page tsx di mana anda akan mendefinisikan fungsi yang memanggil createseller fungsi cloud fungsi ini bertanggung jawab untuk membuat profil penjual untuk pengguna saat ini di dalam file page tsx , ubah status formdata agar terlihat seperti ini const \[formdata, setformdata] = usestate({ phone "", bio "", businessname "", }); ganti logika di fungsi handlesubmit yang dibuat oleh v0 dengan logika di bawah ini const handlesubmit = async (e react formevent) => { e preventdefault(); try { const result = await parse cloud run("createseller", { businessname formdata businessname, bio formdata bio, phone formdata phone, }); console log("seller created ", result sellerid); } catch (error) { console error("error creating seller ", error); } }; panggil fungsi ini saat mengirimkan formulir untuk membuat profil penjual untuk pengguna anda manajemen produk gunakan panggilan fungsi ini di frontend anda untuk mengelola operasi produk sebagai penjual membuat produk untuk memanggil fungsi kode cloud yang menambahkan produk ke database, temukan app/seller/products/new direktori di dalam direktori ini terdapat page tsx file, di file ini terdapat formulir formulir ini mengambil informasi untuk produk termasuk gambar ubah state product agar terlihat seperti ini const \[product, setproduct] = usestate({ name "", price "", description "", stock "", status "active", }); juga buat state untuk menyimpan gambar anda const \[images, setimages] = usestate\<file\[]>(\[]); sekarang, tulis fungsi untuk menangani penambahan gambar ke database fungsi ini harus terlihat seperti ini const handleimageupload = async (event) => { event preventdefault(); try { let name = "image jpg"; const file = new parse file(name, event target files\[0]); const photo = await file save(); setimages((prev) => \[ prev, photo]); console log("file saved ", file); alert(`image uploaded successfully`); } catch (error) { console error("error saving file ", error); } }; ikat fungsi ini ke input yang bertanggung jawab untuk unggahan file menggunakan onchange acara selanjutnya, definisikan fungsi handlesubmit fungsi ini memanggil addproduct kode cloud sambil meneruskan informasi yang diperlukan seperti ini const handlesubmit = async (e react formevent) => { e preventdefault(); try { interface addproductparams { name string; description string; price number; quantityavailable number; isactive boolean; } interface addproductresponse { id string; } parse cloud run\<addproductresponse, addproductparams>("addproduct", { name product name, description product description, price product price, quantityavailable product stock, isactive product status === "active", imagefiles images, }) then((response) => { console log("product created ", response id); }); } catch (error) { console error("error creating product ", error); } }; panggilan ini mengirimkan data produk—termasuk gambar—ke backend untuk membuat daftar baru ambil semua produk panggilan ini mengambil seluruh katalog untuk daftar produk publik atau umpan halaman utama untuk membuat fungsi yang memanggil fetchallproducts fungsi cloud, navigasikan ke app/products direktori di dalam page tsx file, tambahkan kode ini interface product { id string; name string; description string; price number; image? string; } const \[products, setproducts] = usestate\<product\[]>(\[]); async function getallproducts() { try { const response = await parse cloud run("fetchallproducts"); console log("products fetched ", response); return response; } catch (error) { console error("error fetching products ", error); throw error; } } blok kode di atas mendefinisikan sebuah antarmuka untuk produk dan sebuah products state fungsi getallproducts memanggil fungsi cloud fetchallproducts untuk mendapatkan semua produk di database perhatikan bahwa anda perlu memanggil getallproducts fungsi di atas di dalam sebuah useeffect() hook untuk mengambil dan merender produk saat halaman dimuat seperti ini useeffect(() => { getallproducts() then((products) => { setproducts(products); }) catch((error) => { console error("error fetching products ", error); }); }, \[]); ambil produk tunggal panggilan ini mengambil detail lengkap tentang produk tertentu navigasikan ke folder \[id] di direktori app/products folder ini menyimpan file page tsx yang akan berisi logika untuk mengambil detail produk tunggal di file page tsx , tulis kode ini interface product { id string; name string; description string; price number; images? string\[]; quantityavailable number; } const \[product, setproduct] = usestate\<product>({ id "", name "", description "", price 0, images \[], quantityavailable 0, }); async function getsingleproduct() { try { const response = await parse cloud run("getsingleproduct", {productid params id}); console log("product fetched ", response); return response; } catch (error) { console error("error fetching products ", error); throw error; } } useeffect(() => { getsingleproduct() then((product) => { setproduct(product); }) catch((error) => { console error("error fetching products ", error); }); }, \[]); blok kode ini mendefinisikan antarmuka untuk objek produk, mengatur variabel status product dengan nilai default fungsi getsingleproduct memanggil fungsi kode cloud getsingleproduct anda menggunakan productid dari parameter rute hook useeffect ini dijalankan sekali saat komponen dipasang perbarui produk ketika seorang penjual mengedit produk, panggil fungsi ini dengan bidang yang diperbarui untuk memperbarui produk, anda memerlukan formulir dengan bidang input yang mengumpulkan data baru, anda dapat menemukan formulir ini di page tsx file yang terletak di app/seller/products/\[id]/edit direktori sebelum memperbarui produk, anda perlu mengambil produk dan untuk melakukan ini tambahkan kode ini ke page tsx file anda const \[product, setproduct] = usestate({ id "", name "", price "", description "", stock "", images \["", "", ""], status "active", }); useeffect(() => { async function fetchproduct() { try { const response = await parse cloud run("getsingleproduct", { productid params id, }); setproduct({ id response objectid, name response name || "", price string(response price ?? "0"), description response description || "", stock string(response quantityavailable ?? "0"), // fallback to placeholders if actual image data is not provided images \[ response image1 || `/placeholder svg?height=500\&width=500\&text=product`, response image2 || `/placeholder svg?height=500\&width=500\&text=productview+2`, response image3 || `/placeholder svg?height=500\&width=500\&text=productview+3`, ], status response isactive ? "active" "out of stock", }); } catch (error) { console error("error fetching product ", error); } } fetchproduct(); }, \[]); kode ini mengambil rincian dari satu produk dari backend back4app anda dengan fungsi kode cloud getsingleproduct dan menyimpan rincian tersebut dalam status komponen product untuk ditampilkan sebagai nilai default di formulir anda sebelum anda memodifikasinya setelah mengambil rincian produk, anda dapat mengubah rincian tersebut menggunakan formulir setelah mengisi formulir, mengirimkan formulir akan memanggil fungsi handlesubmit yang akan memegang logika untuk memperbarui produk anda fungsi handlesubmit anda harus terlihat seperti ini const handlesubmit = async (e react formevent) => { e preventdefault(); try { await parse cloud run("updateproduct", { productid product id, name product name, description product description, price parsefloat(product price), quantityavailable parseint(product stock, 10), isactive product status === "active", }); } catch (error) { console error("error updating product ", error); } }; fungsi ini memanggil updateproduct cloud code anda dan mengirimkan objek dengan data produk yang diperbarui hapus produk gunakan fungsi ini untuk menghapus produk setelah konfirmasi dari penjual untuk menghapus produk, anda perlu menambahkan fungsi handledelete yang memuat logika yang diperlukan untuk menghapus produk anda akan mendefinisikan fungsi handledelete dalam file page tsx di direktori app/seller/products/\[id]/edit const handledelete = async () => { const confirmdelete = confirm( "are you sure you want to delete this product? this action cannot be undone " ); if (!confirmdelete) return; try { await parse cloud run("deleteproduct", { productid product id, }); } catch (error) { console error("error deleting product ", error); } }; fungsi handledelete pertama tama mengonfirmasi niat pengguna sebelum memanggil fungsi cloud code deleteproduct yang didefinisikan di backend anda ikat fungsi handledelete ke tombol hapus di bagian jsx dari komponen sebagai contoh \<button type="button" variant="destructive" onclick={handledelete} \> \<trash2 classname="h 4 w 4 mr 2" /> delete product \</button> dapatkan produk penjual gunakan ini untuk mengambil semua produk yang dimiliki oleh penjual yang saat ini masuk anda akan mendefinisikan fungsi untuk menangani pengambilan produk penjual di file page tsx di direktori app/seller/dashboard dalam file, tulis kode ini const \[products, setproducts] = usestate< { objectid string; name string; price number; quantityavailable number; sales number; isactive boolean; }\[] \>(\[]); useeffect(() => { async function fetchproducts() { try { const result = await parse cloud run("getsellerproducts"); setproducts(result); } catch (error) { console error("error fetching products ", error); } }; fetchproducts(); }, \[]); blok kode ini mendefinisikan state products dan menggunakan hook useeffect untuk memanggil fungsi fetchproducts sekali saat dimuat fungsi fetchproducts memanggil fungsi kode cloud getsellerproducts dan memperbarui state products dengan hasil panggilan manajemen keranjang panggilan ini memungkinkan pembeli untuk mengelola keranjang belanja mereka sebelum melakukan pemesanan tambahkan ke keranjang panggilan ini menambahkan produk yang dipilih ke keranjang pengguna atau meningkatkan jumlahnya temukan file page tsx di direktori app/products dan tambahkan baris kode berikut async function handleaddtocart(productid string, quantity number = 1) { try { const response = await parse cloud run("addtocart", { productid, quantity, }); console log("add to cart success ", response); } catch (error) { console error("failed to add to cart ", error); } } fungsi handleaddtocart menerima productid dan jumlah opsional sebagai argumen dan memanggil addtocart kode cloud di backend anda fungsi ini harus dijalankan ketika pengguna anda mengklik tombol "tambahkan ke keranjang" di kartu produk anda sebagai contoh \<button classname="w full" size="sm" onclick={() => handleaddtocart(product id)}> \<shoppingcart classname="h 4 w 4 mr 2" /> add to cart \</button> dalam file, tulis kode ini lihat keranjang gunakan ini untuk mengambil isi keranjang dan menampilkan ringkasan keranjang secara langsung untuk melakukan ini, navigasikan ke file page tsx di direktori app/cart dalam file ini, tambahkan blok kode di bawah ini interface cartitem { id string; // product's objectid name string; price number; quantity number; image string; } const \[cartitems, setcartitems] = usestate\<cartitem\[]>(\[]); useeffect(() => { async function fetchcart() { try { const response = await parse cloud run("getcart"); const parsed = response items map((item) => ({ id item productid, name item name, price item price, quantity item quantity, image item image, })); setcartitems(parsed); } catch (error) { console error("failed to fetch cart ", error); } } fetchcart(); }, \[]); blok kode di atas mendefinisikan bentuk data keranjang di frontend dengan interface cartitem , mendefinisikan state cartitems yang menyimpan item keranjang ini juga menggunakan useeffect untuk memicu fungsi fetchcart sekali saat halaman dimuat fungsi fetchcart memanggil fungsi kode cloud getcart dan mengambil keranjang dari backend anda ini menggunakan metode map untuk mengonversi format backend ke format frontend sebelum menyimpan data keranjang yang diproses ke dalam state cartitems perbarui item keranjang panggilan ini mengubah jumlah produk tertentu di keranjang di dalam page tsx file di direktori app/cart , anda akan menemukan sebuah updatequantity fungsi ganti fungsi itu dengan yang di bawah ini const updatequantity = async (productid string, newquantity number) => { if (newquantity < 1) return; try { await parse cloud run("updatecart", { productid, newquantity, }); console log("updated the cart"); } catch (error) { console error("failed to update cart item ", error); } }; fungsi ini mengambil dua parameter, productid dan jumlah yang diperbarui yang ingin diatur pengguna newquantity ini memanggil fungsi cloud updatecart anda dan mengirimkan baik productid dan newquantity sebagai parameter anda mengikat fungsi ini ke tombol +/ menggunakan event onclick seperti ini \<div classname="flex items center gap 2"> \<button variant="outline" size="icon" classname="h 8 w 8" onclick={() => updatequantity(item id, item quantity 1)} \> \<minus classname="h 3 w 3" /> \<span classname="sr only">decrease quantity\</span> \</button> \<span classname="w 8 text center">{item quantity}\</span> \<button variant="outline" size="icon" classname="h 8 w 8" onclick={() => updatequantity(item id, item quantity + 1)} \> \<plus classname="h 3 w 3" /> \<span classname="sr only">increase quantity\</span> \</button> \</div> hapus dari keranjang menghapus item sepenuhnya dari keranjang untuk melakukan ini, tambahkan blok kode di bawah ini ke page tsx file di app/cart direktori dalam file ini const removeitem = async (productid string) => { try { await parse cloud run("removefromcart", { productid, }); setcartitems((items) => items filter((item) => item id !== productid)); } catch (error) { console error("failed to remove item ", error); } }; fungsi ini, removeitem , menghapus produk tertentu dari keranjang pengguna dengan memanggil fungsi cloud removefromcart di backend fungsi ini juga memperbarui status keranjang lokal di frontend untuk mencerminkan perubahan ikat fungsi ini ke tombol "hapus item", seperti ini \<button variant="ghost" size="icon" classname="h 8 w 8 text muted foreground" onclick={() => removeitem(item id)} \> \<trash2 classname="h 4 w 4" /> \<span classname="sr only">remove item\</span> \</button> manajemen pesanan fungsi fungsi ini menangani pembuatan dan pelacakan pesanan untuk pembeli dan penjual buat pesanan ini membuat pesanan dari konten saat ini di keranjang pengguna anda juga mendefinisikan fungsi ini di page tsx file di app/cart direktori fungsi yang memegang logika untuk membuat pesanan harus terlihat seperti ini const handleorder = async () => { try { const user = parse user current(); if (!user) { throw new error("you must be logged in to place an order "); } const result = await parse cloud run("createorder"); console log("order created successfully ", result); } catch (error any) { console error("failed to create order ", error); } }; fungsi ini, handleorder , menangani proses checkout dengan melakukan pemesanan melalui backend back4app anda fungsi ini, handleupdate , memperbarui status pesanan yang ada dengan memanggil fungsi cloud bernama completeorder di backend back4app anda ikat fungsi ini ke tombol "edit" di bagian jsx dari komponen seperti ini \<button variant="ghost" size="icon" onclick={() => {handleupdate(order id)}}> \<pencil classname="h 4 w 4" /> \<span classname="sr only">view\</span> \</button> menyebarkan frontend di kontainer back4app kontainer back4app menawarkan cara yang efisien untuk mengemas dan menyebarkan aplikasi frontend anda alih alih mengelola layanan hosting terpisah, anda dapat menyimpan semua ketergantungan dalam gambar docker, memastikan kinerja yang konsisten dan menyederhanakan pemeliharaan pendekatan berbasis kontainer ini sangat berguna untuk aplikasi next js, di mana anda dapat mengoptimalkan build untuk kecepatan dan keandalan untuk mengontainerisasi aplikasi anda, buat sebuah dockerfile untuk mendefinisikan bagaimana aplikasi anda dibangun dan disajikan di bawah ini adalah contoh dockerfile untuk aplikasi next js # stage 1 build the next js app from node 20 alpine as builder workdir /app copy package json package lock json / run npm install copy run npm run build \# stage 2 run the next js app from node 20 alpine workdir /app copy from=builder /app / expose 3000 cmd \["npm", "start"] setelah membuat dockerfile anda, buat sebuah dockerignore file dan tambahkan perintah perintah ini # node modules (reinstalled in docker) node modules \# next js build output next out \# logs npm debug log yarn debug log yarn error log pnpm debug log \# env files (optional — only if you handle secrets another way) env env local env development env production env test \# os / ide / editor junk ds store thumbs db vscode idea \# git git gitignore sekarang anda dapat membangun dan menguji aplikasi anda secara lokal untuk melakukan ini, jalankan perintah berikut di terminal anda docker build t ecommerce app docker run p 3000 3000 ecommerce app buka http //localhost 3000 untuk memastikan situs anda berjalan dengan baik setelah anda memverifikasi semuanya berfungsi seperti yang diharapkan secara lokal, saatnya untuk mendorong kode anda ke github dan menyebarkannya melalui back4app pastikan kode anda telah dikomit dan didorong ke repositori github ini akan memungkinkan back4app mengakses proyek anda untuk penyebaran di akun back4app anda, pergi ke dasbor anda dan klik pada dasbor menu dropdown di bagian atas layar dashboard menu dari dropdown, pilih platform penyebaran web web deployment platform ini akan membawa anda ke halaman penyebaran aplikasi web deploy web application page klik tombol deploy a web app untuk memulai proses penyebaran link github repo kemudian, klik pada import github repo dan pilih repositori yang berisi dockerfile anda tentukan nama untuk proyek anda (misalnya, ecommerce back4app) ikuti panduan pengaturan untuk membangun dan menyebarkan aplikasi anda setelah penyebaran selesai, back4app akan menampilkan halaman konfirmasi seperti ini successful deployment area yang disorot dalam gambar di atas adalah url di mana aplikasi anda aktif anda dapat menggunakannya untuk melihat dan menguji aplikasi anda langsung di browser web setelah dikerahkan, gunakan dasbor back4app untuk memantau log build, melacak kesehatan kontainer, dan mengembalikan ke versi sebelumnya jika diperlukan dasbor menampilkan pembaruan waktu nyata tentang status kontainer, sehingga lebih mudah untuk menemukan kesalahan dan menjaga lingkungan yang stabil untuk pengguna anda dengan kontainer, anda mendapatkan solusi frontend yang fleksibel dan portabel yang terintegrasi dengan mulus dengan backend back4app anda, membuka jalan untuk rilis yang konsisten dan tanpa masalah anda dapat mengunjungi situs web e commerce yang dibangun dalam tutorial ini di sini https //ecommerceback4app mcphit37 b4a run/ kesimpulan selamat—anda sekarang telah merakit setiap lapisan dari tumpukan e commerce yang telah teruji dan siap produksi pengaturan back end dari penyediaan akun back4app anda hingga memodelkan pengguna, produk, dan pesanan keamanan & api menerapkan otentikasi yang kuat, dan mengekspos data anda melalui endpoint rest dan graphql logika bisnis & pembaruan waktu nyata mengotomatiskan alur kerja dengan cloud code dan menyiarkan perubahan langsung melalui livequery penyebaran front end menghubungkan sdk javascript dan mengirimkan toko next js dalam kontainer back4app apa selanjutnya? selami dokumentasi back4app https //www back4app com/docs dan panduan parse platform https //docs parseplatform org untuk referensi mendalam, atau bergabunglah dengan forum komunitas untuk mendapatkan tips lanjutan dan aplikasi contoh dari pemelihara dan pengembang lainnya fondasi ini baru permulaan—perluas lebih jauh dengan mengintegrasikan webhook dan pekerjaan terjadwal, menghubungkan gateway pembayaran, atau membangun aplikasi pendamping seluler terus iterasi, refactor, dan kembangkan basis kode anda—dan saksikan toko anda tumbuh seiring dengan ambisi anda