feat: Add new Livewire contact us page with corresponding route, view, and styling updates.

This commit is contained in:
Yoga Pangestu 2026-01-06 14:21:33 +07:00
parent b5d27c6931
commit 01e95e05ef
7 changed files with 244 additions and 5 deletions

View File

@ -0,0 +1,78 @@
<?php
namespace App\Livewire\Home;
use App\Models\Contact;
use App\Settings\GeneralSettings;
use Livewire\Attributes\Title;
use Livewire\Component;
#[Title('Hubungi Kami')]
class ContactUs extends Component
{
public string $name = '';
public string $email = '';
public ?string $subject = null;
public string $message = '';
public string $pageTitle = 'Hubungi Kami';
public string $pageDescription = 'Kami siap membantu dan menjawab pertanyaan Anda.';
public function rules()
{
return [
'name' => ['required', 'max:100'],
'email' => ['required', 'email', 'max:254'],
'subject' => 'nullable',
'message' => 'required',
];
}
public function validationAttributes()
{
return [
'name' => 'name',
'email' => 'alamat surel',
'subject' => 'subyek',
'message' => 'pesan',
];
}
public function save()
{
$this->validate();
// Anti-spam: check if this email has submitted in the last 24 hours
$exists = Contact::where('email', $this->email)
->where('created_at', '>=', now()->subDay())
->exists();
if ($exists) {
$this->addError('email', 'Maaf, Anda hanya dapat mengirim pesan sekali dalam 24 jam.');
return;
}
Contact::create([
'name' => $this->name,
'email' => $this->email,
'subject' => $this->subject,
'message' => $this->message,
]);
$this->reset(['name', 'email', 'subject', 'message']);
session()->flash('success', 'Pesan Anda telah terkirim!');
}
public function render(GeneralSettings $settings)
{
return view('livewire.home.contact-us', [
'settings' => $settings,
]);
}
}

View File

@ -2607,10 +2607,10 @@ .magic-round-cursor #ball-cursor:after {
display: none;
}
/* Anime animation */
[data-anime] {
/* [data-anime] {
opacity: 0;
transition: none;
}
} */
[data-anime].appear {
opacity: 1;
}

View File

@ -2,7 +2,7 @@
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<title>{{ $title }} | Simedkom</title>
<title>{{ $title ?? 'Simedkom' }}</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="author" content="Diskominfo Purwakarta">

View File

@ -24,6 +24,16 @@ class="col-12 col-xl-4 col-lg-4 col-sm-6 last-paragraph-no-margin text-xl-start
@if ($general->address)
<p class="lh-22 mb-15px">{{ $general->address }}</p>
@endif
<div class="lh-22 mb-15px">
@if ($general->site_email)
<a href="mailto:{{ $general->site_email }}" class="d-block"><i
class="bi bi-envelope me-10px"></i>{{ $general->site_email }}</a>
@endif
@if ($general->site_phone)
<a href="tel:{{ $general->site_phone }}" class="d-block"><i
class="bi bi-telephone me-10px"></i>{{ $general->site_phone }}</a>
@endif
</div>
<div class="elements-social social-icon-style-02">
<ul class="medium-icon dark">
@if ($social->facebook)
@ -75,7 +85,7 @@ class="col-12 col-xl-4 col-lg-4 col-sm-6 last-paragraph-no-margin text-xl-start
<a wire:navigate href="{{ route('about-us') }}">Tentang Kami</a>
</li>
<li>
<a href="{{ route('home') }}#contact">Kontak</a>
<a wire:navigate href="{{ route('contact-us') }}">Kontak</a>
</li>
</ul>
</div>

View File

@ -50,7 +50,9 @@ class="nav-link {{ Route::is('news.index') || Route::is('news.show') ? 'active'
<a wire:navigate href="{{ route('announcement') }}"
class="nav-link {{ Route::is('announcement') ? 'active' : '' }}">Pengumuman</a>
</li>
<li class="nav-item"><a href="{{ route('home') }}#contact" class="nav-link">Kontak</a>
<li class="nav-item">
<a wire:navigate href="{{ route('contact-us') }}"
class="nav-link {{ Route::is('contact-us') ? 'active' : '' }}">Kontak</a>
</li>
</ul>
</div>

View File

@ -0,0 +1,145 @@
<div>
<section class="pt-0 cover-background ipad-top-space-margin sm-pb-0"
style="background-image:
linear-gradient(rgba(0,0,0,0.45), rgba(0,0,0,0.45)),
url('https://i0.wp.com/infoka.id/wp-content/uploads/2024/04/Diskominfo-Purwakarta.jpg?resize=1000%2C600&ssl=1');">
<div class="shape-image-animation bottom-0 p-0 w-100 d-none d-md-block">
<svg xmlns="http://www.w3.org/2000/svg" widht="3000" height="400" viewBox="0 180 2500 200" fill="#ffffff">
<path class="st1" d="M 0 250 C 1200 400 1200 50 3000 250 L 3000 550 L 0 550 L 0 250">
<animate attributeName="d" dur="5s"
values="M 0 250 C 1200 400 1200 50 3000 250 L 3000 550 L 0 550 L 0 250;
M 0 250 C 400 50 400 400 3000 250 L 3000 550 L 0 550 L 0 250;
M 0 250 C 1200 400 1200 50 3000 250 L 3000 550 L 0 550 L 0 250"
repeatCount="indefinite" />
</path>
</svg>
</div>
<div class="container">
<div class="row align-items-center justify-content-center h-500px sm-h-300px">
<div class="col-12 col-lg-6 col-md-10 position-relative text-center page-title-extra-large d-flex flex-wrap flex-column align-items-center justify-content-center"
data-anime='{ "el": "childs", "translateY": [30, 0], "opacity": [0,1], "duration": 600, "delay": 0, "staggervalue": 300, "easing": "easeOutQuad" }'>
<span
class="ps-25px pe-25px pt-5px pb-5px mb-15px text-uppercase text-white fs-12 ls-1px fw-600 border-radius-100px bg-gradient-dark-gray-transparent d-flex"><i
class="bi bi-megaphone text-white icon-small me-10px"></i>{{ $pageTitle }}</span>
<h5 class="mb-20px text-white fw-600 ls-minus-1px">{{ $pageDescription }}</h5>
</div>
</div>
</div>
</section>
<!-- start section -->
<section>
<div class="container">
<div class="row mb-8">
<div class="col-xl-5 col-lg-6 md-mb-50px"
data-anime='{ "el": "childs", "translateX": [-50, 0], "opacity": [0,1], "duration": 1200, "delay": 0, "staggervalue": 150, "easing": "easeOutQuad" }'>
<div class="bg-white border-radius-6px box-shadow-quadruple-large p-10 ps-12 pe-12 lg-ps-8 lg-pe-8 h-100 d-flex flex-wrap flex-column justify-content-center"
data-anime='{ "el": "childs", "translateY": [0, 0], "opacity": [0,1], "duration": 1200, "delay": 0, "staggervalue": 150, "easing": "easeOutQuad" }'>
<span
class="ps-25px pe-25px mb-20px text-uppercase text-base-color fs-12 lh-40 fw-700 border-radius-100px bg-gradient-very-light-gray-transparent d-inline-flex align-self-start"><i
class="bi bi-chat-square-dots fs-16 me-5px"></i>Mari bekerjasama</span>
<h4 class="text-dark-gray ls-minus-1px fw-700 mb-15px">Siap membantu Anda!</h4>
<p class="w-85 sm-w-100">Kami di sini untuk membantu dan menjawab pertanyaan apa pun yang Anda
miliki.</p>
<div class="row row-cols-1 row-cols-sm-2">
<div class="col last-paragraph-no-margin mb-25px">
<p>Hubungi langsung?</p>
<a href="tel:{{ $settings->site_phone }}"
class="text-dark-gray fw-600">{{ $settings->site_phone }}</a>
</div>
<div class="col last-paragraph-no-margin mb-25px">
<p>Butuh bantuan?</p>
<a href="mailto:{{ $settings->site_email }}"
class="text-dark-gray fw-600">{{ $settings->site_email }}</a>
</div>
</div>
<div class="last-paragraph-no-margin">
<p>Kunjungi kami?</p>
@if ($settings->address)
<span class="text-dark-gray fw-600 d-block mb-10px">{{ $settings->address }}</span>
@endif
</div>
</div>
</div>
<div class="col-lg-6 offset-xl-1 md-mb-50px sm-mb-0">
<div
data-anime='{ "el": "childs", "translateX": [50, 0], "opacity": [0,1], "duration": 1200, "delay": 0, "staggervalue": 150, "easing": "easeOutQuad" }'>
<h3 class="text-dark-gray ls-minus-2px fw-700">Ada yang bisa kami bantu?</h3>
</div>
@if (session()->has('success'))
<div class="alert alert-success border-radius-4px">
{{ session('success') }}
</div>
@endif
<form wire:submit="save" class="contact-form-style-03">
<label for="name" class="form-label fs-13 text-uppercase text-dark-gray fw-700 mb-0">
Nama Lengkap <span class="text-danger">*</span></label>
<div class="position-relative form-group mb-20px">
<input
class="fs-15 ps-0 border-radius-0px border-color-dark-gray bg-transparent form-control @error('name') is-invalid @enderror"
id="name" type="text" wire:model="name" placeholder="Masukkan nama lengkap Anda"
autocomplete="off" />
@error('name')
<span class="text-danger fs-12">{{ $message }}</span>
@enderror
</div>
<label for="email" class="form-label fs-13 text-uppercase text-dark-gray fw-700 mb-0">
Alamat surel <span class="text-danger">*</span></label>
<div class="position-relative form-group mb-20px">
<input
class="fs-15 ps-0 border-radius-0px border-color-dark-gray bg-transparent form-control @error('email') is-invalid @enderror"
id="email" type="email" wire:model="email"
placeholder="Masukkan alamat surel Anda" autocomplete="off" />
@error('email')
<span class="text-danger fs-12">{{ $message }}</span>
@enderror
</div>
<label for="subject"
class="form-label fs-13 text-uppercase text-dark-gray fw-700 mb-0">Subjek</label>
<div class="position-relative form-group mb-20px">
<input
class="fs-15 ps-0 border-radius-0px border-color-dark-gray bg-transparent form-control @error('subject') is-invalid @enderror"
id="subject" type="text" wire:model="subject" placeholder="Subjek pesan Anda"
autocomplete="off" />
@error('subject')
<span class="text-danger fs-12">{{ $message }}</span>
@enderror
</div>
<label for="message" class="form-label fs-13 text-uppercase text-dark-gray fw-700 mb-0">
Pesan Anda <span class="text-danger">*</span></label>
<div class="position-relative form-group form-textarea mb-0">
<textarea
class="fs-15 ps-0 border-radius-0px border-color-dark-gray bg-transparent form-control @error('message') is-invalid @enderror"
id="message" wire:model="message" placeholder="Tuliskan pesan Anda di sini" rows="3"></textarea>
@error('message')
<span class="text-danger fs-12">{{ $message }}</span>
@enderror
</div>
<div class="row mt-25px align-items-center">
<div class="col-xl-7 col-lg-12 col-sm-7 lg-mb-30px md-mb-0">
<p class="mb-0 fs-14 lh-22 text-center text-sm-start">Kami tidak akan pernah
mengumpulkan informasi tentang Anda tanpa persetujuan eksplisit dari Anda.</p>
</div>
<div
class="col-xl-5 col-lg-12 col-sm-5 text-center text-sm-end text-lg-start text-xl-end xs-mt-25px">
<button class="btn btn-dark-gray btn-medium btn-round-edge btn-box-shadow"
type="submit" wire:loading.attr="disabled">
<span wire:loading.remove>Kirim pesan</span>
<span wire:loading>Mengirim...</span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- end section -->
</div>

View File

@ -3,6 +3,7 @@
use App\Http\Middleware\TrackVisitor;
use App\Livewire\Home\AboutUs;
use App\Livewire\Home\Announcement;
use App\Livewire\Home\ContactUs;
use App\Livewire\Home\Index;
use App\Livewire\Home\News\Index as NewsIndex;
use App\Livewire\Home\News\Show as NewsShow;
@ -10,6 +11,7 @@
Route::middleware([TrackVisitor::class])->group(function () {
Route::get('/', Index::class)->name('home');
Route::get('/about-us', AboutUs::class)->name('about-us');
Route::prefix('news')->group(function () {
@ -18,4 +20,6 @@
});
Route::get('/announcements', Announcement::class)->name('announcement');
Route::get('/contact-us', ContactUs::class)->name('contact-us');
});