/ src / checkbox-storage.tsx
checkbox-storage.tsx
 1  import { useEffect } from "react";
 2  
 3  export const CheckboxStorage = () => {
 4    useEffect(() => {
 5      const form = document.querySelector("form");
 6      if (!form) return;
 7  
 8      // --- Checkbox persistence ---
 9      const STORAGE_KEY = "dungeon-motion-selections";
10      const checkboxes = form.querySelectorAll<HTMLInputElement>(
11        'input[type="checkbox"]'
12      );
13  
14      const saved = localStorage.getItem(STORAGE_KEY);
15      if (saved) {
16        try {
17          const selected = JSON.parse(saved);
18          for (const cb of checkboxes) {
19            if (cb.name && selected[cb.name]) {
20              cb.checked = true;
21            }
22          }
23        } catch (error) {
24          console.warn("Failed to parse saved moves", error);
25        }
26      }
27  
28      const handleChange = () => {
29        const selected: Record<string, boolean> = {};
30        for (const cb of checkboxes) {
31          selected[cb.value] = cb.checked;
32        }
33        localStorage.setItem(STORAGE_KEY, JSON.stringify(selected));
34      };
35  
36      for (const cb of checkboxes) {
37        cb.addEventListener("change", handleChange);
38      }
39  
40      // --- Text/number/textarea/select persistence ---
41      const FIELDS_KEY = "dungeon-motion-fields";
42      const fields = form.querySelectorAll<
43        HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
44      >('input[type="text"], input[type="number"], textarea, select');
45  
46      const savedFields = localStorage.getItem(FIELDS_KEY);
47      if (savedFields) {
48        try {
49          const values: Record<string, string> = JSON.parse(savedFields);
50          for (const field of fields) {
51            if (field.name && values[field.name] !== undefined) {
52              field.value = values[field.name];
53            }
54          }
55        } catch (error) {
56          console.warn("Failed to parse saved fields", error);
57        }
58      }
59  
60      let debounceTimer: ReturnType<typeof setTimeout>;
61      const handleFieldInput = () => {
62        clearTimeout(debounceTimer);
63        debounceTimer = setTimeout(() => {
64          const values: Record<string, string> = {};
65          for (const field of fields) {
66            if (field.name) values[field.name] = field.value;
67          }
68          localStorage.setItem(FIELDS_KEY, JSON.stringify(values));
69        }, 300);
70      };
71  
72      for (const field of fields) {
73        field.addEventListener("input", handleFieldInput);
74      }
75  
76      return () => {
77        clearTimeout(debounceTimer);
78        for (const cb of checkboxes) {
79          cb.removeEventListener("change", handleChange);
80        }
81        for (const field of fields) {
82          field.removeEventListener("input", handleFieldInput);
83        }
84      };
85    }, []);
86  
87    return null;
88  };