diff --git a/app/Filament/Client/Pages/Dashboard.php b/app/Filament/Client/Pages/Dashboard.php new file mode 100644 index 00000000..68592448 --- /dev/null +++ b/app/Filament/Client/Pages/Dashboard.php @@ -0,0 +1,30 @@ + + +user(); + + return [ + StatsOverviewWidget::class, + ]; + } + + protected function getColumns(): int + { + return 2; + } +} \ No newline at end of file diff --git a/app/Filament/Client/Pages/Profile.php b/app/Filament/Client/Pages/Profile.php new file mode 100644 index 00000000..d7516a21 --- /dev/null +++ b/app/Filament/Client/Pages/Profile.php @@ -0,0 +1,87 @@ + + +form->fill([ + 'name' => auth()->user()->name, + 'email' => auth()->user()->email, + 'company' => auth()->user()->company, + 'phone' => auth()->user()->phone, + ]); + } + + public function form(Form $form): Form + { + return $form + ->schema([ + TextInput::make('name') + ->required() + ->maxLength(255), + TextInput::make('email') + ->email() + ->required() + ->maxLength(255) + ->unique('clients', 'email', ignorable: auth()->user()), + TextInput::make('company') + ->maxLength(255), + TextInput::make('phone') + ->tel() + ->maxLength(20), + TextInput::make('current_password') + ->password() + ->label('Current Password') + ->required() + ->visible(fn ($get) => (bool) $get('password')), + TextInput::make('password') + ->password() + ->label('New Password') + ->rule(Password::defaults()), + TextInput::make('password_confirmation') + ->password() + ->label('Confirm Password') + ->visible(fn ($get) => (bool) $get('password')) + ->same('password'), + ]); + } + + public function submit(): void + { + $data = $this->form->getState(); + + $user = auth()->user(); + + if (isset($data['password'])) { + if (!Hash::check($data['current_password'], $user->password)) { + $this->addError('current_password', 'The provided password is incorrect.'); + return; + } + $data['password'] = Hash::make($data['password']); + } + + $user->update($data); + + $this->notify('success', 'Profile updated successfully'); + } + + protected static function shouldRegisterNavigation(): bool + { + return true; + } +} \ No newline at end of file diff --git a/app/Filament/Client/Resources/InvoiceResource.php b/app/Filament/Client/Resources/InvoiceResource.php new file mode 100644 index 00000000..54778573 --- /dev/null +++ b/app/Filament/Client/Resources/InvoiceResource.php @@ -0,0 +1,63 @@ + + +columns([ + Tables\Columns\TextColumn::make('invoice_number') + ->searchable() + ->sortable(), + Tables\Columns\TextColumn::make('total_amount') + ->money('usd') + ->sortable(), + Tables\Columns\TextColumn::make('status') + ->badge() + ->colors([ + 'warning' => 'pending', + 'success' => 'paid', + 'danger' => 'overdue', + ]), + Tables\Columns\TextColumn::make('due_date') + ->date() + ->sortable(), + ]) + ->filters([ + Tables\Filters\SelectFilter::make('status') + ->options([ + 'pending' => 'Pending', + 'paid' => 'Paid', + 'overdue' => 'Overdue', + ]), + ]) + ->defaultSort('created_at', 'desc'); + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListInvoices::class, + 'view' => Pages\ViewInvoice::class, + ]; + } + + public static function getEloquentQuery(): \Illuminate\Database\Eloquent\Builder + { + return parent::getEloquentQuery()->where('client_id', auth()->id()); + } +} \ No newline at end of file diff --git a/app/Providers/Filament/ClientPanelProvider.php b/app/Providers/Filament/ClientPanelProvider.php new file mode 100644 index 00000000..c6be3a85 --- /dev/null +++ b/app/Providers/Filament/ClientPanelProvider.php @@ -0,0 +1,56 @@ + + +id('client') + ->path('client') + ->login() + ->colors([ + 'primary' => Color::Blue, + ]) + ->discoverResources(in: app_path('Filament/Client/Resources'), for: 'App\\Filament\\Client\\Resources') + ->discoverPages(in: app_path('Filament/Client/Pages'), for: 'App\\Filament\\Client\\Pages') + ->pages([ + Pages\Dashboard::class, + Pages\Profile::class, + ]) + ->middleware([ + EncryptCookies::class, + AddQueuedCookiesToResponse::class, + StartSession::class, + AuthenticateSession::class, + ShareErrorsFromSession::class, + VerifyCsrfToken::class, + SubstituteBindings::class, + DisableBladeIconComponents::class, + DispatchServingFilamentEvent::class, + ]) + ->authMiddleware([ + Authenticate::class, + ]) + ->authGuard('client'); + } +} \ No newline at end of file