feat(workspace): selector de área en GlobalSettingsPanel reemplaza campo libre "Cliente"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,8 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
|
||||
import { useProcessStore } from '@/store/process-store'
|
||||
import { useAuth } from '@/auth/AuthContext'
|
||||
import { formatPercent } from '@/lib/format'
|
||||
import { supabaseAreaRepo } from '@/persistence/supabase/area-repo'
|
||||
import type { Area } from '@/domain/types'
|
||||
|
||||
const CURRENCIES = [
|
||||
{ code: 'USD', label: 'USD — Dólar estadounidense' },
|
||||
@@ -28,7 +30,9 @@ export function GlobalSettingsPanel() {
|
||||
const { user } = useAuth()
|
||||
const isClientRole = user?.platformRole === 'client_editor' || user?.platformRole === 'client_viewer'
|
||||
const [localName, setLocalName] = useState('')
|
||||
const [localClient, setLocalClient] = useState('')
|
||||
const [localAreaId, setLocalAreaId] = useState<string>('')
|
||||
const [areas, setAreas] = useState<Area[]>([])
|
||||
const [areasLoading, setAreasLoading] = useState(false)
|
||||
const [localCurrency, setLocalCurrency] = useState('USD')
|
||||
const [localOverhead, setLocalOverhead] = useState(20)
|
||||
const [localFrequency, setLocalFrequency] = useState(1000)
|
||||
@@ -39,7 +43,18 @@ export function GlobalSettingsPanel() {
|
||||
useEffect(() => {
|
||||
if (!currentProcess) return
|
||||
setLocalName(currentProcess.name)
|
||||
setLocalClient(currentProcess.clientName)
|
||||
setLocalAreaId(currentProcess.areaId ?? '')
|
||||
|
||||
// Cargar áreas de la org del proceso
|
||||
if (currentProcess.orgId) {
|
||||
setAreasLoading(true)
|
||||
supabaseAreaRepo.getByOrg(currentProcess.orgId)
|
||||
.then(setAreas)
|
||||
.catch(() => setAreas([]))
|
||||
.finally(() => setAreasLoading(false))
|
||||
} else {
|
||||
setAreas([])
|
||||
}
|
||||
setLocalCurrency(currentProcess.currency)
|
||||
setLocalOverhead(Math.round(currentProcess.overheadPercentage * 100))
|
||||
setLocalFrequency(currentProcess.annualFrequency)
|
||||
@@ -54,7 +69,7 @@ export function GlobalSettingsPanel() {
|
||||
const clampedHorizon = Math.min(10, Math.max(1, localHorizon))
|
||||
await updateProcess({
|
||||
name: localName.trim() || 'Proceso sin nombre',
|
||||
clientName: localClient.trim(),
|
||||
areaId: localAreaId === '' ? null : localAreaId,
|
||||
currency: localCurrency,
|
||||
overheadPercentage: localOverhead / 100,
|
||||
annualFrequency: Math.max(1, localFrequency),
|
||||
@@ -82,19 +97,35 @@ export function GlobalSettingsPanel() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Cliente */}
|
||||
{/* Área */}
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs font-medium">Cliente</Label>
|
||||
{isClientRole ? (
|
||||
<p className="text-sm text-slate-600 h-8 flex items-center px-1">{localClient || '—'}</p>
|
||||
<Label className="text-xs font-medium">Área</Label>
|
||||
{areasLoading ? (
|
||||
<div className="h-8 bg-slate-100 animate-pulse rounded-md" />
|
||||
) : !currentProcess.orgId ? (
|
||||
<p className="text-sm text-slate-400 h-8 flex items-center px-1 italic">Sin organización asignada</p>
|
||||
) : isClientRole && user?.platformRole === 'client_viewer' ? (
|
||||
<p className="text-sm text-slate-600 h-8 flex items-center px-1">{currentProcess.areaName || '—'}</p>
|
||||
) : (
|
||||
<Input
|
||||
id="client-name"
|
||||
value={localClient}
|
||||
onChange={(e) => { setLocalClient(e.target.value); markDirty() }}
|
||||
placeholder="ej. Empresa ABC"
|
||||
className="h-8 text-sm"
|
||||
/>
|
||||
<Select
|
||||
value={localAreaId}
|
||||
onValueChange={(v) => { setLocalAreaId(v); markDirty() }}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-xs">
|
||||
<SelectValue placeholder="Sin área" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="" className="text-xs text-slate-400 italic">Sin área</SelectItem>
|
||||
{areas.map((a) => (
|
||||
<SelectItem key={a.id} value={a.id} className="text-xs">{a.name}</SelectItem>
|
||||
))}
|
||||
{areas.length === 0 && (
|
||||
<div className="px-2 py-1.5 text-xs text-slate-400">
|
||||
No hay áreas en esta organización
|
||||
</div>
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user