init
This commit is contained in:
104
src/components/booking/BookingSection.tsx
Normal file
104
src/components/booking/BookingSection.tsx
Normal 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>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user