@jaimevalasek/aioson 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +456 -0
- package/CODE_OF_CONDUCT.md +12 -0
- package/CONTRIBUTING.md +13 -0
- package/LICENSE +21 -0
- package/README.md +254 -0
- package/bin/aioson.js +4 -0
- package/docs/en/cli-reference.md +398 -0
- package/docs/en/i18n.md +52 -0
- package/docs/en/json-schemas.md +41 -0
- package/docs/en/mcp.md +56 -0
- package/docs/en/parallel.md +82 -0
- package/docs/en/qa-browser.md +339 -0
- package/docs/en/release-flow.md +22 -0
- package/docs/en/release-notes-template.md +41 -0
- package/docs/en/release.md +28 -0
- package/docs/en/schemas/agent-prompt.schema.json +17 -0
- package/docs/en/schemas/agents.schema.json +32 -0
- package/docs/en/schemas/context-validate.schema.json +36 -0
- package/docs/en/schemas/doctor.schema.json +89 -0
- package/docs/en/schemas/error.schema.json +24 -0
- package/docs/en/schemas/i18n-add.schema.json +15 -0
- package/docs/en/schemas/index.json +116 -0
- package/docs/en/schemas/info.schema.json +39 -0
- package/docs/en/schemas/init.schema.json +48 -0
- package/docs/en/schemas/install.schema.json +60 -0
- package/docs/en/schemas/locale-apply.schema.json +30 -0
- package/docs/en/schemas/mcp-doctor.schema.json +95 -0
- package/docs/en/schemas/mcp-init.schema.json +122 -0
- package/docs/en/schemas/package-test.schema.json +24 -0
- package/docs/en/schemas/parallel-assign.schema.json +57 -0
- package/docs/en/schemas/parallel-doctor.schema.json +86 -0
- package/docs/en/schemas/parallel-init.schema.json +53 -0
- package/docs/en/schemas/parallel-status.schema.json +94 -0
- package/docs/en/schemas/setup-context.schema.json +39 -0
- package/docs/en/schemas/smoke.schema.json +23 -0
- package/docs/en/schemas/update.schema.json +48 -0
- package/docs/en/schemas/workflow-plan.schema.json +30 -0
- package/docs/en/web3.md +54 -0
- package/docs/pt/README.md +46 -0
- package/docs/pt/advisor-spec.md +335 -0
- package/docs/pt/agentes.md +453 -0
- package/docs/pt/cenarios.md +1230 -0
- package/docs/pt/clientes-ai.md +224 -0
- package/docs/pt/comandos-cli.md +511 -0
- package/docs/pt/genome-3.0-spec.md +296 -0
- package/docs/pt/guia-engineer.md +226 -0
- package/docs/pt/inicio-rapido.md +138 -0
- package/docs/pt/profiler-system.md +214 -0
- package/docs/pt/runtime-observability.md +72 -0
- package/docs/pt/squad-genoma.md +777 -0
- package/docs/pt/web3.md +797 -0
- package/docs/testing/genome-2.0-manual-regression.md +23 -0
- package/docs/testing/genome-2.0-matrix.md +36 -0
- package/docs/testing/genome-2.0-rollout.md +184 -0
- package/package.json +50 -0
- package/src/agents.js +56 -0
- package/src/cli.js +497 -0
- package/src/commands/agents.js +142 -0
- package/src/commands/cloud.js +1767 -0
- package/src/commands/config.js +90 -0
- package/src/commands/context-validate.js +91 -0
- package/src/commands/doctor.js +123 -0
- package/src/commands/genome-doctor.js +41 -0
- package/src/commands/genome-migrate.js +49 -0
- package/src/commands/i18n-add.js +56 -0
- package/src/commands/info.js +41 -0
- package/src/commands/init.js +75 -0
- package/src/commands/install.js +68 -0
- package/src/commands/locale-apply.js +51 -0
- package/src/commands/locale-diff.js +126 -0
- package/src/commands/mcp-doctor.js +406 -0
- package/src/commands/mcp-init.js +379 -0
- package/src/commands/package-e2e.js +273 -0
- package/src/commands/parallel-assign.js +403 -0
- package/src/commands/parallel-doctor.js +437 -0
- package/src/commands/parallel-init.js +249 -0
- package/src/commands/parallel-status.js +290 -0
- package/src/commands/qa-doctor.js +185 -0
- package/src/commands/qa-init.js +161 -0
- package/src/commands/qa-report.js +58 -0
- package/src/commands/qa-run.js +873 -0
- package/src/commands/qa-scan.js +337 -0
- package/src/commands/runtime.js +948 -0
- package/src/commands/scan-project.js +1107 -0
- package/src/commands/setup-context.js +650 -0
- package/src/commands/smoke.js +426 -0
- package/src/commands/squad-doctor.js +358 -0
- package/src/commands/squad-export.js +46 -0
- package/src/commands/squad-pipeline.js +97 -0
- package/src/commands/squad-repair-genomes.js +39 -0
- package/src/commands/squad-status.js +424 -0
- package/src/commands/squad-validate.js +230 -0
- package/src/commands/test-agents.js +194 -0
- package/src/commands/update.js +55 -0
- package/src/commands/workflow-next.js +594 -0
- package/src/commands/workflow-plan.js +108 -0
- package/src/constants.js +314 -0
- package/src/context-parse-reason.js +22 -0
- package/src/context-writer.js +150 -0
- package/src/context.js +217 -0
- package/src/detector.js +261 -0
- package/src/doctor.js +289 -0
- package/src/execution-gateway.js +461 -0
- package/src/genome-files.js +198 -0
- package/src/genome-format.js +442 -0
- package/src/genome-schema.js +215 -0
- package/src/genomes/bindings.js +281 -0
- package/src/genomes.js +467 -0
- package/src/i18n/index.js +103 -0
- package/src/i18n/messages/en.js +784 -0
- package/src/i18n/messages/es.js +718 -0
- package/src/i18n/messages/fr.js +725 -0
- package/src/i18n/messages/pt-BR.js +818 -0
- package/src/i18n/scaffold.js +64 -0
- package/src/installer.js +232 -0
- package/src/lib/genomes/compat.js +206 -0
- package/src/lib/genomes/migrate.js +90 -0
- package/src/lib/squads/genome-repair.js +49 -0
- package/src/locales.js +84 -0
- package/src/onboarding.js +305 -0
- package/src/parser.js +53 -0
- package/src/prompt-tool.js +20 -0
- package/src/qa-html-report.js +472 -0
- package/src/runtime-store.js +1527 -0
- package/src/squads/apply-genome.js +21 -0
- package/src/squads/genome-binding-service.js +154 -0
- package/src/updater.js +32 -0
- package/src/utils.js +46 -0
- package/src/version.js +50 -0
- package/template/.aioson/advisors/.gitkeep +1 -0
- package/template/.aioson/agents/analyst.md +225 -0
- package/template/.aioson/agents/architect.md +221 -0
- package/template/.aioson/agents/dev.md +201 -0
- package/template/.aioson/agents/discovery-design-doc.md +196 -0
- package/template/.aioson/agents/genoma.md +300 -0
- package/template/.aioson/agents/orchestrator.md +107 -0
- package/template/.aioson/agents/pm.md +89 -0
- package/template/.aioson/agents/product.md +361 -0
- package/template/.aioson/agents/profiler-enricher.md +266 -0
- package/template/.aioson/agents/profiler-forge.md +188 -0
- package/template/.aioson/agents/profiler-researcher.md +245 -0
- package/template/.aioson/agents/qa.md +344 -0
- package/template/.aioson/agents/setup.md +381 -0
- package/template/.aioson/agents/squad.md +837 -0
- package/template/.aioson/agents/ux-ui.md +416 -0
- package/template/.aioson/config.md +56 -0
- package/template/.aioson/context/.gitkeep +0 -0
- package/template/.aioson/context/parallel/.gitkeep +0 -0
- package/template/.aioson/context/spec.md.template +37 -0
- package/template/.aioson/genomas/.gitkeep +0 -0
- package/template/.aioson/locales/en/agents/analyst.md +214 -0
- package/template/.aioson/locales/en/agents/architect.md +210 -0
- package/template/.aioson/locales/en/agents/dev.md +187 -0
- package/template/.aioson/locales/en/agents/discovery-design-doc.md +27 -0
- package/template/.aioson/locales/en/agents/genoma.md +212 -0
- package/template/.aioson/locales/en/agents/orchestrator.md +105 -0
- package/template/.aioson/locales/en/agents/pm.md +77 -0
- package/template/.aioson/locales/en/agents/product.md +310 -0
- package/template/.aioson/locales/en/agents/profiler-enricher.md +5 -0
- package/template/.aioson/locales/en/agents/profiler-forge.md +5 -0
- package/template/.aioson/locales/en/agents/profiler-researcher.md +5 -0
- package/template/.aioson/locales/en/agents/qa.md +214 -0
- package/template/.aioson/locales/en/agents/setup.md +342 -0
- package/template/.aioson/locales/en/agents/squad.md +247 -0
- package/template/.aioson/locales/en/agents/ux-ui.md +320 -0
- package/template/.aioson/locales/es/agents/analyst.md +203 -0
- package/template/.aioson/locales/es/agents/architect.md +208 -0
- package/template/.aioson/locales/es/agents/dev.md +183 -0
- package/template/.aioson/locales/es/agents/discovery-design-doc.md +19 -0
- package/template/.aioson/locales/es/agents/genoma.md +102 -0
- package/template/.aioson/locales/es/agents/orchestrator.md +108 -0
- package/template/.aioson/locales/es/agents/pm.md +81 -0
- package/template/.aioson/locales/es/agents/product.md +310 -0
- package/template/.aioson/locales/es/agents/profiler-enricher.md +5 -0
- package/template/.aioson/locales/es/agents/profiler-forge.md +5 -0
- package/template/.aioson/locales/es/agents/profiler-researcher.md +5 -0
- package/template/.aioson/locales/es/agents/qa.md +163 -0
- package/template/.aioson/locales/es/agents/setup.md +347 -0
- package/template/.aioson/locales/es/agents/squad.md +247 -0
- package/template/.aioson/locales/es/agents/ux-ui.md +201 -0
- package/template/.aioson/locales/fr/agents/analyst.md +203 -0
- package/template/.aioson/locales/fr/agents/architect.md +208 -0
- package/template/.aioson/locales/fr/agents/dev.md +183 -0
- package/template/.aioson/locales/fr/agents/discovery-design-doc.md +19 -0
- package/template/.aioson/locales/fr/agents/genoma.md +102 -0
- package/template/.aioson/locales/fr/agents/orchestrator.md +108 -0
- package/template/.aioson/locales/fr/agents/pm.md +81 -0
- package/template/.aioson/locales/fr/agents/product.md +310 -0
- package/template/.aioson/locales/fr/agents/profiler-enricher.md +5 -0
- package/template/.aioson/locales/fr/agents/profiler-forge.md +5 -0
- package/template/.aioson/locales/fr/agents/profiler-researcher.md +5 -0
- package/template/.aioson/locales/fr/agents/qa.md +163 -0
- package/template/.aioson/locales/fr/agents/setup.md +347 -0
- package/template/.aioson/locales/fr/agents/squad.md +247 -0
- package/template/.aioson/locales/fr/agents/ux-ui.md +201 -0
- package/template/.aioson/locales/pt-BR/agents/analyst.md +217 -0
- package/template/.aioson/locales/pt-BR/agents/architect.md +213 -0
- package/template/.aioson/locales/pt-BR/agents/dev.md +198 -0
- package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +198 -0
- package/template/.aioson/locales/pt-BR/agents/genoma.md +297 -0
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +108 -0
- package/template/.aioson/locales/pt-BR/agents/pm.md +81 -0
- package/template/.aioson/locales/pt-BR/agents/product.md +316 -0
- package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/qa.md +217 -0
- package/template/.aioson/locales/pt-BR/agents/setup.md +371 -0
- package/template/.aioson/locales/pt-BR/agents/squad.md +772 -0
- package/template/.aioson/locales/pt-BR/agents/ux-ui.md +322 -0
- package/template/.aioson/mcp/servers.md +24 -0
- package/template/.aioson/profiler-reports/.gitkeep +1 -0
- package/template/.aioson/schemas/content-blueprint.schema.json +30 -0
- package/template/.aioson/schemas/genome-meta.schema.json +150 -0
- package/template/.aioson/schemas/genome.schema.json +115 -0
- package/template/.aioson/schemas/readiness.schema.json +27 -0
- package/template/.aioson/schemas/squad-blueprint.schema.json +172 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +276 -0
- package/template/.aioson/skills/dynamic/README.md +30 -0
- package/template/.aioson/skills/dynamic/cardano-docs.md +16 -0
- package/template/.aioson/skills/dynamic/ethereum-docs.md +17 -0
- package/template/.aioson/skills/dynamic/flux-ui-docs.md +13 -0
- package/template/.aioson/skills/dynamic/laravel-docs.md +41 -0
- package/template/.aioson/skills/dynamic/npm-packages.md +16 -0
- package/template/.aioson/skills/dynamic/solana-docs.md +16 -0
- package/template/.aioson/skills/references/premium-command-center-ui/master-application-prompt.md +79 -0
- package/template/.aioson/skills/references/premium-command-center-ui/operational-ux-playbook.md +253 -0
- package/template/.aioson/skills/references/premium-command-center-ui/quality-validation-checklist.md +82 -0
- package/template/.aioson/skills/references/premium-command-center-ui/visual-system-and-component-patterns.md +270 -0
- package/template/.aioson/skills/static/django-patterns.md +342 -0
- package/template/.aioson/skills/static/fastapi-patterns.md +344 -0
- package/template/.aioson/skills/static/filament-patterns.md +267 -0
- package/template/.aioson/skills/static/flux-ui-components.md +262 -0
- package/template/.aioson/skills/static/git-conventions.md +227 -0
- package/template/.aioson/skills/static/interface-design.md +372 -0
- package/template/.aioson/skills/static/jetstream-setup.md +200 -0
- package/template/.aioson/skills/static/laravel-conventions.md +491 -0
- package/template/.aioson/skills/static/nextjs-patterns.md +321 -0
- package/template/.aioson/skills/static/node-express-patterns.md +317 -0
- package/template/.aioson/skills/static/node-typescript-patterns.md +282 -0
- package/template/.aioson/skills/static/premium-command-center-ui.md +190 -0
- package/template/.aioson/skills/static/rails-conventions.md +307 -0
- package/template/.aioson/skills/static/react-motion-patterns.md +577 -0
- package/template/.aioson/skills/static/static-html-patterns.md +1935 -0
- package/template/.aioson/skills/static/tall-stack-patterns.md +286 -0
- package/template/.aioson/skills/static/ui-ux-modern.md +75 -0
- package/template/.aioson/skills/static/web3-cardano-patterns.md +337 -0
- package/template/.aioson/skills/static/web3-ethereum-patterns.md +310 -0
- package/template/.aioson/skills/static/web3-security-checklist.md +284 -0
- package/template/.aioson/skills/static/web3-solana-patterns.md +324 -0
- package/template/.aioson/squads/.artisan/.gitkeep +0 -0
- package/template/.aioson/squads/.gitkeep +0 -0
- package/template/.aioson/squads/memory.md +5 -0
- package/template/.aioson/tasks/squad-analyze.md +83 -0
- package/template/.aioson/tasks/squad-create.md +99 -0
- package/template/.aioson/tasks/squad-design.md +100 -0
- package/template/.aioson/tasks/squad-export.md +20 -0
- package/template/.aioson/tasks/squad-extend.md +68 -0
- package/template/.aioson/tasks/squad-pipeline.md +122 -0
- package/template/.aioson/tasks/squad-repair.md +85 -0
- package/template/.aioson/tasks/squad-validate.md +58 -0
- package/template/.aioson/templates/squads/content-basic/template.json +21 -0
- package/template/.aioson/templates/squads/media-channel/template.json +24 -0
- package/template/.aioson/templates/squads/research-analysis/template.json +22 -0
- package/template/.aioson/templates/squads/software-delivery/template.json +21 -0
- package/template/.claude/commands/aioson/analyst.md +5 -0
- package/template/.claude/commands/aioson/architect.md +5 -0
- package/template/.claude/commands/aioson/dev.md +5 -0
- package/template/.claude/commands/aioson/orchestrator.md +5 -0
- package/template/.claude/commands/aioson/pm.md +5 -0
- package/template/.claude/commands/aioson/qa.md +5 -0
- package/template/.claude/commands/aioson/setup.md +5 -0
- package/template/.claude/commands/aioson/ux-ui.md +5 -0
- package/template/.gemini/GEMINI.md +10 -0
- package/template/.gemini/commands/aios-analyst.toml +4 -0
- package/template/.gemini/commands/aios-architect.toml +7 -0
- package/template/.gemini/commands/aios-dev.toml +8 -0
- package/template/.gemini/commands/aios-discovery-design-doc.toml +4 -0
- package/template/.gemini/commands/aios-orchestrator.toml +8 -0
- package/template/.gemini/commands/aios-pm.toml +8 -0
- package/template/.gemini/commands/aios-product.toml +4 -0
- package/template/.gemini/commands/aios-qa.toml +6 -0
- package/template/.gemini/commands/aios-setup.toml +3 -0
- package/template/.gemini/commands/aios-ux-ui.toml +8 -0
- package/template/AGENTS.md +67 -0
- package/template/CLAUDE.md +31 -0
- package/template/OPENCODE.md +24 -0
- package/template/aioson-models.json +40 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Filament Patterns
|
|
2
|
+
|
|
3
|
+
> Admin panels and back-office tools built with Filament v3. Panel as product, not afterthought.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Resource structure — CRUD done right
|
|
8
|
+
|
|
9
|
+
```php
|
|
10
|
+
// app/Filament/Resources/AppointmentResource.php
|
|
11
|
+
class AppointmentResource extends Resource
|
|
12
|
+
{
|
|
13
|
+
protected static ?string $model = Appointment::class;
|
|
14
|
+
protected static ?string $navigationIcon = 'heroicon-o-calendar';
|
|
15
|
+
protected static ?string $navigationGroup = 'Scheduling';
|
|
16
|
+
protected static ?int $navigationSort = 1;
|
|
17
|
+
|
|
18
|
+
public static function form(Form $form): Form
|
|
19
|
+
{
|
|
20
|
+
return $form->schema([
|
|
21
|
+
Forms\Components\Select::make('doctor_id')
|
|
22
|
+
->relationship('doctor', 'name')
|
|
23
|
+
->searchable()
|
|
24
|
+
->preload()
|
|
25
|
+
->required(),
|
|
26
|
+
|
|
27
|
+
Forms\Components\DateTimePicker::make('date')
|
|
28
|
+
->required()
|
|
29
|
+
->minDate(now())
|
|
30
|
+
->native(false),
|
|
31
|
+
|
|
32
|
+
Forms\Components\Textarea::make('notes')
|
|
33
|
+
->rows(3)
|
|
34
|
+
->columnSpanFull(),
|
|
35
|
+
|
|
36
|
+
Forms\Components\Select::make('status')
|
|
37
|
+
->options(AppointmentStatus::class)
|
|
38
|
+
->required(),
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public static function table(Table $table): Table
|
|
43
|
+
{
|
|
44
|
+
return $table
|
|
45
|
+
->columns([
|
|
46
|
+
Tables\Columns\TextColumn::make('patient.name')
|
|
47
|
+
->searchable()->sortable(),
|
|
48
|
+
Tables\Columns\TextColumn::make('doctor.name')
|
|
49
|
+
->searchable()->sortable(),
|
|
50
|
+
Tables\Columns\TextColumn::make('date')
|
|
51
|
+
->dateTime('M d, Y H:i')->sortable(),
|
|
52
|
+
Tables\Columns\BadgeColumn::make('status')
|
|
53
|
+
->colors([
|
|
54
|
+
'warning' => 'pending',
|
|
55
|
+
'success' => 'confirmed',
|
|
56
|
+
'danger' => 'cancelled',
|
|
57
|
+
]),
|
|
58
|
+
])
|
|
59
|
+
->filters([
|
|
60
|
+
Tables\Filters\SelectFilter::make('status')
|
|
61
|
+
->options(AppointmentStatus::class),
|
|
62
|
+
Tables\Filters\Filter::make('upcoming')
|
|
63
|
+
->query(fn ($query) => $query->where('date', '>', now())),
|
|
64
|
+
])
|
|
65
|
+
->actions([
|
|
66
|
+
Tables\Actions\EditAction::make(),
|
|
67
|
+
Tables\Actions\Action::make('confirm')
|
|
68
|
+
->icon('heroicon-o-check')
|
|
69
|
+
->color('success')
|
|
70
|
+
->visible(fn ($record) => $record->status === 'pending')
|
|
71
|
+
->action(fn ($record) => (new ConfirmAppointmentAction)->execute($record))
|
|
72
|
+
->requiresConfirmation(),
|
|
73
|
+
])
|
|
74
|
+
->bulkActions([
|
|
75
|
+
Tables\Actions\BulkActionGroup::make([
|
|
76
|
+
Tables\Actions\DeleteBulkAction::make(),
|
|
77
|
+
]),
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Custom Pages — beyond CRUD
|
|
86
|
+
|
|
87
|
+
```php
|
|
88
|
+
// app/Filament/Pages/Dashboard.php
|
|
89
|
+
class Dashboard extends Page
|
|
90
|
+
{
|
|
91
|
+
protected static ?string $navigationIcon = 'heroicon-o-home';
|
|
92
|
+
protected static string $view = 'filament.pages.dashboard';
|
|
93
|
+
|
|
94
|
+
public function getHeaderWidgetsColumns(): int|array
|
|
95
|
+
{
|
|
96
|
+
return ['md' => 2, 'xl' => 4];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
protected function getHeaderWidgets(): array
|
|
100
|
+
{
|
|
101
|
+
return [
|
|
102
|
+
AppointmentsToday::class,
|
|
103
|
+
CancelledThisWeek::class,
|
|
104
|
+
RevenueWidget::class,
|
|
105
|
+
OccupancyRateWidget::class,
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Widgets — stats and charts
|
|
114
|
+
|
|
115
|
+
```php
|
|
116
|
+
class AppointmentsToday extends StatsOverviewWidget
|
|
117
|
+
{
|
|
118
|
+
protected function getStats(): array
|
|
119
|
+
{
|
|
120
|
+
return [
|
|
121
|
+
Stat::make('Today\'s Appointments', Appointment::today()->count())
|
|
122
|
+
->description('+12% from yesterday')
|
|
123
|
+
->descriptionIcon('heroicon-m-arrow-trending-up')
|
|
124
|
+
->color('success'),
|
|
125
|
+
|
|
126
|
+
Stat::make('Pending Confirmation', Appointment::pending()->count())
|
|
127
|
+
->color('warning'),
|
|
128
|
+
|
|
129
|
+
Stat::make('Cancelled Today', Appointment::cancelledToday()->count())
|
|
130
|
+
->color('danger'),
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Relation Managers
|
|
139
|
+
|
|
140
|
+
```php
|
|
141
|
+
// Manage related models from within a parent Resource
|
|
142
|
+
class PrescriptionsRelationManager extends RelationManager
|
|
143
|
+
{
|
|
144
|
+
protected static string $relationship = 'prescriptions';
|
|
145
|
+
|
|
146
|
+
public function form(Form $form): Form
|
|
147
|
+
{
|
|
148
|
+
return $form->schema([
|
|
149
|
+
Forms\Components\TextInput::make('medication')->required(),
|
|
150
|
+
Forms\Components\TextInput::make('dosage')->required(),
|
|
151
|
+
]);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
public function table(Table $table): Table
|
|
155
|
+
{
|
|
156
|
+
return $table
|
|
157
|
+
->columns([
|
|
158
|
+
Tables\Columns\TextColumn::make('medication'),
|
|
159
|
+
Tables\Columns\TextColumn::make('dosage'),
|
|
160
|
+
Tables\Columns\TextColumn::make('created_at')->dateTime()->sortable(),
|
|
161
|
+
])
|
|
162
|
+
->headerActions([Tables\Actions\CreateAction::make()])
|
|
163
|
+
->actions([Tables\Actions\EditAction::make(), Tables\Actions\DeleteAction::make()]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Policies — guard every Filament action
|
|
171
|
+
|
|
172
|
+
```php
|
|
173
|
+
// Filament automatically uses Laravel Policies
|
|
174
|
+
class AppointmentPolicy
|
|
175
|
+
{
|
|
176
|
+
public function viewAny(User $user): bool { return $user->hasRole('admin', 'staff'); }
|
|
177
|
+
public function view(User $user, Appointment $a): bool { return $user->hasRole('admin', 'staff'); }
|
|
178
|
+
public function create(User $user): bool { return $user->hasRole('admin', 'staff'); }
|
|
179
|
+
public function update(User $user, Appointment $a): bool { return $user->hasRole('admin'); }
|
|
180
|
+
public function delete(User $user, Appointment $a): bool { return $user->hasRole('admin'); }
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Register the policy and Filament will enforce it on all Resource actions automatically.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Notifications
|
|
189
|
+
|
|
190
|
+
```php
|
|
191
|
+
// Inside an Action
|
|
192
|
+
Notification::make()
|
|
193
|
+
->title('Appointment confirmed')
|
|
194
|
+
->success()
|
|
195
|
+
->send();
|
|
196
|
+
|
|
197
|
+
// Persistent notification for a specific user
|
|
198
|
+
Notification::make()
|
|
199
|
+
->title('New appointment requires review')
|
|
200
|
+
->warning()
|
|
201
|
+
->sendToDatabase($admin);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Forms — advanced field patterns
|
|
207
|
+
|
|
208
|
+
```php
|
|
209
|
+
// Conditional field visibility
|
|
210
|
+
Forms\Components\Toggle::make('is_recurring')
|
|
211
|
+
->live(),
|
|
212
|
+
|
|
213
|
+
Forms\Components\Select::make('recurrence_type')
|
|
214
|
+
->options(['daily' => 'Daily', 'weekly' => 'Weekly', 'monthly' => 'Monthly'])
|
|
215
|
+
->visible(fn (Get $get) => $get('is_recurring')),
|
|
216
|
+
|
|
217
|
+
// File upload with preview
|
|
218
|
+
Forms\Components\FileUpload::make('medical_report')
|
|
219
|
+
->disk('private')
|
|
220
|
+
->directory('reports')
|
|
221
|
+
->acceptedFileTypes(['application/pdf'])
|
|
222
|
+
->maxSize(10240),
|
|
223
|
+
|
|
224
|
+
// Repeater for structured data
|
|
225
|
+
Forms\Components\Repeater::make('symptoms')
|
|
226
|
+
->schema([
|
|
227
|
+
Forms\Components\TextInput::make('name')->required(),
|
|
228
|
+
Forms\Components\Select::make('severity')
|
|
229
|
+
->options(['mild', 'moderate', 'severe']),
|
|
230
|
+
])
|
|
231
|
+
->minItems(1)
|
|
232
|
+
->columnSpanFull(),
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Business logic — always in Actions, not in Filament
|
|
238
|
+
|
|
239
|
+
```php
|
|
240
|
+
// WRONG — logic inside Filament action
|
|
241
|
+
Tables\Actions\Action::make('confirm')
|
|
242
|
+
->action(function ($record) {
|
|
243
|
+
$record->update(['status' => 'confirmed']);
|
|
244
|
+
Mail::to($record->patient)->send(new ConfirmationMail($record));
|
|
245
|
+
}),
|
|
246
|
+
|
|
247
|
+
// RIGHT — delegate to Action class
|
|
248
|
+
Tables\Actions\Action::make('confirm')
|
|
249
|
+
->action(fn ($record) => (new ConfirmAppointmentAction)->execute($record))
|
|
250
|
+
->requiresConfirmation(),
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## ALWAYS
|
|
256
|
+
- Register Policies — Filament enforces them automatically
|
|
257
|
+
- Use `->relationship()` on Select for Eloquent relations
|
|
258
|
+
- Use `->searchable()` and `->preload()` on FK selects
|
|
259
|
+
- Use `->live()` on fields that control conditional visibility
|
|
260
|
+
- Delegate complex logic to Action classes
|
|
261
|
+
- Use Widgets for dashboard metrics
|
|
262
|
+
|
|
263
|
+
## NEVER
|
|
264
|
+
- Business logic inside Filament action closures
|
|
265
|
+
- Skip policy registration for admin panels
|
|
266
|
+
- Use `->get()` without limits in Resource queries (use Filament's built-in pagination)
|
|
267
|
+
- Build custom admin UIs when a Filament Resource covers the use case
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Flux UI Components
|
|
2
|
+
|
|
3
|
+
> Flux is the official Livewire component library. Use it before building anything custom.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Component inventory
|
|
8
|
+
|
|
9
|
+
Flux ships these — always check before building a custom component:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Buttons : flux:button, flux:button.group
|
|
13
|
+
Forms : flux:input, flux:textarea, flux:select, flux:checkbox, flux:radio,
|
|
14
|
+
flux:switch, flux:field, flux:label, flux:error, flux:description
|
|
15
|
+
Navigation : flux:navbar, flux:sidebar, flux:breadcrumbs, flux:tabs
|
|
16
|
+
Overlays : flux:modal, flux:dropdown, flux:tooltip, flux:popover
|
|
17
|
+
Feedback : flux:badge, flux:toast (via JS), flux:spinner
|
|
18
|
+
Layout : flux:card, flux:separator, flux:table, flux:heading, flux:text
|
|
19
|
+
Media : flux:avatar, flux:icon
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Buttons
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<!-- Variants -->
|
|
28
|
+
<flux:button variant="primary">Save</flux:button>
|
|
29
|
+
<flux:button variant="ghost">Cancel</flux:button>
|
|
30
|
+
<flux:button variant="danger">Delete</flux:button>
|
|
31
|
+
<flux:button variant="outline">Export</flux:button>
|
|
32
|
+
|
|
33
|
+
<!-- With icon -->
|
|
34
|
+
<flux:button icon="plus">New Appointment</flux:button>
|
|
35
|
+
<flux:button icon-trailing="chevron-down">Options</flux:button>
|
|
36
|
+
|
|
37
|
+
<!-- Sizes -->
|
|
38
|
+
<flux:button size="sm">Small</flux:button>
|
|
39
|
+
<flux:button size="lg">Large</flux:button>
|
|
40
|
+
|
|
41
|
+
<!-- Loading state with Livewire -->
|
|
42
|
+
<flux:button wire:click="save" wire:loading.attr="disabled">
|
|
43
|
+
<flux:icon wire:loading name="arrow-path" class="animate-spin" />
|
|
44
|
+
<span wire:loading.remove>Save</span>
|
|
45
|
+
<span wire:loading>Saving...</span>
|
|
46
|
+
</flux:button>
|
|
47
|
+
|
|
48
|
+
<!-- Icon-only with tooltip -->
|
|
49
|
+
<flux:button icon="trash" variant="ghost" aria-label="Delete" />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Form fields
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<!-- Standard input with label and error -->
|
|
58
|
+
<flux:field>
|
|
59
|
+
<flux:label>Email address</flux:label>
|
|
60
|
+
<flux:input wire:model.live="email" type="email" placeholder="you@example.com" />
|
|
61
|
+
<flux:error name="email" />
|
|
62
|
+
</flux:field>
|
|
63
|
+
|
|
64
|
+
<!-- Textarea -->
|
|
65
|
+
<flux:field>
|
|
66
|
+
<flux:label>Notes</flux:label>
|
|
67
|
+
<flux:textarea wire:model="notes" rows="4" />
|
|
68
|
+
<flux:description>Optional. Max 500 characters.</flux:description>
|
|
69
|
+
<flux:error name="notes" />
|
|
70
|
+
</flux:field>
|
|
71
|
+
|
|
72
|
+
<!-- Select with search -->
|
|
73
|
+
<flux:field>
|
|
74
|
+
<flux:label>Doctor</flux:label>
|
|
75
|
+
<flux:select wire:model="doctorId" searchable placeholder="Select a doctor...">
|
|
76
|
+
@foreach ($doctors as $doctor)
|
|
77
|
+
<flux:select.option value="{{ $doctor->id }}">{{ $doctor->name }}</flux:select.option>
|
|
78
|
+
@endforeach
|
|
79
|
+
</flux:select>
|
|
80
|
+
<flux:error name="doctorId" />
|
|
81
|
+
</flux:field>
|
|
82
|
+
|
|
83
|
+
<!-- Checkbox and radio -->
|
|
84
|
+
<flux:checkbox wire:model="agreedToTerms" label="I agree to the terms" />
|
|
85
|
+
|
|
86
|
+
<flux:radio.group wire:model="plan" label="Plan">
|
|
87
|
+
<flux:radio value="free" label="Free" description="Up to 3 projects" />
|
|
88
|
+
<flux:radio value="pro" label="Pro" description="Unlimited projects" />
|
|
89
|
+
</flux:radio.group>
|
|
90
|
+
|
|
91
|
+
<!-- Toggle switch -->
|
|
92
|
+
<flux:switch wire:model.live="notifications" label="Email notifications" />
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Modal
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<!-- Trigger -->
|
|
101
|
+
<flux:modal.trigger name="confirm-delete">
|
|
102
|
+
<flux:button variant="danger" icon="trash">Delete</flux:button>
|
|
103
|
+
</flux:modal.trigger>
|
|
104
|
+
|
|
105
|
+
<!-- Modal definition (anywhere in the component) -->
|
|
106
|
+
<flux:modal name="confirm-delete" class="max-w-md">
|
|
107
|
+
<div class="space-y-4">
|
|
108
|
+
<flux:heading>Delete appointment?</flux:heading>
|
|
109
|
+
<flux:text class="text-zinc-500">
|
|
110
|
+
This action cannot be undone. The patient will be notified.
|
|
111
|
+
</flux:text>
|
|
112
|
+
<div class="flex gap-2 justify-end">
|
|
113
|
+
<flux:modal.close>
|
|
114
|
+
<flux:button variant="ghost">Cancel</flux:button>
|
|
115
|
+
</flux:modal.close>
|
|
116
|
+
<flux:button variant="danger" wire:click="delete" wire:loading.attr="disabled">
|
|
117
|
+
Delete
|
|
118
|
+
</flux:button>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
</flux:modal>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Programmatic control from Livewire:
|
|
125
|
+
```php
|
|
126
|
+
$this->modal('confirm-delete')->show();
|
|
127
|
+
$this->modal('confirm-delete')->close();
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Dropdown menu
|
|
133
|
+
|
|
134
|
+
```html
|
|
135
|
+
<flux:dropdown>
|
|
136
|
+
<flux:button icon-trailing="chevron-down">Actions</flux:button>
|
|
137
|
+
|
|
138
|
+
<flux:menu>
|
|
139
|
+
<flux:menu.item icon="eye" wire:click="view">View</flux:menu.item>
|
|
140
|
+
<flux:menu.item icon="pencil" wire:click="edit">Edit</flux:menu.item>
|
|
141
|
+
<flux:menu.separator />
|
|
142
|
+
<flux:menu.item icon="trash" variant="danger" wire:click="delete">Delete</flux:menu.item>
|
|
143
|
+
</flux:menu>
|
|
144
|
+
</flux:dropdown>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Table
|
|
150
|
+
|
|
151
|
+
```html
|
|
152
|
+
<flux:table>
|
|
153
|
+
<flux:columns>
|
|
154
|
+
<flux:column sortable wire:click="sort('name')">Patient</flux:column>
|
|
155
|
+
<flux:column sortable wire:click="sort('date')">Date</flux:column>
|
|
156
|
+
<flux:column>Status</flux:column>
|
|
157
|
+
<flux:column class="text-right">Actions</flux:column>
|
|
158
|
+
</flux:columns>
|
|
159
|
+
|
|
160
|
+
<flux:rows>
|
|
161
|
+
@forelse ($appointments as $appointment)
|
|
162
|
+
<flux:row :key="$appointment->id">
|
|
163
|
+
<flux:cell class="font-medium">{{ $appointment->patient->name }}</flux:cell>
|
|
164
|
+
<flux:cell>{{ $appointment->date->format('M d, Y H:i') }}</flux:cell>
|
|
165
|
+
<flux:cell>
|
|
166
|
+
<flux:badge :color="$appointment->statusColor()">
|
|
167
|
+
{{ $appointment->status }}
|
|
168
|
+
</flux:badge>
|
|
169
|
+
</flux:cell>
|
|
170
|
+
<flux:cell class="text-right">
|
|
171
|
+
<flux:button size="sm" variant="ghost" wire:click="edit({{ $appointment->id }})">
|
|
172
|
+
Edit
|
|
173
|
+
</flux:button>
|
|
174
|
+
</flux:cell>
|
|
175
|
+
</flux:row>
|
|
176
|
+
@empty
|
|
177
|
+
<flux:row>
|
|
178
|
+
<flux:cell colspan="4" class="text-center py-12 text-zinc-400">
|
|
179
|
+
No appointments found.
|
|
180
|
+
</flux:cell>
|
|
181
|
+
</flux:row>
|
|
182
|
+
@endforelse
|
|
183
|
+
</flux:rows>
|
|
184
|
+
</flux:table>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Badges and status indicators
|
|
190
|
+
|
|
191
|
+
```html
|
|
192
|
+
<flux:badge color="green">Confirmed</flux:badge>
|
|
193
|
+
<flux:badge color="yellow">Pending</flux:badge>
|
|
194
|
+
<flux:badge color="red">Cancelled</flux:badge>
|
|
195
|
+
<flux:badge color="blue">Rescheduled</flux:badge>
|
|
196
|
+
|
|
197
|
+
<!-- Dynamic color from model method -->
|
|
198
|
+
<flux:badge :color="$appointment->statusColor()">{{ $appointment->status }}</flux:badge>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Sidebar navigation
|
|
204
|
+
|
|
205
|
+
```html
|
|
206
|
+
<flux:sidebar>
|
|
207
|
+
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
|
|
208
|
+
|
|
209
|
+
<a href="{{ route('home') }}" class="flex items-center gap-2 px-4 py-3">
|
|
210
|
+
<flux:icon name="calendar" class="text-brand" />
|
|
211
|
+
<span class="font-semibold">Clinic App</span>
|
|
212
|
+
</a>
|
|
213
|
+
|
|
214
|
+
<flux:navlist class="flex-1">
|
|
215
|
+
<flux:navlist.item icon="home" href="{{ route('dashboard') }}" :current="request()->routeIs('dashboard')">
|
|
216
|
+
Dashboard
|
|
217
|
+
</flux:navlist.item>
|
|
218
|
+
<flux:navlist.item icon="calendar" href="{{ route('appointments.index') }}" :current="request()->routeIs('appointments.*')">
|
|
219
|
+
Appointments
|
|
220
|
+
</flux:navlist.item>
|
|
221
|
+
<flux:navlist.group heading="Admin" expandable>
|
|
222
|
+
<flux:navlist.item icon="users" href="{{ route('doctors.index') }}">Doctors</flux:navlist.item>
|
|
223
|
+
<flux:navlist.item icon="cog" href="{{ route('settings') }}">Settings</flux:navlist.item>
|
|
224
|
+
</flux:navlist.group>
|
|
225
|
+
</flux:navlist>
|
|
226
|
+
|
|
227
|
+
<flux:navlist>
|
|
228
|
+
<flux:navlist.item icon="arrow-right-start-on-rectangle" href="{{ route('logout') }}"
|
|
229
|
+
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
|
230
|
+
Sign out
|
|
231
|
+
</flux:navlist.item>
|
|
232
|
+
</flux:navlist>
|
|
233
|
+
</flux:sidebar>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Customizing with Tailwind
|
|
239
|
+
|
|
240
|
+
Flux components accept standard Tailwind classes:
|
|
241
|
+
|
|
242
|
+
```html
|
|
243
|
+
<flux:card class="border-l-4 border-brand p-6">...</flux:card>
|
|
244
|
+
<flux:button class="w-full justify-center">Full width</flux:button>
|
|
245
|
+
<flux:input class="font-mono" />
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Do not override Flux's internal variant styles — customize at the design token level via `tailwind.config.js`.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## ALWAYS
|
|
253
|
+
- Use `flux:field` wrapper for inputs (provides label + error layout)
|
|
254
|
+
- Use `flux:modal.trigger` + `flux:modal` pair for dialogs
|
|
255
|
+
- Use `wire:loading` states on async actions
|
|
256
|
+
- Use `flux:badge` for status labels with semantic colors
|
|
257
|
+
- Check Flux docs before building any custom component
|
|
258
|
+
|
|
259
|
+
## NEVER
|
|
260
|
+
- Duplicate a Flux component with a custom Blade component
|
|
261
|
+
- Mix Flux and other component libraries (shadcn, DaisyUI) in the same project
|
|
262
|
+
- Override Flux variant classes with arbitrary Tailwind — use config tokens
|