// desktop-screen-dashboard.jsx — Dashboard screen for desktop
function DashboardDesktop({
active = 'kauf',
onNav = () => {},
onOpenResults = () => {},
onOpenDetail = () => {},
onNewSearch = () => {},
onOpenAdmin = () => {},
ctx = {},
searchQuery = '',
topBarProps = {},
} = {}) {
const listings = desktopListings(ctx);
const searches = desktopSearches(ctx).filter(s => s.category === 'kauf');
const [activeOnly, setActiveOnly] = React.useState(false);
const [bestSort, setBestSort] = React.useState('score');
const user = ctx.user || {};
const scoredListings = listings.filter(l => l.aiScore);
const avgScore = scoredListings.length ? Math.round(scoredListings.reduce((sum, l) => sum + Number(l.aiScore || 0), 0) / scoredListings.length) : '—';
const recentActivity = desktopNotifications(ctx).slice(0, 4);
const today = new Date().toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' });
const visibleSearches = desktopFilterByQuery(searches, searchQuery).filter(s => !activeOnly || s.active);
const firstVisibleSearch = visibleSearches[0] || searches[0];
const bestDeals = desktopFilterByQuery(listings, searchQuery)
.filter(l => l.type === 'kauf' && l.aiScore)
.sort((a, b) => {
if (bestSort === 'price') return Number(a.price || 0) - Number(b.price || 0);
if (bestSort === 'newest') return new Date(b.posted || 0) - new Date(a.posted || 0);
return Number(b.aiScore || 0) - Number(a.aiScore || 0);
})
.slice(0, 5);
return (
{user?.isAdmin && } onClick={onOpenAdmin}>Jobs}
} onClick={onNewSearch}>Neue Suche
>}
{...topBarProps}
/>
{/* Stats row */}
s.active).length} icon={} delta={`${searches.length} insgesamt`} />
s+x.matches, 0)} icon={} delta="alle Plattformen" />
s+x.newToday, 0)}`} icon={} delta="seit Mitternacht" trend="up" accent />
} delta={scoredListings.length ? `${scoredListings.length} bewertet` : 'noch keine KI-Werte'} trend={scoredListings.length ? 'up' : null} />
{/* Two-column main grid */}
{/* Active searches table */}
Ihre Kauf-Suchen
{searches.filter(s => s.active).length} aktiv · {searches.length - searches.filter(s => s.active).length} pausiert
} size="sm" onClick={() => setActiveOnly(v => !v)}>
{activeOnly ? 'Aktive' : 'Filter'}
Suche
Lage & Budget
Treffer
Neu heute
Letzter Lauf
{visibleSearches.map((s, i) => (
onOpenResults(s.id)} style={{
display: 'grid', gridTemplateColumns: '1.6fr 1fr 0.8fr 0.7fr 0.7fr 32px',
padding: '14px 20px', alignItems: 'center', gap: 8,
borderBottom: i < visibleSearches.length - 1 ? '1px solid var(--border)' : 'none',
fontSize: 13, cursor: 'pointer',
}}>
{s.name}
{desktopSearchPlatforms(s).map(p => {p === 'immoscout24' ? 'Scout24' : 'Kleinanz.'})}
{s.aiEnabled && }>KI}
{s.city} +{s.radius}km
{fmtPriceShort(s.priceMin)}–{fmtPriceShort(s.priceMax)}
{s.matches}
{s.newToday > 0
? +{s.newToday}
: —
}
{fmtRelative(s.lastRun)}
))}
{visibleSearches.length === 0 && (
Keine Kauf-Suchen passen zur aktuellen Suche.
)}
{/* Right column */}
{/* Daily-quota / system */}
System
Tageskontingent · zurückgesetzt 00:00 UTC
}>aktiv
s.active).length} total={ctx.taskLimit?.max_tasks || Math.max(1, searches.length)} color="var(--info)" />
!n.read).length || 0} total={Math.max(1, ctx.notifications?.length || 1)} color="var(--success)" />
{/* Recent activity */}
Letzte Aktivität
{recentActivity.length === 0 ? (
Noch keine Aktivitäten.
) : recentActivity.map((a, i) => (
{a.kind === 'ai-high' ? : a.kind === 'new-match' ? : }
{a.title}
{fmtRelative(a.at)}
))}
{/* Best deals row */}
Kauf
} onClick={() => setBestSort(bestSort === 'score' ? 'price' : bestSort === 'price' ? 'newest' : 'score')}>
{bestSort === 'score' ? 'Score' : bestSort === 'price' ? 'Preis' : 'Neueste'}
firstVisibleSearch && onOpenResults(firstVisibleSearch.id)}>Alle Inserate →
}
/>
{bestDeals.map(l => (
))}
);
}
function Quota({ label, used, total, color }) {
const pct = (used / total) * 100;
return (
{label}
{used.toLocaleString('de-DE')} / {total.toLocaleString('de-DE')}
);
}
function BestDealCard({ listing, onTap }) {
const photos = desktopPhotos(listing);
return (
onTap && onTap(listing.id)} style={{
background: 'var(--surface)', border: '1px solid var(--border)',
borderRadius: 12, overflow: 'hidden', cursor: 'pointer',
}}>
{fmtPriceShort(listing.price)}
{listing.title}
{listing.district}, {listing.city}
{fmtArea(listing.area)}
·
{listing.rooms} Zi.
·
{listing.baujahr}
);
}
Object.assign(window, { DashboardDesktop });