55namespace Relaticle \Flowforge \Adapters ;
66
77use DB ;
8+ use Filament \Forms \Components \DatePicker ;
9+ use Filament \Forms \Components \Hidden ;
10+ use Filament \Forms \Components \Section ;
11+ use Filament \Forms \Components \Select ;
12+ use Filament \Forms \Components \Textarea ;
13+ use Filament \Forms \Components \TextInput ;
14+ use Filament \Forms \Form ;
815use Illuminate \Database \Eloquent \Model ;
916use Illuminate \Support \Collection ;
1017use Illuminate \Support \Str ;
@@ -62,6 +69,14 @@ class DefaultKanbanAdapter implements IKanbanAdapter, Wireable
6269 */
6370 protected string $ modelClass ;
6471
72+
73+ /**
74+ * The create form callable for the model.
75+ *
76+ * @var callable|null
77+ */
78+ protected mixed $ createFormCallable = null ;
79+
6580 /**
6681 * The singular label for the model.
6782 *
@@ -97,6 +112,7 @@ public function __construct(
97112 ?string $ descriptionAttribute = null ,
98113 array $ cardAttributes = [],
99114 ?string $ orderField = null ,
115+ ?callable $ createFormCallable = null ,
100116 ?string $ recordLabel = null ,
101117 ?string $ pluralRecordLabel = null
102118 )
@@ -109,6 +125,8 @@ public function __construct(
109125 $ this ->cardAttributes = $ cardAttributes ;
110126 $ this ->orderField = $ orderField ;
111127
128+ $ this ->createFormCallable = $ createFormCallable ;
129+
112130 // Set model labels with defaults
113131 $ this ->recordLabel = $ recordLabel ?? Str::singular (class_basename ($ modelClass ));
114132 $ this ->pluralRecordLabel = $ pluralRecordLabel ?? Str::singular (class_basename ($ modelClass ));
@@ -307,6 +325,116 @@ public function updateColumnCards(string|int $columnId, array $cards): bool
307325 });
308326 }
309327
328+ /**
329+ * Get the form class for creating cards.
330+ *
331+ * @param Form $form
332+ * @return Form
333+ */
334+ public function getEditForm (Form $ form ): Form
335+ {
336+ return $ form
337+ ->statePath ('editFormData ' )
338+ ->schema ([
339+ Select::make ($ this ->getStatusField ())
340+ ->label (__ ('Status ' ))
341+ ->options ($ this ->getStatusValues ())
342+ ->required (),
343+
344+ TextInput::make ('title ' )
345+ ->label (__ ('Title ' ))
346+ ->required ()
347+ ->maxLength (255 )
348+ ->placeholder (__ ('Enter :recordLabel title ' , ['recordLabel ' => strtolower ($ this ->config ['recordLabel ' ] ?? 'card ' )]))
349+ ->columnSpanFull (),
350+
351+ Textarea::make ('description ' )
352+ ->label (__ ('Description ' ))
353+ ->placeholder (__ ('Enter :recordLabel description ' , ['recordLabel ' => strtolower ($ this ->config ['recordLabel ' ] ?? 'card ' )]))
354+ ->columnSpanFull (),
355+
356+ $ this ->getCardAttributesFields (),
357+ ]);
358+ }
359+
360+ /**
361+ * Get the form class for creating cards.
362+ *
363+ * @param Form $form
364+ * @param mixed $activeColumn
365+ * @return Form
366+ */
367+ public function getCreateForm (Form $ form , mixed $ activeColumn ): Form {
368+ if ($ this ->createFormCallable ) {
369+ return call_user_func ($ this ->createFormCallable , $ form , $ activeColumn );
370+ }
371+
372+ return $ form
373+ ->statePath ('createFormData ' )
374+ ->schema ([
375+ Hidden::make ($ this ->getStatusField ())
376+ ->default (fn () => $ activeColumn ),
377+
378+ TextInput::make ('title ' )
379+ ->label (__ ('Title ' ))
380+ ->required ()
381+ ->maxLength (255 )
382+ ->placeholder (__ ('Enter :recordLabel title ' , ['recordLabel ' => strtolower ($ this ->config ['recordLabel ' ] ?? 'card ' )]))
383+ ->columnSpanFull (),
384+
385+ Textarea::make ('description ' )
386+ ->label (__ ('Description ' ))
387+ ->placeholder (__ ('Enter :recordLabel description ' , ['recordLabel ' => strtolower ($ this ->config ['recordLabel ' ] ?? 'card ' )]))
388+ ->columnSpanFull (),
389+
390+ $ this ->getCardAttributesFields (),
391+ ]);
392+ }
393+
394+ /**
395+ * Generate form fields for card attributes.
396+ *
397+ * @return Section|null
398+ */
399+ protected function getCardAttributesFields (): ?Section
400+ {
401+ $ cardAttributes = $ this ->getCardAttributes ();
402+
403+ if (empty ($ cardAttributes )) {
404+ return null ;
405+ }
406+
407+ $ fields = [];
408+
409+ foreach ($ cardAttributes as $ attribute => $ label ) {
410+ // Determine field type based on attribute name
411+ if (str_contains ($ attribute , 'date ' )) {
412+ $ fields [] = DatePicker::make ($ attribute )
413+ ->label ($ label );
414+ } elseif (str_contains ($ attribute , 'priority ' )) {
415+ $ fields [] = Select::make ($ attribute )
416+ ->label ($ label )
417+ ->options ([
418+ 'Low ' => __ ('Low ' ),
419+ 'Medium ' => __ ('Medium ' ),
420+ 'High ' => __ ('High ' ),
421+ ]);
422+ } else {
423+ $ fields [] = TextInput::make ($ attribute )
424+ ->label ($ label )
425+ ->maxLength (255 );
426+ }
427+ }
428+
429+ if (empty ($ fields )) {
430+ return null ;
431+ }
432+
433+ return Section::make (__ ('Additional Details ' ))
434+ ->schema ($ fields )
435+ ->columns (2 );
436+ }
437+
310438 /**
311439 * Create a new card with the given attributes.
312440 *
@@ -411,6 +539,7 @@ public function toLivewire(): array
411539 'descriptionAttribute ' => $ this ->getDescriptionAttribute (),
412540 'cardAttributes ' => $ this ->getCardAttributes (),
413541 'orderField ' => $ this ->getOrderField (),
542+ 'createFormCallable ' => $ this ->createFormCallable ,
414543 'recordLabel ' => $ this ->getRecordLabel (),
415544 'pluralRecordLabel ' => $ this ->getPluralRecordLabel (),
416545 ];
@@ -432,6 +561,7 @@ public static function fromLivewire($value)
432561 $ value ['descriptionAttribute ' ] ?? null ,
433562 $ value ['cardAttributes ' ] ?? [],
434563 $ value ['orderField ' ] ?? null ,
564+ $ value ['createFormCallable ' ] ?? null ,
435565 $ value ['recordLabel ' ] ?? null ,
436566 $ value ['pluralRecordLabel ' ] ?? null
437567 );
0 commit comments