Add Products page backed by the CRM products API + storefront catalog picker
Deploy Ladill Merchant / deploy (push) Successful in 30s
Deploy Ladill Merchant / deploy (push) Successful in 30s
- New Products page (merchant.products.*) with full CRUD proxied to the Ladill CRM products API via a new CrmClient + config/crm.php (owner-scoped, type=product). - Sidebar gains a Products entry. - The new storefront form loads the merchant's catalog: each shop/menu section gets an "Add from products…" picker that drops a CRM product in as an item (name, price, description). Catalog fetch is resilient — empty if CRM is down. Wires CRM_API_URL + CRM_API_KEY_MERCHANT on the merchant env (matches CRM). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
08d3c99996
commit
b19e2654a1
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Merchant;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\Crm\CrmClient;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* Products page — fully backed by the Ladill CRM products API. The merchant's
|
||||
* catalog lives in CRM (owner-scoped); this controller proxies CRUD to it.
|
||||
*/
|
||||
class ProductController extends Controller
|
||||
{
|
||||
private function crm(): CrmClient
|
||||
{
|
||||
return CrmClient::for((string) ladill_account()->public_id);
|
||||
}
|
||||
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$search = trim((string) $request->query('search', ''));
|
||||
|
||||
$response = $this->crm()->products([
|
||||
'type' => 'product',
|
||||
'per_page' => 100,
|
||||
'search' => $search !== '' ? $search : null,
|
||||
]);
|
||||
|
||||
return view('merchant.products.index', [
|
||||
'products' => (array) ($response['data'] ?? []),
|
||||
'search' => $search,
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
return view('merchant.products.create');
|
||||
}
|
||||
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$this->crm()->createProduct($this->payload($request));
|
||||
|
||||
return redirect()->route('merchant.products.index')->with('success', 'Product created.');
|
||||
}
|
||||
|
||||
public function edit(string $product): View
|
||||
{
|
||||
return view('merchant.products.edit', ['product' => $this->crm()->product($product)]);
|
||||
}
|
||||
|
||||
public function update(Request $request, string $product): RedirectResponse
|
||||
{
|
||||
$this->crm()->updateProduct($product, $this->payload($request));
|
||||
|
||||
return redirect()->route('merchant.products.index')->with('success', 'Product updated.');
|
||||
}
|
||||
|
||||
public function destroy(string $product): RedirectResponse
|
||||
{
|
||||
$this->crm()->deleteProduct($product);
|
||||
|
||||
return redirect()->route('merchant.products.index')->with('success', 'Product deleted.');
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
private function payload(Request $request): array
|
||||
{
|
||||
$data = $request->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'sku' => ['nullable', 'string', 'max:80'],
|
||||
'description' => ['nullable', 'string', 'max:5000'],
|
||||
'unit_price' => ['nullable', 'numeric', 'min:0'],
|
||||
'currency' => ['nullable', 'string', 'size:3'],
|
||||
'tax_rate' => ['nullable', 'numeric', 'min:0', 'max:100'],
|
||||
'active' => ['nullable', 'boolean'],
|
||||
]);
|
||||
|
||||
return [
|
||||
'name' => $data['name'],
|
||||
'sku' => $data['sku'] ?? null,
|
||||
'type' => 'product',
|
||||
'description' => $data['description'] ?? null,
|
||||
'unit_price_minor' => (int) round(((float) ($data['unit_price'] ?? 0)) * 100),
|
||||
'currency' => strtoupper((string) ($data['currency'] ?? config('crm.default_currency', 'GHS'))),
|
||||
'tax_rate' => (float) ($data['tax_rate'] ?? 0),
|
||||
'active' => $request->boolean('active'),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user