Andrew Wallo 8 maanden geleden
bovenliggende
commit
d75d3a7e22

+ 2
- 23
app/Filament/Company/Clusters/Settings/Pages/CompanyProfile.php Bestand weergeven

@@ -4,8 +4,7 @@ namespace App\Filament\Company\Clusters\Settings\Pages;
4 4
 
5 5
 use App\Enums\Setting\EntityType;
6 6
 use App\Filament\Company\Clusters\Settings;
7
-use App\Filament\Forms\Components\CountrySelect;
8
-use App\Models\Locale\State;
7
+use App\Filament\Forms\Components\AddressFields;
9 8
 use App\Models\Setting\CompanyProfile as CompanyProfileModel;
10 9
 use App\Utilities\Localization\Timezone;
11 10
 use CodeWithDennis\SimpleAlert\Components\Forms\SimpleAlert;
@@ -19,7 +18,6 @@ use Filament\Forms\Components\Section;
19 18
 use Filament\Forms\Components\Select;
20 19
 use Filament\Forms\Components\TextInput;
21 20
 use Filament\Forms\Form;
22
-use Filament\Forms\Get;
23 21
 use Filament\Notifications\Notification;
24 22
 use Filament\Pages\Concerns\InteractsWithFormActions;
25 23
 use Filament\Pages\Page;
@@ -204,27 +202,8 @@ class CompanyProfile extends Page
204 202
             ->schema([
205 203
                 Hidden::make('type')
206 204
                     ->default('general'),
207
-                TextInput::make('address_line_1')
208
-                    ->label('Address Line 1')
209
-                    ->softRequired()
210
-                    ->maxLength(255),
211
-                TextInput::make('address_line_2')
212
-                    ->label('Address Line 2')
213
-                    ->maxLength(255),
214
-                CountrySelect::make('country')
215
-                    ->clearStateField()
205
+                AddressFields::make()
216 206
                     ->softRequired(),
217
-                Select::make('state_id')
218
-                    ->localizeLabel('State / Province')
219
-                    ->searchable()
220
-                    ->options(static fn (Get $get) => State::getStateOptions($get('country'))),
221
-                TextInput::make('city')
222
-                    ->localizeLabel('City / Town')
223
-                    ->softRequired()
224
-                    ->maxLength(255),
225
-                TextInput::make('postal_code')
226
-                    ->label('Postal Code / Zip Code')
227
-                    ->maxLength(255),
228 207
             ])
229 208
             ->columns(2);
230 209
     }

+ 50
- 34
app/Filament/Company/Resources/Purchases/VendorResource.php Bestand weergeven

@@ -2,22 +2,23 @@
2 2
 
3 3
 namespace App\Filament\Company\Resources\Purchases;
4 4
 
5
+use App\Enums\Accounting\BillStatus;
5 6
 use App\Enums\Common\ContractorType;
6 7
 use App\Enums\Common\VendorType;
7 8
 use App\Filament\Company\Resources\Purchases\VendorResource\Pages;
8
-use App\Filament\Forms\Components\CountrySelect;
9
+use App\Filament\Forms\Components\AddressFields;
9 10
 use App\Filament\Forms\Components\CreateCurrencySelect;
10 11
 use App\Filament\Forms\Components\CustomSection;
11 12
 use App\Filament\Forms\Components\PhoneBuilder;
12 13
 use App\Filament\Tables\Columns;
13 14
 use App\Models\Common\Vendor;
14
-use App\Models\Locale\State;
15
+use App\Utilities\Currency\CurrencyConverter;
15 16
 use Filament\Forms;
16 17
 use Filament\Forms\Form;
17
-use Filament\Forms\Get;
18 18
 use Filament\Resources\Resource;
19 19
 use Filament\Tables;
20 20
 use Filament\Tables\Table;
21
+use Illuminate\Database\Eloquent\Builder;
21 22
 
22 23
 class VendorResource extends Resource
23 24
 {
@@ -45,12 +46,12 @@ class VendorResource extends Resource
45 46
                                     ->columnSpanFull(),
46 47
                                 CreateCurrencySelect::make('currency_code')
47 48
                                     ->nullable()
48
-                                    ->visible(fn (Forms\Get $get) => VendorType::parse($get('type')) === VendorType::Regular),
49
+                                    ->visible(static fn (Forms\Get $get) => VendorType::parse($get('type')) === VendorType::Regular),
49 50
                                 Forms\Components\Select::make('contractor_type')
50 51
                                     ->label('Contractor Type')
51 52
                                     ->required()
52 53
                                     ->live()
53
-                                    ->visible(fn (Forms\Get $get) => VendorType::parse($get('type')) === VendorType::Contractor)
54
+                                    ->visible(static fn (Forms\Get $get) => VendorType::parse($get('type')) === VendorType::Contractor)
54 55
                                     ->options(ContractorType::class),
55 56
                                 Forms\Components\TextInput::make('ssn')
56 57
                                     ->label('Social Security Number')
@@ -59,7 +60,7 @@ class VendorResource extends Resource
59 60
                                     ->mask('999-99-9999')
60 61
                                     ->stripCharacters('-')
61 62
                                     ->maxLength(11)
62
-                                    ->visible(fn (Forms\Get $get) => ContractorType::parse($get('contractor_type')) === ContractorType::Individual)
63
+                                    ->visible(static fn (Forms\Get $get) => ContractorType::parse($get('contractor_type')) === ContractorType::Individual)
63 64
                                     ->maxLength(255),
64 65
                                 Forms\Components\TextInput::make('ein')
65 66
                                     ->label('Employer Identification Number')
@@ -68,7 +69,7 @@ class VendorResource extends Resource
68 69
                                     ->mask('99-9999999')
69 70
                                     ->stripCharacters('-')
70 71
                                     ->maxLength(10)
71
-                                    ->visible(fn (Forms\Get $get) => ContractorType::parse($get('contractor_type')) === ContractorType::Business)
72
+                                    ->visible(static fn (Forms\Get $get) => ContractorType::parse($get('contractor_type')) === ContractorType::Business)
72 73
                                     ->maxLength(255),
73 74
                                 Forms\Components\TextInput::make('account_number')
74 75
                                     ->maxLength(255),
@@ -145,29 +146,7 @@ class VendorResource extends Resource
145 146
                     ->schema([
146 147
                         Forms\Components\Hidden::make('type')
147 148
                             ->default('general'),
148
-                        Forms\Components\TextInput::make('address_line_1')
149
-                            ->label('Address Line 1')
150
-                            ->required()
151
-                            ->maxLength(255),
152
-                        Forms\Components\TextInput::make('address_line_2')
153
-                            ->label('Address Line 2')
154
-                            ->maxLength(255),
155
-                        CountrySelect::make('country')
156
-                            ->clearStateField()
157
-                            ->required(),
158
-                        Forms\Components\Select::make('state_id')
159
-                            ->localizeLabel('State / Province')
160
-                            ->searchable()
161
-                            ->options(static fn (Get $get) => State::getStateOptions($get('country')))
162
-                            ->nullable(),
163
-                        Forms\Components\TextInput::make('city')
164
-                            ->localizeLabel('City / Town')
165
-                            ->required()
166
-                            ->maxLength(255),
167
-                        Forms\Components\TextInput::make('postal_code')
168
-                            ->label('Postal Code / Zip Code')
169
-                            ->required()
170
-                            ->maxLength(255),
149
+                        AddressFields::make(),
171 150
                     ])
172 151
                     ->columns(2),
173 152
             ]);
@@ -180,16 +159,53 @@ class VendorResource extends Resource
180 159
                 Columns::id(),
181 160
                 Tables\Columns\TextColumn::make('type')
182 161
                     ->badge()
183
-                    ->searchable(),
162
+                    ->searchable()
163
+                    ->sortable(),
184 164
                 Tables\Columns\TextColumn::make('name')
185 165
                     ->searchable()
186
-                    ->description(fn (Vendor $vendor) => $vendor->contact?->full_name),
166
+                    ->sortable()
167
+                    ->description(static fn (Vendor $vendor) => $vendor->contact?->full_name),
187 168
                 Tables\Columns\TextColumn::make('contact.email')
188 169
                     ->label('Email')
189 170
                     ->searchable(),
190
-                Tables\Columns\TextColumn::make('primaryContact.phones')
171
+                Tables\Columns\TextColumn::make('contact.first_available_phone')
191 172
                     ->label('Phone')
192
-                    ->state(fn (Vendor $vendor) => $vendor->contact?->first_available_phone),
173
+                    ->state(static fn (Vendor $vendor) => $vendor->contact?->first_available_phone),
174
+                Tables\Columns\TextColumn::make('address.address_string')
175
+                    ->label('Address')
176
+                    ->searchable()
177
+                    ->toggleable(isToggledHiddenByDefault: true)
178
+                    ->listWithLineBreaks(),
179
+                Tables\Columns\TextColumn::make('payable_balance')
180
+                    ->label('Payable Balance')
181
+                    ->getStateUsing(function (Vendor $vendor) {
182
+                        return $vendor->bills()
183
+                            ->outstanding()
184
+                            ->get()
185
+                            ->sumMoneyInDefaultCurrency('amount_due');
186
+                    })
187
+                    ->coloredDescription(function (Vendor $vendor) {
188
+                        $overdue = $vendor->bills()
189
+                            ->where('status', BillStatus::Overdue)
190
+                            ->get()
191
+                            ->sumMoneyInDefaultCurrency('amount_due');
192
+
193
+                        if ($overdue <= 0) {
194
+                            return null;
195
+                        }
196
+
197
+                        $formattedOverdue = CurrencyConverter::formatCentsToMoney($overdue);
198
+
199
+                        return "Overdue: {$formattedOverdue}";
200
+                    })
201
+                    ->sortable(query: function (Builder $query, string $direction) {
202
+                        return $query
203
+                            ->withSum(['bills' => fn (Builder $query) => $query->outstanding()], 'amount_due')
204
+                            ->orderBy('bills_sum_amount_due', $direction);
205
+                    })
206
+                    ->currency(convert: false)
207
+                    ->alignEnd(),
208
+
193 209
             ])
194 210
             ->filters([
195 211
                 //

+ 14
- 59
app/Filament/Company/Resources/Sales/ClientResource.php Bestand weergeven

@@ -3,14 +3,13 @@
3 3
 namespace App\Filament\Company\Resources\Sales;
4 4
 
5 5
 use App\Filament\Company\Resources\Sales\ClientResource\Pages;
6
-use App\Filament\Forms\Components\CountrySelect;
6
+use App\Filament\Forms\Components\AddressFields;
7 7
 use App\Filament\Forms\Components\CreateCurrencySelect;
8 8
 use App\Filament\Forms\Components\CustomSection;
9 9
 use App\Filament\Forms\Components\PhoneBuilder;
10 10
 use App\Filament\Tables\Columns;
11 11
 use App\Models\Common\Address;
12 12
 use App\Models\Common\Client;
13
-use App\Models\Locale\State;
14 13
 use App\Utilities\Currency\CurrencyConverter;
15 14
 use Filament\Forms;
16 15
 use Filament\Forms\Form;
@@ -20,7 +19,6 @@ use Filament\Resources\Resource;
20 19
 use Filament\Tables;
21 20
 use Filament\Tables\Table;
22 21
 use Illuminate\Database\Eloquent\Builder;
23
-use Illuminate\Support\HtmlString;
24 22
 
25 23
 class ClientResource extends Resource
26 24
 {
@@ -185,29 +183,7 @@ class ClientResource extends Resource
185 183
                             ->schema([
186 184
                                 Forms\Components\Hidden::make('type')
187 185
                                     ->default('billing'),
188
-                                Forms\Components\TextInput::make('address_line_1')
189
-                                    ->label('Address Line 1')
190
-                                    ->required()
191
-                                    ->maxLength(255),
192
-                                Forms\Components\TextInput::make('address_line_2')
193
-                                    ->label('Address Line 2')
194
-                                    ->maxLength(255),
195
-                                CountrySelect::make('country')
196
-                                    ->clearStateField()
197
-                                    ->required(),
198
-                                Forms\Components\Select::make('state_id')
199
-                                    ->localizeLabel('State / Province')
200
-                                    ->searchable()
201
-                                    ->options(static fn (Get $get) => State::getStateOptions($get('country')))
202
-                                    ->nullable(),
203
-                                Forms\Components\TextInput::make('city')
204
-                                    ->label('City')
205
-                                    ->required()
206
-                                    ->maxLength(255),
207
-                                Forms\Components\TextInput::make('postal_code')
208
-                                    ->label('Postal Code / Zip Code')
209
-                                    ->required()
210
-                                    ->maxLength(255),
186
+                                AddressFields::make(),
211 187
                             ])->columns(),
212 188
                     ])
213 189
                     ->columns(1),
@@ -260,33 +236,8 @@ class ClientResource extends Resource
260 236
                                         }
261 237
                                     })
262 238
                                     ->columnSpanFull(),
263
-                                Forms\Components\Grid::make()
264
-                                    ->schema([
265
-                                        Forms\Components\TextInput::make('address_line_1')
266
-                                            ->label('Address Line 1')
267
-                                            ->required()
268
-                                            ->maxLength(255),
269
-                                        Forms\Components\TextInput::make('address_line_2')
270
-                                            ->label('Address Line 2')
271
-                                            ->maxLength(255),
272
-                                        CountrySelect::make('country')
273
-                                            ->clearStateField()
274
-                                            ->required(),
275
-                                        Forms\Components\Select::make('state_id')
276
-                                            ->localizeLabel('State / Province')
277
-                                            ->searchable()
278
-                                            ->options(static fn (Get $get) => State::getStateOptions($get('country')))
279
-                                            ->nullable(),
280
-                                        Forms\Components\TextInput::make('city')
281
-                                            ->label('City')
282
-                                            ->required()
283
-                                            ->maxLength(255),
284
-                                        Forms\Components\TextInput::make('postal_code')
285
-                                            ->label('Postal Code / Zip Code')
286
-                                            ->required()
287
-                                            ->maxLength(255),
288
-                                    ])
289
-                                    ->visible(fn (Get $get) => ! $get('same_as_billing')),
239
+                                AddressFields::make()
240
+                                    ->visible(static fn (Get $get) => ! $get('same_as_billing')),
290 241
                                 Forms\Components\Textarea::make('notes')
291 242
                                     ->label('Delivery Instructions')
292 243
                                     ->maxLength(255)
@@ -304,7 +255,7 @@ class ClientResource extends Resource
304 255
                 Tables\Columns\TextColumn::make('name')
305 256
                     ->searchable()
306 257
                     ->sortable()
307
-                    ->description(fn (Client $client) => $client->primaryContact->full_name),
258
+                    ->description(static fn (Client $client) => $client->primaryContact->full_name),
308 259
                 Tables\Columns\TextColumn::make('primaryContact.email')
309 260
                     ->label('Email')
310 261
                     ->searchable()
@@ -312,7 +263,7 @@ class ClientResource extends Resource
312 263
                 Tables\Columns\TextColumn::make('primaryContact.phones')
313 264
                     ->label('Phone')
314 265
                     ->toggleable()
315
-                    ->state(fn (Client $client) => $client->primaryContact->first_available_phone),
266
+                    ->state(static fn (Client $client) => $client->primaryContact->first_available_phone),
316 267
                 Tables\Columns\TextColumn::make('billingAddress.address_string')
317 268
                     ->label('Billing Address')
318 269
                     ->searchable()
@@ -326,7 +277,7 @@ class ClientResource extends Resource
326 277
                             ->get()
327 278
                             ->sumMoneyInDefaultCurrency('amount_due');
328 279
                     })
329
-                    ->description(function (Client $client) {
280
+                    ->coloredDescription(function (Client $client) {
330 281
                         $overdue = $client->invoices()
331 282
                             ->overdue()
332 283
                             ->get()
@@ -338,21 +289,24 @@ class ClientResource extends Resource
338 289
 
339 290
                         $formattedOverdue = CurrencyConverter::formatCentsToMoney($overdue);
340 291
 
341
-                        return new HtmlString("<span class='text-danger-700 dark:text-danger-400'>Overdue: {$formattedOverdue}</span>");
292
+                        return "Overdue: {$formattedOverdue}";
342 293
                     })
343 294
                     ->sortable(query: function (Builder $query, string $direction) {
344 295
                         return $query
345 296
                             ->withSum(['invoices' => fn (Builder $query) => $query->unpaid()], 'amount_due')
346 297
                             ->orderBy('invoices_sum_amount_due', $direction);
347 298
                     })
348
-                    ->currency(fn (Client $client) => $client->currency_code, false)
299
+                    ->currency(convert: false)
349 300
                     ->alignEnd(),
350 301
             ])
351 302
             ->filters([
352 303
                 //
353 304
             ])
354 305
             ->actions([
355
-                Tables\Actions\EditAction::make(),
306
+                Tables\Actions\ActionGroup::make([
307
+                    Tables\Actions\EditAction::make(),
308
+                    Tables\Actions\ViewAction::make(),
309
+                ]),
356 310
             ])
357 311
             ->bulkActions([
358 312
                 Tables\Actions\BulkActionGroup::make([
@@ -373,6 +327,7 @@ class ClientResource extends Resource
373 327
         return [
374 328
             'index' => Pages\ListClients::route('/'),
375 329
             'create' => Pages\CreateClient::route('/create'),
330
+            'view' => Pages\ViewClient::route('/{record}'),
376 331
             'edit' => Pages\EditClient::route('/{record}/edit'),
377 332
         ];
378 333
     }

+ 75
- 0
app/Filament/Company/Resources/Sales/ClientResource/Pages/ViewClient.php Bestand weergeven

@@ -0,0 +1,75 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Resources\Sales\ClientResource\Pages;
4
+
5
+use App\Filament\Company\Resources\Sales\ClientResource;
6
+use App\Filament\Company\Resources\Sales\ClientResource\RelationManagers;
7
+use App\Models\Common\Client;
8
+use Filament\Infolists\Components\Section;
9
+use Filament\Infolists\Components\TextEntry;
10
+use Filament\Infolists\Infolist;
11
+use Filament\Resources\Pages\ViewRecord;
12
+use Illuminate\Support\Number;
13
+
14
+class ViewClient extends ViewRecord
15
+{
16
+    protected static string $resource = ClientResource::class;
17
+
18
+    public function getRelationManagers(): array
19
+    {
20
+        return [
21
+            RelationManagers\InvoicesRelationManager::class,
22
+        ];
23
+    }
24
+
25
+    public function infolist(Infolist $infolist): Infolist
26
+    {
27
+        return $infolist
28
+            ->schema([
29
+                Section::make('Financial Overview')
30
+                    ->columns(4)
31
+                    ->schema([
32
+                        TextEntry::make('last_12_months_paid')
33
+                            ->label('Last 12 Months Paid')
34
+                            ->getStateUsing(function (Client $record) {
35
+                                return $record->invoices()
36
+                                    ->whereNotNull('paid_at')
37
+                                    ->where('paid_at', '>=', now()->subMonths(12))
38
+                                    ->get()
39
+                                    ->sumMoneyInDefaultCurrency('total');
40
+                            })
41
+                            ->currency(convert: false),
42
+                        TextEntry::make('total_unpaid')
43
+                            ->label('Total Unpaid')
44
+                            ->getStateUsing(function (Client $record) {
45
+                                return $record->invoices()
46
+                                    ->unpaid()
47
+                                    ->get()
48
+                                    ->sumMoneyInDefaultCurrency('amount_due');
49
+                            })
50
+                            ->currency(convert: false),
51
+                        TextEntry::make('total_overdue')
52
+                            ->label('Total Overdue')
53
+                            ->getStateUsing(function (Client $record) {
54
+                                return $record->invoices()
55
+                                    ->overdue()
56
+                                    ->get()
57
+                                    ->sumMoneyInDefaultCurrency('amount_due');
58
+                            })
59
+                            ->currency(convert: false),
60
+                        TextEntry::make('average_payment_time')
61
+                            ->label('Average Payment Time')
62
+                            ->getStateUsing(function (Client $record) {
63
+                                return $record->invoices()
64
+                                    ->whereNotNull('paid_at')
65
+                                    ->selectRaw('AVG(TIMESTAMPDIFF(DAY, date, paid_at)) as avg_days')
66
+                                    ->value('avg_days');
67
+                            })
68
+                            ->suffix(' days')
69
+                            ->formatStateUsing(function ($state) {
70
+                                return Number::format($state ?? 0, maxPrecision: 1);
71
+                            }),
72
+                    ]),
73
+            ]);
74
+    }
75
+}

+ 29
- 0
app/Filament/Company/Resources/Sales/ClientResource/RelationManagers/InvoicesRelationManager.php Bestand weergeven

@@ -0,0 +1,29 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Resources\Sales\ClientResource\RelationManagers;
4
+
5
+use App\Filament\Company\Resources\Sales\InvoiceResource;
6
+use Filament\Resources\RelationManagers\RelationManager;
7
+use Filament\Tables;
8
+use Filament\Tables\Table;
9
+
10
+class InvoicesRelationManager extends RelationManager
11
+{
12
+    protected static string $relationship = 'invoices';
13
+
14
+    protected static bool $isLazy = false;
15
+
16
+    public function isReadOnly(): bool
17
+    {
18
+        return false;
19
+    }
20
+
21
+    public function table(Table $table): Table
22
+    {
23
+        return InvoiceResource::table($table)
24
+            ->headerActions([
25
+                Tables\Actions\CreateAction::make()
26
+                    ->url(InvoiceResource\Pages\CreateInvoice::getUrl(['client' => $this->getOwnerRecord()->getKey()])),
27
+            ]);
28
+    }
29
+}

+ 9
- 5
app/Filament/Company/Resources/Sales/InvoiceResource.php Bestand weergeven

@@ -298,10 +298,12 @@ class InvoiceResource extends Resource
298 298
         return $table
299 299
             ->defaultSort('due_date')
300 300
             ->modifyQueryUsing(function (Builder $query, Tables\Contracts\HasTable $livewire) {
301
-                $recurringInvoiceId = $livewire->recurringInvoice;
301
+                if (property_exists($livewire, 'recurringInvoice')) {
302
+                    $recurringInvoiceId = $livewire->recurringInvoice;
302 303
 
303
-                if (! empty($recurringInvoiceId)) {
304
-                    $query->where('recurring_invoice_id', $recurringInvoiceId);
304
+                    if (! empty($recurringInvoiceId)) {
305
+                        $query->where('recurring_invoice_id', $recurringInvoiceId);
306
+                    }
305 307
                 }
306 308
 
307 309
                 return $query;
@@ -388,8 +390,10 @@ class InvoiceResource extends Resource
388 390
             ])
389 391
             ->actions([
390 392
                 Tables\Actions\ActionGroup::make([
391
-                    Tables\Actions\EditAction::make(),
392
-                    Tables\Actions\ViewAction::make(),
393
+                    Tables\Actions\EditAction::make()
394
+                        ->url(static fn (Invoice $record) => Pages\EditInvoice::getUrl(['record' => $record])),
395
+                    Tables\Actions\ViewAction::make()
396
+                        ->url(static fn (Invoice $record) => Pages\ViewInvoice::getUrl(['record' => $record])),
393 397
                     Tables\Actions\DeleteAction::make(),
394 398
                     Invoice::getReplicateAction(Tables\Actions\ReplicateAction::class),
395 399
                     Invoice::getApproveDraftAction(Tables\Actions\Action::class),

+ 11
- 0
app/Filament/Company/Resources/Sales/InvoiceResource/Pages/CreateInvoice.php Bestand weergeven

@@ -17,6 +17,17 @@ class CreateInvoice extends CreateRecord
17 17
 
18 18
     protected static string $resource = InvoiceResource::class;
19 19
 
20
+    public function mount(): void
21
+    {
22
+        parent::mount();
23
+
24
+        $clientId = request()->query('client');
25
+
26
+        if ($clientId) {
27
+            $this->data['client_id'] = $clientId;
28
+        }
29
+    }
30
+
20 31
     public function getMaxContentWidth(): MaxWidth | string | null
21 32
     {
22 33
         return MaxWidth::Full;

+ 58
- 0
app/Filament/Forms/Components/AddressFields.php Bestand weergeven

@@ -0,0 +1,58 @@
1
+<?php
2
+
3
+namespace App\Filament\Forms\Components;
4
+
5
+use Filament\Forms\Components\Field;
6
+use Filament\Forms\Components\Grid;
7
+use Filament\Forms\Components\TextInput;
8
+
9
+class AddressFields extends Grid
10
+{
11
+    protected bool $isSoftRequired = false;
12
+
13
+    protected function setUp(): void
14
+    {
15
+        parent::setUp();
16
+
17
+        $this->schema([
18
+            TextInput::make('address_line_1')
19
+                ->label('Address Line 1')
20
+                ->required()
21
+                ->maxLength(255),
22
+            TextInput::make('address_line_2')
23
+                ->label('Address Line 2')
24
+                ->maxLength(255),
25
+            CountrySelect::make('country')
26
+                ->clearStateField()
27
+                ->required(),
28
+            StateSelect::make('state_id'),
29
+            TextInput::make('city')
30
+                ->label('City')
31
+                ->required()
32
+                ->maxLength(255),
33
+            TextInput::make('postal_code')
34
+                ->label('Postal Code / Zip Code')
35
+                ->maxLength(255),
36
+        ]);
37
+    }
38
+
39
+    public function softRequired(bool $condition = true): static
40
+    {
41
+        $this->setSoftRequired($condition);
42
+
43
+        return $this;
44
+    }
45
+
46
+    protected function setSoftRequired(bool $condition): void
47
+    {
48
+        $this->isSoftRequired = $condition;
49
+
50
+        $childComponents = $this->getChildComponents();
51
+
52
+        foreach ($childComponents as $component) {
53
+            if ($component instanceof Field && $component->isRequired()) {
54
+                $component->markAsRequired(! $condition);
55
+            }
56
+        }
57
+    }
58
+}

+ 20
- 0
app/Filament/Forms/Components/StateSelect.php Bestand weergeven

@@ -0,0 +1,20 @@
1
+<?php
2
+
3
+namespace App\Filament\Forms\Components;
4
+
5
+use App\Models\Locale\State;
6
+use Filament\Forms\Components\Select;
7
+use Filament\Forms\Get;
8
+
9
+class StateSelect extends Select
10
+{
11
+    protected function setUp(): void
12
+    {
13
+        parent::setUp();
14
+
15
+        $this
16
+            ->localizeLabel('State / Province')
17
+            ->searchable()
18
+            ->options(static fn (Get $get) => State::getStateOptions($get('country')));
19
+    }
20
+}

+ 12
- 0
app/Providers/MacroServiceProvider.php Bestand weergeven

@@ -20,7 +20,9 @@ use Filament\Forms\Components\TextInput;
20 20
 use Filament\Infolists\Components\TextEntry;
21 21
 use Filament\Tables\Columns\TextColumn;
22 22
 use Filament\Tables\Contracts\HasTable;
23
+use Illuminate\Contracts\Support\Htmlable;
23 24
 use Illuminate\Support\Carbon;
25
+use Illuminate\Support\HtmlString;
24 26
 use Illuminate\Support\ServiceProvider;
25 27
 
26 28
 class MacroServiceProvider extends ServiceProvider
@@ -114,6 +116,16 @@ class MacroServiceProvider extends ServiceProvider
114 116
                 });
115 117
         });
116 118
 
119
+        TextColumn::macro('coloredDescription', function (string | Htmlable | Closure | null $description, string $color = 'danger') {
120
+            $this->description(static function (TextColumn $column) use ($description, $color): Htmlable {
121
+                $description = $column->evaluate($description);
122
+
123
+                return new HtmlString("<span class='text-{$color}-700 dark:text-{$color}-400'>{$description}</span>");
124
+            });
125
+
126
+            return $this;
127
+        });
128
+
117 129
         TextColumn::macro('hideOnTabs', function (array $tabs): static {
118 130
             $this->toggleable(isToggledHiddenByDefault: function (HasTable $livewire) use ($tabs) {
119 131
                 return in_array($livewire->activeTab, $tabs);

+ 6
- 10
database/factories/Common/ContactFactory.php Bestand weergeven

@@ -71,19 +71,15 @@ class ContactFactory extends Factory
71 71
 
72 72
     public function primary(): self
73 73
     {
74
-        return $this->state(function (array $attributes) {
75
-            return [
76
-                'is_primary' => true,
77
-            ];
78
-        });
74
+        return $this->state([
75
+            'is_primary' => true,
76
+        ]);
79 77
     }
80 78
 
81 79
     public function secondary(): self
82 80
     {
83
-        return $this->state(function (array $attributes) {
84
-            return [
85
-                'is_primary' => false,
86
-            ];
87
-        });
81
+        return $this->state([
82
+            'is_primary' => false,
83
+        ]);
88 84
     }
89 85
 }

Laden…
Annuleren
Opslaan