Initial scaffold: Клиника УГН mobile prototype
Ported HTML/CSS/JS design bundle from Claude Design to Vite + React. 20 screens (home 3 variants, booking flow, doctors, appointments, results + audiogram, recovery, audio test, chat, profile, QR, telemed, medcard, notifications). Tweaks panel with iOS/Android frames, layout/accent/font switchers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { TabBar } from './components.jsx';
|
||||
import { HomeCardsScreen, HomeListScreen, HomeFeedScreen } from './screens/screens-home.jsx';
|
||||
import {
|
||||
BookingSpecsScreen, BookingDoctorScreen, BookingTimeScreen,
|
||||
BookingConfirmScreen, BookingSuccessScreen,
|
||||
DoctorsTabScreen, DoctorDetailScreen,
|
||||
} from './screens/screens-booking.jsx';
|
||||
import {
|
||||
ApptsTabScreen, ApptDetailScreen,
|
||||
ResultsScreen, ResultAudioScreen,
|
||||
RecoveryScreen, AudioTestScreen,
|
||||
ChatTabScreen, ProfileTabScreen, QRScreen,
|
||||
TelemedScreen, MedcardScreen, NotificationsScreen,
|
||||
} from './screens/screens-misc.jsx';
|
||||
|
||||
function renderScreen(screenId, nav, ctx) {
|
||||
const parts = screenId.split(':');
|
||||
const id = parts[0];
|
||||
const HOME = { cards: HomeCardsScreen, list: HomeListScreen, feed: HomeFeedScreen }[ctx.homeVariant] || HomeCardsScreen;
|
||||
switch (id) {
|
||||
case 'home': return <HOME nav={nav} ctx={ctx} />;
|
||||
case 'doctors': return <DoctorsTabScreen nav={nav} ctx={ctx} />;
|
||||
case 'doctor': return <DoctorDetailScreen nav={nav} doctorId={parts[1]} />;
|
||||
case 'booking-specs': return <BookingSpecsScreen nav={nav} />;
|
||||
case 'booking-doctor': return <BookingDoctorScreen nav={nav} specId={parts[1]} />;
|
||||
case 'booking-time': return <BookingTimeScreen nav={nav} doctorId={parts[1]} />;
|
||||
case 'booking-confirm': return <BookingConfirmScreen nav={nav} doctorId={parts[1]} dateIdx={+parts[2]} time={parts[3]} />;
|
||||
case 'booking-success': return <BookingSuccessScreen nav={nav} />;
|
||||
case 'appts': return <ApptsTabScreen nav={nav} />;
|
||||
case 'appt': return <ApptDetailScreen nav={nav} apptId={parts[1]} />;
|
||||
case 'results': return <ResultsScreen nav={nav} />;
|
||||
case 'result-audio': return <ResultAudioScreen nav={nav} />;
|
||||
case 'recovery': return <RecoveryScreen nav={nav} />;
|
||||
case 'audiotest': return <AudioTestScreen nav={nav} />;
|
||||
case 'chat': return <ChatTabScreen nav={nav} />;
|
||||
case 'profile': return <ProfileTabScreen nav={nav} ctx={ctx} />;
|
||||
case 'qr': return <QRScreen nav={nav} />;
|
||||
case 'telemed': return <TelemedScreen nav={nav} />;
|
||||
case 'medcard': return <MedcardScreen nav={nav} />;
|
||||
case 'notifications': return <NotificationsScreen nav={nav} />;
|
||||
default: return <div style={{padding: 40, textAlign: 'center'}}>Экран не найден: {screenId}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
const TAB_IDS = ['home', 'appts', 'doctors', 'chat', 'profile'];
|
||||
|
||||
export function PhoneApp({ initialScreen, ctx }) {
|
||||
const [stack, setStack] = useState([initialScreen]);
|
||||
|
||||
useEffect(() => { setStack([initialScreen]); }, [initialScreen]);
|
||||
|
||||
const nav = useMemo(() => ({
|
||||
push: (id) => setStack(s => [...s, id]),
|
||||
pop: () => setStack(s => s.length > 1 ? s.slice(0, -1) : s),
|
||||
set: (id) => setStack([id]),
|
||||
reset:() => setStack(['home']),
|
||||
}), []);
|
||||
|
||||
const current = stack[stack.length - 1];
|
||||
const tabId = TAB_IDS.includes(current.split(':')[0]) ? current.split(':')[0] : null;
|
||||
const showTabBar = tabId !== null;
|
||||
|
||||
const modalScreens = ['qr', 'telemed', 'booking-success', 'audiotest'];
|
||||
const isModal = modalScreens.includes(current.split(':')[0]);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
position: 'absolute', inset: 0,
|
||||
background: 'var(--c-bg)',
|
||||
overflow: 'hidden',
|
||||
fontFamily: 'var(--font-base)',
|
||||
}}>
|
||||
<div style={{ position: 'absolute', inset: 0, overflowY: 'auto', overflowX: 'hidden', paddingTop: 58, paddingBottom: showTabBar ? 80 : 0 }}>
|
||||
{renderScreen(current, nav, ctx)}
|
||||
</div>
|
||||
{showTabBar && !isModal && (
|
||||
<TabBar active={tabId} onChange={(t) => nav.set(t)} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user