Add HL3D branding, Etsy Live/Draft paging and Projects lifecycle
Deploy HickLab3D Dashboard / Deploy to production (push) Failing after 23s
Deploy HickLab3D Dashboard / Deploy to production (push) Failing after 23s
Replace the old touchmark/PNG identity with the supplied lockup and monogram, segmented role-aware navigation, Live/Draft listing filters with generation-based cache invalidation, and admin Projects covering immutable file revisions, listing live pointers, and exact-decimal filament/packaging/shipping costing. Additive schema only; no Etsy publication. Isolated clone tests: 301 tests, 1162 assertions.
This commit is contained in:
@@ -11,25 +11,73 @@ use Throwable;
|
||||
|
||||
class EtsyController extends Controller
|
||||
{
|
||||
/** @var list<string> */
|
||||
private const UI_STATES = ['active', 'draft'];
|
||||
|
||||
private const PER_PAGE = 20;
|
||||
|
||||
public function index(Request $request, Etsy $etsy): View
|
||||
{
|
||||
abort_unless($request->user()->role === 'admin', 403);
|
||||
$connection = EtsyConnection::first();
|
||||
$receipts = [];
|
||||
$listings = [];
|
||||
$integrationError = null;
|
||||
$listingCount = 0;
|
||||
$receiptsError = null;
|
||||
$listingsError = null;
|
||||
$stateError = null;
|
||||
$pageError = null;
|
||||
|
||||
$rawState = $request->query('state', 'active');
|
||||
$state = is_string($rawState) ? strtolower($rawState) : '';
|
||||
if (! in_array($state, self::UI_STATES, true)) {
|
||||
$stateError = 'This is not a supported listing state. Select Live or Drafts.';
|
||||
$state = 'active';
|
||||
}
|
||||
|
||||
$rawPage = $request->query('page', '1');
|
||||
if (! is_string($rawPage) || ! ctype_digit($rawPage) || strlen($rawPage) > 5 || (int) $rawPage < 1 || (int) $rawPage > 10000) {
|
||||
$pageError = 'This is not a valid page number. Use pages 1–10000.';
|
||||
$page = 1;
|
||||
} else {
|
||||
$page = (int) $rawPage;
|
||||
}
|
||||
|
||||
if ($connection && $etsy->configured()) {
|
||||
try {
|
||||
$receipts = $etsy->receipts($connection)['results'] ?? [];
|
||||
$listings = $etsy->listings($connection)['results'] ?? [];
|
||||
} catch (Throwable $exception) {
|
||||
report($exception);
|
||||
$integrationError = 'Etsy data is temporarily unavailable. Reconnect the shop if this continues.';
|
||||
$receiptsError = 'Order data is temporarily unavailable. Reconnect the shop if this continues.';
|
||||
}
|
||||
|
||||
if (! $stateError && ! $pageError) {
|
||||
try {
|
||||
$listingPage = $etsy->listListings($connection, $state, self::PER_PAGE, (max(1, $page) - 1) * self::PER_PAGE);
|
||||
$listings = $listingPage['results'];
|
||||
$listingCount = $listingPage['count'];
|
||||
} catch (Throwable $exception) {
|
||||
report($exception);
|
||||
$listingsError = 'Listing data is temporarily unavailable. Reconnect the shop if this continues.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return view('etsy', compact('connection', 'receipts', 'listings', 'integrationError') + ['configured' => $etsy->configured()]);
|
||||
return view('etsy', [
|
||||
'connection' => $connection,
|
||||
'receipts' => $receipts,
|
||||
'listings' => $listings,
|
||||
'listingSnapshot' => $listingPage ?? null,
|
||||
'listingCount' => $listingCount,
|
||||
'state' => $state,
|
||||
'page' => $page,
|
||||
'perPage' => self::PER_PAGE,
|
||||
'receiptsError' => $receiptsError,
|
||||
'listingsError' => $listingsError,
|
||||
'stateError' => $stateError,
|
||||
'pageError' => $pageError,
|
||||
'configured' => $etsy->configured(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function connect(Request $request, Etsy $etsy): RedirectResponse
|
||||
|
||||
Reference in New Issue
Block a user