/ client / src / pages / home / index.tsx
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;