Feat: Upgrading Lunar to 1.5

This commit is contained in:
2026-08-31 13:16:13 +03:00
parent 661e8b9a96
commit d873cb4931
42 changed files with 229 additions and 173 deletions
+5 -4
View File
@@ -10,15 +10,15 @@
}, },
"require": { "require": {
"php": "^8.5", "php": "^8.5",
"lunarphp/lunar": "1.3.0", "lunarphp/lunar": "1.5.0",
"laravel/framework": "^12.0", "laravel/framework": "^12.0",
"laravel/tinker": "^3.0", "laravel/tinker": "^3.0",
"symfony/yaml": "^7.0", "symfony/yaml": "^7.0",
"lunarphp/table-rate-shipping": "^1.3", "lunarphp/table-rate-shipping": "1.5.0",
"lunarphp/search": "*", "lunarphp/search": "*",
"lunarphp/meilisearch": "*", "lunarphp/meilisearch": "*",
"spatie/laravel-translation-loader": "^2.8", "spatie/laravel-translation-loader": "^2.8",
"lunarphp/stripe": "1.3.0" "lunarphp/stripe": "^1.5"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.23",
@@ -28,7 +28,8 @@
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6", "nunomaduro/collision": "^8.6",
"pestphp/pest": "^4.6", "pestphp/pest": "^4.6",
"pestphp/pest-plugin-laravel": "^4.1" "pestphp/pest-plugin-laravel": "^4.1",
"filament/upgrade": "^4.0"
}, },
"extra": { "extra": {
"laravel": { "laravel": {
@@ -2,18 +2,18 @@
namespace Modules\Core\Auth\Extensions; namespace Modules\Core\Auth\Extensions;
use Filament\Forms\Form; use Filament\Schemas\Schema;
use Lunar\Admin\Support\Extending\ResourceExtension; use Lunar\Admin\Support\Extending\ResourceExtension;
class StaffResourceExtension extends ResourceExtension class StaffResourceExtension extends ResourceExtension
{ {
public function extendForm(Form $form): Form public function extendForm(Schema $form): Schema
{ {
$schema = collect($form->getComponents()) $schema = collect($form->getComponents())
->reject(fn ($component) => method_exists($component, 'getName') && $component->getName() == 'password') ->reject(fn ($component) => method_exists($component, 'getName') && $component->getName() == 'password')
->values() ->values()
->all(); ->all();
return $form->schema($schema); return $form->components($schema);
} }
} }
+2 -2
View File
@@ -15,7 +15,7 @@ class Login extends SimplePage
{ {
use WithRateLimiting; use WithRateLimiting;
protected static string $view = 'core::auth.filament.pages.login'; protected string $view = 'core::auth.filament.pages.login';
public ?string $email = ''; public ?string $email = '';
public ?string $otp = ''; public ?string $otp = '';
@@ -78,7 +78,7 @@ class Login extends SimplePage
]); ]);
} }
if ($staff instanceof FilamentUser && !$staff->canAccessPanel(Filament::getCurrentPanel())) { if ($staff instanceof FilamentUser && !$staff->canAccessPanel(Filament::getCurrentOrDefaultPanel())) {
throw ValidationException::withMessages([ throw ValidationException::withMessages([
'email' => 'You do not have access to this panel.', 'email' => 'You do not have access to this panel.',
]); ]);
@@ -12,8 +12,8 @@ use RuntimeException;
*/ */
class InvalidCouponException extends RuntimeException class InvalidCouponException extends RuntimeException
{ {
public function __construct(public readonly string $code) public function __construct(public readonly string $couponCode)
{ {
parent::__construct("The coupon code \"{$code}\" is not valid."); parent::__construct("The coupon code \"{$couponCode}\" is not valid.");
} }
} }
+17 -13
View File
@@ -2,6 +2,10 @@
namespace Modules\Core\Cart\Filament\Resources; namespace Modules\Core\Cart\Filament\Resources;
use Filament\Tables\Columns\TextColumn;
use Filament\Actions\ViewAction;
use Modules\Core\Cart\Filament\Resources\CartResource\Pages\ListCarts;
use Modules\Core\Cart\Filament\Resources\CartResource\Pages\ViewCart;
use Filament\Resources\Resource; use Filament\Resources\Resource;
use Filament\Tables; use Filament\Tables;
use Filament\Tables\Table; use Filament\Tables\Table;
@@ -24,9 +28,9 @@ class CartResource extends Resource
{ {
protected static ?string $model = Cart::class; protected static ?string $model = Cart::class;
protected static ?string $navigationIcon = 'heroicon-o-shopping-cart'; protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-shopping-cart';
protected static ?string $navigationGroup = 'Sales'; protected static string | \UnitEnum | null $navigationGroup = 'Sales';
protected static ?string $modelLabel = 'Cart'; protected static ?string $modelLabel = 'Cart';
@@ -70,37 +74,37 @@ class CartResource extends Resource
{ {
return $table return $table
->columns([ ->columns([
Tables\Columns\TextColumn::make('id') TextColumn::make('id')
->label('Cart') ->label('Cart')
->sortable(), ->sortable(),
Tables\Columns\TextColumn::make('customer.full_name') TextColumn::make('customer.full_name')
->label('Customer') ->label('Customer')
->placeholder('—') ->placeholder('—')
->searchable() ->searchable()
->url(fn (Cart $record) => $record->customer_id !== null ->url(fn (Cart $record) => $record->customer_id !== null
? CustomerResource::getUrl('view', ['record' => $record->customer_id]) ? CustomerResource::getUrl('view', ['record' => $record->customer_id])
: null), : null),
Tables\Columns\TextColumn::make('user.email') TextColumn::make('user.email')
->label('User') ->label('User')
->placeholder('—') ->placeholder('—')
->searchable(), ->searchable(),
Tables\Columns\TextColumn::make('lines_count') TextColumn::make('lines_count')
->label('Lines') ->label('Lines')
->counts('lines') ->counts('lines')
->sortable(), ->sortable(),
Tables\Columns\TextColumn::make('lines_sum_quantity') TextColumn::make('lines_sum_quantity')
->label('Items') ->label('Items')
->sum('lines', 'quantity') ->sum('lines', 'quantity')
->sortable(), ->sortable(),
Tables\Columns\TextColumn::make('currency.code') TextColumn::make('currency.code')
->label('Currency'), ->label('Currency'),
Tables\Columns\TextColumn::make('updated_at') TextColumn::make('updated_at')
->label('Last activity') ->label('Last activity')
->dateTime() ->dateTime()
->sortable(), ->sortable(),
]) ])
->actions([ ->recordActions([
Tables\Actions\ViewAction::make(), ViewAction::make(),
]) ])
->defaultSort('updated_at', 'desc'); ->defaultSort('updated_at', 'desc');
} }
@@ -108,8 +112,8 @@ class CartResource extends Resource
public static function getPages(): array public static function getPages(): array
{ {
return [ return [
'index' => Pages\ListCarts::route('/'), 'index' => ListCarts::route('/'),
'view' => Pages\ViewCart::route('/{record}'), 'view' => ViewCart::route('/{record}'),
]; ];
} }
@@ -2,7 +2,7 @@
namespace Modules\Core\Cart\Filament\Resources\CartResource\Pages; namespace Modules\Core\Cart\Filament\Resources\CartResource\Pages;
use Filament\Resources\Components\Tab; use Filament\Schemas\Components\Tabs\Tab;
use Filament\Resources\Pages\ListRecords; use Filament\Resources\Pages\ListRecords;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Modules\Core\Cart\Filament\Resources\CartResource; use Modules\Core\Cart\Filament\Resources\CartResource;
@@ -2,11 +2,11 @@
namespace Modules\Core\Cart\Filament\Resources\CartResource\Pages; namespace Modules\Core\Cart\Filament\Resources\CartResource\Pages;
use Filament\Schemas\Schema;
use Filament\Schemas\Components\Section;
use Filament\Actions\Action; use Filament\Actions\Action;
use Filament\Infolists\Components\RepeatableEntry; use Filament\Infolists\Components\RepeatableEntry;
use Filament\Infolists\Components\Section;
use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Infolist;
use Filament\Resources\Pages\ViewRecord; use Filament\Resources\Pages\ViewRecord;
use Lunar\Admin\Filament\Resources\CustomerResource; use Lunar\Admin\Filament\Resources\CustomerResource;
use Lunar\Models\Cart; use Lunar\Models\Cart;
@@ -44,10 +44,10 @@ class ViewCart extends ViewRecord
return $cart->calculate(); return $cart->calculate();
} }
public function infolist(Infolist $infolist): Infolist public function infolist(Schema $schema): Schema
{ {
return $infolist return $schema
->schema([ ->components([
Section::make('Cart') Section::make('Cart')
->columns(3) ->columns(3)
->schema([ ->schema([
@@ -2,7 +2,7 @@
namespace Modules\Core\Catalog\Contracts; namespace Modules\Core\Catalog\Contracts;
use Filament\Forms\Components\Component; use Filament\Schemas\Components\Component;
/** /**
* A Product Option Type describes how a category of Lunar `ProductOption` (e.g. * A Product Option Type describes how a category of Lunar `ProductOption` (e.g.
@@ -2,8 +2,8 @@
namespace Modules\Core\Catalog\Filament\Extensions; namespace Modules\Core\Catalog\Filament\Extensions;
use Filament\Schemas\Schema;
use Filament\Forms\Components\Select; use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Lunar\Admin\Support\Extending\ResourceExtension; use Lunar\Admin\Support\Extending\ResourceExtension;
use Modules\Core\Catalog\Services\ProductOptionTypeManager; use Modules\Core\Catalog\Services\ProductOptionTypeManager;
@@ -16,7 +16,7 @@ use Modules\Core\Catalog\Services\ProductOptionTypeManager;
*/ */
class ProductOptionResourceExtension extends ResourceExtension class ProductOptionResourceExtension extends ResourceExtension
{ {
public function extendForm(Form $form): Form public function extendForm(Schema $schema): Schema
{ {
$options = collect(ProductOptionTypeManager::get()->all()) $options = collect(ProductOptionTypeManager::get()->all())
->keys() ->keys()
@@ -24,11 +24,11 @@ class ProductOptionResourceExtension extends ResourceExtension
->all(); ->all();
if ($options === []) { if ($options === []) {
return $form; return $schema;
} }
return $form->schema([ return $schema->components([
...$form->getComponents(), ...$schema->getComponents(),
Select::make('meta.option_type') Select::make('meta.option_type')
->label('Option Type') ->label('Option Type')
->options($options) ->options($options)
@@ -2,7 +2,7 @@
namespace Modules\Core\Catalog\Filament\Extensions; namespace Modules\Core\Catalog\Filament\Extensions;
use Filament\Forms\Form; use Filament\Schemas\Schema;
use Lunar\Admin\Support\Extending\RelationManagerExtension; use Lunar\Admin\Support\Extending\RelationManagerExtension;
use Lunar\Models\ProductOption; use Lunar\Models\ProductOption;
use Modules\Core\Catalog\Services\ProductOptionTypeManager; use Modules\Core\Catalog\Services\ProductOptionTypeManager;
@@ -15,7 +15,7 @@ use Modules\Core\Catalog\Services\ProductOptionTypeManager;
*/ */
class ValuesRelationManagerExtension extends RelationManagerExtension class ValuesRelationManagerExtension extends RelationManagerExtension
{ {
public function extendForm(Form $form): Form public function extendForm(Schema $schema): Schema
{ {
/** @var ProductOption $option */ /** @var ProductOption $option */
$option = $this->caller->getOwnerRecord(); $option = $this->caller->getOwnerRecord();
@@ -23,11 +23,11 @@ class ValuesRelationManagerExtension extends RelationManagerExtension
$type = ProductOptionTypeManager::get()->resolve($option->meta['option_type'] ?? null); $type = ProductOptionTypeManager::get()->resolve($option->meta['option_type'] ?? null);
if ($type === null) { if ($type === null) {
return $form; return $schema;
} }
return $form->schema([ return $schema->components([
...$form->getComponents(), ...$schema->getComponents(),
...$type->getMetaForm(), ...$type->getMetaForm(),
]); ]);
} }
+4 -2
View File
@@ -2,6 +2,8 @@
namespace Modules\Core\Checkout\Contracts; namespace Modules\Core\Checkout\Contracts;
use Lunar\Exceptions\FingerprintMismatchException;
use Lunar\Exceptions\Carts\CartException;
use Lunar\Models\Cart; use Lunar\Models\Cart;
use Lunar\Models\Order; use Lunar\Models\Order;
@@ -34,8 +36,8 @@ interface PaymentDriver
* *
* @param array<string, mixed> $data * @param array<string, mixed> $data
* *
* @throws \Lunar\Exceptions\FingerprintMismatchException * @throws FingerprintMismatchException
* @throws \Lunar\Exceptions\Carts\CartException * @throws CartException
*/ */
public function confirm(Cart $cart, string $fingerprint, array $data): Order; public function confirm(Cart $cart, string $fingerprint, array $data): Order;
} }
+4 -2
View File
@@ -2,6 +2,8 @@
namespace Modules\Core\Checkout\Services; namespace Modules\Core\Checkout\Services;
use Lunar\Exceptions\FingerprintMismatchException;
use Lunar\Exceptions\Carts\CartException;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use Lunar\Base\Addressable; use Lunar\Base\Addressable;
@@ -107,8 +109,8 @@ class CheckoutService
* render as form errors directly. FingerprintMismatchException * render as form errors directly. FingerprintMismatchException
* propagates the same way, for the same reason. * propagates the same way, for the same reason.
* *
* @throws \Lunar\Exceptions\FingerprintMismatchException * @throws FingerprintMismatchException
* @throws \Lunar\Exceptions\Carts\CartException * @throws CartException
*/ */
public function placeOrder(string $fingerprint): Order public function placeOrder(string $fingerprint): Order
{ {
+2 -1
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Command; namespace Modules\Core\Command;
use Lunar\Admin\Models\Staff;
use Lunar\Admin\Console\Commands\MakeLunarAdminCommand; use Lunar\Admin\Console\Commands\MakeLunarAdminCommand;
use function Laravel\Prompts\text; use function Laravel\Prompts\text;
@@ -31,7 +32,7 @@ class CreateAdminCommand extends MakeLunarAdminCommand
required: true, required: true,
validate: fn (string $email): ?string => match (true) { validate: fn (string $email): ?string => match (true) {
! filter_var($email, FILTER_VALIDATE_EMAIL) => 'The email address must be valid.', ! filter_var($email, FILTER_VALIDATE_EMAIL) => 'The email address must be valid.',
\Lunar\Admin\Models\Staff::where('email', $email)->exists() => 'A user with this email address already exists', Staff::where('email', $email)->exists() => 'A user with this email address already exists',
default => null, default => null,
}, },
), ),
+6 -3
View File
@@ -2,6 +2,9 @@
namespace Modules\Core\Command; namespace Modules\Core\Command;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
use FilesystemIterator;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Modules\Core\ResultType\Error; use Modules\Core\ResultType\Error;
@@ -88,10 +91,10 @@ class ExportCommand extends Command
$zip->addFile($sqlFile, basename($sqlFile)); $zip->addFile($sqlFile, basename($sqlFile));
if (is_dir($filesDir)) { if (is_dir($filesDir)) {
$iterator = new \RecursiveIteratorIterator( $iterator = new RecursiveIteratorIterator(
new \RecursiveDirectoryIterator( new RecursiveDirectoryIterator(
$filesDir, $filesDir,
\FilesystemIterator::SKIP_DOTS, FilesystemIterator::SKIP_DOTS,
), ),
); );
foreach ($iterator as $file) { foreach ($iterator as $file) {
+4 -4
View File
@@ -2,6 +2,7 @@
namespace Modules\Core; namespace Modules\Core;
use Lunar\Admin\Filament\Resources\OrderResource\Pages\ManageOrder;
use Filament\Contracts\Plugin; use Filament\Contracts\Plugin;
use Filament\Panel; use Filament\Panel;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -59,7 +60,7 @@ class CorePlugin implements Plugin
ValuesRelationManager::class => ValuesRelationManagerExtension::class, ValuesRelationManager::class => ValuesRelationManagerExtension::class,
ShippingMethodResource::class => ShippingMethodResourceExtension::class, ShippingMethodResource::class => ShippingMethodResourceExtension::class,
ListShippingMethod::class => ShippingMethodListExtension::class, ListShippingMethod::class => ShippingMethodListExtension::class,
OrderResource\Pages\ManageOrder::class => OrderViewExtension::class, ManageOrder::class => OrderViewExtension::class,
]); ]);
Product::macro('reviews', function (): HasMany { Product::macro('reviews', function (): HasMany {
@@ -73,9 +74,8 @@ class CorePlugin implements Plugin
'password', 'password',
'remember_token', 'remember_token',
'email_verified_at', 'email_verified_at',
'two_factor_secret', 'app_authentication_secret',
'two_factor_recovery_codes', 'app_authentication_recovery_codes',
'two_factor_confirmed_at',
]); ]);
LunarStaff::created(function (LunarStaff $staff) { LunarStaff::created(function (LunarStaff $staff) {
@@ -2,12 +2,12 @@
namespace Modules\Core\Customer\RelationManagers; namespace Modules\Core\Customer\RelationManagers;
use Filament\Forms\Components\Group; use Filament\Actions\CreateAction;
use Filament\Actions\EditAction;
use Filament\Actions\DeleteAction;
use Filament\Schemas\Components\Group;
use Filament\Forms\Components\Select; use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput; use Filament\Forms\Components\TextInput;
use Filament\Tables\Actions\CreateAction;
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\EditAction;
use Filament\Tables\Columns\TextColumn; use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table; use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@@ -38,9 +38,9 @@ class AddressRelationManager extends BaseAddressRelationManager
), ),
]) ])
->headerActions([ ->headerActions([
CreateAction::make()->form($this->addressForm()), CreateAction::make()->schema($this->addressForm()),
]) ])
->actions([ ->recordActions([
EditAction::make('editAddress') EditAction::make('editAddress')
->fillForm(fn (AddressContract $record): array => [ ->fillForm(fn (AddressContract $record): array => [
'line_one' => $record->line_one, 'line_one' => $record->line_one,
@@ -51,7 +51,7 @@ class AddressRelationManager extends BaseAddressRelationManager
'contact_email' => $record->contact_email, 'contact_email' => $record->contact_email,
'contact_phone' => $record->contact_phone, 'contact_phone' => $record->contact_phone,
]) ])
->form($this->addressForm()), ->schema($this->addressForm()),
DeleteAction::make('deleteAddress'), DeleteAction::make('deleteAddress'),
]); ]);
} }
@@ -2,6 +2,8 @@
namespace Modules\Core\Customer\RelationManagers; namespace Modules\Core\Customer\RelationManagers;
use Filament\Tables\Columns\TextColumn;
use Filament\Actions\EditAction;
use Filament\Forms\Components\TextInput; use Filament\Forms\Components\TextInput;
use Filament\Tables; use Filament\Tables;
use Filament\Tables\Table; use Filament\Tables\Table;
@@ -14,16 +16,16 @@ class UserRelationManager extends BaseUserRelationManager
public function getDefaultTable(Table $table): Table public function getDefaultTable(Table $table): Table
{ {
return $table->columns([ return $table->columns([
Tables\Columns\TextColumn::make('name') TextColumn::make('name')
->label(__('lunarpanel::user.table.name.label')), ->label(__('lunarpanel::user.table.name.label')),
Tables\Columns\TextColumn::make('email') TextColumn::make('email')
->label(__('lunarpanel::user.table.email.label')), ->label(__('lunarpanel::user.table.email.label')),
])->actions([ ])->recordActions([
Tables\Actions\EditAction::make('edit') EditAction::make('edit')
->after( ->after(
fn (Model $record) => CustomerUserEdited::dispatch($record) fn (Model $record) => CustomerUserEdited::dispatch($record)
) )
->form([ ->schema([
TextInput::make('email') TextInput::make('email')
->label(__('lunarpanel::user.form.email.label')) ->label(__('lunarpanel::user.form.email.label'))
->required() ->required()
@@ -2,8 +2,17 @@
namespace Modules\Core\Localization\Filament\Resources; namespace Modules\Core\Localization\Filament\Resources;
use Filament\Schemas\Schema;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Fieldset;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Modules\Core\Localization\Filament\Resources\LanguageLineResource\Pages\ListLanguageLines;
use Modules\Core\Localization\Filament\Resources\LanguageLineResource\Pages\CreateLanguageLine;
use Modules\Core\Localization\Filament\Resources\LanguageLineResource\Pages\EditLanguageLine;
use Filament\Forms\Components\Textarea;
use Illuminate\Support\Collection;
use Filament\Forms; use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource; use Filament\Resources\Resource;
use Filament\Tables; use Filament\Tables;
use Filament\Tables\Table; use Filament\Tables\Table;
@@ -15,29 +24,29 @@ class LanguageLineResource extends Resource
{ {
protected static ?string $model = LanguageLine::class; protected static ?string $model = LanguageLine::class;
protected static ?string $navigationIcon = 'heroicon-o-language'; protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-language';
protected static ?string $navigationGroup = 'Settings'; protected static string | \UnitEnum | null $navigationGroup = 'Settings';
protected static ?string $modelLabel = 'Translation'; protected static ?string $modelLabel = 'Translation';
protected static ?string $pluralModelLabel = 'Translations'; protected static ?string $pluralModelLabel = 'Translations';
public static function form(Form $form): Form public static function form(Schema $schema): Schema
{ {
return $form->schema([ return $schema->components([
Forms\Components\TextInput::make('group') TextInput::make('group')
->required() ->required()
->maxLength(255) ->maxLength(255)
->default('storefront') ->default('storefront')
->helperText('Namespace for this label, e.g. "storefront" for e-shop UI text.'), ->helperText('Namespace for this label, e.g. "storefront" for e-shop UI text.'),
Forms\Components\TextInput::make('key') TextInput::make('key')
->required() ->required()
->maxLength(255) ->maxLength(255)
->helperText('Dot-notation key, e.g. "nav.cart".'), ->helperText('Dot-notation key, e.g. "nav.cart".'),
Forms\Components\Fieldset::make('Translations') Fieldset::make('Translations')
->schema(static::localeInputs()), ->schema(static::localeInputs()),
]); ]);
} }
@@ -46,16 +55,16 @@ class LanguageLineResource extends Resource
{ {
return $table return $table
->columns([ ->columns([
Tables\Columns\TextColumn::make('group') TextColumn::make('group')
->badge() ->badge()
->sortable(), ->sortable(),
Tables\Columns\TextColumn::make('key') TextColumn::make('key')
->searchable() ->searchable()
->sortable(), ->sortable(),
...static::localeColumns(), ...static::localeColumns(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('group') SelectFilter::make('group')
->options(fn () => LanguageLine::query()->distinct()->pluck('group', 'group')), ->options(fn () => LanguageLine::query()->distinct()->pluck('group', 'group')),
]) ])
->defaultSort('key'); ->defaultSort('key');
@@ -69,38 +78,38 @@ class LanguageLineResource extends Resource
public static function getPages(): array public static function getPages(): array
{ {
return [ return [
'index' => Pages\ListLanguageLines::route('/'), 'index' => ListLanguageLines::route('/'),
'create' => Pages\CreateLanguageLine::route('/create'), 'create' => CreateLanguageLine::route('/create'),
'edit' => Pages\EditLanguageLine::route('/{record}/edit'), 'edit' => EditLanguageLine::route('/{record}/edit'),
]; ];
} }
/** /**
* @return array<Forms\Components\Textarea> * @return array<Textarea>
*/ */
private static function localeInputs(): array private static function localeInputs(): array
{ {
return static::localeCodes() return static::localeCodes()
->map(fn (string $code) => Forms\Components\Textarea::make("text.{$code}") ->map(fn (string $code) => Textarea::make("text.{$code}")
->label(strtoupper($code)) ->label(strtoupper($code))
->rows(2)) ->rows(2))
->all(); ->all();
} }
/** /**
* @return array<Tables\Columns\TextColumn> * @return array<TextColumn>
*/ */
private static function localeColumns(): array private static function localeColumns(): array
{ {
return static::localeCodes() return static::localeCodes()
->map(fn (string $code) => Tables\Columns\TextColumn::make("text.{$code}") ->map(fn (string $code) => TextColumn::make("text.{$code}")
->label(strtoupper($code)) ->label(strtoupper($code))
->limit(40) ->limit(40)
->toggleable()) ->toggleable())
->all(); ->all();
} }
private static function localeCodes(): \Illuminate\Support\Collection private static function localeCodes(): Collection
{ {
return Language::query()->pluck('code'); return Language::query()->pluck('code');
} }
@@ -2,6 +2,7 @@
namespace Modules\Core\Localization\Filament\Resources\LanguageLineResource\Pages; namespace Modules\Core\Localization\Filament\Resources\LanguageLineResource\Pages;
use Filament\Actions\DeleteAction;
use Filament\Actions; use Filament\Actions;
use Filament\Actions\Action; use Filament\Actions\Action;
use Filament\Resources\Pages\EditRecord; use Filament\Resources\Pages\EditRecord;
@@ -17,7 +18,7 @@ class EditLanguageLine extends EditRecord
protected function getHeaderActions(): array protected function getHeaderActions(): array
{ {
return [ return [
Actions\DeleteAction::make() DeleteAction::make()
->action(function (LanguageLine $record) { ->action(function (LanguageLine $record) {
app(TranslationService::class)->delete($record); app(TranslationService::class)->delete($record);
@@ -2,6 +2,7 @@
namespace Modules\Core\Localization\Filament\Resources\LanguageLineResource\Pages; namespace Modules\Core\Localization\Filament\Resources\LanguageLineResource\Pages;
use Filament\Actions\CreateAction;
use Filament\Actions; use Filament\Actions;
use Filament\Resources\Pages\ListRecords; use Filament\Resources\Pages\ListRecords;
use Modules\Core\Localization\Filament\Resources\LanguageLineResource; use Modules\Core\Localization\Filament\Resources\LanguageLineResource;
@@ -13,7 +14,7 @@ class ListLanguageLines extends ListRecords
protected function getHeaderActions(): array protected function getHeaderActions(): array
{ {
return [ return [
Actions\CreateAction::make(), CreateAction::make(),
]; ];
} }
} }
+2 -1
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\MigrateImport; namespace Modules\Core\MigrateImport;
use InvalidArgumentException;
use Modules\Core\MigrateImport\JudgeMe\JudgeMeExportImporter; use Modules\Core\MigrateImport\JudgeMe\JudgeMeExportImporter;
use Modules\Core\MigrateImport\Shopify\ShopifyExportImporter; use Modules\Core\MigrateImport\Shopify\ShopifyExportImporter;
@@ -15,7 +16,7 @@ class ImporterFactory
['judgeme', 'export'] => new JudgeMeExportImporter, ['judgeme', 'export'] => new JudgeMeExportImporter,
// ["woocommerce", "export"] => new WooCommerceExportImporter(), // ["woocommerce", "export"] => new WooCommerceExportImporter(),
// ["woocommerce", "api"] => new WooCommerceApiImporter(), // ["woocommerce", "api"] => new WooCommerceApiImporter(),
default => throw new \InvalidArgumentException( default => throw new InvalidArgumentException(
"No importer available for source \"{$spec->source}\" with type \"{$spec->type}\".", "No importer available for source \"{$spec->source}\" with type \"{$spec->type}\".",
), ),
}; };
@@ -2,6 +2,8 @@
namespace Modules\Core\MigrateImport\JudgeMe; namespace Modules\Core\MigrateImport\JudgeMe;
use RuntimeException;
class JudgeMeCsvReader class JudgeMeCsvReader
{ {
/** /**
@@ -12,7 +14,7 @@ class JudgeMeCsvReader
$handle = fopen($csvPath, 'r'); $handle = fopen($csvPath, 'r');
if ($handle === false) { if ($handle === false) {
throw new \RuntimeException("Could not open CSV file: {$csvPath}"); throw new RuntimeException("Could not open CSV file: {$csvPath}");
} }
$headers = fgetcsv($handle); $headers = fgetcsv($handle);
@@ -2,6 +2,7 @@
namespace Modules\Core\MigrateImport\JudgeMe; namespace Modules\Core\MigrateImport\JudgeMe;
use Throwable;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Modules\Core\MigrateImport\Importer; use Modules\Core\MigrateImport\Importer;
@@ -75,7 +76,7 @@ class JudgeMeExportImporter implements Importer
foreach ($urls as $url) { foreach ($urls as $url) {
try { try {
$review->addMediaFromUrl($url)->toMediaCollection(ProductReview::IMAGES_COLLECTION); $review->addMediaFromUrl($url)->toMediaCollection(ProductReview::IMAGES_COLLECTION);
} catch (\Throwable $e) { } catch (Throwable $e) {
Log::warning('JudgeMe import: failed to download review image', [ Log::warning('JudgeMe import: failed to download review image', [
'review_id' => $review->id, 'review_id' => $review->id,
'url' => $url, 'url' => $url,
@@ -2,6 +2,8 @@
namespace Modules\Core\MigrateImport\Shopify; namespace Modules\Core\MigrateImport\Shopify;
use RuntimeException;
class ShopifyCsvReader class ShopifyCsvReader
{ {
/** /**
@@ -12,7 +14,7 @@ class ShopifyCsvReader
$handle = fopen($csvPath, 'r'); $handle = fopen($csvPath, 'r');
if ($handle === false) { if ($handle === false) {
throw new \RuntimeException("Could not open CSV file: {$csvPath}"); throw new RuntimeException("Could not open CSV file: {$csvPath}");
} }
$headers = fgetcsv($handle); $headers = fgetcsv($handle);
@@ -2,6 +2,8 @@
namespace Modules\Core\MigrateImport\Shopify; namespace Modules\Core\MigrateImport\Shopify;
use Lunar\Models\TaxClass;
use Lunar\Models\ProductOption;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Lunar\Models\Collection; use Lunar\Models\Collection;
use Lunar\Models\CollectionGroup; use Lunar\Models\CollectionGroup;
@@ -120,7 +122,7 @@ class ShopifyExportImporter implements Importer
} }
/** /**
* @return array<int, \Lunar\Models\ProductOption> * @return array<int, ProductOption>
*/ */
private function attachOptions(Product $product, array $row): array private function attachOptions(Product $product, array $row): array
{ {
@@ -146,7 +148,7 @@ class ShopifyExportImporter implements Importer
string $handle, string $handle,
int $index, int $index,
array $row, array $row,
\Lunar\Models\TaxClass $taxClass, TaxClass $taxClass,
Currency $currency, Currency $currency,
array $options, array $options,
): void { ): void {
+2 -1
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Notification; namespace Modules\Core\Notification;
use Throwable;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
class NotificationRegistry class NotificationRegistry
@@ -44,7 +45,7 @@ class NotificationRegistry
$notification->delay($event->delaySeconds); $notification->delay($event->delaySeconds);
} }
$notification->notifiable()->notify($notification); $notification->notifiable()->notify($notification);
} catch (\Throwable $e) { } catch (Throwable $e) {
report($e); report($e);
} }
}); });
+6 -3
View File
@@ -2,6 +2,9 @@
namespace Modules\Core\Option; namespace Modules\Core\Option;
use InvalidArgumentException;
use Exception;
use RuntimeException;
use Traversable; use Traversable;
/** /**
@@ -39,7 +42,7 @@ final class LazyOption extends Option
public function __construct($callback, array $arguments = []) public function __construct($callback, array $arguments = [])
{ {
if (!is_callable($callback)) { if (!is_callable($callback)) {
throw new \InvalidArgumentException("Invalid callback given"); throw new InvalidArgumentException("Invalid callback given");
} }
$this->callback = $callback; $this->callback = $callback;
@@ -71,7 +74,7 @@ final class LazyOption extends Option
return $this->option()->getOrCall($callable); return $this->option()->getOrCall($callable);
} }
public function getOrThrow(\Exception $ex) public function getOrThrow(Exception $ex)
{ {
return $this->option()->getOrThrow($ex); return $this->option()->getOrThrow($ex);
} }
@@ -146,7 +149,7 @@ final class LazyOption extends Option
if ($option instanceof Option) { if ($option instanceof Option) {
$this->option = $option; $this->option = $option;
} else { } else {
throw new \RuntimeException( throw new RuntimeException(
sprintf("Expected instance of %s", Option::class), sprintf("Expected instance of %s", Option::class),
); );
} }
+4 -2
View File
@@ -2,6 +2,8 @@
namespace Modules\Core\Option; namespace Modules\Core\Option;
use RuntimeException;
use Exception;
use EmptyIterator; use EmptyIterator;
/** /**
@@ -24,7 +26,7 @@ final class None extends Option
public function get() public function get()
{ {
throw new \RuntimeException("None has no value."); throw new RuntimeException("None has no value.");
} }
public function getOrCall($callable) public function getOrCall($callable)
@@ -37,7 +39,7 @@ final class None extends Option
return $default; return $default;
} }
public function getOrThrow(\Exception $ex) public function getOrThrow(Exception $ex)
{ {
throw $ex; throw $ex;
} }
+2 -1
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Option; namespace Modules\Core\Option;
use Exception;
use ArrayAccess; use ArrayAccess;
use IteratorAggregate; use IteratorAggregate;
@@ -164,7 +165,7 @@ abstract class Option implements IteratorAggregate
abstract public function getOrCall($callable); abstract public function getOrCall($callable);
/** @return T */ /** @return T */
abstract public function getOrThrow(\Exception $ex); abstract public function getOrThrow(Exception $ex);
abstract public function isEmpty(): bool; abstract public function isEmpty(): bool;
+3 -2
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Option; namespace Modules\Core\Option;
use RuntimeException;
use ArrayIterator; use ArrayIterator;
use Exception; use Exception;
@@ -56,7 +57,7 @@ final class Some extends Option
return $this->value; return $this->value;
} }
public function getOrThrow(\Exception $ex) public function getOrThrow(Exception $ex)
{ {
return $this->value; return $this->value;
} }
@@ -88,7 +89,7 @@ final class Some extends Option
/** @var mixed */ /** @var mixed */
$rs = $callable($this->value); $rs = $callable($this->value);
if (!$rs instanceof Option) { if (!$rs instanceof Option) {
throw new \RuntimeException( throw new RuntimeException(
"Callables passed to flatMap() must return an Option. Maybe you should use map() instead?", "Callables passed to flatMap() must return an Option. Maybe you should use map() instead?",
); );
} }
+2 -1
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Payment\Drivers; namespace Modules\Core\Payment\Drivers;
use Lunar\Exceptions\FingerprintMismatchException;
use Lunar\Exceptions\Carts\CartException; use Lunar\Exceptions\Carts\CartException;
use Lunar\Exceptions\DisallowMultipleCartOrdersException; use Lunar\Exceptions\DisallowMultipleCartOrdersException;
use Lunar\Models\Cart; use Lunar\Models\Cart;
@@ -39,7 +40,7 @@ class StripePaymentDriver implements PaymentDriver
* payment intent (wrong intent id, already processed, order already * payment intent (wrong intent id, already processed, order already
* placed, or the gateway call itself fails) — nothing here should be * placed, or the gateway call itself fails) — nothing here should be
* treated as "place the order anyway." * treated as "place the order anyway."
* @throws \Lunar\Exceptions\FingerprintMismatchException * @throws FingerprintMismatchException
* @throws CartException * @throws CartException
*/ */
public function confirm(Cart $cart, string $fingerprint, array $data): Order public function confirm(Cart $cart, string $fingerprint, array $data): Order
+10 -9
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Modules\Core\ResultType; namespace Modules\Core\ResultType;
use Modules\Core\Option\Option;
use Modules\Core\Option\None; use Modules\Core\Option\None;
use Modules\Core\Option\Some; use Modules\Core\Option\Some;
@@ -11,7 +12,7 @@ use Modules\Core\Option\Some;
* @template T * @template T
* @template E * @template E
* *
* @extends \Modules\Core\ResultType\Result<T,E> * @extends Result<T, E>
*/ */
final class Error extends Result final class Error extends Result
{ {
@@ -39,7 +40,7 @@ final class Error extends Result
* *
* @param F $value * @param F $value
* *
* @return \Modules\Core\ResultType\Result<T,F> * @return Result<T, F>
*/ */
public static function create($value): Error public static function create($value): Error
{ {
@@ -49,7 +50,7 @@ final class Error extends Result
/** /**
* Get the success option value. * Get the success option value.
* *
* @return \Modules\Core\Option\Option<T> * @return Option<T>
*/ */
public function success() public function success()
{ {
@@ -63,7 +64,7 @@ final class Error extends Result
* *
* @param callable(T):S $f * @param callable(T):S $f
* *
* @return \Modules\Core\ResultType\Result<S,E> * @return Result<S, E>
*/ */
public function map(callable $f): Result public function map(callable $f): Result
{ {
@@ -76,20 +77,20 @@ final class Error extends Result
* @template S * @template S
* @template F * @template F
* *
* @param callable(T):\Modules\Core\ResultType\Result<S,F> $f * @param callable(T):Result<S, F> $f
* *
* @return \Modules\Core\ResultType\Result<S,F> * @return Result<S, F>
*/ */
public function flatMap(callable $f): Result public function flatMap(callable $f): Result
{ {
/** @var \Modules\Core\ResultType\Result<S,F> */ /** @var Result<S, F> */
return self::create($this->value); return self::create($this->value);
} }
/** /**
* Get the error option value. * Get the error option value.
* *
* @return \Modules\Core\Option\Option<E> * @return Option<E>
*/ */
public function error(): Some public function error(): Some
{ {
@@ -103,7 +104,7 @@ final class Error extends Result
* *
* @param callable(E):F $f * @param callable(E):F $f
* *
* @return \Modules\Core\ResultType\Result<T,F> * @return Result<T, F>
*/ */
public function mapError(callable $f): Result public function mapError(callable $f): Result
{ {
+8 -6
View File
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Modules\Core\ResultType; namespace Modules\Core\ResultType;
use Modules\Core\Option\Option;
/** /**
* @template T * @template T
* @template E * @template E
@@ -13,7 +15,7 @@ abstract class Result
/** /**
* Get the success option value. * Get the success option value.
* *
* @return \Modules\Core\Option\Option<T> * @return Option<T>
*/ */
abstract public function success(); abstract public function success();
@@ -24,7 +26,7 @@ abstract class Result
* *
* @param callable(T):S $f * @param callable(T):S $f
* *
* @return \Modules\Core\ResultType\Result<S,E> * @return Result<S, E>
*/ */
abstract public function map(callable $f); abstract public function map(callable $f);
@@ -34,16 +36,16 @@ abstract class Result
* @template S * @template S
* @template F * @template F
* *
* @param callable(T):\Modules\Core\ResultType\Result<S,F> $f * @param callable(T):Result<S, F> $f
* *
* @return \Modules\Core\ResultType\Result<S,F> * @return Result<S, F>
*/ */
abstract public function flatMap(callable $f); abstract public function flatMap(callable $f);
/** /**
* Get the error option value. * Get the error option value.
* *
* @return \Modules\Core\Option\Option<E> * @return Option<E>
*/ */
abstract public function error(); abstract public function error();
@@ -54,7 +56,7 @@ abstract class Result
* *
* @param callable(E):F $f * @param callable(E):F $f
* *
* @return \Modules\Core\ResultType\Result<T,F> * @return Result<T, F>
*/ */
abstract public function mapError(callable $f); abstract public function mapError(callable $f);
} }
+9 -8
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Modules\Core\ResultType; namespace Modules\Core\ResultType;
use Modules\Core\Option\Option;
use Modules\Core\Option\None; use Modules\Core\Option\None;
use Modules\Core\Option\Some; use Modules\Core\Option\Some;
@@ -11,7 +12,7 @@ use Modules\Core\Option\Some;
* @template T * @template T
* @template E * @template E
* *
* @extends \Modules\Core\ResultType\Result<T,E> * @extends Result<T, E>
*/ */
final class Success extends Result final class Success extends Result
{ {
@@ -39,7 +40,7 @@ final class Success extends Result
* *
* @param S $value * @param S $value
* *
* @return \Modules\Core\ResultType\Result<S,E> * @return Result<S, E>
*/ */
public static function create($value): Success public static function create($value): Success
{ {
@@ -49,7 +50,7 @@ final class Success extends Result
/** /**
* Get the success option value. * Get the success option value.
* *
* @return \Modules\Core\Option\Option<T> * @return Option<T>
*/ */
public function success(): Some public function success(): Some
{ {
@@ -63,7 +64,7 @@ final class Success extends Result
* *
* @param callable(T):S $f * @param callable(T):S $f
* *
* @return \Modules\Core\ResultType\Result<S,E> * @return Result<S, E>
*/ */
public function map(callable $f): Result public function map(callable $f): Result
{ {
@@ -76,9 +77,9 @@ final class Success extends Result
* @template S * @template S
* @template F * @template F
* *
* @param callable(T):\Modules\Core\ResultType\Result<S,F> $f * @param callable(T):Result<S, F> $f
* *
* @return \Modules\Core\ResultType\Result<S,F> * @return Result<S, F>
*/ */
public function flatMap(callable $f) public function flatMap(callable $f)
{ {
@@ -88,7 +89,7 @@ final class Success extends Result
/** /**
* Get the error option value. * Get the error option value.
* *
* @return \Modules\Core\Option\Option<E> * @return Option<E>
*/ */
public function error() public function error()
{ {
@@ -102,7 +103,7 @@ final class Success extends Result
* *
* @param callable(E):F $f * @param callable(E):F $f
* *
* @return \Modules\Core\ResultType\Result<T,F> * @return Result<T, F>
*/ */
public function mapError(callable $f): Result public function mapError(callable $f): Result
{ {
@@ -2,15 +2,15 @@
namespace Modules\Core\Review\Filament\Pages; namespace Modules\Core\Review\Filament\Pages;
use Filament\Forms\Components\Group; use Filament\Schemas\Schema;
use Filament\Schemas\Components\Group;
use Filament\Actions\ViewAction;
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Forms\Components\Placeholder; use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Textarea; use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput; use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\DeleteBulkAction;
use Filament\Tables\Actions\ViewAction;
use Filament\Tables\Columns\TextColumn; use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table; use Filament\Tables\Table;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
@@ -40,10 +40,10 @@ class ManageProductReviews extends BaseManageRelatedRecords
return 'Reviews'; return 'Reviews';
} }
public function form(Form $form): Form public function form(Schema $schema): Schema
{ {
return $form return $schema
->schema([ ->components([
TextInput::make('rating') TextInput::make('rating')
->label('Rating') ->label('Rating')
->disabled(), ->disabled(),
@@ -127,12 +127,12 @@ class ManageProductReviews extends BaseManageRelatedRecords
->filters([ ->filters([
// //
]) ])
->actions([ ->recordActions([
ViewAction::make(), ViewAction::make(),
Action::make('reply') Action::make('reply')
->label(fn (ProductReview $record) => $record->reply ? 'Edit reply' : 'Reply') ->label(fn (ProductReview $record) => $record->reply ? 'Edit reply' : 'Reply')
->icon('heroicon-o-chat-bubble-left-right') ->icon('heroicon-o-chat-bubble-left-right')
->form([ ->schema([
Textarea::make('reply') Textarea::make('reply')
->label('Reply') ->label('Reply')
->required(), ->required(),
@@ -146,7 +146,7 @@ class ManageProductReviews extends BaseManageRelatedRecords
}), }),
DeleteAction::make(), DeleteAction::make(),
]) ])
->bulkActions([ ->toolbarActions([
DeleteBulkAction::make(), DeleteBulkAction::make(),
]); ]);
} }
@@ -2,6 +2,7 @@
namespace Modules\Core\Shipping\Carriers\Acs; namespace Modules\Core\Shipping\Carriers\Acs;
use RuntimeException;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Lunar\Models\Order; use Lunar\Models\Order;
@@ -88,7 +89,7 @@ class AcsFulfillmentService implements CarrierFulfillmentInterface, SupportsMani
public function cancelShipment(Shipment $shipment): void public function cancelShipment(Shipment $shipment): void
{ {
if ($shipment->manifest_reference) { if ($shipment->manifest_reference) {
throw new \RuntimeException('Cannot cancel a shipment already included in an issued manifest.'); throw new RuntimeException('Cannot cancel a shipment already included in an issued manifest.');
} }
$this->client->call('ACS_Delete_Voucher', [ $this->client->call('ACS_Delete_Voucher', [
+2 -1
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Shipping\Concerns; namespace Modules\Core\Shipping\Concerns;
use Closure;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Lunar\DataTypes\ShippingOption; use Lunar\DataTypes\ShippingOption;
use Lunar\Models\Cart; use Lunar\Models\Cart;
@@ -27,7 +28,7 @@ use Lunar\Shipping\Models\ShippingRate;
*/ */
trait CachesLivePricing trait CachesLivePricing
{ {
private function cached(ShippingRate $shippingRate, Cart $cart, \Closure $resolve): ?ShippingOption private function cached(ShippingRate $shippingRate, Cart $cart, Closure $resolve): ?ShippingOption
{ {
return Cache::remember( return Cache::remember(
"shipping.live_price.{$shippingRate->id}.{$cart->id}", "shipping.live_price.{$shippingRate->id}.{$cart->id}",
+14 -9
View File
@@ -2,6 +2,11 @@
namespace Modules\Core\Shipping\Extensions; namespace Modules\Core\Shipping\Extensions;
use Filament\Actions\Action;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Closure;
use Throwable;
use Filament\Actions; use Filament\Actions;
use Filament\Forms; use Filament\Forms;
use Filament\Notifications\Notification; use Filament\Notifications\Notification;
@@ -20,28 +25,28 @@ class OrderViewExtension extends ViewPageExtension
return $actions; return $actions;
} }
private function createShipmentAction(): Actions\Action private function createShipmentAction(): Action
{ {
return Actions\Action::make('create_shipment') return Action::make('create_shipment')
->label('Create Shipment') ->label('Create Shipment')
->icon('heroicon-o-truck') ->icon('heroicon-o-truck')
->modalSubmitActionLabel('Create Shipment') ->modalSubmitActionLabel('Create Shipment')
->form([ ->schema([
Forms\Components\TextInput::make('weight') TextInput::make('weight')
->label('Package weight (kg)') ->label('Package weight (kg)')
->numeric() ->numeric()
->minValue(0) ->minValue(0)
->helperText('Leave blank to use the carrier\'s default.'), ->helperText('Leave blank to use the carrier\'s default.'),
Forms\Components\TextInput::make('destination_location_id') TextInput::make('destination_location_id')
->label('Box Now locker ID') ->label('Box Now locker ID')
->helperText('Only required for Box Now shipments.') ->helperText('Only required for Box Now shipments.')
->default(fn (Order $record) => $record->shippingAddress?->meta['box_now_locker']['locationId'] ?? null), ->default(fn (Order $record) => $record->shippingAddress?->meta['box_now_locker']['locationId'] ?? null),
Forms\Components\Toggle::make('confirm') Toggle::make('confirm')
->label('Confirm') ->label('Confirm')
->helperText('This will create a real shipment with the carrier.') ->helperText('This will create a real shipment with the carrier.')
->rules([ ->rules([
function () { function () {
return function (string $attribute, $value, \Closure $fail) { return function (string $attribute, $value, Closure $fail) {
if ($value !== true) { if ($value !== true) {
$fail('Please confirm before creating the shipment.'); $fail('Please confirm before creating the shipment.');
} }
@@ -49,7 +54,7 @@ class OrderViewExtension extends ViewPageExtension
}, },
]), ]),
]) ])
->action(function (Order $record, array $data, Actions\Action $action) { ->action(function (Order $record, array $data, Action $action) {
$service = $this->resolveFulfillmentService($record); $service = $this->resolveFulfillmentService($record);
if (! $service) { if (! $service) {
@@ -70,7 +75,7 @@ class OrderViewExtension extends ViewPageExtension
try { try {
$service->createShipment($record, $request); $service->createShipment($record, $request);
} catch (\Throwable $e) { } catch (Throwable $e) {
report($e); report($e);
Notification::make() Notification::make()
@@ -2,8 +2,9 @@
namespace Modules\Core\Shipping\Extensions; namespace Modules\Core\Shipping\Extensions;
use Filament\Actions\CreateAction;
use Filament\Schemas\Components\Group;
use Filament\Actions; use Filament\Actions;
use Filament\Forms\Components\Group;
use Filament\Forms\Components\Select; use Filament\Forms\Components\Select;
use Lunar\Admin\Support\Extending\BaseExtension; use Lunar\Admin\Support\Extending\BaseExtension;
use Lunar\Shipping\Facades\Shipping; use Lunar\Shipping\Facades\Shipping;
@@ -22,8 +23,8 @@ class ShippingMethodListExtension extends BaseExtension
public function headerActions(array $actions): array public function headerActions(array $actions): array
{ {
foreach ($actions as $action) { foreach ($actions as $action) {
if ($action instanceof Actions\CreateAction) { if ($action instanceof CreateAction) {
$action->form([ $action->schema([
ShippingMethodResource::getNameFormComponent(), ShippingMethodResource::getNameFormComponent(),
Group::make([ Group::make([
ShippingMethodResource::getCodeFormComponent(), ShippingMethodResource::getCodeFormComponent(),
@@ -2,11 +2,12 @@
namespace Modules\Core\Shipping\Extensions; namespace Modules\Core\Shipping\Extensions;
use Filament\Forms\Components\Component; use Filament\Schemas\Schema;
use Filament\Forms\Components\Concerns\HasChildComponents; use Filament\Schemas\Components\Component;
use Filament\Schemas\Components\Concerns\HasChildComponents;
use Filament\Schemas\Components\Utilities\Get;
use InvalidArgumentException;
use Filament\Forms\Components\Select; use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Tables\Columns\TextColumn; use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table; use Filament\Tables\Table;
use Lunar\Admin\Support\Extending\ResourceExtension; use Lunar\Admin\Support\Extending\ResourceExtension;
@@ -15,11 +16,11 @@ use Modules\Core\Shipping\Contracts\SupportsLivePricing;
class ShippingMethodResourceExtension extends ResourceExtension class ShippingMethodResourceExtension extends ResourceExtension
{ {
public function extendForm(Form $form): Form public function extendForm(Schema $schema): Schema
{ {
return $form->schema( return $schema->components(
$this->replaceChargeByField( $this->replaceChargeByField(
$this->replaceDriverField($form->getComponents()) $this->replaceDriverField($schema->getComponents())
) )
); );
} }
@@ -83,7 +84,7 @@ class ShippingMethodResourceExtension extends ResourceExtension
try { try {
return Shipping::driver($driver) instanceof SupportsLivePricing; return Shipping::driver($driver) instanceof SupportsLivePricing;
} catch (\InvalidArgumentException) { } catch (InvalidArgumentException) {
return false; return false;
} }
} }
@@ -120,7 +121,7 @@ class ShippingMethodResourceExtension extends ResourceExtension
* Select (nested inside Section > Group) with one listing every * Select (nested inside Section > Group) with one listing every
* registered driver, built-in or custom. * registered driver, built-in or custom.
* *
* @param array<Component> $components * @param array<Component> $components
* @return array<Component> * @return array<Component>
*/ */
private function replaceDriverField(array $components): array private function replaceDriverField(array $components): array
@@ -2,10 +2,10 @@
namespace Modules\Core\Shipping\Filament\Pages; namespace Modules\Core\Shipping\Filament\Pages;
use Filament\Actions\Action;
use Filament\Actions\BulkAction;
use Filament\Notifications\Notification; use Filament\Notifications\Notification;
use Filament\Pages\Page; use Filament\Pages\Page;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\BulkAction;
use Filament\Tables\Columns\TextColumn; use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable; use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable; use Filament\Tables\Contracts\HasTable;
@@ -21,7 +21,7 @@ class ManagePickupManifests extends Page implements HasTable
{ {
use InteractsWithTable; use InteractsWithTable;
protected static ?string $navigationIcon = 'heroicon-o-truck'; protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-truck';
protected static ?string $navigationLabel = 'Pickup Manifests'; protected static ?string $navigationLabel = 'Pickup Manifests';
@@ -38,11 +38,11 @@ class ManagePickupManifests extends Page implements HasTable
* OrderResource uses 1) so this page never competes to be first even as * OrderResource uses 1) so this page never competes to be first even as
* more Sales-group items are added later. * more Sales-group items are added later.
*/ */
protected static ?string $navigationGroup = 'Sales'; protected static string | \UnitEnum | null $navigationGroup = 'Sales';
protected static ?int $navigationSort = 100; protected static ?int $navigationSort = 100;
protected static string $view = 'core::shipping.filament.pages.manage-pickup-manifests'; protected string $view = 'core::shipping.filament.pages.manage-pickup-manifests';
public function table(Table $table): Table public function table(Table $table): Table
{ {
@@ -54,13 +54,13 @@ class ManagePickupManifests extends Page implements HasTable
TextColumn::make('order.reference')->label('Order'), TextColumn::make('order.reference')->label('Order'),
TextColumn::make('label_printed_at')->label('Printed')->dateTime()->placeholder('Not printed'), TextColumn::make('label_printed_at')->label('Printed')->dateTime()->placeholder('Not printed'),
]) ])
->actions([ ->recordActions([
Action::make('print') Action::make('print')
->label('Print') ->label('Print')
->icon('heroicon-o-printer') ->icon('heroicon-o-printer')
->action(fn (Shipment $record) => $this->printShipment($record)), ->action(fn (Shipment $record) => $this->printShipment($record)),
]) ])
->bulkActions([ ->toolbarActions([
BulkAction::make('print_selected') BulkAction::make('print_selected')
->label('Print selected') ->label('Print selected')
->icon('heroicon-o-printer') ->icon('heroicon-o-printer')
@@ -2,9 +2,9 @@
namespace Modules\Core\Shipping\Filament\Pages; namespace Modules\Core\Shipping\Filament\Pages;
use Filament\Schemas\Schema;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Forms\Components\TextInput; use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Tables\Columns\TextColumn; use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table; use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@@ -36,12 +36,12 @@ use Lunar\Shipping\Models\ShippingRate;
*/ */
class ManageShippingRates extends BaseManageShippingRates class ManageShippingRates extends BaseManageShippingRates
{ {
public function form(Form $form): Form public function form(Schema $schema): Schema
{ {
$form = parent::form($form); $schema = parent::form($schema);
return $form->schema( return $schema->components(
$this->labelPriceFieldsAsFallbackWhenLive($form->getComponents()) $this->labelPriceFieldsAsFallbackWhenLive($schema->getComponents())
); );
} }