fix: team editor layout — compact header with photo matching field height
- Photo 150px wide, stretches to match fields height (no empty space) - Profile header: photo + name/role/instagram inline - Full-width descriptions and biography below - Remove extra closing div that caused TS error
This commit is contained in:
@@ -257,40 +257,31 @@ function TeamMemberEditor() {
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 flex gap-6 items-start">
|
{/* Profile header: photo + name/role/instagram */}
|
||||||
{/* Photo */}
|
<div className="mt-6 flex gap-5 items-start">
|
||||||
<div className="shrink-0">
|
<label className="relative shrink-0 block w-[150px] self-stretch overflow-hidden rounded-xl border border-white/10 cursor-pointer group">
|
||||||
<p className="text-sm text-neutral-400 mb-2">Фото</p>
|
<Image
|
||||||
<label className="relative block w-[130px] aspect-[3/4] overflow-hidden rounded-xl border border-white/10 cursor-pointer group">
|
src={data.image}
|
||||||
<Image
|
alt={data.name || "Фото"}
|
||||||
src={data.image}
|
fill
|
||||||
alt={data.name || "Фото"}
|
className="object-cover"
|
||||||
fill
|
sizes="150px"
|
||||||
className="object-cover"
|
priority
|
||||||
sizes="130px"
|
/>
|
||||||
priority
|
<div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex flex-col items-center justify-center gap-1">
|
||||||
/>
|
{uploading ? (
|
||||||
<div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex flex-col items-center justify-center gap-1">
|
<Loader2 size={20} className="animate-spin text-white" />
|
||||||
{uploading ? (
|
) : (
|
||||||
<Loader2 size={20} className="animate-spin text-white" />
|
<>
|
||||||
) : (
|
<Upload size={20} className="text-white" />
|
||||||
<>
|
<span className="text-[11px] text-white/80">Изменить</span>
|
||||||
<Upload size={20} className="text-white" />
|
</>
|
||||||
<span className="text-[11px] text-white/80">Изменить фото</span>
|
)}
|
||||||
</>
|
</div>
|
||||||
)}
|
<input type="file" accept="image/*" onChange={handleUpload} className="hidden" />
|
||||||
</div>
|
</label>
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
accept="image/*"
|
|
||||||
onChange={handleUpload}
|
|
||||||
className="hidden"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Fields */}
|
<div className="flex-1 space-y-3">
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<InputField
|
<InputField
|
||||||
label="Имя"
|
label="Имя"
|
||||||
@@ -331,7 +322,7 @@ function TeamMemberEditor() {
|
|||||||
validateInstagram(username);
|
validateInstagram(username);
|
||||||
}}
|
}}
|
||||||
placeholder="username"
|
placeholder="username"
|
||||||
className={`w-full rounded-lg border bg-neutral-800 pl-8 pr-10 py-2.5 text-white placeholder-neutral-500 outline-none transition-colors ${
|
className={`w-full rounded-lg border bg-neutral-800 pl-8 pr-10 py-2.5 text-white placeholder-neutral-500 outline-none hover:border-gold/30 transition-colors ${
|
||||||
igStatus === "invalid"
|
igStatus === "invalid"
|
||||||
? "border-red-500 focus:border-red-500"
|
? "border-red-500 focus:border-red-500"
|
||||||
: igStatus === "valid"
|
: igStatus === "valid"
|
||||||
@@ -352,22 +343,27 @@ function TeamMemberEditor() {
|
|||||||
<p className="mt-1 text-xs text-neutral-500">instagram.com/{data.instagram}</p>
|
<p className="mt-1 text-xs text-neutral-500">instagram.com/{data.instagram}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<TextareaField
|
</div>
|
||||||
label="Краткое описание (для карточки)"
|
</div>
|
||||||
value={data.shortDescription}
|
|
||||||
onChange={(v) => setData({ ...data, shortDescription: v })}
|
|
||||||
rows={2}
|
|
||||||
placeholder="1-2 предложения для карусели"
|
|
||||||
/>
|
|
||||||
<TextareaField
|
|
||||||
label="Полное описание (для страницы тренера)"
|
|
||||||
value={data.description}
|
|
||||||
onChange={(v) => setData({ ...data, description: v })}
|
|
||||||
rows={6}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="border-t border-white/5 pt-4 mt-4">
|
{/* Full-width fields */}
|
||||||
<p className="text-sm font-medium text-neutral-300 mb-4">Биография</p>
|
<div className="mt-6 space-y-4">
|
||||||
|
<TextareaField
|
||||||
|
label="Краткое описание (для карточки)"
|
||||||
|
value={data.shortDescription}
|
||||||
|
onChange={(v) => setData({ ...data, shortDescription: v })}
|
||||||
|
rows={2}
|
||||||
|
placeholder="1-2 предложения для карусели"
|
||||||
|
/>
|
||||||
|
<TextareaField
|
||||||
|
label="Полное описание (для страницы тренера)"
|
||||||
|
value={data.description}
|
||||||
|
onChange={(v) => setData({ ...data, description: v })}
|
||||||
|
rows={6}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="border-t border-white/5 pt-4 mt-4">
|
||||||
|
<p className="text-sm font-medium text-neutral-300 mb-4">Биография</p>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<ListField
|
<ListField
|
||||||
label="Опыт"
|
label="Опыт"
|
||||||
@@ -411,6 +407,6 @@ function TeamMemberEditor() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user