|
|
|
@ -5,40 +5,44 @@ import { IOSDevice } from './frames/IOSDevice.jsx'; |
|
|
|
import { FitWrap } from './FitWrap.jsx'; |
|
|
|
import { FitWrap } from './FitWrap.jsx'; |
|
|
|
import { ClinicLeafletMap } from './ClinicLeafletMap.jsx'; |
|
|
|
import { ClinicLeafletMap } from './ClinicLeafletMap.jsx'; |
|
|
|
|
|
|
|
|
|
|
|
/** Палитра и типографика ближе к скриншоту Oclinica */ |
|
|
|
/** Палитра и toolbar синхронизированы с clinic-ecosystem mobile-app */ |
|
|
|
const oc = { |
|
|
|
const oc = { |
|
|
|
pageBg: '#F2F2F2', |
|
|
|
pageBg: '#FFFFFF', |
|
|
|
headerBg: '#FFFFFF', |
|
|
|
headerBg: '#FFFFFF', |
|
|
|
card: '#FFFFFF', |
|
|
|
card: '#FFFFFF', |
|
|
|
/** Телефон и «Записаться на приём» — один фон и цвет текста */ |
|
|
|
border: '#E3EBEB', |
|
|
|
phoneBtnBg: '#9ad1d8', |
|
|
|
fg: '#172121', |
|
|
|
phoneBtnFg: '#001c22', |
|
|
|
mutedFg: '#6F7D7D', |
|
|
|
phoneBtnShadow: '0 3px 14px rgba(0, 28, 34, 0.08)', |
|
|
|
primary: '#4c9a9a', |
|
|
|
bookBtnBg: '#9ad1d8', |
|
|
|
/** Телефон и «Записаться на приём» как primary из mobile-app */ |
|
|
|
bookBtnFg: '#001c22', |
|
|
|
phoneBtnBg: '#4c9a9a', |
|
|
|
chatBorder: '#C4A574', |
|
|
|
phoneBtnFg: '#FFFFFF', |
|
|
|
chatFg: '#6B542E', |
|
|
|
phoneBtnShadow: '0 4px 14px rgba(76, 154, 154, 0.24)', |
|
|
|
openBadgeBg: '#769197', |
|
|
|
bookBtnBg: '#4c9a9a', |
|
|
|
|
|
|
|
bookBtnFg: '#FFFFFF', |
|
|
|
|
|
|
|
chatBorder: '#D8E3E3', |
|
|
|
|
|
|
|
chatFg: '#4A5A5A', |
|
|
|
|
|
|
|
openBadgeBg: '#4c9a9a', |
|
|
|
openBadgeFg: '#FFFFFF', |
|
|
|
openBadgeFg: '#FFFFFF', |
|
|
|
/** Блок «Почему нас выбирают» */ |
|
|
|
/** Блок «Почему нас выбирают» */ |
|
|
|
hWhy: '#B88E71', |
|
|
|
hWhy: '#4A6E6E', |
|
|
|
whyWrapBg: '#EBEDF0', |
|
|
|
whyWrapBg: '#F4F8F8', |
|
|
|
/** Звезда над заголовком «Почему нас выбирают» */ |
|
|
|
/** Звезда над заголовком «Почему нас выбирают» */ |
|
|
|
whyHeaderStar: '#5f96a0', |
|
|
|
whyHeaderStar: '#4c9a9a', |
|
|
|
/** Иконки Email / Веб-сайт */ |
|
|
|
/** Иконки Email / Веб-сайт */ |
|
|
|
whyInfoIconBg: '#f8faf9', |
|
|
|
whyInfoIconBg: '#F7FAFA', |
|
|
|
whyInfoIconFg: '#619799', |
|
|
|
whyInfoIconFg: '#4c9a9a', |
|
|
|
whyRowLabel: '#5A9E95', |
|
|
|
whyRowLabel: '#4c9a9a', |
|
|
|
whyRowValue: '#3A4149', |
|
|
|
whyRowValue: '#2F3B3B', |
|
|
|
statCardValue: '#599195', |
|
|
|
statCardValue: '#4c9a9a', |
|
|
|
statCardLabel: '#6B7684', |
|
|
|
statCardLabel: '#6B7A7A', |
|
|
|
noteBg: '#E8F4FC', |
|
|
|
noteBg: '#ECF6F6', |
|
|
|
noteBorder: '#B9D8EE', |
|
|
|
noteBorder: '#CFE3E3', |
|
|
|
noteFg: '#245A7A', |
|
|
|
noteFg: '#2C5F62', |
|
|
|
routeBtnBg: '#EBEDEF', |
|
|
|
routeBtnBg: '#EEF3F3', |
|
|
|
routeBtnFg: '#4A5560', |
|
|
|
routeBtnFg: '#4A5A5A', |
|
|
|
teal: '#1F8F85', |
|
|
|
teal: '#4c9a9a', |
|
|
|
tealDark: '#166B63', |
|
|
|
tealDark: '#4c9a9a', |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function MiniBuilding() { |
|
|
|
function MiniBuilding() { |
|
|
|
@ -106,28 +110,57 @@ function SocialYoutubeIcon({ size = 26, color = oc.whyHeaderStar, playColor = '# |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function RoundChatTabIcon({ size = 24, sw = 1.9, style }) { |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" style={style}> |
|
|
|
|
|
|
|
<circle cx="12" cy="11.5" r="7.5" /> |
|
|
|
|
|
|
|
<path d="M8.8 18.1l-2.1 2.4.5-3.4" /> |
|
|
|
|
|
|
|
</svg> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function OclinicaTabBar() { |
|
|
|
function OclinicaTabBar() { |
|
|
|
const tab = (label, Icon, active) => ( |
|
|
|
const items = [ |
|
|
|
<div |
|
|
|
{ label: 'Главная', Icon: I.home, to: '/' }, |
|
|
|
|
|
|
|
{ label: 'Приемы', Icon: I.calendar, to: '/appointments' }, |
|
|
|
|
|
|
|
{ label: 'Чат', Icon: RoundChatTabIcon, to: '/chat' }, |
|
|
|
|
|
|
|
{ label: 'Профиль', Icon: I.profile, to: '/profile' }, |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const tab = ({ label, Icon, to }) => ( |
|
|
|
|
|
|
|
<Link |
|
|
|
key={label} |
|
|
|
key={label} |
|
|
|
|
|
|
|
to={to} |
|
|
|
style={{ |
|
|
|
style={{ |
|
|
|
flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3, |
|
|
|
flex: 1, |
|
|
|
padding: '5px 0 2px', color: active ? oc.tealDark : '#9AA7B4', |
|
|
|
textDecoration: 'none', |
|
|
|
fontSize: 10, fontWeight: active ? 700 : 600, |
|
|
|
color: 'inherit', |
|
|
|
}} |
|
|
|
}} |
|
|
|
> |
|
|
|
> |
|
|
|
<Icon size={22} sw={active ? 2.1 : 1.75} style={{ color: active ? oc.tealDark : '#9AA7B4' }} /> |
|
|
|
<div |
|
|
|
<span>{label}</span> |
|
|
|
style={{ |
|
|
|
</div> |
|
|
|
position: 'relative', |
|
|
|
|
|
|
|
flex: 1, |
|
|
|
|
|
|
|
display: 'flex', |
|
|
|
|
|
|
|
flexDirection: 'column', |
|
|
|
|
|
|
|
alignItems: 'center', |
|
|
|
|
|
|
|
justifyContent: 'flex-end', |
|
|
|
|
|
|
|
gap: 1, |
|
|
|
|
|
|
|
minHeight: 56, |
|
|
|
|
|
|
|
color: oc.mutedFg, |
|
|
|
|
|
|
|
fontSize: 12, |
|
|
|
|
|
|
|
fontWeight: 500, |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<Icon size={24} sw={1.9} style={{ color: oc.mutedFg }} /> |
|
|
|
|
|
|
|
<span>{label}</span> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</Link> |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<div style={{ display: 'flex', paddingBottom: 20 }}> |
|
|
|
<div style={{ display: 'flex', gap: 8, padding: '8px 16px calc(12px + env(safe-area-inset-bottom, 0px))' }}> |
|
|
|
<Link to="/" style={{ flex: 1, textDecoration: 'none', color: 'inherit' }}> |
|
|
|
{items.map(tab)} |
|
|
|
{tab('Главная', I.home, false)} |
|
|
|
|
|
|
|
</Link> |
|
|
|
|
|
|
|
{tab('Клиники', I.pin, true)} |
|
|
|
|
|
|
|
{tab('Запись', I.calendar, false)} |
|
|
|
|
|
|
|
{tab('Профиль', I.profile, false)} |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -285,7 +318,7 @@ function ClinicCirclePhoto({ imageUrl, href }) { |
|
|
|
return img; |
|
|
|
return img; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const FOOTER_H = 162; |
|
|
|
const FOOTER_H = 92; |
|
|
|
/** Выше внутренних слоёв Leaflet (~400–700), чтобы хром не перекрывался картой при скролле */ |
|
|
|
/** Выше внутренних слоёв Leaflet (~400–700), чтобы хром не перекрывался картой при скролле */ |
|
|
|
const Z_SCROLL = 0; |
|
|
|
const Z_SCROLL = 0; |
|
|
|
const Z_HEADER = 2000; |
|
|
|
const Z_HEADER = 2000; |
|
|
|
@ -327,7 +360,7 @@ function ContactsPhoneBody() { |
|
|
|
background: oc.pageBg, |
|
|
|
background: oc.pageBg, |
|
|
|
overflow: 'hidden', |
|
|
|
overflow: 'hidden', |
|
|
|
fontFamily: 'var(--font-base), "Inter", system-ui, sans-serif', |
|
|
|
fontFamily: 'var(--font-base), "Inter", system-ui, sans-serif', |
|
|
|
color: '#1F2A37', |
|
|
|
color: oc.fg, |
|
|
|
}}> |
|
|
|
}}> |
|
|
|
<div style={{ |
|
|
|
<div style={{ |
|
|
|
position: 'absolute', inset: 0, |
|
|
|
position: 'absolute', inset: 0, |
|
|
|
@ -344,16 +377,16 @@ function ContactsPhoneBody() { |
|
|
|
padding: '10px 12px 11px', |
|
|
|
padding: '10px 12px 11px', |
|
|
|
position: 'sticky', top: 0, zIndex: Z_HEADER, |
|
|
|
position: 'sticky', top: 0, zIndex: Z_HEADER, |
|
|
|
background: oc.headerBg, |
|
|
|
background: oc.headerBg, |
|
|
|
borderBottom: '1px solid #EFEFEF', |
|
|
|
borderBottom: `1px solid ${oc.border}`, |
|
|
|
}}> |
|
|
|
}}> |
|
|
|
<button type="button" onClick={goBack} className="press" style={{ |
|
|
|
<button type="button" onClick={goBack} className="press" style={{ |
|
|
|
width: 38, height: 38, borderRadius: 999, background: '#F5F5F5', |
|
|
|
width: 38, height: 38, borderRadius: 999, background: '#F4F7F7', |
|
|
|
display: 'flex', alignItems: 'center', justifyContent: 'center', |
|
|
|
display: 'flex', alignItems: 'center', justifyContent: 'center', |
|
|
|
border: 0, |
|
|
|
border: `1px solid ${oc.border}`, |
|
|
|
}}> |
|
|
|
}}> |
|
|
|
<I.chevL size={20} style={{ color: '#2A3540' }} /> |
|
|
|
<I.chevL size={20} style={{ color: oc.fg }} /> |
|
|
|
</button> |
|
|
|
</button> |
|
|
|
<h1 style={{ margin: 0, fontSize: 17, fontWeight: 700, textAlign: 'center', color: '#1F2A37' }}>Контакты</h1> |
|
|
|
<h1 style={{ margin: 0, fontSize: 17, fontWeight: 600, textAlign: 'center', color: oc.fg }}>Контакты</h1> |
|
|
|
<span /> |
|
|
|
<span /> |
|
|
|
</header> |
|
|
|
</header> |
|
|
|
|
|
|
|
|
|
|
|
@ -531,31 +564,29 @@ function ContactsPhoneBody() { |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div style={{ marginTop: 10 }}> |
|
|
|
|
|
|
|
<Link to="/" className="press" style={{ |
|
|
|
|
|
|
|
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10, |
|
|
|
|
|
|
|
width: '100%', padding: '15px 16px', borderRadius: 16, textDecoration: 'none', |
|
|
|
|
|
|
|
background: oc.bookBtnBg, |
|
|
|
|
|
|
|
color: oc.bookBtnFg, fontWeight: 800, fontSize: 16, letterSpacing: 0.02, |
|
|
|
|
|
|
|
boxShadow: '0 6px 16px rgba(76, 154, 154, 0.25)', |
|
|
|
|
|
|
|
border: '1px solid rgba(76,154,154,0.2)', |
|
|
|
|
|
|
|
}}> |
|
|
|
|
|
|
|
<I.calendar size={21} sw={2} style={{ color: oc.bookBtnFg }} /> |
|
|
|
|
|
|
|
Записаться на приём |
|
|
|
|
|
|
|
</Link> |
|
|
|
|
|
|
|
</div> |
|
|
|
<div style={{ height: 20 }} /> |
|
|
|
<div style={{ height: 20 }} /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div style={{ |
|
|
|
<div style={{ |
|
|
|
position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: Z_FOOTER_BAR, |
|
|
|
position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: Z_FOOTER_BAR, |
|
|
|
background: 'rgba(255,255,255,0.94)', |
|
|
|
background: oc.card, |
|
|
|
backdropFilter: 'blur(16px) saturate(180%)', |
|
|
|
borderTop: `1px solid ${oc.border}`, |
|
|
|
WebkitBackdropFilter: 'blur(16px) saturate(180%)', |
|
|
|
boxShadow: 'none', |
|
|
|
borderTop: '1px solid #E8E8E8', |
|
|
|
|
|
|
|
boxShadow: '0 -4px 24px rgba(15,30,40,0.06)', |
|
|
|
|
|
|
|
}}> |
|
|
|
}}> |
|
|
|
<div style={{ padding: '10px 16px 6px' }}> |
|
|
|
|
|
|
|
<Link to="/" className="press" style={{ |
|
|
|
|
|
|
|
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10, |
|
|
|
|
|
|
|
width: '100%', padding: '15px 16px', borderRadius: 16, textDecoration: 'none', |
|
|
|
|
|
|
|
background: oc.bookBtnBg, |
|
|
|
|
|
|
|
color: oc.bookBtnFg, fontWeight: 800, fontSize: 16, letterSpacing: 0.02, |
|
|
|
|
|
|
|
boxShadow: '0 6px 18px rgba(0, 28, 34, 0.1)', |
|
|
|
|
|
|
|
border: '1px solid rgba(255,255,255,0.35)', |
|
|
|
|
|
|
|
}}> |
|
|
|
|
|
|
|
<I.calendar size={21} sw={2} style={{ color: oc.bookBtnFg }} /> |
|
|
|
|
|
|
|
Записаться на приём |
|
|
|
|
|
|
|
</Link> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<OclinicaTabBar /> |
|
|
|
<OclinicaTabBar /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|