Created
March 9, 2024 10:36
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Filament\AdminPanel\Resources\Management\GroupResource\RelationManagers; | |
use App\Filament\AdminPanel\Resources\Management\ParticipantResource\ParticipantResource; | |
use App\Filament\AdminPanel\Shared\EnumArrays\GenderStatus; | |
use App\Filament\Imports\Participant2Importer; | |
use App\Models\Country; | |
use App\Models\Lookup\AcademicLevel; | |
use App\Models\Lookup\Interest; | |
use App\Models\Participant; | |
use App\Models\ParticipantAcademicInstution; | |
use App\Models\State; | |
use App\Services\ParticipantService; | |
use Awcodes\FilamentTableRepeater\Components\TableRepeater; | |
use Cheesegrits\FilamentGoogleMaps\Fields\Map; | |
use Filament\Forms\Components\DatePicker; | |
use Filament\Forms\Components\Fieldset; | |
use Filament\Forms\Components\Grid; | |
use Filament\Forms\Components\Hidden; | |
use Filament\Forms\Components\RichEditor; | |
use Filament\Forms\Components\Section; | |
use Filament\Forms\Components\Select; | |
use Filament\Forms\Components\Tabs; | |
use Filament\Forms\Components\Textarea; | |
use Filament\Forms\Components\TextInput; | |
use Filament\Forms\Components\Toggle; | |
use Filament\Forms\Form; | |
use Filament\Forms\Get; | |
use Filament\Forms\Set; | |
use Filament\Resources\RelationManagers\RelationManager; | |
use Filament\Tables; | |
use Filament\Tables\Actions\ImportAction; | |
use Filament\Tables\Table; | |
use Illuminate\Support\HtmlString; | |
use Ysfkaya\FilamentPhoneInput\Forms\PhoneInput; | |
class ParticipantsRelationManager extends RelationManager | |
{ | |
protected static string $relationship = 'participants'; | |
protected static ?string $recordTitleAttribute = 'id'; | |
protected static bool $shouldRegisterNavigation = false; | |
protected $listeners = [ | |
'refreshParticipants' => '$refresh', | |
'showModalPaticipants', | |
]; | |
public function form(Form $form): Form | |
{ | |
return $form->schema([ | |
Grid::make(['default' => 0]) | |
->schema([ | |
Section::make('') | |
->schema([ | |
Grid::make(['default' => 0]) | |
->schema([ | |
Toggle::make('enrolled_to_site') | |
->label(fn(RelationManager $livewire): string => 'Enrolled to : ' . $livewire->getOwnerRecord()->site->name) | |
->live() | |
->visible(function (RelationManager $livewire) { | |
return $livewire->getOwnerRecord()->site->is_school; | |
}), | |
Grid::make(['default' => 3]) | |
->schema([ | |
TextInput::make('preferred_name') | |
->rules(['max:255', 'string']) | |
->required() | |
->placeholder('Full Name') | |
->columnSpan(1), | |
TextInput::make('username') | |
->unique(ignoreRecord: true) | |
->rules(['max:255', 'string']) | |
->required() | |
->placeholder('Username') | |
->columnSpan(1), | |
DatePicker::make('birthdate') | |
->live(onBlur: true) | |
->helperText(function (Get $get, Set $set, ParticipantService $service) { | |
$isExist = $service->duplicatePosibilityByName(organization(), $get('first_name'), $get('last_name'), $get('birthdate')); | |
if ($isExist) { | |
$set('possible_duplicate', true); | |
return new HtmlString('This combination of data has posibility to duplicate'); | |
} | |
$set('possible_duplicate', false); | |
return ''; | |
}), | |
TextInput::make('first_name') | |
->rules(['max:255', 'string']) | |
->required() | |
->placeholder('First Name') | |
->live(onBlur: true) | |
->helperText(function (Get $get, Set $set, ParticipantService $service) { | |
$isExist = $service->duplicatePosibilityByName(organization(), $get('first_name'), $get('last_name'), $get('birthdate')); | |
if ($isExist) { | |
$set('possible_duplicate', true); | |
return new HtmlString('This combination of data has posibility to duplicate'); | |
} | |
$set('possible_duplicate', false); | |
return ''; | |
}), | |
TextInput::make('middle_name') | |
->rules(['max:255', 'string']) | |
->nullable() | |
->placeholder('Middle Name'), | |
TextInput::make('last_name') | |
->required() | |
->live(onBlur: true) | |
->helperText(function (Get $get, Set $set, ParticipantService $service) { | |
$isExist = $service->duplicatePosibilityByName(organization(), $get('first_name'), $get('last_name'), $get('birthdate')); | |
if ($isExist) { | |
$set('possible_duplicate', true); | |
return new HtmlString('This combination of data has posibility to duplicate'); | |
} | |
$set('possible_duplicate', false); | |
return ''; | |
}) | |
->rules(['max:255', 'string']) | |
->placeholder('Last Name'), | |
]), | |
Hidden::make('possible_duplicate') | |
->default(false), | |
TextInput::make('email') | |
->unique(ignoreRecord: true) | |
->email() | |
->required() | |
->placeholder('Email') | |
->columnSpanFull(), | |
Select::make('gender') | |
->required() | |
->options(GenderStatus::class), | |
Grid::make(2) | |
->schema([ | |
Select::make('academic_level_id') | |
->label('Academic Level') | |
->options(AcademicLevel::all() | |
->pluck('name', 'id')), | |
DatePicker::make('enrollment_date') | |
->label(__('Enrollment Date')), | |
]) | |
->visible(function (Get $get) { | |
return $get('enrolled_to_site'); | |
}), | |
Tabs::make('Contact Info') | |
->columnSpanFull() | |
->schema([ | |
Tabs\Tab::make('Identity Information') | |
->columnSpanFull() | |
->schema([ | |
TextInput::make('national_id_number') | |
->unique() | |
->nullable() | |
->label('National ID Number'), | |
TextInput::make('passport_number') | |
->unique() | |
->nullable() | |
->label('Passport Number'), | |
Select::make('passport_country') | |
->nullable() | |
->options( | |
Country::all() | |
->pluck('name', 'id') | |
->toArray() | |
) | |
->label('Passport Country') | |
->searchable() | |
->reactive(), | |
]), | |
Tabs\Tab::make('Bio') | |
->columnSpanFull() | |
->schema([ | |
RichEditor::make('bio') | |
->nullable() | |
->placeholder('Bio') | |
->columnSpanFull(), | |
Select::make('Interest') | |
->nullable() | |
->relationship('interests', 'name') | |
->options( | |
//use the interests relationship to get the list of interests | |
Interest::all() | |
->pluck('name', 'id') | |
->toArray() | |
) | |
->label('Interests') | |
->multiple() | |
->searchable() | |
->reactive(), | |
]), | |
Tabs\Tab::make('Career Objectives') | |
->columnSpanFull() | |
->schema([ | |
RichEditor::make('career_goal') | |
->nullable() | |
->placeholder('Career Goal') | |
->columnSpanFull(), | |
]), | |
Tabs\Tab::make('Contact Data') | |
->columnSpanFull() | |
->schema([ | |
Fieldset::make('Contact Numbers') | |
->schema([ | |
PhoneInput::make('home_telephone'), | |
PhoneInput::make('mobile_telephone'), | |
PhoneInput::make('office_telephone'), | |
PhoneInput::make('emergency_contact_telephone'), | |
]), | |
]), | |
Tabs\Tab::make('Address Details') | |
->schema([ | |
Grid::make(5) | |
->schema([ | |
Grid::make(['default' => 2]) | |
->schema([ | |
Textarea::make('address1') | |
->required(), | |
Textarea::make('address2'), | |
Select::make('country_id') | |
->nullable() | |
->label('Country') | |
->getSearchResultsUsing(fn(string $search): array => Country::where('name', 'like', "%{$search}%") | |
->limit(20) | |
->pluck('name', 'id') | |
->toArray()) | |
->getOptionLabelUsing(fn($value): ?string => Country::find($value)?->name) | |
->searchable() | |
->reactive() | |
->afterStateUpdated(fn(callable $set) => $set('state_id', null)), | |
Select::make('state_id') | |
->nullable() | |
->label('State') | |
->options( | |
function (callable $get) { | |
return State::whereCountryId($get('country_id')) | |
->pluck('name', 'id') | |
->toArray(); | |
} | |
) | |
->searchable(), | |
TextInput::make('city') | |
->nullable() | |
->label('City'), | |
TextInput::make('postal_code') | |
->nullable() | |
->label('Postal Code'), | |
]), | |
Grid::make(['default' => 0]) | |
->schema([ | |
Map::make('location') | |
->mapControls([ | |
'mapTypeControl' => true, | |
'scaleControl' => true, | |
'streetViewControl' => true, | |
'rotateControl' => true, | |
'fullscreenControl' => true, | |
'searchBoxControl' => false, | |
// creates geocomplete field inside map | |
'zoomControl' => false, | |
]) | |
->height(fn() => '400px') // map height (width is controlled by Filament options) | |
->defaultZoom(5) // default zoom level when opening form | |
->autocomplete('address1') // field on form to use as Places geocompletion field | |
->autocompleteReverse(true) // reverse geocode marker location to autocomplete field | |
->reverseGeocode([ | |
'country' => '%c', | |
'address1' => '%n %S', | |
'city' => '%A1', | |
'postal_code' => '%z', | |
]) // reverse geocode marker location to form fields, see notes below | |
->debug() // prints reverse geocode format strings to the debug console | |
->defaultLocation(function ($record) { | |
if ($record && $record->longitude && $record->latitude) { | |
return [ | |
$record->latitude, | |
$record->longitude, | |
]; | |
} | |
else { | |
return [0, 0]; | |
} | |
}) // default for new forms | |
->draggable() // allow dragging to move marker | |
->clickable(false) // allow clicking to move marker | |
->afterStateUpdated(fn(callable $set) => $set('state_id', null)) | |
->reactive(), | |
// array of KML layer URLs to add to the map, | |
]), | |
]), | |
]), | |
Tabs\Tab::make('Social Media') | |
->columnSpanFull() | |
->schema([ | |
TableRepeater::make('social_media') | |
->label('') | |
->schema([ | |
Select::make('platform') | |
->disableLabel() | |
->options([ | |
'behance' => 'Behance', | |
'bitbucket' => 'BitBucket', | |
'facebook' => 'Facebook', | |
'flickr' => 'Flickr', | |
'github' => 'GitHub', | |
'gitlab' => 'GitLab', | |
'instagram' => 'Instagram', | |
'linkedin' => 'LinkedIn', | |
'pinterest' => 'Pinterest', | |
'reddit' => 'Reddit', | |
'skype' => 'Skype', | |
'snapchat' => 'Snapchat', | |
'stackoverflow' => 'StackOverflow', | |
'telegram' => 'Telegram', | |
'tiktok' => 'TikTok', | |
'tumblr' => 'Tumblr', | |
'twitter' => 'Administrator', | |
'viber' => 'Viber', | |
'vimeo' => 'Vimeo', | |
'whatsapp' => 'WhatsApp', | |
'youtube' => 'YouTube', | |
'other' => 'Other', | |
]), | |
TextInput::make('url') | |
->disableLabel(), | |
]) | |
->columnSpan('full'), | |
]), | |
]), | |
]), | |
]), | |
]), | |
]); | |
} | |
public function table(Table $table): Table | |
{ | |
return $table | |
->columns(\App\Filament\Fields\Participant\Table::main()) | |
->filters([]) | |
->headerActions([ | |
Tables\Actions\CreateAction::make() | |
->closeModalByClickingAway(false) | |
->after(function (Participant $record, RelationManager $livewire, array $data) { | |
if (isset($data['enrolled_to_site']) && isset($data['academic_level_id'])) { | |
ParticipantAcademicInstution::create([ | |
'participant_id' => $record->id, | |
'academic_level_id' => $data['academic_level_id'], | |
'academic_site_id' => $livewire->getOwnerRecord()->site->id, | |
'enrollment_date' => $data['enrollment_date'], | |
]); | |
} | |
}), | |
// Action::make('Attach Participant') | |
// ->dispatch('showModalPaticipants'), | |
ImportAction::make('importParticipants') | |
->importer(Participant2Importer::class), | |
]) | |
->actions([ | |
Tables\Actions\Action::make('View') | |
->icon('heroicon-o-eye') | |
->url(fn($record) => ParticipantResource::getUrl('view', [$record->id])) | |
->openUrlInNewTab(), | |
]) | |
->bulkActions([]); | |
} | |
public function showModalPaticipants(RelationManager $livewire): void | |
{ | |
$this->dispatch('getListParticipantTable'); | |
$this->dispatch('open-modal', id: 'list-participant'); | |
} | |
public function refreshParticipants(): void | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment