fix: горизонтальная раскладка GeoField/ContactField и убран max-width у обёрток в TaskDetail
This commit is contained in:
@@ -93,107 +93,121 @@ export default function ContactField({ value, onChange, disabled = false }: Cont
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-muted-foreground">ФИО</label>
|
||||
<div>
|
||||
<div className="flex flex-wrap gap-2 items-start">
|
||||
{/* ФИО */}
|
||||
<Input
|
||||
value={name}
|
||||
onChange={(e) => handleNameChange(e.target.value)}
|
||||
disabled={disabled}
|
||||
placeholder="Иванов И.И."
|
||||
className="h-8"
|
||||
placeholder="ФИО (Иванов И.И.)"
|
||||
className="h-8 flex-1 min-w-[140px]"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-muted-foreground">Должность</label>
|
||||
{/* Должность */}
|
||||
<Input
|
||||
value={position}
|
||||
onChange={(e) => handlePositionChange(e.target.value)}
|
||||
disabled={disabled}
|
||||
placeholder="Директор"
|
||||
className="h-8"
|
||||
placeholder="Должность (Директор)"
|
||||
className="h-8 flex-1 min-w-[140px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-muted-foreground">Телефоны</label>
|
||||
<div className="space-y-1">
|
||||
{phones.map((phone, idx) => (
|
||||
<div key={`phone-${idx}`} className="flex items-center gap-1">
|
||||
<Input
|
||||
value={phone}
|
||||
onChange={(e) => changePhone(idx, e.target.value)}
|
||||
disabled={disabled}
|
||||
placeholder="+7 (999) 123-45-67"
|
||||
className="h-8 flex-1"
|
||||
/>
|
||||
{phones.length > 1 && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0"
|
||||
onClick={() => removePhone(idx)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{/* Телефон — первый + кнопка добавить */}
|
||||
<div className="flex gap-1 flex-1 min-w-[180px]">
|
||||
<Input
|
||||
value={phones[0] || ""}
|
||||
onChange={(e) => changePhone(0, e.target.value)}
|
||||
disabled={disabled}
|
||||
placeholder="Телефон +7 (999) 123-45-67"
|
||||
className="h-8 flex-1 min-w-0"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 text-xs"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0"
|
||||
onClick={addPhone}
|
||||
disabled={disabled}
|
||||
title="Добавить телефон"
|
||||
>
|
||||
<Plus className="h-3 w-3 mr-1" />
|
||||
Добавить телефон
|
||||
<Plus className="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
{/* Email — первый + кнопка добавить */}
|
||||
<div className="flex gap-1 flex-1 min-w-[180px]">
|
||||
<Input
|
||||
value={emails[0] || ""}
|
||||
onChange={(e) => changeEmail(0, e.target.value)}
|
||||
disabled={disabled}
|
||||
placeholder="Email ivan@example.com"
|
||||
className="h-8 flex-1 min-w-0"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0"
|
||||
onClick={addEmail}
|
||||
disabled={disabled}
|
||||
title="Добавить email"
|
||||
>
|
||||
<Plus className="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-muted-foreground">Email</label>
|
||||
<div className="space-y-1">
|
||||
{emails.map((email, idx) => (
|
||||
<div key={`email-${idx}`} className="flex items-center gap-1">
|
||||
{/* Дополнительные телефоны (если есть) */}
|
||||
{phones.length > 1 && (
|
||||
<div className="flex flex-wrap gap-1 mt-1">
|
||||
{phones.slice(1).map((phone, idx) => (
|
||||
<div key={`phone-${idx + 1}`} className="flex items-center gap-1 flex-1 min-w-[180px]">
|
||||
<Input
|
||||
value={email}
|
||||
onChange={(e) => changeEmail(idx, e.target.value)}
|
||||
value={phone}
|
||||
onChange={(e) => changePhone(idx + 1, e.target.value)}
|
||||
disabled={disabled}
|
||||
placeholder="ivan@example.com"
|
||||
className="h-8 flex-1"
|
||||
placeholder="+7 (999) 123-45-67"
|
||||
className="h-8 flex-1 min-w-0"
|
||||
/>
|
||||
{emails.length > 1 && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0"
|
||||
onClick={() => removeEmail(idx)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0"
|
||||
onClick={() => removePhone(idx + 1)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 text-xs"
|
||||
onClick={addEmail}
|
||||
disabled={disabled}
|
||||
>
|
||||
<Plus className="h-3 w-3 mr-1" />
|
||||
Добавить email
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Дополнительные email (если есть) */}
|
||||
{emails.length > 1 && (
|
||||
<div className="flex flex-wrap gap-1 mt-1">
|
||||
{emails.slice(1).map((email, idx) => (
|
||||
<div key={`email-${idx + 1}`} className="flex items-center gap-1 flex-1 min-w-[180px]">
|
||||
<Input
|
||||
value={email}
|
||||
onChange={(e) => changeEmail(idx + 1, e.target.value)}
|
||||
disabled={disabled}
|
||||
placeholder="ivan@example.com"
|
||||
className="h-8 flex-1 min-w-0"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0"
|
||||
onClick={() => removeEmail(idx + 1)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -156,18 +156,18 @@ export default function GeoField({ value, onChange, disabled = false }: GeoField
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex flex-wrap gap-2 items-start">
|
||||
{/* Адрес с подсказками */}
|
||||
<Popover open={isOpen} onOpenChange={setIsOpen} modal={false}>
|
||||
<PopoverAnchor asChild>
|
||||
<div className="relative">
|
||||
<div className="relative flex-1 min-w-[200px]">
|
||||
<MapPin className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder="Начните вводить адрес..."
|
||||
value={inputValue}
|
||||
onChange={(e) => handleAddressChange(e.target.value)}
|
||||
disabled={disabled}
|
||||
className="pl-9"
|
||||
className="pl-9 w-full"
|
||||
/>
|
||||
{isLoading && (
|
||||
<Loader2 className="absolute right-2.5 top-2.5 h-4 w-4 animate-spin text-muted-foreground" />
|
||||
@@ -195,18 +195,19 @@ export default function GeoField({ value, onChange, disabled = false }: GeoField
|
||||
</Popover>
|
||||
|
||||
{/* Координаты — совмещённое поле */}
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-2 flex-1 min-w-[180px]">
|
||||
<Input
|
||||
placeholder="55.707339, 52.315169"
|
||||
value={coordInput}
|
||||
onChange={(e) => handleCoordChange(e.target.value)}
|
||||
disabled={disabled}
|
||||
className="flex-1 font-mono text-sm"
|
||||
className="flex-1 font-mono text-sm min-w-0"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="shrink-0"
|
||||
onClick={handleGeolocate}
|
||||
disabled={disabled || isGeoLoading || !geo.lat || !geo.lng}
|
||||
title="Определить адрес по координатам"
|
||||
|
||||
@@ -1059,7 +1059,7 @@ function FieldValueRow({
|
||||
? new Set([String(editorValue)])
|
||||
: new Set<string>();
|
||||
return (
|
||||
<div className="w-full max-w-[320px]" onClick={e => e.stopPropagation()}>
|
||||
<div className="flex-1 min-w-0" onClick={e => e.stopPropagation()}>
|
||||
<SearchableMultiSelect
|
||||
options={opts.map((o) => ({ value: o.value, label: o.label }))}
|
||||
selected={selected}
|
||||
@@ -1112,7 +1112,7 @@ function FieldValueRow({
|
||||
}
|
||||
if (field.type === 'geo') {
|
||||
return (
|
||||
<div className="w-full max-w-[320px]" onClick={e => e.stopPropagation()}>
|
||||
<div className="flex-1 min-w-0" onClick={e => e.stopPropagation()}>
|
||||
<GeoField
|
||||
value={editorValue as unknown as GeoValue | string | null}
|
||||
onChange={val => onDraftChange?.(val as unknown as string | number | boolean | null | undefined)}
|
||||
@@ -1122,7 +1122,7 @@ function FieldValueRow({
|
||||
}
|
||||
if (field.type === 'company') {
|
||||
return (
|
||||
<div className="w-full max-w-[280px]" onClick={e => e.stopPropagation()}>
|
||||
<div className="flex-1 min-w-0" onClick={e => e.stopPropagation()}>
|
||||
<CompanyFieldInput
|
||||
value={editorValue === null || editorValue === undefined ? '' : String(editorValue)}
|
||||
onChange={val => onDraftChange?.(val)}
|
||||
@@ -1171,7 +1171,7 @@ function FieldValueRow({
|
||||
const opts = field.options && !Array.isArray(field.options) ? (field.options as Record<string, any>) : {};
|
||||
const showSubdirectory = !!opts.showSubdirectory;
|
||||
return (
|
||||
<div className="w-full max-w-[280px]" onClick={e => e.stopPropagation()}>
|
||||
<div className="flex-1 min-w-0" onClick={e => e.stopPropagation()}>
|
||||
{showSubdirectory ? (
|
||||
<TableFieldWithSubdirectory
|
||||
fieldId={field.id}
|
||||
@@ -1206,7 +1206,7 @@ function FieldValueRow({
|
||||
}
|
||||
if (field.type === 'contact') {
|
||||
return (
|
||||
<div className="w-full max-w-[320px]" onClick={e => e.stopPropagation()}>
|
||||
<div className="flex-1 min-w-0" onClick={e => e.stopPropagation()}>
|
||||
<ContactField
|
||||
value={editorValue as any}
|
||||
onChange={(val) => onDraftChange?.(JSON.stringify(val))}
|
||||
@@ -1216,7 +1216,7 @@ function FieldValueRow({
|
||||
}
|
||||
if (field.type === 'task' && field.linkedFormId) {
|
||||
return (
|
||||
<div className="w-full max-w-[320px]" onClick={e => e.stopPropagation()}>
|
||||
<div className="flex-1 min-w-0" onClick={e => e.stopPropagation()}>
|
||||
<TaskFieldSelect
|
||||
formField={field as any}
|
||||
value={editorValue}
|
||||
|
||||
Reference in New Issue
Block a user