Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

CompanyProfile.php 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <?php
  2. namespace App\Filament\Company\Pages\Setting;
  3. use App\Enums\EntityType;
  4. use App\Models\Locale\City;
  5. use App\Models\Locale\Country;
  6. use App\Models\Locale\State;
  7. use App\Models\Setting\CompanyProfile as CompanyProfileModel;
  8. use Filament\Actions\Action;
  9. use Filament\Actions\ActionGroup;
  10. use Filament\Facades\Filament;
  11. use Filament\Forms\Components\Component;
  12. use Filament\Forms\Components\FileUpload;
  13. use Filament\Forms\Components\Group;
  14. use Filament\Forms\Components\Section;
  15. use Filament\Forms\Components\Select;
  16. use Filament\Forms\Components\TextInput;
  17. use Filament\Forms\Form;
  18. use Filament\Forms\Get;
  19. use Filament\Forms\Set;
  20. use Filament\Notifications\Notification;
  21. use Filament\Pages\Concerns\InteractsWithFormActions;
  22. use Filament\Pages\Page;
  23. use Filament\Support\Exceptions\Halt;
  24. use Illuminate\Auth\Access\AuthorizationException;
  25. use Illuminate\Contracts\Support\Htmlable;
  26. use Illuminate\Database\Eloquent\Model;
  27. use Illuminate\Support\Facades\Auth;
  28. use Livewire\Attributes\Locked;
  29. use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
  30. use function Filament\authorize;
  31. /**
  32. * @property Form $form
  33. */
  34. class CompanyProfile extends Page
  35. {
  36. use InteractsWithFormActions;
  37. protected static ?string $navigationIcon = 'heroicon-o-building-office-2';
  38. protected static ?string $title = 'Company Profile';
  39. protected static ?string $navigationGroup = 'Settings';
  40. protected static ?string $slug = 'settings/company-profile';
  41. protected static string $view = 'filament.company.pages.setting.company-profile';
  42. public ?array $data = [];
  43. #[Locked]
  44. public ?CompanyProfileModel $record = null;
  45. public function getTitle(): string | Htmlable
  46. {
  47. return translate(static::$title);
  48. }
  49. public static function getNavigationLabel(): string
  50. {
  51. return translate(static::$title);
  52. }
  53. public static function getNavigationParentItem(): ?string
  54. {
  55. if (Filament::hasTopNavigation()) {
  56. return translate('Company');
  57. }
  58. return null;
  59. }
  60. public function mount(): void
  61. {
  62. $this->record = CompanyProfileModel::firstOrNew([
  63. 'company_id' => auth()->user()->currentCompany->id,
  64. ]);
  65. abort_unless(static::canView($this->record), 404);
  66. $this->fillForm();
  67. }
  68. public function fillForm(): void
  69. {
  70. $data = $this->record->attributesToArray();
  71. $this->form->fill($data);
  72. }
  73. public function save(): void
  74. {
  75. try {
  76. $data = $this->form->getState();
  77. $this->handleRecordUpdate($this->record, $data);
  78. } catch (Halt $exception) {
  79. return;
  80. }
  81. $this->getSavedNotification()->send();
  82. }
  83. protected function getSavedNotification(): Notification
  84. {
  85. return Notification::make()
  86. ->success()
  87. ->title(__('filament-panels::resources/pages/edit-record.notifications.saved.title'));
  88. }
  89. public function form(Form $form): Form
  90. {
  91. return $form
  92. ->schema([
  93. $this->getIdentificationSection(),
  94. $this->getLocationDetailsSection(),
  95. $this->getLegalAndComplianceSection(),
  96. ])
  97. ->model($this->record)
  98. ->statePath('data')
  99. ->operation('edit');
  100. }
  101. protected function getIdentificationSection(): Component
  102. {
  103. return Section::make('Identification')
  104. ->schema([
  105. Group::make()
  106. ->schema([
  107. TextInput::make('email')
  108. ->email()
  109. ->localizeLabel()
  110. ->maxLength(255)
  111. ->required(),
  112. TextInput::make('phone_number')
  113. ->tel()
  114. ->nullable()
  115. ->localizeLabel(),
  116. ])->columns(1),
  117. FileUpload::make('logo')
  118. ->openable()
  119. ->maxSize(2048)
  120. ->localizeLabel()
  121. ->visibility('public')
  122. ->disk('public')
  123. ->directory('logos/company')
  124. ->imageResizeMode('contain')
  125. ->imageCropAspectRatio('1:1')
  126. ->panelAspectRatio('1:1')
  127. ->panelLayout('compact')
  128. ->removeUploadedFileButtonPosition('center bottom')
  129. ->uploadButtonPosition('center bottom')
  130. ->uploadProgressIndicatorPosition('center bottom')
  131. ->getUploadedFileNameForStorageUsing(
  132. static fn (TemporaryUploadedFile $file): string => (string) str($file->getClientOriginalName())
  133. ->prepend(Auth::user()->currentCompany->id . '_'),
  134. )
  135. ->extraAttributes(['class' => 'w-32 h-32'])
  136. ->acceptedFileTypes(['image/png', 'image/jpeg']),
  137. ])->columns();
  138. }
  139. protected function getLocationDetailsSection(): Component
  140. {
  141. return Section::make('Location Details')
  142. ->schema([
  143. Select::make('country')
  144. ->searchable()
  145. ->localizeLabel()
  146. ->live()
  147. ->options(Country::getAvailableCountryOptions())
  148. ->afterStateUpdated(static function (Set $set) {
  149. $set('state_id', null);
  150. $set('city_id', null);
  151. })
  152. ->required(),
  153. Select::make('state_id')
  154. ->localizeLabel('State / Province')
  155. ->searchable()
  156. ->live()
  157. ->options(static fn (Get $get) => State::getStateOptions($get('country')))
  158. ->nullable(),
  159. TextInput::make('address')
  160. ->localizeLabel('Street Address')
  161. ->maxLength(255)
  162. ->nullable(),
  163. Select::make('city_id')
  164. ->localizeLabel('City / Town')
  165. ->searchable()
  166. ->options(static fn (Get $get) => City::getCityOptions($get('country'), $get('state_id')))
  167. ->nullable(),
  168. TextInput::make('zip_code')
  169. ->localizeLabel('Zip / Postal Code')
  170. ->maxLength(20)
  171. ->nullable(),
  172. ])->columns();
  173. }
  174. protected function getLegalAndComplianceSection(): Component
  175. {
  176. return Section::make('Legal & Compliance')
  177. ->schema([
  178. Select::make('entity_type')
  179. ->localizeLabel()
  180. ->options(EntityType::class)
  181. ->required(),
  182. TextInput::make('tax_id')
  183. ->localizeLabel('Tax ID')
  184. ->maxLength(50)
  185. ->nullable(),
  186. ])->columns();
  187. }
  188. protected function handleRecordUpdate(CompanyProfileModel $record, array $data): CompanyProfileModel
  189. {
  190. $record->fill($data);
  191. $keysToWatch = [
  192. 'logo',
  193. ];
  194. if ($record->isDirty($keysToWatch)) {
  195. $this->dispatch('companyProfileUpdated');
  196. }
  197. $record->save();
  198. return $record;
  199. }
  200. /**
  201. * @return array<Action | ActionGroup>
  202. */
  203. protected function getFormActions(): array
  204. {
  205. return [
  206. $this->getSaveFormAction(),
  207. ];
  208. }
  209. protected function getSaveFormAction(): Action
  210. {
  211. return Action::make('save')
  212. ->label(__('filament-panels::resources/pages/edit-record.form.actions.save.label'))
  213. ->submit('save')
  214. ->keyBindings(['mod+s']);
  215. }
  216. public static function canView(Model $record): bool
  217. {
  218. try {
  219. return authorize('update', $record)->allowed();
  220. } catch (AuthorizationException $exception) {
  221. return $exception->toResponse()->allowed();
  222. }
  223. }
  224. }