index.tsx
1 import { FileOutlined, HighlightOutlined, PlusOutlined, UnorderedListOutlined, UserOutlined } from "@ant-design/icons"; 2 import { useList, useTranslate } from "@refinedev/core"; 3 import { Card, Col, Row, Statistic, theme } from "antd"; 4 import { Content } from "antd/es/layout/layout"; 5 import Title from "antd/es/typography/Title"; 6 import dayjs from "dayjs"; 7 import utc from "dayjs/plugin/utc"; 8 import { ReactNode } from "react"; 9 import { Trans } from "react-i18next"; 10 import { Link } from "react-router"; 11 import Logo from "../../icon.svg?react"; 12 import { ISpool } from "../spools/model"; 13 14 dayjs.extend(utc); 15 16 const { useToken } = theme; 17 18 export const Home = () => { 19 const { token } = useToken(); 20 const t = useTranslate(); 21 22 const spools = useList<ISpool>({ 23 resource: "spool", 24 pagination: { pageSize: 1 }, 25 }); 26 const filaments = useList<ISpool>({ 27 resource: "filament", 28 pagination: { pageSize: 1 }, 29 }); 30 const vendors = useList<ISpool>({ 31 resource: "vendor", 32 pagination: { pageSize: 1 }, 33 }); 34 35 const hasSpools = !spools.result || spools.result.data.length > 0; 36 37 const ResourceStatsCard = (props: { loading: boolean; value: number; resource: string; icon: ReactNode }) => ( 38 <Col xs={12} md={6}> 39 <Card 40 loading={props.loading} 41 actions={[ 42 <Link to={`/${props.resource}`} key="resource"> 43 <UnorderedListOutlined /> 44 </Link>, 45 <Link to={`/${props.resource}/create`} key="create"> 46 <PlusOutlined /> 47 </Link>, 48 ]} 49 > 50 <Statistic title={t(`${props.resource}.${props.resource}`)} value={props.value} prefix={props.icon} /> 51 </Card> 52 </Col> 53 ); 54 55 return ( 56 <Content 57 style={{ 58 padding: "2em 20px", 59 minHeight: 280, 60 maxWidth: 800, 61 margin: "0 auto", 62 backgroundColor: token.colorBgContainer, 63 borderRadius: token.borderRadiusLG, 64 color: token.colorText, 65 fontFamily: token.fontFamily, 66 fontSize: token.fontSizeLG, 67 lineHeight: 1.5, 68 }} 69 > 70 <Title 71 style={{ 72 display: "flex", 73 alignItems: "center", 74 justifyContent: "center", 75 fontSize: token.fontSizeHeading1, 76 }} 77 > 78 <div 79 style={{ 80 display: "inline-block", 81 height: "1.5em", 82 marginRight: "0.5em", 83 }} 84 > 85 <Logo /> 86 </div> 87 Spoolman 88 </Title> 89 <Row justify="center" gutter={[16, 16]} style={{ marginTop: "3em" }}> 90 <ResourceStatsCard 91 resource="spool" 92 value={spools.result?.total || 0} 93 loading={spools.query.isLoading} 94 icon={<FileOutlined />} 95 /> 96 <ResourceStatsCard 97 resource="filament" 98 value={filaments.result?.total || 0} 99 loading={filaments.query.isLoading} 100 icon={<HighlightOutlined />} 101 /> 102 <ResourceStatsCard 103 resource="vendor" 104 value={vendors.result?.total || 0} 105 loading={vendors.query.isLoading} 106 icon={<UserOutlined />} 107 /> 108 </Row> 109 {!hasSpools && ( 110 <> 111 <p style={{ marginTop: 32 }}>{t("home.welcome")}</p> 112 <p> 113 <Trans 114 i18nKey="home.description" 115 components={{ 116 helpPageLink: <Link to="/help" />, 117 }} 118 /> 119 </p> 120 </> 121 )} 122 </Content> 123 ); 124 }; 125 126 export default Home;