瀏覽代碼

Merge pull request #161 from andrewdwallo/development-3.x

Development 3.x
3.x
Andrew Wallo 5 月之前
父節點
當前提交
60f05c6fe9
沒有連結到貢獻者的電子郵件帳戶。
共有 38 個檔案被更改,包括 606 行新增800 行删除
  1. 17
    9
      app/DTO/DocumentDTO.php
  2. 1
    1
      app/DTO/DocumentLabelDTO.php
  3. 6
    1
      app/DTO/DocumentPreviewDTO.php
  4. 1
    1
      app/Enums/Accounting/DocumentType.php
  5. 3
    0
      app/Enums/Setting/Template.php
  6. 7
    18
      app/Filament/Company/Clusters/Settings/Resources/DocumentDefaultResource.php
  7. 47
    7
      app/Filament/Company/Pages/Accounting/Transactions.php
  8. 0
    6
      app/Filament/Company/Resources/Sales/EstimateResource/Pages/ViewEstimate.php
  9. 0
    5
      app/Filament/Company/Resources/Sales/InvoiceResource/Pages/ViewInvoice.php
  10. 0
    6
      app/Filament/Company/Resources/Sales/RecurringInvoiceResource/Pages/ViewRecurringInvoice.php
  11. 24
    0
      app/Filament/Forms/Components/CustomTableRepeater.php
  12. 0
    8
      app/Filament/Forms/Components/DocumentHeaderSection.php
  13. 45
    0
      app/Filament/Forms/Components/DocumentPreview.php
  14. 15
    0
      app/Filament/Infolists/Components/DocumentPreview.php
  15. 38
    4
      app/View/Models/DocumentTotalViewModel.php
  16. 29
    0
      resources/css/filament/company/theme.css
  17. 37
    10
      resources/css/filament/company/tooltip.css
  18. 15
    12
      resources/views/components/company/document-template/container.blade.php
  19. 1
    1
      resources/views/components/company/document-template/footer.blade.php
  20. 1
    1
      resources/views/components/company/tables/reports/account-transactions.blade.php
  21. 1
    1
      resources/views/components/company/tables/reports/balance-sheet-summary.blade.php
  22. 1
    1
      resources/views/components/company/tables/reports/balance-sheet.blade.php
  23. 2
    2
      resources/views/components/company/tables/reports/cash-flow-statement-summary.blade.php
  24. 2
    2
      resources/views/components/company/tables/reports/cash-flow-statement.blade.php
  25. 1
    1
      resources/views/components/company/tables/reports/income-statement-summary.blade.php
  26. 1
    1
      resources/views/components/company/tables/reports/income-statement.blade.php
  27. 20
    0
      resources/views/components/tooltip.blade.php
  28. 45
    49
      resources/views/filament/company/components/document-templates/classic.blade.php
  29. 67
    63
      resources/views/filament/company/components/document-templates/default.blade.php
  30. 51
    61
      resources/views/filament/company/components/document-templates/modern.blade.php
  31. 1
    1
      resources/views/filament/company/pages/accounting/chart.blade.php
  32. 25
    22
      resources/views/filament/forms/components/custom-table-repeater.blade.php
  33. 21
    0
      resources/views/filament/forms/components/document-preview.blade.php
  34. 78
    57
      resources/views/filament/forms/components/document-totals.blade.php
  35. 3
    2
      resources/views/filament/infolists/components/document-preview.blade.php
  36. 0
    153
      resources/views/filament/infolists/components/document-templates/classic.blade.php
  37. 0
    147
      resources/views/filament/infolists/components/document-templates/default.blade.php
  38. 0
    147
      resources/views/filament/infolists/components/document-templates/modern.blade.php

+ 17
- 9
app/DTO/DocumentDTO.php 查看文件

2
 
2
 
3
 namespace App\DTO;
3
 namespace App\DTO;
4
 
4
 
5
+use App\Enums\Accounting\DocumentType;
5
 use App\Enums\Setting\Font;
6
 use App\Enums\Setting\Font;
6
 use App\Models\Accounting\Document;
7
 use App\Models\Accounting\Document;
7
 use App\Models\Setting\DocumentDefault;
8
 use App\Models\Setting\DocumentDefault;
30
         public ?string $discount,
31
         public ?string $discount,
31
         public ?string $tax,
32
         public ?string $tax,
32
         public string $total,
33
         public string $total,
33
-        public string $amountDue,
34
+        public ?string $amountDue,
34
         public CompanyDTO $company,
35
         public CompanyDTO $company,
35
         public ClientDTO $client,
36
         public ClientDTO $client,
36
         public iterable $lineItems,
37
         public iterable $lineItems,
50
 
51
 
51
         $currencyCode = $document->currency_code ?? CurrencyAccessor::getDefaultCurrency();
52
         $currencyCode = $document->currency_code ?? CurrencyAccessor::getDefaultCurrency();
52
 
53
 
53
-        $discount = $document->discount_total > 0 ? self::formatToMoney($document->discount_total, $currencyCode) : null;
54
-        $tax = $document->tax_total > 0 ? self::formatToMoney($document->tax_total, $currencyCode) : null;
54
+        $discount = $document->discount_total > 0
55
+            ? self::formatToMoney($document->discount_total, $currencyCode)
56
+            : null;
55
 
57
 
56
-        if (! $discount && ! $tax) {
57
-            $subtotal = null;
58
-        } else {
59
-            $subtotal = self::formatToMoney($document->subtotal, $currencyCode);
60
-        }
58
+        $tax = $document->tax_total > 0
59
+            ? self::formatToMoney($document->tax_total, $currencyCode)
60
+            : null;
61
+
62
+        $subtotal = ($discount || $tax)
63
+            ? self::formatToMoney($document->subtotal, $currencyCode)
64
+            : null;
65
+
66
+        $amountDue = $document::documentType() !== DocumentType::Estimate ?
67
+            self::formatToMoney($document->amountDue(), $currencyCode) :
68
+            null;
61
 
69
 
62
         return new self(
70
         return new self(
63
             header: $document->header,
71
             header: $document->header,
74
             discount: $discount,
82
             discount: $discount,
75
             tax: $tax,
83
             tax: $tax,
76
             total: self::formatToMoney($document->total, $currencyCode),
84
             total: self::formatToMoney($document->total, $currencyCode),
77
-            amountDue: self::formatToMoney($document->amountDue(), $currencyCode),
85
+            amountDue: $amountDue,
78
             company: CompanyDTO::fromModel($document->company),
86
             company: CompanyDTO::fromModel($document->company),
79
             client: ClientDTO::fromModel($document->client),
87
             client: ClientDTO::fromModel($document->client),
80
             lineItems: $document->lineItems->map(fn ($item) => LineItemDTO::fromModel($item)),
88
             lineItems: $document->lineItems->map(fn ($item) => LineItemDTO::fromModel($item)),

+ 1
- 1
app/DTO/DocumentLabelDTO.php 查看文件

10
         public string $referenceNumber,
10
         public string $referenceNumber,
11
         public string $date,
11
         public string $date,
12
         public string $dueDate,
12
         public string $dueDate,
13
-        public string $amountDue,
13
+        public ?string $amountDue,
14
     ) {}
14
     ) {}
15
 
15
 
16
     public function toArray(): array
16
     public function toArray(): array

+ 6
- 1
app/DTO/DocumentPreviewDTO.php 查看文件

2
 
2
 
3
 namespace App\DTO;
3
 namespace App\DTO;
4
 
4
 
5
+use App\Enums\Accounting\DocumentType;
5
 use App\Enums\Setting\Font;
6
 use App\Enums\Setting\Font;
6
 use App\Enums\Setting\PaymentTerms;
7
 use App\Enums\Setting\PaymentTerms;
7
 use App\Models\Setting\DocumentDefault;
8
 use App\Models\Setting\DocumentDefault;
15
 
16
 
16
         $paymentTerms = PaymentTerms::parse($data['payment_terms']) ?? $settings->payment_terms;
17
         $paymentTerms = PaymentTerms::parse($data['payment_terms']) ?? $settings->payment_terms;
17
 
18
 
19
+        $amountDue = $settings->type !== DocumentType::Estimate ?
20
+            self::formatToMoney('950', null) :
21
+            null;
22
+
18
         return new self(
23
         return new self(
19
             header: $data['header'] ?? $settings->header ?? 'Invoice',
24
             header: $data['header'] ?? $settings->header ?? 'Invoice',
20
             subheader: $data['subheader'] ?? $settings->subheader,
25
             subheader: $data['subheader'] ?? $settings->subheader,
30
             discount: self::formatToMoney('100', null),
35
             discount: self::formatToMoney('100', null),
31
             tax: self::formatToMoney('50', null),
36
             tax: self::formatToMoney('50', null),
32
             total: self::formatToMoney('950', null),
37
             total: self::formatToMoney('950', null),
33
-            amountDue: self::formatToMoney('950', null),
38
+            amountDue: $amountDue,
34
             company: CompanyDTO::fromModel($company),
39
             company: CompanyDTO::fromModel($company),
35
             client: ClientPreviewDTO::fake(),
40
             client: ClientPreviewDTO::fake(),
36
             lineItems: LineItemPreviewDTO::fakeItems(),
41
             lineItems: LineItemPreviewDTO::fakeItems(),

+ 1
- 1
app/Enums/Accounting/DocumentType.php 查看文件

79
                 referenceNumber: 'Reference Number',
79
                 referenceNumber: 'Reference Number',
80
                 date: 'Estimate Date',
80
                 date: 'Estimate Date',
81
                 dueDate: 'Expiration Date',
81
                 dueDate: 'Expiration Date',
82
-                amountDue: 'Grand Total',
82
+                amountDue: null,
83
             ),
83
             ),
84
             self::Bill => new DocumentLabelDTO(
84
             self::Bill => new DocumentLabelDTO(
85
                 title: self::Bill->getLabel(),
85
                 title: self::Bill->getLabel(),

+ 3
- 0
app/Enums/Setting/Template.php 查看文件

2
 
2
 
3
 namespace App\Enums\Setting;
3
 namespace App\Enums\Setting;
4
 
4
 
5
+use App\Enums\Concerns\ParsesEnum;
5
 use Filament\Support\Contracts\HasLabel;
6
 use Filament\Support\Contracts\HasLabel;
6
 
7
 
7
 enum Template: string implements HasLabel
8
 enum Template: string implements HasLabel
8
 {
9
 {
10
+    use ParsesEnum;
11
+
9
     case Default = 'default';
12
     case Default = 'default';
10
     case Modern = 'modern';
13
     case Modern = 'modern';
11
     case Classic = 'classic';
14
     case Classic = 'classic';

+ 7
- 18
app/Filament/Company/Clusters/Settings/Resources/DocumentDefaultResource.php 查看文件

9
 use App\Enums\Setting\Template;
9
 use App\Enums\Setting\Template;
10
 use App\Filament\Company\Clusters\Settings;
10
 use App\Filament\Company\Clusters\Settings;
11
 use App\Filament\Company\Clusters\Settings\Resources\DocumentDefaultResource\Pages;
11
 use App\Filament\Company\Clusters\Settings\Resources\DocumentDefaultResource\Pages;
12
+use App\Filament\Forms\Components\DocumentPreview;
12
 use App\Models\Setting\DocumentDefault;
13
 use App\Models\Setting\DocumentDefault;
13
 use Filament\Forms;
14
 use Filament\Forms;
14
 use Filament\Forms\Components\Component;
15
 use Filament\Forms\Components\Component;
128
                             ->options(Template::class),
129
                             ->options(Template::class),
129
                         ...static::getColumnLabelsSchema(),
130
                         ...static::getColumnLabelsSchema(),
130
                     ])->columnSpan(1),
131
                     ])->columnSpan(1),
131
-                Forms\Components\Grid::make()
132
-                    ->schema([
133
-                        Forms\Components\ViewField::make('preview.default')
134
-                            ->columnSpan(2)
135
-                            ->hiddenLabel()
136
-                            ->visible(static fn (Get $get) => $get('template') === 'default')
137
-                            ->view('filament.company.components.document-templates.default'),
138
-                        Forms\Components\ViewField::make('preview.modern')
139
-                            ->columnSpan(2)
140
-                            ->hiddenLabel()
141
-                            ->visible(static fn (Get $get) => $get('template') === 'modern')
142
-                            ->view('filament.company.components.document-templates.modern'),
143
-                        Forms\Components\ViewField::make('preview.classic')
144
-                            ->columnSpan(2)
145
-                            ->hiddenLabel()
146
-                            ->visible(static fn (Get $get) => $get('template') === 'classic')
147
-                            ->view('filament.company.components.document-templates.classic'),
148
-                    ])->columnSpan(2),
132
+                DocumentPreview::make()
133
+                    ->template(static fn (Get $get) => Template::parse($get('template')))
134
+                    ->preview()
135
+                    ->columnSpan([
136
+                        'lg' => 2,
137
+                    ]),
149
             ])->columns(3);
138
             ])->columns(3);
150
     }
139
     }
151
 
140
 

+ 47
- 7
app/Filament/Company/Pages/Accounting/Transactions.php 查看文件

8
 use App\Enums\Accounting\TransactionType;
8
 use App\Enums\Accounting\TransactionType;
9
 use App\Facades\Accounting;
9
 use App\Facades\Accounting;
10
 use App\Filament\Company\Pages\Service\ConnectedAccount;
10
 use App\Filament\Company\Pages\Service\ConnectedAccount;
11
+use App\Filament\Forms\Components\CustomTableRepeater;
11
 use App\Filament\Forms\Components\DateRangeSelect;
12
 use App\Filament\Forms\Components\DateRangeSelect;
12
-use App\Filament\Forms\Components\JournalEntryRepeater;
13
 use App\Filament\Tables\Actions\ReplicateBulkAction;
13
 use App\Filament\Tables\Actions\ReplicateBulkAction;
14
 use App\Models\Accounting\Account;
14
 use App\Models\Accounting\Account;
15
 use App\Models\Accounting\JournalEntry;
15
 use App\Models\Accounting\JournalEntry;
383
                             ->label('Edit journal transaction')
383
                             ->label('Edit journal transaction')
384
                             ->modalHeading('Journal Entry')
384
                             ->modalHeading('Journal Entry')
385
                             ->modalWidth(MaxWidth::Screen)
385
                             ->modalWidth(MaxWidth::Screen)
386
+                            ->extraModalWindowAttributes([
387
+                                'class' => 'journal-transaction-modal',
388
+                            ])
386
                             ->form(fn (Form $form) => $this->journalTransactionForm($form))
389
                             ->form(fn (Form $form) => $this->journalTransactionForm($form))
387
                             ->afterFormFilled(function (Transaction $transaction) {
390
                             ->afterFormFilled(function (Transaction $transaction) {
388
                                 $debitAmounts = $transaction->journalEntries->sumDebits()->getAmount();
391
                                 $debitAmounts = $transaction->journalEntries->sumDebits()->getAmount();
538
             ]);
541
             ]);
539
     }
542
     }
540
 
543
 
541
-    protected function getJournalEntriesTableRepeater(): JournalEntryRepeater
544
+    protected function getJournalEntriesTableRepeater(): CustomTableRepeater
542
     {
545
     {
543
-        return JournalEntryRepeater::make('journalEntries')
546
+        return CustomTableRepeater::make('journalEntries')
544
             ->relationship('journalEntries')
547
             ->relationship('journalEntries')
545
             ->hiddenLabel()
548
             ->hiddenLabel()
546
             ->columns(4)
549
             ->columns(4)
547
             ->headers($this->getJournalEntriesTableRepeaterHeaders())
550
             ->headers($this->getJournalEntriesTableRepeaterHeaders())
548
             ->schema($this->getJournalEntriesTableRepeaterSchema())
551
             ->schema($this->getJournalEntriesTableRepeaterSchema())
549
-            ->streamlined()
550
-            ->deletable(fn (JournalEntryRepeater $repeater) => $repeater->getItemsCount() > 2)
552
+            ->deletable(fn (CustomTableRepeater $repeater) => $repeater->getItemsCount() > 2)
551
             ->deleteAction(function (Forms\Components\Actions\Action $action) {
553
             ->deleteAction(function (Forms\Components\Actions\Action $action) {
552
                 return $action
554
                 return $action
553
-                    ->action(function (array $arguments, JournalEntryRepeater $component): void {
555
+                    ->action(function (array $arguments, CustomTableRepeater $component): void {
554
                         $items = $component->getState();
556
                         $items = $component->getState();
555
 
557
 
556
                         $amount = $items[$arguments['item']]['amount'];
558
                         $amount = $items[$arguments['item']]['amount'];
565
                         $component->callAfterStateUpdated();
567
                         $component->callAfterStateUpdated();
566
                     });
568
                     });
567
             })
569
             })
570
+            ->rules([
571
+                function () {
572
+                    return function (string $attribute, $value, \Closure $fail) {
573
+                        if (empty($value) || ! is_array($value)) {
574
+                            $fail('Journal entries are required.');
575
+
576
+                            return;
577
+                        }
578
+
579
+                        $hasDebit = false;
580
+                        $hasCredit = false;
581
+
582
+                        foreach ($value as $entry) {
583
+                            if (! isset($entry['type'])) {
584
+                                continue;
585
+                            }
586
+
587
+                            if (JournalEntryType::parse($entry['type'])->isDebit()) {
588
+                                $hasDebit = true;
589
+                            } elseif (JournalEntryType::parse($entry['type'])->isCredit()) {
590
+                                $hasCredit = true;
591
+                            }
592
+
593
+                            if ($hasDebit && $hasCredit) {
594
+                                break;
595
+                            }
596
+                        }
597
+
598
+                        if (! $hasDebit) {
599
+                            $fail('At least one debit entry is required.');
600
+                        }
601
+
602
+                        if (! $hasCredit) {
603
+                            $fail('At least one credit entry is required.');
604
+                        }
605
+                    };
606
+                },
607
+            ])
568
             ->minItems(2)
608
             ->minItems(2)
569
             ->defaultItems(2)
609
             ->defaultItems(2)
570
             ->addable(false)
610
             ->addable(false)
634
             ->color($type->isDebit() ? 'primary' : 'gray')
674
             ->color($type->isDebit() ? 'primary' : 'gray')
635
             ->iconSize(IconSize::Small)
675
             ->iconSize(IconSize::Small)
636
             ->iconPosition(IconPosition::Before)
676
             ->iconPosition(IconPosition::Before)
637
-            ->action(function (JournalEntryRepeater $component) use ($type) {
677
+            ->action(function (CustomTableRepeater $component) use ($type) {
638
                 $state = $component->getState();
678
                 $state = $component->getState();
639
                 $newUuid = (string) Str::uuid();
679
                 $newUuid = (string) Str::uuid();
640
                 $state[$newUuid] = $this->defaultEntry($type);
680
                 $state[$newUuid] = $this->defaultEntry($type);

+ 0
- 6
app/Filament/Company/Resources/Sales/EstimateResource/Pages/ViewEstimate.php 查看文件

17
 use Filament\Support\Enums\FontWeight;
17
 use Filament\Support\Enums\FontWeight;
18
 use Filament\Support\Enums\IconPosition;
18
 use Filament\Support\Enums\IconPosition;
19
 use Filament\Support\Enums\IconSize;
19
 use Filament\Support\Enums\IconSize;
20
-use Filament\Support\Enums\MaxWidth;
21
 use Illuminate\Support\HtmlString;
20
 use Illuminate\Support\HtmlString;
22
 
21
 
23
 class ViewEstimate extends ViewRecord
22
 class ViewEstimate extends ViewRecord
28
         'refresh' => '$refresh',
27
         'refresh' => '$refresh',
29
     ];
28
     ];
30
 
29
 
31
-    public function getMaxContentWidth(): MaxWidth | string | null
32
-    {
33
-        return MaxWidth::SixExtraLarge;
34
-    }
35
-
36
     protected function getHeaderActions(): array
30
     protected function getHeaderActions(): array
37
     {
31
     {
38
         return [
32
         return [

+ 0
- 5
app/Filament/Company/Resources/Sales/InvoiceResource/Pages/ViewInvoice.php 查看文件

28
         'refresh' => '$refresh',
28
         'refresh' => '$refresh',
29
     ];
29
     ];
30
 
30
 
31
-    public function getMaxContentWidth(): MaxWidth | string | null
32
-    {
33
-        return MaxWidth::SixExtraLarge;
34
-    }
35
-
36
     protected function getHeaderActions(): array
31
     protected function getHeaderActions(): array
37
     {
32
     {
38
         return [
33
         return [

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

19
 use Filament\Support\Enums\FontWeight;
19
 use Filament\Support\Enums\FontWeight;
20
 use Filament\Support\Enums\IconPosition;
20
 use Filament\Support\Enums\IconPosition;
21
 use Filament\Support\Enums\IconSize;
21
 use Filament\Support\Enums\IconSize;
22
-use Filament\Support\Enums\MaxWidth;
23
 use Illuminate\Support\HtmlString;
22
 use Illuminate\Support\HtmlString;
24
 use Illuminate\Support\Str;
23
 use Illuminate\Support\Str;
25
 
24
 
27
 {
26
 {
28
     protected static string $resource = RecurringInvoiceResource::class;
27
     protected static string $resource = RecurringInvoiceResource::class;
29
 
28
 
30
-    public function getMaxContentWidth(): MaxWidth | string | null
31
-    {
32
-        return MaxWidth::SixExtraLarge;
33
-    }
34
-
35
     protected function getHeaderActions(): array
29
     protected function getHeaderActions(): array
36
     {
30
     {
37
         return [
31
         return [

+ 24
- 0
app/Filament/Forms/Components/CustomTableRepeater.php 查看文件

5
 use Awcodes\TableRepeater\Components\TableRepeater;
5
 use Awcodes\TableRepeater\Components\TableRepeater;
6
 use Closure;
6
 use Closure;
7
 use Filament\Forms\Components\Actions\Action;
7
 use Filament\Forms\Components\Actions\Action;
8
+use Filament\Support\Enums\MaxWidth;
9
+use Illuminate\Contracts\Support\Htmlable;
10
+use Illuminate\Contracts\View\View;
8
 
11
 
9
 class CustomTableRepeater extends TableRepeater
12
 class CustomTableRepeater extends TableRepeater
10
 {
13
 {
12
 
15
 
13
     protected bool | Closure $reorderAtStart = false;
16
     protected bool | Closure $reorderAtStart = false;
14
 
17
 
18
+    protected View | Htmlable | Closure | null $footerItem = null;
19
+
15
     /**
20
     /**
16
      * @var array<string> | Closure | null
21
      * @var array<string> | Closure | null
17
      */
22
      */
48
         return $this->evaluate($this->reorderAtStart) && $this->isReorderable();
53
         return $this->evaluate($this->reorderAtStart) && $this->isReorderable();
49
     }
54
     }
50
 
55
 
56
+    public function footerItem(View | Htmlable | Closure | null $footer = null): static
57
+    {
58
+        $this->footerItem = $footer;
59
+
60
+        return $this;
61
+    }
62
+
63
+    public function getFooterItem(): View | Htmlable | null
64
+    {
65
+        return $this->evaluate($this->footerItem);
66
+    }
67
+
68
+    public function hasFooterItem(): bool
69
+    {
70
+        return $this->footerItem !== null;
71
+    }
72
+
51
     /**
73
     /**
52
      * @param  array<string> | Closure | null  $attributes
74
      * @param  array<string> | Closure | null  $attributes
53
      */
75
      */
72
 
94
 
73
         $this->minItems(1);
95
         $this->minItems(1);
74
 
96
 
97
+        $this->stackAt(MaxWidth::Large);
98
+
75
         $this->extraAttributes(function (): array {
99
         $this->extraAttributes(function (): array {
76
             $attributes = [];
100
             $attributes = [];
77
 
101
 

+ 0
- 8
app/Filament/Forms/Components/DocumentHeaderSection.php 查看文件

2
 
2
 
3
 namespace App\Filament\Forms\Components;
3
 namespace App\Filament\Forms\Components;
4
 
4
 
5
-use App\DTO\CompanyDTO;
6
 use Closure;
5
 use Closure;
7
 use Filament\Forms\Components\FileUpload;
6
 use Filament\Forms\Components\FileUpload;
8
 use Filament\Forms\Components\Group;
7
 use Filament\Forms\Components\Group;
9
 use Filament\Forms\Components\Section;
8
 use Filament\Forms\Components\Section;
10
 use Filament\Forms\Components\Split;
9
 use Filament\Forms\Components\Split;
11
 use Filament\Forms\Components\TextInput;
10
 use Filament\Forms\Components\TextInput;
12
-use Filament\Forms\Components\View;
13
 use Filament\Support\Enums\MaxWidth;
11
 use Filament\Support\Enums\MaxWidth;
14
 use Illuminate\Support\Facades\Auth;
12
 use Illuminate\Support\Facades\Auth;
15
 use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
13
 use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
41
         $this->collapsible();
39
         $this->collapsible();
42
         $this->collapsed();
40
         $this->collapsed();
43
 
41
 
44
-        $company = Auth::user()->currentCompany;
45
-
46
         $this->schema([
42
         $this->schema([
47
             Split::make([
43
             Split::make([
48
                 Group::make([
44
                 Group::make([
72
                         ->default(fn () => $this->getDefaultHeader()),
68
                         ->default(fn () => $this->getDefaultHeader()),
73
                     TextInput::make('subheader')
69
                     TextInput::make('subheader')
74
                         ->default(fn () => $this->getDefaultSubheader()),
70
                         ->default(fn () => $this->getDefaultSubheader()),
75
-                    View::make('filament.forms.components.company-info')
76
-                        ->viewData([
77
-                            'companyDTO' => CompanyDTO::fromModel($company),
78
-                        ]),
79
                 ])->grow(true),
71
                 ])->grow(true),
80
             ])->from('md'),
72
             ])->from('md'),
81
         ]);
73
         ]);

+ 45
- 0
app/Filament/Forms/Components/DocumentPreview.php 查看文件

1
+<?php
2
+
3
+namespace App\Filament\Forms\Components;
4
+
5
+use App\Enums\Setting\Template;
6
+use Closure;
7
+use Filament\Forms\Components\Grid;
8
+
9
+class DocumentPreview extends Grid
10
+{
11
+    protected string $view = 'filament.forms.components.document-preview';
12
+
13
+    protected bool | Closure $isPreview = false;
14
+
15
+    protected Template | Closure $template = Template::Default;
16
+
17
+    protected function setUp(): void
18
+    {
19
+        parent::setUp();
20
+    }
21
+
22
+    public function preview(bool | Closure $condition = true): static
23
+    {
24
+        $this->isPreview = $condition;
25
+
26
+        return $this;
27
+    }
28
+
29
+    public function template(Template | Closure $template): static
30
+    {
31
+        $this->template = $template;
32
+
33
+        return $this;
34
+    }
35
+
36
+    public function isPreview(): bool
37
+    {
38
+        return (bool) $this->evaluate($this->isPreview);
39
+    }
40
+
41
+    public function getTemplate(): Template
42
+    {
43
+        return $this->evaluate($this->template);
44
+    }
45
+}

+ 15
- 0
app/Filament/Infolists/Components/DocumentPreview.php 查看文件

5
 use App\Enums\Accounting\DocumentType;
5
 use App\Enums\Accounting\DocumentType;
6
 use App\Enums\Setting\Template;
6
 use App\Enums\Setting\Template;
7
 use App\Models\Setting\DocumentDefault;
7
 use App\Models\Setting\DocumentDefault;
8
+use Closure;
8
 use Filament\Infolists\Components\Grid;
9
 use Filament\Infolists\Components\Grid;
9
 
10
 
10
 class DocumentPreview extends Grid
11
 class DocumentPreview extends Grid
13
 
14
 
14
     protected DocumentType $documentType = DocumentType::Invoice;
15
     protected DocumentType $documentType = DocumentType::Invoice;
15
 
16
 
17
+    protected bool | Closure $isPreview = false;
18
+
16
     protected function setUp(): void
19
     protected function setUp(): void
17
     {
20
     {
18
         parent::setUp();
21
         parent::setUp();
31
         return $this;
34
         return $this;
32
     }
35
     }
33
 
36
 
37
+    public function preview(bool | Closure $condition = true): static
38
+    {
39
+        $this->isPreview = $condition;
40
+
41
+        return $this;
42
+    }
43
+
34
     public function getType(): DocumentType
44
     public function getType(): DocumentType
35
     {
45
     {
36
         return $this->documentType;
46
         return $this->documentType;
37
     }
47
     }
38
 
48
 
49
+    public function isPreview(): bool
50
+    {
51
+        return (bool) $this->evaluate($this->isPreview);
52
+    }
53
+
39
     public function getTemplate(): Template
54
     public function getTemplate(): Template
40
     {
55
     {
41
         if ($this->documentType === DocumentType::RecurringInvoice) {
56
         if ($this->documentType === DocumentType::RecurringInvoice) {

+ 38
- 4
app/View/Models/DocumentTotalViewModel.php 查看文件

32
 
32
 
33
         $grandTotalInCents = $subtotalInCents + ($taxTotalInCents - $discountTotalInCents);
33
         $grandTotalInCents = $subtotalInCents + ($taxTotalInCents - $discountTotalInCents);
34
 
34
 
35
+        $amountDueInCents = $this->calculateAmountDueInCents($grandTotalInCents, $currencyCode);
36
+
35
         $conversionMessage = $this->buildConversionMessage($grandTotalInCents, $currencyCode, $defaultCurrencyCode);
37
         $conversionMessage = $this->buildConversionMessage($grandTotalInCents, $currencyCode, $defaultCurrencyCode);
36
 
38
 
39
+        $discountMethod = DocumentDiscountMethod::parse($this->data['discount_method']);
40
+        $isPerDocumentDiscount = $discountMethod->isPerDocument();
41
+
42
+        $taxTotal = $taxTotalInCents > 0
43
+            ? CurrencyConverter::formatCentsToMoney($taxTotalInCents, $currencyCode)
44
+            : null;
45
+
46
+        $discountTotal = ($isPerDocumentDiscount || $discountTotalInCents > 0)
47
+            ? CurrencyConverter::formatCentsToMoney($discountTotalInCents, $currencyCode)
48
+            : null;
49
+
50
+        $subtotal = ($taxTotal || $discountTotal)
51
+            ? CurrencyConverter::formatCentsToMoney($subtotalInCents, $currencyCode)
52
+            : null;
53
+
54
+        $grandTotal = CurrencyConverter::formatCentsToMoney($grandTotalInCents, $currencyCode);
55
+
56
+        $amountDue = $this->documentType !== DocumentType::Estimate
57
+            ? CurrencyConverter::formatCentsToMoney($amountDueInCents, $currencyCode)
58
+            : null;
59
+
37
         return [
60
         return [
38
-            'subtotal' => CurrencyConverter::formatCentsToMoney($subtotalInCents, $currencyCode),
39
-            'taxTotal' => CurrencyConverter::formatCentsToMoney($taxTotalInCents, $currencyCode),
40
-            'discountTotal' => CurrencyConverter::formatCentsToMoney($discountTotalInCents, $currencyCode),
41
-            'grandTotal' => CurrencyConverter::formatCentsToMoney($grandTotalInCents, $currencyCode),
61
+            'subtotal' => $subtotal,
62
+            'taxTotal' => $taxTotal,
63
+            'discountTotal' => $discountTotal,
64
+            'grandTotal' => $grandTotal,
65
+            'amountDue' => $amountDue,
66
+            'currencyCode' => $currencyCode,
42
             'conversionMessage' => $conversionMessage,
67
             'conversionMessage' => $conversionMessage,
68
+            'isPerDocumentDiscount' => $isPerDocumentDiscount,
43
         ];
69
         ];
44
     }
70
     }
45
 
71
 
123
             $defaultCurrencyCode
149
             $defaultCurrencyCode
124
         );
150
         );
125
     }
151
     }
152
+
153
+    private function calculateAmountDueInCents(int $grandTotalInCents, string $currencyCode): int
154
+    {
155
+        $amountPaid = $this->data['amount_paid'] ?? '0.00';
156
+        $amountPaidInCents = CurrencyConverter::convertToCents($amountPaid, $currencyCode);
157
+
158
+        return $grandTotalInCents - $amountPaidInCents;
159
+    }
126
 }
160
 }

+ 29
- 0
resources/css/filament/company/theme.css 查看文件

101
         box-shadow: none !important;
101
         box-shadow: none !important;
102
     }
102
     }
103
 }
103
 }
104
+
105
+.doc-template-container {
106
+    color: initial;
107
+}
108
+
109
+.doc-template-container .overflow-x-auto,
110
+.doc-template-paper {
111
+    scrollbar-width: thin;
112
+}
113
+
114
+.doc-template-paper.preview {
115
+    zoom: 0.5;
116
+}
117
+
118
+@media (min-width: 1024px) {
119
+    .doc-template-paper.preview {
120
+        zoom: 0.85;
121
+    }
122
+}
123
+
124
+.doc-template-paper:not(.preview) {
125
+    zoom: 0.65;
126
+}
127
+
128
+@media (min-width: 1024px) {
129
+    .doc-template-paper:not(.preview) {
130
+        zoom: 1;
131
+    }
132
+}

+ 37
- 10
resources/css/filament/company/tooltip.css 查看文件

1
-.es-toolip .tippy-arrow {
1
+.es-tooltip .tippy-arrow {
2
     border-color: inherit;
2
     border-color: inherit;
3
 }
3
 }
4
 
4
 
5
-.es-tooltip .tippy-box[data-placement^='right'] > .tippy-arrow::before {
5
+.es-tooltip .tippy-box > .tippy-arrow::before {
6
     transform: scale(1.75);
6
     transform: scale(1.75);
7
 }
7
 }
8
 
8
 
9
-.es-tooltip .tippy-box[data-placement^='right'] > .tippy-arrow::after {
9
+.es-tooltip .tippy-box > .tippy-arrow::after {
10
     content: "";
10
     content: "";
11
     z-index: -1;
11
     z-index: -1;
12
     position: absolute;
12
     position: absolute;
13
     border-color: transparent;
13
     border-color: transparent;
14
     border-style: solid;
14
     border-style: solid;
15
+    border-width: 8px;
16
+    transform: scale(1.75);
17
+}
18
+
19
+.es-tooltip .tippy-box[data-placement^='right'] > .tippy-arrow::after {
20
+    left: -11px;
15
     top: 0;
21
     top: 0;
16
     border-width: 8px 8px 8px 0;
22
     border-width: 8px 8px 8px 0;
17
     border-right-color: inherit;
23
     border-right-color: inherit;
18
-    left: -11px;
19
-    transform: scale(1.75);
20
 }
24
 }
21
 
25
 
26
+.es-tooltip .tippy-box[data-placement^='left'] > .tippy-arrow::after {
27
+    right: -11px;
28
+    top: 0;
29
+    border-width: 8px 0 8px 8px;
30
+    border-right-color: transparent;
31
+    border-left-color: inherit;
32
+}
33
+
34
+.es-tooltip .tippy-box[data-placement^='top'] > .tippy-arrow::after {
35
+    bottom: -11px;
36
+    left: 0;
37
+    border-width: 8px 8px 0;
38
+    border-right-color: transparent;
39
+    border-top-color: inherit;
40
+}
41
+
42
+.es-tooltip .tippy-box[data-placement^='bottom'] > .tippy-arrow::after {
43
+    top: -11px;
44
+    left: 0;
45
+    border-width: 0 8px 8px;
46
+    border-right-color: transparent;
47
+    border-bottom-color: inherit;
48
+}
22
 
49
 
23
-.es-tooltip .tippy-box[data-theme~='light'][data-placement^='right'] {
50
+.es-tooltip .tippy-box {
24
     border-radius: 8px;
51
     border-radius: 8px;
52
+}
53
+
54
+.es-tooltip .tippy-box[data-theme~='light'] {
25
     border: 1px solid #d4dde3;
55
     border: 1px solid #d4dde3;
26
-    box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
27
 }
56
 }
28
 
57
 
29
-.es-tooltip .tippy-box[data-theme~='dark'][data-placement^='right'] {
30
-    border-radius: 8px;
58
+.es-tooltip .tippy-box[data-theme~='dark'] {
31
     border: 1px solid #555555;
59
     border: 1px solid #555555;
32
-    box-shadow: 0 4px 16px 0 rgba(0, 0, 0, .7);
33
 }
60
 }
34
 
61
 
35
 .es-close-tooltip {
62
 .es-close-tooltip {

+ 15
- 12
resources/views/components/company/document-template/container.blade.php 查看文件

2
     'preview' => false,
2
     'preview' => false,
3
 ])
3
 ])
4
 
4
 
5
-<div class="doc-template-container flex justify-center p-6">
6
-    <div
7
-        @class([
8
-            'doc-template-paper bg-[#ffffff] dark:bg-gray-800 rounded-sm shadow-xl',
9
-            'w-full max-w-[820px] min-h-[1066px] max-h-[1200px] overflow-y-auto' => $preview === false,
10
-            'w-[38.25rem] h-[49.5rem] overflow-hidden' => $preview === true,
11
-        ])
12
-        @style([
13
-            'scrollbar-width: thin;' => $preview === false,
14
-        ])
15
-    >
16
-        {{ $slot }}
5
+<div
6
+    @class([
7
+        'doc-template-container flex justify-center',
8
+    ])
9
+>
10
+    <div class="max-w-full overflow-x-auto shadow-xl ring-1 ring-gray-950/5 dark:ring-white/10">
11
+        <div
12
+            @class([
13
+                'doc-template-paper bg-[#ffffff] overflow-y-auto',
14
+                'w-[51.25rem] h-[64rem]' => ! $preview,
15
+                'w-[48rem] min-h-[61.75rem] preview' => $preview,
16
+            ])
17
+        >
18
+            {{ $slot }}
19
+        </div>
17
     </div>
20
     </div>
18
 </div>
21
 </div>

+ 1
- 1
resources/views/components/company/document-template/footer.blade.php 查看文件

1
-<footer {{ $attributes->class(['doc-template-footer min-h-60']) }}>
1
+<footer {{ $attributes->class(['doc-template-footer min-h-48']) }}>
2
     {{ $slot }}
2
     {{ $slot }}
3
 </footer>
3
 </footer>

+ 1
- 1
resources/views/components/company/tables/reports/account-transactions.blade.php 查看文件

7
     $iconPosition = \Filament\Support\Enums\IconPosition::After;
7
     $iconPosition = \Filament\Support\Enums\IconPosition::After;
8
 @endphp
8
 @endphp
9
 
9
 
10
-<table class="w-full table-auto divide-y divide-gray-200 dark:divide-white/5">
10
+<table class="w-full table-auto min-w-[50rem] divide-y divide-gray-200 dark:divide-white/5">
11
     <x-company.tables.header :headers="$report->getHeaders()" :alignmentClass="[$report, 'getAlignmentClass']"/>
11
     <x-company.tables.header :headers="$report->getHeaders()" :alignmentClass="[$report, 'getAlignmentClass']"/>
12
     @foreach($report->getCategories() as $categoryIndex => $category)
12
     @foreach($report->getCategories() as $categoryIndex => $category)
13
         <tbody class="divide-y divide-gray-200 dark:divide-white/5">
13
         <tbody class="divide-y divide-gray-200 dark:divide-white/5">

+ 1
- 1
resources/views/components/company/tables/reports/balance-sheet-summary.blade.php 查看文件

1
-<table class="w-full table-fixed divide-y divide-gray-200 dark:divide-white/5">
1
+<table class="w-full min-w-[50rem] divide-y divide-gray-200 dark:divide-white/5">
2
     <colgroup>
2
     <colgroup>
3
         <col span="1" style="width: 65%;">
3
         <col span="1" style="width: 65%;">
4
         <col span="1" style="width: 35%;">
4
         <col span="1" style="width: 35%;">

+ 1
- 1
resources/views/components/company/tables/reports/balance-sheet.blade.php 查看文件

1
-<table class="w-full table-fixed divide-y divide-gray-200 dark:divide-white/5">
1
+<table class="w-full min-w-[50rem] divide-y divide-gray-200 dark:divide-white/5">
2
     <colgroup>
2
     <colgroup>
3
         @if(array_key_exists('account_code', $report->getHeaders()))
3
         @if(array_key_exists('account_code', $report->getHeaders()))
4
             <col span="1" style="width: 20%;">
4
             <col span="1" style="width: 20%;">

+ 2
- 2
resources/views/components/company/tables/reports/cash-flow-statement-summary.blade.php 查看文件

1
-<table class="w-full table-fixed divide-y divide-gray-200 dark:divide-white/5">
1
+<table class="w-full min-w-[50rem] divide-y divide-gray-200 dark:divide-white/5">
2
     <colgroup>
2
     <colgroup>
3
         <col span="1" style="width: 65%;">
3
         <col span="1" style="width: 65%;">
4
         <col span="1" style="width: 35%;">
4
         <col span="1" style="width: 35%;">
35
     @endforeach
35
     @endforeach
36
 </table>
36
 </table>
37
 
37
 
38
-<table class="w-full table-fixed divide-y border-t divide-gray-200 dark:divide-white/5">
38
+<table class="w-full min-w-[50rem] divide-y border-t divide-gray-200 dark:divide-white/5">
39
     <colgroup>
39
     <colgroup>
40
         <col span="1" style="width: 65%;">
40
         <col span="1" style="width: 65%;">
41
         <col span="1" style="width: 35%;">
41
         <col span="1" style="width: 35%;">

+ 2
- 2
resources/views/components/company/tables/reports/cash-flow-statement.blade.php 查看文件

1
-<table class="w-full table-fixed divide-y divide-gray-200 dark:divide-white/5">
1
+<table class="w-full min-w-[50rem] divide-y divide-gray-200 dark:divide-white/5">
2
     <colgroup>
2
     <colgroup>
3
         @if(array_key_exists('account_code', $report->getHeaders()))
3
         @if(array_key_exists('account_code', $report->getHeaders()))
4
             <col span="1" style="width: 20%;">
4
             <col span="1" style="width: 20%;">
139
     <x-company.tables.footer :totals="$report->getOverallTotals()" :alignment-class="[$report, 'getAlignmentClass']"/>
139
     <x-company.tables.footer :totals="$report->getOverallTotals()" :alignment-class="[$report, 'getAlignmentClass']"/>
140
 </table>
140
 </table>
141
 
141
 
142
-<table class="w-full table-fixed divide-y border-t divide-gray-200 dark:divide-white/5">
142
+<table class="w-full min-w-[50rem] divide-y border-t divide-gray-200 dark:divide-white/5">
143
     <colgroup>
143
     <colgroup>
144
         @if(array_key_exists('account_code', $report->getHeaders()))
144
         @if(array_key_exists('account_code', $report->getHeaders()))
145
             <col span="1" style="width: 20%;">
145
             <col span="1" style="width: 20%;">

+ 1
- 1
resources/views/components/company/tables/reports/income-statement-summary.blade.php 查看文件

1
-<table class="w-full table-fixed divide-y divide-gray-200 dark:divide-white/5">
1
+<table class="w-full min-w-[50rem] divide-y divide-gray-200 dark:divide-white/5">
2
     <colgroup>
2
     <colgroup>
3
         <col span="1" style="width: 65%;">
3
         <col span="1" style="width: 65%;">
4
         <col span="1" style="width: 35%;">
4
         <col span="1" style="width: 35%;">

+ 1
- 1
resources/views/components/company/tables/reports/income-statement.blade.php 查看文件

1
-<table class="w-full table-fixed divide-y divide-gray-200 dark:divide-white/5">
1
+<table class="w-full min-w-[50rem] divide-y divide-gray-200 dark:divide-white/5">
2
     <colgroup>
2
     <colgroup>
3
         @if(array_key_exists('account_code', $report->getHeaders()))
3
         @if(array_key_exists('account_code', $report->getHeaders()))
4
             <col span="1" style="width: 20%;">
4
             <col span="1" style="width: 20%;">

+ 20
- 0
resources/views/components/tooltip.blade.php 查看文件

19
             theme: $store.theme,
19
             theme: $store.theme,
20
             placement: '{{ $placement }}',
20
             placement: '{{ $placement }}',
21
             maxWidth: {{ $maxWidth }},
21
             maxWidth: {{ $maxWidth }},
22
+            popperOptions: {
23
+                strategy: 'fixed',
24
+                modifiers: [
25
+                    {
26
+                        name: 'flip',
27
+                        enabled: true,
28
+                        options: {
29
+                            fallbackPlacements: ['left', 'top', 'bottom'],
30
+                        }
31
+                    },
32
+                    {
33
+                        name: 'preventOverflow',
34
+                        enabled: true,
35
+                        options: {
36
+                            boundary: 'viewport',
37
+                            padding: 8
38
+                        }
39
+                    }
40
+                ]
41
+            }
22
         }">
42
         }">
23
         <x-filament::icon-button
43
         <x-filament::icon-button
24
             :icon="$icon"
44
             :icon="$icon"

+ 45
- 49
resources/views/filament/company/components/document-templates/classic.blade.php 查看文件

1
-@php
2
-    $data = $this->form->getRawState();
3
-    $document = \App\DTO\DocumentPreviewDTO::fromSettings($this->record, $data);
4
-@endphp
5
-
6
-{!! $document->getFontHtml() !!}
7
-
8
-<style>
9
-    .doc-template-paper {
10
-        font-family: '{{ $document->font->getLabel() }}', sans-serif;
11
-    }
12
-</style>
13
-
14
-<x-company.document-template.container class="classic-template-container" preview>
1
+<x-company.document-template.container class="classic-template-container" :preview="$preview">
15
     <!-- Header Section -->
2
     <!-- Header Section -->
16
-    <x-company.document-template.header class="default-template-header">
3
+    <x-company.document-template.header class="classic-template-header">
17
         <div class="w-2/3 text-left">
4
         <div class="w-2/3 text-left">
18
-            <div class="text-xs">
19
-                <strong class="text-xs block">{{ $document->company->name }}</strong>
5
+            <div class="text-sm">
6
+                <strong class="text-sm block">{{ $document->company->name }}</strong>
20
                 @if($formattedAddress = $document->company->getFormattedAddressHtml())
7
                 @if($formattedAddress = $document->company->getFormattedAddressHtml())
21
                     {!! $formattedAddress !!}
8
                     {!! $formattedAddress !!}
22
                 @endif
9
                 @endif
30
         </div>
17
         </div>
31
     </x-company.document-template.header>
18
     </x-company.document-template.header>
32
 
19
 
33
-    <x-company.document-template.metadata class="classic-template-metadata space-y-2">
20
+    <x-company.document-template.metadata class="classic-template-metadata space-y-4">
34
         <div class="items-center flex">
21
         <div class="items-center flex">
35
             <hr class="grow-[2] py-0.5 border-solid border-y-2" style="border-color: {{ $document->accentColor }};">
22
             <hr class="grow-[2] py-0.5 border-solid border-y-2" style="border-color: {{ $document->accentColor }};">
36
             <x-icons.document-header-decoration
23
             <x-icons.document-header-decoration
37
                 color="{{ $document->accentColor }}"
24
                 color="{{ $document->accentColor }}"
38
                 text="{{ $document->header }}"
25
                 text="{{ $document->header }}"
39
-                class="w-48"
26
+                class="w-60"
40
             />
27
             />
41
             <hr class="grow-[2] py-0.5 border-solid border-y-2" style="border-color: {{ $document->accentColor }};">
28
             <hr class="grow-[2] py-0.5 border-solid border-y-2" style="border-color: {{ $document->accentColor }};">
42
         </div>
29
         </div>
43
         @if ($document->subheader)
30
         @if ($document->subheader)
44
-            <p class="text-xs text-center text-gray-600 dark:text-gray-400">{{ $document->subheader }}</p>
31
+            <p class="text-sm text-center text-gray-600">{{ $document->subheader }}</p>
45
         @endif
32
         @endif
46
 
33
 
47
         <div class="flex justify-between items-end">
34
         <div class="flex justify-between items-end">
48
             <!-- Billing Details -->
35
             <!-- Billing Details -->
49
-            <div class="text-xs">
50
-                <h3 class="text-gray-600 dark:text-gray-400 font-medium mb-1">BILL TO</h3>
51
-                <p class="text-xs font-bold">{{ $document->client->name }}</p>
36
+            <div class="text-sm">
37
+                <h3 class="text-gray-600 font-medium mb-1">BILL TO</h3>
38
+                <p class="text-sm font-bold">{{ $document->client->name }}</p>
52
                 @if($formattedAddress = $document->client->getFormattedAddressHtml())
39
                 @if($formattedAddress = $document->client->getFormattedAddressHtml())
53
                     {!! $formattedAddress !!}
40
                     {!! $formattedAddress !!}
54
                 @endif
41
                 @endif
55
             </div>
42
             </div>
56
 
43
 
57
-            <div class="text-xs">
44
+            <div class="text-sm">
58
                 <table class="min-w-full">
45
                 <table class="min-w-full">
59
                     <tbody>
46
                     <tbody>
60
                     <tr>
47
                     <tr>
61
                         <td class="font-semibold text-right pr-2">{{ $document->label->number }}:</td>
48
                         <td class="font-semibold text-right pr-2">{{ $document->label->number }}:</td>
62
                         <td class="text-left pl-2">{{ $document->number }}</td>
49
                         <td class="text-left pl-2">{{ $document->number }}</td>
63
                     </tr>
50
                     </tr>
64
-                    <tr>
65
-                        <td class="font-semibold text-right pr-2">{{ $document->label->referenceNumber }}:</td>
66
-                        <td class="text-left pl-2">{{ $document->referenceNumber }}</td>
67
-                    </tr>
51
+                    @if($document->referenceNumber)
52
+                        <tr>
53
+                            <td class="font-semibold text-right pr-2">{{ $document->label->referenceNumber }}:</td>
54
+                            <td class="text-left pl-2">{{ $document->referenceNumber }}</td>
55
+                        </tr>
56
+                    @endif
68
                     <tr>
57
                     <tr>
69
                         <td class="font-semibold text-right pr-2">{{ $document->label->date }}:</td>
58
                         <td class="font-semibold text-right pr-2">{{ $document->label->date }}:</td>
70
                         <td class="text-left pl-2">{{ $document->date }}</td>
59
                         <td class="text-left pl-2">{{ $document->date }}</td>
82
     <!-- Line Items -->
71
     <!-- Line Items -->
83
     <x-company.document-template.line-items class="classic-template-line-items px-6">
72
     <x-company.document-template.line-items class="classic-template-line-items px-6">
84
         <table class="w-full text-left table-fixed">
73
         <table class="w-full text-left table-fixed">
85
-            <thead class="text-xs leading-8">
74
+            <thead class="text-sm leading-relaxed">
86
             <tr>
75
             <tr>
87
-                <th class="text-left">{{ $document->columnLabel->items }}</th>
88
-                <th class="text-center">{{ $document->columnLabel->units }}</th>
89
-                <th class="text-right">{{ $document->columnLabel->price }}</th>
90
-                <th class="text-right">{{ $document->columnLabel->amount }}</th>
76
+                <th class="text-left w-[50%] py-4">{{ $document->columnLabel->items }}</th>
77
+                <th class="text-center w-[10%] py-4">{{ $document->columnLabel->units }}</th>
78
+                <th class="text-right w-[20%] py-4">{{ $document->columnLabel->price }}</th>
79
+                <th class="text-right w-[20%] py-4">{{ $document->columnLabel->amount }}</th>
91
             </tr>
80
             </tr>
92
             </thead>
81
             </thead>
93
-            <tbody class="text-xs border-t-2 border-b-2 border-dotted border-gray-300 leading-8">
82
+            <tbody class="text-sm border-y-2 border-dotted border-gray-300">
94
             @foreach($document->lineItems as $item)
83
             @foreach($document->lineItems as $item)
95
                 <tr>
84
                 <tr>
96
-                    <td class="text-left font-semibold">{{ $item->name }}</td>
97
-                    <td class="text-center">{{ $item->quantity }}</td>
98
-                    <td class="text-right">{{ $item->unitPrice }}</td>
99
-                    <td class="text-right">{{ $item->subtotal }}</td>
85
+                    <td class="text-left font-semibold py-3">
86
+                        {{ $item->name }}
87
+                        @if($item->description)
88
+                            <div class="text-gray-600 font-normal line-clamp-2 mt-1">{{ $item->description }}</div>
89
+                        @endif
90
+                    </td>
91
+                    <td class="text-center py-3">{{ $item->quantity }}</td>
92
+                    <td class="text-right py-3">{{ $item->unitPrice }}</td>
93
+                    <td class="text-right py-3">{{ $item->subtotal }}</td>
100
                 </tr>
94
                 </tr>
101
             @endforeach
95
             @endforeach
102
             </tbody>
96
             </tbody>
103
         </table>
97
         </table>
104
 
98
 
105
         <!-- Financial Details and Notes -->
99
         <!-- Financial Details and Notes -->
106
-        <div class="flex justify-between text-xs space-x-1 pt-2">
100
+        <div class="flex justify-between text-sm space-x-1 pt-4">
107
             <!-- Notes Section -->
101
             <!-- Notes Section -->
108
             <div class="w-[60%] py-2">
102
             <div class="w-[60%] py-2">
109
                 <p class="font-semibold">{{ $document->footer }}</p>
103
                 <p class="font-semibold">{{ $document->footer }}</p>
112
             <!-- Financial Summary -->
106
             <!-- Financial Summary -->
113
             <div class="w-[40%]">
107
             <div class="w-[40%]">
114
                 <table class="w-full table-fixed whitespace-nowrap">
108
                 <table class="w-full table-fixed whitespace-nowrap">
115
-                    <tbody class="text-xs">
116
-                    <tr>
117
-                        <td class="text-right font-semibold py-2">Subtotal:</td>
118
-                        <td class="text-right py-2">{{ $document->subtotal }}</td>
119
-                    </tr>
109
+                    <tbody class="text-sm">
110
+                    @if($document->subtotal)
111
+                        <tr>
112
+                            <td class="text-right font-semibold py-2">Subtotal:</td>
113
+                            <td class="text-right py-2">{{ $document->subtotal }}</td>
114
+                        </tr>
115
+                    @endif
120
                     @if($document->discount)
116
                     @if($document->discount)
121
-                        <tr class="text-success-800 dark:text-success-600">
117
+                        <tr class="text-success-800">
122
                             <td class="text-right py-2">Discount:</td>
118
                             <td class="text-right py-2">Discount:</td>
123
                             <td class="text-right py-2">
119
                             <td class="text-right py-2">
124
                                 ({{ $document->discount }})
120
                                 ({{ $document->discount }})
132
                         </tr>
128
                         </tr>
133
                     @endif
129
                     @endif
134
                     <tr>
130
                     <tr>
135
-                        <td class="text-right font-semibold border-t py-2">Total:</td>
131
+                        <td class="text-right font-semibold border-t py-2">{{ $document->amountDue ? 'Total' : 'Grand Total' }}:</td>
136
                         <td class="text-right border-t py-2">{{ $document->total }}</td>
132
                         <td class="text-right border-t py-2">{{ $document->total }}</td>
137
                     </tr>
133
                     </tr>
138
                     @if($document->amountDue)
134
                     @if($document->amountDue)
150
     </x-company.document-template.line-items>
146
     </x-company.document-template.line-items>
151
 
147
 
152
     <!-- Footer -->
148
     <!-- Footer -->
153
-    <x-company.document-template.footer class="classic-template-footer text-xs">
154
-        <h4 class="font-semibold px-6 mb-2">Terms & Conditions</h4>
155
-        <p class="px-6 break-words line-clamp-4">{{ $document->terms }}</p>
149
+    <x-company.document-template.footer class="classic-template-footer p-6 text-sm">
150
+        <h4 class="font-semibold mb-2">Terms & Conditions</h4>
151
+        <p class="break-words line-clamp-4">{{ $document->terms }}</p>
156
     </x-company.document-template.footer>
152
     </x-company.document-template.footer>
157
 </x-company.document-template.container>
153
 </x-company.document-template.container>

+ 67
- 63
resources/views/filament/company/components/document-templates/default.blade.php 查看文件

1
-@php
2
-    $data = $this->form->getRawState();
3
-    $document = \App\DTO\DocumentPreviewDTO::fromSettings($this->record, $data);
4
-@endphp
5
-
6
-{!! $document->getFontHtml() !!}
7
-
8
-<style>
9
-    .doc-template-paper {
10
-        font-family: '{{ $document->font->getLabel() }}', sans-serif;
11
-    }
12
-</style>
13
-
14
-<x-company.document-template.container class="default-template-container" preview>
1
+<x-company.document-template.container class="default-template-container" :preview="$preview">
15
 
2
 
16
     <x-company.document-template.header class="default-template-header border-b">
3
     <x-company.document-template.header class="default-template-header border-b">
17
         <div class="w-1/3">
4
         <div class="w-1/3">
25
                 <div>
12
                 <div>
26
                     <h1 class="text-3xl font-light uppercase">{{ $document->header }}</h1>
13
                     <h1 class="text-3xl font-light uppercase">{{ $document->header }}</h1>
27
                     @if ($document->subheader)
14
                     @if ($document->subheader)
28
-                        <p class="text-xs text-gray-600 dark:text-gray-400">{{ $document->subheader }}</p>
15
+                        <p class="text-sm text-gray-600">{{ $document->subheader }}</p>
29
                     @endif
16
                     @endif
30
                 </div>
17
                 </div>
31
-                <div class="text-xs">
32
-                    <strong class="text-xs block">{{ $document->company->name }}</strong>
18
+                <div class="text-sm">
19
+                    <strong class="text-sm block">{{ $document->company->name }}</strong>
33
                     @if($formattedAddress = $document->company->getFormattedAddressHtml())
20
                     @if($formattedAddress = $document->company->getFormattedAddressHtml())
34
                         {!! $formattedAddress !!}
21
                         {!! $formattedAddress !!}
35
                     @endif
22
                     @endif
38
         </div>
25
         </div>
39
     </x-company.document-template.header>
26
     </x-company.document-template.header>
40
 
27
 
41
-    <x-company.document-template.metadata class="default-template-metadata space-y-2">
28
+    <x-company.document-template.metadata class="default-template-metadata space-y-4">
42
         <div class="flex justify-between items-end">
29
         <div class="flex justify-between items-end">
43
             <!-- Billing Details -->
30
             <!-- Billing Details -->
44
-            <div class="text-xs">
45
-                <h3 class="text-gray-600 dark:text-gray-400 font-medium mb-1">BILL TO</h3>
46
-                <p class="text-xs font-bold">{{ $document->client->name }}</p>
31
+            <div class="text-sm">
32
+                <h3 class="text-gray-600 font-medium mb-1">BILL TO</h3>
33
+                <p class="text-sm font-bold">{{ $document->client->name }}</p>
47
                 @if($formattedAddress = $document->client->getFormattedAddressHtml())
34
                 @if($formattedAddress = $document->client->getFormattedAddressHtml())
48
                     {!! $formattedAddress !!}
35
                     {!! $formattedAddress !!}
49
                 @endif
36
                 @endif
50
             </div>
37
             </div>
51
 
38
 
52
-            <div class="text-xs">
39
+            <div class="text-sm">
53
                 <table class="min-w-full">
40
                 <table class="min-w-full">
54
                     <tbody>
41
                     <tbody>
55
                     <tr>
42
                     <tr>
56
                         <td class="font-semibold text-right pr-2">{{ $document->label->number }}:</td>
43
                         <td class="font-semibold text-right pr-2">{{ $document->label->number }}:</td>
57
                         <td class="text-left pl-2">{{ $document->number }}</td>
44
                         <td class="text-left pl-2">{{ $document->number }}</td>
58
                     </tr>
45
                     </tr>
59
-                    <tr>
60
-                        <td class="font-semibold text-right pr-2">{{ $document->label->referenceNumber }}:</td>
61
-                        <td class="text-left pl-2">{{ $document->referenceNumber }}</td>
62
-                    </tr>
46
+                    @if($document->referenceNumber)
47
+                        <tr>
48
+                            <td class="font-semibold text-right pr-2">{{ $document->label->referenceNumber }}:</td>
49
+                            <td class="text-left pl-2">{{ $document->referenceNumber }}</td>
50
+                        </tr>
51
+                    @endif
63
                     <tr>
52
                     <tr>
64
                         <td class="font-semibold text-right pr-2">{{ $document->label->date }}:</td>
53
                         <td class="font-semibold text-right pr-2">{{ $document->label->date }}:</td>
65
                         <td class="text-left pl-2">{{ $document->date }}</td>
54
                         <td class="text-left pl-2">{{ $document->date }}</td>
77
     <!-- Line Items Table -->
66
     <!-- Line Items Table -->
78
     <x-company.document-template.line-items class="default-template-line-items">
67
     <x-company.document-template.line-items class="default-template-line-items">
79
         <table class="w-full text-left table-fixed">
68
         <table class="w-full text-left table-fixed">
80
-            <thead class="text-xs leading-8" style="background: {{ $document->accentColor }}">
69
+            <thead class="text-sm leading-relaxed" style="background: {{ $document->accentColor }}">
81
             <tr class="text-white">
70
             <tr class="text-white">
82
-                <th class="text-left pl-6">{{ $document->columnLabel->items }}</th>
83
-                <th class="text-center">{{ $document->columnLabel->units }}</th>
84
-                <th class="text-right">{{ $document->columnLabel->price }}</th>
85
-                <th class="text-right pr-6">{{ $document->columnLabel->amount }}</th>
71
+                <th class="text-left pl-6 w-[50%] py-2">{{ $document->columnLabel->items }}</th>
72
+                <th class="text-center w-[10%] py-2">{{ $document->columnLabel->units }}</th>
73
+                <th class="text-right w-[20%] py-2">{{ $document->columnLabel->price }}</th>
74
+                <th class="text-right pr-6 w-[20%] py-2">{{ $document->columnLabel->amount }}</th>
86
             </tr>
75
             </tr>
87
             </thead>
76
             </thead>
88
-            <tbody class="text-xs border-b-2 border-gray-300 leading-8">
77
+            <tbody class="text-sm border-b-2 border-gray-300">
89
             @foreach($document->lineItems as $item)
78
             @foreach($document->lineItems as $item)
90
                 <tr>
79
                 <tr>
91
-                    <td class="text-left pl-6 font-semibold">{{ $item->name }}</td>
92
-                    <td class="text-center">{{ $item->quantity }}</td>
93
-                    <td class="text-right">{{ $item->unitPrice }}</td>
94
-                    <td class="text-right pr-6">{{ $item->subtotal }}</td>
80
+                    <td class="text-left pl-6 font-semibold py-3">
81
+                        {{ $item->name }}
82
+                        @if($item->description)
83
+                            <div class="text-gray-600 font-normal line-clamp-2 mt-1">{{ $item->description }}</div>
84
+                        @endif
85
+                    </td>
86
+                    <td class="text-center py-3">{{ $item->quantity }}</td>
87
+                    <td class="text-right py-3">{{ $item->unitPrice }}</td>
88
+                    <td class="text-right pr-6 py-3">{{ $item->subtotal }}</td>
95
                 </tr>
89
                 </tr>
96
             @endforeach
90
             @endforeach
97
             </tbody>
91
             </tbody>
98
-            <tfoot class="text-xs leading-loose">
99
-            <tr>
100
-                <td class="pl-6" colspan="2"></td>
101
-                <td class="text-right font-semibold">Subtotal:</td>
102
-                <td class="text-right pr-6">{{ $document->subtotal }}</td>
103
-            </tr>
104
-            <tr class="text-success-800 dark:text-success-600">
105
-                <td class="pl-6" colspan="2"></td>
106
-                <td class="text-right">Discount (5%):</td>
107
-                <td class="text-right pr-6">({{ $document->discount }})</td>
108
-            </tr>
109
-            <tr>
110
-                <td class="pl-6" colspan="2"></td>
111
-                <td class="text-right">Tax:</td>
112
-                <td class="text-right pr-6">{{ $document->tax }}</td>
113
-            </tr>
114
-            <tr>
115
-                <td class="pl-6" colspan="2"></td>
116
-                <td class="text-right font-semibold border-t">Total:</td>
117
-                <td class="text-right border-t pr-6">{{ $document->total }}</td>
118
-            </tr>
92
+            <tfoot class="text-sm summary-section">
93
+            @if($document->subtotal)
94
+                <tr>
95
+                    <td class="pl-6 py-2" colspan="2"></td>
96
+                    <td class="text-right font-semibold py-2">Subtotal:</td>
97
+                    <td class="text-right pr-6 py-2">{{ $document->subtotal }}</td>
98
+                </tr>
99
+            @endif
100
+            @if($document->discount)
101
+                <tr class="text-success-800">
102
+                    <td class="pl-6 py-2" colspan="2"></td>
103
+                    <td class="text-right py-2">Discount:</td>
104
+                    <td class="text-right pr-6 py-2">
105
+                        ({{ $document->discount }})
106
+                    </td>
107
+                </tr>
108
+            @endif
109
+            @if($document->tax)
110
+                <tr>
111
+                    <td class="pl-6 py-2" colspan="2"></td>
112
+                    <td class="text-right py-2">Tax:</td>
113
+                    <td class="text-right pr-6 py-2">{{ $document->tax }}</td>
114
+                </tr>
115
+            @endif
119
             <tr>
116
             <tr>
120
-                <td class="pl-6" colspan="2"></td>
121
-                <td class="text-right font-semibold border-t-4 border-double">{{ $document->label->amountDue }}
122
-                    ({{ $document->currencyCode }}):
123
-                </td>
124
-                <td class="text-right border-t-4 border-double pr-6">{{ $document->amountDue }}</td>
117
+                <td class="pl-6 py-2" colspan="2"></td>
118
+                <td class="text-right font-semibold border-t py-2">{{ $document->amountDue ? 'Total' : 'Grand Total' }}:</td>
119
+                <td class="text-right border-t pr-6 py-2">{{ $document->total }}</td>
125
             </tr>
120
             </tr>
121
+            @if($document->amountDue)
122
+                <tr>
123
+                    <td class="pl-6 py-2" colspan="2"></td>
124
+                    <td class="text-right font-semibold border-t-4 border-double py-2">{{ $document->label->amountDue }}
125
+                        ({{ $document->currencyCode }}):
126
+                    </td>
127
+                    <td class="text-right border-t-4 border-double pr-6 py-2">{{ $document->amountDue }}</td>
128
+                </tr>
129
+            @endif
126
             </tfoot>
130
             </tfoot>
127
         </table>
131
         </table>
128
     </x-company.document-template.line-items>
132
     </x-company.document-template.line-items>
129
 
133
 
130
     <!-- Footer Notes -->
134
     <!-- Footer Notes -->
131
-    <x-company.document-template.footer class="default-template-footer min-h-48 flex flex-col text-xs p-6">
135
+    <x-company.document-template.footer class="default-template-footer flex flex-col text-sm p-6">
132
         <div>
136
         <div>
133
             <h4 class="font-semibold mb-2">Terms & Conditions</h4>
137
             <h4 class="font-semibold mb-2">Terms & Conditions</h4>
134
             <p class="break-words line-clamp-4">{{ $document->terms }}</p>
138
             <p class="break-words line-clamp-4">{{ $document->terms }}</p>

+ 51
- 61
resources/views/filament/company/components/document-templates/modern.blade.php 查看文件

1
-@php
2
-    $data = $this->form->getRawState();
3
-    $document = \App\DTO\DocumentPreviewDTO::fromSettings($this->record, $data);
4
-@endphp
5
-
6
-{!! $document->getFontHtml() !!}
7
-
8
-<style>
9
-    .doc-template-paper {
10
-        font-family: '{{ $document->font->getLabel() }}', sans-serif;
11
-    }
12
-</style>
13
-
14
-<x-company.document-template.container class="modern-template-container" preview>
15
-
1
+<x-company.document-template.container class="modern-template-container" :preview="$preview">
16
     <!-- Colored Header with Logo -->
2
     <!-- Colored Header with Logo -->
17
-    <x-company.document-template.header class="bg-gray-800 h-20">
3
+    <x-company.document-template.header class="bg-gray-800 h-24">
18
         <!-- Logo -->
4
         <!-- Logo -->
19
         <div class="w-2/3">
5
         <div class="w-2/3">
20
             @if($document->logo && $document->showLogo)
6
             @if($document->logo && $document->showLogo)
21
-                <x-company.document-template.logo class="ml-6" :src="$document->logo"/>
7
+                <x-company.document-template.logo class="ml-8" :src="$document->logo"/>
22
             @endif
8
             @endif
23
         </div>
9
         </div>
24
 
10
 
25
         <!-- Ribbon Container -->
11
         <!-- Ribbon Container -->
26
-        <div class="w-1/3 absolute right-0 top-0 p-2 h-28 flex flex-col justify-end rounded-bl-sm"
12
+        <div class="w-1/3 absolute right-0 top-0 p-3 h-32 flex flex-col justify-end rounded-bl-sm"
27
              style="background: {{ $document->accentColor }};">
13
              style="background: {{ $document->accentColor }};">
28
             @if($document->header)
14
             @if($document->header)
29
-                <h1 class="text-3xl font-bold text-white text-center uppercase">{{ $document->header }}</h1>
15
+                <h1 class="text-4xl font-bold text-white text-center uppercase">{{ $document->header }}</h1>
30
             @endif
16
             @endif
31
         </div>
17
         </div>
32
     </x-company.document-template.header>
18
     </x-company.document-template.header>
33
 
19
 
34
     <!-- Company Details -->
20
     <!-- Company Details -->
35
-    <x-company.document-template.metadata class="modern-template-metadata space-y-6">
36
-        <div class="text-xs">
37
-            <h2 class="text-xs font-semibold">{{ $document->company->name }}</h2>
21
+    <x-company.document-template.metadata class="modern-template-metadata space-y-8">
22
+        <div class="text-sm">
23
+            <strong class="text-sm block">{{ $document->company->name }}</strong>
38
             @if($formattedAddress = $document->company->getFormattedAddressHtml())
24
             @if($formattedAddress = $document->company->getFormattedAddressHtml())
39
                 {!! $formattedAddress !!}
25
                 {!! $formattedAddress !!}
40
             @endif
26
             @endif
42
 
28
 
43
         <div class="flex justify-between items-end">
29
         <div class="flex justify-between items-end">
44
             <!-- Billing Details -->
30
             <!-- Billing Details -->
45
-            <div class="text-xs">
46
-                <h3 class="text-gray-600 dark:text-gray-400 font-medium mb-1">BILL TO</h3>
47
-                <p class="text-xs font-bold"
31
+            <div class="text-sm">
32
+                <h3 class="text-gray-600 font-medium mb-1">BILL TO</h3>
33
+                <p class="text-sm font-bold"
48
                    style="color: {{ $document->accentColor }}">{{ $document->client->name }}</p>
34
                    style="color: {{ $document->accentColor }}">{{ $document->client->name }}</p>
49
 
35
 
50
                 @if($formattedAddress = $document->client->getFormattedAddressHtml())
36
                 @if($formattedAddress = $document->client->getFormattedAddressHtml())
52
                 @endif
38
                 @endif
53
             </div>
39
             </div>
54
 
40
 
55
-            <div class="text-xs">
41
+            <div class="text-sm">
56
                 <table class="min-w-full">
42
                 <table class="min-w-full">
57
                     <tbody>
43
                     <tbody>
58
                     <tr>
44
                     <tr>
82
     <!-- Line Items Table -->
68
     <!-- Line Items Table -->
83
     <x-company.document-template.line-items class="modern-template-line-items">
69
     <x-company.document-template.line-items class="modern-template-line-items">
84
         <table class="w-full text-left table-fixed">
70
         <table class="w-full text-left table-fixed">
85
-            <thead class="text-xs leading-8">
86
-            <tr class="text-gray-600 dark:text-gray-400">
87
-                <th class="text-left pl-6 w-[50%]">{{ $document->columnLabel->items }}</th>
88
-                <th class="text-center w-[10%]">{{ $document->columnLabel->units }}</th>
89
-                <th class="text-right w-[20%]">{{ $document->columnLabel->price }}</th>
90
-                <th class="text-right pr-6 w-[20%]">{{ $document->columnLabel->amount }}</th>
71
+            <thead class="text-sm leading-relaxed">
72
+            <tr class="text-gray-600">
73
+                <th class="text-left pl-6 w-[50%] py-4">{{ $document->columnLabel->items }}</th>
74
+                <th class="text-center w-[10%] py-4">{{ $document->columnLabel->units }}</th>
75
+                <th class="text-right w-[20%] py-4">{{ $document->columnLabel->price }}</th>
76
+                <th class="text-right pr-6 w-[20%] py-4">{{ $document->columnLabel->amount }}</th>
91
             </tr>
77
             </tr>
92
             </thead>
78
             </thead>
93
-            <tbody class="text-xs border-y-2">
79
+            <tbody class="text-sm border-y-2">
94
             @foreach($document->lineItems as $index => $item)
80
             @foreach($document->lineItems as $index => $item)
95
-                <tr @class(['bg-gray-100 dark:bg-gray-800' => $index % 2 === 0])>
96
-                    <td class="text-left pl-6 font-semibold py-2">
81
+                <tr @class(['bg-gray-100' => $index % 2 === 0])>
82
+                    <td class="text-left pl-6 font-semibold py-3">
97
                         {{ $item->name }}
83
                         {{ $item->name }}
98
                         @if($item->description)
84
                         @if($item->description)
99
-                            <div class="text-gray-600 font-normal line-clamp-2">{{ $item->description }}</div>
85
+                            <div class="text-gray-600 font-normal line-clamp-2 mt-1">{{ $item->description }}</div>
100
                         @endif
86
                         @endif
101
                     </td>
87
                     </td>
102
-                    <td class="text-center">{{ $item->quantity }}</td>
103
-                    <td class="text-right">{{ $item->unitPrice }}</td>
104
-                    <td class="text-right pr-6">{{ $item->subtotal }}</td>
88
+                    <td class="text-center py-3">{{ $item->quantity }}</td>
89
+                    <td class="text-right py-3">{{ $item->unitPrice }}</td>
90
+                    <td class="text-right pr-6 py-3">{{ $item->subtotal }}</td>
105
                 </tr>
91
                 </tr>
106
             @endforeach
92
             @endforeach
107
             </tbody>
93
             </tbody>
108
-            <tfoot class="text-xs">
109
-            <tr>
110
-                <td class="pl-6 py-1" colspan="2"></td>
111
-                <td class="text-right font-semibold py-1">Subtotal:</td>
112
-                <td class="text-right pr-6 py-1">{{ $document->subtotal }}</td>
113
-            </tr>
94
+            <tfoot class="text-sm summary-section">
95
+            @if($document->subtotal)
96
+                <tr>
97
+                    <td class="pl-6 py-2" colspan="2"></td>
98
+                    <td class="text-right font-semibold py-2">Subtotal:</td>
99
+                    <td class="text-right pr-6 py-2">{{ $document->subtotal }}</td>
100
+                </tr>
101
+            @endif
114
             @if($document->discount)
102
             @if($document->discount)
115
-                <tr class="text-success-800 dark:text-success-600">
116
-                    <td class="pl-6 py-1" colspan="2"></td>
117
-                    <td class="text-right py-1">Discount:</td>
118
-                    <td class="text-right pr-6 py-1">
103
+                <tr class="text-success-800">
104
+                    <td class="pl-6 py-2" colspan="2"></td>
105
+                    <td class="text-right py-2">Discount:</td>
106
+                    <td class="text-right pr-6 py-2">
119
                         ({{ $document->discount }})
107
                         ({{ $document->discount }})
120
                     </td>
108
                     </td>
121
                 </tr>
109
                 </tr>
122
             @endif
110
             @endif
123
             @if($document->tax)
111
             @if($document->tax)
124
                 <tr>
112
                 <tr>
125
-                    <td class="pl-6 py-1" colspan="2"></td>
126
-                    <td class="text-right py-1">Tax:</td>
127
-                    <td class="text-right pr-6 py-1">{{ $document->tax }}</td>
113
+                    <td class="pl-6 py-2" colspan="2"></td>
114
+                    <td class="text-right py-2">Tax:</td>
115
+                    <td class="text-right pr-6 py-2">{{ $document->tax }}</td>
128
                 </tr>
116
                 </tr>
129
             @endif
117
             @endif
130
             <tr>
118
             <tr>
131
-                <td class="pl-6 py-1" colspan="2"></td>
132
-                <td class="text-right font-semibold border-t py-1">Total:</td>
133
-                <td class="text-right border-t pr-6 py-1">{{ $document->total }}</td>
119
+                <td class="pl-6 py-2" colspan="2"></td>
120
+                <td class="text-right font-semibold border-t py-2">{{ $document->amountDue ? 'Total' : 'Grand Total' }}:</td>
121
+                <td class="text-right border-t pr-6 py-2">{{ $document->total }}</td>
134
             </tr>
122
             </tr>
135
             @if($document->amountDue)
123
             @if($document->amountDue)
136
                 <tr>
124
                 <tr>
137
-                    <td class="pl-6 py-1" colspan="2"></td>
138
-                    <td class="text-right font-semibold border-t-4 border-double py-1">{{ $document->label->amountDue }}
125
+                    <td class="pl-6 py-2" colspan="2"></td>
126
+                    <td class="text-right font-semibold border-t-4 border-double py-2">{{ $document->label->amountDue }}
139
                         ({{ $document->currencyCode }}):
127
                         ({{ $document->currencyCode }}):
140
                     </td>
128
                     </td>
141
-                    <td class="text-right border-t-4 border-double pr-6 py-1">{{ $document->amountDue }}</td>
129
+                    <td class="text-right border-t-4 border-double pr-6 py-2">{{ $document->amountDue }}</td>
142
                 </tr>
130
                 </tr>
143
             @endif
131
             @endif
144
             </tfoot>
132
             </tfoot>
146
     </x-company.document-template.line-items>
134
     </x-company.document-template.line-items>
147
 
135
 
148
     <!-- Footer Notes -->
136
     <!-- Footer Notes -->
149
-    <x-company.document-template.footer class="modern-template-footer text-xs">
150
-        <h4 class="font-semibold px-6" style="color: {{ $document->accentColor }}">Terms & Conditions</h4>
137
+    <x-company.document-template.footer class="modern-template-footer">
138
+        <h4 class="font-semibold px-6 text-sm" style="color: {{ $document->accentColor }}">
139
+            Terms & Conditions
140
+        </h4>
151
         <span class="border-t-2 my-2 border-gray-300 block w-full"></span>
141
         <span class="border-t-2 my-2 border-gray-300 block w-full"></span>
152
-        <div class="flex justify-between space-x-4 px-6">
142
+        <div class="flex justify-between space-x-4 px-6 text-sm">
153
             <p class="w-1/2 break-words line-clamp-4">{{ $document->terms }}</p>
143
             <p class="w-1/2 break-words line-clamp-4">{{ $document->terms }}</p>
154
             <p class="w-1/2 break-words line-clamp-4">{{ $document->footer }}</p>
144
             <p class="w-1/2 break-words line-clamp-4">{{ $document->footer }}</p>
155
         </div>
145
         </div>

+ 1
- 1
resources/views/filament/company/pages/accounting/chart.blade.php 查看文件

20
                     <div class="es-table__header-ctn"></div>
20
                     <div class="es-table__header-ctn"></div>
21
                     <div class="es-table__content overflow-x-auto">
21
                     <div class="es-table__content overflow-x-auto">
22
                         <table
22
                         <table
23
-                            class="es-table table-fixed w-full divide-y divide-gray-200 text-start text-sm dark:divide-white/5">
23
+                            class="es-table w-full min-w-[70rem] divide-y divide-gray-200 text-start text-sm dark:divide-white/5">
24
                             <colgroup>
24
                             <colgroup>
25
                                 <col span="1" style="width: 12.5%;">
25
                                 <col span="1" style="width: 12.5%;">
26
                                 <col span="1" style="width: 20%;">
26
                                 <col span="1" style="width: 20%;">

+ 25
- 22
resources/views/filament/forms/components/custom-table-repeater.blade.php 查看文件

222
             </div>
222
             </div>
223
         @endif
223
         @endif
224
 
224
 
225
-        @if ($addAction->isVisible() || filled($visibleExtraActions))
226
-            <ul
227
-                @class([
228
-                    'relative flex gap-4',
229
-                    match ($getAddActionAlignment()) {
230
-                        Alignment::Start, Alignment::Left => 'justify-start',
231
-                        Alignment::End, Alignment::Right => 'justify-end',
232
-                        default =>  'justify-center',
233
-                    },
234
-                ])
235
-            >
236
-                @if ($addAction->isVisible())
237
-                    <li>
238
-                        {{ $addAction }}
239
-                    </li>
225
+        @if ($addAction->isVisible() || filled($visibleExtraActions) || $hasFooterItem())
226
+            <div class="flex justify-between items-start">
227
+                <!-- Actions grouped to the left -->
228
+                @if ($addAction->isVisible() || filled($visibleExtraActions))
229
+                    <ul class="flex gap-4">
230
+                        @if ($addAction->isVisible())
231
+                            <li>
232
+                                {{ $addAction }}
233
+                            </li>
234
+                        @endif
235
+                        @if (filled($visibleExtraActions))
236
+                            @foreach ($visibleExtraActions as $extraAction)
237
+                                <li>
238
+                                    {{ $extraAction }}
239
+                                </li>
240
+                            @endforeach
241
+                        @endif
242
+                    </ul>
240
                 @endif
243
                 @endif
241
-                @if (filled($visibleExtraActions))
242
-                    @foreach ($visibleExtraActions as $extraAction)
243
-                        <li>
244
-                            {{ ($extraAction) }}
245
-                        </li>
246
-                    @endforeach
244
+
245
+                <!-- Container for Footer Item to the right -->
246
+                @if($hasFooterItem())
247
+                    <div>
248
+                        {{ $getFooterItem() }}
249
+                    </div>
247
                 @endif
250
                 @endif
248
-            </ul>
251
+            </div>
249
         @endif
252
         @endif
250
     </div>
253
     </div>
251
 </x-dynamic-component>
254
 </x-dynamic-component>

+ 21
- 0
resources/views/filament/forms/components/document-preview.blade.php 查看文件

1
+@php
2
+    $data = $this->form->getRawState();
3
+    $document = \App\DTO\DocumentPreviewDTO::fromSettings($this->record, $data);
4
+    $template = $getTemplate();
5
+    $preview = $isPreview();
6
+@endphp
7
+
8
+{!! $document->getFontHtml() !!}
9
+
10
+<style>
11
+    .doc-template-paper {
12
+        font-family: '{{ $document->font->getLabel() }}', sans-serif;
13
+    }
14
+</style>
15
+
16
+<div {{ $attributes }}>
17
+    @include("filament.company.components.document-templates.{$template->value}", [
18
+        'document' => $document,
19
+        'preview' => $preview,
20
+    ])
21
+</div>

+ 78
- 57
resources/views/filament/forms/components/document-totals.blade.php 查看文件

7
     $type = $getType();
7
     $type = $getType();
8
     $viewModel = new DocumentTotalViewModel($data, $type);
8
     $viewModel = new DocumentTotalViewModel($data, $type);
9
     extract($viewModel->buildViewData(), EXTR_SKIP);
9
     extract($viewModel->buildViewData(), EXTR_SKIP);
10
-
11
-    $discountMethod = DocumentDiscountMethod::parse($data['discount_method']);
12
-    $isPerDocumentDiscount = $discountMethod->isPerDocument();
13
 @endphp
10
 @endphp
14
 
11
 
15
-<div class="totals-summary w-full sm:pr-14">
16
-    <table class="w-full text-right table-fixed hidden sm:table">
12
+<div class="totals-summary w-full lg:pl-[4rem] lg:pr-[6rem] py-8 lg:py-0">
13
+    <table class="w-full text-right table-fixed hidden lg:table">
17
         <colgroup>
14
         <colgroup>
18
-            <col class="w-[20%]"> {{-- Items --}}
19
-            <col class="w-[30%]"> {{-- Description --}}
15
+            <col class="w-[30%]"> {{-- Items --}}
20
             <col class="w-[10%]"> {{-- Quantity --}}
16
             <col class="w-[10%]"> {{-- Quantity --}}
21
             <col class="w-[10%]"> {{-- Price --}}
17
             <col class="w-[10%]"> {{-- Price --}}
22
-            <col class="w-[20%]"> {{-- Taxes --}}
18
+            <col class="w-[15%]">
19
+            <col class="w-[15%]"> {{-- Adjustments --}}
23
             <col class="w-[10%]"> {{-- Amount --}}
20
             <col class="w-[10%]"> {{-- Amount --}}
24
         </colgroup>
21
         </colgroup>
25
         <tbody>
22
         <tbody>
23
+        @if($subtotal)
26
             <tr>
24
             <tr>
27
                 <td colspan="4"></td>
25
                 <td colspan="4"></td>
28
-                <td class="text-sm px-4 py-2 font-medium leading-6 text-gray-950 dark:text-white">Subtotal:</td>
29
-                <td class="text-sm pl-4 py-2 leading-6">{{ $subtotal }}</td>
26
+                <td class="text-sm p-2 font-semibold text-gray-950 dark:text-white">Subtotal:</td>
27
+                <td class="text-sm p-2">{{ $subtotal }}</td>
30
             </tr>
28
             </tr>
29
+        @endif
30
+        @if($taxTotal)
31
             <tr>
31
             <tr>
32
                 <td colspan="4"></td>
32
                 <td colspan="4"></td>
33
-                <td class="text-sm px-4 py-2 font-medium leading-6 text-gray-950 dark:text-white">Taxes:</td>
34
-                <td class="text-sm pl-4 py-2 leading-6">{{ $taxTotal }}</td>
33
+                <td class="text-sm p-2">Tax:</td>
34
+                <td class="text-sm p-2">{{ $taxTotal }}</td>
35
             </tr>
35
             </tr>
36
-            @if($isPerDocumentDiscount)
37
-                <tr>
38
-                    <td colspan="3" class="text-sm px-4 py-2 font-medium leading-6 text-gray-950 dark:text-white text-right">Discount:</td>
39
-                    <td colspan="2" class="text-sm px-4 py-2">
40
-                        <div class="flex justify-between space-x-2">
41
-                            @foreach($getChildComponentContainer()->getComponents() as $component)
42
-                                <div class="flex-1 text-left">{{ $component }}</div>
43
-                            @endforeach
44
-                        </div>
45
-                    </td>
46
-                    <td class="text-sm pl-4 py-2 leading-6">({{ $discountTotal }})</td>
47
-                </tr>
48
-            @else
49
-                <tr>
50
-                    <td colspan="4"></td>
51
-                    <td class="text-sm px-4 py-2 font-medium leading-6 text-gray-950 dark:text-white">Discounts:</td>
52
-                    <td class="text-sm pl-4 py-2 leading-6">({{ $discountTotal }})</td>
53
-                </tr>
54
-            @endif
55
-            <tr class="font-semibold">
36
+        @endif
37
+        @if($isPerDocumentDiscount)
38
+            <tr>
39
+                <td colspan="3" class="text-sm p-2">Discount:</td>
40
+                <td colspan="2" class="text-sm p-2">
41
+                    <div class="flex justify-between space-x-2">
42
+                        @foreach($getChildComponentContainer()->getComponents() as $component)
43
+                            <div class="flex-1 text-left">{{ $component }}</div>
44
+                        @endforeach
45
+                    </div>
46
+                </td>
47
+                <td class="text-sm p-2">({{ $discountTotal }})</td>
48
+            </tr>
49
+        @elseif($discountTotal)
50
+            <tr>
56
                 <td colspan="4"></td>
51
                 <td colspan="4"></td>
57
-                <td class="text-sm px-4 py-2 font-medium leading-6 text-gray-950 dark:text-white">Total:</td>
58
-                <td class="text-sm pl-4 py-2 leading-6">{{ $grandTotal }}</td>
52
+                <td class="text-sm p-2">Discount:</td>
53
+                <td class="text-sm p-2">({{ $discountTotal }})</td>
59
             </tr>
54
             </tr>
60
-            @if($conversionMessage)
61
-                <tr>
62
-                    <td colspan="6" class="text-sm pl-4 py-2 leading-6 text-gray-600">
63
-                        {{ $conversionMessage }}
64
-                    </td>
65
-                </tr>
66
-            @endif
55
+        @endif
56
+        <tr>
57
+            <td colspan="4"></td>
58
+            <td class="text-sm p-2 font-semibold text-gray-950 dark:text-white">{{ $amountDue ? 'Total' : 'Grand Total' }}:</td>
59
+            <td class="text-sm p-2">{{ $grandTotal }}</td>
60
+        </tr>
61
+        @if($amountDue)
62
+            <tr>
63
+                <td colspan="4"></td>
64
+                <td class="text-sm p-2 font-semibold text-gray-950 dark:text-white border-t-4 border-double">Amount Due
65
+                    ({{ $currencyCode }}):
66
+                </td>
67
+                <td class="text-sm p-2 border-t-4 border-double">{{ $amountDue }}</td>
68
+            </tr>
69
+        @endif
70
+        @if($conversionMessage)
71
+            <tr>
72
+                <td colspan="6" class="text-sm p-2 text-gray-600">
73
+                    {{ $conversionMessage }}
74
+                </td>
75
+            </tr>
76
+        @endif
67
         </tbody>
77
         </tbody>
68
     </table>
78
     </table>
69
 
79
 
70
     <!-- Mobile View -->
80
     <!-- Mobile View -->
71
-    <div class="block sm:hidden p-5">
81
+    <div class="block lg:hidden">
72
         <div class="flex flex-col space-y-6">
82
         <div class="flex flex-col space-y-6">
73
-            <div class="flex justify-between items-center">
74
-                <span class="text-sm font-medium text-gray-950 dark:text-white">Subtotal:</span>
75
-                <span class="text-sm text-gray-950 dark:text-white">{{ $subtotal }}</span>
76
-            </div>
77
-            <div class="flex justify-between items-center">
78
-                <span class="text-sm font-medium text-gray-950 dark:text-white">Taxes:</span>
79
-                <span class="text-sm text-gray-950 dark:text-white">{{ $taxTotal }}</span>
80
-            </div>
83
+            @if($subtotal)
84
+                <div class="flex justify-between items-center">
85
+                    <span class="text-sm font-semibold text-gray-950 dark:text-white">Subtotal:</span>
86
+                    <span class="text-sm">{{ $subtotal }}</span>
87
+                </div>
88
+            @endif
89
+            @if($taxTotal)
90
+                <div class="flex justify-between items-center">
91
+                    <span class="text-sm">Tax:</span>
92
+                    <span class="text-sm">{{ $taxTotal }}</span>
93
+                </div>
94
+            @endif
81
             @if($isPerDocumentDiscount)
95
             @if($isPerDocumentDiscount)
82
                 <div class="flex flex-col space-y-2">
96
                 <div class="flex flex-col space-y-2">
83
-                    <span class="text-sm font-medium text-gray-950 dark:text-white">Discount:</span>
97
+                    <span class="text-sm">Discount:</span>
84
                     <div class="flex justify-between space-x-2">
98
                     <div class="flex justify-between space-x-2">
85
                         @foreach($getChildComponentContainer()->getComponents() as $component)
99
                         @foreach($getChildComponentContainer()->getComponents() as $component)
86
                             <div class="w-1/2">{{ $component }}</div>
100
                             <div class="w-1/2">{{ $component }}</div>
87
                         @endforeach
101
                         @endforeach
88
                     </div>
102
                     </div>
89
                 </div>
103
                 </div>
90
-            @else
104
+            @elseif($discountTotal)
91
                 <div class="flex justify-between items-center">
105
                 <div class="flex justify-between items-center">
92
-                    <span class="text-sm font-medium text-gray-950 dark:text-white">Discounts:</span>
93
-                    <span class="text-sm text-gray-950 dark:text-white">({{ $discountTotal }})</span>
106
+                    <span class="text-sm">Discount:</span>
107
+                    <span class="text-sm">({{ $discountTotal }})</span>
94
                 </div>
108
                 </div>
95
             @endif
109
             @endif
96
-            <div class="flex justify-between items-center font-semibold">
97
-                <span class="text-sm font-medium text-gray-950 dark:text-white">Total:</span>
98
-                <span class="text-sm text-gray-950 dark:text-white">{{ $grandTotal }}</span>
110
+            <div class="flex justify-between items-center">
111
+                <span class="text-sm font-semibold text-gray-950 dark:text-white">{{ $amountDue ? 'Total' : 'Grand Total' }}:</span>
112
+                <span class="text-sm">{{ $grandTotal }}</span>
99
             </div>
113
             </div>
114
+            @if($amountDue)
115
+                <div class="flex justify-between items-center">
116
+                    <span
117
+                        class="text-sm font-semibold text-gray-950 dark:text-white">Amount Due ({{ $currencyCode }}):</span>
118
+                    <span class="text-sm">{{ $amountDue }}</span>
119
+                </div>
120
+            @endif
100
             @if($conversionMessage)
121
             @if($conversionMessage)
101
                 <div class="text-sm text-gray-600">
122
                 <div class="text-sm text-gray-600">
102
                     {{ $conversionMessage }}
123
                     {{ $conversionMessage }}

+ 3
- 2
resources/views/filament/infolists/components/document-preview.blade.php 查看文件

1
 @php
1
 @php
2
     $document = \App\DTO\DocumentDTO::fromModel($getRecord());
2
     $document = \App\DTO\DocumentDTO::fromModel($getRecord());
3
     $template = $getTemplate();
3
     $template = $getTemplate();
4
+    $preview = $isPreview();
4
 @endphp
5
 @endphp
5
 
6
 
6
 {!! $document->getFontHtml() !!}
7
 {!! $document->getFontHtml() !!}
12
 </style>
13
 </style>
13
 
14
 
14
 <div {{ $attributes }}>
15
 <div {{ $attributes }}>
15
-    @include("filament.infolists.components.document-templates.{$template->value}", [
16
+    @include("filament.company.components.document-templates.{$template->value}", [
16
         'document' => $document,
17
         'document' => $document,
17
-        'preview' => false,
18
+        'preview' => $preview,
18
     ])
19
     ])
19
 </div>
20
 </div>

+ 0
- 153
resources/views/filament/infolists/components/document-templates/classic.blade.php 查看文件

1
-<x-company.document-template.container class="classic-template-container">
2
-    <!-- Header Section -->
3
-    <x-company.document-template.header class="classic-template-header">
4
-        <div class="w-2/3 text-left">
5
-            <div class="text-sm">
6
-                <strong class="text-sm block">{{ $document->company->name }}</strong>
7
-                @if($formattedAddress = $document->company->getFormattedAddressHtml())
8
-                    {!! $formattedAddress !!}
9
-                @endif
10
-            </div>
11
-        </div>
12
-
13
-        <div class="w-1/3 flex justify-end">
14
-            @if($document->logo && $document->showLogo)
15
-                <x-company.document-template.logo :src="$document->logo"/>
16
-            @endif
17
-        </div>
18
-    </x-company.document-template.header>
19
-
20
-    <x-company.document-template.metadata class="classic-template-metadata space-y-4">
21
-        <div class="items-center flex">
22
-            <hr class="grow-[2] py-0.5 border-solid border-y-2" style="border-color: {{ $document->accentColor }};">
23
-            <x-icons.document-header-decoration
24
-                color="{{ $document->accentColor }}"
25
-                text="{{ $document->header }}"
26
-                class="w-60"
27
-            />
28
-            <hr class="grow-[2] py-0.5 border-solid border-y-2" style="border-color: {{ $document->accentColor }};">
29
-        </div>
30
-        @if ($document->subheader)
31
-            <p class="text-sm text-center text-gray-600 dark:text-gray-400">{{ $document->subheader }}</p>
32
-        @endif
33
-
34
-        <div class="flex justify-between items-end">
35
-            <!-- Billing Details -->
36
-            <div class="text-sm">
37
-                <h3 class="text-gray-600 dark:text-gray-400 font-medium mb-1">BILL TO</h3>
38
-                <p class="text-sm font-bold">{{ $document->client->name }}</p>
39
-                @if($formattedAddress = $document->client->getFormattedAddressHtml())
40
-                    {!! $formattedAddress !!}
41
-                @endif
42
-            </div>
43
-
44
-            <div class="text-sm">
45
-                <table class="min-w-full">
46
-                    <tbody>
47
-                    <tr>
48
-                        <td class="font-semibold text-right pr-2">{{ $document->label->number }}:</td>
49
-                        <td class="text-left pl-2">{{ $document->number }}</td>
50
-                    </tr>
51
-                    @if($document->referenceNumber)
52
-                        <tr>
53
-                            <td class="font-semibold text-right pr-2">{{ $document->label->referenceNumber }}:</td>
54
-                            <td class="text-left pl-2">{{ $document->referenceNumber }}</td>
55
-                        </tr>
56
-                    @endif
57
-                    <tr>
58
-                        <td class="font-semibold text-right pr-2">{{ $document->label->date }}:</td>
59
-                        <td class="text-left pl-2">{{ $document->date }}</td>
60
-                    </tr>
61
-                    <tr>
62
-                        <td class="font-semibold text-right pr-2">{{ $document->label->dueDate }}:</td>
63
-                        <td class="text-left pl-2">{{ $document->dueDate }}</td>
64
-                    </tr>
65
-                    </tbody>
66
-                </table>
67
-            </div>
68
-        </div>
69
-    </x-company.document-template.metadata>
70
-
71
-    <!-- Line Items -->
72
-    <x-company.document-template.line-items class="classic-template-line-items px-6">
73
-        <table class="w-full text-left table-fixed">
74
-            <thead class="text-sm leading-relaxed">
75
-            <tr>
76
-                <th class="text-left w-[50%] py-4">{{ $document->columnLabel->items }}</th>
77
-                <th class="text-center w-[10%] py-4">{{ $document->columnLabel->units }}</th>
78
-                <th class="text-right w-[20%] py-4">{{ $document->columnLabel->price }}</th>
79
-                <th class="text-right w-[20%] py-4">{{ $document->columnLabel->amount }}</th>
80
-            </tr>
81
-            </thead>
82
-            <tbody class="text-sm border-y-2 border-dotted border-gray-300">
83
-            @foreach($document->lineItems as $item)
84
-                <tr>
85
-                    <td class="text-left font-semibold py-3">
86
-                        {{ $item->name }}
87
-                        @if($item->description)
88
-                            <div class="text-gray-600 font-normal line-clamp-2 mt-1">{{ $item->description }}</div>
89
-                        @endif
90
-                    </td>
91
-                    <td class="text-center py-3">{{ $item->quantity }}</td>
92
-                    <td class="text-right py-3">{{ $item->unitPrice }}</td>
93
-                    <td class="text-right py-3">{{ $item->subtotal }}</td>
94
-                </tr>
95
-            @endforeach
96
-            </tbody>
97
-        </table>
98
-
99
-        <!-- Financial Details and Notes -->
100
-        <div class="flex justify-between text-sm space-x-1 pt-4">
101
-            <!-- Notes Section -->
102
-            <div class="w-[60%] py-2">
103
-                <p class="font-semibold">{{ $document->footer }}</p>
104
-            </div>
105
-
106
-            <!-- Financial Summary -->
107
-            <div class="w-[40%]">
108
-                <table class="w-full table-fixed whitespace-nowrap">
109
-                    <tbody class="text-sm">
110
-                    @if($document->subtotal)
111
-                        <tr>
112
-                            <td class="text-right font-semibold py-2">Subtotal:</td>
113
-                            <td class="text-right py-2">{{ $document->subtotal }}</td>
114
-                        </tr>
115
-                    @endif
116
-                    @if($document->discount)
117
-                        <tr class="text-success-800 dark:text-success-600">
118
-                            <td class="text-right py-2">Discount:</td>
119
-                            <td class="text-right py-2">
120
-                                ({{ $document->discount }})
121
-                            </td>
122
-                        </tr>
123
-                    @endif
124
-                    @if($document->tax)
125
-                        <tr>
126
-                            <td class="text-right py-2">Tax:</td>
127
-                            <td class="text-right py-2">{{ $document->tax }}</td>
128
-                        </tr>
129
-                    @endif
130
-                    <tr>
131
-                        <td class="text-right font-semibold border-t py-2">Total:</td>
132
-                        <td class="text-right border-t py-2">{{ $document->total }}</td>
133
-                    </tr>
134
-                    @if($document->amountDue)
135
-                        <tr>
136
-                            <td class="text-right font-semibold border-t-4 border-double py-2">{{ $document->label->amountDue }}
137
-                                ({{ $document->currencyCode }}):
138
-                            </td>
139
-                            <td class="text-right border-t-4 border-double py-2">{{ $document->amountDue }}</td>
140
-                        </tr>
141
-                    @endif
142
-                    </tbody>
143
-                </table>
144
-            </div>
145
-        </div>
146
-    </x-company.document-template.line-items>
147
-
148
-    <!-- Footer -->
149
-    <x-company.document-template.footer class="default-template-footer min-h-48 p-6 text-sm">
150
-        <h4 class="font-semibold mb-2">Terms & Conditions</h4>
151
-        <p class="break-words line-clamp-4">{{ $document->terms }}</p>
152
-    </x-company.document-template.footer>
153
-</x-company.document-template.container>

+ 0
- 147
resources/views/filament/infolists/components/document-templates/default.blade.php 查看文件

1
-<x-company.document-template.container class="default-template-container">
2
-
3
-    <x-company.document-template.header class="default-template-header border-b">
4
-        <div class="w-1/3">
5
-            @if($document->logo && $document->showLogo)
6
-                <x-company.document-template.logo :src="$document->logo"/>
7
-            @endif
8
-        </div>
9
-
10
-        <div class="w-2/3 text-right">
11
-            <div class="space-y-4">
12
-                <div>
13
-                    <h1 class="text-3xl font-light uppercase">{{ $document->header }}</h1>
14
-                    @if ($document->subheader)
15
-                        <p class="text-sm text-gray-600 dark:text-gray-400">{{ $document->subheader }}</p>
16
-                    @endif
17
-                </div>
18
-                <div class="text-sm">
19
-                    <strong class="text-sm block">{{ $document->company->name }}</strong>
20
-                    @if($formattedAddress = $document->company->getFormattedAddressHtml())
21
-                        {!! $formattedAddress !!}
22
-                    @endif
23
-                </div>
24
-            </div>
25
-        </div>
26
-    </x-company.document-template.header>
27
-
28
-    <x-company.document-template.metadata class="default-template-metadata space-y-4">
29
-        <div class="flex justify-between items-end">
30
-            <!-- Billing Details -->
31
-            <div class="text-sm">
32
-                <h3 class="text-gray-600 dark:text-gray-400 font-medium mb-1">BILL TO</h3>
33
-                <p class="text-sm font-bold">{{ $document->client->name }}</p>
34
-                @if($formattedAddress = $document->client->getFormattedAddressHtml())
35
-                    {!! $formattedAddress !!}
36
-                @endif
37
-            </div>
38
-
39
-            <div class="text-sm">
40
-                <table class="min-w-full">
41
-                    <tbody>
42
-                    <tr>
43
-                        <td class="font-semibold text-right pr-2">{{ $document->label->number }}:</td>
44
-                        <td class="text-left pl-2">{{ $document->number }}</td>
45
-                    </tr>
46
-                    @if($document->referenceNumber)
47
-                        <tr>
48
-                            <td class="font-semibold text-right pr-2">{{ $document->label->referenceNumber }}:</td>
49
-                            <td class="text-left pl-2">{{ $document->referenceNumber }}</td>
50
-                        </tr>
51
-                    @endif
52
-                    <tr>
53
-                        <td class="font-semibold text-right pr-2">{{ $document->label->date }}:</td>
54
-                        <td class="text-left pl-2">{{ $document->date }}</td>
55
-                    </tr>
56
-                    <tr>
57
-                        <td class="font-semibold text-right pr-2">{{ $document->label->dueDate }}:</td>
58
-                        <td class="text-left pl-2">{{ $document->dueDate }}</td>
59
-                    </tr>
60
-                    </tbody>
61
-                </table>
62
-            </div>
63
-        </div>
64
-    </x-company.document-template.metadata>
65
-
66
-    <!-- Line Items Table -->
67
-    <x-company.document-template.line-items class="default-template-line-items">
68
-        <table class="w-full text-left table-fixed">
69
-            <thead class="text-sm leading-relaxed" style="background: {{ $document->accentColor }}">
70
-            <tr class="text-white">
71
-                <th class="text-left pl-6 w-[50%] py-2">{{ $document->columnLabel->items }}</th>
72
-                <th class="text-center w-[10%] py-2">{{ $document->columnLabel->units }}</th>
73
-                <th class="text-right w-[20%] py-2">{{ $document->columnLabel->price }}</th>
74
-                <th class="text-right pr-6 w-[20%] py-2">{{ $document->columnLabel->amount }}</th>
75
-            </tr>
76
-            </thead>
77
-            <tbody class="text-sm border-b-2 border-gray-300">
78
-            @foreach($document->lineItems as $item)
79
-                <tr>
80
-                    <td class="text-left pl-6 font-semibold py-3">
81
-                        {{ $item->name }}
82
-                        @if($item->description)
83
-                            <div class="text-gray-600 font-normal line-clamp-2 mt-1">{{ $item->description }}</div>
84
-                        @endif
85
-                    </td>
86
-                    <td class="text-center py-3">{{ $item->quantity }}</td>
87
-                    <td class="text-right py-3">{{ $item->unitPrice }}</td>
88
-                    <td class="text-right pr-6 py-3">{{ $item->subtotal }}</td>
89
-                </tr>
90
-            @endforeach
91
-            </tbody>
92
-            <tfoot class="text-sm summary-section">
93
-            @if($document->subtotal)
94
-                <tr>
95
-                    <td class="pl-6 py-2" colspan="2"></td>
96
-                    <td class="text-right font-semibold py-2">Subtotal:</td>
97
-                    <td class="text-right pr-6 py-2">{{ $document->subtotal }}</td>
98
-                </tr>
99
-            @endif
100
-            @if($document->discount)
101
-                <tr class="text-success-800 dark:text-success-600">
102
-                    <td class="pl-6 py-2" colspan="2"></td>
103
-                    <td class="text-right py-2">Discount:</td>
104
-                    <td class="text-right pr-6 py-2">
105
-                        ({{ $document->discount }})
106
-                    </td>
107
-                </tr>
108
-            @endif
109
-            @if($document->tax)
110
-                <tr>
111
-                    <td class="pl-6 py-2" colspan="2"></td>
112
-                    <td class="text-right py-2">Tax:</td>
113
-                    <td class="text-right pr-6 py-2">{{ $document->tax }}</td>
114
-                </tr>
115
-            @endif
116
-            <tr>
117
-                <td class="pl-6 py-2" colspan="2"></td>
118
-                <td class="text-right font-semibold border-t py-2">Total:</td>
119
-                <td class="text-right border-t pr-6 py-2">{{ $document->total }}</td>
120
-            </tr>
121
-            @if($document->amountDue)
122
-                <tr>
123
-                    <td class="pl-6 py-2" colspan="2"></td>
124
-                    <td class="text-right font-semibold border-t-4 border-double py-2">{{ $document->label->amountDue }}
125
-                        ({{ $document->currencyCode }}):
126
-                    </td>
127
-                    <td class="text-right border-t-4 border-double pr-6 py-2">{{ $document->amountDue }}</td>
128
-                </tr>
129
-            @endif
130
-            </tfoot>
131
-        </table>
132
-    </x-company.document-template.line-items>
133
-
134
-    <!-- Footer Notes -->
135
-    <x-company.document-template.footer class="classic-template-footer min-h-48 flex flex-col text-sm p-6">
136
-        <div>
137
-            <h4 class="font-semibold mb-2">Terms & Conditions</h4>
138
-            <p class="break-words line-clamp-4">{{ $document->terms }}</p>
139
-        </div>
140
-
141
-        @if($document->footer)
142
-            <div class="mt-auto text-center py-4">
143
-                <p class="font-semibold">{{ $document->footer }}</p>
144
-            </div>
145
-        @endif
146
-    </x-company.document-template.footer>
147
-</x-company.document-template.container>

+ 0
- 147
resources/views/filament/infolists/components/document-templates/modern.blade.php 查看文件

1
-<x-company.document-template.container class="modern-template-container">
2
-    <!-- Colored Header with Logo -->
3
-    <x-company.document-template.header class="bg-gray-800 h-24">
4
-        <!-- Logo -->
5
-        <div class="w-2/3">
6
-            @if($document->logo && $document->showLogo)
7
-                <x-company.document-template.logo class="ml-8" :src="$document->logo"/>
8
-            @endif
9
-        </div>
10
-
11
-        <!-- Ribbon Container -->
12
-        <div class="w-1/3 absolute right-0 top-0 p-3 h-32 flex flex-col justify-end rounded-bl-sm"
13
-             style="background: {{ $document->accentColor }};">
14
-            @if($document->header)
15
-                <h1 class="text-4xl font-bold text-white text-center uppercase">{{ $document->header }}</h1>
16
-            @endif
17
-        </div>
18
-    </x-company.document-template.header>
19
-
20
-    <!-- Company Details -->
21
-    <x-company.document-template.metadata class="modern-template-metadata space-y-8">
22
-        <div class="text-sm">
23
-            <h2 class="text-lg font-semibold">{{ $document->company->name }}</h2>
24
-            @if($formattedAddress = $document->company->getFormattedAddressHtml())
25
-                {!! $formattedAddress !!}
26
-            @endif
27
-        </div>
28
-
29
-        <div class="flex justify-between items-end">
30
-            <!-- Billing Details -->
31
-            <div class="text-sm">
32
-                <h3 class="text-gray-600 dark:text-gray-400 font-medium mb-1">BILL TO</h3>
33
-                <p class="text-sm font-bold"
34
-                   style="color: {{ $document->accentColor }}">{{ $document->client->name }}</p>
35
-
36
-                @if($formattedAddress = $document->client->getFormattedAddressHtml())
37
-                    {!! $formattedAddress !!}
38
-                @endif
39
-            </div>
40
-
41
-            <div class="text-sm">
42
-                <table class="min-w-full">
43
-                    <tbody>
44
-                    <tr>
45
-                        <td class="font-semibold text-right pr-2">{{ $document->label->number }}:</td>
46
-                        <td class="text-left pl-2">{{ $document->number }}</td>
47
-                    </tr>
48
-                    @if($document->referenceNumber)
49
-                        <tr>
50
-                            <td class="font-semibold text-right pr-2">{{ $document->label->referenceNumber }}:</td>
51
-                            <td class="text-left pl-2">{{ $document->referenceNumber }}</td>
52
-                        </tr>
53
-                    @endif
54
-                    <tr>
55
-                        <td class="font-semibold text-right pr-2">{{ $document->label->date }}:</td>
56
-                        <td class="text-left pl-2">{{ $document->date }}</td>
57
-                    </tr>
58
-                    <tr>
59
-                        <td class="font-semibold text-right pr-2">{{ $document->label->dueDate }}:</td>
60
-                        <td class="text-left pl-2">{{ $document->dueDate }}</td>
61
-                    </tr>
62
-                    </tbody>
63
-                </table>
64
-            </div>
65
-        </div>
66
-    </x-company.document-template.metadata>
67
-
68
-    <!-- Line Items Table -->
69
-    <x-company.document-template.line-items class="modern-template-line-items">
70
-        <table class="w-full text-left table-fixed">
71
-            <thead class="text-sm leading-relaxed">
72
-            <tr class="text-gray-600 dark:text-gray-400">
73
-                <th class="text-left pl-6 w-[50%] py-4">{{ $document->columnLabel->items }}</th>
74
-                <th class="text-center w-[10%] py-4">{{ $document->columnLabel->units }}</th>
75
-                <th class="text-right w-[20%] py-4">{{ $document->columnLabel->price }}</th>
76
-                <th class="text-right pr-6 w-[20%] py-4">{{ $document->columnLabel->amount }}</th>
77
-            </tr>
78
-            </thead>
79
-            <tbody class="text-sm border-y-2">
80
-            @foreach($document->lineItems as $index => $item)
81
-                <tr @class(['bg-gray-100 dark:bg-gray-800' => $index % 2 === 0])>
82
-                    <td class="text-left pl-6 font-semibold py-3">
83
-                        {{ $item->name }}
84
-                        @if($item->description)
85
-                            <div class="text-gray-600 font-normal line-clamp-2 mt-1">{{ $item->description }}</div>
86
-                        @endif
87
-                    </td>
88
-                    <td class="text-center py-3">{{ $item->quantity }}</td>
89
-                    <td class="text-right py-3">{{ $item->unitPrice }}</td>
90
-                    <td class="text-right pr-6 py-3">{{ $item->subtotal }}</td>
91
-                </tr>
92
-            @endforeach
93
-            </tbody>
94
-            <tfoot class="text-sm summary-section">
95
-            @if($document->subtotal)
96
-                <tr>
97
-                    <td class="pl-6 py-2" colspan="2"></td>
98
-                    <td class="text-right font-semibold py-2">Subtotal:</td>
99
-                    <td class="text-right pr-6 py-2">{{ $document->subtotal }}</td>
100
-                </tr>
101
-            @endif
102
-            @if($document->discount)
103
-                <tr class="text-success-800 dark:text-success-600">
104
-                    <td class="pl-6 py-2" colspan="2"></td>
105
-                    <td class="text-right py-2">Discount:</td>
106
-                    <td class="text-right pr-6 py-2">
107
-                        ({{ $document->discount }})
108
-                    </td>
109
-                </tr>
110
-            @endif
111
-            @if($document->tax)
112
-                <tr>
113
-                    <td class="pl-6 py-2" colspan="2"></td>
114
-                    <td class="text-right py-2">Tax:</td>
115
-                    <td class="text-right pr-6 py-2">{{ $document->tax }}</td>
116
-                </tr>
117
-            @endif
118
-            <tr>
119
-                <td class="pl-6 py-2" colspan="2"></td>
120
-                <td class="text-right font-semibold border-t py-2">Total:</td>
121
-                <td class="text-right border-t pr-6 py-2">{{ $document->total }}</td>
122
-            </tr>
123
-            @if($document->amountDue)
124
-                <tr>
125
-                    <td class="pl-6 py-2" colspan="2"></td>
126
-                    <td class="text-right font-semibold border-t-4 border-double py-2">{{ $document->label->amountDue }}
127
-                        ({{ $document->currencyCode }}):
128
-                    </td>
129
-                    <td class="text-right border-t-4 border-double pr-6 py-2">{{ $document->amountDue }}</td>
130
-                </tr>
131
-            @endif
132
-            </tfoot>
133
-        </table>
134
-    </x-company.document-template.line-items>
135
-
136
-    <!-- Footer Notes -->
137
-    <x-company.document-template.footer class="modern-template-footer">
138
-        <h4 class="font-semibold px-6 text-sm" style="color: {{ $document->accentColor }}">
139
-            Terms & Conditions
140
-        </h4>
141
-        <span class="border-t-2 my-2 border-gray-300 block w-full"></span>
142
-        <div class="flex justify-between space-x-4 px-6 text-sm">
143
-            <p class="w-1/2 break-words line-clamp-4">{{ $document->terms }}</p>
144
-            <p class="w-1/2 break-words line-clamp-4">{{ $document->footer }}</p>
145
-        </div>
146
-    </x-company.document-template.footer>
147
-</x-company.document-template.container>

Loading…
取消
儲存