From 6273d1a31d0603de195324b7c11870da00e394d3 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Sat, 20 Jun 2026 12:04:58 +0700 Subject: [PATCH] feat: integrate homepage settings management in Admin and HomeController, enhancing homepage configuration capabilities --- .../Admin/System/SettingController.php | 13 + app/Http/Controllers/HomeController.php | 7 +- .../System/Setting/HomepageSettingRequest.php | 42 ++ app/Models/HomepageConfiguration.php | 35 ++ .../System/Setting/HomepageSettingService.php | 55 ++ app/Settings/HomepageSettings.php | 89 +++ ...0_create_homepage_configurations_table.php | 21 + ..._06_20_110000_create_homepage_settings.php | 89 +++ ...000_rename_deal_to_gallery_in_homepage.php | 32 + .../admin/setting/HomepageSection.vue | 116 ++++ resources/js/layouts/SettingLayout.vue | 3 +- resources/js/pages/Home.vue | 571 +++++++----------- .../js/pages/admin/system/setting/Index.vue | 4 + resources/js/types/setting.ts | 14 +- routes/web.php | 4 + 15 files changed, 745 insertions(+), 350 deletions(-) create mode 100644 app/Http/Requests/Admin/System/Setting/HomepageSettingRequest.php create mode 100644 app/Models/HomepageConfiguration.php create mode 100644 app/Services/System/Setting/HomepageSettingService.php create mode 100644 app/Settings/HomepageSettings.php create mode 100644 database/migrations/2026_06_20_130000_create_homepage_configurations_table.php create mode 100644 database/settings/2026_06_20_110000_create_homepage_settings.php create mode 100644 database/settings/2026_06_20_120000_rename_deal_to_gallery_in_homepage.php create mode 100644 resources/js/components/admin/setting/HomepageSection.vue diff --git a/app/Http/Controllers/Admin/System/SettingController.php b/app/Http/Controllers/Admin/System/SettingController.php index efd7af8..213f851 100644 --- a/app/Http/Controllers/Admin/System/SettingController.php +++ b/app/Http/Controllers/Admin/System/SettingController.php @@ -4,10 +4,12 @@ use App\Http\Controllers\Concerns\FlashesEntityMessage; use App\Http\Controllers\Controller; +use App\Http\Requests\Admin\System\Setting\HomepageSettingRequest; use App\Http\Requests\Admin\System\Setting\HrSettingRequest; use App\Http\Requests\Admin\System\Setting\MarketplaceRequest; use App\Http\Requests\Admin\System\Setting\SocialMediaRequest; use App\Http\Requests\Admin\System\Setting\SystemRequest; +use App\Services\System\Setting\HomepageSettingService; use App\Services\System\Setting\HrSettingService; use App\Services\System\Setting\MarketplaceService; use App\Services\System\Setting\SocialMediaService; @@ -25,6 +27,7 @@ public function __construct( private readonly SocialMediaService $socialMediaService, private readonly MarketplaceService $marketplaceService, private readonly HrSettingService $hrSettingService, + private readonly HomepageSettingService $homepageSettingService, ) {} public function index(): Response @@ -34,6 +37,7 @@ public function index(): Response 'socialMedia' => $this->socialMediaService->socialMediaData(), 'marketplace' => $this->marketplaceService->marketplaceData(), 'hr' => $this->hrSettingService->hrData(), + 'homepage' => $this->homepageSettingService->homepageData(), ]); } @@ -72,4 +76,13 @@ public function updateHr(HrSettingRequest $request): RedirectResponse return redirect()->route('admin.system.setting.index'); } + + public function updateHomepage(HomepageSettingRequest $request): RedirectResponse + { + $this->homepageSettingService->updateHomepage($request->validated()); + + $this->flashSuccess('Pengaturan homepage berhasil disimpan.'); + + return redirect()->route('admin.system.setting.index'); + } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 5b723f9..e05479b 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -7,6 +7,7 @@ use App\Models\Product; use App\Models\SystemConfiguration; use App\Services\Manage\CuttingResultPriceResolver; +use App\Services\System\Setting\HomepageSettingService; use App\Settings\SocialMediaSettings; use App\Settings\SystemSettings; use App\Support\Media\MediaPresenter; @@ -17,6 +18,7 @@ class HomeController extends Controller { public function __construct( private readonly CuttingResultPriceResolver $cuttingResultPriceResolver, + private readonly HomepageSettingService $homepageSettingService, ) {} public function index(): Response @@ -60,10 +62,12 @@ public function index(): Response $settings = app(SystemSettings::class); $socialSettings = app(SocialMediaSettings::class); + $appName = $settings->app_name ?? 'DST Collection'; + return Inertia::render('Home', [ 'categories' => $categories, 'products' => $products, - 'appName' => $settings->app_name ?? 'DST Collection', + 'appName' => $appName, 'aboutApp' => $settings->about_app ?? '', 'contactEmail' => $settings->email ?? '', 'contactPhone' => $settings->phone ?? '', @@ -72,6 +76,7 @@ public function index(): Response 'instagramUrl' => $socialSettings->instagram_url ?? null, 'facebookUrl' => $socialSettings->facebook_url ?? null, 'tiktokUrl' => $socialSettings->tiktok_url ?? null, + 'homepage' => $this->homepageSettingService->homepageData(), ]); } } diff --git a/app/Http/Requests/Admin/System/Setting/HomepageSettingRequest.php b/app/Http/Requests/Admin/System/Setting/HomepageSettingRequest.php new file mode 100644 index 0000000..ca363fb --- /dev/null +++ b/app/Http/Requests/Admin/System/Setting/HomepageSettingRequest.php @@ -0,0 +1,42 @@ +user()?->can(Permission::SETTINGS_UPDATE->value) ?? false; + } + + /** + * @return array + */ + public function rules(): array + { + return [ + 'hero_image' => ['nullable', 'image', 'max:5120'], + 'about_image' => ['nullable', 'image', 'max:5120'], + 'gallery_images' => ['nullable', 'array', 'max:10'], + 'gallery_images.*' => ['image', 'max:5120'], + 'gallery_images_remove' => ['nullable', 'array'], + 'gallery_images_remove.*' => ['integer'], + ]; + } + + /** + * @return array + */ + public function attributes(): array + { + return [ + 'hero_image' => 'Foto Hero', + 'about_image' => 'Foto Tentang Kami', + 'gallery_images' => 'Foto Lookbook', + 'gallery_images.*' => 'Foto Lookbook', + ]; + } +} diff --git a/app/Models/HomepageConfiguration.php b/app/Models/HomepageConfiguration.php new file mode 100644 index 0000000..aa1ce3d --- /dev/null +++ b/app/Models/HomepageConfiguration.php @@ -0,0 +1,35 @@ +firstOrCreate(['id' => 1]); + } + + public function registerMediaCollections(): void + { + $this->addMediaCollection('hero_image')->singleFile(); + $this->addMediaCollection('about_image')->singleFile(); + $this->addMediaCollection('gallery')->singleFile(); + } +} diff --git a/app/Services/System/Setting/HomepageSettingService.php b/app/Services/System/Setting/HomepageSettingService.php new file mode 100644 index 0000000..be5e3c9 --- /dev/null +++ b/app/Services/System/Setting/HomepageSettingService.php @@ -0,0 +1,55 @@ +load('media'); + + $heroImage = MediaPresenter::first($configuration, 'hero_image'); + $aboutImage = MediaPresenter::first($configuration, 'about_image'); + $galleryImages = MediaPresenter::collection($configuration, 'gallery'); + + return [ + 'hero_image_url' => $heroImage['url'] ?? null, + 'about_image_url' => $aboutImage['url'] ?? null, + 'gallery_images' => $galleryImages, + ]; + } + + public function updateHomepage(array $validated): void + { + $configuration = HomepageConfiguration::instance(); + + if (isset($validated['hero_image']) && $validated['hero_image'] instanceof UploadedFile) { + $this->mediaService->replaceSingleFile($configuration, $validated['hero_image'], 'hero_image', 'hero-image'); + } + + if (isset($validated['about_image']) && $validated['about_image'] instanceof UploadedFile) { + $this->mediaService->replaceSingleFile($configuration, $validated['about_image'], 'about_image', 'about-image'); + } + + if (isset($validated['gallery_images'])) { + $this->mediaService->syncCollection( + $configuration, + 'gallery', + $validated['gallery_images'] ?? [], + $validated['gallery_images_remove'] ?? [], + 10, + 'gallery', + ); + } + } +} diff --git a/app/Settings/HomepageSettings.php b/app/Settings/HomepageSettings.php new file mode 100644 index 0000000..bbc52bc --- /dev/null +++ b/app/Settings/HomepageSettings.php @@ -0,0 +1,89 @@ +id(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('homepage_configurations'); + } +}; diff --git a/database/settings/2026_06_20_110000_create_homepage_settings.php b/database/settings/2026_06_20_110000_create_homepage_settings.php new file mode 100644 index 0000000..13cc1a1 --- /dev/null +++ b/database/settings/2026_06_20_110000_create_homepage_settings.php @@ -0,0 +1,89 @@ +migrator->inGroup('homepage', function (SettingsBlueprint $blueprint): void { + // Hero Section + $blueprint->add('hero_badge', 'Koleksi Segar 2026'); + $blueprint->add('hero_title_line1', 'Ekspresikan'); + $blueprint->add('hero_title_line2', 'Gaya'); + $blueprint->add('hero_title_highlight', 'Segar Anda'); + $blueprint->add('hero_description', 'Selamat datang di {app_name}. Temukan keanggunan motif batik modern dan setelan pakaian santai berkualitas premium. Dirancang khusus dengan bahan adem yang menyejukkan aktivitas harian Anda.'); + $blueprint->add('hero_cta_primary_text', 'Beli Sekarang'); + $blueprint->add('hero_cta_secondary_text', 'Tentang Kami'); + $blueprint->add('hero_image_url', 'https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=1000&auto=format&fit=crop&q=80'); + $blueprint->add('hero_bg_text_left', 'DST'); + $blueprint->add('hero_bg_text_right', 'Collection'); + + // Scroll Indicator + $blueprint->add('scroll_hashtag', '#DSTCollection'); + $blueprint->add('scroll_tagline', 'Bahan Adem & Lembut'); + + // Catalog Section + $blueprint->add('catalog_badge', 'Katalog Eksklusif'); + $blueprint->add('catalog_title', 'Koleksi Busana Pilihan'); + $blueprint->add('catalog_description', 'Gunakan kategori dan filter di bawah untuk menyesuaikan pencarian busana idaman Anda dengan mudah.'); + $blueprint->add('catalog_search_placeholder', 'Cari nama pakaian...'); + + // Deal Section + $blueprint->add('deal_badge', 'Promo Terbatas'); + $blueprint->add('deal_title', 'Penawaran Bulan Ini'); + $blueprint->add('deal_description', 'Jangan lewatkan promosi batik dan daster eksklusif kami! Dapatkan potongan harga spesial up to 25% untuk varian daster pilihan dan setelan pakaian modern. Dapatkan kenyamanan ekstra dengan bahan menyejukkan sebelum masa promo habis!'); + $blueprint->add('deal_cta_text', 'Jelajahi Produk Diskon'); + $blueprint->add('deal_images', [ + 'https://images.unsplash.com/photo-1595777457583-95e059d581b8?w=800&auto=format&fit=crop&q=80', + 'https://images.unsplash.com/photo-1572804013309-59a88b7e92f1?w=800&auto=format&fit=crop&q=80', + 'https://images.unsplash.com/photo-1515886657613-9f3515b0c78f?w=800&auto=format&fit=crop&q=80', + 'https://images.unsplash.com/photo-1539109136881-3be0616acf4b?w=800&auto=format&fit=crop&q=80', + ]); + + // Order Guide Section + $blueprint->add('order_guide_badge', 'Langkah Pemesanan'); + $blueprint->add('order_guide_title', 'Cara Melakukan Pemesanan'); + $blueprint->add('order_guide_description', 'Sistem pemesanan kami sangat mudah dan terhubung langsung via WhatsApp untuk pelayanan cepat dan personal.'); + $blueprint->add('order_steps', [ + [ + 'title' => 'Pilih Produk', + 'description' => 'Jelajahi pakaian batik dan daster favorit Anda, lalu ketuk "Lihat Detail" untuk memeriksa ukuran.', + ], + [ + 'title' => 'Pilih Varian & Harga', + 'description' => 'Tentukan varian ukuran yang diinginkan dan pilih jenis harga (Eceran, Grosir, Agen, dll.).', + ], + [ + 'title' => 'Masukkan Keranjang', + 'description' => 'Masukkan ke Keranjang Belanja untuk menampung seluruh daftar pakaian yang ingin Anda beli.', + ], + [ + 'title' => 'Kirim ke WhatsApp', + 'description' => 'Klik tombol kirim pesanan, admin kami akan merespons rincian transfer bank dan pengiriman kurir.', + ], + ]); + + // About Section + $blueprint->add('about_badge', 'Tentang Kami'); + $blueprint->add('about_title', 'DST Collection'); + $blueprint->add('about_image_url', 'https://images.unsplash.com/photo-1595777457583-95e059d581b8?w=800&auto=format&fit=crop&q=80'); + $blueprint->add('about_features', [ + 'Kain Rayon Super Tebal & Menyerap Keringat', + 'Motif Eksklusif & Tidak Pasaran', + 'Dukungan Penuh Layanan Admin Via WhatsApp', + ]); + + // Contact Section + $blueprint->add('contact_badge', 'Kontak Kami'); + $blueprint->add('contact_title', 'Ada Pertanyaan? Hubungi Kami'); + $blueprint->add('contact_description', 'Kami sangat senang mendengarkan pertanyaan Anda terkait spesifikasi produk, ketersediaan grosir, atau kemitraan. Hubungi tim admin kami melalui media di bawah.'); + $blueprint->add('contact_form_title', 'Kirim Pesan Cepat'); + + // Footer + $blueprint->add('footer_description', 'Galeri resmi {app_name}. Pilihan busana lokal premium berpotongan modern dengan kenyamanan menyejukkan.'); + $blueprint->add('footer_copyright', '© 2026 {app_name} DST Collection. Hak Cipta Dilindungi.'); + }); + } +}; diff --git a/database/settings/2026_06_20_120000_rename_deal_to_gallery_in_homepage.php b/database/settings/2026_06_20_120000_rename_deal_to_gallery_in_homepage.php new file mode 100644 index 0000000..29eeac2 --- /dev/null +++ b/database/settings/2026_06_20_120000_rename_deal_to_gallery_in_homepage.php @@ -0,0 +1,32 @@ +migrator->inGroup('homepage', function (SettingsBlueprint $blueprint): void { + // Delete old deal fields + $blueprint->delete('deal_badge'); + $blueprint->delete('deal_title'); + $blueprint->delete('deal_description'); + $blueprint->delete('deal_cta_text'); + $blueprint->delete('deal_images'); + + // Add new gallery fields + $blueprint->add('gallery_badge', 'Galeri Kami'); + $blueprint->add('gallery_title', 'Koleksi Lookbook'); + $blueprint->add('gallery_description', 'Intip koleksi lookbook kami untuk inspirasi gaya sehari-hari. Padu padan batik modern dan daster yang nyaman untuk berbagai suasana.'); + $blueprint->add('gallery_images', [ + 'https://images.unsplash.com/photo-1595777457583-95e059d581b8?w=800&auto=format&fit=crop&q=80', + 'https://images.unsplash.com/photo-1572804013309-59a88b7e92f1?w=800&auto=format&fit=crop&q=80', + 'https://images.unsplash.com/photo-1515886657613-9f3515b0c78f?w=800&auto=format&fit=crop&q=80', + 'https://images.unsplash.com/photo-1539109136881-3be0616acf4b?w=800&auto=format&fit=crop&q=80', + 'https://images.unsplash.com/photo-1496747611176-843222e1e57c?w=800&auto=format&fit=crop&q=80', + 'https://images.unsplash.com/photo-1509631179647-0177331693ae?w=800&auto=format&fit=crop&q=80', + ]); + }); + } +}; diff --git a/resources/js/components/admin/setting/HomepageSection.vue b/resources/js/components/admin/setting/HomepageSection.vue new file mode 100644 index 0000000..3323207 --- /dev/null +++ b/resources/js/components/admin/setting/HomepageSection.vue @@ -0,0 +1,116 @@ + + + diff --git a/resources/js/layouts/SettingLayout.vue b/resources/js/layouts/SettingLayout.vue index bcdad3e..d00f51b 100644 --- a/resources/js/layouts/SettingLayout.vue +++ b/resources/js/layouts/SettingLayout.vue @@ -1,5 +1,5 @@