mirror of
https://github.com/openclassify/openclassify.git
synced 2026-04-14 11:12:09 -05:00
Fix create listing publish flow
This commit is contained in:
parent
6fde32cc8b
commit
46b70a91f7
@ -29,6 +29,7 @@ class PanelQuickListingForm extends Component
|
||||
|
||||
private const TOTAL_STEPS = 5;
|
||||
private const DRAFT_SESSION_KEY = 'panel_quick_listing_draft';
|
||||
private const OTHER_CITY_ID = -1;
|
||||
|
||||
public array $photos = [];
|
||||
public array $videos = [];
|
||||
@ -57,6 +58,7 @@ class PanelQuickListingForm extends Component
|
||||
public ?int $selectedCityId = null;
|
||||
public bool $isPublishing = false;
|
||||
public bool $shouldPersistDraft = true;
|
||||
public ?string $publishError = null;
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
@ -117,11 +119,13 @@ class PanelQuickListingForm extends Component
|
||||
|
||||
public function goToStep(int $step): void
|
||||
{
|
||||
$this->publishError = null;
|
||||
$this->currentStep = max(1, min(self::TOTAL_STEPS, $step));
|
||||
}
|
||||
|
||||
public function goToCategoryStep(): void
|
||||
{
|
||||
$this->publishError = null;
|
||||
$this->validatePhotos();
|
||||
$this->validateVideos();
|
||||
$this->currentStep = 2;
|
||||
@ -133,12 +137,14 @@ class PanelQuickListingForm extends Component
|
||||
|
||||
public function goToDetailsStep(): void
|
||||
{
|
||||
$this->publishError = null;
|
||||
$this->validateCategoryStep();
|
||||
$this->currentStep = 3;
|
||||
}
|
||||
|
||||
public function goToFeaturesStep(): void
|
||||
{
|
||||
$this->publishError = null;
|
||||
$this->validateCategoryStep();
|
||||
$this->validateDetailsStep();
|
||||
$this->currentStep = 4;
|
||||
@ -146,6 +152,7 @@ class PanelQuickListingForm extends Component
|
||||
|
||||
public function goToPreviewStep(): void
|
||||
{
|
||||
$this->publishError = null;
|
||||
$this->validateCategoryStep();
|
||||
$this->validateDetailsStep();
|
||||
$this->validateCustomFieldsStep();
|
||||
@ -199,6 +206,7 @@ class PanelQuickListingForm extends Component
|
||||
return;
|
||||
}
|
||||
|
||||
$this->publishError = null;
|
||||
$this->selectedCategoryId = $categoryId;
|
||||
$this->loadListingCustomFields();
|
||||
}
|
||||
@ -210,6 +218,8 @@ class PanelQuickListingForm extends Component
|
||||
}
|
||||
|
||||
$this->isPublishing = true;
|
||||
$this->publishError = null;
|
||||
$this->resetErrorBag();
|
||||
|
||||
try {
|
||||
$this->validatePhotos();
|
||||
@ -221,11 +231,13 @@ class PanelQuickListingForm extends Component
|
||||
$listing = $this->createListing();
|
||||
} catch (ValidationException $exception) {
|
||||
$this->isPublishing = false;
|
||||
$this->handlePublishValidationFailure($exception);
|
||||
|
||||
throw $exception;
|
||||
return;
|
||||
} catch (Throwable $exception) {
|
||||
report($exception);
|
||||
$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.');
|
||||
|
||||
return;
|
||||
@ -361,10 +373,20 @@ class PanelQuickListingForm extends Component
|
||||
return [];
|
||||
}
|
||||
|
||||
return collect($this->cities)
|
||||
$cities = collect($this->cities)
|
||||
->where('country_id', $this->selectedCountryId)
|
||||
->values()
|
||||
->all();
|
||||
|
||||
if ($cities !== []) {
|
||||
return $cities;
|
||||
}
|
||||
|
||||
return [[
|
||||
'id' => self::OTHER_CITY_ID,
|
||||
'name' => 'Other',
|
||||
'country_id' => $this->selectedCountryId,
|
||||
]];
|
||||
}
|
||||
|
||||
public function getSelectedCountryNameProperty(): ?string
|
||||
@ -384,6 +406,10 @@ class PanelQuickListingForm extends Component
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((int) $this->selectedCityId === self::OTHER_CITY_ID) {
|
||||
return 'Other';
|
||||
}
|
||||
|
||||
$city = collect($this->cities)->firstWhere('id', $this->selectedCityId);
|
||||
|
||||
return $city['name'] ?? null;
|
||||
@ -772,6 +798,49 @@ class PanelQuickListingForm extends Component
|
||||
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
|
||||
{
|
||||
$draft = session()->get($this->draftSessionKey(), []);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
@php
|
||||
$maxPhotoCount = (int) config('quick-listing.max_photo_count', 20);
|
||||
$visiblePhotoSlotCount = min($maxPhotoCount, 8);
|
||||
$maxVideoCount = (int) config('video.max_listing_videos', 5);
|
||||
$currency = \Modules\Listing\Support\ListingPanelHelper::defaultCurrency();
|
||||
$displayPrice = is_numeric($price) ? number_format((float) $price, 0, ',', '.') : $price;
|
||||
@ -737,6 +738,8 @@
|
||||
.qc-publish-stack {
|
||||
display: grid;
|
||||
gap: 0.7rem;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.qc-button,
|
||||
@ -841,6 +844,14 @@
|
||||
</div>
|
||||
|
||||
<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)
|
||||
<div class="qc-body">
|
||||
<div class="qc-stack">
|
||||
@ -880,7 +891,7 @@
|
||||
</div>
|
||||
|
||||
<div class="qc-photo-grid">
|
||||
@for ($index = 0; $index < $maxPhotoCount; $index++)
|
||||
@for ($index = 0; $index < $visiblePhotoSlotCount; $index++)
|
||||
<div class="qc-photo-slot">
|
||||
@if (isset($photos[$index]))
|
||||
<img src="{{ $photos[$index]->temporaryUrl() }}" alt="Uploaded photo {{ $index + 1 }}">
|
||||
@ -894,6 +905,10 @@
|
||||
</div>
|
||||
@endfor
|
||||
</div>
|
||||
|
||||
@if (count($photos) > $visiblePhotoSlotCount)
|
||||
<p class="qc-meta-copy mt-3">{{ count($photos) - $visiblePhotoSlotCount }} more photos added.</p>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<div class="qc-empty">Add one cover photo to continue.</div>
|
||||
@ -1322,10 +1337,11 @@
|
||||
</div>
|
||||
|
||||
<div class="qc-panel">
|
||||
<form class="qc-publish-stack" wire:submit.prevent="publishListing">
|
||||
<div class="qc-publish-stack">
|
||||
<button
|
||||
type="submit"
|
||||
type="button"
|
||||
class="qc-button"
|
||||
wire:click.prevent="publishListing"
|
||||
wire:loading.attr="disabled"
|
||||
wire:target="publishListing"
|
||||
>
|
||||
@ -1333,7 +1349,7 @@
|
||||
<span wire:loading wire:target="publishListing">Publishing...</span>
|
||||
</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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user