Skip to content

10 Results UI

JP Barbosa edited this page Sep 24, 2022 · 15 revisions

Results UI

Diagram

Results UI

Create results component

code ./frontend/src/components/Results.tsx
import { useEffect, useRef } from "react";
import { Item } from "../../../types/Item";
import { useFetch } from "../hooks/useFetch";
import { ResultsItem } from "./ResultsItem";
import { Status } from "./Status";

type Result = {
  Items: Item[];
};

export const Results: React.FC = () => {
  const { fetchItems, fetching, result, error } = useFetch<Result>(
    import.meta.env.VITE_API_URL
  );

  useEffect(() => {
    fetchItems();
  }, []);

  return (
    <div id="results">
      <Status
        status={[
          {
            condition: fetching,
            message: "Loading...",
          },
        ]}
      />
      <h2>Results ({result?.Items ? result.Items.length : "..."})</h2>
      {error ? (
        <div className="box error">{error.message}</div>
      ) : (
        <div className="scrollable">
          <ul className="results">
            {result?.Items?.map((item) => (
              <ResultsItem key={item.id} item={item} />
            ))}
          </ul>
        </div>
      )}
    </div>
  );
};

Create results item

code ./frontend/src/components/ResultsItem.tsx
/// <reference types="vite-plugin-svgr/client" />

import moment from "moment";
import { Item } from "../../../types/Item";
import { useAppContext } from "../contexts/AppContext";
import { ReactComponent as Arrow } from "../assets/arrow.svg";

type ResultsItemProps = {
  item: Item;
};

export const ResultsItem: React.FC<ResultsItemProps> = ({ item }) => {
  const { selectedItem, setSelectedItem, setUploadId } = useAppContext();

  const getItemClassName = (item: Item) => {
    const classes = [
      selectedItem?.id === item.id ? "selected" : "",
      item.error ? "error" : "success",
    ];
    return classes.join(" ");
  };

  const handleItemClick = (item: Item) => {
    setSelectedItem(item);
    setUploadId(undefined);
  };

  return (
    <li
      className={getItemClassName(item)}
      onClick={() => handleItemClick(item)}
    >
      <div>
        <div className="date">
          {moment(item.createdAt).format("YYYY-MM-DD HH:mm:ss")}
        </div>
        <div className="id">{item.id}</div>
      </div>
      <Arrow />
    </li>
  );
};

Create fetch hook

code ./frontend/src/hooks/useFetch.ts
import { useState } from "react";
import axios, { AxiosError } from "axios";

export const useFetch = <T>(url: string) => {
  const [fetching, setFetching] = useState(false);
  const [result, setResult] = useState<T | undefined>();
  const [error, setError] = useState<AxiosError | undefined>(undefined);

  const fetchItems = async () => {
    try {
      setError(undefined);
      setFetching(true);
      const response = await axios.get(url);
      setResult(response.data);
      setFetching(false);
    } catch (e) {
      setError(e as AxiosError);
    } finally {
      setFetching(false);
    }
  };

  return {
    fetchItems,
    fetching,
    result,
    error,
  };
};

Add results to the app

code ./frontend/src/App.tsx
...
import { Results } from "./components/Results";

function App() {
  return (
    <div id="app">
      <AppContextProvider>
        <Header />
        <div className="content">
          <Upload />
          <Results />
        </div>
      </AppContextProvider>
    </div>
  );
}

export default App;

Results

After Upload After Manual Reload
image image

Commit

git add .
git commit -m "Results UI"

Next step

Labels UI