Andrew Wallo 8 月之前
父節點
當前提交
3bb4756c3d

+ 21
- 11
app/Filament/Company/Clusters/Settings/Pages/CompanyProfile.php 查看文件

8
 use App\Models\Locale\State;
8
 use App\Models\Locale\State;
9
 use App\Models\Setting\CompanyProfile as CompanyProfileModel;
9
 use App\Models\Setting\CompanyProfile as CompanyProfileModel;
10
 use App\Utilities\Localization\Timezone;
10
 use App\Utilities\Localization\Timezone;
11
+use CodeWithDennis\SimpleAlert\Components\Forms\SimpleAlert;
11
 use Filament\Actions\Action;
12
 use Filament\Actions\Action;
12
 use Filament\Actions\ActionGroup;
13
 use Filament\Actions\ActionGroup;
13
 use Filament\Forms\Components\Component;
14
 use Filament\Forms\Components\Component;
137
         return $form
138
         return $form
138
             ->schema([
139
             ->schema([
139
                 $this->getIdentificationSection(),
140
                 $this->getIdentificationSection(),
141
+                $this->getNeedsAddressCompletionAlert(),
140
                 $this->getLocationDetailsSection(),
142
                 $this->getLocationDetailsSection(),
141
                 $this->getLegalAndComplianceSection(),
143
                 $this->getLegalAndComplianceSection(),
142
             ])
144
             ])
155
                             ->email()
157
                             ->email()
156
                             ->localizeLabel()
158
                             ->localizeLabel()
157
                             ->maxLength(255)
159
                             ->maxLength(255)
158
-                            ->required(),
160
+                            ->softRequired(),
159
                         TextInput::make('phone_number')
161
                         TextInput::make('phone_number')
160
                             ->tel()
162
                             ->tel()
161
-                            ->nullable()
162
                             ->localizeLabel(),
163
                             ->localizeLabel(),
163
                     ])->columns(1),
164
                     ])->columns(1),
164
                 FileUpload::make('logo')
165
                 FileUpload::make('logo')
184
             ])->columns();
185
             ])->columns();
185
     }
186
     }
186
 
187
 
188
+    protected function getNeedsAddressCompletionAlert(): Component
189
+    {
190
+        return SimpleAlert::make('needsAddressCompletion')
191
+            ->warning()
192
+            ->border()
193
+            ->icon('heroicon-o-exclamation-triangle')
194
+            ->title('Address Information Incomplete')
195
+            ->description('Please complete the required address information for proper business operations.')
196
+            ->visible(fn (CompanyProfileModel $record) => $record->address->isIncomplete())
197
+            ->columnSpanFull();
198
+    }
199
+
187
     protected function getLocationDetailsSection(): Component
200
     protected function getLocationDetailsSection(): Component
188
     {
201
     {
189
         return Section::make('Address Information')
202
         return Section::make('Address Information')
193
                     ->default('general'),
206
                     ->default('general'),
194
                 TextInput::make('address_line_1')
207
                 TextInput::make('address_line_1')
195
                     ->label('Address Line 1')
208
                     ->label('Address Line 1')
196
-                    ->required()
209
+                    ->softRequired()
197
                     ->maxLength(255),
210
                     ->maxLength(255),
198
                 TextInput::make('address_line_2')
211
                 TextInput::make('address_line_2')
199
                     ->label('Address Line 2')
212
                     ->label('Address Line 2')
200
                     ->maxLength(255),
213
                     ->maxLength(255),
201
                 CountrySelect::make('country')
214
                 CountrySelect::make('country')
202
                     ->clearStateField()
215
                     ->clearStateField()
203
-                    ->required(),
216
+                    ->softRequired(),
204
                 Select::make('state_id')
217
                 Select::make('state_id')
205
                     ->localizeLabel('State / Province')
218
                     ->localizeLabel('State / Province')
206
                     ->searchable()
219
                     ->searchable()
207
-                    ->options(static fn (Get $get) => State::getStateOptions($get('country')))
208
-                    ->nullable(),
220
+                    ->options(static fn (Get $get) => State::getStateOptions($get('country'))),
209
                 TextInput::make('city')
221
                 TextInput::make('city')
210
                     ->localizeLabel('City / Town')
222
                     ->localizeLabel('City / Town')
211
-                    ->required()
223
+                    ->softRequired()
212
                     ->maxLength(255),
224
                     ->maxLength(255),
213
                 TextInput::make('postal_code')
225
                 TextInput::make('postal_code')
214
                     ->label('Postal Code / Zip Code')
226
                     ->label('Postal Code / Zip Code')
215
-                    ->required()
216
                     ->maxLength(255),
227
                     ->maxLength(255),
217
             ])
228
             ])
218
             ->columns(2);
229
             ->columns(2);
225
                 Select::make('entity_type')
236
                 Select::make('entity_type')
226
                     ->localizeLabel()
237
                     ->localizeLabel()
227
                     ->options(EntityType::class)
238
                     ->options(EntityType::class)
228
-                    ->required(),
239
+                    ->softRequired(),
229
                 TextInput::make('tax_id')
240
                 TextInput::make('tax_id')
230
                     ->localizeLabel('Tax ID')
241
                     ->localizeLabel('Tax ID')
231
-                    ->maxLength(50)
232
-                    ->nullable(),
242
+                    ->maxLength(50),
233
             ])->columns();
243
             ])->columns();
234
     }
244
     }
235
 
245
 

+ 2
- 0
app/Filament/Company/Resources/Sales/RecurringInvoiceResource/Pages/ViewRecurringInvoice.php 查看文件

56
             ->schema([
56
             ->schema([
57
                 SimpleAlert::make('scheduleIsNotSet')
57
                 SimpleAlert::make('scheduleIsNotSet')
58
                     ->info()
58
                     ->info()
59
+                    ->border()
60
+                    ->icon('heroicon-o-information-circle')
59
                     ->title('Schedule Not Set')
61
                     ->title('Schedule Not Set')
60
                     ->description('The schedule for this recurring invoice has not been set. You must set a schedule before you can approve this draft and start creating invoices.')
62
                     ->description('The schedule for this recurring invoice has not been set. You must set a schedule before you can approve this draft and start creating invoices.')
61
                     ->visible(fn (RecurringInvoice $record) => ! $record->hasValidStartDate())
63
                     ->visible(fn (RecurringInvoice $record) => ! $record->hasValidStartDate())

+ 5
- 0
app/Models/Common/Address.php 查看文件

86
             ]);
86
             ]);
87
         });
87
         });
88
     }
88
     }
89
+
90
+    public function isIncomplete(): bool
91
+    {
92
+        return empty($this->address_line_1) || empty($this->city);
93
+    }
89
 }
94
 }

+ 0
- 4
database/migrations/2023_09_03_100000_create_accounting_tables.php 查看文件

51
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
51
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
52
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
52
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
53
             $table->timestamps();
53
             $table->timestamps();
54
-
55
-            $table->unique(['company_id', 'code']);
56
         });
54
         });
57
 
55
 
58
         Schema::create('bank_accounts', function (Blueprint $table) {
56
         Schema::create('bank_accounts', function (Blueprint $table) {
66
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
64
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
67
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
65
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
68
             $table->timestamps();
66
             $table->timestamps();
69
-
70
-            $table->unique(['company_id', 'account_id']);
71
         });
67
         });
72
 
68
 
73
         Schema::create('connected_bank_accounts', function (Blueprint $table) {
69
         Schema::create('connected_bank_accounts', function (Blueprint $table) {

+ 0
- 2
database/migrations/2024_11_14_230753_create_adjustments_table.php 查看文件

28
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
28
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
29
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
29
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
30
             $table->timestamps();
30
             $table->timestamps();
31
-
32
-            $table->unique(['company_id', 'account_id']);
33
         });
31
         });
34
     }
32
     }
35
 
33
 

+ 3
- 3
package-lock.json 查看文件

1074
             }
1074
             }
1075
         },
1075
         },
1076
         "node_modules/caniuse-lite": {
1076
         "node_modules/caniuse-lite": {
1077
-            "version": "1.0.30001692",
1078
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz",
1079
-            "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==",
1077
+            "version": "1.0.30001695",
1078
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz",
1079
+            "integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==",
1080
             "dev": true,
1080
             "dev": true,
1081
             "funding": [
1081
             "funding": [
1082
                 {
1082
                 {

+ 0
- 0
resources/views/vendor/filament-simple-alert/.gitkeep 查看文件


+ 15
- 0
resources/views/vendor/filament-simple-alert/components/simple-alert-entry.blade.php 查看文件

1
+<x-dynamic-component :component="$getEntryWrapperView()" :entry="$entry">
2
+    <x-filament-simple-alert::simple-alert
3
+            :icon="$getIcon()"
4
+            :icon-vertical-alignment="$getIconVerticalAlignment()"
5
+            :color="$getColor()"
6
+            :title="$getTitle()"
7
+            :description="$getDescription()"
8
+            :link="$getLink()"
9
+            :link-label="$getLinkLabel()"
10
+            :link-blank="$getLinkBlank()"
11
+            :actions-vertical-alignment="$getActionsVerticalAlignment()"
12
+            :actions="$getActions()"
13
+            :border="$getBorder()"
14
+    />
15
+</x-dynamic-component>

+ 15
- 0
resources/views/vendor/filament-simple-alert/components/simple-alert-field.blade.php 查看文件

1
+<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
2
+    <x-filament-simple-alert::simple-alert
3
+            :icon="$getIcon()"
4
+            :icon-vertical-alignment="$getIconVerticalAlignment()"
5
+            :color="$getColor()"
6
+            :title="$getTitle()"
7
+            :description="$getDescription()"
8
+            :link="$getLink()"
9
+            :link-label="$getLinkLabel()"
10
+            :link-blank="$getLinkBlank()"
11
+            :actions-vertical-alignment="$getActionsVerticalAlignment()"
12
+            :actions="$getActions()"
13
+            :border="$getBorder()"
14
+    />
15
+</x-dynamic-component>

+ 84
- 0
resources/views/vendor/filament-simple-alert/components/simple-alert.blade.php 查看文件

1
+@props([
2
+    'actions' => null,
3
+    'actionsVerticalAlignment' => 'center',
4
+    'border' => false,
5
+    'color' => null,
6
+    'description' => null,
7
+    'icon' => null,
8
+    'iconVerticalAlignment' => 'center',
9
+    'link' => null,
10
+    'linkBlank' => false,
11
+    'linkLabel' => null,
12
+    'title' => null,
13
+])
14
+
15
+@php
16
+    use function Filament\Support\get_color_css_variables;
17
+
18
+    $colors = \Illuminate\Support\Arr::toCssStyles([
19
+           get_color_css_variables($color, shades: [50, 100, 400, 500, 700, 800]),
20
+   ]);
21
+@endphp
22
+
23
+<div x-data="{}"
24
+     @class([
25
+       'filament-simple-alert rounded-md bg-custom-50 p-4 dark:bg-custom-400/10',
26
+       'ring-1 ring-custom-100 dark:ring-custom-500/70' => $border,
27
+     ])
28
+     style="{{ $colors }}">
29
+    <div class="flex gap-3">
30
+        @if($icon)
31
+            <div @class([
32
+                'flex-shrink-0',
33
+                $iconVerticalAlignment === 'start' ? 'self-start' : 'self-center',
34
+            ])>
35
+                <x-filament::icon
36
+                        :icon="$icon"
37
+                        class="h-5 w-5 text-custom-400"
38
+                />
39
+            </div>
40
+        @endif
41
+        <div class="items-center flex-1 md:flex md:justify-between space-y-3 md:space-y-0 md:gap-3">
42
+            @if($title || $description)
43
+                <div class="space-y-0.5">
44
+                    @if($title)
45
+                        <p class="text-sm font-medium text-custom-800 dark:text-white">
46
+                            {{ $title }}
47
+                        </p>
48
+                    @endif
49
+                    @if($description)
50
+                        <p class="text-sm text-custom-700 dark:text-white">
51
+                            {{ $description }}
52
+                        </p>
53
+                    @endif
54
+                </div>
55
+            @endif
56
+            @if($link || $actions)
57
+                <div @class([
58
+                  'flex items-center gap-3',
59
+                    $actionsVerticalAlignment === 'start' ? 'self-start' : 'self-center',
60
+                ])>
61
+                    <div class="flex items-center whitespace-nowrap gap-3">
62
+                        @if($link)
63
+                            <p class="text-sm md:mt-0 self-center">
64
+                                <a href="{{ $link }}" {{ $linkBlank ? 'target="_blank"' : '' }} class="whitespace-nowrap font-medium text-custom-400 hover:text-custom-500">
65
+                                    {{ $linkLabel }}
66
+                                    <span aria-hidden="true"> &rarr;</span>
67
+                                </a>
68
+                            </p>
69
+                        @endif
70
+                        @if($actions)
71
+                            <div class="gap-3 flex items-center justify-start">
72
+                                @foreach ($actions as $action)
73
+                                    @if ($action->isVisible())
74
+                                        {{ $action }}
75
+                                    @endif
76
+                                @endforeach
77
+                            </div>
78
+                        @endif
79
+                    </div>
80
+                </div>
81
+            @endif
82
+        </div>
83
+    </div>
84
+</div>

Loading…
取消
儲存