batas waktu

This commit is contained in:
hildaaaevs 2025-06-10 15:54:13 +07:00
parent 4cd4abccd7
commit f5f2056e86
8 changed files with 122 additions and 71 deletions

View File

@ -35,6 +35,7 @@
use Barryvdh\DomPDF\Facade\Pdf;
use Filament\Forms\Components\Modal;
use Filament\Forms\Components\FileUpload;
use Illuminate\Support\Facades\Storage;
class ReservasiiResource extends Resource
{
@ -97,6 +98,12 @@ public static function form(Form $form): Form
->imageCropAspectRatio('16:9')
->imageResizeTargetWidth('1920')
->imageResizeTargetHeight('1080')
->preserveFilenames()
->downloadable()
->openable()
->deleteUploadedFileUsing(function ($file) {
Storage::disk('public')->delete($file);
})
->columnSpanFull(),
])
])->columnSpan(1),
@ -216,8 +223,7 @@ public static function table(Table $table): Table
return $table
->columns([
Tables\Columns\TextColumn::make('nama')
->label('Nama')
->searchable(),
->label('Nama'),
Tables\Columns\TextColumn::make('tanggal')
->date('d F Y')
@ -229,8 +235,7 @@ public static function table(Table $table): Table
Tables\Columns\TextColumn::make('detail.paketFoto.nama_paket_foto')
->label('Paket Foto')
->listWithLineBreaks()
->searchable(),
->listWithLineBreaks(),
Tables\Columns\TextColumn::make('total')
->money('IDR'),

View File

@ -27,12 +27,21 @@ protected function getHeaderActions(): array
//}
public function getTabs(): array{
return[
null => \Filament\Resources\Components\Tab::make('Semua'),
'Paket Pasangan' => \Filament\Resources\Components\Tab::make()->query(fn($query) => $query->whereRelation('detail.paketFoto', 'nama_paket_foto', 'Paket Pasangan')),
'Paket 5 orang' => \Filament\Resources\Components\Tab::make()->query(fn($query) => $query->whereRelation('detail.paketFoto', 'nama_paket_foto', 'Paket 5 Orang')),
'Widebox Couple' => \Filament\Resources\Components\Tab::make()->query(fn($query) => $query->whereRelation('detail.paketFoto', 'nama_paket_foto', 'Widebox Couple')),
'Widebox Group' => \Filament\Resources\Components\Tab::make()->query(fn($query) => $query->whereRelation('detail.paketFoto', 'nama_paket_foto', 'Widebox Group')),
$paketFotos = \App\Models\PaketFoto::orderBy('nama_paket_foto')->get();
$tabs = [
null => \Filament\Resources\Components\Tab::make('Semua Paket')
->badge(fn () => \App\Models\Reservasii::count())
->icon('heroicon-o-photo'),
];
foreach ($paketFotos as $paketFoto) {
$tabs[$paketFoto->id] = \Filament\Resources\Components\Tab::make($paketFoto->nama_paket_foto)
->query(fn($query) => $query->whereRelation('detail.paketFoto', 'nama_paket_foto', $paketFoto->nama_paket_foto))
->badge(fn () => \App\Models\Reservasii::whereRelation('detail.paketFoto', 'nama_paket_foto', $paketFoto->nama_paket_foto)->count())
->icon('heroicon-o-camera');
}
return $tabs;
}
}

View File

@ -118,8 +118,9 @@ public function updateUnavailableTimes()
{
if ($this->tanggal) {
// Ambil waktu yang sudah dipesan dari database untuk tanggal yang dipilih
// dan paket foto yang sama
// dan paket foto yang sama, hanya yang statusnya approved
$this->bookedTimes = Reservasii::where('tanggal', $this->tanggal)
->where('status_pembayaran', 'approved') // Hanya ambil yang sudah approved
->whereHas('detail', function($query) {
$query->where('paket_foto_id', $this->paketfoto->id);
})

View File

@ -6,6 +6,8 @@
use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\Attributes\Title;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
#[Title('Upload Bukti Pembayaran - SiKolaself')]
class UploadBuktiPembayaran extends Component
@ -15,6 +17,8 @@ class UploadBuktiPembayaran extends Component
public $booking;
public $bukti_pembayaran;
public $bookingId;
public $timeLeft;
public $isExpired = false;
public function mount($id)
{
@ -32,10 +36,48 @@ public function mount($id)
if ($this->booking->status_pembayaran === 'approved') {
return redirect()->route('booking.success', $this->booking->id);
}
// Check if booking is expired
$createdAt = Carbon::parse($this->booking->created_at);
$expiryTime = $createdAt->addMinutes(5);
if (Carbon::now()->gt($expiryTime)) {
// Update status pembayaran menjadi rejected
$this->booking->update(['status_pembayaran' => 'rejected']);
// Hapus reservasi ini dari daftar waktu yang tidak tersedia
DB::table('unavailable_times')
->where('tanggal', $this->booking->tanggal)
->where('waktu', $this->booking->waktu)
->where('reservasii_id', $this->booking->id)
->delete();
$this->isExpired = true;
session()->flash('error', 'Waktu upload bukti pembayaran telah habis. Reservasi ditolak.');
return redirect()->route('histori');
}
$this->timeLeft = Carbon::now()->diffInSeconds($expiryTime);
}
public function getTimeLeftProperty()
{
if ($this->isExpired) {
return 0;
}
$createdAt = Carbon::parse($this->booking->created_at);
$expiryTime = $createdAt->addMinutes(5);
return max(0, Carbon::now()->diffInSeconds($expiryTime));
}
public function uploadBuktiPembayaran()
{
if ($this->isExpired) {
session()->flash('error', 'Waktu upload bukti pembayaran telah habis.');
return redirect()->route('histori');
}
$this->validate([
'bukti_pembayaran' => 'required|image|max:2048', // max 2MB
], [

View File

@ -25,7 +25,8 @@ class Reservasii extends Model
protected $casts = [
'tanggal' => 'date',
'waktu' => 'datetime',
'total' => 'decimal:2'
'total' => 'decimal:2',
'bukti_pembayaran' => 'array'
];
public function user()

View File

@ -1,65 +1,41 @@
<div class="w-full max-w-[85rem] max-h-screen py-10 px-4 sm:px-6 lg:px-8 mx-auto">
<section class="overflow-hidden bg-white py-11 font-poppins dark:bg-gray-800">
<div class="w-full max-w-[85rem] py-10 px-4 sm:px-6 lg:px-8 mx-auto">
<section class="overflow-hidden bg-white py-6 sm:py-11 font-poppins dark:bg-gray-800">
<div class="max-w-6xl px-4 py-4 mx-auto lg:py-8 md:px-6">
<div class="flex flex-wrap -mx-4">
<div class="flex flex-col md:flex-row -mx-4">
<!-- Bagian Gambar -->
<div class="w-full mb-8 md:w-1/2 md:mb-0" x-data="{ mainImage: '{{ url('storage', $paketfoto->gambar) }}' }">
<div class="sticky top-0 z-50 overflow-hidden ">
<div class="aspect-[4/3] ">
<img x-bind:src="mainImage" alt="" class="object-cover w-full lg:h-full ">
<div class="sticky top-0 z-50 overflow-hidden">
<div class="aspect-[4/3]">
<img x-bind:src="mainImage" alt="{{ $paketfoto->nama_paket_foto }}" class="object-cover w-full h-full rounded-lg shadow-lg">
</div>
<div class="flex-wrap hidden md:flex ">
<div class="flex-wrap hidden md:flex mt-4">
<div class="w-1/2 p-2 sm:w-1/4" x-on:click="mainImage='https://m.media-amazon.com/images/I/71f5Eu5lJSL._SX679_.jpg'">
<alt="" class="object-cover w-full lg:h-20 cursor-pointer hover:border hover:border-blue-500">
</div>
</div>
<div class="px-6 pb-6 mt-6 border-t border-gray-300 dark:border-gray-400 ">
<div class="flex flex-wrap items-center mt-6">
{{-- <span class="mr-2">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-4 h-4 text-gray-700 dark:text-gray-400 bi bi-truck" viewBox="0 0 16 16">
<path d="M0 3.5A1.5 1.5 0 0 1 1.5 2h9A1.5 1.5 0 0 1 12 3.5V5h1.02a1.5 1.5 0 0 1 1.17.563l1.481 1.85a1.5 1.5 0 0 1 .329.938V10.5a1.5 1.5 0 0 1-1.5 1.5H14a2 2 0 1 1-4 0H5a2 2 0 1 1-3.998-.085A1.5 1.5 0 0 1 0 10.5v-7zm1.294 7.456A1.999 1.999 0 0 1 4.732 11h5.536a2.01 2.01 0 0 1 .732-.732V3.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .294.456zM12 10a2 2 0 0 1 1.732 1h.768a.5.5 0 0 0 .5-.5V8.35a.5.5 0 0 0-.11-.312l-1.48-1.85A.5.5 0 0 0 13.02 6H12v4zm-9 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm9 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z">
</path>
</svg>
</span>
<h2 class="text-lg font-bold text-gray-700 dark:text-gray-400">Free Shipping</h2>--}}
{{-- <img src="https://m.media-amazon.com/images/I/71f5Eu5lJSL._SX679_.jpg" alt="Thumbnail" class="object-cover w-full h-20 rounded cursor-pointer hover:border-2 hover:border-blue-500">--}}
</div>
</div>
</div>
</div>
<div class="w-full px-4 md:w-1/2 ">
<!-- Bagian Informasi -->
<div class="w-full px-4 md:w-1/2">
<div class="lg:pl-20">
<div class="mb-8 ">
<h2 class="max-w-xl mb-6 text-2xl font-bold dark:text-gray-400 md:text-4xl">
{{ $paketfoto->nama_paket_foto }}
</h2>
<p class="inline-block mb-6 text-4xl font-bold text-gray-700 dark:text-gray-400 ">
<span>
{{ Number::currency($paketfoto->harga_paket_foto, 'IDR') }}
</span>
{{-- <span class="text-base font-normal text-gray-500 line-through dark:text-gray-400">$1800.99</span> --}}
<div class="mb-8">
<h2 class="max-w-xl mb-4 text-xl sm:text-2xl md:text-4xl font-bold dark:text-gray-400">
{{ $paketfoto->nama_paket_foto }}
</h2>
<p class="inline-block mb-6 text-2xl sm:text-3xl md:text-4xl font-bold text-gray-700 dark:text-gray-400">
<span>{{ Number::currency($paketfoto->harga_paket_foto, 'IDR') }}</span>
</p>
<p class="max-w-md text-sm sm:text-base text-gray-700 dark:text-gray-400">
{{ $paketfoto->fasilitas }}
</p>
<p class="max-w-md text-gray-700 dark:text-gray-400">
{{ $paketfoto->fasilitas }}
</p>
</div>
<div class="w-32 mb-8 ">
<div class="flex flex-col items-start">
<a href="{{ route('booking', ['id' => $paketfoto->id]) }}" class="px-6 py-3 bg-blue-500 rounded-md text-white hover:bg-blue-600 dark:bg-blue-500 dark:hover:bg-blue-700">
Reservasi
</a>
</div>
{{-- <label for="" class="w-full pb-1 text-xl font-semibold text-gray-700 border-b border-blue-300 dark:border-gray-600 dark:text-gray-400">Quantity</label>
<div class="relative flex flex-row w-full h-10 mt-6 bg-transparent rounded-lg"> --}}
{{-- <button class="w-20 h-full text-gray-600 bg-gray-300 rounded-l outline-none cursor-pointer dark:hover:bg-gray-700 dark:text-gray-400 hover:text-gray-700 dark:bg-gray-900 hover:bg-gray-400">
<span class="m-auto text-2xl font-thin">-</span>
</button>
<input type="number" readonly class="flex items-center w-full font-semibold text-center text-gray-700 placeholder-gray-700 bg-gray-300 outline-none dark:text-gray-400 dark:placeholder-gray-400 dark:bg-gray-900 focus:outline-none text-md hover:text-black" placeholder="1">
<button class="w-20 h-full text-gray-600 bg-gray-300 rounded-r outline-none cursor-pointer dark:hover:bg-gray-700 dark:text-gray-400 dark:bg-gray-900 hover:text-gray-700 hover:bg-gray-400">
<span class="m-auto text-2xl font-thin">+</span>
</button> --}}
<div class="w-full sm:w-32 mb-8">
<div class="flex flex-col items-start">
<a href="{{ route('booking', ['id' => $paketfoto->id]) }}"
class="w-full sm:w-auto px-6 py-3 text-center bg-blue-500 rounded-md text-white hover:bg-blue-600 dark:bg-blue-500 dark:hover:bg-blue-700 transition duration-300">
Reservasi
</a>
</div>
</div>
</div>

View File

@ -2,9 +2,26 @@
<div class="flex items-center font-poppins">
<div class="w-full px-4 py-4 mx-auto bg-white border rounded-lg shadow-sm">
<div>
<h1 class="mb-6 text-xl font-semibold text-gray-700">
Upload Bukti Pembayaran
</h1>
<div class="flex justify-between items-center mb-6">
<h1 class="text-xl font-semibold text-gray-700">
Upload Bukti Pembayaran
</h1>
<div class="text-right">
<p class="text-sm text-gray-600">Sisa Waktu</p>
<p class="font-medium text-red-600"
x-data="{
timeLeft: {{ $this->timeLeft }},
formatTime(seconds) {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = Math.floor(seconds % 60);
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
}
}"
x-init="setInterval(() => { if(timeLeft > 0) timeLeft--; }, 1000)"
x-text="formatTime(timeLeft)">
</p>
</div>
</div>
<!-- Informasi Pelanggan -->
<div class="mb-6 p-4 bg-gray-50 rounded-lg">
@ -61,8 +78,8 @@
<div>
<p class="text-sm text-gray-600">Jumlah yang Harus Dibayar</p>
<p class="font-medium">
@if($booking->tipe_pembayaran === 'dp')
Rp {{ number_format(max(20000, $booking->total * 0.3), 0, ',', '.') }}
@if(strtolower($booking->tipe_pembayaran) === 'dp')
Rp {{ number_format(20000, 0, ',', '.') }}
<span class="text-xs text-gray-500 block">(Minimal 30% atau Rp 20.000)</span>
@else
Rp {{ number_format($booking->total, 0, ',', '.') }}
@ -73,8 +90,8 @@
@if($booking->metode_pembayaran === 'transfer')
<div class="md:col-span-2">
<p class="text-sm text-gray-600">Nomor Rekening</p>
<p class="font-medium">1234567890 (Bank BCA)</p>
<p class="text-xs text-gray-500">a.n. Nama Studio Foto</p>
<p class="font-medium">116101022592507 (Bank BRI)</p>
<p class="text-xs text-gray-500">a.n. Adella Novita</p>
</div>
@endif
</div>

View File

@ -71,7 +71,7 @@
<td>{{ $index + 1 }}</td>
<td>{{ $reservasi->nama }}</td>
<td>{{ $reservasi->tanggal->format('d F Y') }}</td>
<td>{{ $reservasi->waktu }}</td>
<td>{{ \Carbon\Carbon::parse($reservasi->waktu)->format('H:i') }}</td>
<td>
@foreach($reservasi->detail as $detail)
{{ $detail->paketFoto->nama_paket_foto }}<br>