This commit is contained in:
Ilnar
2026-03-05 06:55:42 +03:00
commit 36a7d530c1
50 changed files with 3091 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
import React, { useEffect, useRef } from 'react'
type Props = React.TextareaHTMLAttributes<HTMLTextAreaElement> & { value: string; onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void }
export default function AutoTextarea(props: Props){
const ref = useRef<HTMLTextAreaElement|null>(null)
const resize=()=>{ const el=ref.current; if(!el) return; el.style.height='0px'; el.style.height=el.scrollHeight+'px' }
useEffect(()=>{ resize() },[props.value])
return <textarea {...props} ref={ref} onChange={(e)=>{ props.onChange(e); requestAnimationFrame(resize) }} style={{...(props.style||{}), overflow:'hidden'}}/>
}

View File

@@ -0,0 +1,62 @@
import React from 'react'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { clearToken, getToken } from '../api/client'
function NavItem({ to, label }: { to: string; label: string }) {
const loc = useLocation()
const active = loc.pathname === to || loc.pathname.startsWith(to + '/')
return (
<Link
to={to}
className="small"
style={{
padding: '10px 12px',
borderRadius: 12,
border: '1px solid transparent',
background: active ? 'rgba(45,96,255,.10)' : 'transparent',
color: active ? '#2d60ff' : undefined,
fontWeight: active ? 700 : 600,
textDecoration: 'none',
}}
>
{label}
</Link>
)
}
export default function NavBar() {
const nav = useNavigate()
const token = getToken()
return (
<div className="card compact" style={{ marginBottom: 16 }}>
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<div className="row" style={{ alignItems: 'center' }}>
<div style={{ fontWeight: 800, letterSpacing: '-0.03em' }}>AdsAssistant</div>
<div className="row" style={{ marginLeft: 10, gap: 8 }}>
<NavItem to="/briefs" label="Брифы" />
<NavItem to="/tests" label="Тесты" />
</div>
</div>
<div className="row" style={{ alignItems: 'center' }}>
{token ? (
<button
className="btn secondary"
onClick={() => {
clearToken()
nav('/login')
}}
>
Выйти
</button>
) : (
<Link to="/login" className="small">
Вход
</Link>
)}
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,31 @@
import React, { useId, useState } from 'react'
export default function Tooltip({ text }: { text: string }) {
const [open, setOpen] = useState(false)
const id = useId()
return (
<span
style={{ position: 'relative', display: 'inline-flex', alignItems: 'center' }}
onMouseEnter={() => setOpen(true)}
onMouseLeave={() => setOpen(false)}
onFocus={() => setOpen(true)}
onBlur={() => setOpen(false)}
>
<button
type="button"
aria-describedby={id}
className="tipbtn"
title={text}
onClick={() => setOpen((v) => !v)}
>
i
</button>
{open && (
<span id={id} role="tooltip" className="tooltip">
{text}
</span>
)}
</span>
)
}