feat: implement comprehensive project management and client tracking portal with Filament integration
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Admin\Resources\Projects\Schemas;
|
||||
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Components\Tabs;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
use Filament\Schemas\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ProjectForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->schema([
|
||||
Tabs::make('ProjectTabs')
|
||||
->tabs([
|
||||
Tab::make('Proje Detayları & Müşteri')
|
||||
->icon('heroicon-m-briefcase')
|
||||
->schema([
|
||||
Section::make('Temel Proje Bilgileri')
|
||||
->columns(12)
|
||||
->schema([
|
||||
TextInput::make('title')
|
||||
->label('Proje Adı')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->live(onBlur: true)
|
||||
->afterStateUpdated(function (string $operation, $state, callable $set) {
|
||||
if ($operation !== 'create') return;
|
||||
$set('slug', Str::slug($state));
|
||||
})
|
||||
->columnSpan(6),
|
||||
|
||||
TextInput::make('slug')
|
||||
->label('URL Slug')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->unique(ignoreRecord: true)
|
||||
->rules(['alpha_dash'])
|
||||
->columnSpan(6),
|
||||
|
||||
TextInput::make('client_name')
|
||||
->label('Müşteri Unvanı / Firma')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->columnSpan(4),
|
||||
|
||||
TextInput::make('client_email')
|
||||
->label('Müşteri E-Posta')
|
||||
->email()
|
||||
->maxLength(255)
|
||||
->columnSpan(4),
|
||||
|
||||
TextInput::make('client_access_code')
|
||||
->label('Müşteri Giriş Şifresi / PIN')
|
||||
->default(fn () => strtoupper(Str::random(6)))
|
||||
->helperText('Müşterinin takip ekranına giriş yapabileceği şifre')
|
||||
->columnSpan(4),
|
||||
|
||||
Select::make('proposal_id')
|
||||
->label('İlişkili Fiyat Teklifi')
|
||||
->relationship('proposal', 'title')
|
||||
->searchable()
|
||||
->preload()
|
||||
->nullable()
|
||||
->live()
|
||||
->afterStateUpdated(function ($state, callable $set) {
|
||||
if ($state) {
|
||||
$prop = \App\Models\Proposal::find($state);
|
||||
if ($prop) {
|
||||
$set('slug', $prop->slug);
|
||||
}
|
||||
}
|
||||
})
|
||||
->columnSpan(4),
|
||||
|
||||
Select::make('status')
|
||||
->label('Proje Genel Durumu')
|
||||
->options([
|
||||
'planning' => 'Planlama Aşamasında',
|
||||
'in_progress' => 'Devam Ediyor (Aktif)',
|
||||
'on_hold' => 'Beklemeye Alındı',
|
||||
'completed' => 'Tamamlandı',
|
||||
'cancelled' => 'İptal Edildi',
|
||||
])
|
||||
->default('in_progress')
|
||||
->required()
|
||||
->columnSpan(4),
|
||||
|
||||
TextInput::make('progress_percent')
|
||||
->label('İlerleme Yüzdesi (%)')
|
||||
->numeric()
|
||||
->default(0)
|
||||
->suffix('%')
|
||||
->columnSpan(4),
|
||||
|
||||
DatePicker::make('start_date')
|
||||
->label('Proje Başlangıç Tarihi')
|
||||
->native(false)
|
||||
->displayFormat('d.m.Y')
|
||||
->columnSpan(6),
|
||||
|
||||
DatePicker::make('target_date')
|
||||
->label('Hedef Bitiş Tarihi')
|
||||
->native(false)
|
||||
->displayFormat('d.m.Y')
|
||||
->columnSpan(6),
|
||||
|
||||
Textarea::make('notes')
|
||||
->label('İç Notlar ve Açıklamalar')
|
||||
->rows(3)
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
]),
|
||||
|
||||
Tab::make('Hizmet Modülleri (% İlerleme)')
|
||||
->icon('heroicon-m-squares-2x2')
|
||||
->schema([
|
||||
Section::make('Sözleşme Kapsamındaki Modüller')
|
||||
->description('Hangi modüllerin tamamlandığını işaretleyin. İlerleme yüzdesi modül ağırlıklarına göre otomatik hesaplanır.')
|
||||
->schema([
|
||||
Repeater::make('modules')
|
||||
->relationship('modules')
|
||||
->columns(12)
|
||||
->orderColumn('order')
|
||||
->defaultItems(0)
|
||||
->schema([
|
||||
TextInput::make('title')
|
||||
->label('Modül Adı')
|
||||
->required()
|
||||
->columnSpan(4),
|
||||
|
||||
TextInput::make('weight_percent')
|
||||
->label('Ağırlık (%)')
|
||||
->numeric()
|
||||
->default(10)
|
||||
->suffix('%')
|
||||
->columnSpan(2),
|
||||
|
||||
Select::make('status')
|
||||
->label('Durum')
|
||||
->options([
|
||||
'pending' => 'Bekliyor',
|
||||
'in_progress' => 'Devam Ediyor',
|
||||
'completed' => 'Tamamlandı',
|
||||
])
|
||||
->default('pending')
|
||||
->required()
|
||||
->columnSpan(3),
|
||||
|
||||
DatePicker::make('start_date')
|
||||
->label('Başlangıç')
|
||||
->native(false)
|
||||
->columnSpan(1.5),
|
||||
|
||||
DatePicker::make('end_date')
|
||||
->label('Bitiş')
|
||||
->native(false)
|
||||
->columnSpan(1.5),
|
||||
])
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
]),
|
||||
|
||||
Tab::make('Kanban Görev Kartları')
|
||||
->icon('heroicon-m-view-columns')
|
||||
->schema([
|
||||
Section::make('İş Takvimi ve Görev Listesi')
|
||||
->description('Sözleşmedeki taskları ve detaylı görev kartlarını burada yönetin.')
|
||||
->schema([
|
||||
Repeater::make('tasks')
|
||||
->relationship('tasks')
|
||||
->columns(12)
|
||||
->orderColumn('order_index')
|
||||
->defaultItems(0)
|
||||
->schema([
|
||||
TextInput::make('title')
|
||||
->label('Görev Başlığı')
|
||||
->required()
|
||||
->columnSpan(4),
|
||||
|
||||
Select::make('status')
|
||||
->label('Kanban Durumu')
|
||||
->options([
|
||||
'todo' => 'Yapılacak',
|
||||
'in_progress' => 'Devam Ediyor',
|
||||
'review' => 'Kontrol Bekliyor',
|
||||
'done' => 'Tamamlandı',
|
||||
])
|
||||
->default('todo')
|
||||
->required()
|
||||
->columnSpan(3),
|
||||
|
||||
Select::make('priority')
|
||||
->label('Öncelik')
|
||||
->options([
|
||||
'low' => 'Düşük',
|
||||
'medium' => 'Orta',
|
||||
'high' => 'Yüksek',
|
||||
'urgent' => 'Acil',
|
||||
])
|
||||
->default('medium')
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('assigned_person')
|
||||
->label('Sorumlu')
|
||||
->columnSpan(3),
|
||||
])
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
]),
|
||||
|
||||
Tab::make('Gidişat Güncellemeleri Logu')
|
||||
->icon('heroicon-m-chat-bubble-bottom-center-text')
|
||||
->schema([
|
||||
Section::make('Canlı İlerleme Duyuruları')
|
||||
->description('Yazılım ekibi tarafından girilen ve müşterinin canlı izleyebildiği durum mesajları.')
|
||||
->schema([
|
||||
Repeater::make('updates')
|
||||
->relationship('updates')
|
||||
->columns(12)
|
||||
->defaultItems(0)
|
||||
->schema([
|
||||
TextInput::make('title')
|
||||
->label('Güncelleme Başlığı')
|
||||
->required()
|
||||
->columnSpan(6),
|
||||
|
||||
TextInput::make('progress_percent_at_update')
|
||||
->label('O Anki Yüzde (%)')
|
||||
->numeric()
|
||||
->columnSpan(3),
|
||||
|
||||
Checkbox::make('is_public')
|
||||
->label('Müşteriye Göster')
|
||||
->default(true)
|
||||
->columnSpan(3),
|
||||
|
||||
Textarea::make('content')
|
||||
->label('Güncelleme Notu / Sürüm Açıklaması')
|
||||
->required()
|
||||
->rows(2)
|
||||
->columnSpanFull(),
|
||||
])
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
]),
|
||||
])->columnSpanFull()
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user