From 8ac27da65b600cf373d618014142d8d252f18b79 Mon Sep 17 00:00:00 2001 From: Baghaztra Date: Wed, 22 Oct 2025 17:09:41 +0700 Subject: [PATCH] [Update] Guest --- .../Controllers/Api/GuestApiController.php | 137 ++++++++++ .../Api/PelangganApiController.php | 32 +-- backend-baru/app/Models/Guest.php | 22 ++ backend-baru/app/Models/Pelanggan.php | 7 +- .../database/factories/GuestFactory.php | 28 ++ .../database/factories/PelangganFactory.php | 4 +- ...5_10_02_052812_create_pelanggans_table.php | 2 +- .../2025_10_22_085343_create_guests_table.php | 30 +++ .../database/seeders/PelangganSeeder.php | 12 +- backend-baru/routes/api.php | 11 +- proyek-frontend/app/pages/p/[code].vue | 231 ++++++++++------- proyek-frontend/app/pages/p/daftar-tamu.vue | 241 ++++++++++++++++++ proyek-frontend/nuxt.config.ts | 1 + 13 files changed, 632 insertions(+), 126 deletions(-) create mode 100644 backend-baru/app/Http/Controllers/Api/GuestApiController.php create mode 100644 backend-baru/app/Models/Guest.php create mode 100644 backend-baru/database/factories/GuestFactory.php create mode 100644 backend-baru/database/migrations/2025_10_22_085343_create_guests_table.php create mode 100644 proyek-frontend/app/pages/p/daftar-tamu.vue diff --git a/backend-baru/app/Http/Controllers/Api/GuestApiController.php b/backend-baru/app/Http/Controllers/Api/GuestApiController.php new file mode 100644 index 0000000..8dd9070 --- /dev/null +++ b/backend-baru/app/Http/Controllers/Api/GuestApiController.php @@ -0,0 +1,137 @@ +first(); + if (!$pelanggan) { + return response()->json([ + 'success' => false, + 'message' => 'Pelanggan tidak ditemukan.', + ], 404); + } + if ($pelanggan->status !== 'diterima') { + return response()->json([ + 'success' => false, + 'message' => 'Pesanan belum diterima.', + ], 400); + } + + $guests = Guest::where('id_pelanggan', $pelanggan->id)->get(); + + return response()->json([ + 'success' => true, + 'data' => $guests, + ]); + } + + public function store(Request $request) + { + try { + $validated = $request->validate([ + 'kode_pelanggan' => 'required|exists:pelanggans,kode_pelanggan', + 'nama_tamu' => 'required|string|max:255', + ]); + + $pelanggan = Pelanggan::where('kode_pelanggan', $validated['kode_pelanggan'])->firstOrFail(); + + $jumlah_tamu = Guest::where('id_pelanggan', $pelanggan->id)->count(); + $paket = $pelanggan->template->paket; + if ($paket === 'starter' && $jumlah_tamu >= 10) { + return response()->json([ + 'success' => false, + 'message' => 'Batas tamu untuk paket starter adalah 10.', + ], 400); + } elseif ($paket === 'basic' && $jumlah_tamu >= 20) { + return response()->json([ + 'success' => false, + 'message' => 'Batas tamu untuk paket Basic adalah 20.', + ], 400); + } elseif ($paket === 'premium' && $jumlah_tamu >= 30) { + return response()->json([ + 'success' => false, + 'message' => 'Batas tamu untuk paket Premium adalah 30.', + ], 400); + } + // cek anunya udah diterima + if ($pelanggan->status !== 'diterima') { + return response()->json([ + 'success' => false, + 'message' => 'Pesanan belum diterima.', + ], 400); + } + + $guest = Guest::create([ + 'id_pelanggan' => $pelanggan->id, + 'nama_tamu' => $validated['nama_tamu'], + 'kode_invitasi' => 'INV-' . strtoupper(Str::random(6)), + ]); + + return response()->json([ + 'success' => true, + 'data' => $guest, + ], 201); + } catch (\Illuminate\Validation\ValidationException $e) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed', + 'errors' => $e->errors(), + ], 422); + } + } + + public function destroy(int $id) + { + $guest = Guest::find($id); + + if (!$guest) { + return response()->json([ + 'success' => false, + 'message' => 'Tamu tidak ditemukan.', + ], 404); + } + + try { + $guest->delete(); + + return response()->json([ + 'success' => true, + 'message' => 'Tamu berhasil dihapus.', + ], 200); + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => 'Gagal menghapus tamu.', + ], 500); + } + } + + // Ambil undangan berdasarkan invitation code + public function getByInvitationCode($code) + { + $data = Guest::with('pelanggan.template') + ->where('kode_invitasi', $code) + ->first(); + + if (!$data) { + return response()->json([ + 'success' => false, + 'message' => 'Data undangan tidak ditemukan.', + ], 404); + } + + return response()->json([ + 'success' => true, + 'data' => $data, + ]); + } +} diff --git a/backend-baru/app/Http/Controllers/Api/PelangganApiController.php b/backend-baru/app/Http/Controllers/Api/PelangganApiController.php index 305492a..2ecbe52 100644 --- a/backend-baru/app/Http/Controllers/Api/PelangganApiController.php +++ b/backend-baru/app/Http/Controllers/Api/PelangganApiController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; +use App\Models\Guest; use App\Models\Pelanggan; use App\Models\Template; use Illuminate\Http\Request; @@ -26,10 +27,10 @@ class PelangganApiController extends Controller $template = Template::where('slug', $request->input('template_slug'))->firstOrFail(); - // Generate unique invitation code - $invitationCode = 'INV-' . strtoupper(Str::random(6)); - while (Pelanggan::where('invitation_code', $invitationCode)->exists()) { - $invitationCode = 'INV-' . strtoupper(Str::random(6)); + // Generate unique customer code + $customerCode = 'CUST-' . strtoupper(Str::random(6)); + while (Pelanggan::where('kode_pelanggan', $customerCode)->exists()) { + $customerCode = 'CUST-' . strtoupper(Str::random(6)); } // Handle file uploads @@ -50,7 +51,7 @@ class PelangganApiController extends Controller 'form' => array_merge($validated['form'], ['foto' => $fotoPaths]), 'harga' => $template->harga, 'status' => 'menunggu', - 'invitation_code' => $invitationCode, + 'kode_pelanggan' => $customerCode, ]); return response()->json([ @@ -108,27 +109,6 @@ class PelangganApiController extends Controller ]); } - // ๐Ÿ”น Ambil pesanan berdasarkan invitation code - public function getByInvitationCode($code) - { - $pelanggan = Pelanggan::with('template') - ->where('invitation_code', $code) - ->where('status', 'diterima') - ->first(); - - if (!$pelanggan) { - return response()->json([ - 'success' => false, - 'message' => 'Data undangan tidak ditemukan.', - ], 404); - } - - return response()->json([ - 'success' => true, - 'data' => $pelanggan, - ]); - } - // ๐Ÿ”น Update status pesanan (opsional untuk admin mobile) public function updateStatus(Request $request, $id) { diff --git a/backend-baru/app/Models/Guest.php b/backend-baru/app/Models/Guest.php new file mode 100644 index 0000000..3867890 --- /dev/null +++ b/backend-baru/app/Models/Guest.php @@ -0,0 +1,22 @@ +belongsTo(Pelanggan::class, 'id_pelanggan'); + } +} diff --git a/backend-baru/app/Models/Pelanggan.php b/backend-baru/app/Models/Pelanggan.php index 095f08c..30780a0 100644 --- a/backend-baru/app/Models/Pelanggan.php +++ b/backend-baru/app/Models/Pelanggan.php @@ -19,7 +19,7 @@ class Pelanggan extends Model 'form', 'harga', 'status', - 'invitation_code', + 'kode_pelanggan', ]; protected $casts = [ @@ -31,4 +31,9 @@ class Pelanggan extends Model { return $this->belongsTo(Template::class, 'template_id'); } + + public function guests() + { + return $this->hasMany(Guest::class, 'id_pelanggan'); + } } diff --git a/backend-baru/database/factories/GuestFactory.php b/backend-baru/database/factories/GuestFactory.php new file mode 100644 index 0000000..7a0d4b5 --- /dev/null +++ b/backend-baru/database/factories/GuestFactory.php @@ -0,0 +1,28 @@ + null, // Diisi oleh seeder + 'nama_tamu' => $this->faker->name(), + 'kode_invitasi' => $this->generateUniqueInvitationCode(), + ]; + } + + protected function generateUniqueInvitationCode(): string + { + do { + $code = 'INV-' . strtoupper(Str::random(6)); + } while (Guest::where('kode_invitasi', $code)->exists()); + + return $code; + } +} \ No newline at end of file diff --git a/backend-baru/database/factories/PelangganFactory.php b/backend-baru/database/factories/PelangganFactory.php index f1d8341..fdcaf68 100644 --- a/backend-baru/database/factories/PelangganFactory.php +++ b/backend-baru/database/factories/PelangganFactory.php @@ -24,7 +24,7 @@ class PelangganFactory extends Factory // Generate unique invitation code $invitationCode = 'INV-' . strtoupper(Str::random(6)); - while (Pelanggan::where('invitation_code', $invitationCode)->exists()) { + while (Pelanggan::where('kode_pelanggan', $invitationCode)->exists()) { $invitationCode = 'INV-' . strtoupper(Str::random(6)); } @@ -36,7 +36,7 @@ class PelangganFactory extends Factory 'form' => $formData, 'harga' => $template->harga, 'status' => $this->faker->randomElement(['menunggu', 'diterima', 'ditolak']), - 'invitation_code' => $invitationCode, + 'kode_pelanggan' => $invitationCode, ]; } diff --git a/backend-baru/database/migrations/2025_10_02_052812_create_pelanggans_table.php b/backend-baru/database/migrations/2025_10_02_052812_create_pelanggans_table.php index d2a9068..b6cc86a 100644 --- a/backend-baru/database/migrations/2025_10_02_052812_create_pelanggans_table.php +++ b/backend-baru/database/migrations/2025_10_02_052812_create_pelanggans_table.php @@ -21,7 +21,7 @@ return new class extends Migration { $table->decimal('harga', 15, 2)->nullable(); $table->enum('status', ['menunggu', 'diterima', 'ditolak'])->default('menunggu'); - $table->string('invitation_code')->unique(); + $table->string('kode_pelanggan')->unique(); $table->timestamps(); }); } diff --git a/backend-baru/database/migrations/2025_10_22_085343_create_guests_table.php b/backend-baru/database/migrations/2025_10_22_085343_create_guests_table.php new file mode 100644 index 0000000..38499fe --- /dev/null +++ b/backend-baru/database/migrations/2025_10_22_085343_create_guests_table.php @@ -0,0 +1,30 @@ +id(); + $table->foreignId('id_pelanggan')->constrained('pelanggans')->cascadeOnDelete(); + $table->string('nama_tamu'); + $table->string('kode_invitasi'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('guests'); + } +}; diff --git a/backend-baru/database/seeders/PelangganSeeder.php b/backend-baru/database/seeders/PelangganSeeder.php index d554cec..03ea70a 100644 --- a/backend-baru/database/seeders/PelangganSeeder.php +++ b/backend-baru/database/seeders/PelangganSeeder.php @@ -10,7 +10,17 @@ class PelangganSeeder extends Seeder { public function run(): void { - Pelanggan::factory(100)->create(); + $pelanggan = Pelanggan::factory(100)->create(); + + $guests = []; + foreach ($pelanggan as $item) { + $guestData = \App\Models\Guest::factory()->count(rand(1, 5))->make([ + 'id_pelanggan' => $item->id, + ])->toArray(); + $guests = array_merge($guests, $guestData); + } + \App\Models\Guest::insert($guests); + // $pelanggans = [ // [ // 'nama_pemesan' => 'Arief Dwi Wicaksono', diff --git a/backend-baru/routes/api.php b/backend-baru/routes/api.php index ca5891f..4dc045b 100644 --- a/backend-baru/routes/api.php +++ b/backend-baru/routes/api.php @@ -1,5 +1,6 @@ -
- - +
-
-
-

Loading invitation...

+
+
+
+

Loading invitation...

+
-
- - - - -

Undangan Tidak Ditemukan

-

Maaf, undangan yang Anda cari tidak tersedia atau sudah tidak berlaku.

- - Kembali ke Beranda - +
+
+ + + + +

Undangan Tidak Ditemukan

+

{{ errorMessage }}

+ + Kembali ke Beranda + +
-
+
- + -
-

Invitation Data

-
Tampilan ini muncul saat komponen template belum tersedia
-
-

{{ key.replace('_', ' ') }}

-

{{ value }}

-
{{ JSON.stringify(value, null, 2) }}
+
+
+

Invitation Data

+
Tampilan ini muncul saat komponen template belum tersedia
+ + +
+

Informasi Tamu

+

Nama: {{ tamuData.nama_tamu }}

+

Kode: {{ tamuData.kode_invitasi }}

+
+ + +
+

Informasi Pelanggan

+

Nama: {{ pelangganData.nama_pemesan }}

+

Email: {{ pelangganData.email }}

+

No. Telp: {{ pelangganData.no_tlpn }}

+

Status: {{ pelangganData.status }}

+
+ + +
+

Template

+

Nama: {{ pelangganData.template.nama_template }}

+

Slug: {{ pelangganData.template.slug }}

+

Paket: {{ pelangganData.template.paket }}

+
+ + +
+

Data Form

+
+
+

{{ key.replace(/_/g, ' ') }}

+

{{ value || '-' }}

+
{{ JSON.stringify(value, null, 2) }}
+
+
+
@@ -44,63 +79,20 @@ \ No newline at end of file diff --git a/proyek-frontend/nuxt.config.ts b/proyek-frontend/nuxt.config.ts index c3b5343..bb13bc7 100644 --- a/proyek-frontend/nuxt.config.ts +++ b/proyek-frontend/nuxt.config.ts @@ -26,6 +26,7 @@ export default defineNuxtConfig({ runtimeConfig: { public: { + baseUrl: process.env.NUXT_PUBLIC_BASE_URL || 'http://localhost:3000', apiBaseUrl: process.env.NUXT_PUBLIC_API_BASE_URL || 'http://localhost:8000' } }