This commit is contained in:
salam committed 2026-10-04 15:25:03 +02:00
1 parent 9bcd4432c6
commit 6f92f9e1d5
1209 files changed
+220940

No files matched your search

+115
View File
@@ -0,0 +1,115 @@
<?php
namespace App\Filament\Pages;
use App\Models\User;
use BackedEnum;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
class EventMapper extends Page
{
use HasPageShield;
protected $listeners = [
'refresh' => '$refresh',
];
protected string $view = 'filament.pages.event-mapper';
protected static string|BackedEnum|null $navigationIcon = 'phosphor-arrows-in-line-horizontal';
protected static ?string $navigationLabel = 'Mapper';
protected ?string $heading = '';
protected static ?int $navigationSort = 4; // Smaller number = higher up
// protected static ?int $navigationSort = 100;
protected function getHeaderActions(): array
{
return [
ActionGroup::make([
Action::make('bet365')
->extraAttributes(['x-on:click' => 'toggle'])
->visible(fn (): bool => auth()->user()->provider_id != 2)
->action(function ($livewire) {
User::where('id', auth()->user()->id)->update(['provider_id' => 2]);
Notification::make()
->title('Event Mapper changed to Bet365')
->success()
->send();
$livewire->dispatch('refresh');
}),
Action::make('magloo_nigeria')
->label('MAGLOO NIGERIA')
->extraAttributes(['x-on:click' => 'toggle'])
->visible(fn (): bool => in_array(auth()->user()->provider_id, [2, 4]))
->hidden(fn (): bool => ! in_array(auth()->user()->bookmaker_id, [10, 16]))
->action(function ($livewire) {
User::where('id', auth()->user()->id)->update(['provider_id' => 3]);
$livewire->dispatch('refresh');
Notification::make()
->title('Event Mapper changed to MAGLOO NIGERIA')
->success()
->send();
}),
Action::make('magloo_kenia')
->label('MAGLOO KENIA')
->extraAttributes(['x-on:click' => 'toggle'])
->visible(fn (): bool => in_array(auth()->user()->provider_id, [2, 3]))
->hidden(fn (): bool => ! in_array(auth()->user()->bookmaker_id, [10, 16]))
->action(function ($livewire) {
User::where('id', auth()->user()->id)->update(['provider_id' => 4]);
$livewire->dispatch('refresh');
Notification::make()
->title('Event Mapper changed to MAGLOO KENIA')
->success()
->send();
}),
Action::make('logifuture_nigeria')
->label('LOGIFUTURE NIGERA')
->extraAttributes(['x-on:click' => 'toggle'])
->visible(fn (): bool => auth()->user()->provider_id == 6)
->hidden(fn (): bool => ! in_array(auth()->user()->bookmaker_id, [35, 36]))
->action(function ($livewire) {
User::where('id', auth()->user()->id)->update(['provider_id' => 5]);
$livewire->dispatch('refresh');
Notification::make()
->title('Event Mapper changed to LOGIFUTURE NIGERIA')
->success()
->send();
}),
Action::make('logifuture_colombia')
->label('LOGIFUTURE COLOMBIA')
->extraAttributes(['x-on:click' => 'toggle'])
->visible(fn (): bool => auth()->user()->provider_id == 5)
->hidden(fn (): bool => ! in_array(auth()->user()->bookmaker_id, [35, 36]))
->action(function ($livewire) {
User::where('id', auth()->user()->id)->update(['provider_id' => 6]);
$livewire->dispatch('refresh');
Notification::make()
->title('Event Mapper changed to LOGIFUTURE COLOMBIA')
->success()
->send();
}),
])
->label('Swop Bookmaker')
->icon('phosphor-dots-three-vertical')
->visible(fn (): bool => auth()->user()->hasRole('mapper_source_betsapi'))
->color('primary')
->button(),
];
}
}
+276
View File
@@ -0,0 +1,276 @@
<?php
namespace App\Filament\Pages;
use App\Actions\LoadSofaScoreCategory;
use App\Actions\LoadStatisticFixturesLeaguesOptions;
use App\Actions\LoadStatisticFixturesMatchOptions;
use App\Filament\Widgets\PlayerPropsDrop;
use App\Filament\Widgets\PlayerPropsTable;
use App\Models\SofaScoreRosa;
use App\Models\SsLineupMemory;
use App\Models\StatisticFixtures;
use BackedEnum;
use Filament\Forms\Components\Select;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Navigation\NavigationItem;
use Filament\Pages\Page;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Livewire\Attributes\On;
class PlayerProps extends Page implements HasForms
{
use InteractsWithForms;
protected string $view = 'filament.pages.player-props';
public static function getNavigationItems(): array
{
return [
NavigationItem::make(static::getNavigationLabel())
->group(static::getNavigationGroup())
->icon(static::getNavigationIcon())
->activeIcon(static::getActiveNavigationIcon())
->isActiveWhen(fn() => request()->routeIs(static::getRouteName()))
->sort(static::getNavigationSort())
->url(static::getUrl(), shouldOpenInNewTab: true), // 👈 Forces target="_blank"
];
}
protected static string|BackedEnum|null $navigationIcon = 'icon-soccerplayer';
public function getHeading(): string
{
return '';
}
protected static ?string $title = 'Player Props';
protected static ?int $navigationSort = 2;
public ?array $filterData;
public array $lineUpOptions;
public string $activeLineUp = '3313';
public array $players = [];
public array $clientLineUps = [];
public int $team_id;
public function mount(): void
{
// Initialisiert das Formular mit leeren Werten
$this->form->fill();
}
public function getWidgetData(): array
{
return [
'activeLineUp' => $this->activeLineUp,
];
}
public function form(Schema $schema): Schema
{
return $schema
->columns(5)
->components([
Select::make('cid')
->live()
->preload()
->searchable(false)
->prefixIconColor(fn(Get $get): string => $get('cid') ? 'success' : 'danger')
->prefixIcon('phosphor-globe-fill')
->hiddenLabel()
->options(fn() => LoadSofaScoreCategory::load())
->placeholder('Country')
->afterStateUpdated(function (callable $set, $state) {
$set('lid', null);
$set('mid', null);
$set('tid', null);
$this->dispatch('clear-all');
}),
Select::make('lid')
->live()
->preload()
->prefixIconColor(fn(Get $get): string => $get('lid') ? 'success' : 'danger')
->prefixIcon('phosphor-trophy-fill')
->hiddenLabel()
->options(fn(Get $get) => LoadStatisticFixturesLeaguesOptions::load($get('cid')))
->placeholder('League')
->afterStateUpdated(function (callable $set) {
$set('mid', null);
$set('tid', null);
$this->dispatch('clear-all');
}),
Select::make('mid')
->live()
->hiddenLabel()
->prefixIconColor(fn(Get $get): string => $get('mid') ? 'success' : 'danger')
->prefixIcon('phosphor-calendar-check-fill')
->options(function (Get $get) {
return LoadStatisticFixturesMatchOptions::load($get('lid'));
})
->afterStateUpdated(function (callable $set, $state) {
$set('tid', null);
if ($state) {
$this->dispatch('match-update', match_id: $state);
} else {
$this->dispatch('clear-all');
}
})
->placeholder('Events'),
Select::make('tid')
->live()
->hiddenLabel()
->prefixIconColor(fn(Get $get): string => $get('tid') ? 'success' : 'danger')
->prefixIcon('icon-player')
->options(function (Get $get) {
if ($get('mid')) {
$res = StatisticFixtures::where('id', $get('mid'))->first();
$arr = [];
if ($res) {
$arr[$res->home_id] = SofaScoreRosa::query()->where('ss_team_id', $res->home_id)->value('ss_team_name');
$arr[$res->away_id] = SofaScoreRosa::query()->where('ss_team_id', $res->away_id)->value('ss_team_name');
}
return $arr;
}
})
->placeholder('Team')
->afterStateUpdated(function ($state, Set $set) {
if ($state) {
$this->dispatch('team-update', team_id: $state);
$tmp = SsLineupMemory::where('client_id', Auth::user()->client_id)->where('team_id', $state)->orderBy('created_at', 'desc')->first();
if ($tmp) {
$set('lineup', $tmp->lineup);
$this->dispatch('lineup-update', activeLineUp: $tmp->lineup);
}
}
}),
Select::make('lineup')
->live()
->hiddenLabel()
->allowHtml()
->native(false)
->selectablePlaceholder(false)
->prefixIconColor('info')
->prefixIcon('icon-soccerfield-fill')
->options(function () {
$res = $this->lineUpOptions();
$arr = [];
foreach ($res as $key => $value) {
if ($this->players && in_array($key, $this->clientLineUps)) {
$arr[$key] = $value . '<span class="text-blue-600"> has lineup</span>';
} else {
$arr[$key] = $value;
}
}
return $arr;
})
->placeholder('LineUp')
->searchable()
->default($this->activeLineUp)
->afterStateUpdated(function ($state) {
$this->dispatch('lineup-update', activeLineUp: $state);
}),
])->statePath('filterData');
}
#[On('team-update')]
public function syncData(?int $team_id)
{
if ($team_id) {
$this->team_id = $team_id;
$this->clientLineUps = SsLineupMemory::where('team_id', $team_id)->where('client_id', Auth::user()->client_id)->pluck('lineup')->toArray();
} else {
$this->players = [];
$this->dispatch('clear-all');
}
}
#[On('update-players')]
public function updatePlayers(array $players)
{
$this->players = $players;
}
protected function getFooterWidgets(): array
{
return [
PlayerPropsTable::make(['players' => $this->players]),
PlayerPropsDrop::make(['players' => $this->players]),
];
}
public function getFooterWidgetsColumns(): int|array
{
return 5;
}
private function lineUpOptions(): array
{
return [
'3313' => '3313',
'3331' => '3331',
'3331-' => '3331-',
'3331+' => '3331+',
'3412-' => '3412-',
'3412+' => '3412+',
'3421-' => '3421-',
'3421+' => '3421+',
'343-' => '343-',
'343+' => '343+',
'3511' => '3511',
'3511-' => '3511-',
'3511+' => '3511+',
'352' => '352',
'352-' => '352-',
'352+' => '352+',
'4132' => '4132',
'4213-' => '4213-',
'4213+' => '4213+',
'4222' => '4222',
'4231' => '4231',
'424' => '424',
'4312' => '4312',
'4312-' => '4312-',
'4312+' => '4312+',
'4321' => '4321',
'4321-' => '4321-',
'4321+' => '4321+',
'433' => '433',
'433-' => '433-',
'433+' => '433+',
'4411-' => '4411-',
'4411+' => '4411+',
'442' => '442',
'442-' => '442-',
'442+' => '442+',
'451' => '451',
'451-' => '451-',
'451+' => '451+',
'523-' => '523-',
'523+' => '523+',
'5311' => '5311',
'5311-' => '5311-',
'5311+' => '5311+',
'532' => '532',
'532-' => '532-',
'532+' => '532+',
'541-' => '541-',
'541+' => '541+',
];
}
}
@@ -0,0 +1,48 @@
<?php
namespace App\Filament\Pages\Selections\Helper;
use Illuminate\Support\Carbon;
class GetSeason
{
public static function load(?array $season, ?string $seasonmode)
{
if (! \is_array($season) || ! \count($season)) {
$date = Carbon::now();
$season = [];
if ($seasonmode == 'halfyear') {
if ((int) date('m') > 7) {
$season[] = (string) $date->format('y').'/'.$date->format('y') + 1;
} else {
$season[] = (string) $date->format('y') - 1 .'/'.$date->format('y');
}
} else {
$season[] = (string) $date->year;
}
}
return $season;
}
public static function active(?string $seasonmode)
{
$date = Carbon::now();
$active_season = '';
if ($seasonmode == 'halfyear') {
if ((int) date('m') > 7) {
$active_season = (string) $date->format('y').'/'.$date->format('y') + 1;
} else {
$active_season = (string) $date->format('y') - 1 .'/'.$date->format('y');
}
} else {
$active_season = (string) $date->year;
}
return $active_season;
}
}
@@ -0,0 +1,133 @@
<?php
namespace App\Filament\Pages\Selections;
use App\Filament\Pages\Selections\Helper\GetSeason;
use App\Models\SofaScorePlayerPerSeason;
use App\Models\StatistikoEvent;
class LoadPlayerSelection
{
public static function load(?int $team_id, ?string $team_position, ?int $sofascore_category_id, ?array $season, ?string $seasonmode)
{
$season = GetSeason::load($season, $seasonmode);
// $hash = hash('crc32', $team_id.$team_position.$sofascore_category_id.serialize($season));
// $cached_players = SofaScorePlayerCache::where('hash', $hash)->value('players');
// if ($cached_players) {
// return $cached_players;
// }
$matches = StatistikoEvent::whereIn('season', $season)
->where(function ($query) use ($team_id, $team_position) {
switch ($team_position) {
case 'home':
return $query->where('home_id', '=', $team_id);
case 'away':
return $query->where('away_id', '=', $team_id);
default:
return $query->where('home_id', '=', $team_id)
->orWhere('away_id', '=', $team_id);
}
})->pluck('match_id')->toArray();
$matches_count = count($matches);
$positions_map = LoadPositions::load();
$player = SofaScorePlayerPerSeason::with('details')->where('ss_team_id', $team_id)->whereIn('season', $season)->get();
// dd($player);
$arr = [];
foreach ($player as $val) {
if ($val->details) {
$player_id = $val->ss_player_id;
if (! isset($arr[$player_id])) {
$arr[$player_id]['player_name'] = $val->details->player_name;
$arr[$player_id]['events_played_home'] = $val->events_played_home;
$arr[$player_id]['events_played_away'] = $val->events_played_away;
$arr[$player_id]['minutes_played_home'] = $val->minutes_played_home;
$arr[$player_id]['minutes_played_away'] = $val->minutes_played_away;
$arr[$player_id]['preferred_foot'] = $val->details->preferred_foot ?? '';
$arr[$player_id]['player_position'] = $val->details->position ?? '';
$arr[$player_id]['color_level'] = round($matches_count / 3);
} else {
$arr[$player_id]['events_played_home'] += $val->events_played_home;
$arr[$player_id]['events_played_away'] += $val->events_played_away;
$arr[$player_id]['minutes_played_home'] += $val->minutes_played_home;
$arr[$player_id]['minutes_played_away'] += $val->minutes_played_away;
}
}
}
$result = [];
foreach ($arr as $player_id => $val) {
switch ($team_position) {
case 'home':
$events_played = $val['events_played_home'];
$minues_played = $val['minutes_played_home'];
break;
case 'away':
$events_played = $val['events_played_away'];
$minues_played = $val['minutes_played_away'];
break;
default:
$events_played = $val['events_played_home'] + $val['events_played_away'];
$minues_played = $val['minutes_played_home'] + $val['minutes_played_home'];
break;
}
$colorlevel = round($matches_count / 3);
if (in_array($val['player_position'], $positions_map['MIDFIELD'])) {
$position = 'MIDFIELD';
} elseif (in_array($val['player_position'], $positions_map['DEFENCE'])) {
$position = 'DEFENCE';
} elseif (in_array($val['player_position'], $positions_map['ATTACK'])) {
$position = 'ATTACK';
} elseif (in_array($val['player_position'], $positions_map['GOALKEEPER'])) {
$position = 'GOALKEEPER';
} else {
$position = 'NO SPECIFIC POSITION';
}
$infostring = '';
if ($colorlevel > 1 && $events_played < $colorlevel) {
$infostring = '<div class="w-full text-red-600 dark:text-red-500 cursor-pointer flex flex-row gap-1">';
} elseif ($events_played < $colorlevel * 2) {
$infostring = '<div class="w-full text-blue-600 dark:text-blue-500 cursor-pointer flex flex-row gap-1">';
} else {
$infostring = '<div class="w-full text-green-600 dark:text-green-500 cursor-pointer flex flex-row gap-1">';
}
$infostring .= '<div class="flex-1 font-bold">'.$val['player_name'].' '.$val['player_position'].'</div>';
$infostring .= '<div>'.$events_played.' Events,</div>';
$infostring .= '<div>'.$val['preferred_foot'].' foot,</div>';
if ($events_played) {
$infostring .= '<div>Av. on field '.round($minues_played / $events_played).'min</div>';
}
$infostring .= '</div>';
$result[$position][$player_id] = $infostring;
}
// if ($result) {
// SofaScorePlayerCache::updateOrCreate(['hash' => $hash], ['players' => $result]);
// }
return $result;
}
public static function convertToHoursMins(int $time, $format = '%02dh:%02dm')
{
if ($time < 1) {
return;
}
$hours = floor($time / 60);
$minutes = $time % 60;
return sprintf($format, $hours, $minutes);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Pages\Selections;
use App\Models\SofaScorePlayerPosition;
class LoadPositions
{
public static function load()
{
$res = SofaScorePlayerPosition::all();
$arr = [];
foreach ($res as $val) {
$arr[$val->generalposition][] = $val->ss_code;
}
return $arr;
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Filament\Pages\Selections;
use Carbon\CarbonPeriod;
use Illuminate\Support\Carbon;
class LoadSeasons
{
public static function load($seasonmode)
{
if (!$seasonmode) {
return [];
}
$season = [];
$period = CarbonPeriod::create(Carbon::now()->year(2024), '1 year', Carbon::now());
foreach ($period as $date) {
if ($seasonmode == 'halfyear') {
if ((int) date('m') > 7)
$tmp = $date->format('y') . '/' . $date->format('y') + 1;
else
$tmp = $date->format('y') - 1 . '/' . $date->format('y');
$season[$tmp] = $tmp;
} else {
$season[(string) $date->year] = (string) $date->year;
}
}
return $season;
}
}
+639
View File
@@ -0,0 +1,639 @@
<?php
namespace App\Filament\Pages;
use App\Actions\LoadSofaScoreCategory;
use App\Actions\LoadStatisticFixturesLeaguesOptions;
use App\Actions\LoadStatisticFixturesMatchOptions;
use App\Filament\Pages\Selections\LoadPlayerSelection;
use App\Filament\Widgets\Boxes\LoadEventsBoxes;
use App\Models\SofaScoreCategory;
use App\Models\SofaScoreRosa;
use App\Models\StatisticFixtures;
use BackedEnum;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
use Filament\Actions\Action;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Radio;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Slider;
use Filament\Notifications\Notification;
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Schemas\Components\Actions;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
use Filament\Support\Enums\Size;
use Filament\Support\RawJs;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\HtmlString;
class Statistic extends BaseDashboard
{
use HasFiltersForm, HasPageShield;
protected static string|BackedEnum|null $navigationIcon = 'phosphor-chart-line-up';
protected string $view = 'filament.pages.statistic';
protected ?string $pollingInterval = null;
protected static ?string $title = 'Statistiko';
protected static ?int $navigationSort = 1;
protected int|string|array $columnSpan = [
'md' => 2,
'xl' => 3,
];
public function resetFilters(): void
{
$filters = array_keys($this->filters);
foreach ($filters as $filter) {
switch ($filter) {
case 'accuracy':
$this->filters[$filter] = 0.125;
break;
case 'similar_past_matches':
$this->filters[$filter] = 'none';
break;
case 'team_position':
$this->filters[$filter] = 'all';
break;
case 'statistic_type':
$this->filters[$filter] = 'gls';
break;
case 'season_or_date':
$this->filters[$filter] = 'season';
break;
default:
$this->filters[$filter] = null;
break;
}
}
}
public function getHeading(): string|Htmlable|null
{
return '';
}
// protected function getHeaderActions(): array
// {
// return [
// Action::make('esc')
// ->label('Reset')
// ->icon('phosphor-x-circle')
// ->color('gray')
// ->keyBindings(['esc'])
// ->action('resetFilters'),
// Action::make('openDispatcherBoard')
// ->modalHeading('')
// ->label('Calculate')
// ->icon('icon-player')
// ->color(fn (): string => $this->filters['team_id'] ? 'primary' : 'gray')
// ->disabled(fn (): string => $this->filters['team_id'] ? false : true)
// ->slideOver()
// ->slideOverPosition(SlideOverPosition::Start)
// ->modalWidth(Width::Screen)
// ->modalSubmitAction(false)
// ->modalCancelAction(false)
// ->modalContent(fn (): View => view('livewire.board-dispatcher-modal-wrapper', ['filters' => $this->filters])),
// ];
// }
public function filtersForm(Schema $schema): Schema
{
return $schema
->components([
// ToggleButtons::make('status')
// ->columnSpanFull()
// ->hiddenLabel()
// ->inline()
// ->default(1)
// ->options([
// '1' => 'Soccer',
// '3' => 'Basketball',
// '2' => 'Ice Hockey',
// '5' => 'Tennis',
// ])
// ->icons([
// '1' => 'icon-soccerball',
// '3' => 'icon-basketball',
// '2' => 'icon-icehockey',
// '5' => 'icon-tennisball',
// ]),
Grid::make([
'default' => 1,
'sm' => 2,
'md' => 5,
])
->columnSpanFull()
->schema([
Hidden::make('seasonmode'),
Select::make('sofascore_category_id')
->live()
->preload()
->searchable(false)
->prefixIconColor(fn(Get $get): string => $get('sofascore_category_id') ? 'success' : 'danger')
->prefixIcon('phosphor-globe')
->hiddenLabel()
->options(fn() => LoadSofaScoreCategory::load())
->placeholder('Select Country')
->afterStateUpdated(function (callable $set, $state) {
$set('seasonmode', SofaScoreCategory::where('id', $state)->value('season_mode'));
$set('league_id', null);
$set('match_id', null);
$set('team_id', null);
$set('ss_player_id', null);
$set('season', null);
}),
Select::make('league_id')
->live()
->preload()
->prefixIconColor(fn(Get $get): string => $get('league_id') ? 'success' : 'danger')
->prefixIcon('phosphor-trophy')
->hiddenLabel()
->options(fn(Get $get) => LoadStatisticFixturesLeaguesOptions::load($get('sofascore_category_id')))
->placeholder('Select League')
->afterStateUpdated(function (callable $set) {
$set('match_id', null);
$set('team_id', null);
$set('ss_player_id', null);
$this->dispatch('reset-tab');
}),
Select::make('match_id')
->live()
->hiddenLabel()
->columnSpan(fn(Get $get) => $get('similar_past_matches') != 'none' ? 2 : 1)
->prefixIconColor(fn(Get $get): string => $get('match_id') ? 'success' : 'danger')
->prefixIcon('phosphor-calendar-check')
->options(function (Get $get) {
return LoadStatisticFixturesMatchOptions::load($get('league_id'));
})
->afterStateUpdated(function (callable $set) {
$set('team_id', null);
$set('ss_player_id', null);
$this->dispatch('reset-tab');
})
->placeholder('Select Event'),
Action::make('esc')
->hiddenLabel()
->visible(fn(Get $get) => $get('similar_past_matches') != 'none')
->tooltip('Clear All (esc)')
->icon('phosphor-x-circle')
->color('danger')
->keyBindings(['esc'])
->size(Size::Medium)
->outlined()
->action('resetFilters'),
Select::make('team_id')
->live()
->hiddenLabel()
->prefixIconColor(function (Get $get): string {
if ($get('team_id')) {
return 'success';
} elseif ($get('similar_past_matches') != 'none') {
return 'gray';
} else {
return 'danger';
}
})
->prefixIcon('phosphor-users')
->suffixAction(Action::make('reset')
->icon('phosphor-x-circle')
->tooltip('Clear Team')
->action(fn(callable $set) => $set('team_id', null))
->color(fn(Get $get): string => $get('team_id') != 0 ? 'danger' : 'gray'))
->hidden(fn(Get $get) => $get('similar_past_matches') != 'none')
->options(function (Get $get) {
if ($get('match_id')) {
$res = StatisticFixtures::where('id', $get('match_id'))->first();
$arr = [];
if ($res) {
$arr[$res->home_id] = SofaScoreRosa::query()->where('ss_team_id', $res->home_id)->value('ss_team_name');
$arr[$res->away_id] = SofaScoreRosa::query()->where('ss_team_id', $res->away_id)->value('ss_team_name');
}
return $arr;
}
})
->afterStateUpdated(function (callable $set) {
$set('ss_player_id', null);
$this->dispatch('reset-tab');
})
->placeholder('Select Team'),
]),
Grid::make([
'default' => 1,
'sm' => 3,
'md' => 5,
])
->columnSpanFull()
->schema([
Select::make('team_position')
->live()
->hiddenLabel()
->placeholder('Select Team Position')
->prefix('TP')
->prefixAction(
Action::make('iconInfo')
->color('success')
->icon('phosphor-question')
->tooltip(fn() => 'Team Position')
)
->hidden(fn(Get $get) => $get('similar_past_matches') != 'none')
->default('all')
->selectablePlaceholder(false)
->options([
'all' => 'All',
'home' => 'Home',
'away' => 'Away',
])->afterStateUpdated(function (callable $set) {
$set('ss_player_id', null);
}),
Select::make('statistic_type')
->live()
->hiddenLabel()
->allowHtml()
->placeholder('Statistic Type')
->prefixIconColor('success')
->prefixIcon(function (Get $get) {
return match ($get('statistic_type')) {
'gls' => 'phosphor-soccer-ball',
'crn' => 'phosphor-angle',
'fls' => 'phosphor-first-aid-kit',
'ofs' => 'phosphor-arrow-fat-lines-right',
'crd' => 'phosphor-cards',
'snt' => 'phosphor-target',
'tsh' => 'phosphor-chart-polar',
default => 'phosphor-soccer-ball',
};
})
->default('gls')
->selectablePlaceholder(false)
->options([
'gls' => 'Goals',
'crn' => 'Corner',
'fls' => 'Fouls Commited',
'ofs' => 'Offside',
'crd' => 'Cards',
'snt' => 'Shots On Target',
'tsh' => 'Total Shots',
]),
/************************
* SMP
************************/
Select::make('similar_past_matches')
->live()
// ->columnSpan(2)
->hiddenLabel()
->hidden(fn(Get $get) => $get('team_id') != null)
->columnSpan(fn(Get $get) => $get('similar_past_matches') != 'none' ? 2 : 1)
->suffixAction(Action::make('reset')
->icon('phosphor-x-circle')
->tooltip('Clear SMP')
->action(fn(callable $set) => $set('similar_past_matches', 'none'))
->color(fn(Get $get): string => $get('similar_past_matches') != 'none' ? 'danger' : 'gray'))
->placeholder('Similar Past Matches')
->suffix(fn(Get $get): string|HtmlString => $get('similar_past_matches') != 'none' ? new HtmlString('<div class="text-center w-24 font-bold rounded p-1 bg-blue-600 dark:bg-blue-700 text-white dark:text-gray-300">± ' . $get('accuracy') . '</div>') : '')
->prefix('SPM')
->prefixAction(
Action::make('iconInfo')
->icon('phosphor-question')
->color(fn(Get $get): string => $get('similar_past_matches') != 'none' ? 'success' : 'danger')
->tooltip(fn() => $this->tooltip_similar_past_matches())
)
->default('none')
->selectablePlaceholder(false)
->afterStateUpdated(function (callable $set) {
$set('ss_player_id', null);
$set('team_position', null);
$this->dispatch('reset-tab');
})
->options([
'none' => 'None',
'league' => 'League',
'all' => 'All Database',
]),
/************************
* SLIDER
************************/
Slider::make('accuracy')
->live()
->hiddenLabel()
->hidden(fn(Get $get) => $get('similar_past_matches') == 'none')
->fillTrack()
->minValue(0)
->maxValue(0.25)
->default(0.125)
->step(0.025)
->decimalPlaces(3)
->pips()
->pipsFormatter(RawJs::make(<<<'JS'
`${$value.toFixed(2)}`
JS)),
/************************
* PLAYER
************************/
Select::make('ss_player_id')
->live()
->hiddenLabel()
->allowHtml()
->columnSpan(2)
->placeholder('Player')
->visible(fn(Get $get) => $get('team_id'))
->hidden(fn(Get $get) => $get('similar_past_matches') != 'none')
->prefixIconColor(fn(Get $get): string => $get('similar_past_matches') == 'none' ? 'success' : '')
->prefixIcon('icon-player')
->preload()
->searchable()
->extraAttributes(fn() => [
'id' => 'player_selector',
'style' => 'width: 100%;',
])
->suffixAction(
Action::make('iconInfo')
->icon('phosphor-question')
->color('success')
->tooltip(fn() => $this->tooltip_player_info())
)
->options(function (Get $get) {
$team_id = $get('team_id');
$team_position = $get('team_position');
$sofascore_category_id = $get('sofascore_category_id');
$season = $get('season');
$seasonmode = $get('seasonmode');
return LoadPlayerSelection::load($team_id, $team_position, $sofascore_category_id, $season, $seasonmode);
}),
Select::make('player_on_field')
->live()
->hiddenLabel()
->placeholder('Time on field')
->prefixIcon('phosphor-watch')
->default('all')
->hidden(fn(Get $get) => ! $get('ss_player_id'))
->prefixIconColor('success')
->selectablePlaceholder(false)
->options([
'all' => 'All',
'lineup' => 'Lineup',
'substituted' => 'Substituted',
'notplayed' => 'Not Played',
]),
]),
Grid::make([
'default' => 7,
'sm' => 7,
])
->columnSpanFull()
->schema([
Radio::make('season_or_date')
->live()
->extraAttributes([
'class' => 'radio-statistic-group',
])
->hidden(fn(Get $get) => $get('similar_past_matches') != 'none')
->columnSpan(2)
->inline()
->default('season')
->hiddenLabel()
->options([
'season' => 'Season',
'date' => 'Date',
]),
/************************
* SEASON full time
************************/
Select::make('season')
->live()
->columnSpan(2)
->hiddenLabel()
->multiple()
->placeholder('Current Season')
->prefixIconColor('success')
->visible(fn(Get $get) => $get('seasonmode'))
->hidden(fn(Get $get) => $get('seasonmode') == 'halfyear' || $get('season_or_date') == 'date' || $get('similar_past_matches') != 'none')
->prefixIcon('phosphor-calendar-star')
->options([
'2026' => '2026',
'2025' => '2025',
'2024' => '2024',
])
->afterStateUpdated(function (callable $set, Get $get) {
$set('ss_player_id', null);
}),
/************************
* SEASON half time
************************/
Select::make('season')
->live()
->columnSpan(2)
->hiddenLabel()
->multiple()
->placeholder('Current Season')
->prefixIconColor('success')
->visible(fn(Get $get) => $get('seasonmode'))
->hidden(fn(Get $get) => $get('seasonmode') == 'fullyear' || $get('season_or_date') == 'date' || $get('similar_past_matches') != 'none')
->prefixIcon('phosphor-calendar-star')
->options([
'26/27' => '26/27',
'25/26' => '25/26',
'24/25' => '24/25',
])
->afterStateUpdated(function (callable $set) {
$set('ss_player_id', null);
}),
/************************
* DATE PICKER
************************/
DatePicker::make('start_date')
->live()
->hiddenLabel()
->hidden(fn(Get $get) => $get('season_or_date') == 'season')
->native(false)
->prefixIconColor(fn(Get $get): string => $get('start_date') ? 'success' : 'primary')
->prefixIcon('phosphor-calendar')
->prefix('Start')
->suffixAction(
Action::make('clear_start')
->icon('phosphor-x')
->color('gray')
->action(fn(Set $set) => $set('start_date', null))
),
DatePicker::make('end_date')
->live()
->hiddenLabel()
->hidden(fn(Get $get) => $get('season_or_date') == 'season')
->native(false)
->prefixIconColor(fn(Get $get): string => $get('end_date') ? 'success' : 'primary')
->prefixIcon('phosphor-calendar')
->prefix('End')
->suffixAction(
Action::make('clear_end')
->icon('phosphor-x')
->color('gray')
->action(fn(Set $set) => $set('end_date', null))
),
Actions::make([
Action::make('esc')
->hiddenLabel()
->hidden(fn(Get $get) => $get('similar_past_matches') != 'none')
->tooltip('Clear All (esc)')
->icon('phosphor-x-circle')
->color(fn(Get $get) => $get('sofascore_category_id') ? 'danger' : 'gray')
->keyBindings(['esc'])
->outlined()
->size(Size::Medium)
->action('resetFilters'),
Action::make('copy')
->hiddenLabel()
->hidden(fn(Get $get) => $get('similar_past_matches') != 'none')
->visible(fn(Get $get) => $get('team_id'))
->tooltip('Copy data for pasting into spreadsheet')
->color('success')
->size(Size::Medium)
->outlined()
->icon('phosphor-copy')
->action(function ($livewire) {
// 1. Call your custom Livewire function to generate the data
$dataToCopy = $livewire->generateDynamicPayload();
$this->js("navigator.clipboard.writeText(`$dataToCopy`)");
// 3. Send a helpful Filament Toast notification to the UI
Notification::make()
->title('Copied to clipboard!')
->success()
->send();
}),
]),
]),
]);
}
public function generateDynamicPayload(): string
{
$data = LoadEventsBoxes::load($this->filters, false);
$header = ['Team', 'Event', 'Odd 1', 'Odd X', 'Odd 2', 'Category', 'EXP H', 'EXP A', 'AGV+', 'AGV-', 'AGV Team Season H', 'AGV Team Season A', 'AGV League H', 'AGV League A'];
$copystring = implode(';', $header) . "\n";
$row = [];
$row[] = $data['active_team'];
$row[] = $data['count_events'];
$row[] = $data['win_odd'];
$row[] = $data['draw_odd'];
$row[] = $data['lost_odd'];
$row[] = 'Goals';
$row[] = $data['gls']['home'];
$row[] = $data['gls']['away'];
$row[] = $data['gls_team']['home'];
$row[] = $data['gls_team']['away'];
$row[] = $data['gls_team_season']['home'];
$row[] = $data['gls_team_season']['away'];
$row[] = $data['gls_liga_season']['home'];
$row[] = $data['gls_liga_season']['away'];
$copystring .= implode(';', $row) . "\n";
$row = [];
$row = array_fill(0, 5, '');
$row[] = 'Fouls';
$row[] = $data['fls']['home'];
$row[] = $data['fls']['away'];
$row[] = $data['fls_team']['home'];
$row[] = $data['fls_team']['away'];
$row[] = $data['fls_team_season']['home'];
$row[] = $data['fls_team_season']['away'];
$row[] = $data['fls_liga_season']['home'];
$row[] = $data['fls_liga_season']['away'];
$copystring .= implode(';', $row) . "\n";
$row = [];
$row = array_fill(0, 5, '');
$row[] = 'Offside';
$row[] = $data['ofs']['home'];
$row[] = $data['ofs']['away'];
$row[] = $data['ofs_team']['home'];
$row[] = $data['ofs_team']['away'];
$row[] = $data['ofs_team_season']['home'];
$row[] = $data['ofs_team_season']['away'];
$row[] = $data['ofs_liga_season']['home'];
$row[] = $data['ofs_liga_season']['away'];
$copystring .= implode(';', $row) . "\n";
$row = [];
$row = array_fill(0, 5, '');
$row[] = 'Cards';
$row[] = $data['crd']['home'];
$row[] = $data['crd']['away'];
$row[] = $data['crd_team']['home'];
$row[] = $data['crd_team']['away'];
$row[] = $data['crd_team_season']['home'];
$row[] = $data['crd_team_season']['away'];
$row[] = $data['crd_liga_season']['home'];
$row[] = $data['crd_liga_season']['away'];
$copystring .= implode(';', $row) . "\n";
$row = [];
$row = array_fill(0, 5, '');
$row[] = 'Shots on traget';
$row[] = $data['snt']['home'];
$row[] = $data['snt']['away'];
$row[] = $data['snt_team']['home'];
$row[] = $data['snt_team']['away'];
$row[] = $data['snt_team_season']['home'];
$row[] = $data['snt_team_season']['away'];
$row[] = $data['snt_liga_season']['home'];
$row[] = $data['snt_liga_season']['away'];
$copystring .= implode(';', $row) . "\n";
$row = [];
$row = array_fill(0, 5, '');
$row[] = 'Total Shots';
$row[] = $data['tsh']['home'];
$row[] = $data['tsh']['away'];
$row[] = $data['tsh_team']['home'];
$row[] = $data['tsh_team']['away'];
$row[] = $data['tsh_team_season']['home'];
$row[] = $data['tsh_team_season']['away'];
$row[] = $data['tsh_liga_season']['home'];
$row[] = $data['tsh_liga_season']['away'];
$copystring .= implode(';', $row) . "\n";
return $copystring;
}
protected function tooltip_similar_past_matches(): HtmlString
{
$str = '<div class="m-3 grid grid-cols-4 gap-2 max-w-lg">';
$str .= '<div class="col-span-4 font-bold">Similar Past Matches (SMP)</div>';
$str .= '<div class="font-bold">None</div>';
$str .= '<div class="col-span-3"><u>Team</u> within selected league</div>';
$str .= '<div class="font-bold">League</div>';
$str .= '<div class="col-span-3"><u>Simmilar events</u> in league in the range of slider.</div>';
$str .= '<div class="font-bold">All Database</div>';
$str .= '<div class="col-span-3"><u>Simmilar events</u> in database in the range of slider.</div>';
$str .= '</div>';
return new HtmlString($str);
}
protected function tooltip_player_info(): HtmlString
{
$str = '<div class="m-3 grid grid-cols-2 gap-2 max-w-lg">';
$str .= '<div class="col-span-2 font-bold">Player Information</div>';
$str .= '<div class="font-bold">Events played:</div>';
$str .= '<div>sum</div>';
$str .= '<div class="font-bold">Stronger foot:</div>';
$str .= '<div>left | right | both</div>';
$str .= '<div class="font-bold">Average on field:</div>';
$str .= '<div>minutes</div>';
$str .= '</div>';
return new HtmlString($str);
}
}