api catalog

import React, { useState, createContext, useContext, useCallback } from 'react';
import { 
  AppBar, 
  Toolbar, 
  InputBase, 
  Card, 
  CardContent, 
  Typography, 
  Button,
  Grid,
  createTheme,
  ThemeProvider,
  Box,
  List,
  ListItem,
  ListItemText,
  Popper,
  Paper,
  ClickAwayListener,
  Grow,
  Container,
  IconButton,
  Select,
  MenuItem,
  FormControl,
  InputLabel,
  Tabs,
  Tab,
  Tooltip
} from '@mui/material';
import { 
  Search as SearchIcon, 
  Add as AddIcon, 
  ArrowForward as ArrowForwardIcon,
  Home as HomeIcon,
  Api as ApiIcon,
  Description as DescriptionIcon,
  AttachMoney as AttachMoneyIcon,
  Help as HelpIcon,
  AccountCircle as AccountCircleIcon,
  Dashboard as DashboardIcon,
  BarChart as BarChartIcon,
  Settings as SettingsIcon
} from '@mui/icons-material';
import { styled, alpha } from '@mui/material/styles';
import { IntlProvider, FormattedMessage, useIntl } from 'react-intl';

// Language context
const LanguageContext = createContext();

// Language provider component
const LanguageProvider = ({ children, value }) => {
  return (
    <LanguageContext.Provider value={value}>
      {children}
    </LanguageContext.Provider>
  );
};

// Hook to use language
const useLanguage = () => {
  const context = useContext(LanguageContext);
  if (context === undefined) {
    throw new Error('useLanguage must be used within a LanguageProvider');
  }
  return context;
};

// Translation messages
const messages = {
  zh: {
    'app.title': 'API查询平台',
    'app.subtitle': '轻松查找、比较和集成各种API',
    'search.placeholder': '请输入API名称',
    'search.button': '搜索',
    'api.categories': 'API 类别',
    'api.type': 'API类型',
    'api.type.all': '全部',
    'api.type.hbim': 'HBIM',
    'api.type.project': '项目',
    'api.add': '新增 API',
    'api.count': '{count} 个 API',
    'api.type.label': '类型: {type}',
    'tab.home': '首页',
    'tab.apis': 'API',
    'tab.docs': '文档',
    'tab.pricing': '价格',
    'tab.support': '支持',
    'tab.account': '账户',
    'tab.dashboard': '仪表板',
    'tab.analytics': '分析',
    'tab.settings': '设置',
    'language.switch': '切换到英文',
    'category.auth': '认证与授权',
    'category.data': '数据处理',
    'category.payment': '支付集成',
    'category.social': '社交媒体',
    'category.map': '地图服务',
    'category.notification': '消息推送',
  },
  en: {
    'app.title': 'API Query Platform',
    'app.subtitle': 'Easily find, compare and integrate various APIs',
    'search.placeholder': 'Enter API name',
    'search.button': 'Search',
    'api.categories': 'API Categories',
    'api.type': 'API Type',
    'api.type.all': 'All',
    'api.type.hbim': 'HBIM',
    'api.type.project': 'Project',
    'api.add': 'Add API',
    'api.count': '{count} APIs',
    'api.type.label': 'Type: {type}',
    'tab.home': 'Home',
    'tab.apis': 'APIs',
    'tab.docs': 'Documentation',
    'tab.pricing': 'Pricing',
    'tab.support': 'Support',
    'tab.account': 'Account',
    'tab.dashboard': 'Dashboard',
    'tab.analytics': 'Analytics',
    'tab.settings': 'Settings',
    'language.switch': 'Switch to Chinese',
    'category.auth': 'Authentication & Authorization',
    'category.data': 'Data Processing',
    'category.payment': 'Payment Integration',
    'category.social': 'Social Media',
    'category.map': 'Map Services',
    'category.notification': 'Notifications',
  },
};

// API categories data
const apiCategories = [
  { id: 1, nameId: 'category.auth', count: 15, type: 'hbim' },
  { id: 2, nameId: 'category.data', count: 23, type: 'hbim' },
  { id: 3, nameId: 'category.payment', count: 8, type: 'project' },
  { id: 4, nameId: 'category.social', count: 12, type: 'project' },
  { id: 5, nameId: 'category.map', count: 7, type: 'hbim' },
  { id: 6, nameId: 'category.notification', count: 9, type: 'project' },
];

// Styled components (unchanged)
const Search = styled('div')(({ theme }) => ({
  position: 'relative',
  borderRadius: theme.shape.borderRadius,
  backgroundColor: alpha(theme.palette.common.white, 1),
  '&:hover': {
    backgroundColor: alpha(theme.palette.common.white, 0.95),
  },
  marginRight: theme.spacing(2),
  marginLeft: 0,
  width: '100%',
  [theme.breakpoints.up('sm')]: {
    width: 'auto',
  },
  boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
}));

const SearchIconWrapper = styled('div')(({ theme }) => ({
  padding: theme.spacing(0, 2),
  height: '100%',
  position: 'absolute',
  pointerEvents: 'none',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  color: theme.palette.text.secondary,
}));

const StyledInputBase = styled(InputBase)(({ theme }) => ({
  color: theme.palette.text.primary,
  width: '100%',
  '& .MuiInputBase-input': {
    padding: theme.spacing(1.5, 1, 1.5, 0),
    paddingLeft: `calc(1em + ${theme.spacing(4)})`,
    transition: theme.transitions.create('width'),
    width: '100%',
    [theme.breakpoints.up('md')]: {
      width: '50ch',
    },
  },
}));

const StyledPopper = styled(Popper)(({ theme }) => ({
  zIndex: theme.zIndex.modal,
  width: '100%',
  [theme.breakpoints.up('md')]: {
    width: '50ch',
  },
}));

const ResultItem = styled(ListItem)(({ theme }) => ({
  '&:hover': {
    backgroundColor: alpha(theme.palette.primary.main, 0.08),
  },
}));

const StyledTab = styled(Tab)(({ theme }) => ({
  minWidth: 100,
  maxWidth: 100,
  width: 100,
  padding: theme.spacing(1),
  overflow: 'hidden',
  textOverflow: 'ellipsis',
  whiteSpace: 'nowrap',
}));

const theme = createTheme({
  palette: {
    primary: {
      main: '#2196f3',
    },
    secondary: {
      main: '#f50057',
    },
    background: {
      default: '#f5f5f5',
    },
  },
  typography: {
    fontFamily: [
      '-apple-system',
      'BlinkMacSystemFont',
      '"Segoe UI"',
      'Roboto',
      '"Helvetica Neue"',
      'Arial',
      'sans-serif',
      '"Apple Color Emoji"',
      '"Segoe UI Emoji"',
      '"Segoe UI Symbol"',
    ].join(','),
  },
});

function ApiCatalogPage() {
  const [searchTerm, setSearchTerm] = useState('');
  const [anchorEl, setAnchorEl] = useState(null);
  const [apiType, setApiType] = useState('all');
  const [tabValue, setTabValue] = useState(0);
  const { locale, setLocale } = useLanguage();
  const intl = useIntl();

  const handleSearchChange = (event) => {
    setSearchTerm(event.target.value);
    setAnchorEl(event.currentTarget);
  };

  const handleClickAway = () => {
    setAnchorEl(null);
  };

  const handleApiTypeChange = (event) => {
    setApiType(event.target.value);
  };

  const handleTabChange = (event, newValue) => {
    setTabValue(newValue);
  };

  const toggleLanguage = useCallback(() => {
    setLocale(prevLocale => prevLocale === 'zh' ? 'en' : 'zh');
  }, [setLocale]);

  const filteredCategories = apiCategories.filter(category => 
    apiType === 'all' || category.type === apiType
  );

  const open = Boolean(anchorEl) && searchTerm.length > 0;

  const tabItems = [
    { id: 'tab.home', label: intl.formatMessage({ id: 'tab.home' }), icon: <HomeIcon /> },
    { id: 'tab.apis', label: intl.formatMessage({ id: 'tab.apis' }), icon: <ApiIcon /> },
    { id: 'tab.docs', label: intl.formatMessage({ id: 'tab.docs' }), icon: <DescriptionIcon /> },
    { id: 'tab.pricing', label: intl.formatMessage({ id: 'tab.pricing' }), icon: <AttachMoneyIcon /> },
    { id: 'tab.support', label: intl.formatMessage({ id: 'tab.support' }), icon: <HelpIcon /> },
    { id: 'tab.account', label: intl.formatMessage({ id: 'tab.account' }), icon: <AccountCircleIcon /> },
    { id: 'tab.dashboard', label: intl.formatMessage({ id: 'tab.dashboard' }), icon: <DashboardIcon /> },
    { id: 'tab.analytics', label: intl.formatMessage({ id: 'tab.analytics' }), icon: <BarChartIcon /> },
    { id: 'tab.settings', label: intl.formatMessage({ id: 'tab.settings' }), icon: <SettingsIcon /> },
  ];

  return (
    <ThemeProvider theme={theme}>
      <div className="min-h-screen bg-gray-100">
        <AppBar position="static" color="default" elevation={0}>
          <Toolbar>
            <Tabs 
              value={tabValue} 
              onChange={handleTabChange} 
              aria-label="navigation tabs"
              variant="scrollable"
              scrollButtons="auto"
              sx={{ flexGrow: 1 }}
            >
              {tabItems.map((tab, index) => (
                <Tooltip title={tab.label} key={tab.id}>
                  <StyledTab
                    icon={tab.icon}
                    label={tab.label}
                    id={`tab-${index}`}
                    aria-controls={`tabpanel-${index}`}
                  />
                </Tooltip>
              ))}
            </Tabs>
            <Button onClick={toggleLanguage}>
              <FormattedMessage id="language.switch" />
            </Button>
          </Toolbar>
        </AppBar>

        <Box sx={{ bgcolor: 'primary.main', color: 'white', py: 8, textAlign: 'center' }}>
          <Container maxWidth="lg">
            <Typography variant="h3" component="h1" gutterBottom>
              <FormattedMessage id="app.title" />
            </Typography>
            <Typography variant="h6" component="p" gutterBottom sx={{ mb: 4 }}>
              <FormattedMessage id="app.subtitle" />
            </Typography>
            <Box sx={{ display: 'flex', justifyContent: 'center', position: 'relative' }}>
              <Search>
                <SearchIconWrapper>
                  <SearchIcon />
                </SearchIconWrapper>
                <StyledInputBase
                  placeholder={intl.formatMessage({ id: 'search.placeholder' })}
                  inputProps={{ 'aria-label': 'search' }}
                  value={searchTerm}
                  onChange={handleSearchChange}
                />
                <Button
                  variant="contained"
                  color="secondary"
                  sx={{ position: 'absolute', right: 0, top: 0, bottom: 0 }}
                >
                  <FormattedMessage id="search.button" />
                </Button>
              </Search>
              <StyledPopper open={open} anchorEl={anchorEl} placement="bottom-start" transition>
                {({ TransitionProps }) => (
                  <Grow {...TransitionProps} style={{ transformOrigin: 'top left' }}>
                    <Paper elevation={3} sx={{ mt: 1, borderRadius: 2, overflow: 'hidden' }}>
                      <ClickAwayListener onClickAway={handleClickAway}>
                        <List sx={{ py: 0 }}>
                          {/* We would need to implement a proper search functionality here */}
                          <ResultItem button>
                            <ListItemText 
                              primary={intl.formatMessage({ id: 'category.auth' })}
                              primaryTypographyProps={{ 
                                sx: { fontWeight: 'medium' } 
                              }}
                            />
                          </ResultItem>
                        </List>
                      </ClickAwayListener>
                    </Paper>
                  </Grow>
                )}
              </StyledPopper>
            </Box>
          </Container>
        </Box>

        <Container maxWidth="lg" sx={{ mt: 4, mb: 4 }}>
          <Box  sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
            <Typography variant="h5" component="h2">
              <FormattedMessage id="api.categories" />
            </Typography>
            <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
              <FormControl variant="outlined" size="small">
                <InputLabel id="api-type-select-label">
                  <FormattedMessage id="api.type" />
                </InputLabel>
                <Select
                  labelId="api-type-select-label"
                  id="api-type-select"
                  value={apiType}
                  onChange={handleApiTypeChange}
                  label={intl.formatMessage({ id: 'api.type' })}
                >
                  <MenuItem value="all"><FormattedMessage id="api.type.all" /></MenuItem>
                  <MenuItem value="hbim"><FormattedMessage id="api.type.hbim" /></MenuItem>
                  <MenuItem value="project"><FormattedMessage id="api.type.project" /></MenuItem>
                </Select>
              </FormControl>
              <Button
                variant="contained"
                color="primary"
                startIcon={<AddIcon />}
                sx={{ fontWeight: 'bold' }}
              >
                <FormattedMessage id="api.add" />
              </Button>
            </Box>
          </Box>
          <Grid container spacing={3}>
            {filteredCategories.map((category) => (
              <Grid item xs={12} sm={6} md={4} key={category.id}>
                <Card sx={{ height: '100%', display: 'flex', flexDirection: 'column', transition: '0.3s', '&:hover': { transform: 'translateY(-5px)', boxShadow: 3 } }}>
                  <CardContent sx={{ flexGrow: 1  }}>
                    <Typography variant="h6" component="h3" gutterBottom>
                      <FormattedMessage id={category.nameId} />
                    </Typography>
                    <Typography variant="body2" color="text.secondary">
                      <FormattedMessage id="api.count" values={{ count: category.count }} />
                    </Typography>
                    <Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
                      <FormattedMessage id="api.type.label" values={{ type: intl.formatMessage({ id: `api.type.${category.type}` }) }} />
                    </Typography>
                  </CardContent>
                  <Box sx={{ p: 2, display: 'flex', justifyContent: 'flex-end' }}>
                    <IconButton size="small" color="primary">
                      <ArrowForwardIcon />
                    </IconButton>
                  </Box>
                </Card>
              </Grid>
            ))}
          </Grid>
        </Container>
      </div>
    </ThemeProvider>
  );
}

function App() {
  const [locale, setLocale] = useState('zh');

  const toggleLanguage = useCallback(() => {
    setLocale(prevLocale => prevLocale === 'zh' ? 'en' : 'zh');
  }, []);

  return (
    <LanguageProvider value={{ locale, setLocale: toggleLanguage }}>
      <IntlProvider messages={messages[locale]} locale={locale}>
        <ApiCatalogPage />
      </IntlProvider>
    </LanguageProvider>
  );
}

export default function Component() {
  return <App />;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值