TinyBase logoTinyBase

Todo App v4 (metrics)

In this version of the Todo app, we add a Metrics object that tracks the number of todos of each type and how many are not yet done. This allows us to show people how well they are getting through them.

We're making changes to the Todo App v3 (persistence) demo.

Additional Initialization

We create a Metrics object with the useCreateMetrics hook, and will need the useMetric hook so that we can get the metrics out of it:

-const {createIndexes, createStore} = TinyBase;
+const {createIndexes, createMetrics, createStore} = TinyBase;
 const {createLocalPersister, createSessionPersister} = TinyBasePersisterBrowser;
 const {
   CellView,
   Provider,
   SliceView,
   useAddRowCallback,
   useCell,
   useCreateIndexes,
+  useCreateMetrics,
   useCreatePersister,
   useCreateStore,
+  useMetric,
   useSetCellCallback,
   useSetValueCallback,
   useValue,
 } = TinyBaseUiReact;

Adding Metrics

We define a metric to count how many todos are pending (i.e. not done), and then set up additional metrics to track the number of pending todos of each type. We use the useCreateMetrics hook to memoize this whole initialization:

   const indexes = useCreateIndexes(store, (store) =>
     createIndexes(store).setIndexDefinition('types', 'todos', 'type'),
   );
+  const metrics = useCreateMetrics(store, (store) => {
+    const metrics = createMetrics(store);
+    metrics.setMetricDefinition('pending', 'todos', 'sum', (getCell) =>
+      !getCell('done') ? 1 : 0,
+    );
+    TYPES.forEach((type) => {
+      metrics.setMetricDefinition(type, 'todos', 'sum', (getCell) =>
+        getCell('type') == type && !getCell('done') ? 1 : 0,
+      );
+    });
+    return metrics;
+  });

As before, we make this Metrics object available though the Provider component as the default for the app:

   return (
-    <Provider store={store} storesById={{viewStore}} indexes={indexes}>+    <Provider
+      store={store}
+      storesById={{viewStore}}
+      indexes={indexes}
+      metrics={metrics}
+    >       <Title />
       <NewTodo />
       <Types />
       <Todos />
       <StoreInspector />
     </Provider>
   );
 };

Upgrading The Title Component

Now that we are tracking the total number of pending todos, we can have that number appear in the title. We simply use the useMetric hook to get the pending metric that was previously defined:

-const Title = () => 'Todos';
+const Title = () => {
+  const pending = useMetric('pending');
+
+  return pending > 0 ? `Todo: ${pending}` : 'All done!';
+};

Upgrading The Type Component

We also have a metric for each type that represents the number of pending todos of that type. We can display those alongside each type name in the side-bar. Apart from the addition of the pending variable, this component is as it was in the previous version:

 const Type = ({type}) => {
+  const pending = useMetric(type);
   const currentType = useValue('type', 'viewStore');
   const handleClick = useSetValueCallback(
     'type',
     () => type,
     [type],
     'viewStore',
   );
   const className = 'type' + (type == currentType ? ' current' : '');

   return (
     <li className={className} onClick={handleClick}>
       {type}+      {pending > 0 ? ` (${pending})` : ''}
     </li>
   );
 };

Summary

We now have a fairly useful app for tracking todos. As a final flourish, we will add an undo and redo feature. Please continue to the Todo App v5 (checkpoints) demo.