doctor-mail/apps/web/src/app/main/letter/write/page.tsx

128 lines
5.0 KiB
TypeScript

import { useState, useMemo, useCallback, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import Header from './header';
import { SendCard } from './SendCard';
import { Spin, Empty, Input, Alert, message, Pagination } from 'antd';
import { api } from '@nice/client';
import DepartmentSelect from '@web/src/components/models/department/department-select';
import debounce from 'lodash/debounce';
import { SearchOutlined } from '@ant-design/icons';
export default function WriteLetterPage() {
const [searchQuery, setSearchQuery] = useState('');
const [selectedDept, setSelectedDept] = useState<string>();
const [currentPage, setCurrentPage] = useState(1);
const pageSize = 10;
const { data, isLoading, error } = api.staff.findManyWithPagination.useQuery({
page: currentPage,
pageSize,
where: {
deptId: selectedDept,
OR: [{
showname: {
contains: searchQuery
}
}, {
username: {
contains: searchQuery
}
}]
}
});
useEffect(() => {
console.log(selectedDept)
console.log(data)
console.log(searchQuery)
}, [selectedDept, data, searchQuery])
// Reset to first page when search query or department changes
useCallback(() => {
setCurrentPage(1);
}, [searchQuery, selectedDept]);
return (
<div className="min-h-screen bg-gradient-to-b from-slate-50 to-slate-100">
<Header />
<div className="container mx-auto px-4 py-8">
<div className="mb-8 space-y-4">
{/* Search and Filter Section */}
<div className="flex flex-col md:flex-row gap-4 items-center">
<div className="w-full md:w-96">
<Input
prefix={<SearchOutlined className="text-gray-400" />}
placeholder="搜索领导姓名或职级..."
onChange={debounce((e) => setSearchQuery(e.target.value), 300)}
className="w-full"
size="large"
/>
</div>
<DepartmentSelect
size="large"
value={selectedDept}
onChange={setSelectedDept as any}
className="w-full md:w-64"
/>
</div>
{error && (
<Alert
message="加载失败"
description="获取数据时出现错误,请刷新页面重试。"
type="error"
showIcon
/>
)}
</div>
<AnimatePresence>
{isLoading ? (
<div className="flex justify-center items-center py-12">
<Spin size="large" tip="加载中..." />
</div>
) : data?.items.length > 0 ? (
<motion.div
className="grid grid-cols-1 gap-6"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{data?.items.map((item) => (
<SendCard
key={item.id}
staff={item as any}
/>
))}
</motion.div>
) : (
<motion.div
className="text-center py-12"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<Empty
description="没有找到匹配的收信人"
className="py-12"
/>
</motion.div>
)}
</AnimatePresence>
{/* Pagination */}
{data?.items.length > 0 && (
<div className="flex justify-center mt-8">
<Pagination
current={currentPage}
total={data?.totalPages || 0}
pageSize={pageSize}
onChange={(page) => setCurrentPage(page)}
showSizeChanger={false}
showTotal={(total) => `${total} 条记录`}
/>
</div>
)}
</div>
</div>
);
}