Bladeren bron

wip budgets

3.x
Andrew Wallo 7 maanden geleden
bovenliggende
commit
6d39f9b557

+ 0
- 7
app/Filament/Company/Resources/Accounting/BudgetResource.php Bestand weergeven

@@ -224,13 +224,6 @@ class BudgetResource extends Resource
224 224
                     ->label('End Date')
225 225
                     ->date()
226 226
                     ->sortable(),
227
-
228
-                Tables\Columns\TextColumn::make('total_budgeted_amount')
229
-                    ->label('Total Budgeted')
230
-                    ->money()
231
-                    ->sortable()
232
-                    ->alignEnd()
233
-                    ->getStateUsing(fn (Budget $record) => $record->budgetItems->sum(fn ($item) => $item->allocations->sum('amount'))),
234 227
             ])
235 228
             ->filters([
236 229
                 //

+ 51
- 9
app/Filament/Company/Resources/Accounting/BudgetResource/Pages/CreateBudget.php Bestand weergeven

@@ -5,13 +5,17 @@ namespace App\Filament\Company\Resources\Accounting\BudgetResource\Pages;
5 5
 use App\Enums\Accounting\BudgetIntervalType;
6 6
 use App\Facades\Accounting;
7 7
 use App\Filament\Company\Resources\Accounting\BudgetResource;
8
+use App\Filament\Forms\Components\LinearWizard;
8 9
 use App\Models\Accounting\Account;
9 10
 use App\Models\Accounting\Budget;
10 11
 use App\Models\Accounting\BudgetAllocation;
11 12
 use App\Models\Accounting\BudgetItem;
13
+use App\Utilities\Currency\CurrencyConverter;
14
+use Filament\Actions\ActionGroup;
12 15
 use Filament\Forms;
13 16
 use Filament\Forms\Components\Actions\Action;
14 17
 use Filament\Forms\Components\Wizard\Step;
18
+use Filament\Forms\Form;
15 19
 use Filament\Resources\Pages\CreateRecord;
16 20
 use Illuminate\Database\Eloquent\Builder;
17 21
 use Illuminate\Database\Eloquent\Model;
@@ -19,14 +23,44 @@ use Illuminate\Support\Carbon;
19 23
 
20 24
 class CreateBudget extends CreateRecord
21 25
 {
22
-    use CreateRecord\Concerns\HasWizard;
23
-
24 26
     protected static string $resource = BudgetResource::class;
25 27
 
28
+    public function getStartStep(): int
29
+    {
30
+        return 1;
31
+    }
32
+
33
+    public function form(Form $form): Form
34
+    {
35
+        return parent::form($form)
36
+            ->schema([
37
+                LinearWizard::make($this->getSteps())
38
+                    ->startOnStep($this->getStartStep())
39
+                    ->cancelAction($this->getCancelFormAction())
40
+                    ->submitAction($this->getSubmitFormAction()->label('Next'))
41
+                    ->skippable($this->hasSkippableSteps()),
42
+            ])
43
+            ->columns(null);
44
+    }
45
+
46
+    /**
47
+     * @return array<\Filament\Actions\Action | ActionGroup>
48
+     */
49
+    public function getFormActions(): array
50
+    {
51
+        return [];
52
+    }
53
+
54
+    protected function hasSkippableSteps(): bool
55
+    {
56
+        return false;
57
+    }
58
+
26 59
     public function getSteps(): array
27 60
     {
28 61
         return [
29 62
             Step::make('General Information')
63
+                ->icon('heroicon-o-document-text')
30 64
                 ->columns(2)
31 65
                 ->schema([
32 66
                     Forms\Components\TextInput::make('name')
@@ -57,6 +91,7 @@ class CreateBudget extends CreateRecord
57 91
                 ]),
58 92
 
59 93
             Step::make('Budget Setup & Settings')
94
+                ->icon('heroicon-o-cog-6-tooth')
60 95
                 ->schema([
61 96
                     // Prefill configuration
62 97
                     Forms\Components\Toggle::make('prefill_data')
@@ -112,6 +147,7 @@ class CreateBudget extends CreateRecord
112 147
                 ]),
113 148
 
114 149
             Step::make('Modify Budget Structure')
150
+                ->icon('heroicon-o-adjustments-horizontal')
115 151
                 ->schema([
116 152
                     Forms\Components\CheckboxList::make('selected_accounts')
117 153
                         ->label('Select Accounts to Exclude')
@@ -205,7 +241,7 @@ class CreateBudget extends CreateRecord
205 241
                     'interval_type' => $data['interval_type'],
206 242
                     'start_date' => $allocationStart->toDateString(),
207 243
                     'end_date' => $allocationEnd->toDateString(),
208
-                    'amount' => $amount,
244
+                    'amount' => CurrencyConverter::convertCentsToFloat($amount),
209 245
                 ]);
210 246
 
211 247
                 $allocationStart = $allocationEnd->addDay();
@@ -226,7 +262,7 @@ class CreateBudget extends CreateRecord
226 262
         return $this->distributeAmountAcrossPeriods($netMovement->getAmount(), $fiscalYearStart, $fiscalYearEnd, $intervalType);
227 263
     }
228 264
 
229
-    private function distributeAmountAcrossPeriods(float $totalAmount, Carbon $startDate, Carbon $endDate, BudgetIntervalType $intervalType): array
265
+    private function distributeAmountAcrossPeriods(int $totalAmountInCents, Carbon $startDate, Carbon $endDate, BudgetIntervalType $intervalType): array
230 266
     {
231 267
         $amounts = [];
232 268
         $periods = [];
@@ -240,10 +276,16 @@ class CreateBudget extends CreateRecord
240 276
 
241 277
         // Evenly distribute total amount across periods
242 278
         $periodCount = count($periods);
243
-        $amountPerPeriod = $periodCount > 0 ? round($totalAmount / $periodCount, 2) : 0;
244 279
 
245
-        foreach ($periods as $periodLabel) {
246
-            $amounts[$periodLabel] = $amountPerPeriod;
280
+        if ($periodCount === 0) {
281
+            return $amounts;
282
+        }
283
+
284
+        $baseAmount = intdiv($totalAmountInCents, $periodCount); // Floor division to get the base amount in cents
285
+        $remainder = $totalAmountInCents % $periodCount; // Remaining cents to distribute
286
+
287
+        foreach ($periods as $index => $period) {
288
+            $amounts[$period] = $baseAmount + ($index < $remainder ? 1 : 0); // Distribute remainder cents evenly
247 289
         }
248 290
 
249 291
         return $amounts;
@@ -258,7 +300,7 @@ class CreateBudget extends CreateRecord
258 300
             ->get();
259 301
 
260 302
         foreach ($previousAllocations as $allocation) {
261
-            $amounts[$allocation->period] = $allocation->amount;
303
+            $amounts[$allocation->period] = $allocation->getRawOriginal('amount');
262 304
         }
263 305
 
264 306
         return $amounts;
@@ -271,7 +313,7 @@ class CreateBudget extends CreateRecord
271 313
         $currentPeriod = Carbon::parse($startDate);
272 314
         while ($currentPeriod->lte(Carbon::parse($endDate))) {
273 315
             $period = $this->determinePeriod($currentPeriod, $intervalType);
274
-            $amounts[$period] = 0.00;
316
+            $amounts[$period] = 0;
275 317
             $currentPeriod->addUnit($intervalType->value);
276 318
         }
277 319
 

+ 50
- 0
app/Filament/Forms/Components/LinearWizard.php Bestand weergeven

@@ -0,0 +1,50 @@
1
+<?php
2
+
3
+namespace App\Filament\Forms\Components;
4
+
5
+use Filament\Forms\Components\Wizard;
6
+
7
+class LinearWizard extends Wizard
8
+{
9
+    protected string $view = 'filament.forms.components.linear-wizard';
10
+
11
+    protected bool $hideStepTabs = false;
12
+
13
+    protected ?string $currentStepDescription = null;
14
+
15
+    /**
16
+     * Hide the step tabs at the top of the wizard
17
+     */
18
+    public function hideStepTabs(bool $condition = true): static
19
+    {
20
+        $this->hideStepTabs = $condition;
21
+
22
+        return $this;
23
+    }
24
+
25
+    /**
26
+     * Add a description for the current step
27
+     */
28
+    public function currentStepDescription(?string $description): static
29
+    {
30
+        $this->currentStepDescription = $description;
31
+
32
+        return $this;
33
+    }
34
+
35
+    /**
36
+     * Get whether the step tabs should be hidden
37
+     */
38
+    public function areStepTabsHidden(): bool
39
+    {
40
+        return $this->hideStepTabs;
41
+    }
42
+
43
+    /**
44
+     * Get the description for the current step
45
+     */
46
+    public function getCurrentStepDescription(): ?string
47
+    {
48
+        return $this->currentStepDescription;
49
+    }
50
+}

+ 7
- 0
app/Models/Accounting/BudgetAllocation.php Bestand weergeven

@@ -4,6 +4,7 @@ namespace App\Models\Accounting;
4 4
 
5 5
 use App\Casts\DocumentMoneyCast;
6 6
 use App\Concerns\CompanyOwned;
7
+use App\Enums\Accounting\BudgetIntervalType;
7 8
 use Illuminate\Database\Eloquent\Factories\HasFactory;
8 9
 use Illuminate\Database\Eloquent\Model;
9 10
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -26,6 +27,7 @@ class BudgetAllocation extends Model
26 27
     protected $casts = [
27 28
         'start_date' => 'date',
28 29
         'end_date' => 'date',
30
+        'interval_type' => BudgetIntervalType::class,
29 31
         'amount' => DocumentMoneyCast::class,
30 32
     ];
31 33
 
@@ -33,4 +35,9 @@ class BudgetAllocation extends Model
33 35
     {
34 36
         return $this->belongsTo(BudgetItem::class);
35 37
     }
38
+
39
+    public function isCurrentPeriod(): bool
40
+    {
41
+        return now()->between($this->start_date, $this->end_date);
42
+    }
36 43
 }

+ 1
- 1
app/Utilities/Currency/CurrencyConverter.php Bestand weergeven

@@ -32,7 +32,7 @@ class CurrencyConverter
32 32
 
33 33
     public static function prepareForAccessor(string $amount, string $currency): int
34 34
     {
35
-        return money($amount, $currency, true)->getAmount();
35
+        return self::convertToCents($amount, $currency);
36 36
     }
37 37
 
38 38
     public static function convertCentsToFormatSimple(int $amount, ?string $currency = null): string

+ 6
- 6
composer.lock Bestand weergeven

@@ -497,16 +497,16 @@
497 497
         },
498 498
         {
499 499
             "name": "aws/aws-sdk-php",
500
-            "version": "3.342.6",
500
+            "version": "3.342.7",
501 501
             "source": {
502 502
                 "type": "git",
503 503
                 "url": "https://github.com/aws/aws-sdk-php.git",
504
-                "reference": "2ad93ef447289da27892707efa683c1ae7ced85f"
504
+                "reference": "4d42e384dac1e71107226ed72ed5e8e4d4ee3358"
505 505
             },
506 506
             "dist": {
507 507
                 "type": "zip",
508
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2ad93ef447289da27892707efa683c1ae7ced85f",
509
-                "reference": "2ad93ef447289da27892707efa683c1ae7ced85f",
508
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/4d42e384dac1e71107226ed72ed5e8e4d4ee3358",
509
+                "reference": "4d42e384dac1e71107226ed72ed5e8e4d4ee3358",
510 510
                 "shasum": ""
511 511
             },
512 512
             "require": {
@@ -588,9 +588,9 @@
588 588
             "support": {
589 589
                 "forum": "https://github.com/aws/aws-sdk-php/discussions",
590 590
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
591
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.342.6"
591
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.342.7"
592 592
             },
593
-            "time": "2025-03-14T18:01:18+00:00"
593
+            "time": "2025-03-17T18:18:04+00:00"
594 594
         },
595 595
         {
596 596
             "name": "aws/aws-sdk-php-laravel",

+ 82
- 82
package-lock.json Bestand weergeven

@@ -575,9 +575,9 @@
575 575
             }
576 576
         },
577 577
         "node_modules/@rollup/rollup-android-arm-eabi": {
578
-            "version": "4.35.0",
579
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.35.0.tgz",
580
-            "integrity": "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==",
578
+            "version": "4.36.0",
579
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.36.0.tgz",
580
+            "integrity": "sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w==",
581 581
             "cpu": [
582 582
                 "arm"
583 583
             ],
@@ -589,9 +589,9 @@
589 589
             ]
590 590
         },
591 591
         "node_modules/@rollup/rollup-android-arm64": {
592
-            "version": "4.35.0",
593
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.35.0.tgz",
594
-            "integrity": "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==",
592
+            "version": "4.36.0",
593
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.36.0.tgz",
594
+            "integrity": "sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg==",
595 595
             "cpu": [
596 596
                 "arm64"
597 597
             ],
@@ -603,9 +603,9 @@
603 603
             ]
604 604
         },
605 605
         "node_modules/@rollup/rollup-darwin-arm64": {
606
-            "version": "4.35.0",
607
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.35.0.tgz",
608
-            "integrity": "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==",
606
+            "version": "4.36.0",
607
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.36.0.tgz",
608
+            "integrity": "sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw==",
609 609
             "cpu": [
610 610
                 "arm64"
611 611
             ],
@@ -617,9 +617,9 @@
617 617
             ]
618 618
         },
619 619
         "node_modules/@rollup/rollup-darwin-x64": {
620
-            "version": "4.35.0",
621
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.35.0.tgz",
622
-            "integrity": "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==",
620
+            "version": "4.36.0",
621
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.36.0.tgz",
622
+            "integrity": "sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA==",
623 623
             "cpu": [
624 624
                 "x64"
625 625
             ],
@@ -631,9 +631,9 @@
631 631
             ]
632 632
         },
633 633
         "node_modules/@rollup/rollup-freebsd-arm64": {
634
-            "version": "4.35.0",
635
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.35.0.tgz",
636
-            "integrity": "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==",
634
+            "version": "4.36.0",
635
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.36.0.tgz",
636
+            "integrity": "sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg==",
637 637
             "cpu": [
638 638
                 "arm64"
639 639
             ],
@@ -645,9 +645,9 @@
645 645
             ]
646 646
         },
647 647
         "node_modules/@rollup/rollup-freebsd-x64": {
648
-            "version": "4.35.0",
649
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.35.0.tgz",
650
-            "integrity": "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==",
648
+            "version": "4.36.0",
649
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.36.0.tgz",
650
+            "integrity": "sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ==",
651 651
             "cpu": [
652 652
                 "x64"
653 653
             ],
@@ -659,9 +659,9 @@
659 659
             ]
660 660
         },
661 661
         "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
662
-            "version": "4.35.0",
663
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.35.0.tgz",
664
-            "integrity": "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==",
662
+            "version": "4.36.0",
663
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.36.0.tgz",
664
+            "integrity": "sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg==",
665 665
             "cpu": [
666 666
                 "arm"
667 667
             ],
@@ -673,9 +673,9 @@
673 673
             ]
674 674
         },
675 675
         "node_modules/@rollup/rollup-linux-arm-musleabihf": {
676
-            "version": "4.35.0",
677
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.35.0.tgz",
678
-            "integrity": "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==",
676
+            "version": "4.36.0",
677
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.36.0.tgz",
678
+            "integrity": "sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg==",
679 679
             "cpu": [
680 680
                 "arm"
681 681
             ],
@@ -687,9 +687,9 @@
687 687
             ]
688 688
         },
689 689
         "node_modules/@rollup/rollup-linux-arm64-gnu": {
690
-            "version": "4.35.0",
691
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.35.0.tgz",
692
-            "integrity": "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==",
690
+            "version": "4.36.0",
691
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.36.0.tgz",
692
+            "integrity": "sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A==",
693 693
             "cpu": [
694 694
                 "arm64"
695 695
             ],
@@ -701,9 +701,9 @@
701 701
             ]
702 702
         },
703 703
         "node_modules/@rollup/rollup-linux-arm64-musl": {
704
-            "version": "4.35.0",
705
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.35.0.tgz",
706
-            "integrity": "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==",
704
+            "version": "4.36.0",
705
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.36.0.tgz",
706
+            "integrity": "sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw==",
707 707
             "cpu": [
708 708
                 "arm64"
709 709
             ],
@@ -715,9 +715,9 @@
715 715
             ]
716 716
         },
717 717
         "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
718
-            "version": "4.35.0",
719
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.35.0.tgz",
720
-            "integrity": "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==",
718
+            "version": "4.36.0",
719
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.36.0.tgz",
720
+            "integrity": "sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg==",
721 721
             "cpu": [
722 722
                 "loong64"
723 723
             ],
@@ -729,9 +729,9 @@
729 729
             ]
730 730
         },
731 731
         "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
732
-            "version": "4.35.0",
733
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.35.0.tgz",
734
-            "integrity": "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==",
732
+            "version": "4.36.0",
733
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.36.0.tgz",
734
+            "integrity": "sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg==",
735 735
             "cpu": [
736 736
                 "ppc64"
737 737
             ],
@@ -743,9 +743,9 @@
743 743
             ]
744 744
         },
745 745
         "node_modules/@rollup/rollup-linux-riscv64-gnu": {
746
-            "version": "4.35.0",
747
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.35.0.tgz",
748
-            "integrity": "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==",
746
+            "version": "4.36.0",
747
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.36.0.tgz",
748
+            "integrity": "sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA==",
749 749
             "cpu": [
750 750
                 "riscv64"
751 751
             ],
@@ -757,9 +757,9 @@
757 757
             ]
758 758
         },
759 759
         "node_modules/@rollup/rollup-linux-s390x-gnu": {
760
-            "version": "4.35.0",
761
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.35.0.tgz",
762
-            "integrity": "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==",
760
+            "version": "4.36.0",
761
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.36.0.tgz",
762
+            "integrity": "sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag==",
763 763
             "cpu": [
764 764
                 "s390x"
765 765
             ],
@@ -771,9 +771,9 @@
771 771
             ]
772 772
         },
773 773
         "node_modules/@rollup/rollup-linux-x64-gnu": {
774
-            "version": "4.35.0",
775
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.35.0.tgz",
776
-            "integrity": "sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==",
774
+            "version": "4.36.0",
775
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.36.0.tgz",
776
+            "integrity": "sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ==",
777 777
             "cpu": [
778 778
                 "x64"
779 779
             ],
@@ -785,9 +785,9 @@
785 785
             ]
786 786
         },
787 787
         "node_modules/@rollup/rollup-linux-x64-musl": {
788
-            "version": "4.35.0",
789
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.35.0.tgz",
790
-            "integrity": "sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==",
788
+            "version": "4.36.0",
789
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.36.0.tgz",
790
+            "integrity": "sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ==",
791 791
             "cpu": [
792 792
                 "x64"
793 793
             ],
@@ -799,9 +799,9 @@
799 799
             ]
800 800
         },
801 801
         "node_modules/@rollup/rollup-win32-arm64-msvc": {
802
-            "version": "4.35.0",
803
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.35.0.tgz",
804
-            "integrity": "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==",
802
+            "version": "4.36.0",
803
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.36.0.tgz",
804
+            "integrity": "sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A==",
805 805
             "cpu": [
806 806
                 "arm64"
807 807
             ],
@@ -813,9 +813,9 @@
813 813
             ]
814 814
         },
815 815
         "node_modules/@rollup/rollup-win32-ia32-msvc": {
816
-            "version": "4.35.0",
817
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.35.0.tgz",
818
-            "integrity": "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==",
816
+            "version": "4.36.0",
817
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.36.0.tgz",
818
+            "integrity": "sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ==",
819 819
             "cpu": [
820 820
                 "ia32"
821 821
             ],
@@ -827,9 +827,9 @@
827 827
             ]
828 828
         },
829 829
         "node_modules/@rollup/rollup-win32-x64-msvc": {
830
-            "version": "4.35.0",
831
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz",
832
-            "integrity": "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==",
830
+            "version": "4.36.0",
831
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.36.0.tgz",
832
+            "integrity": "sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw==",
833 833
             "cpu": [
834 834
                 "x64"
835 835
             ],
@@ -1264,9 +1264,9 @@
1264 1264
             "license": "MIT"
1265 1265
         },
1266 1266
         "node_modules/electron-to-chromium": {
1267
-            "version": "1.5.119",
1268
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.119.tgz",
1269
-            "integrity": "sha512-Ku4NMzUjz3e3Vweh7PhApPrZSS4fyiCIbcIrG9eKrriYVLmbMepETR/v6SU7xPm98QTqMSYiCwfO89QNjXLkbQ==",
1267
+            "version": "1.5.120",
1268
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.120.tgz",
1269
+            "integrity": "sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ==",
1270 1270
             "dev": true,
1271 1271
             "license": "ISC"
1272 1272
         },
@@ -2412,9 +2412,9 @@
2412 2412
             }
2413 2413
         },
2414 2414
         "node_modules/rollup": {
2415
-            "version": "4.35.0",
2416
-            "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.35.0.tgz",
2417
-            "integrity": "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==",
2415
+            "version": "4.36.0",
2416
+            "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.36.0.tgz",
2417
+            "integrity": "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q==",
2418 2418
             "dev": true,
2419 2419
             "license": "MIT",
2420 2420
             "dependencies": {
@@ -2428,25 +2428,25 @@
2428 2428
                 "npm": ">=8.0.0"
2429 2429
             },
2430 2430
             "optionalDependencies": {
2431
-                "@rollup/rollup-android-arm-eabi": "4.35.0",
2432
-                "@rollup/rollup-android-arm64": "4.35.0",
2433
-                "@rollup/rollup-darwin-arm64": "4.35.0",
2434
-                "@rollup/rollup-darwin-x64": "4.35.0",
2435
-                "@rollup/rollup-freebsd-arm64": "4.35.0",
2436
-                "@rollup/rollup-freebsd-x64": "4.35.0",
2437
-                "@rollup/rollup-linux-arm-gnueabihf": "4.35.0",
2438
-                "@rollup/rollup-linux-arm-musleabihf": "4.35.0",
2439
-                "@rollup/rollup-linux-arm64-gnu": "4.35.0",
2440
-                "@rollup/rollup-linux-arm64-musl": "4.35.0",
2441
-                "@rollup/rollup-linux-loongarch64-gnu": "4.35.0",
2442
-                "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0",
2443
-                "@rollup/rollup-linux-riscv64-gnu": "4.35.0",
2444
-                "@rollup/rollup-linux-s390x-gnu": "4.35.0",
2445
-                "@rollup/rollup-linux-x64-gnu": "4.35.0",
2446
-                "@rollup/rollup-linux-x64-musl": "4.35.0",
2447
-                "@rollup/rollup-win32-arm64-msvc": "4.35.0",
2448
-                "@rollup/rollup-win32-ia32-msvc": "4.35.0",
2449
-                "@rollup/rollup-win32-x64-msvc": "4.35.0",
2431
+                "@rollup/rollup-android-arm-eabi": "4.36.0",
2432
+                "@rollup/rollup-android-arm64": "4.36.0",
2433
+                "@rollup/rollup-darwin-arm64": "4.36.0",
2434
+                "@rollup/rollup-darwin-x64": "4.36.0",
2435
+                "@rollup/rollup-freebsd-arm64": "4.36.0",
2436
+                "@rollup/rollup-freebsd-x64": "4.36.0",
2437
+                "@rollup/rollup-linux-arm-gnueabihf": "4.36.0",
2438
+                "@rollup/rollup-linux-arm-musleabihf": "4.36.0",
2439
+                "@rollup/rollup-linux-arm64-gnu": "4.36.0",
2440
+                "@rollup/rollup-linux-arm64-musl": "4.36.0",
2441
+                "@rollup/rollup-linux-loongarch64-gnu": "4.36.0",
2442
+                "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0",
2443
+                "@rollup/rollup-linux-riscv64-gnu": "4.36.0",
2444
+                "@rollup/rollup-linux-s390x-gnu": "4.36.0",
2445
+                "@rollup/rollup-linux-x64-gnu": "4.36.0",
2446
+                "@rollup/rollup-linux-x64-musl": "4.36.0",
2447
+                "@rollup/rollup-win32-arm64-msvc": "4.36.0",
2448
+                "@rollup/rollup-win32-ia32-msvc": "4.36.0",
2449
+                "@rollup/rollup-win32-x64-msvc": "4.36.0",
2450 2450
                 "fsevents": "~2.3.2"
2451 2451
             }
2452 2452
         },

+ 206
- 0
resources/views/filament/forms/components/linear-wizard.blade.php Bestand weergeven

@@ -0,0 +1,206 @@
1
+@php
2
+    $isContained = $isContained();
3
+    $statePath = $getStatePath();
4
+    $previousAction = $getAction('previous');
5
+    $nextAction = $getAction('next');
6
+    $currentStepDescription = $getCurrentStepDescription();
7
+    $areStepTabsHidden = $areStepTabsHidden();
8
+@endphp
9
+
10
+<div
11
+    wire:ignore.self
12
+    x-cloak
13
+    x-data="{
14
+        step: null,
15
+
16
+        nextStep: function () {
17
+            let nextStepIndex = this.getStepIndex(this.step) + 1
18
+
19
+            if (nextStepIndex >= this.getSteps().length) {
20
+                return
21
+            }
22
+
23
+            this.step = this.getSteps()[nextStepIndex]
24
+
25
+            this.autofocusFields()
26
+            this.scroll()
27
+        },
28
+
29
+        previousStep: function () {
30
+            let previousStepIndex = this.getStepIndex(this.step) - 1
31
+
32
+            if (previousStepIndex < 0) {
33
+                return
34
+            }
35
+
36
+            this.step = this.getSteps()[previousStepIndex]
37
+
38
+            this.autofocusFields()
39
+            this.scroll()
40
+        },
41
+
42
+        scroll: function () {
43
+            this.$nextTick(() => {
44
+                this.$refs.header.children[
45
+                    this.getStepIndex(this.step)
46
+                ].scrollIntoView({ behavior: 'smooth', block: 'start' })
47
+            })
48
+        },
49
+
50
+        autofocusFields: function () {
51
+            $nextTick(() =>
52
+                this.$refs[`step-${this.step}`]
53
+                    .querySelector('[autofocus]')
54
+                    ?.focus(),
55
+            )
56
+        },
57
+
58
+        getStepIndex: function (step) {
59
+            let index = this.getSteps().findIndex(
60
+                (indexedStep) => indexedStep === step,
61
+            )
62
+
63
+            if (index === -1) {
64
+                return 0
65
+            }
66
+
67
+            return index
68
+        },
69
+
70
+        getSteps: function () {
71
+            return JSON.parse(this.$refs.stepsData.value)
72
+        },
73
+
74
+        isFirstStep: function () {
75
+            return this.getStepIndex(this.step) <= 0
76
+        },
77
+
78
+        isLastStep: function () {
79
+            return this.getStepIndex(this.step) + 1 >= this.getSteps().length
80
+        },
81
+
82
+        isStepAccessible: function (stepId) {
83
+            return (
84
+                @js($isSkippable()) || this.getStepIndex(this.step) > this.getStepIndex(stepId)
85
+            )
86
+        },
87
+
88
+        updateQueryString: function () {
89
+            if (! @js($isStepPersistedInQueryString())) {
90
+                return
91
+            }
92
+
93
+            const url = new URL(window.location.href)
94
+            url.searchParams.set(@js($getStepQueryStringKey()), this.step)
95
+
96
+            history.pushState(null, document.title, url.toString())
97
+        },
98
+    }"
99
+    x-init="
100
+        $watch('step', () => updateQueryString())
101
+
102
+        step = getSteps().at({{ $getStartStep() - 1 }})
103
+
104
+        autofocusFields()
105
+    "
106
+    x-on:next-wizard-step.window="if ($event.detail.statePath === '{{ $statePath }}') nextStep()"
107
+    {{
108
+        $attributes
109
+            ->merge([
110
+                'id' => $getId(),
111
+            ], escape: false)
112
+            ->merge($getExtraAttributes(), escape: false)
113
+            ->merge($getExtraAlpineAttributes(), escape: false)
114
+            ->class([
115
+                'fi-fo-wizard',
116
+                'fi-contained rounded-xl bg-white shadow-sm ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10' => $isContained,
117
+            ])
118
+    }}
119
+>
120
+    <input
121
+        type="hidden"
122
+        value="{{
123
+            collect($getChildComponentContainer()->getComponents())
124
+                ->filter(static fn (\Filament\Forms\Components\Wizard\Step $step): bool => $step->isVisible())
125
+                ->map(static fn (\Filament\Forms\Components\Wizard\Step $step) => $step->getId())
126
+                ->values()
127
+                ->toJson()
128
+        }}"
129
+        x-ref="stepsData"
130
+    />
131
+
132
+    @foreach ($getChildComponentContainer()->getComponents() as $step)
133
+        <div
134
+            x-ref="step-{{ $step->getId() }}"
135
+            wire:key="{{ $this->getId() }}.{{ $statePath }}.{{ $step->getId() }}.step"
136
+            x-bind:class="{ 'hidden': step !== '{{ $step->getId() }}' }"
137
+        >
138
+            <x-filament::section
139
+                :id="'wizard-step-{{ $step->getId() }}'"
140
+                :icon="$step->getIcon()"
141
+            >
142
+                @if (!$step->isLabelHidden())
143
+                    <x-slot name="heading">
144
+                        {{ $step->getLabel() }}
145
+                    </x-slot>
146
+                @endif
147
+
148
+                @if (filled($description = $step->getDescription()))
149
+                    <x-slot name="description">
150
+                        {{ $description }}
151
+                    </x-slot>
152
+                @endif
153
+
154
+                {{ $step->getChildComponentContainer() }}
155
+
156
+                <footer
157
+                    @class([
158
+                        'fi-section-footer py-6',
159
+                    ])
160
+                >
161
+                    <div
162
+                        @class([
163
+                            'flex items-center justify-between gap-x-3',
164
+                        ])
165
+                    >
166
+                        <span
167
+                            x-cloak
168
+                            @if (! $previousAction->isDisabled())
169
+                                x-on:click="previousStep"
170
+                            @endif
171
+                            x-show="! isFirstStep()"
172
+                        >
173
+                            {{ $previousAction }}
174
+                        </span>
175
+
176
+                        <span x-show="isFirstStep()">
177
+                            {{ $getCancelAction() }}
178
+                        </span>
179
+
180
+                        <span
181
+                            x-cloak
182
+                            @if (! $nextAction->isDisabled())
183
+                                x-on:click="
184
+                                    $wire.dispatchFormEvent(
185
+                                        'wizard::nextStep',
186
+                                        '{{ $statePath }}',
187
+                                        getStepIndex(step),
188
+                                    )
189
+                                "
190
+                            @endif
191
+                            x-bind:class="{ 'hidden': isLastStep(), 'block': ! isLastStep() }"
192
+                        >
193
+                            {{ $nextAction }}
194
+                        </span>
195
+
196
+                        <span
197
+                            x-bind:class="{ 'hidden': ! isLastStep(), 'block': isLastStep() }"
198
+                        >
199
+                            {{ $getSubmitAction() }}
200
+                        </span>
201
+                    </div>
202
+                </footer>
203
+            </x-filament::section>
204
+        </div>
205
+    @endforeach
206
+</div>

Laden…
Annuleren
Opslaan