Fix create listing publish flow

This commit is contained in:
fatihalp 2026-03-08 16:45:42 +03:00
parent 6fde32cc8b
commit 46b70a91f7
2 changed files with 91 additions and 6 deletions

View File

@ -29,6 +29,7 @@ class PanelQuickListingForm extends Component
private const TOTAL_STEPS = 5; private const TOTAL_STEPS = 5;
private const DRAFT_SESSION_KEY = 'panel_quick_listing_draft'; private const DRAFT_SESSION_KEY = 'panel_quick_listing_draft';
private const OTHER_CITY_ID = -1;
public array $photos = []; public array $photos = [];
public array $videos = []; public array $videos = [];
@ -57,6 +58,7 @@ class PanelQuickListingForm extends Component
public ?int $selectedCityId = null; public ?int $selectedCityId = null;
public bool $isPublishing = false; public bool $isPublishing = false;
public bool $shouldPersistDraft = true; public bool $shouldPersistDraft = true;
public ?string $publishError = null;
public function mount(): void public function mount(): void
{ {
@ -117,11 +119,13 @@ class PanelQuickListingForm extends Component
public function goToStep(int $step): void public function goToStep(int $step): void
{ {
$this->publishError = null;
$this->currentStep = max(1, min(self::TOTAL_STEPS, $step)); $this->currentStep = max(1, min(self::TOTAL_STEPS, $step));
} }
public function goToCategoryStep(): void public function goToCategoryStep(): void
{ {
$this->publishError = null;
$this->validatePhotos(); $this->validatePhotos();
$this->validateVideos(); $this->validateVideos();
$this->currentStep = 2; $this->currentStep = 2;
@ -133,12 +137,14 @@ class PanelQuickListingForm extends Component
public function goToDetailsStep(): void public function goToDetailsStep(): void
{ {
$this->publishError = null;
$this->validateCategoryStep(); $this->validateCategoryStep();
$this->currentStep = 3; $this->currentStep = 3;
} }
public function goToFeaturesStep(): void public function goToFeaturesStep(): void
{ {
$this->publishError = null;
$this->validateCategoryStep(); $this->validateCategoryStep();
$this->validateDetailsStep(); $this->validateDetailsStep();
$this->currentStep = 4; $this->currentStep = 4;
@ -146,6 +152,7 @@ class PanelQuickListingForm extends Component
public function goToPreviewStep(): void public function goToPreviewStep(): void
{ {
$this->publishError = null;
$this->validateCategoryStep(); $this->validateCategoryStep();
$this->validateDetailsStep(); $this->validateDetailsStep();
$this->validateCustomFieldsStep(); $this->validateCustomFieldsStep();
@ -199,6 +206,7 @@ class PanelQuickListingForm extends Component
return; return;
} }
$this->publishError = null;
$this->selectedCategoryId = $categoryId; $this->selectedCategoryId = $categoryId;
$this->loadListingCustomFields(); $this->loadListingCustomFields();
} }
@ -210,6 +218,8 @@ class PanelQuickListingForm extends Component
} }
$this->isPublishing = true; $this->isPublishing = true;
$this->publishError = null;
$this->resetErrorBag();
try { try {
$this->validatePhotos(); $this->validatePhotos();
@ -221,11 +231,13 @@ class PanelQuickListingForm extends Component
$listing = $this->createListing(); $listing = $this->createListing();
} catch (ValidationException $exception) { } catch (ValidationException $exception) {
$this->isPublishing = false; $this->isPublishing = false;
$this->handlePublishValidationFailure($exception);
throw $exception; return;
} catch (Throwable $exception) { } catch (Throwable $exception) {
report($exception); report($exception);
$this->isPublishing = false; $this->isPublishing = false;
$this->publishError = 'The listing could not be created. Please try again.';
session()->flash('error', 'The listing could not be created. Please try again.'); session()->flash('error', 'The listing could not be created. Please try again.');
return; return;
@ -361,10 +373,20 @@ class PanelQuickListingForm extends Component
return []; return [];
} }
return collect($this->cities) $cities = collect($this->cities)
->where('country_id', $this->selectedCountryId) ->where('country_id', $this->selectedCountryId)
->values() ->values()
->all(); ->all();
if ($cities !== []) {
return $cities;
}
return [[
'id' => self::OTHER_CITY_ID,
'name' => 'Other',
'country_id' => $this->selectedCountryId,
]];
} }
public function getSelectedCountryNameProperty(): ?string public function getSelectedCountryNameProperty(): ?string
@ -384,6 +406,10 @@ class PanelQuickListingForm extends Component
return null; return null;
} }
if ((int) $this->selectedCityId === self::OTHER_CITY_ID) {
return 'Other';
}
$city = collect($this->cities)->firstWhere('id', $this->selectedCityId); $city = collect($this->cities)->firstWhere('id', $this->selectedCityId);
return $city['name'] ?? null; return $city['name'] ?? null;
@ -772,6 +798,49 @@ class PanelQuickListingForm extends Component
return (string) config('media_storage.local_disk', MediaStorage::diskFromDriver(MediaStorage::DRIVER_LOCAL)); return (string) config('media_storage.local_disk', MediaStorage::diskFromDriver(MediaStorage::DRIVER_LOCAL));
} }
private function handlePublishValidationFailure(ValidationException $exception): void
{
$errors = $exception->errors();
foreach ($errors as $key => $messages) {
foreach ($messages as $message) {
$this->addError($key, $message);
}
}
$this->currentStep = $this->stepForValidationErrors(array_keys($errors));
$this->publishError = collect($errors)->flatten()->filter()->first() ?: 'Please fix the highlighted fields before publishing.';
}
private function stepForValidationErrors(array $keys): int
{
$normalizedKeys = collect($keys)->map(fn ($key) => (string) $key)->values();
if ($normalizedKeys->contains(fn ($key) => str_starts_with($key, 'photos') || str_starts_with($key, 'videos'))) {
return 1;
}
if ($normalizedKeys->contains('selectedCategoryId')) {
return 2;
}
if ($normalizedKeys->contains(fn ($key) => in_array($key, [
'listingTitle',
'price',
'description',
'selectedCountryId',
'selectedCityId',
], true))) {
return 3;
}
if ($normalizedKeys->contains(fn ($key) => str_starts_with($key, 'customFieldValues.'))) {
return 4;
}
return 5;
}
private function restoreDraft(): void private function restoreDraft(): void
{ {
$draft = session()->get($this->draftSessionKey(), []); $draft = session()->get($this->draftSessionKey(), []);

View File

@ -1,5 +1,6 @@
@php @php
$maxPhotoCount = (int) config('quick-listing.max_photo_count', 20); $maxPhotoCount = (int) config('quick-listing.max_photo_count', 20);
$visiblePhotoSlotCount = min($maxPhotoCount, 8);
$maxVideoCount = (int) config('video.max_listing_videos', 5); $maxVideoCount = (int) config('video.max_listing_videos', 5);
$currency = \Modules\Listing\Support\ListingPanelHelper::defaultCurrency(); $currency = \Modules\Listing\Support\ListingPanelHelper::defaultCurrency();
$displayPrice = is_numeric($price) ? number_format((float) $price, 0, ',', '.') : $price; $displayPrice = is_numeric($price) ? number_format((float) $price, 0, ',', '.') : $price;
@ -737,6 +738,8 @@
.qc-publish-stack { .qc-publish-stack {
display: grid; display: grid;
gap: 0.7rem; gap: 0.7rem;
position: relative;
z-index: 2;
} }
.qc-button, .qc-button,
@ -841,6 +844,14 @@
</div> </div>
<div class="qc-card"> <div class="qc-card">
@if ($publishError)
<div class="px-4 pt-4">
<div class="rounded-[18px] border border-rose-200 bg-rose-50 px-4 py-3 text-sm font-semibold text-rose-700">
{{ $publishError }}
</div>
</div>
@endif
@if ($currentStep === 1) @if ($currentStep === 1)
<div class="qc-body"> <div class="qc-body">
<div class="qc-stack"> <div class="qc-stack">
@ -880,7 +891,7 @@
</div> </div>
<div class="qc-photo-grid"> <div class="qc-photo-grid">
@for ($index = 0; $index < $maxPhotoCount; $index++) @for ($index = 0; $index < $visiblePhotoSlotCount; $index++)
<div class="qc-photo-slot"> <div class="qc-photo-slot">
@if (isset($photos[$index])) @if (isset($photos[$index]))
<img src="{{ $photos[$index]->temporaryUrl() }}" alt="Uploaded photo {{ $index + 1 }}"> <img src="{{ $photos[$index]->temporaryUrl() }}" alt="Uploaded photo {{ $index + 1 }}">
@ -894,6 +905,10 @@
</div> </div>
@endfor @endfor
</div> </div>
@if (count($photos) > $visiblePhotoSlotCount)
<p class="qc-meta-copy mt-3">{{ count($photos) - $visiblePhotoSlotCount }} more photos added.</p>
@endif
</div> </div>
@else @else
<div class="qc-empty">Add one cover photo to continue.</div> <div class="qc-empty">Add one cover photo to continue.</div>
@ -1322,10 +1337,11 @@
</div> </div>
<div class="qc-panel"> <div class="qc-panel">
<form class="qc-publish-stack" wire:submit.prevent="publishListing"> <div class="qc-publish-stack">
<button <button
type="submit" type="button"
class="qc-button" class="qc-button"
wire:click.prevent="publishListing"
wire:loading.attr="disabled" wire:loading.attr="disabled"
wire:target="publishListing" wire:target="publishListing"
> >
@ -1333,7 +1349,7 @@
<span wire:loading wire:target="publishListing">Publishing...</span> <span wire:loading wire:target="publishListing">Publishing...</span>
</button> </button>
<button type="button" class="qc-button-secondary" wire:click="goToStep(4)" wire:loading.attr="disabled" wire:target="publishListing">Back</button> <button type="button" class="qc-button-secondary" wire:click="goToStep(4)" wire:loading.attr="disabled" wire:target="publishListing">Back</button>
</form> </div>
</div> </div>
</div> </div>
</div> </div>