From de96895e9c5a6e97fc1bc9d01aae5c30ba3f5b7e Mon Sep 17 00:00:00 2001 From: Aleksey Razorvin Date: Sun, 19 Apr 2026 18:48:08 +0500 Subject: [PATCH] Add articles list and detail screens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enriched the 4 articles in data.js with id, doctorId, hero color, emoji, date, lede, and structured body blocks (paragraphs, headings, bullet lists, tone-variant callouts). New screens: - ArticlesScreen — tag-filtered list with hero-card layout - ArticleDetailScreen — hero block, meta row, lede, body renderer (p/h/ul/callout), author card linking to doctor profile, CTA to book the author, and "Related" footer Home card and feed sections now link to detail and list screens. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/App.jsx | 5 + src/PhoneApp.jsx | 3 + src/data.js | 111 ++++++++++++++- src/screens/screens-articles.jsx | 234 +++++++++++++++++++++++++++++++ src/screens/screens-home.jsx | 17 +-- 5 files changed, 358 insertions(+), 12 deletions(-) create mode 100644 src/screens/screens-articles.jsx diff --git a/src/App.jsx b/src/App.jsx index 9b1b245..5a42b12 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -69,6 +69,11 @@ const SCREEN_OPTIONS = [ { id: 'telemed', lb: 'Телемед' }, { id: 'medcard', lb: 'Медкарта' }, { id: 'notifications', lb: 'Уведомления' }, + { id: 'articles', lb: 'Статьи врачей' }, + { id: 'article:otitis-kids', lb: 'Статья: отит у ребёнка' }, + { id: 'article:septoplasty-recovery', lb: 'Статья: восстановление после септопластики' }, + { id: 'article:throat-pregnancy', lb: 'Статья: горло при беременности' }, + { id: 'article:hearing-check', lb: 'Статья: когда проверить слух' }, ]; function applyTheme(tw) { diff --git a/src/PhoneApp.jsx b/src/PhoneApp.jsx index 2c7495f..f4bee3e 100644 --- a/src/PhoneApp.jsx +++ b/src/PhoneApp.jsx @@ -13,6 +13,7 @@ import { ChatTabScreen, ProfileTabScreen, QRScreen, TelemedScreen, MedcardScreen, NotificationsScreen, } from './screens/screens-misc.jsx'; +import { ArticlesScreen, ArticleDetailScreen } from './screens/screens-articles.jsx'; function renderScreen(screenId, nav, ctx) { const parts = screenId.split(':'); @@ -40,6 +41,8 @@ function renderScreen(screenId, nav, ctx) { case 'telemed': return ; case 'medcard': return ; case 'notifications': return ; + case 'articles': return ; + case 'article': return ; default: return
Экран не найден: {screenId}
; } } diff --git a/src/data.js b/src/data.js index e8e7fec..18d9faf 100644 --- a/src/data.js +++ b/src/data.js @@ -60,10 +60,113 @@ export const CLINIC_DATA = { { id: 'r5', name: 'Посев на микрофлору', date: '20 апр 2026',doctor: 'syndaev', status: 'pending', kind: 'lab' }, ], articles: [ - { tag: 'Дети', title: 'Как понять, что у ребёнка отит', mins: 4, author: 'Макарова Л.Г.' }, - { tag: 'Операции', title: 'Восстановление после септопластики', mins: 6, author: 'Синдяев А.В.' }, - { tag: 'Беременность', title: 'Безопасно лечим горло при беременности', mins: 5, author: 'Лобанова И.Ю.' }, - { tag: 'Слух', title: 'Когда пора проверить слух', mins: 3, author: 'Семерикова Н.А.' }, + { + id: 'otitis-kids', + tag: 'Дети', + title: 'Как понять, что у ребёнка отит', + mins: 4, + author: 'Макарова Л.Г.', + doctorId: 'makarova', + hero: '#F5EDDF', + emoji: '👶', + date: '12 апр 2026', + lede: 'Ребёнок капризничает и трёт ушко? Рассказываем, когда это повод срочно показаться врачу, а когда можно подождать.', + body: [ + { type: 'p', text: 'Отит — одна из самых частых причин обращения к педиатру у детей до 5 лет. Пик заболеваемости приходится на осенне-зимний сезон: ОРВИ даёт осложнение на ухо, и слизистая слуховой трубы воспаляется следом за носоглоткой.' }, + { type: 'h', text: 'На что обращать внимание' }, + { type: 'ul', items: [ + 'Ребёнок дёргает или трёт ушко', + 'Беспокойный сон, плач при кормлении', + 'Температура выше 38°C без видимой причины', + 'Снижение реакции на тихие звуки, просит повторить', + 'Выделения из слухового прохода', + ] }, + { type: 'h', text: 'Когда нужен врач в тот же день' }, + { type: 'p', text: 'Если ребёнку меньше 2 лет, боль длится более суток, температура выше 38,5°C или появились гнойные выделения — не откладывайте визит. При двустороннем остром отите антибиотик нужен почти всегда.' }, + { type: 'callout', tone: 'danger', title: 'Чего не делать до осмотра', text: 'Не закапывайте борный спирт и масла, не грейте ухо компрессами, не давайте анальгин. Это может навредить и смазать картину для врача.' }, + { type: 'p', text: 'Если есть сомнения — позвоните в клинику или напишите в чат. Детский ЛОР поможет оценить ситуацию и подскажет, нужно ли везти ребёнка на приём сегодня.' }, + ], + }, + { + id: 'septoplasty-recovery', + tag: 'Операции', + title: 'Восстановление после септопластики', + mins: 6, + author: 'Синдяев А.В.', + doctorId: 'syndaev', + hero: '#E3F4F2', + emoji: '🩺', + date: '8 апр 2026', + lede: 'Что происходит после операции по исправлению носовой перегородки и как ускорить восстановление.', + body: [ + { type: 'p', text: 'Септопластика — операция короткая, но восстановление идёт постепенно. Большая часть отёка уходит за первые 2 недели, окончательная форма носа формируется к 3-му месяцу.' }, + { type: 'h', text: 'Первая неделя' }, + { type: 'p', text: 'Сразу после операции в нос устанавливают силиконовые сплинты или тампоны — дышать приходится ртом. Это временно: сплинты снимают на 3–5 день. В этот период важен постельный режим, холод на переносицу первые сутки, обезболивание по схеме.' }, + { type: 'h', text: 'Со 2-й недели — промывания' }, + { type: 'ul', items: [ + 'Солевой раствор 4–6 раз в день', + 'Мягкое удаление корочек у ЛОР-врача', + 'Контрольная эндоскопия на 10–14 день', + ] }, + { type: 'callout', tone: 'warn', title: 'Ограничения на месяц', text: 'Нельзя: баня, сауна, бассейн, спорт, авиаперелёты, алкоголь, острая и горячая пища. Сморкаться — только поочерёдно каждой ноздрёй, без усилия.' }, + { type: 'h', text: 'Когда срочно к врачу' }, + { type: 'p', text: 'Сильная боль, не снимающаяся анальгетиками, температура выше 38,5°C, обильное кровотечение, резкое нарастание отёка с покраснением кожи — повод связаться с хирургом в тот же день. В приложении есть чат с вашим врачом.' }, + ], + }, + { + id: 'throat-pregnancy', + tag: 'Беременность', + title: 'Безопасно лечим горло при беременности', + mins: 5, + author: 'Лобанова И.Ю.', + doctorId: 'lobanova', + hero: '#FDF8E6', + emoji: '🤱', + date: '2 апр 2026', + lede: 'Большинство привычных препаратов при беременности запрещены. Разбираем, что точно безопасно, а что — только по назначению врача.', + body: [ + { type: 'p', text: 'При беременности иммунитет естественно снижается, и горло болит чаще обычного. Главная задача — не навредить малышу лечением: многие антисептики и анальгетики проникают через плаценту.' }, + { type: 'h', text: 'Безопасно на любом сроке' }, + { type: 'ul', items: [ + 'Полоскание солевым раствором (1 ч. л. соли на стакан тёплой воды)', + 'Полоскание отваром ромашки', + 'Обильное тёплое питьё, мёд (если нет аллергии)', + 'Ингаляции физраствором через небулайзер', + ] }, + { type: 'h', text: 'Можно по назначению врача' }, + { type: 'p', text: 'Пастилки Лизобакт и Фарингосепт, спрей Тантум Верде (со 2-го триместра), Мирамистин — применяют после оценки пользы и рисков. Антибиотики — только по строгим показаниям и только группы пенициллинов или цефалоспоринов.' }, + { type: 'callout', tone: 'danger', title: 'Категорически нельзя', text: 'Спиртсодержащие антисептики, аспирин, большинство леденцов с ментолом, прогревания, горчичники. Народная «смазка горла люголем» — только после осмотра врача.' }, + { type: 'h', text: 'Когда срочно к ЛОРу' }, + { type: 'p', text: 'Температура выше 38°C более 2 дней, гнойные налёты на миндалинах, трудно открывать рот, асимметрия горла или сильная боль с одной стороны — немедленно на приём. Возможен паратонзиллярный абсцесс, который требует вскрытия.' }, + ], + }, + { + id: 'hearing-check', + tag: 'Слух', + title: 'Когда пора проверить слух', + mins: 3, + author: 'Семерикова Н.А.', + doctorId: 'semerikova', + hero: '#FCF1F0', + emoji: '👂', + date: '28 мар 2026', + lede: 'Снижение слуха часто развивается медленно, и человек замечает проблему последним. На что обратить внимание, чтобы не упустить момент.', + body: [ + { type: 'p', text: 'В отличие от зрения, слух редко падает резко — исключение только травма или острая сенсоневральная тугоухость, когда помощь нужна в первые 72 часа. Обычно снижение копится годами и становится заметным, когда теряется уже 20–30%.' }, + { type: 'h', text: 'Бытовые признаки' }, + { type: 'ul', items: [ + 'Часто просите повторить сказанное', + 'Увеличиваете громкость ТВ больше, чем раньше', + 'Плохо разбираете речь в шумном кафе', + 'Появился звон или шум в ушах', + 'Близкие говорят, что вы «кричите», когда говорите нормально', + ] }, + { type: 'h', text: 'Группы риска' }, + { type: 'p', text: 'Люди после 50, музыканты, рабочие шумных производств, любители наушников на высокой громкости, перенёсшие черепно-мозговую травму или ототоксичные препараты (некоторые антибиотики и химиотерапия).' }, + { type: 'callout', tone: 'info', title: 'Быстрая проверка', text: 'В приложении есть тест слуха на 3 минуты — покажет ориентир. Если результат пограничный или хуже нормы — запишитесь на аудиометрию у сурдолога для точного диагноза.' }, + { type: 'p', text: 'Ранняя коррекция (слуховой аппарат или лечение причины) останавливает дальнейшее снижение и сохраняет речевую зону коры мозга активной — это критично для качества жизни в пожилом возрасте.' }, + ], + }, ], recovery: { op: 'Септопластика', diff --git a/src/screens/screens-articles.jsx b/src/screens/screens-articles.jsx new file mode 100644 index 0000000..8a06c4e --- /dev/null +++ b/src/screens/screens-articles.jsx @@ -0,0 +1,234 @@ +import React, { useState } from 'react'; +import { I } from '../icons.jsx'; +import { CLINIC_DATA } from '../data.js'; +import { Avatar, ScreenHeader } from '../components.jsx'; + +function ArticleHero({ article, big = false }) { + return ( +
+ {article.tag} +
{article.emoji}
+
+ ); +} + +function renderBlock(b, i) { + if (b.type === 'p') { + return

{b.text}

; + } + if (b.type === 'h') { + return

{b.text}

; + } + if (b.type === 'ul') { + return ( +
    + {b.items.map((it, j) => ( +
  • + + {it} +
  • + ))} +
+ ); + } + if (b.type === 'callout') { + const tones = { + danger: { bg: 'var(--c-accent-50)', border: 'var(--c-accent)', icon: I.shield, color: 'var(--c-accent)' }, + info: { bg: 'var(--c-primary-50)', border: 'var(--c-primary-darker)', icon: I.stetho, color: 'var(--c-primary-darker)' }, + warn: { bg: 'var(--c-warning-50)', border: 'var(--c-warning)', icon: I.bell, color: 'var(--c-warning)' }, + }; + const t = tones[b.tone] || tones.info; + const IconC = t.icon; + return ( +
+ +
+ {b.title &&
{b.title}
} +
{b.text}
+
+
+ ); + } + return null; +} + +export function ArticlesScreen({ nav }) { + const { articles } = CLINIC_DATA; + const tags = ['Все', ...Array.from(new Set(articles.map(a => a.tag)))]; + const [tag, setTag] = useState('Все'); + const filtered = tag === 'Все' ? articles : articles.filter(a => a.tag === tag); + return ( +
+ nav.pop()} rightIcon={I.search} /> +
+ {tags.map(t => ( + + ))} +
+
+ {filtered.map(a => ( + + ))} +
+
+ ); +} + +export function ArticleDetailScreen({ nav, articleId }) { + const a = CLINIC_DATA.articles.find(x => x.id === articleId) || CLINIC_DATA.articles[0]; + const doctor = CLINIC_DATA.doctors.find(d => d.id === a.doctorId); + const related = CLINIC_DATA.articles.filter(x => x.id !== a.id).slice(0, 2); + const [bookmarked, setBookmarked] = useState(false); + + return ( +
+ {/* Floating back button over hero */} +
+ + +
+ + {/* Hero pulled up to fill under status bar area */} +
+
+ {a.tag} +

{a.title}

+
{a.emoji}
+
+
+ + {/* Meta row */} +
+ +
+
{doctor.name.split(' ').slice(0, 2).join(' ')}
+
{a.date} · {a.mins} мин чтения
+
+ +
+ +
+ + {/* Lede */} +
+

{a.lede}

+
+ + {/* Body */} +
+ {a.body.map(renderBlock)} +
+ + {/* Author card */} +
+
+ +
+
Автор статьи
+
{doctor.name.split(' ').slice(0, 2).join(' ')}
+
{doctor.spec} · {doctor.exp} лет
+
+ +
+
+ + {/* CTA */} +
+ +
+ + {/* Related */} + {related.length > 0 && ( +
+

Ещё по теме

+
+ {related.map(r => ( + + ))} +
+
+ )} +
+ ); +} diff --git a/src/screens/screens-home.jsx b/src/screens/screens-home.jsx index fb0f8b8..eed61e4 100644 --- a/src/screens/screens-home.jsx +++ b/src/screens/screens-home.jsx @@ -118,14 +118,15 @@ export function HomeCardsScreen({ nav }) { nav.push('articles')} />
{articles.map((a, i) => ( -