Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions admin/app/Enums/ShippingMethodForEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace App\Enums;

use App\Traits\HasOptions;

enum ShippingMethodForEnum: int
{
use HasOptions;

case CUSTOMER = 10;
case PARTNER = 20;
case EMPLOYEE = 30;

public function label(): string
{
return match ($this) {
self::CUSTOMER => 'Customer',
self::PARTNER => 'Partner',
self::EMPLOYEE => 'Employee',
};
}

public function color(): string
{
return match ($this) {
self::CUSTOMER => 'success',
self::PARTNER => 'info',
self::EMPLOYEE => 'warning',
};
}
}
160 changes: 160 additions & 0 deletions admin/app/Filament/Resources/ShippingCityResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Resources\ShippingCityResource\Pages\CreateShippingCity;
use App\Filament\Resources\ShippingCityResource\Pages\EditShippingCity;
use App\Filament\Resources\ShippingCityResource\Pages\ListShippingCities;
use App\Models\ShippingCity;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;

class ShippingCityResource extends Resource
{
protected static ?string $model = ShippingCity::class;

protected static string | \UnitEnum | null $navigationGroup = 'Logistics';

protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-map-pin';

protected static ?int $navigationSort = 3;

public static function form(Schema $schema): Schema
{
return $schema
->components([
Select::make('shipping_method_id')
->relationship('shippingMethod', 'name')
->required()
->searchable()
->preload()
->native(false)
->columnSpanFull()
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('The shipping method this city config applies to.'),
Select::make('province_id')
->relationship('province', 'name')
->searchable()
->preload()
->nullable()
->native(false)
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('Set a province for a province-wide rule. Leave empty if targeting a specific city.'),
Select::make('city_id')
->relationship('city', 'name')
->searchable()
->preload()
->nullable()
->native(false)
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('Set a city for city-specific rules. City rules take priority over province rules. At least one of city or province must be set.'),
TextInput::make('amount')
->numeric()
->nullable()
->prefix('تومان')
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('Shipping cost for this location. Leave empty for postpaid. Set 0 for free shipping.'),
Toggle::make('pay_on_delivery')
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('When on, the customer pays at delivery — no online payment required.'),
TextInput::make('sending_days')
->nullable()
->placeholder('e.g. 1,2,3,4,5')
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('Days this method ships for this location (comma-separated day numbers). Leave empty for every day.'),
TextInput::make('delay')
->numeric()
->nullable()
->suffix('days')
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('Extra delivery delay in days for this location (e.g. 1 for next-day).'),
Textarea::make('description')
->nullable()
->rows(2)
->columnSpanFull()
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('Human-readable delivery details shown to the customer (e.g. "Delivered within 72 hours").'),
DateTimePicker::make('disable_from')
->nullable()
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('Start of a period when this method is unavailable in this location.'),
DateTimePicker::make('disable_to')
->nullable()
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('End of the unavailability period.'),
Toggle::make('status')
->default(true)
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('When off, this entry is ignored at checkout.'),
]);
}

public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('shippingMethod.name')
->label('Method')
->searchable()
->sortable(),
TextColumn::make('province.name')
->label('Province')
->placeholder('—'),
TextColumn::make('city.name')
->label('City')
->placeholder('—')
->searchable(),
TextColumn::make('amount')
->money()
->placeholder('Postpaid'),
IconColumn::make('pay_on_delivery')
->boolean(),
TextColumn::make('delay')
->suffix(' d')
->placeholder('—'),
IconColumn::make('status')
->boolean(),
TextColumn::make('created_at')
->dateTime()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->recordActions([
EditAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}

public static function getRelations(): array
{
return [];
}

public static function getPages(): array
{
return [
'index' => ListShippingCities::route('/'),
'create' => CreateShippingCity::route('/create'),
'edit' => EditShippingCity::route('/{record}/edit'),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace App\Filament\Resources\ShippingCityResource\Pages;

use App\Filament\Resources\ShippingCityResource;
use Filament\Resources\Pages\CreateRecord;

class CreateShippingCity extends CreateRecord
{
protected static string $resource = ShippingCityResource::class;

protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Filament\Resources\ShippingCityResource\Pages;

use App\Filament\Resources\ShippingCityResource;
use Filament\Actions\DeleteAction;
use Filament\Resources\Pages\EditRecord;

class EditShippingCity extends EditRecord
{
protected static string $resource = ShippingCityResource::class;

protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}

protected function getHeaderActions(): array
{
return [
DeleteAction::make(),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace App\Filament\Resources\ShippingCityResource\Pages;

use App\Filament\Resources\ShippingCityResource;
use Filament\Actions\CreateAction;
use Filament\Resources\Pages\ListRecords;

class ListShippingCities extends ListRecords
{
protected static string $resource = ShippingCityResource::class;

protected ?string $subheading = 'Per-city (or per-province) shipping availability, cost overrides, and delivery schedules for each shipping method.';

protected function getHeaderActions(): array
{
return [
CreateAction::make(),
];
}
}
89 changes: 89 additions & 0 deletions admin/app/Filament/Resources/ShippingLineResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Resources\ShippingLineResource\Pages\CreateShippingLine;
use App\Filament\Resources\ShippingLineResource\Pages\EditShippingLine;
use App\Filament\Resources\ShippingLineResource\Pages\ListShippingLines;
use App\Models\ShippingLine;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;

class ShippingLineResource extends Resource
{
protected static ?string $model = ShippingLine::class;

protected static string | \UnitEnum | null $navigationGroup = 'Logistics';

protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-truck';

public static function form(Schema $schema): Schema
{
return $schema
->components([
TextInput::make('name')
->required()
->maxLength(255)
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('The shipping carrier or line name (e.g. Post, Express, Same-day Courier).'),
TextInput::make('cost')
->required()
->numeric()
->prefix('تومان')
->hintIcon('heroicon-o-information-circle')
->hintIconTooltip('Base shipping cost for this line. Use 0 for free shipping.'),
]);
}

public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('name')
->searchable()
->sortable(),
TextColumn::make('cost')
->money()
->sortable(),
TextColumn::make('created_at')
->dateTime()
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('updated_at')
->dateTime()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->recordActions([
EditAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}

public static function getRelations(): array
{
return [];
}

public static function getPages(): array
{
return [
'index' => ListShippingLines::route('/'),
'create' => CreateShippingLine::route('/create'),
'edit' => EditShippingLine::route('/{record}/edit'),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace App\Filament\Resources\ShippingLineResource\Pages;

use App\Filament\Resources\ShippingLineResource;
use Filament\Resources\Pages\CreateRecord;

class CreateShippingLine extends CreateRecord
{
protected static string $resource = ShippingLineResource::class;

protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
}
Loading
Loading