ladowanie ogloszen
Deploy Polska Lokalnie / deploy (push) Successful in 11s

This commit is contained in:
2026-09-05 21:10:33 +02:00
parent c981b3cb93
commit fbfb0db38e
2 changed files with 179 additions and 1 deletions
+65 -1
View File
@@ -14240,6 +14240,7 @@ function AddListingPage({ editListingId }: { editListingId?: number }) {
// dalej, zeby nie krzyczec o brakach zanim uzytkownik cokolwiek wypelni.
const [showDetailsError, setShowDetailsError] = useState(false);
const [showLocationError, setShowLocationError] = useState(false);
const [showPhotosError, setShowPhotosError] = useState(false);
const [listingDetails, setListingDetails] = useState(INITIAL_LISTING_DETAILS);
// Ekran startowy z wyborem "Chcę sprzedać / wynająć" + kategorii. Przy edycji pomijamy go i od razu
// pokazujemy formularz. Wybor kategorii ustawia transakcje i rodzaj, a potem wchodzimy w kreator.
@@ -14640,8 +14641,17 @@ function AddListingPage({ editListingId }: { editListingId?: number }) {
});
return;
}
// Krok "Zdjęcia" (currentStep 2) - wymagamy przynajmniej jednego zdjecia, zeby przejsc dalej.
if (currentStep === 2 && step > 2 && photos.length === 0) {
setShowPhotosError(true);
window.requestAnimationFrame(() => {
document.querySelector('.add-step-error')?.scrollIntoView({ behavior: 'smooth', block: 'center' });
});
return;
}
setShowDetailsError(false);
setShowLocationError(false);
setShowPhotosError(false);
setCurrentStep(step);
window.requestAnimationFrame(() => {
document.querySelector('.add-page')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
@@ -15328,6 +15338,12 @@ function AddListingPage({ editListingId }: { editListingId?: number }) {
{virtualTourError && <p className="photo-tour-error" role="alert">{virtualTourError}</p>}
</div>
{showPhotosError && photos.length === 0 && (
<p className="add-field-error add-step-error" role="alert">
Dodaj przynajmniej jedno zdjęcie, aby przejść dalej.
</p>
)}
<div className="add-location-actions photos-actions">
<button className="back-step-button" type="button" onClick={() => goToStep(1)}>
Wstecz
@@ -22518,6 +22534,45 @@ function ResultCardGallery({ photos, cover, alt }: { photos: string[]; cover: st
);
}
// Animacja wczytywania listy ofert - pokazywana zamiast pustego miejsca, dopoki backend nie odda
// ogloszen. Znika sama, gdy dane przyjda (komponent nadrzedny przestaje ja renderowac).
function ListingsLoader() {
return (
<div className="listings-loader" role="status" aria-live="polite">
<div className="listings-loader-art" aria-hidden="true">
<svg viewBox="0 0 240 150" width="200" height="125" role="img">
<path d="M42 118a78 78 0 0 1 156 0Z" fill="#e8f5ed" />
<g className="ll-cloud ll-cloud-a" fill="#eef2f6">
<ellipse cx="58" cy="44" rx="17" ry="9" />
<ellipse cx="70" cy="40" rx="12" ry="8" />
</g>
<g className="ll-cloud ll-cloud-b" fill="#eef2f6">
<ellipse cx="188" cy="52" rx="15" ry="8" />
<ellipse cx="177" cy="48" rx="10" ry="7" />
</g>
<g>
<rect x="58" y="96" width="7" height="22" rx="3" fill="#c3ddca" />
<circle cx="61.5" cy="90" r="16" fill="#d4ead9" />
</g>
<g className="ll-house">
<rect x="96" y="86" width="60" height="34" rx="3" fill="#ffffff" stroke="#cadfd2" strokeWidth="2.5" />
<path d="M126 58l34 30H92Z" fill="#d4ead9" stroke="#9ecfae" strokeWidth="2.5" strokeLinejoin="round" />
<rect x="150" y="66" width="8" height="16" rx="2" fill="#c3ddca" />
<rect x="118" y="98" width="16" height="22" rx="2" fill="#38b26a" />
<circle cx="130" cy="109" r="1.6" fill="#ffffff" />
</g>
<rect x="42" y="117" width="156" height="3" rx="1.5" fill="#d9ebe0" />
</svg>
</div>
<p className="listings-loader-title">Wczytujemy <span>ogłoszenia</span>…</p>
<p className="listings-loader-sub">Zaraz pokażemy Ci najlepsze oferty dopasowane do Twoich kryteriów.</p>
<div className="listings-loader-bars" aria-hidden="true">
<span /><span /><span /><span />
</div>
</div>
);
}
function RealListingsBand({
offerType,
onOpenListing,
@@ -22553,7 +22608,16 @@ function RealListingsBand({
const cityFilter = (city ?? '').trim();
const visible = cityFilter ? items.filter((item) => cityStartsWith(item.city, cityFilter)) : items;
if (loading || visible.length === 0) {
// W trakcie ladowania pokazujemy animacje zamiast pustego miejsca; gdy dane przyjda i lista jest
// pusta - nie pokazujemy nic (jak dotad).
if (loading) {
return (
<div className="real-listings-section" aria-label="Ogłoszenia dodane w serwisie">
<ListingsLoader />
</div>
);
}
if (visible.length === 0) {
return null;
}