105 lines
3.8 KiB
TypeScript
105 lines
3.8 KiB
TypeScript
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>
|
||
);
|
||
|
||
|