import { type Ref, createContext, memo, useContext, useEffect, useRef, } from "react" import { createStore, useStore } from "zustand" import { useShallow } from "zustand/react/shallow" import { Button } from "~/components/button" import { DEFAULT_NODE, type Entry } from "~/home/graph" import { useRootStore } from "./store" function ApplicationList() { const entries = useRootStore(useShallow((state) => state.entries)) return Object.values(entries).map((entry) => ( )) } interface ListItemState { isAddingStage: boolean newStageValue: string setNewStageValue: (newStageValue: string) => void setIsAddingStage: (isAddingStage: boolean) => void addStage: (entryName: string) => void } function createListItemStore() { return createStore()((set, get) => ({ isAddingStage: false, newStageValue: "", setNewStageValue: (newStageValue: string) => set({ newStageValue }), setIsAddingStage: (isAddingStage: boolean) => set({ isAddingStage }), addStage: (entryName) => { const store = useRootStore.getState() let stage = get().newStageValue if (stage) { if (stage === DEFAULT_NODE.acceptedNode.key.toLowerCase()) { stage = DEFAULT_NODE.acceptedNode.key } else if (stage === DEFAULT_NODE.rejectedNode.key.toLowerCase()) { stage = DEFAULT_NODE.rejectedNode.key } store.addStageInEntry(stage, entryName) set({ isAddingStage: false, newStageValue: "" }) } }, })) } type ListItemStore = ReturnType const ListItemStoreContext = createContext( null as unknown as ListItemStore, ) function useListItemStore(selector: (state: ListItemState) => T): T { const store = useContext(ListItemStoreContext) return useStore(store, selector) } const EntryContext = createContext(null as unknown as Entry) const ApplicationListItem = memo(({ entry }: { entry: Entry }) => { const store = useRef(null) if (!store.current) { store.current = createListItemStore() } return (
{entry.name}
    {entry.stages.map((step) => ( ))}
) }) const StageItem = memo(({ stage }: { stage: string }) => (
  • {stage} {stage !== DEFAULT_NODE.applicationSubmittedNode.key ? ( ) : null}
  • )) function StageItemActions({ stage }: { stage: string }) { const entry = useContext(EntryContext) const deleteStageInEntry = useRootStore((state) => state.deleteStageInEntry) return (
    ) } function NewStageInput() { const isAddingStage = useListItemStore((state) => state.isAddingStage) const inputRef = useRef(null) useEffect(() => { if (isAddingStage) { inputRef.current?.focus() } }, [isAddingStage]) if (isAddingStage) { return (
  • ) } return null } function ActualStageInput({ ref }: { ref: Ref }) { const entry = useContext(EntryContext) const newStageValue = useListItemStore((state) => state.newStageValue) const setNewStageValue = useListItemStore((state) => state.setNewStageValue) const addStage = useListItemStore((state) => state.addStage) return ( { setNewStageValue(event.currentTarget.value) }} onKeyDown={(event) => { if (event.key === "Enter") { addStage(entry.name) } }} className="bg-transparent" /> ) } function ApplicationActions() { const isAddingStage = useListItemStore((state) => state.isAddingStage) if (isAddingStage) { return } return } const DefaultActions = memo(() => { const entry = useContext(EntryContext) const setIsAddingStage = useListItemStore((state) => state.setIsAddingStage) const addStageToEntry = useRootStore((state) => state.addStageInEntry) const deleteEntry = useRootStore((state) => state.deleteEntry) const isApplicationFinalized = entry.stages.at(-1) === DEFAULT_NODE.acceptedNode.key || entry.stages.at(-1) === DEFAULT_NODE.rejectedNode.key function onDeleteApplication() { if (confirm("Are you sure you want to delete this application?")) { deleteEntry(entry.name) } } function onAccepted() { addStageToEntry(DEFAULT_NODE.acceptedNode.key, entry.name) } function onRejected() { addStageToEntry(DEFAULT_NODE.rejectedNode.key, entry.name) } return (
    ) }) const AddStageActions = memo(() => { const entry = useContext(EntryContext) const setIsAddingStage = useListItemStore((state) => state.setIsAddingStage) const addStage = useListItemStore((state) => state.addStage) function onOk() { addStage(entry.name) } function onCancel() { setIsAddingStage(false) } return (
    ) }) export { ApplicationList }