This commit is contained in:
YI FANG
2025-11-26 09:50:49 +08:00
commit 8155c9f95d
43 changed files with 7687 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
import { BOOKING_DOCTORS } from '../../data/mockData';
import { Button, Input } from '../ui';
interface BookingModalProps {
doctor: (typeof BOOKING_DOCTORS)[number];
onClose: () => void;
}
export const BookingModal = ({ doctor, onClose }: BookingModalProps) => (
<div className='fixed inset-0 z-40 flex items-center justify-center bg-black/30'>
<div className='w-[520px] max-w-[95vw] bg-white rounded-3xl shadow-xl overflow-hidden text-sm'>
<div className='px-4 py-3 border-b flex items-center justify-between'>
<div className='font-semibold'> · {doctor.name}</div>
<button className='text-xs text-gray-500' onClick={onClose}>
</button>
</div>
<div className='px-4 py-4 bg-gray-50/60 space-y-3 text-xs text-gray-700'>
<div className='grid grid-cols-2 gap-3'>
<div>
<select className='mt-1 w-full rounded-2xl border px-3 py-1.5 bg-white outline-none text-xs'>
<option></option>
<option></option>
</select>
</div>
<div>
<Input placeholder='如:专家门诊咨询' className='mt-1' />
</div>
<div>
<select className='mt-1 w-full rounded-2xl border px-3 py-1.5 bg-white outline-none text-xs'>
<option></option>
<option></option>
</select>
</div>
<div>
<Input placeholder='例如2025-11-20 上午' className='mt-1' />
</div>
</div>
<div>
<textarea
className='w-full mt-1 rounded-2xl border px-3 py-2 text-xs outline-none focus:ring-2 focus:ring-gray-200 min-h-[72px]'
placeholder='可填写病情简要、既往史、特殊需求等信息'
/>
</div>
<div className='flex items-center justify-between text-[11px] text-gray-500'>
<span>
{doctor.name}{doctor.dept}
</span>
<Button></Button>
</div>
</div>
</div>
</div>
);

View File

@@ -0,0 +1,104 @@
import { BOOKING_DOCTORS } from '../../data/mockData';
import { Card, CardContent, CardHeader } from '../ui';
import { BookingModal } from './BookingModal';
import { cls } from '../../utils/cls';
interface BookingSectionProps {
selectedDay: number;
onSelectDay: (day: number) => void;
bookingDoctor: (typeof BOOKING_DOCTORS)[number] | null;
onSelectDoctor: (doctor: (typeof BOOKING_DOCTORS)[number]) => void;
onCloseModal: () => void;
}
export const BookingSection = ({
selectedDay,
onSelectDay,
bookingDoctor,
onSelectDoctor,
onCloseModal,
}: BookingSectionProps) => (
<div className='grid grid-cols-12 gap-6'>
<div className='col-span-4 space-y-4'>
<Card>
<CardHeader></CardHeader>
<CardContent>
<div className='grid grid-cols-6 gap-2 text-sm'>
{Array.from({ length: 30 }, (_, i) => i + 1).map((day) => (
<button
key={day}
onClick={() => onSelectDay(day)}
className={cls(
'h-9 rounded-2xl border flex items-center justify-center',
selectedDay === day ? 'bg-gray-900 text-white border-gray-900' : 'bg-white hover:bg-gray-50',
)}
>
{day}
</button>
))}
</div>
</CardContent>
</Card>
<Card>
<CardContent>
<div className='flex items-center justify-between text-sm'>
<span></span>
<span className='text-lg font-semibold'>{BOOKING_DOCTORS.length}</span>
</div>
</CardContent>
</Card>
</div>
<div className='col-span-8 space-y-4'>
<Card>
<CardHeader>
<span> · {selectedDay} </span>
<div className='flex items-center gap-2 text-xs'>
<span className='text-gray-500'></span>
<select className='border rounded-2xl px-3 py-1 bg-white outline-none text-xs'>
<option></option>
<option></option>
<option></option>
</select>
</div>
</CardHeader>
</Card>
<div className='grid grid-cols-2 gap-4'>
{BOOKING_DOCTORS.map((doctor) => {
const ratio = doctor.total ? (doctor.total - doctor.remain) / doctor.total : 0;
const percent = Math.round(Math.max(0, Math.min(1, ratio)) * 100);
return (
<button key={doctor.id} onClick={() => onSelectDoctor(doctor)} className='text-left w-full'>
<Card className='bg-gray-50/40'>
<CardContent>
<div className='flex items-start justify-between mb-3'>
<div>
<div className='font-semibold mb-1'>{doctor.name}</div>
<div className='text-xs text-gray-500'>{doctor.dept}</div>
</div>
<span className='px-3 py-1 rounded-2xl border text-xs text-gray-600 bg-white'>{doctor.period}</span>
</div>
<div className='text-xs text-gray-600 space-y-1 mb-2'>
<div>{doctor.total} </div>
<div>
<span className='font-semibold text-gray-900'>{doctor.remain}</span>
</div>
</div>
<div className='h-2 rounded-full bg-gray-200 overflow-hidden'>
<div className='h-full bg-gray-900' style={{ width: `${percent}%` }} />
</div>
</CardContent>
</Card>
</button>
);
})}
</div>
</div>
{bookingDoctor && <BookingModal doctor={bookingDoctor} onClose={onCloseModal} />}
</div>
);