Skip to content

Commit

Permalink
Create Zustand store for table column defs
Browse files Browse the repository at this point in the history
  • Loading branch information
tomtitherington committed Nov 5, 2023
1 parent 6d6ef1a commit 714330e
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 6 deletions.
1 change: 1 addition & 0 deletions .dictionary/custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,4 @@ probs
Customise
popperjs
tanstack
upsert
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Popover, Transition } from '@headlessui/react';
import { SlimTextInput } from 'components/inputs';
import { usePeopleStore, PropertyDefinition } from 'features/people/stores/usePeopleStore';
import { Fragment, useCallback, useEffect, useRef, useState } from 'react';
import { MdAdd } from 'react-icons/md';
import { usePopper } from 'react-popper';
import _ from 'lodash';
import { nanoid } from 'nanoid';

const AddPropertyHeader = () => {
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: 'bottom',
});

const [id] = useState(() => nanoid()); // Initialize with a new GUID
const [property, setProperty] = useState<Partial<Omit<PropertyDefinition, 'id'>>>({});

const debounce = useCallback(
// Delay saving state until user activity stops
_.debounce((definition: Partial<Omit<PropertyDefinition, 'id'>>) => {
usePeopleStore.getState().upsertDefinition(id, definition);
// API Calls go here
const val = usePeopleStore.getState().propertyDefinitions;
console.log(val);
}, 750), // Delay (ms)
[usePeopleStore.getState().propertyDefinitions],
);

const handleChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
setProperty(prev => {
const updatedProperty = { ...prev, [name]: value };
debounce(updatedProperty);
return updatedProperty;
});
},
[debounce], // Only recreate this function if debounceSave changes
);

return (
<Popover>
{({ open }) => (
<>
<Popover.Button ref={setReferenceElement} className="flex items-center p-2 outline-none">
<MdAdd className="text-center text-base text-grey-700" />
</Popover.Button>
<Popover.Panel>
<Transition
show={open}
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1">
<Popover.Panel
static
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
className="w-64 overflow-hidden p-4 bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5">
<SlimTextInput
label="Display Name"
placeholder="Property name"
onChange={event => handleChange(event)}
inputProps={{ name: 'header' }}
/>
<SlimTextInput
label="Identifier"
placeholder="property_name"
onChange={event => handleChange(event)}
inputProps={{ name: 'accessor' }}
/>
</Popover.Panel>
</Transition>
</Popover.Panel>
</>
)}
</Popover>
);
};

export default AddPropertyHeader;
9 changes: 3 additions & 6 deletions frontend/src/features/people/components/table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import PropertyHeader from './headers/PropertyHeader';
import { MdAdd } from 'react-icons/md';
import EditableCell from './cells/EditableCell';
import { IndeterminateCheckbox } from 'components';
import AddPropertyHeader from './headers/AddPropertyHeader';

const Table = ({ data, columnJson }: { data: any[]; columnJson: any[] }) => {
// Convert the structure to column definitions for TanStack Table
Expand Down Expand Up @@ -54,12 +55,8 @@ const Table = ({ data, columnJson }: { data: any[]; columnJson: any[] }) => {
},
...userColumns,
{
id: 'add_column',
header: ({ table }) => (
<div className="flex items-center p-2">
<MdAdd className="text-center text-base text-grey-700" />{' '}
</div>
),
id: 'add_property',
header: ({table}) => <AddPropertyHeader />,
cell: ({ row }) => <div></div>,
},
];
Expand Down
28 changes: 28 additions & 0 deletions frontend/src/features/people/stores/usePeopleStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { create } from 'zustand';

export interface PropertyDefinition {
id: string;
accessor?: string;
header?: string;
type?: string;
}

interface State {
propertyDefinitions: Record<string, PropertyDefinition>;
}

//TODO: Maybe rename to upsertProperty ?
interface Actions {
upsertDefinition: (id: string, definition: Partial<Omit<PropertyDefinition, 'id'>>) => void;
}

export const usePeopleStore = create<State & Actions>(set => ({
propertyDefinitions: {},
upsertDefinition: (id, definition) =>
set(state => ({
propertyDefinitions: {
...state.propertyDefinitions,
[id]: { ...definition, id }, // Merge with the existing data
},
})),
}));

0 comments on commit 714330e

Please sign in to comment.