Enhance Group and Document resources; add leader and helper teacher relationships, update navigation icons, and adjust navigation sorting.

This commit is contained in:
2025-08-30 17:21:47 +05:00
parent 18e425f533
commit 710554a28d
24 changed files with 760 additions and 11 deletions

View File

@@ -11,20 +11,23 @@ use App\Models\Document;
use BackedEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Contracts\Support\Htmlable;
class DocumentResource extends Resource
{
protected static ?string $model = Document::class;
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedRectangleStack;
protected static ?string $navigationLabel = 'Resminamalar';
protected static ?string $pluralLabel = 'Resminamalar';
protected static ?int $navigationSort = 3;
protected static ?int $navigationSort = 4;
public static function getNavigationIcon(): string | BackedEnum | Htmlable | null
{
return 'heroicon-o-document-text';
}
public static function form(Schema $schema): Schema
{

View File

@@ -12,7 +12,6 @@ use App\Models\Group;
use BackedEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Contracts\Support\Htmlable;
@@ -20,8 +19,6 @@ class GroupResource extends Resource
{
protected static ?string $model = Group::class;
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedRectangleStack;
protected static ?string $navigationLabel = 'Toparlar';
protected static ?string $pluralLabel = 'Toparlar';
@@ -32,7 +29,7 @@ class GroupResource extends Resource
public static function getNavigationIcon(): string | BackedEnum | Htmlable | null
{
return 'heroicon-o-user-group';
return 'icon-flight-takeoff';
}
public static function form(Schema $schema): Schema

View File

@@ -2,8 +2,10 @@
namespace App\Filament\Resources\Groups\Schemas;
use App\Models\Teacher;
use Carbon\Carbon;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
@@ -22,6 +24,19 @@ class GroupForm
DatePicker::make('end_date')
->label('Gutarýan senesi')
->required(),
Select::make('leader_teacher_id')
->label('Topar başy')
->options(Teacher::query()->pluck('name', 'id'))
->searchable()
->required(),
Select::make('helperTeachers')
->label('Topar kömekçileri')
->relationship('helperTeachers', 'name')
->multiple()
->searchable()
->preload(),
]);
}
}

View File

@@ -14,6 +14,11 @@ class GroupsTable
{
return $table
->columns([
TextColumn::make('leaderTeacher.name')
->label('Topar başy')
->searchable()
->sortable(),
TextColumn::make('start_date')
->label('Başlanýan senesi')
->date()

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Filament\Resources\Teachers\Pages;
use App\Filament\Resources\Teachers\TeacherResource;
use Filament\Resources\Pages\CreateRecord;
class CreateTeacher extends CreateRecord
{
protected static string $resource = TeacherResource::class;
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\Teachers\Pages;
use App\Filament\Resources\Teachers\TeacherResource;
use Filament\Actions\DeleteAction;
use Filament\Resources\Pages\EditRecord;
class EditTeacher extends EditRecord
{
protected static string $resource = TeacherResource::class;
protected function getHeaderActions(): array
{
return [
DeleteAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\Teachers\Pages;
use App\Filament\Resources\Teachers\TeacherResource;
use Filament\Actions\CreateAction;
use Filament\Resources\Pages\ListRecords;
class ListTeachers extends ListRecords
{
protected static string $resource = TeacherResource::class;
protected function getHeaderActions(): array
{
return [
CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Filament\Resources\Teachers\Schemas;
use Filament\Schemas\Schema;
class TeacherForm
{
public static function configure(Schema $schema): Schema
{
return $schema
->components([
//
]);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Filament\Resources\Teachers\Tables;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Tables\Table;
class TeachersTable
{
public static function configure(Table $table): Table
{
return $table
->columns([
//
])
->filters([
//
])
->recordActions([
EditAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace App\Filament\Resources\Teachers;
use App\Filament\Resources\Teachers\Pages\CreateTeacher;
use App\Filament\Resources\Teachers\Pages\EditTeacher;
use App\Filament\Resources\Teachers\Pages\ListTeachers;
use App\Models\Teacher;
use BackedEnum;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction as ActionsEditAction;
use Filament\Forms;
use Filament\Schemas\Schema;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Contracts\Support\Htmlable;
class TeacherResource extends Resource
{
protected static ?string $model = Teacher::class;
protected static ?string $navigationLabel = 'Mugallymlar';
protected static ?string $pluralLabel = 'Mugallymlar';
protected static ?string $recordTitleAttribute = 'name';
protected static ?int $navigationSort = 3;
public static function getNavigationIcon(): string | BackedEnum | Htmlable | null
{
return 'heroicon-o-user-group';
}
public static function form(Schema $schema): Schema
{
return $schema
->schema([
Forms\Components\TextInput::make('name')
->required()
->maxLength(255),
Forms\Components\FileUpload::make('photo')
->image(),
Forms\Components\Textarea::make('bio')
->columnSpanFull(),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\ImageColumn::make('photo')
->label('Surat')
->circular(),
Tables\Columns\TextColumn::make('name')
->label('Ady')
->searchable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->recordActions([
ActionsEditAction::make(),
])
->bulkActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => ListTeachers::route('/'),
'create' => CreateTeacher::route('/create'),
'edit' => EditTeacher::route('/{record}/edit'),
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreTeacherRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
//
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateTeacherRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
//
];
}
}

View File

@@ -3,11 +3,12 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Factories\HasFactory;
/**
* @property string $name
* @property date $start_date
* @property date $end_date
* @property Pilgrim[] $pilgrims
@@ -22,4 +23,14 @@ class Group extends Model
{
return $this->hasMany(Pilgrim::class);
}
public function leaderTeacher(): BelongsTo
{
return $this->belongsTo(Teacher::class, 'leader_teacher_id');
}
public function helperTeachers(): BelongsToMany
{
return $this->belongsToMany(Teacher::class, 'group_teacher');
}
}

24
app/Models/Teacher.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Teacher extends Model
{
/** @use HasFactory<\Database\Factories\TeacherFactory> */
use HasFactory;
public function ledGroups(): HasMany
{
return $this->hasMany(Group::class, 'leader_teacher_id');
}
public function assistedGroups(): BelongsToMany
{
return $this->belongsToMany(Group::class, 'group_teacher');
}
}

View File

@@ -39,7 +39,6 @@ class PanelPanelProvider extends PanelProvider
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\Filament\Widgets')
->widgets([
AccountWidget::class,
FilamentInfoWidget::class,
])
->middleware([
EncryptCookies::class,
@@ -54,6 +53,14 @@ class PanelPanelProvider extends PanelProvider
])
->authMiddleware([
Authenticate::class,
])
->colors([
'danger' => Color::Rose,
'gray' => Color::Gray,
'info' => Color::Blue,
'primary' => Color::Indigo,
'success' => Color::Emerald,
'warning' => Color::Orange,
]);
}
}

183
config/blade-icons.php Normal file
View File

@@ -0,0 +1,183 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Icons Sets
|--------------------------------------------------------------------------
|
| With this config option you can define a couple of
| default icon sets. Provide a key name for your icon
| set and a combination from the options below.
|
*/
'sets' => [
'default' => [
/*
|-----------------------------------------------------------------
| Icons Path
|-----------------------------------------------------------------
|
| Provide the relative path from your app root to your SVG icons
| directory. Icons are loaded recursively so there's no need to
| list every sub-directory.
|
| Relative to the disk root when the disk option is set.
|
*/
'path' => 'resources/svg',
/*
|-----------------------------------------------------------------
| Filesystem Disk
|-----------------------------------------------------------------
|
| Optionally, provide a specific filesystem disk to read
| icons from. When defining a disk, the "path" option
| starts relatively from the disk root.
|
*/
'disk' => '',
/*
|-----------------------------------------------------------------
| Default Prefix
|-----------------------------------------------------------------
|
| This config option allows you to define a default prefix for
| your icons. The dash separator will be applied automatically
| to every icon name. It's required and needs to be unique.
|
*/
'prefix' => 'icon',
/*
|-----------------------------------------------------------------
| Fallback Icon
|-----------------------------------------------------------------
|
| This config option allows you to define a fallback
| icon when an icon in this set cannot be found.
|
*/
'fallback' => '',
/*
|-----------------------------------------------------------------
| Default Set Classes
|-----------------------------------------------------------------
|
| This config option allows you to define some classes which
| will be applied by default to all icons within this set.
|
*/
'class' => '',
/*
|-----------------------------------------------------------------
| Default Set Attributes
|-----------------------------------------------------------------
|
| This config option allows you to define some attributes which
| will be applied by default to all icons within this set.
|
*/
'attributes' => [
// 'width' => 50,
// 'height' => 50,
],
],
],
/*
|--------------------------------------------------------------------------
| Global Default Classes
|--------------------------------------------------------------------------
|
| This config option allows you to define some classes which
| will be applied by default to all icons.
|
*/
'class' => '',
/*
|--------------------------------------------------------------------------
| Global Default Attributes
|--------------------------------------------------------------------------
|
| This config option allows you to define some attributes which
| will be applied by default to all icons.
|
*/
'attributes' => [
// 'width' => 50,
// 'height' => 50,
],
/*
|--------------------------------------------------------------------------
| Global Fallback Icon
|--------------------------------------------------------------------------
|
| This config option allows you to define a global fallback
| icon when an icon in any set cannot be found. It can
| reference any icon from any configured set.
|
*/
'fallback' => '',
/*
|--------------------------------------------------------------------------
| Components
|--------------------------------------------------------------------------
|
| These config options allow you to define some
| settings related to Blade Components.
|
*/
'components' => [
/*
|----------------------------------------------------------------------
| Disable Components
|----------------------------------------------------------------------
|
| This config option allows you to disable Blade components
| completely. It's useful to avoid performance problems
| when working with large icon libraries.
|
*/
'disabled' => false,
/*
|----------------------------------------------------------------------
| Default Icon Component Name
|----------------------------------------------------------------------
|
| This config option allows you to define the name
| for the default Icon class component.
|
*/
'default' => 'icon',
],
];

120
config/filament.php Normal file
View File

@@ -0,0 +1,120 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Broadcasting
|--------------------------------------------------------------------------
|
| By uncommenting the Laravel Echo configuration, you may connect Filament
| to any Pusher-compatible websockets server.
|
| This will allow your users to receive real-time notifications.
|
*/
'broadcasting' => [
// 'echo' => [
// 'broadcaster' => 'pusher',
// 'key' => env('VITE_PUSHER_APP_KEY'),
// 'cluster' => env('VITE_PUSHER_APP_CLUSTER'),
// 'wsHost' => env('VITE_PUSHER_HOST'),
// 'wsPort' => env('VITE_PUSHER_PORT'),
// 'wssPort' => env('VITE_PUSHER_PORT'),
// 'authEndpoint' => '/broadcasting/auth',
// 'disableStats' => true,
// 'encrypted' => true,
// 'forceTLS' => true,
// ],
],
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| This is the storage disk Filament will use to store files. You may use
| any of the disks defined in the `config/filesystems.php`.
|
*/
'default_filesystem_disk' => env('FILESYSTEM_DISK', 'local'),
/*
|--------------------------------------------------------------------------
| Assets Path
|--------------------------------------------------------------------------
|
| This is the directory where Filament's assets will be published to. It
| is relative to the `public` directory of your Laravel application.
|
| After changing the path, you should run `php artisan filament:assets`.
|
*/
'assets_path' => null,
/*
|--------------------------------------------------------------------------
| Cache Path
|--------------------------------------------------------------------------
|
| This is the directory that Filament will use to store cache files that
| are used to optimize the registration of components.
|
| After changing the path, you should run `php artisan filament:cache-components`.
|
*/
'cache_path' => base_path('bootstrap/cache/filament'),
/*
|--------------------------------------------------------------------------
| Livewire Loading Delay
|--------------------------------------------------------------------------
|
| This sets the delay before loading indicators appear.
|
| Setting this to 'none' makes indicators appear immediately, which can be
| desirable for high-latency connections. Setting it to 'default' applies
| Livewire's standard 200ms delay.
|
*/
'livewire_loading_delay' => 'default',
/*
|--------------------------------------------------------------------------
| File Generation
|--------------------------------------------------------------------------
|
| Artisan commands that generate files can be configured here by setting
| configuration flags that will impact their location or content.
|
| Often, this is useful to preserve file generation behavior from a
| previous version of Filament, to ensure consistency between older and
| newer generated files. These flags are often documented in the upgrade
| guide for the version of Filament you are upgrading to.
|
*/
'file_generation' => [
'flags' => [],
],
/*
|--------------------------------------------------------------------------
| System Route Prefix
|--------------------------------------------------------------------------
|
| This is the prefix used for the system routes that Filament registers,
| such as the routes for downloading exports and failed import rows.
|
*/
'system_route_prefix' => 'filament',
];

View File

@@ -0,0 +1,24 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Teacher>
*/
class TeacherFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->name(),
'bio' => $this->faker->paragraph(),
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('teachers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('photo')->nullable();
$table->text('bio')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('teachers');
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('groups', function (Blueprint $table) {
$table->foreignId('leader_teacher_id')->nullable()->constrained('teachers')->nullOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('groups', function (Blueprint $table) {
$table->dropForeign(['leader_teacher_id']);
$table->dropColumn('leader_teacher_id');
});
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('group_teacher', function (Blueprint $table) {
$table->id();
$table->foreignId('group_id')->constrained()->cascadeOnDelete();
$table->foreignId('teacher_id')->constrained()->cascadeOnDelete();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('group_teacher');
}
};

View File

@@ -11,8 +11,9 @@ class DatabaseSeeder extends Seeder
*/
public function run(): void
{
// User::factory(10)->create();
$this->call([
UserTableSeeder::class,
TeacherSeeder::class,
]);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Database\Seeders;
use App\Models\Teacher;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class TeacherSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Teacher::factory(10)->create();
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M120-120v-80h720v80H120Zm70-200L40-570l96-26 112 94 140-37-207-276 116-31 299 251 170-46q32-9 60.5 7.5T864-585q9 32-7.5 60.5T808-487L190-320Z"/></svg>

After

Width:  |  Height:  |  Size: 271 B