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 --}}
+
+
+
- @else
-
- @endif
- @endforeach
-
\ No newline at end of file
+
+
+ {{-- second row --}}
+
+
+
+
+
+
+
+ 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,