feat: convert Minishop to Composer package with Filament v5 admin (Phase 1 + 2)#55
Conversation
Creates packages/minishop/ as a path-repository Composer package with the Minishop namespace. Moves all 23 models, 7 enums, 8 actions, 6 services, 8 observers, 9 policies, mail, notifications, AI agent, factories, domain seeders, and migrations into the package. Updates all App\Models\*, App\Enums\*, etc. imports across controllers, tests, and config to Minishop\* namespace. Registers custom Factory name/model resolvers so Eloquent factories resolve correctly for the new namespace. The main app retains only Fortify auth, settings controllers, and the Laravel bootstrap layer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Install filament/filament:^5.0 in the package
- Create MinishopPanelProvider extending PanelProvider at /dashboard
- Add FilamentUser contract and canAccessPanel() to User model
- Build 11 Filament resources: Category, Tag, Product, ShippingMethod,
TaxZone (with RatesRelationManager), Coupon, User, Customer, Order
(with ItemsRelationManager), OrderReturn, ActivityLog
- Remove 25 legacy admin Inertia controllers, 20 admin Form Requests,
23 admin test files, 12 admin Vue page directories
- Strip admin route group from routes/web.php
- Move OrderStatusChangedMail dispatch from deleted controller into
OrderObserver so status-change emails still fire from any trigger
- Fix LowStockSubject to use url() instead of route('admin.products.show')
- Update auth/account tests to reference /dashboard path directly
- All 294 tests passing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move storefront, account, API v1, and webhook controllers into Minishop\Http\Controllers\*
- Move form requests (storefront, account, API) and Eloquent API resources into the package
- Move mail and invoice PDF Blade views into packages/minishop/resources/views/
- Create packages/minishop/routes/web.php and api.php; strip main app routes to settings only
- Move all storefront, account, API, webhook, and unit tests into packages/minishop/tests/
- Fix phpunit.xml to reference package test suite; remove deleted main-app test directories
- Move OrderStatusChangedMail dispatch from deleted admin controller into OrderObserver
- Fix LowStockSubject URL generation to use url() helper (no Filament panel context at checkout)
- Use Route::middleware('web')->group() for implicit route model binding in package routes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Update storefront Vue pages and composables: replace App/Http/Controllers/Storefront/* imports with Minishop/Http/Controllers/Storefront/* (generated by php artisan wayfinder:generate after Phase 3 controller move) - Replace deleted admin Wayfinder imports in AppSidebar.vue with hardcoded Filament panel paths (/dashboard/products, /dashboard/orders, etc.) - Remove Admin/ProductController import from AppSidebarHeader.vue; point low-stock badge to Filament products page - Delete Dashboard.vue (no Inertia route; /dashboard now served by Filament) - Delete resources/js/tests/pages/admin/ and Dashboard.test.ts (tested deleted Inertia admin pages replaced by Filament) - Update AppSidebar.test.ts to remove dead admin controller mocks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ardize project skill configurations
- Eliminate all App\ namespace dependencies from the package so it can
be dropped into any Laravel app without modifications
- Move CreateNewUser, LoginResponse, and RegisterResponse into the
package (Minishop\Actions\Fortify, Minishop\Http\Responses) and
register them as default Fortify bindings in MinishopServiceProvider
- Create package base Controller with AuthorizesRequests trait
- Add `EncryptCookies::except('cart_token')` in ServiceProvider boot
so the cart session cookie always bypasses encryption
- Gate storefront routes behind `minishop.load_storefront_routes`
(MINISHOP_STOREFRONT env var, default false)
- Add minishop:install Artisan command for drop-in setup
- Fix Orchestra Testbench v11 package test suite: add AI, Sanctum,
Fortify, Inertia, Filament, Livewire, Spatie providers; register
role/permission middleware aliases; configure app key, auth guards,
inertia page existence check, Fortify features; create app.blade.php
fixture for Inertia test rendering
- Move OrderEmailTest to package test suite
- Update main app tests to remove stale route('home') references
Package test suite: 251 passed; main app tests: 42 passed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Code Review6 issues found (scored ≥ 80 confidence). Ordered by severity. 🔴 Critical —
|
- StorefrontRendererContract: swappable inertia/blade/custom renderer
bound in ServiceProvider; 12 controllers + route closure migrated
- PaymentManager (extends Manager): driver-based gateway plugin system
with StripeGateway, NullGateway (COD); host apps extend via Payment::extend()
- Remove PayMongo gateway, webhook controller, routes, migration columns,
model fields, and all tests
- publishesMigrations() replaces loadMigrationsFrom() so host apps control
which migrations run
Fix 6 code-review findings:
- Stripe webhook: catch UnexpectedValueException (bad JSON → 400 not 500)
- Stripe webhook: wrap order update in DB::transaction() + lockForUpdate()
to prevent duplicate confirmation emails on concurrent webhook delivery
- Stripe webhook: guard $order->customer->user null-deref with eager load
and null check before queuing mail
- StripeGateway::initiate(): check intent status before reusing; recreate
intent when canceled or succeeded (client_secret would be unusable)
- BladeRenderer: convert PascalCase segments to kebab-case so
'storefront/OrderConfirmation' → 'storefront.order-confirmation'
(was broken strtolower producing 'storefront.orderconfirmation')
- Webhook routes: add throttle:60,1 to generic {gateway} route
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CI was failing because storefront routes (MINISHOP_STOREFRONT=true) were not registered in .env.example, so Wayfinder never generated the TypeScript action files for the package's storefront controllers. Added the env var to .env.example and an explicit wayfinder:generate step before npm run build so CI always has the action files before Vite processes the Vue imports. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ongo - Replace `dashboard()` Wayfinder import with hardcoded `/dashboard` in AppHeader, AppSidebar, and Welcome — the Filament panel doesn't register a Wayfinder-compatible named route, so Wayfinder never generates `dashboard` - Remove PayMongo imports and template block from Payment.vue (`paymongoCheckout`, `initPayMongo`, gateway === 'paymongo' onMounted branch, PayMongo UI section) - Add MINISHOP_STOREFRONT=true to .env.example so CI registers storefront routes before wayfinder:generate runs, ensuring all storefront action files are generated before Vite processes Vue imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…table publishesMigrations() alone does not load migrations — it only registers them for publishing. The host app's php artisan migrate never ran the package permission/schema tables, causing every test that seeds RoleAndPermissionSeeder to fail with "no such table: permissions". Added loadMigrationsFrom() alongside publishesMigrations() so migrations run automatically in any host app (including CI) while still allowing host apps to publish and customise them when needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
packages/minishop/App\namespace dependencies sominishop/minishopcan be installed in any Laravel appCreateNewUser,LoginResponse,RegisterResponseinto the package; register as default Fortify bindingsControllerwithAuthorizesRequeststraitcart_tokenfrom cookie encryption viaEncryptCookies::except()in ServiceProviderMINISHOP_STOREFRONTenv var (default off; Admin + API only)php artisan minishop:installcommand for drop-in setupTest plan
php artisan test --compact→ 42 passed (main app)php artisan test --compact --testsuite=Package→ 251 passedphp artisan minishop:installruns without errors in a fresh Laravel app/dashboardas super-admin → Filament panel loads/dashboardas customer → 403 forbiddenPOST /api/v1/auth/register→ creates user, assigns customer role, returns tokenMINISHOP_STOREFRONTis unset🤖 Generated with Claude Code