)
}
+
+export function EditCategoriesButton(props: { user: User }) {
+ const { user } = props
+ const [isOpen, setIsOpen] = useState(false)
+
+ return (
+
setIsOpen(true)}
+ >
+
+
+
+ )
+}
+
+function CategorySelectorModal(props: {
+ user: User
+ isOpen: boolean
+ setIsOpen: (isOpen: boolean) => void
+}) {
+ const { user, isOpen, setIsOpen } = props
+ const followedCategories =
+ user?.followedCategories === undefined
+ ? CATEGORY_LIST
+ : user.followedCategories
+
+ const selectAll =
+ user.followedCategories === undefined ||
+ followedCategories.length < CATEGORY_LIST.length
+
+ return (
+
+
+
+ {CATEGORY_LIST.map((cat) => (
+ {
+ updateUser(user.id, {
+ followedCategories: checked
+ ? difference(followedCategories, [cat])
+ : union([cat], followedCategories),
+ })
+ }}
+ />
+ ))}
+
+
+
+
+ )
+}
diff --git a/web/hooks/use-event.ts b/web/hooks/use-event.ts
new file mode 100644
index 00000000..443e1095
--- /dev/null
+++ b/web/hooks/use-event.ts
@@ -0,0 +1,20 @@
+// A hook soon to be added to the React core library:
+// https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md
+// TODO: Once React adds this hook, use it instead.
+
+import { useRef, useLayoutEffect, useCallback } from 'react'
+
+type AnyFunction = (...args: any[]) => any
+
+export function useEvent
(callback?: T) {
+ const ref = useRef(() => {
+ throw new Error('Cannot call an event handler while rendering.')
+ })
+ useLayoutEffect(() => {
+ ref.current = callback
+ })
+ return useCallback(
+ (...args) => ref.current?.apply(null, args),
+ []
+ ) as T
+}