Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

CustomerResource.php 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. namespace App\Filament\Resources;
  3. use App\Actions\OptionAction\CreateCurrency;
  4. use App\Filament\Resources\CustomerResource\Pages;
  5. use App\Models\Setting\Currency;
  6. use App\Services\CurrencyService;
  7. use Illuminate\Support\Facades\Auth;
  8. use Wallo\FilamentSelectify\Components\ButtonGroup;
  9. use App\Models\Contact;
  10. use Filament\Forms;
  11. use Filament\Resources\Form;
  12. use Filament\Resources\Resource;
  13. use Filament\Resources\Table;
  14. use Filament\Tables;
  15. use Illuminate\Database\Eloquent\Builder;
  16. use Illuminate\Support\Facades\DB;
  17. class CustomerResource extends Resource
  18. {
  19. protected static ?string $model = Contact::class;
  20. protected static ?string $navigationIcon = 'heroicon-o-user-group';
  21. protected static ?string $navigationGroup = 'Sales';
  22. protected static ?string $navigationLabel = 'Customers';
  23. protected static ?string $modelLabel = 'customer';
  24. public static function getEloquentQuery(): Builder
  25. {
  26. return parent::getEloquentQuery()->customer();
  27. }
  28. public static function form(Form $form): Form
  29. {
  30. return $form
  31. ->schema([
  32. Forms\Components\Section::make('General')
  33. ->schema([
  34. Forms\Components\Grid::make(3)
  35. ->schema([
  36. ButtonGroup::make('entity')
  37. ->label('Entity')
  38. ->options([
  39. 'individual' => 'Individual',
  40. 'company' => 'Company',
  41. ])
  42. ->gridDirection('column')
  43. ->default('individual')
  44. ->columnSpan(1),
  45. Forms\Components\Grid::make()
  46. ->schema([
  47. Forms\Components\TextInput::make('name')
  48. ->label('Name')
  49. ->maxLength(100)
  50. ->required(),
  51. Forms\Components\TextInput::make('email')
  52. ->label('Email')
  53. ->email()
  54. ->nullable(),
  55. Forms\Components\TextInput::make('phone')
  56. ->label('Phone')
  57. ->tel()
  58. ->maxLength(20),
  59. Forms\Components\TextInput::make('website')
  60. ->label('Website')
  61. ->maxLength(100)
  62. ->url()
  63. ->nullable(),
  64. Forms\Components\TextInput::make('reference')
  65. ->label('Reference')
  66. ->maxLength(100)
  67. ->columnSpan(2)
  68. ->nullable(),
  69. ])->columnSpan(2),
  70. ]),
  71. ])->columns(),
  72. Forms\Components\Section::make('Billing')
  73. ->schema([
  74. Forms\Components\TextInput::make('tax_number')
  75. ->label('Tax Number')
  76. ->maxLength(100)
  77. ->nullable(),
  78. Forms\Components\Select::make('currency_code')
  79. ->label('Currency')
  80. ->relationship('currency', 'name')
  81. ->preload()
  82. ->default(Currency::getDefaultCurrency())
  83. ->searchable()
  84. ->reactive()
  85. ->required()
  86. ->createOptionForm([
  87. Forms\Components\Select::make('currency.code')
  88. ->label('Code')
  89. ->searchable()
  90. ->options(Currency::getCurrencyCodes())
  91. ->reactive()
  92. ->afterStateUpdated(static function (callable $set, $state) {
  93. if ($state === null) {
  94. return;
  95. }
  96. $code = $state;
  97. $currencyConfig = config("money.{$code}", []);
  98. $currencyService = app(CurrencyService::class);
  99. $defaultCurrency = Currency::getDefaultCurrency();
  100. $rate = 1;
  101. if ($defaultCurrency !== null) {
  102. $rate = $currencyService->getCachedExchangeRate($defaultCurrency, $code);
  103. }
  104. $set('currency.name', $currencyConfig['name'] ?? '');
  105. $set('currency.rate', $rate);
  106. })
  107. ->required(),
  108. Forms\Components\TextInput::make('currency.name')
  109. ->label('Name')
  110. ->maxLength(100)
  111. ->required(),
  112. Forms\Components\TextInput::make('currency.rate')
  113. ->label('Rate')
  114. ->numeric()
  115. ->required(),
  116. ])->createOptionAction(static function (Forms\Components\Actions\Action $action) {
  117. return $action
  118. ->label('Add Currency')
  119. ->modalHeading('Add Currency')
  120. ->modalButton('Add')
  121. ->action(static function (array $data) {
  122. return DB::transaction(static function () use ($data) {
  123. $code = $data['currency']['code'];
  124. $name = $data['currency']['name'];
  125. $rate = $data['currency']['rate'];
  126. return (new CreateCurrency())->create($code, $name, $rate);
  127. });
  128. });
  129. }),
  130. ])->columns(),
  131. Forms\Components\Section::make('Address')
  132. ->schema([
  133. Forms\Components\TextInput::make('address')
  134. ->label('Address')
  135. ->maxLength(100)
  136. ->columnSpanFull()
  137. ->nullable(),
  138. Forms\Components\Select::make('country')
  139. ->label('Country')
  140. ->searchable()
  141. ->reactive()
  142. ->options(Contact::getCountryOptions())
  143. ->nullable(),
  144. Forms\Components\Select::make('doesnt_exist') // TODO: Remove this when we have a better way to handle the searchable select when disabled
  145. ->label('Province/State')
  146. ->disabled()
  147. ->hidden(static fn (callable $get) => $get('country') !== null),
  148. Forms\Components\Select::make('state')
  149. ->label('Province/State')
  150. ->hidden(static fn (callable $get) => $get('country') === null)
  151. ->options(static function (callable $get) {
  152. $country = $get('country');
  153. if (! $country) {
  154. return [];
  155. }
  156. return Contact::getRegionOptions($country);
  157. })
  158. ->searchable()
  159. ->nullable(),
  160. Forms\Components\TextInput::make('city')
  161. ->label('Town/City')
  162. ->maxLength(100)
  163. ->nullable(),
  164. Forms\Components\TextInput::make('zip_code')
  165. ->label('Postal/Zip Code')
  166. ->maxLength(100)
  167. ->nullable(),
  168. ])->columns(),
  169. ]);
  170. }
  171. public static function table(Table $table): Table
  172. {
  173. return $table
  174. ->columns([
  175. Tables\Columns\TextColumn::make('name')
  176. ->label('Name')
  177. ->weight('semibold')
  178. ->description(static fn (Contact $record) => $record->tax_number ?: 'N/A')
  179. ->searchable()
  180. ->sortable(),
  181. Tables\Columns\TextColumn::make('email')
  182. ->label('Email')
  183. ->formatStateUsing(static fn (Contact $record) => $record->email ?: 'N/A')
  184. ->description(static fn (Contact $record) => $record->phone ?: 'N/A')
  185. ->searchable()
  186. ->sortable(),
  187. Tables\Columns\TextColumn::make('country')
  188. ->label('Country')
  189. ->searchable()
  190. ->formatStateUsing(static fn (Contact $record) => $record->country ?: 'N/A')
  191. ->description(static fn (Contact $record) => $record->currency->name ?: 'N/A')
  192. ->sortable(),
  193. ])
  194. ->filters([
  195. //
  196. ])
  197. ->actions([
  198. Tables\Actions\EditAction::make(),
  199. ])
  200. ->bulkActions([
  201. Tables\Actions\DeleteBulkAction::make(),
  202. ]);
  203. }
  204. public static function getSlug(): string
  205. {
  206. return '{company}/sales/customers';
  207. }
  208. public static function getUrl($name = 'index', $params = [], $isAbsolute = true): string
  209. {
  210. $routeBaseName = static::getRouteBaseName();
  211. return route("{$routeBaseName}.{$name}", [
  212. 'company' => Auth::user()->currentCompany,
  213. 'record' => $params['record'] ?? null,
  214. ], $isAbsolute);
  215. }
  216. public static function getRelations(): array
  217. {
  218. return [
  219. //
  220. ];
  221. }
  222. public static function getPages(): array
  223. {
  224. return [
  225. 'index' => Pages\ListCustomers::route('/'),
  226. 'create' => Pages\CreateCustomer::route('/create'),
  227. 'edit' => Pages\EditCustomer::route('/{record}/edit'),
  228. ];
  229. }
  230. }