diff --git a/app/Filament/Pages/Statistic.php b/app/Filament/Pages/Statistic.php index 2a6d3137..ccf30e21 100644 --- a/app/Filament/Pages/Statistic.php +++ b/app/Filament/Pages/Statistic.php @@ -17,7 +17,6 @@ use Filament\Forms\Components\Hidden; use Filament\Forms\Components\Radio; use Filament\Forms\Components\Select; use Filament\Forms\Components\Slider; -use Filament\Forms\Components\ToggleButtons; use Filament\Pages\Dashboard as BaseDashboard; use Filament\Pages\Dashboard\Concerns\HasFiltersForm; use Filament\Schemas\Components\Grid; @@ -89,72 +88,16 @@ class Statistic extends BaseDashboard ->keyBindings(['esc']) ->action('resetFilters'), Action::make('calculator') - // ->modalHeading('') + ->modalHeading('') ->modalSubmitAction(false) // Hides the submit button ->modalCancelAction(false) // Optional: hides the cancel button too ->label('Calculate') ->icon('icon-player') - ->color(fn (): string => $this->filters['team_id'] ? 'primary' : 'gray') - ->disabled(fn (): string => $this->filters['team_id'] ? false : true) + ->color(fn(): string => $this->filters['team_id'] ? 'primary' : 'gray') + ->disabled(fn(): string => $this->filters['team_id'] ? false : true) ->slideOverPosition(SlideOverPosition::Start) - ->modalWidth(Width::SevenExtraLarge) + ->modalWidth(Width::SixExtraLarge) ->slideOver() - ->schema([ - Grid::make(2) - ->extraAttributes([ - 'class' => 'justify-between w-full gap-4', - ]) - ->schema([ - ToggleButtons::make('status') - ->live() - ->hiddenLabel() - ->multiple() - ->inline() - ->default('attack') - ->options([ - 'attack' => 'Attack', - 'midfield' => 'Midfield', - 'defence' => 'Defence', - 'goalkeeper' => 'Goalkeeper', - ]) - ->colors([ - 'attack' => 'warning', - 'midfield' => 'info', - 'defence' => 'success', - 'goalkeeper' => 'gray', - ]) - ->afterStateUpdated(function (ToggleButtons $component, $state, $livewire) { - // 1. Fetch the enabled options array - $livewireComponent = $component->getLivewire(); - $data = json_encode($livewireComponent->mountedActions); - $livewire->js('toggle_type(\''.$data.'\')'); - - }), - Grid::make(5) - ->schema([ - Action::make('restart') - ->extraAttributes([ - 'class' => 'w-30', - ]) - ->color('warning') - ->icon('phosphor-arrow-counter-clockwise'), - Action::make('copy') - ->extraAttributes([ - 'class' => 'w-30', - ]) - ->color('success') - ->icon('phosphor-copy'), - Action::make('calculate') - ->extraAttributes([ - 'class' => 'w-30', - ]) - ->icon('phosphor-calculator'), - ]) - ->extraAttributes([ - 'class' => 'flex justify-center items-center gap-0', - ]), - ]), - ]) ->modalContentFooter(view('filament.modals.player-calculator-modal', ['filters' => $this->filters])), ]; } @@ -193,10 +136,10 @@ class Statistic extends BaseDashboard ->live() ->preload() ->searchable(false) - ->prefixIconColor(fn (Get $get): string => $get('sofascore_category_id') ? 'success' : 'danger') + ->prefixIconColor(fn(Get $get): string => $get('sofascore_category_id') ? 'success' : 'danger') ->prefixIcon('phosphor-globe-fill') ->hiddenLabel() - ->options(fn () => LoadSofaScoreCategory::load()) + ->options(fn() => LoadSofaScoreCategory::load()) ->placeholder('Country') ->afterStateUpdated(function (callable $set, $state) { $set('seasonmode', SofaScoreCategory::where('id', $state)->value('season_mode')); @@ -209,10 +152,10 @@ class Statistic extends BaseDashboard Select::make('league_id') ->live() ->preload() - ->prefixIconColor(fn (Get $get): string => $get('league_id') ? 'success' : 'danger') + ->prefixIconColor(fn(Get $get): string => $get('league_id') ? 'success' : 'danger') ->prefixIcon('phosphor-trophy-fill') ->hiddenLabel() - ->options(fn (Get $get) => LoadStatisticFixturesLeaguesOptions::load($get('sofascore_category_id'))) + ->options(fn(Get $get) => LoadStatisticFixturesLeaguesOptions::load($get('sofascore_category_id'))) ->placeholder('League') ->afterStateUpdated(function (callable $set) { $set('match_id', null); @@ -223,7 +166,7 @@ class Statistic extends BaseDashboard Select::make('match_id') ->live() ->hiddenLabel() - ->prefixIconColor(fn (Get $get): string => $get('match_id') ? 'success' : 'danger') + ->prefixIconColor(fn(Get $get): string => $get('match_id') ? 'success' : 'danger') ->prefixIcon('phosphor-calendar-check-fill') ->options(function (Get $get) { return LoadStatisticFixturesMatchOptions::load($get('league_id')); @@ -248,7 +191,7 @@ class Statistic extends BaseDashboard } }) ->prefixIcon('phosphor-users-three-fill') - ->hidden(fn (Get $get) => $get('similar_past_matches') != 'none') + ->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(); @@ -277,9 +220,9 @@ class Statistic extends BaseDashboard Action::make('iconInfo') ->color('success') ->icon('phosphor-question-fill') - ->tooltip(fn () => 'Team Position') + ->tooltip(fn() => 'Team Position') ) - ->hidden(fn (Get $get) => $get('similar_past_matches') != 'none') + ->hidden(fn(Get $get) => $get('similar_past_matches') != 'none') ->default('all') ->selectablePlaceholder(false) ->options([ @@ -335,17 +278,17 @@ class Statistic extends BaseDashboard ->hiddenLabel() ->suffixAction(Action::make('reset') ->icon('phosphor-x-circle') - ->action(fn (callable $set) => $set('similar_past_matches', 'none')) - ->color(fn (Get $get): string => $get('similar_past_matches') != 'none' ? 'info' : 'gray')) + ->action(fn(callable $set) => $set('similar_past_matches', 'none')) + ->color(fn(Get $get): string => $get('similar_past_matches') != 'none' ? 'info' : 'gray')) ->placeholder('Similar Past Matches') - ->suffix(fn (Get $get): string|HtmlString => $get('similar_past_matches') != 'none' ? new HtmlString('
± '.$get('accuracy').'
') : '') + ->suffix(fn(Get $get): string|HtmlString => $get('similar_past_matches') != 'none' ? new HtmlString('
± ' . $get('accuracy') . '
') : '') ->prefix('SPM') ->prefixAction( Action::make('iconInfo') ->icon('phosphor-question-fill') // ->color(fn(Get $get): string => $get('similar_past_matches') != 'none' ? 'success' : 'primary') ->color('success') - ->tooltip(fn () => $this->tooltip_similar_past_matches()) + ->tooltip(fn() => $this->tooltip_similar_past_matches()) ) ->default('none') ->selectablePlaceholder(false) @@ -365,7 +308,7 @@ class Statistic extends BaseDashboard Slider::make('accuracy') ->live() ->hiddenLabel() - ->hidden(fn (Get $get) => $get('similar_past_matches') == 'none') + ->hidden(fn(Get $get) => $get('similar_past_matches') == 'none') ->fillTrack() ->minValue(0) ->maxValue(0.25) @@ -384,17 +327,17 @@ class Statistic extends BaseDashboard ->hiddenLabel() ->allowHtml() ->placeholder('Player') - ->hidden(fn (Get $get) => $get('similar_past_matches') != 'none') - ->prefixIconColor(fn (Get $get): string => $get('similar_past_matches') == 'none' ? 'success' : '') + ->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']) + ->extraAttributes(fn() => ['id' => 'player_selector']) ->suffixAction( Action::make('iconInfo') ->icon('phosphor-question-fill') ->color('success') - ->tooltip(fn () => $this->tooltip_player_info()) + ->tooltip(fn() => $this->tooltip_player_info()) ) ->options(function (Get $get) { $team_id = $get('team_id'); @@ -411,7 +354,7 @@ class Statistic extends BaseDashboard ->placeholder('Time on field') ->prefixIcon('phosphor-watch-fill') ->default('all') - ->hidden(fn (Get $get) => ! $get('ss_player_id')) + ->hidden(fn(Get $get) => ! $get('ss_player_id')) ->prefixIconColor('success') ->selectablePlaceholder(false) ->options([ @@ -431,7 +374,7 @@ class Statistic extends BaseDashboard ->extraAttributes([ 'class' => 'radio-statistic-group', ]) - ->hidden(fn (Get $get) => $get('similar_past_matches') != 'none') + ->hidden(fn(Get $get) => $get('similar_past_matches') != 'none') ->columnSpan([ 'default' => 4, 'sm' => 4, @@ -455,7 +398,7 @@ class Statistic extends BaseDashboard ->multiple() ->placeholder('Current Season') ->prefixIconColor('success') - ->hidden(fn (Get $get) => $get('seasonmode') == 'halfyear' || $get('season_or_date') == 'date' || $get('similar_past_matches') != 'none') + ->hidden(fn(Get $get) => $get('seasonmode') == 'halfyear' || $get('season_or_date') == 'date' || $get('similar_past_matches') != 'none') ->prefixIcon('phosphor-calendar-star-fill') ->options([ '2026' => '2026', @@ -475,7 +418,7 @@ class Statistic extends BaseDashboard ->multiple() ->placeholder('Current Season') ->prefixIconColor('success') - ->hidden(fn (Get $get) => $get('seasonmode') == 'fullyear' || $get('season_or_date') == 'date' || $get('similar_past_matches') != 'none') + ->hidden(fn(Get $get) => $get('seasonmode') == 'fullyear' || $get('season_or_date') == 'date' || $get('similar_past_matches') != 'none') ->prefixIcon('phosphor-calendar-star-fill') ->options([ '26/27' => '26/27', @@ -491,30 +434,30 @@ class Statistic extends BaseDashboard DatePicker::make('start_date') ->live() ->hiddenLabel() - ->hidden(fn (Get $get) => $get('season_or_date') == 'season') + ->hidden(fn(Get $get) => $get('season_or_date') == 'season') ->native(false) - ->prefixIconColor(fn (Get $get): string => $get('start_date') ? 'success' : 'primary') + ->prefixIconColor(fn(Get $get): string => $get('start_date') ? 'success' : 'primary') ->prefixIcon('phosphor-calendar-fill') ->prefix('Start') ->suffixAction( Action::make('clear_start') ->icon('phosphor-x') ->color('gray') - ->action(fn (Set $set) => $set('start_date', null)) + ->action(fn(Set $set) => $set('start_date', null)) ), DatePicker::make('end_date') ->live() ->hiddenLabel() - ->hidden(fn (Get $get) => $get('season_or_date') == 'season') + ->hidden(fn(Get $get) => $get('season_or_date') == 'season') ->native(false) - ->prefixIconColor(fn (Get $get): string => $get('end_date') ? 'success' : 'primary') + ->prefixIconColor(fn(Get $get): string => $get('end_date') ? 'success' : 'primary') ->prefixIcon('phosphor-calendar-fill') ->prefix('End') ->suffixAction( Action::make('clear_end') ->icon('phosphor-x') ->color('gray') - ->action(fn (Set $set) => $set('end_date', null)) + ->action(fn(Set $set) => $set('end_date', null)) ), ]); } diff --git a/app/Livewire/PlayerCalculator.php b/app/Livewire/PlayerCalculator.php index 45bc3f60..394641c9 100644 --- a/app/Livewire/PlayerCalculator.php +++ b/app/Livewire/PlayerCalculator.php @@ -4,7 +4,6 @@ namespace App\Livewire; use App\Filament\Pages\Selections\Helper\GetSeason; use App\Filament\Pages\Selections\LoadPositions; -use App\Livewire\Mapper\LoadGridPositions; use App\Models\SofaScorePlayerPerSeason; use App\Models\StatistikoEvent; use Filament\Widgets\Concerns\InteractsWithPageFilters; @@ -14,41 +13,11 @@ class PlayerCalculator extends Component { use InteractsWithPageFilters; - public $grid = []; + public $players = []; public function mount(array $filters) { - $pos = array_chunk(LoadGridPositions::load(), 5); - $pla = array_chunk(self::load($filters), 5); - - $i = 1; - while ($v = array_shift($pos)) { - array_splice($pla, $i, 0, [$v]); - $i += 2; - } - $x = 1; - $y = 1; - foreach ($pla as $ele) { - foreach ($ele as $val) { - $tmp = []; - if (is_array($val)) { - foreach ($val as $key => $value) { - $tmp[$key] = $value; - } - $tmp['type'] = ''; - } else { - $tmp['type'] = $val != 0 ? $val : ''; - } - $tmp['x'] = 104 * $x; - $tmp['y'] = 104 * $y; - $this->grid[] = $tmp; - $x++; - if ($x > 10) { - $x = 1; - $y++; - } - } - } + $this->players = self::load($filters); } public static function load(array $filters) @@ -137,7 +106,7 @@ class PlayerCalculator extends Component $name = $val['player_name']; $preferred_foot = $val['preferred_foot'] ?? '-'; - $everage_minutes = round($minues_played / $events_played).' min'; + $everage_minutes = round($minues_played / $events_played) . ' min'; if ($colorlevel > 1 && $events_played < $colorlevel) { $color = 'danger'; } elseif ($events_played < $colorlevel * 2) { @@ -148,20 +117,14 @@ class PlayerCalculator extends Component $result[] = [ 'player_id' => $player_id, - 'name' => $name, + 'player_name' => $name, 'position' => $position, 'position_color' => $position_color, 'color' => $color, - 'info' => 'Ev '.$events_played.', '.$preferred_foot.', '.$everage_minutes, + 'info' => 'Ev ' . $events_played . ', ' . $preferred_foot . ', ' . $everage_minutes, ]; } - $maxlength = 35; - $len = count($result); - if ($len < $maxlength) { - $result += array_fill($len, $maxlength - $len, [0, 0, 0, 0, 0, 0, 0]); - } - return $result; } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 78873152..2682b7d5 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,7 +2,6 @@ namespace App\Providers; -use App\Filament\Pages\Statistic; use App\Filament\Resources\Events\Pages\ListEvents; use Carbon\Carbon; use Filament\Support\Assets\Css; @@ -38,9 +37,8 @@ class AppServiceProvider extends ServiceProvider FilamentAsset::register([ Css::make('font-stylesheet', __DIR__ . '/../../resources/css/font.css'), - Js::make('example-external-script', 'https://cdn.jsdelivr.net/npm/interactjs@latest'), Js::make('number-animator', __DIR__ . '/../../resources/js/number-animator.js'), - Js::make('dragndrop', __DIR__ . '/../../resources/js/dragndrop.js'), + Js::make('dragndrop', __DIR__ . '/../../resources/js/dragndrop-store.js'), ]); FilamentView::registerRenderHook( diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index fdaa0a97..da2e346d 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -2,7 +2,6 @@ namespace App\Providers\Filament; -use Agencetwogether\HooksHelper\HooksHelperPlugin; use App\Filament\Exports\BetfairExporter; use App\Filament\Pages\Statistic; use App\Http\Middleware\RecordUserActivity; @@ -21,6 +20,8 @@ use Filament\Http\Middleware\DisableBladeIconComponents; use Filament\Http\Middleware\DispatchServingFilamentEvent; use Filament\Panel; use Filament\PanelProvider; +use Filament\Support\Assets\Css; +use Filament\Support\Assets\Js; use Filament\Support\Enums\Width; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; use Illuminate\Cookie\Middleware\EncryptCookies; @@ -29,6 +30,7 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken; use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\Session\Middleware\StartSession; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Vite; use Illuminate\View\Middleware\ShareErrorsFromSession; use Joaopaulolndev\FilamentEditProfile\FilamentEditProfilePlugin; use Joaopaulolndev\FilamentEditProfile\Pages\EditProfilePage; @@ -46,6 +48,11 @@ class AdminPanelProvider extends PanelProvider ->middleware([ RecordUserActivity::class, ]) + ->assets([ + // Point directly to the source files on disk relative to this provider + Css::make('dragula-css', base_path('resources/js/filament-dragula.js')), // Vite extracts CSS imported here + Js::make('filament-dragula', Vite::asset('resources/js/filament-dragula.js'))->module(), + ]) ->userMenuItems([ ExportAction::make('download_betfair') ->columnMapping(false) diff --git a/composer.lock b/composer.lock index 26198244..cb9b75df 100644 --- a/composer.lock +++ b/composer.lock @@ -4705,24 +4705,24 @@ }, { "name": "mongodb/mongodb", - "version": "2.3.0", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/mongodb/mongo-php-library", - "reference": "12e56461166d915e3dd8e4969ad0940ed5207d88" + "url": "https://github.com/mongodb/mongo-php-library.git", + "reference": "bbb13f969e37e047fd822527543df55fdc1c9298" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/12e56461166d915e3dd8e4969ad0940ed5207d88", - "reference": "12e56461166d915e3dd8e4969ad0940ed5207d88", + "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/bbb13f969e37e047fd822527543df55fdc1c9298", + "reference": "bbb13f969e37e047fd822527543df55fdc1c9298", "shasum": "" }, "require": { "composer-runtime-api": "^2.0", - "ext-mongodb": "^2.3", + "ext-mongodb": "^2.2", "php": "^8.1", "psr/log": "^1.1.4|^2|^3", - "symfony/polyfill-php85": "^1.33" + "symfony/polyfill-php85": "^1.32" }, "replace": { "mongodb/builder": "*" @@ -4774,7 +4774,11 @@ "mongodb", "persistence" ], - "time": "2026-04-28T12:50:06+00:00" + "support": { + "issues": "https://github.com/mongodb/mongo-php-library/issues", + "source": "https://github.com/mongodb/mongo-php-library/tree/2.2.0" + }, + "time": "2026-02-11T11:39:56+00:00" }, { "name": "monolog/monolog", diff --git a/package-lock.json b/package-lock.json index a8294c4a..31a9d9f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,10 @@ "requires": true, "packages": { "": { + "dependencies": { + "dragula": "^3.7.3", + "prettier-plugin-blade": "^3.3.2" + }, "devDependencies": { "@tailwindcss/vite": "^4.1.11", "axios": "^1.11.0", @@ -526,6 +530,18 @@ "node": "^22.20 || ^24.12 || >=25" } }, + "node_modules/@prettier/html-tags": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@prettier/html-tags/-/html-tags-2.2.0.tgz", + "integrity": "sha512-6qLjt8ncestmSfEOeVf/kX5VhkinUsppybvkwn1X7wu+BjQ/GBSZYu7cytxdCvi5BaljCGIAr4rmfL5zVqdgyQ==", + "license": "MIT" + }, + "node_modules/@prettier/parse-srcset": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@prettier/parse-srcset/-/parse-srcset-3.1.0.tgz", + "integrity": "sha512-FIRv2rZotO9NP/r66taYqD1zICpPiBbrECqjKV/xqNotqDxF7fLzzUeK+1RSRx9Tenk0DajR/GcRmTJ2qtHaKQ==", + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.63.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.1.tgz", @@ -1252,6 +1268,12 @@ "dev": true, "license": "MIT" }, + "node_modules/atoa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atoa/-/atoa-1.0.0.tgz", + "integrity": "sha512-VVE1H6cc4ai+ZXo/CRWoJiHXrA1qfA31DPnx6D20+kSI547hQN5Greh51LQ1baMRMfxO5K5M4ImMtZbZt2DODQ==", + "license": "MIT" + }, "node_modules/axios": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz", @@ -1382,6 +1404,31 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, + "node_modules/contra": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/contra/-/contra-1.9.4.tgz", + "integrity": "sha512-N9ArHAqwR/lhPq4OdIAwH4e1btn6EIZMAz4TazjnzCiVECcWUPTma+dRAM38ERImEJBh8NiCCpjoQruSZ+agYg==", + "license": "MIT", + "dependencies": { + "atoa": "1.0.0", + "ticky": "1.0.1" + } + }, + "node_modules/crossvent": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/crossvent/-/crossvent-1.5.5.tgz", + "integrity": "sha512-MY4xhBYEnVi+pmTpHCOCsCLYczc0PVtGdPBz6NXNXxikLaUZo4HdAeUb1UqAo3t3yXAloSelTmfxJ+/oUqkW5w==", + "license": "MIT", + "dependencies": { + "custom-event": "^1.0.0" + } + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1420,6 +1467,16 @@ "node": ">=8" } }, + "node_modules/dragula": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/dragula/-/dragula-3.7.3.tgz", + "integrity": "sha512-/rRg4zRhcpf81TyDhaHLtXt6sEywdfpv1cRUMeFFy7DuypH2U0WUL0GTdyAQvXegviT4PJK4KuMmOaIDpICseQ==", + "license": "MIT", + "dependencies": { + "contra": "1.9.4", + "crossvent": "1.5.5" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1759,6 +1816,16 @@ "node": ">= 0.4" } }, + "node_modules/html-element-attributes": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/html-element-attributes/-/html-element-attributes-3.5.0.tgz", + "integrity": "sha512-rU2BFhp0kQla9sqPBI46C+zbP6PFOtD7z6XNAJ6as+cGecCDXLx0W3aIs6XdPLmBBG/Fy1meRi/n65Exofz4Qw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -2204,6 +2271,49 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-blade": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-blade/-/prettier-plugin-blade-3.3.2.tgz", + "integrity": "sha512-bw5bWD+C0Xj1jd+wcOcU5fh4EVtD0ZzWKeEL276kmA5j7k2KfX5lGQgj/C+SFU9Ga4PcoOdJ7k9dJUCC5DkoNQ==", + "license": "MIT", + "dependencies": { + "@prettier/html-tags": "^2.2.0", + "@prettier/parse-srcset": "^3.1.0", + "html-element-attributes": "^3.5.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@prettier/plugin-php": "^0.24.0 || ^0.25.0", + "prettier": "^3.0.0", + "prettier-plugin-tailwindcss": "^0.7.0 || ^0.8.0" + }, + "peerDependenciesMeta": { + "@prettier/plugin-php": { + "optional": true + }, + "prettier-plugin-tailwindcss": { + "optional": true + } + } + }, "node_modules/proxy-from-env": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", @@ -2368,6 +2478,12 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/ticky": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ticky/-/ticky-1.0.1.tgz", + "integrity": "sha512-RX35iq/D+lrsqhcPWIazM9ELkjOe30MSeoBHQHSsRwd1YuhJO5ui1K1/R0r7N3mFvbLBs33idw+eR6j+w6i/DA==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", diff --git a/package.json b/package.json index 9bd2a6ff..bffc6114 100644 --- a/package.json +++ b/package.json @@ -19,5 +19,9 @@ "esbuild@0.25.12": true, "fsevents@2.3.3": true, "esbuild@0.28.2": true + }, + "dependencies": { + "dragula": "^3.7.3", + "prettier-plugin-blade": "^3.3.2" } } diff --git a/resources/css/filament/admin/theme.css b/resources/css/filament/admin/theme.css index e019db10..4448f4f6 100644 --- a/resources/css/filament/admin/theme.css +++ b/resources/css/filament/admin/theme.css @@ -235,12 +235,45 @@ less padding in table } } -.chessboard { - background-position: top right; - background-size: 512px auto; - background-repeat: no-repeat; +/* 1. Das Element, das am Mauszeiger klebt (Der Mirror) */ +.gu-mirror { + position: fixed !important; + margin: 0 !important; + z-index: 9999 !important; + opacity: 0.95 !important; + pointer-events: none; + /* Verhindert, dass der Klon Maus-Events blockiert */ + + /* Styling für den Klon (Hell-Modus) */ + background-color: rgb(255, 255, 255) !important; + border: 1px solid rgb(226, 232, 240) !important; + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 10px 10px -5px rgba(0, 0, 0, 0.04) !important; + border-radius: 0.5rem !important; + transform: rotate(3deg); + /* Optionale leichte Drehung für einen dynamischen Look */ + transition: transform 0.15s ease; } -.piece:active { - @apply cursor-grabbing drop-shadow border +/* Dark Mode Anpassung für den Mirror (Wichtig in Filament!) */ +.dark .gu-mirror { + background-color: rgb(31, 41, 55) !important; + border-color: rgb(55, 65, 81) !important; + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5) !important; +} + +/* 2. Der „Schatten“ am ursprünglichen Platz (Transit-Element) */ +.gu-transit { + opacity: 0.3 !important; + border: 2px dashed rgb(99, 102, 241) !important; + /* Indigo-farbener gestrichelter Rahmen */ + background-color: rgba(99, 102, 241, 0.05) !important; +} + +.dark .gu-transit { + background-color: rgba(99, 102, 241, 0.1) !important; +} + +/* 3. Sicherstellen, dass die Dropzones Platz für das Element bieten */ +.drag-box { + @apply flex flex-col gap-0 size-24 bg-gray-100/50 border-2 border-dashed border-gray-300 rounded-xl text-xs p-0; } \ No newline at end of file diff --git a/resources/js/dragndrop-store.js b/resources/js/dragndrop-store.js new file mode 100644 index 00000000..47f19fb6 --- /dev/null +++ b/resources/js/dragndrop-store.js @@ -0,0 +1,44 @@ +document.addEventListener("alpine:init", () => { + Alpine.store("main", { + attack: true, + midfield: true, + defence: true, + goalkeeper: true, + players: [], + groups: [], + toggleAttack() { + this.attack = !this.attack; + // Loop through them and add Tailwind's invisible class + elements.forEach((el) => el.classList.add("invisible")); + }, + console(index) { + console.log(this.players[index].player_id); + var p = this.players[index].player_id; + }, + loadPlayer(data) { + this.players = data; + }, + setPosGroup(group) { + this.groups = group; + console.log(this.groups, group); + }, + hasVisible(type) { + console.log(type); + return true; + }, + toggleType(toggleStates) { + var toggleState = toggleStates; + // var toggleState = JSON.parse(mode); + // this.visa = toggleState[0].data.status; + // console.log(this.visabilities); + }, + findByPlayerId(player_id) { + const index = this.items.findIndex( + (item) => item.player_id === player_id, + ); + if (index > -1) { + return item; + } + }, + }); +}); diff --git a/resources/js/dragndrop.js b/resources/js/dragndrop.js deleted file mode 100644 index e7cafcdf..00000000 --- a/resources/js/dragndrop.js +++ /dev/null @@ -1,69 +0,0 @@ -interact(".piece").draggable({ - modifiers: [ - interact.modifiers.snap({ - targets: [ - // 1. Match the grid to your square sizes (50px x 50px) - interact.snappers.grid({ x: 104, y: 104 }), - ], - range: Infinity, - // 2. Snap by the top-left corner (0,0) of the piece to align with square borders - relativePoints: [{ x: 0, y: 0 }], - // 3. Keep the element constrained within the 400x400 board boundaries - offset: "parent", - }), - interact.modifiers.restrictRect({ - restriction: "parent", - endOnly: false, - }), - ], - - listeners: { - move(event) { - const target = event.target; - const x = - (parseFloat(target.getAttribute("data-x")) || 0) + event.dx; - const y = - (parseFloat(target.getAttribute("data-y")) || 0) + event.dy; - - console.log("console", x, y); - - target.style.transform = `translate(${x}px, ${y}px)`; - - target.setAttribute("data-x", x); - target.setAttribute("data-y", y); - }, - end(event) { - // Optional: Calculate and log the final algebraic notation (e.g., e4, a1) - const target = event.target; - const currentX = - (parseFloat(target.getAttribute("data-x")) || 0) + 200; // Adding initial left offset - const currentY = - (parseFloat(target.getAttribute("data-y")) || 0) + 200; // Adding initial top offset - - const files = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "k"]; - const fileIndex = Math.floor(currentX / 50); - const rankIndex = 8 - Math.floor(currentY / 50); - - if (files[fileIndex] && rankIndex >= 1 && rankIndex <= 8) { - console.log(`Piece landed on: ${files[fileIndex]}${rankIndex}`); - } - }, - }, -}); - -function toggle_type(mode) { - console.log(mode); -} - - -document.addEventListener("alpine:init", () => { - Alpine.store("main", { - players: [], - console(index) { - console.log(this.players[index]); - }, - loadPlayer(data) { - this.players = data; - } - }); -}); \ No newline at end of file diff --git a/resources/js/filament-dragula.js b/resources/js/filament-dragula.js new file mode 100644 index 00000000..dbc7fcf8 --- /dev/null +++ b/resources/js/filament-dragula.js @@ -0,0 +1,6 @@ +import dragula from "dragula"; +import "dragula/dist/dragula.css"; + +document.addEventListener("alpine:init", () => { + window.dragula = dragula; +}); diff --git a/resources/views/livewire/player-calculator.blade.php b/resources/views/livewire/player-calculator.blade.php index c8927a26..54508cf4 100644 --- a/resources/views/livewire/player-calculator.blade.php +++ b/resources/views/livewire/player-calculator.blade.php @@ -1,51 +1,71 @@ -@php - use Illuminate\Support\HtmlString; -@endphp + +
+ if (allContainers.length === 0) return; - {{-- 0 => array:9 [▼ - "player_id" => 789695 - "name" => "Favio Álvarez" - "position" => "MIDFIELD" - "position_color" => "info" - "color" => "info" - "info" => "Ev 3, Right, 8 min" - "type" => "" - "x" => 104 - "y" => 104 + // Dragula initialisieren + const drake = dragula(Array.from(allContainers), { + revertOnSpill: true, + copy: false + }); - 7 => array:3 [▼ - "type" => "ST" - "x" => 832 - "y" => 104 - ] - ] --}} + // Drop-Event verarbeiten + drake.on('drop', (el, target, source) => { + const playerId = el.getAttribute('data-item-id'); + const targetZone = target.getAttribute('data-container-id'); + const sourceZone = source.getAttribute('data-container-id'); - @foreach ($grid as $key => $ele) + console.log('Spieler ' + playerId + ' von ' + sourceZone + ' nach ' + targetZone); - @if(isset($ele['player_id'])) - -
{{ $ele['position'] }}
- {{ $ele['name'] }} + + {{-- If the item lands in the "trash" zone, remove it entirely + if (targetZone === 'trash') { + el.remove(); + } + --}} + }); + }); + } +}" class="grid grid-cols-12 gap-1"> +
+ @foreach ($players as $player) + + ⚽️ {{ $player['player_name'] }} - @elseif($ele['type']) -
-
- {{ $ele['type'] }} -
+ @endforeach +
+ +
+
+ {{-- first row --}} +
+
+
+
SW
- @else -
- @endif - @endforeach -
\ No newline at end of file +
+
+ {{-- second row --}} +
+
DR
+
+
+
DC
+
+
+
DC
+
+
+
DC
+
+
+
DL
+
+
+
+
Actions
+
diff --git a/vite.config.js b/vite.config.js index 4de10272..86bd4bc8 100644 --- a/vite.config.js +++ b/vite.config.js @@ -8,6 +8,7 @@ export default defineConfig({ input: [ "resources/css/app.css", "resources/js/app.js", + "resources/js/filament-dragula.js", "resources/css/filament/admin/theme.css", ], refresh: true,