Lupa Password
This commit is contained in:
parent
f5f2056e86
commit
0657270b87
|
@ -79,7 +79,9 @@ public static function form(Form $form): Form
|
|||
'full' => 'Full',
|
||||
'dp' => 'DP',
|
||||
])
|
||||
->required(),
|
||||
->required()
|
||||
->default('full')
|
||||
->inline(),
|
||||
Select::make('status_pembayaran')
|
||||
->label('Status Pembayaran')
|
||||
->options([
|
||||
|
@ -94,10 +96,6 @@ public static function form(Form $form): Form
|
|||
->image()
|
||||
->directory('bukti-pembayaran')
|
||||
->visibility('public')
|
||||
->imageResizeMode('cover')
|
||||
->imageCropAspectRatio('16:9')
|
||||
->imageResizeTargetWidth('1920')
|
||||
->imageResizeTargetHeight('1080')
|
||||
->preserveFilenames()
|
||||
->downloadable()
|
||||
->openable()
|
||||
|
@ -171,7 +169,7 @@ public static function form(Form $form): Form
|
|||
'cream' => 'Cream',
|
||||
'spotlight' => 'Spotlight'
|
||||
])
|
||||
->columnSpan(2), // Lebih kecil karena opsinya sedikit
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('jumlah')
|
||||
->numeric()
|
||||
|
@ -208,11 +206,33 @@ public static function form(Form $form): Form
|
|||
foreach ($repeaters as $key => $repeater){
|
||||
$total += $get("detail.{$key}.total_harga");
|
||||
}
|
||||
|
||||
// Hitung diskon jika ada promo
|
||||
$diskon = 0;
|
||||
if ($promoId = $get('promo_id')) {
|
||||
$promo = \App\Models\Promo::find($promoId);
|
||||
if ($promo && $promo->aktif) {
|
||||
if ($promo->tipe === 'fix') {
|
||||
$diskon = $promo->diskon;
|
||||
} else if ($promo->tipe === 'persen') {
|
||||
$diskon = ($total * $promo->diskon) / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$totalSetelahDiskon = $total - $diskon;
|
||||
$set('total', $total);
|
||||
return 'Rp ' . number_format($total, 0, ',', '.');
|
||||
$set('diskon', $diskon);
|
||||
$set('total_setelah_diskon', $totalSetelahDiskon);
|
||||
|
||||
return 'Rp ' . number_format($totalSetelahDiskon, 0, ',', '.');
|
||||
}),
|
||||
Hidden::make('total')
|
||||
->default(0)
|
||||
->default(0),
|
||||
Hidden::make('diskon')
|
||||
->default(0),
|
||||
Hidden::make('total_setelah_diskon')
|
||||
->default(0),
|
||||
])->columnSpanFull(),
|
||||
])
|
||||
]);
|
||||
|
@ -221,6 +241,7 @@ public static function form(Form $form): Form
|
|||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->defaultSort('created_at', 'desc')
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('nama')
|
||||
->label('Nama'),
|
||||
|
|
|
@ -23,18 +23,17 @@ public function save(){
|
|||
]);
|
||||
|
||||
// save to database
|
||||
$user = User::create([
|
||||
User::create([
|
||||
'name' => $this->name,
|
||||
'email' => $this->email,
|
||||
'password' => Hash::make($this->password)
|
||||
]);
|
||||
|
||||
// login user
|
||||
auth()->login($user);
|
||||
|
||||
// redirect to home page
|
||||
return redirect()->intended();
|
||||
// set success message
|
||||
session()->flash('success', 'Registrasi berhasil! Silakan login untuk melanjutkan.');
|
||||
|
||||
// redirect to login page
|
||||
return redirect()->route('login');
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
|
|
|
@ -3,9 +3,58 @@
|
|||
namespace App\Livewire\Auth;
|
||||
|
||||
use Livewire\Component;
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\User;
|
||||
|
||||
class ResetPasswordPage extends Component
|
||||
{
|
||||
public $token;
|
||||
#[Url]
|
||||
public $email;
|
||||
public $password;
|
||||
public $password_confirmation;
|
||||
|
||||
public function mount($token = null)
|
||||
{
|
||||
$this->token = $token ?? request()->route('token');
|
||||
$this->email = request()->query('email');
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate([
|
||||
'email' => 'required|email|exists:users,email',
|
||||
'password' => 'required|min:6|confirmed',
|
||||
]);
|
||||
|
||||
$status = Password::reset(
|
||||
[
|
||||
'email' => $this->email,
|
||||
'password' => $this->password,
|
||||
'password_confirmation' => $this->password_confirmation,
|
||||
'token' => $this->token,
|
||||
],
|
||||
function (User $user, string $password) {
|
||||
$password = $this->password;
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($password)
|
||||
])->setRememberToken(Str::random(60));
|
||||
$user->save();
|
||||
event(new PasswordReset($user));
|
||||
}
|
||||
);
|
||||
|
||||
if ($status == Password::PASSWORD_RESET) {
|
||||
session()->flash('success', 'Password berhasil diubah!');
|
||||
return redirect('/login');
|
||||
} else {
|
||||
session()->flash('error', 'Terjadi kesalahan. Silakan coba lagi.');
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.auth.reset-password-page');
|
||||
|
|
|
@ -67,7 +67,7 @@ public function getTimeLeftProperty()
|
|||
}
|
||||
|
||||
$createdAt = Carbon::parse($this->booking->created_at);
|
||||
$expiryTime = $createdAt->addMinutes(5);
|
||||
$expiryTime = $createdAt->addMinutes(1);
|
||||
return max(0, Carbon::now()->diffInSeconds($expiryTime));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,13 @@
|
|||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use App\Notifications\ReservasiApproved;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class Reservasii extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use HasFactory, Notifiable;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
|
@ -24,9 +27,8 @@ class Reservasii extends Model
|
|||
|
||||
protected $casts = [
|
||||
'tanggal' => 'date',
|
||||
'waktu' => 'datetime',
|
||||
'total' => 'decimal:2',
|
||||
'bukti_pembayaran' => 'array'
|
||||
'waktu' => 'string',
|
||||
'total' => 'decimal:2'
|
||||
];
|
||||
|
||||
public function user()
|
||||
|
@ -45,6 +47,21 @@ public function paketFoto()
|
|||
{
|
||||
return $this->belongsTo(PaketFoto::class);
|
||||
}
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::updated(function ($reservasi) {
|
||||
if ($reservasi->isDirty('status_pembayaran') && $reservasi->status_pembayaran === 'approved') {
|
||||
Log::info('Mencoba mengirim notifikasi email untuk reservasi ID: ' . $reservasi->id);
|
||||
try {
|
||||
$reservasi->notify(new ReservasiApproved($reservasi));
|
||||
Log::info('Notifikasi email berhasil dikirim untuk reservasi ID: ' . $reservasi->id);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Gagal mengirim notifikasi email: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,4 +54,9 @@ public function canAccessPanel(Panel $panel): bool
|
|||
{
|
||||
return $this->email == 'admin@gmail.com';
|
||||
}
|
||||
|
||||
public function routeNotificationForMail()
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use App\Models\Reservasii;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ReservasiApproved extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
protected $reservasi;
|
||||
|
||||
public function __construct(Reservasii $reservasi)
|
||||
{
|
||||
$this->reservasi = $reservasi;
|
||||
Log::info('Notifikasi ReservasiApproved dibuat untuk reservasi ID: ' . $reservasi->id);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
Log::info('Mengirim notifikasi via email untuk reservasi ID: ' . $this->reservasi->id);
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
Log::info('Menyiapkan email untuk reservasi ID: ' . $this->reservasi->id);
|
||||
return (new MailMessage)
|
||||
->subject('Reservasi Anda Telah Disetujui')
|
||||
->greeting('Halo ' . $this->reservasi->nama . '!')
|
||||
->line('Reservasi Anda dengan nomor ID: ' . $this->reservasi->id . ' telah disetujui.')
|
||||
->line('Detail Reservasi:')
|
||||
->line('Tanggal: ' . $this->reservasi->tanggal->format('d F Y'))
|
||||
->line('Waktu: ' . $this->reservasi->waktu)
|
||||
->line('Total Pembayaran: Rp ' . number_format($this->reservasi->total, 0, ',', '.'))
|
||||
->line('Silahkan datang sesuai dengan jadwal yang telah ditentukan.')
|
||||
->line('Terima kasih telah memilih layanan kami!')
|
||||
->salutation('Salam, Tim SiKolaself');
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@ public function up(): void
|
|||
$table->string('metode_pembayaran');
|
||||
$table->string('bukti_pembayaran')->nullable();
|
||||
$table->enum('status_pembayaran', ['pending', 'approved', 'rejected'])->default('pending');
|
||||
$table->decimal('diskon', 10, 2)->default(0);
|
||||
$table->decimal('total_setelah_diskon', 10, 2)->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<div class="grid gap-y-4">
|
||||
<!-- Form Group -->
|
||||
<div>
|
||||
<label for="email" class="block text-sm mb-2 dark:text-white">Email address</label>
|
||||
<label for="email" class="block text-sm mb-2 dark:text-white">Alamat Email</label>
|
||||
<div class="relative">
|
||||
<input type="email" id="email" wire:model="email" class="py-3 px-4 block w-full border border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500
|
||||
disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400 dark:focus:ring-gray-600" aria-describedby="email-error">
|
||||
|
|
|
@ -13,6 +13,12 @@
|
|||
<h1 class="text-2xl font-bold text-center text-gray-800 mb-6">Login</h1>
|
||||
<form wire:submit.prevent="save" class="space-y-6">
|
||||
|
||||
@if (session('success'))
|
||||
<div class="bg-green-500 text-white p-4 rounded-lg text-sm mb-4" role="alert">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (session('error'))
|
||||
<div class="bg-red-500 text-white p-4 rounded-lg text-sm mb-4" role="alert">
|
||||
{{ session('error') }}
|
||||
|
@ -32,7 +38,7 @@
|
|||
<div>
|
||||
<div class="flex justify-between items-center mb-1">
|
||||
<label for="password" class="block text-sm font-medium text-gray-700 dark:text-white">Password</label>
|
||||
{{--<a href="/forgot" class="text-sm text-blue-600 hover:underline">Lupa password?</a>--}}
|
||||
<a href="/forgot" class="text-sm text-blue-600 hover:underline">Lupa password?</a>
|
||||
</div>
|
||||
<input type="password" id="password" wire:model="password" class="py-3 px-4 block w-full border border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400 dark:focus:ring-gray-600">
|
||||
@error('password')
|
||||
|
@ -45,6 +51,5 @@
|
|||
|
||||
<p class="text-sm text-center text-gray-600">Belum punya akun? <a href="/register" class="text-blue-600 hover:underline">Daftar</a></p>
|
||||
</form>
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,43 +7,64 @@
|
|||
<h1 class="block text-2xl font-bold text-gray-800 dark:text-white">Reset password</h1>
|
||||
</div>
|
||||
|
||||
@if (session()->has('error'))
|
||||
<div class="mt-4 p-4 text-sm text-red-800 border border-red-300 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400 dark:border-red-800" role="alert">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (session()->has('success'))
|
||||
<div class="mt-4 p-4 text-sm text-green-800 border border-green-300 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400 dark:border-green-800" role="alert">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-5">
|
||||
<!-- Form -->
|
||||
<form wire:submit.prevent="save">
|
||||
<div class="grid gap-y-4">
|
||||
<!-- Form Group -->
|
||||
<div>
|
||||
<label for="password" class="block text-sm mb-2 dark:text-white">Password</label>
|
||||
<label for="password" class="block text-sm mb-2 dark:text-white">Password Baru</label>
|
||||
<div class="relative">
|
||||
<input type="password" id="password" wire:model="password" class="py-3 px-4 block w-full border border-gray-200 rounded-lg text-sm
|
||||
focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400 dark:focus:ring-gray-600" aria-describedby="email-error">
|
||||
<div class=" absolute inset-y-0 end-0 flex items-center pointer-events-none pe-3">
|
||||
<svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true">
|
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<input type="password" id="password" wire:model.live="password" class="py-3 px-4 block w-full border border-gray-200 rounded-lg text-sm
|
||||
focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400 dark:focus:ring-gray-600 @error('password') border-red-500 @enderror" aria-describedby="password-error">
|
||||
@error('password')
|
||||
<div class="absolute inset-y-0 end-0 flex items-center pointer-events-none pe-3">
|
||||
<svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true">
|
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z" />
|
||||
</svg>
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<p class="text-red-600 mt-2" id="password-error">Password error message</p>
|
||||
@error('password')
|
||||
<p class="text-red-600 text-xs mt-2" id="password-error">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
<!-- End Form Group -->
|
||||
|
||||
<div>
|
||||
<label for="password_confirmation" class="block text-sm mb-2 dark:text-white">Confirm Password</label>
|
||||
<label for="password_confirmation" class="block text-sm mb-2 dark:text-white">Konfirmasi Password</label>
|
||||
<div class="relative">
|
||||
<input type="password" id="password_confirmation" wire:model="password_confirmation" class="py-3 px-4 block w-full border border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400 dark:focus:ring-gray-600" required aria-describedby="email-error">
|
||||
<input type="password" id="password_confirmation" wire:model.live="password_confirmation" class="py-3 px-4 block w-full border border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400 dark:focus:ring-gray-600 @error('password_confirmation') border-red-500 @enderror" required aria-describedby="password_confirmation-error">
|
||||
|
||||
<div class="hidden inset-y-0 end-0 flex items-center pointer-events-none pe-3">
|
||||
<svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true">
|
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z" />
|
||||
</svg>
|
||||
</div>
|
||||
@error('password_confirmation')
|
||||
<div class="absolute inset-y-0 end-0 flex items-center pointer-events-none pe-3">
|
||||
<svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true">
|
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z" />
|
||||
</svg>
|
||||
</div>
|
||||
@enderror
|
||||
|
||||
</div>
|
||||
<p class="text-xs text-red-600 mt-2" id="password_confirmation-error">Confirm Password Error</p>
|
||||
@error('password_confirmation')
|
||||
<p class="text-xs text-red-600 mt-2" id="password_confirmation-error">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<button type="submit" class="w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-semibold rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600">
|
||||
Save password
|
||||
<span wire:loading.remove>Simpan Password</span>
|
||||
<span wire:loading>Simpan Password</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
Loading…
Reference in New Issue