Update on frontend pages May 27th

Change-Id: I452e5a0ae089114f5b68920e507e56db897856f8
diff --git a/frontend/my-app/src/pages/Home.jsx b/frontend/my-app/src/pages/Home.jsx
index 1764f5c..6bca4b8 100644
--- a/frontend/my-app/src/pages/Home.jsx
+++ b/frontend/my-app/src/pages/Home.jsx
@@ -1,190 +1,205 @@
-// src/pages/Home.jsx
 import React, { useState, useEffect } from 'react';
 import {
-  Table, TableHead, TableRow, TableCell, TableBody,
-  Typography, Box, Container, Paper, Tooltip, IconButton, Chip
+  Box, Container, Typography, Paper,
+  List, ListItem, ListItemText, Chip, Stack, CircularProgress, Alert
 } from '@mui/material';
-import DownloadIcon from '@mui/icons-material/Download';
-import StarBorderIcon from '@mui/icons-material/StarBorder';
+import { Link } from 'react-router-dom'; // 假设你已经配置了 React Router
+
+// import '../styles/base/base.css'; // ✅ 引入统一样式 - 我们将尝试用 sx prop 替代
+
+// 模拟从API获取数据
+const fetchTorrents = () => {
+  return new Promise((resolve) => {
+    setTimeout(() => {
+      resolve([
+        {
+          id: 1,
+          title: 'Ubuntu ISO 镜像',
+          tags: ['Linux', '操作系统', 'ISO'],
+          size: '2.1 GB',
+          uploader: 'admin',
+          description: '最新的 Ubuntu Desktop 长期支持版。适用于开发者和普通用户。'
+        },
+        {
+          id: 2,
+          title: '开源电影素材包 - Blender "Sintel"',
+          tags: ['视频', '素材', '开源', 'Blender'],
+          size: '800 MB',
+          uploader: 'user001',
+          description: '来自 Blender Foundation 的开源电影 "Sintel" 的原始素材,可用于学习和创作。'
+        },
+        {
+          id: 3,
+          title: 'React 学习资料大全',
+          tags: ['React', 'JavaScript', '前端开发', '教程'],
+          size: '150 MB',
+          uploader: 'dev_guru',
+          description: '包含 React 官方文档、优秀教程链接和项目示例。'
+        }
+      ]);
+    }, 1500); // 模拟网络延迟
+  });
+};
+
 
 function Home() {
   const [torrents, setTorrents] = useState([]);
+  const [loading, setLoading] = useState(true);
+  const [error, setError] = useState(null);
 
   useEffect(() => {
-    setTorrents([
-      { title: 'Ubuntu 22.04 LTS', size: '3.2 GB', seeders: 1200, leechers: 300, date: '2025-04-01', tags: ['Linux', 'ISO'] },
-      { title: 'LibreOffice 7.5.2', size: '320 MB', seeders: 450, leechers: 50, date: '2025-03-28', tags: ['办公'] },
-      { title: 'Movie.Title.1080p.BluRay', size: '2.5 GB', seeders: 900, leechers: 200, date: '2025-04-05', tags: ['电影', '高清'] },
-    ]);
+    setLoading(true);
+    fetchTorrents()
+      .then(data => {
+        setTorrents(data);
+        setLoading(false);
+      })
+      .catch(err => {
+        console.error("Failed to fetch torrents:", err);
+        setError("加载资源失败,请稍后再试。");
+        setLoading(false);
+      });
   }, []);
 
   return (
-    <Box sx={styles.mainContainer}>
-      <Container maxWidth="lg">
-        <Typography variant="h4" sx={styles.title}>
-          🎬 资源列表 · Mini-Tracker
+    <Box sx={{ minHeight: '100vh', py: 4, background: 'linear-gradient(135deg, #2c3e50, #4ca1af)', color: 'white' }}>
+      <Container maxWidth="md" sx={{ position: 'relative', zIndex: 10 }}> {/* Changed to md for wider content */}
+        <Typography variant="h4" sx={{ textAlign: 'center', mb: 3, fontWeight: 'bold' }}>
+          🌐 首页 · Mini-Tracker
         </Typography>
 
-        <Paper sx={styles.paper}>
-          <Table size="small">
-            <TableHead>
-              <TableRow>
-                <TableCell sx={styles.header}>名称</TableCell>
-                <TableCell sx={styles.header}>标签</TableCell>
-                <TableCell sx={styles.header}>大小</TableCell>
-                <TableCell sx={styles.header}>做种者</TableCell>
-                <TableCell sx={styles.header}>下载者</TableCell>
-                <TableCell sx={styles.header}>上传时间</TableCell>
-                <TableCell sx={styles.header}>操作</TableCell>
-              </TableRow>
-            </TableHead>
-            <TableBody>
-              {torrents.map((t, i) => (
-                <TableRow key={i} sx={styles.row}>
-                  <TableCell sx={styles.cell}>{t.title}</TableCell>
-                  <TableCell sx={styles.cell}>
-                    {t.tags.map(tag => (
-                      <Chip key={tag} label={tag} size="small" sx={styles.chip} />
+        <Paper sx={{ position: 'relative', zIndex: 20, padding: '2rem', backgroundColor: 'rgba(30, 30, 30, 0.9)', borderRadius: '12px' }}>
+          <Typography variant="h6" gutterBottom sx={{ mb: 2, color: '#eee' }}>
+            最新种子资源
+          </Typography>
+
+          {loading && (
+            <Box sx={{ display: 'flex', justifyContent: 'center', my: 3 }}>
+              <CircularProgress color="inherit" />
+            </Box>
+          )}
+
+          {error && (
+            <Alert severity="error" sx={{ my: 2 }}>{error}</Alert>
+          )}
+
+          {!loading && !error && (
+            <List sx={{ '& .MuiListItem-root:hover': { backgroundColor: 'rgba(255, 255, 255, 0.05)' }}}>
+              {torrents.map(torrent => (
+                <ListItem
+                  key={torrent.id}
+                  component={Link} // react-router-dom Link
+                  to={`/detail/${torrent.id}`} // 假设的详情页路由
+                  sx={{ 
+                    color: 'white', 
+                    textDecoration: 'none',
+                    mb: 1.5, // 增加列表项间距
+                    p: 1.5, // 增加列表项内边距
+                    borderBottom: '1px solid rgba(255, 255, 255, 0.1)',
+                    '&:last-child': {
+                        borderBottom: 'none' // 移除最后一个元素的边框
+                    },
+                    display: 'flex', // 确保内部元素正确对齐
+                    flexDirection: { xs: 'column', sm: 'row' }, // 响应式布局
+                    alignItems: { xs: 'flex-start', sm: 'center' }
+                  }}
+                  divider={false} // 使用自定义边框代替
+                >
+                  <ListItemText
+                    primary={torrent.title}
+                    secondary={`大小: ${torrent.size} · 上传者: ${torrent.uploader}`}
+                    primaryTypographyProps={{ variant: 'h6', component: 'div', sx: { mb: 0.5, color: '#f5f5f5', fontWeight: 500 } }}
+                    secondaryTypographyProps={{ sx: { color: '#bbb', fontSize: '0.85rem' } }}
+                    sx={{ flexGrow: 1, mb: { xs: 1, sm: 0 }, mr: { sm: 2 } }} // 响应式边距
+                  />
+                  <Stack direction="row" spacing={1} sx={{ flexWrap: 'wrap', gap: 0.5 }}> {/* 允许标签换行 */}
+                    {torrent.tags.map(tag => (
+                      <Chip
+                        key={tag}
+                        label={tag}
+                        size="small"
+                        sx={{ 
+                          backgroundColor: 'rgba(255, 255, 255, 0.2)', // upload-chip 样式
+                          color: 'white',
+                          cursor: 'pointer',
+                          '&:hover': {
+                            backgroundColor: 'rgba(255, 255, 255, 0.3)',
+                          }
+                        }}
+                      />
                     ))}
-                  </TableCell>
-                  <TableCell sx={styles.cell}>{t.size}</TableCell>
-                  <TableCell sx={styles.cell}>{t.seeders}</TableCell>
-                  <TableCell sx={styles.cell}>{t.leechers}</TableCell>
-                  <TableCell sx={styles.cell}>{t.date}</TableCell>
-                  <TableCell sx={styles.cell}>
-                    <Tooltip title="下载种子">
-                      <IconButton color="success" size="small">
-                        <DownloadIcon fontSize="small" />
-                      </IconButton>
-                    </Tooltip>
-                    <Tooltip title="收藏">
-                      <IconButton color="warning" size="small">
-                        <StarBorderIcon fontSize="small" />
-                      </IconButton>
-                    </Tooltip>
-                  </TableCell>
-                </TableRow>
+                  </Stack>
+                </ListItem>
               ))}
-            </TableBody>
-          </Table>
+            </List>
+          )}
         </Paper>
       </Container>
 
-      {/* 柔和深蓝渐变背景 */}
-      <div style={styles.background}></div>
-
-      {/* 舒缓漂浮的柔和粒子 */}
-      <div style={styles.bubbles}>
+      {/* 背景泡泡动画复用 - 这些类名 (.bubbles, .bubble) 和 @keyframes rise 应该在全局CSS或者下面的 <style> 标签中定义 */}
+      <Box className="bubbles" sx={{
+         pointerEvents: 'none',
+         position: 'fixed',
+         top: 0,
+         left: 0,
+         width: '100%',
+         height: '100%',
+         overflow: 'hidden',
+         zIndex: 1, 
+      }}>
         {[...Array(40)].map((_, i) => (
-          <div key={i} style={{ ...styles.bubble, ...bubbleAnimation(i) }} />
+          <Box
+            key={i}
+            className="bubble"
+            sx={{
+              position: 'absolute',
+              bottom: '-150px', // 确保从屏幕外开始
+              background: `hsla(${Math.random() * 360}, 70%, 80%, 0.15)`, // 增加颜色多样性
+              borderRadius: '50%',
+              animation: 'rise 20s infinite ease-in',
+              width: `${Math.random() * 25 + 10}px`, // 调整大小范围
+              height: `${Math.random() * 25 + 10}px`,
+              left: `${Math.random() * 100}%`,
+              animationDuration: `${15 + Math.random() * 20}s`, // 调整动画时长
+              animationDelay: `${Math.random() * 10}s`, // 调整动画延迟
+              opacity: 0, // 初始透明
+            }}
+          />
         ))}
-      </div>
+      </Box>
+      {/* 定义动画和其他全局可能需要的样式 */}
+      <style>
+        {`
+          body { /* 基本重置 */
+            margin: 0;
+            font-family: 'Roboto', sans-serif; /* 确保字体一致 */
+          }
 
-      {/* 动画 Keyframes */}
-      <style>{animationCSS}</style>
+          @keyframes rise {
+            0% {
+              transform: translateY(0) scale(0.8);
+              opacity: 0; /* 从透明开始 */
+            }
+            10% {
+                opacity: 1; /* 渐显 */
+            }
+            90% {
+                opacity: 1; /* 保持可见 */
+            }
+            100% {
+              transform: translateY(-130vh) scale(0.3); /* 飘得更高更小 */
+              opacity: 0; /* 渐隐 */
+            }
+          }
+
+          /* 如果 .bubbles 和 .bubble 样式没有在 sx 中完全覆盖,可以在这里补充 */
+          /* .bubbles { ... } */
+          /* .bubble { ... } */
+        `}
+      </style>
     </Box>
   );
 }
 
 export default Home;
 
-// 样式对象
-const styles = {
-  mainContainer: {
-    minHeight: '100vh',
-    bgcolor: '#0d1b2a',
-    color: '#e0e0e0',
-    py: 5,
-    position: 'relative',
-    overflow: 'hidden',
-  },
-  title: {
-    mb: 3,
-    fontFamily: '"Fira Code", monospace',
-    color: '#a3cef1',
-    textAlign: 'center',
-    fontSize: '2rem',
-    fontWeight: 'bold',
-  },
-  paper: {
-    bgcolor: '#1b263b',
-    p: 2,
-    borderRadius: 3,
-    boxShadow: 3,
-    backdropFilter: 'blur(6px)',
-    border: '1px solid rgba(255, 255, 255, 0.08)',
-  },
-  header: {
-    fontWeight: 'bold',
-    color: '#b0ccee',
-    fontFamily: '"Fira Code", monospace',
-    borderBottom: '1px solid #3a4a6b',
-  },
-  cell: {
-    fontFamily: '"Fira Code", monospace',
-    color: '#e0e0e0',
-    fontSize: '0.85rem',
-    padding: '8px 12px',
-  },
-  chip: {
-    mr: 0.5,
-    backgroundColor: '#2e3b53',
-    color: '#81c784',
-    fontSize: '0.75rem',
-  },
-  row: {
-    '&:nth-of-type(odd)': { bgcolor: '#19263e' },
-    '&:hover': { bgcolor: '#26354f' },
-  },
-  background: {
-    position: 'absolute',
-    top: 0, left: 0,
-    width: '100%', height: '100%',
-    background: 'linear-gradient(45deg, #0d1b2a, #122b44, rgb(28, 102, 158))',
-    backgroundSize: '400% 400%',
-    animation: 'bgShift 30s ease infinite',    
-    zIndex: -1,
-  },
-  bubbles: {
-    position: 'absolute',
-    top: 0, left: 0,
-    width: '100%', height: '100%',
-    zIndex: 0,
-    overflow: 'hidden',
-  },
-  bubble: {
-    position: 'absolute',
-    width: '6px',
-    height: '6px',
-    borderRadius: '50%',
-    backgroundColor: 'rgba(163, 206, 241, 0.4)',
-    animation: 'bubbleFloat 8s ease-in-out infinite',
-  },
-};
-
-const animationCSS = `
-@keyframes bgShift {
-  0% { background-position: 0% 50%; }
-  50% { background-position: 100% 50%; }
-  100% { background-position: 0% 50%; }
-}
-@keyframes bubbleFloat {
-  0% { transform: translateY(100%); opacity: 0; }
-  50% { opacity: 0.5; }
-  100% { transform: translateY(-100%); opacity: 0; }
-}
-`;
-
-function bubbleAnimation(i) {
-  const delay = Math.random() * 6;
-  const left = Math.random() * 100;
-  const size = 4 + Math.random() * 8;
-  const top = Math.random() * 100;
-  return {
-    left: `${left}%`,
-    top: `${top}%`,
-    width: `${size}px`,
-    height: `${size}px`,
-    animationDelay: `${delay}s`,
-  };
-}