diff --git a/src/components/supply/PreMarketPanel.tsx b/src/components/supply/PreMarketPanel.tsx index 28fde35..57b1b86 100644 --- a/src/components/supply/PreMarketPanel.tsx +++ b/src/components/supply/PreMarketPanel.tsx @@ -9,19 +9,20 @@ import { useToastStore } from '../../stores/toastStore' import { DS_BORDER, DS_PRE_MARKET, DS_SURFACE, DS_TEXT } from '../../lib/ds' import { SectionTitle } from './PropertyDetailHelpers' import { PreMarketDemandIntelligence } from './PreMarketDemandIntelligence' -import { PreMarketUnitGrid } from './PreMarketUnitGrid' +import { PreMarketUnitGrid, type UnitReleaseState } from './PreMarketUnitGrid' export const MOCK_TODAY = new Date('2026-05-20') export function PreMarketPanel({ p }: { p: Property }) { const [enabled, setEnabled] = useState(p.schattenmarktRelease?.enabled ?? false) const [leadTimeMonths, setLeadTimeMonths] = useState(p.schattenmarktRelease?.leadTimeMonths ?? 6) - const [unitStates, setUnitStates] = useState>(() => { - const init: Record = {} + const [unitStates, setUnitStates] = useState>(() => { + const init: Record = {} for (const u of p.units ?? []) { init[u.id] = { enabled: u.schattenmarktRelease?.enabled ?? false, availableFrom: u.schattenmarktRelease?.availableFrom ?? u.leaseEndDate ?? '', + anonymous: u.schattenmarktRelease?.anonymous ?? false, } } return init @@ -80,11 +81,11 @@ export function PreMarketPanel({ p }: { p: Property }) { if (enabled) save(enabled, months) } - async function saveUnit(unitId: string, nextEnabled: boolean, nextDate: string) { + async function saveUnit(unitId: string, nextEnabled: boolean, nextDate: string, nextAnonymous: boolean) { setUnitSaving(prev => ({ ...prev, [unitId]: true })) try { await MockupUnitProvider.update(unitId, { - schattenmarktRelease: { enabled: nextEnabled, availableFrom: nextDate || undefined }, + schattenmarktRelease: { enabled: nextEnabled, availableFrom: nextDate || undefined, anonymous: nextAnonymous }, }) await queryClient.invalidateQueries({ queryKey: ['property', p.id] }) await queryClient.invalidateQueries({ queryKey: ['properties'] }) diff --git a/src/components/supply/PreMarketUnitGrid.tsx b/src/components/supply/PreMarketUnitGrid.tsx index bfcaad5..5774f2f 100644 --- a/src/components/supply/PreMarketUnitGrid.tsx +++ b/src/components/supply/PreMarketUnitGrid.tsx @@ -1,16 +1,23 @@ -import { Box, CircularProgress, Switch, TextField, Typography } from '@mui/material' +import { Box, CircularProgress, Switch, TextField, Tooltip, Typography } from '@mui/material' +import { EyeOff } from 'lucide-react' import type { Property } from '../../domain/property' import { DS_PRE_MARKET, DS_TEXT } from '../../lib/ds' import { floorLabel } from './PropertyDetailHelpers' type PropertyUnit = NonNullable[number] +export interface UnitReleaseState { + enabled: boolean + availableFrom: string + anonymous: boolean +} + interface Props { units: PropertyUnit[] - unitStates: Record + unitStates: Record unitSaving: Record - setUnitStates: React.Dispatch>> - saveUnit: (unitId: string, enabled: boolean, availableFrom: string) => Promise + setUnitStates: React.Dispatch>> + saveUnit: (unitId: string, enabled: boolean, availableFrom: string, anonymous: boolean) => Promise } export function PreMarketUnitGrid({ units, unitStates, unitSaving, setUnitStates, saveUnit }: Props) { @@ -20,40 +27,86 @@ export function PreMarketUnitGrid({ units, unitStates, unitSaving, setUnitStates Einheiten freigeben {units.map(u => { - const us = unitStates[u.id] ?? { enabled: false, availableFrom: '' } + const us = unitStates[u.id] ?? { enabled: false, availableFrom: '', anonymous: false } return ( + {/* Unit info + anonym toggle (shown when enabled) */} {floorLabel(u)}{u.unitLabel ? ` · ${u.unitLabel}` : ''} {u.areaSqm.toLocaleString('de-CH')} m² - {u.currentTenant ? ` · ${u.currentTenant}` : ''} + {us.enabled && ( + + { + const next = { ...us, anonymous: !us.anonymous } + setUnitStates(prev => ({ ...prev, [u.id]: next })) + saveUnit(u.id, us.enabled, us.availableFrom, !us.anonymous) + }} + > + + + Anonym + + { + const next = { ...us, anonymous: checked } + setUnitStates(prev => ({ ...prev, [u.id]: next })) + saveUnit(u.id, us.enabled, us.availableFrom, checked) + }} + onClick={e => e.stopPropagation()} + sx={{ + width: 28, height: 16, p: 0, + '& .MuiSwitch-switchBase': { p: '2px', '&.Mui-checked': { transform: 'translateX(12px)', color: '#fff' } }, + '& .MuiSwitch-thumb': { width: 12, height: 12 }, + '& .MuiSwitch-track': { borderRadius: 8, bgcolor: '#cbd5e1' }, + '& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': { bgcolor: '#8b5cf6' }, + }} + /> + + + )} + + {/* Available-from date */} { const next = { ...us, availableFrom: e.target.value } setUnitStates(prev => ({ ...prev, [u.id]: next })) - if (us.enabled) saveUnit(u.id, true, e.target.value) + if (us.enabled) saveUnit(u.id, true, e.target.value, us.anonymous) }} /> - + + {/* Enabled toggle */} + {unitSaving[u.id] && } { const next = { ...us, enabled: checked } setUnitStates(prev => ({ ...prev, [u.id]: next })) - saveUnit(u.id, checked, us.availableFrom) + saveUnit(u.id, checked, us.availableFrom, us.anonymous) }} sx={{ '& .MuiSwitch-switchBase.Mui-checked': { color: DS_PRE_MARKET.accent }, diff --git a/src/domain/property.ts b/src/domain/property.ts index e29db16..ee2ac60 100644 --- a/src/domain/property.ts +++ b/src/domain/property.ts @@ -163,7 +163,7 @@ export interface Property { importedAt?: string lastUpdatedAt?: string - schattenmarktRelease?: { enabled: boolean; leadTimeMonths?: number } + schattenmarktRelease?: { enabled: boolean; leadTimeMonths?: number; anonymous?: boolean } status?: 'ACTIVE' | 'INACTIVE' | 'DRAFT' | 'ARCHIVED' lastReviewedAt?: string diff --git a/src/domain/unit.ts b/src/domain/unit.ts index 37e6ea7..0a1ee9d 100644 --- a/src/domain/unit.ts +++ b/src/domain/unit.ts @@ -33,6 +33,7 @@ export interface PropertyUnit { schattenmarktRelease?: { enabled: boolean availableFrom?: string // ISO date + anonymous?: boolean // hide address/name in pre-market feed } }