You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ClientResource.php 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <?php
  2. namespace App\Filament\Company\Resources\Common;
  3. use App\Filament\Company\Resources\Common\ClientResource\Pages;
  4. use App\Filament\Forms\Components\CreateCurrencySelect;
  5. use App\Filament\Forms\Components\CustomSection;
  6. use App\Filament\Forms\Components\PhoneBuilder;
  7. use App\Models\Common\Client;
  8. use Filament\Forms;
  9. use Filament\Forms\Form;
  10. use Filament\Resources\Resource;
  11. use Filament\Tables;
  12. use Filament\Tables\Table;
  13. class ClientResource extends Resource
  14. {
  15. protected static ?string $model = Client::class;
  16. public static function form(Form $form): Form
  17. {
  18. return $form
  19. ->schema([
  20. Forms\Components\Section::make('General Information')
  21. ->schema([
  22. Forms\Components\Group::make()
  23. ->columns()
  24. ->schema([
  25. Forms\Components\TextInput::make('name')
  26. ->label('Client Name')
  27. ->required()
  28. ->maxLength(255),
  29. Forms\Components\TextInput::make('account_number')
  30. ->maxLength(255)
  31. ->columnStart(1),
  32. Forms\Components\TextInput::make('website')
  33. ->maxLength(255),
  34. Forms\Components\Textarea::make('notes')
  35. ->columnSpanFull(),
  36. ]),
  37. CustomSection::make('Primary Contact')
  38. ->relationship('primaryContact')
  39. ->contained(false)
  40. ->schema([
  41. Forms\Components\Hidden::make('is_primary')
  42. ->default(true),
  43. Forms\Components\TextInput::make('first_name')
  44. ->label('First Name')
  45. ->required()
  46. ->maxLength(255),
  47. Forms\Components\TextInput::make('last_name')
  48. ->label('Last Name')
  49. ->required()
  50. ->maxLength(255),
  51. Forms\Components\TextInput::make('email')
  52. ->label('Email')
  53. ->required()
  54. ->email()
  55. ->columnSpanFull()
  56. ->maxLength(255),
  57. PhoneBuilder::make('phones')
  58. ->hiddenLabel()
  59. ->blockLabels(false)
  60. ->default([
  61. ['type' => 'primary'],
  62. ])
  63. ->columnSpanFull()
  64. ->blocks([
  65. Forms\Components\Builder\Block::make('primary')
  66. ->schema([
  67. Forms\Components\TextInput::make('number')
  68. ->label('Phone')
  69. ->required()
  70. ->maxLength(15),
  71. ])->maxItems(1),
  72. Forms\Components\Builder\Block::make('mobile')
  73. ->schema([
  74. Forms\Components\TextInput::make('number')
  75. ->label('Mobile')
  76. ->required()
  77. ->maxLength(15),
  78. ])->maxItems(1),
  79. Forms\Components\Builder\Block::make('toll_free')
  80. ->schema([
  81. Forms\Components\TextInput::make('number')
  82. ->label('Toll Free')
  83. ->required()
  84. ->maxLength(15),
  85. ])->maxItems(1),
  86. Forms\Components\Builder\Block::make('fax')
  87. ->schema([
  88. Forms\Components\TextInput::make('number')
  89. ->label('Fax')
  90. ->live()
  91. ->maxLength(15),
  92. ])->maxItems(1),
  93. ])
  94. ->deletable(fn (PhoneBuilder $builder) => $builder->getItemsCount() > 1)
  95. ->reorderable(false)
  96. ->blockNumbers(false)
  97. ->addActionLabel('Add Phone'),
  98. ])->columns(),
  99. Forms\Components\Repeater::make('secondaryContacts')
  100. ->relationship()
  101. ->hiddenLabel()
  102. ->extraAttributes([
  103. 'class' => 'uncontained',
  104. ])
  105. ->columns()
  106. ->defaultItems(0)
  107. ->maxItems(3)
  108. ->itemLabel(function (Forms\Components\Repeater $component, array $state): ?string {
  109. if ($component->getItemsCount() === 1) {
  110. return 'Secondary Contact';
  111. }
  112. $firstName = $state['first_name'] ?? null;
  113. $lastName = $state['last_name'] ?? null;
  114. if ($firstName && $lastName) {
  115. return "{$firstName} {$lastName}";
  116. }
  117. if ($firstName) {
  118. return $firstName;
  119. }
  120. return 'Secondary Contact';
  121. })
  122. ->addActionLabel('Add Contact')
  123. ->schema([
  124. Forms\Components\TextInput::make('first_name')
  125. ->label('First Name')
  126. ->required()
  127. ->live(onBlur: true)
  128. ->maxLength(255),
  129. Forms\Components\TextInput::make('last_name')
  130. ->label('Last Name')
  131. ->required()
  132. ->live(onBlur: true)
  133. ->maxLength(255),
  134. Forms\Components\TextInput::make('email')
  135. ->label('Email')
  136. ->required()
  137. ->email()
  138. ->maxLength(255),
  139. PhoneBuilder::make('phones')
  140. ->hiddenLabel()
  141. ->blockLabels(false)
  142. ->default([
  143. ['type' => 'primary'],
  144. ])
  145. ->blocks([
  146. Forms\Components\Builder\Block::make('primary')
  147. ->schema([
  148. Forms\Components\TextInput::make('number')
  149. ->label('Phone')
  150. ->required()
  151. ->maxLength(255),
  152. ])->maxItems(1),
  153. ])
  154. ->addable(false)
  155. ->deletable(false)
  156. ->reorderable(false)
  157. ->blockNumbers(false),
  158. ]),
  159. ])->columns(1),
  160. Forms\Components\Section::make('Billing')
  161. ->schema([
  162. CreateCurrencySelect::make('currency_code')
  163. ->relationship('currency', 'name'),
  164. CustomSection::make('Billing Address')
  165. ->relationship('billingAddress')
  166. ->contained(false)
  167. ->schema([
  168. Forms\Components\Hidden::make('type')
  169. ->default('billing'),
  170. Forms\Components\TextInput::make('address_line_1')
  171. ->label('Address Line 1')
  172. ->required()
  173. ->maxLength(255),
  174. Forms\Components\TextInput::make('address_line_2')
  175. ->label('Address Line 2')
  176. ->maxLength(255),
  177. Forms\Components\TextInput::make('city')
  178. ->label('City')
  179. ->required()
  180. ->maxLength(255),
  181. Forms\Components\TextInput::make('state')
  182. ->label('State')
  183. ->required()
  184. ->maxLength(255),
  185. Forms\Components\TextInput::make('postal_code')
  186. ->label('Postal Code / Zip Code')
  187. ->required()
  188. ->maxLength(255),
  189. Forms\Components\TextInput::make('country')
  190. ->label('Country')
  191. ->required()
  192. ->maxLength(255),
  193. ])->columns(),
  194. ])
  195. ->columns(1),
  196. Forms\Components\Section::make('Shipping')
  197. ->relationship('shippingAddress')
  198. ->schema([
  199. Forms\Components\TextInput::make('recipient')
  200. ->label('Recipient')
  201. ->required()
  202. ->maxLength(255),
  203. Forms\Components\Hidden::make('type')
  204. ->default('shipping'),
  205. Forms\Components\TextInput::make('phone')
  206. ->label('Phone')
  207. ->required()
  208. ->maxLength(255),
  209. CustomSection::make('Shipping Address')
  210. ->contained(false)
  211. ->schema([
  212. Forms\Components\TextInput::make('address_line_1')
  213. ->label('Address Line 1')
  214. ->required()
  215. ->maxLength(255),
  216. Forms\Components\TextInput::make('address_line_2')
  217. ->label('Address Line 2')
  218. ->maxLength(255),
  219. Forms\Components\TextInput::make('city')
  220. ->label('City')
  221. ->required()
  222. ->maxLength(255),
  223. Forms\Components\TextInput::make('state')
  224. ->label('State')
  225. ->required()
  226. ->maxLength(255),
  227. Forms\Components\TextInput::make('postal_code')
  228. ->label('Postal Code / Zip Code')
  229. ->required()
  230. ->maxLength(255),
  231. Forms\Components\TextInput::make('country')
  232. ->label('Country')
  233. ->required()
  234. ->maxLength(255),
  235. Forms\Components\Textarea::make('notes')
  236. ->label('Delivery Instructions')
  237. ->maxLength(255)
  238. ->columnSpanFull(),
  239. ])->columns(),
  240. ])->columns(),
  241. ]);
  242. }
  243. public static function table(Table $table): Table
  244. {
  245. return $table
  246. ->columns([
  247. Tables\Columns\TextColumn::make('name')
  248. ->searchable()
  249. ->description(fn (Client $client) => $client->primaryContact->full_name),
  250. Tables\Columns\TextColumn::make('primaryContact.email')
  251. ->label('Email')
  252. ->searchable(),
  253. Tables\Columns\TextColumn::make('primaryContact.phones')
  254. ->label('Phone')
  255. ->state(fn (Client $client) => $client->primaryContact->primary_phone),
  256. ])
  257. ->filters([
  258. //
  259. ])
  260. ->actions([
  261. Tables\Actions\EditAction::make(),
  262. ])
  263. ->bulkActions([
  264. Tables\Actions\BulkActionGroup::make([
  265. Tables\Actions\DeleteBulkAction::make(),
  266. ]),
  267. ]);
  268. }
  269. public static function getRelations(): array
  270. {
  271. return [
  272. //
  273. ];
  274. }
  275. public static function getPages(): array
  276. {
  277. return [
  278. 'index' => Pages\ListClients::route('/'),
  279. 'create' => Pages\CreateClient::route('/create'),
  280. 'edit' => Pages\EditClient::route('/{record}/edit'),
  281. ];
  282. }
  283. }