您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

DiscountResource.php 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. namespace App\Filament\Company\Resources\Setting;
  3. use App\Enums\{DiscountComputation, DiscountScope, DiscountType};
  4. use App\Filament\Company\Resources\Setting\DiscountResource\Pages;
  5. use App\Models\Setting\Discount;
  6. use Closure;
  7. use Filament\Forms\Form;
  8. use Filament\Resources\Resource;
  9. use Filament\Tables\Table;
  10. use Filament\{Forms, Tables};
  11. use Wallo\FilamentSelectify\Components\ToggleButton;
  12. class DiscountResource extends Resource
  13. {
  14. protected static ?string $model = Discount::class;
  15. protected static ?string $navigationIcon = 'heroicon-o-tag';
  16. protected static ?string $navigationGroup = 'Settings';
  17. protected static ?string $slug = 'settings/discounts';
  18. public static function form(Form $form): Form
  19. {
  20. return $form
  21. ->schema([
  22. Forms\Components\Section::make('General')
  23. ->schema([
  24. Forms\Components\TextInput::make('name')
  25. ->label('Name')
  26. ->autofocus()
  27. ->required()
  28. ->maxLength(255)
  29. ->rule(static function (Forms\Get $get, Forms\Components\Component $component): Closure {
  30. return static function (string $attribute, $value, Closure $fail) use ($get, $component) {
  31. $existingCategory = Discount::where('company_id', auth()->user()->currentCompany->id)
  32. ->where('name', $value)
  33. ->where('type', $get('type'))
  34. ->first();
  35. if ($existingCategory && $existingCategory->getKey() !== $component->getRecord()?->getKey()) {
  36. $type = $get('type')->getLabel();
  37. $fail("The {$type} discount \"{$value}\" already exists.");
  38. }
  39. };
  40. }),
  41. Forms\Components\TextInput::make('description')
  42. ->label('Description'),
  43. Forms\Components\Select::make('computation')
  44. ->label('Computation')
  45. ->options(DiscountComputation::class)
  46. ->default(DiscountComputation::Percentage)
  47. ->live()
  48. ->native(false)
  49. ->required(),
  50. Forms\Components\TextInput::make('rate')
  51. ->label('Rate')
  52. ->numeric()
  53. ->suffix(static function (Forms\Get $get) {
  54. $computation = $get('computation');
  55. if ($computation === DiscountComputation::Percentage) {
  56. return '%';
  57. }
  58. return null;
  59. })
  60. ->required(),
  61. Forms\Components\Select::make('type')
  62. ->label('Type')
  63. ->options(DiscountType::class)
  64. ->default(DiscountType::Sales)
  65. ->native(false)
  66. ->required(),
  67. Forms\Components\Select::make('scope')
  68. ->label('Scope')
  69. ->options(DiscountScope::class)
  70. ->native(false),
  71. Forms\Components\DateTimePicker::make('start_date')
  72. ->label('Start Date')
  73. ->native(false)
  74. ->minDate(static function ($context, ?Discount $record = null) {
  75. if ($context === 'create') {
  76. return today()->addDay();
  77. }
  78. return $record?->start_date?->isFuture() ? today()->addDay() : $record?->start_date;
  79. })
  80. ->maxDate(static function (callable $get, ?Discount $record = null) {
  81. $end_date = $get('end_date') ?? $record?->end_date;
  82. return $end_date ?: today()->addYear();
  83. })
  84. ->format('Y-m-d H:i:s')
  85. ->displayFormat('F d, Y H:i')
  86. ->seconds(false)
  87. ->live()
  88. ->disabled(static fn ($context, ?Discount $record = null) => $context === 'edit' && $record?->start_date?->isPast() ?? false)
  89. ->helperText(static fn (Forms\Components\DateTimePicker $component) => $component->isDisabled() ? 'Start date cannot be changed after the discount has begun.' : null),
  90. Forms\Components\DateTimePicker::make('end_date')
  91. ->label('End Date')
  92. ->native(false)
  93. ->live()
  94. ->minDate(static function (callable $get, ?Discount $record = null) {
  95. $start_date = $get('start_date') ?? $record?->start_date;
  96. return $start_date ?: today()->addDay();
  97. })
  98. ->maxDate(today()->addYear())
  99. ->format('Y-m-d H:i:s')
  100. ->displayFormat('F d, Y H:i')
  101. ->seconds(false),
  102. ToggleButton::make('enabled')
  103. ->label('Default'),
  104. ])->columns(),
  105. ]);
  106. }
  107. public static function table(Table $table): Table
  108. {
  109. return $table
  110. ->columns([
  111. Tables\Columns\TextColumn::make('name')
  112. ->label('Name')
  113. ->weight('semibold')
  114. ->icon(static fn (Discount $record) => $record->enabled ? 'heroicon-o-lock-closed' : null)
  115. ->tooltip(static fn (Discount $record) => $record->enabled ? "Default {$record->type->getLabel()} Discount" : null)
  116. ->iconPosition('after')
  117. ->searchable()
  118. ->sortable(),
  119. Tables\Columns\TextColumn::make('computation')
  120. ->label('Computation')
  121. ->searchable()
  122. ->sortable(),
  123. Tables\Columns\TextColumn::make('rate')
  124. ->label('Rate')
  125. ->formatStateUsing(static fn (Discount $record) => $record->rate . ($record->computation === DiscountComputation::Percentage ? '%' : null))
  126. ->searchable()
  127. ->sortable(),
  128. Tables\Columns\TextColumn::make('type')
  129. ->label('Type')
  130. ->badge()
  131. ->searchable()
  132. ->sortable(),
  133. Tables\Columns\TextColumn::make('start_date')
  134. ->label('Start Date')
  135. ->formatStateUsing(static fn (Discount $record) => $record->start_date ? $record->start_date->format('F d, Y H:i') : 'N/A')
  136. ->searchable()
  137. ->sortable(),
  138. Tables\Columns\TextColumn::make('end_date')
  139. ->label('End Date')
  140. ->formatStateUsing(static fn (Discount $record) => $record->end_date ? $record->end_date->format('F d, Y H:i') : 'N/A')
  141. ->color(static fn (Discount $record) => $record->end_date?->isPast() ? 'danger' : null)
  142. ->searchable()
  143. ->sortable(),
  144. ])
  145. ->filters([
  146. //
  147. ])
  148. ->actions([
  149. Tables\Actions\EditAction::make(),
  150. ])
  151. ->bulkActions([
  152. Tables\Actions\BulkActionGroup::make([
  153. Tables\Actions\DeleteBulkAction::make(),
  154. ]),
  155. ])
  156. ->emptyStateActions([
  157. Tables\Actions\CreateAction::make(),
  158. ]);
  159. }
  160. public static function getRelations(): array
  161. {
  162. return [
  163. //
  164. ];
  165. }
  166. public static function getPages(): array
  167. {
  168. return [
  169. 'index' => Pages\ListDiscounts::route('/'),
  170. 'create' => Pages\CreateDiscount::route('/create'),
  171. 'edit' => Pages\EditDiscount::route('/{record}/edit'),
  172. ];
  173. }
  174. }