feat: improve admin responsive pages and teacher candidates
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { List, Typography, Menu, Layout, Button, Empty, Spin, Space } from 'antd';
|
||||
import { List, Typography, Menu, Layout, Button, Empty, Spin, Space, Grid, Select } from 'antd';
|
||||
import {
|
||||
BellOutlined,
|
||||
DollarOutlined,
|
||||
@@ -13,6 +13,7 @@ import { message } from '../../ui/app-message';
|
||||
import { formatNotificationText } from '../../utils/notification-display';
|
||||
|
||||
const { Sider, Content } = Layout;
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
interface NotificationItem {
|
||||
id: number;
|
||||
@@ -49,6 +50,8 @@ function timeAgo(dateStr: string): string {
|
||||
}
|
||||
|
||||
const NotificationsPage: React.FC = () => {
|
||||
const screens = useBreakpoint();
|
||||
const isMobile = !screens.sm;
|
||||
const [notifications, setNotifications] = useState<NotificationItem[]>([]);
|
||||
const [filter, setFilter] = useState('all');
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -101,27 +104,39 @@ const NotificationsPage: React.FC = () => {
|
||||
? notifications
|
||||
: notifications.filter((n) => n.type === filter);
|
||||
|
||||
const filterItems = [
|
||||
{ key: 'all', icon: <BellOutlined />, label: '全部' },
|
||||
{ key: 'bill_generated', icon: <DollarOutlined />, label: '账单' },
|
||||
{ key: 'check_in', icon: <HomeOutlined />, label: '入住' },
|
||||
{ key: 'class_change', icon: <TeamOutlined />, label: '班级' },
|
||||
{ key: 'announcement', icon: <SettingOutlined />, label: '公告' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100%', background: '#fff' }}>
|
||||
<Sider width={180} style={{ background: '#fff', borderRight: '1px solid #f0f0f0' }}>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={[filter]}
|
||||
onClick={({ key }) => setFilter(key)}
|
||||
items={[
|
||||
{ key: 'all', icon: <BellOutlined />, label: '全部' },
|
||||
{ key: 'bill_generated', icon: <DollarOutlined />, label: '账单' },
|
||||
{ key: 'check_in', icon: <HomeOutlined />, label: '入住' },
|
||||
{ key: 'class_change', icon: <TeamOutlined />, label: '班级' },
|
||||
{ key: 'announcement', icon: <SettingOutlined />, label: '公告' },
|
||||
]}
|
||||
/>
|
||||
</Sider>
|
||||
<Content style={{ padding: 24 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
|
||||
<Layout className="notifications-layout" style={{ minHeight: '100%', background: '#fff' }}>
|
||||
{!isMobile && (
|
||||
<Sider width={180} style={{ background: '#fff', borderRight: '1px solid #f0f0f0' }}>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={[filter]}
|
||||
onClick={({ key }) => setFilter(key)}
|
||||
items={filterItems}
|
||||
/>
|
||||
</Sider>
|
||||
)}
|
||||
<Content className="notifications-content" style={{ padding: isMobile ? 0 : 24 }}>
|
||||
<div className="notifications-header">
|
||||
<Typography.Title level={4} style={{ margin: 0 }}>通知中心</Typography.Title>
|
||||
<Button onClick={handleMarkAll}>全部已读</Button>
|
||||
</div>
|
||||
{isMobile && (
|
||||
<Select
|
||||
value={filter}
|
||||
onChange={setFilter}
|
||||
options={filterItems.map((item) => ({ value: item.key, label: item.label }))}
|
||||
className="notifications-filter"
|
||||
/>
|
||||
)}
|
||||
<Spin spinning={loading}>
|
||||
{filtered.length === 0 ? (
|
||||
<Empty description="暂无通知" />
|
||||
@@ -165,7 +180,7 @@ const NotificationsPage: React.FC = () => {
|
||||
</div>
|
||||
}
|
||||
title={
|
||||
<Space>
|
||||
<Space wrap size={[8, 2]}>
|
||||
<Typography.Text
|
||||
strong={!item.isRead}
|
||||
style={{ fontSize: 15 }}
|
||||
|
||||
Reference in New Issue
Block a user