Skip to content

Instantly share code, notes, and snippets.

@craigvc
Created March 9, 2024 10:36
<?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