]> Eric's Git Repo - listv4.git/commitdiff
Fixing notifications and list item issues main
authorEric Wertz <ericwertz@Erics-MacBook-Pro.local>
Thu, 19 Jun 2025 16:20:34 +0000 (12:20 -0400)
committerEric Wertz <ericwertz@Erics-MacBook-Pro.local>
Thu, 19 Jun 2025 16:20:34 +0000 (12:20 -0400)
frontend/app/AppContext.tsx
frontend/components/ListContext.tsx
frontend/views/Login.tsx

index 5acbb61a645f981249e9216aa6afada72dfef431..80e984af0bca4b14f5bc5124fd86a196cdebfc0e 100644 (file)
@@ -25,7 +25,7 @@ interface AppContextType {
     user: User | null;
     setUser: (user: User) => void;
     checkAuth: () => void;
     user: User | null;
     setUser: (user: User) => void;
     checkAuth: () => void;
-    fetchData: (url: string) => Promise<any>;
+    fetchData: (url: string, body?: any) => Promise<any>;
     logout: () => void;
 }
 
     logout: () => void;
 }
 
@@ -65,41 +65,50 @@ export class AppContextProvider extends Component<{ children: any }> {
         checkAuth: async () => {
             // Ensure isLoading is true at the beginning of the check
             if (!this.state.isLoading) {
         checkAuth: async () => {
             // Ensure isLoading is true at the beginning of the check
             if (!this.state.isLoading) {
-                this.state.setIsLoading(true);
+                this.setState({ isLoading: true });
             }
             try {
                 const response = await fetch('/auth/check', { credentials: 'include' });
                 const data = await response.json();
                 
                 if (data.status !== 'success') {
             }
             try {
                 const response = await fetch('/auth/check', { credentials: 'include' });
                 const data = await response.json();
                 
                 if (data.status !== 'success') {
-                    this.state.setLoggedIn(false);
+                    this.setState({ loggedIn: false });
                     // Optionally set user to null if not successful
                     // Optionally set user to null if not successful
-                    // this.state.setUser(null);
+                    // this.setState({ user: null });
                     return; // Early return if auth check fails
                 }
                     return; // Early return if auth check fails
                 }
-                this.state.setLoggedIn(true);
-                this.state.setUser({
-                    username: data.data.username,
-                    uuid: data.data.uuid,
+                this.setState({ 
+                    loggedIn: true,
+                    user: {
+                        username: data.data.username,
+                        uuid: data.data.uuid,
+                    }
                 });
             } catch (error) {
                 console.error('Error during auth check:', error);
                 });
             } catch (error) {
                 console.error('Error during auth check:', error);
-                this.state.setLoggedIn(false);
-                // Optionally set user to null on error
-                // this.state.setUser(null);
-                this.state.setNotification({
-                    visible: true,
-                    message: 'Error checking authentication status',
-                    showSpinner: false,
-                    type: 'error',
+                this.setState({ 
+                    loggedIn: false,
+                    notification: {
+                        visible: true,
+                        message: 'Error checking authentication status',
+                        showSpinner: false,
+                        type: 'error',
+                    }
                 });
                 });
+                // Optionally set user to null on error
+                // this.setState({ user: null });
             } finally {
                 // This will always run, ensuring isLoading is set to false
             } finally {
                 // This will always run, ensuring isLoading is set to false
-                this.state.setIsLoading(false);
+                this.setState({ isLoading: false });
             }
         },
             }
         },
-        fetchData: async (url: string) => {
-            return fetch(url, { credentials: 'include' })
+        fetchData: async (url: string, body?: any) => {
+            return fetch(url, { 
+                credentials: 'include', 
+                method: body ? 'POST' : 'GET',
+                headers: body ? { 'Content-Type': 'application/json' } : undefined,
+                body: body ? JSON.stringify(body) : undefined 
+            })
             .then(response => {
                 if (!response.ok) {
                     throw new Error(`Failed to fetch: ${response.status} ${response.statusText}`);
             .then(response => {
                 if (!response.ok) {
                     throw new Error(`Failed to fetch: ${response.status} ${response.statusText}`);
@@ -107,18 +116,21 @@ export class AppContextProvider extends Component<{ children: any }> {
                 return response.json();
             })
             .catch(error => {
                 return response.json();
             })
             .catch(error => {
+                console.log('error', error);
                 console.error('[LoadError]', error);
                 console.error('[LoadError]', error);
-                this.state.setNotification({
-                    visible: true,
-                    message: error.message || 'Failed to load list. Please check connection.',
-                    showSpinner: false,
-                    type: 'error',
+                this.setState({
+                    notification: {
+                        visible: true,
+                        message: error.message || 'Failed to load data. Please check connection.',
+                        showSpinner: false,
+                        type: 'error',
+                    }
                 });
 
                 return null;
             })
             .finally(() => {
                 });
 
                 return null;
             })
             .finally(() => {
-                this.state.setIsLoading(false);
+                this.setState({ isLoading: false });
             });
         },
         logout: () => {
             });
         },
         logout: () => {
index c26a02e27fb61b98d00e75b3e1a357b8e44d62de..92da97ca1abbd6e5ad35bc5a72b7bbdb47b8f502 100644 (file)
@@ -174,13 +174,34 @@ export const useListState = () => {
         }));
     };
 
         }));
     };
 
+    // Recursively set level values based on position in the tree (depth)
+    const applyItemLevels = (items: ItemProps[], level: number = 0): ItemProps[] => {
+        return items.map(item => ({
+            ...item,
+            level,
+            _children: applyItemLevels(item._children, level + 1)
+        }));
+    };
+
+    // Adjust an item's level (and its descendants) by a delta value
+    const adjustLevels = (item: ItemProps, delta: number): ItemProps => {
+        const newLevel = Math.max(0, item.level + delta);
+        return {
+            ...item,
+            level: newLevel,
+            __is_dirty: true,
+            _children: item._children.map(child => adjustLevels(child, delta))
+        };
+    };
+
     const fetchItems = async () => {
         try {
             const response = await fetchData('/list/fetch') as { data: ItemProps[] };
             if (response?.data?.length > 0) {
                 const itemsWithOrders = ensureItemOrders(response.data);
     const fetchItems = async () => {
         try {
             const response = await fetchData('/list/fetch') as { data: ItemProps[] };
             if (response?.data?.length > 0) {
                 const itemsWithOrders = ensureItemOrders(response.data);
-                setItems(itemsWithOrders);
-                //setFocusedItemUuid(itemsWithOrders[0]._uuid);
+                const itemsWithLevels = applyItemLevels(itemsWithOrders);
+                setItems(itemsWithLevels);
+                //setFocusedItemUuid(itemsWithLevels[0]._uuid);
             } else {
                 // Create default empty item
                 const defaultItem: ItemProps = {
             } else {
                 // Create default empty item
                 const defaultItem: ItemProps = {
@@ -246,12 +267,7 @@ export const useListState = () => {
                 if (flatItems.length === 0) return;
                 
                 setSaveStatus('saving');
                 if (flatItems.length === 0) return;
                 
                 setSaveStatus('saving');
-                const response = await fetch('/list/save', {
-                    method: 'POST',
-                    headers: { 'Content-Type': 'application/json' },
-                    credentials: 'include',
-                    body: JSON.stringify(flatItems)
-                });
+                const response = await fetchData('/list/save', flatItems);
                 
                 if (!response.ok) throw new Error(`Save failed: ${response.status}`);
                 
                 
                 if (!response.ok) throw new Error(`Save failed: ${response.status}`);
                 
@@ -299,7 +315,7 @@ export const useListState = () => {
             _type: 'item',
             _created_at: new Date().toISOString(),
             _updated_at: new Date().toISOString(),
             _type: 'item',
             _created_at: new Date().toISOString(),
             _updated_at: new Date().toISOString(),
-            _children: [],
+            _children: currentItem._children, // Inherit children from current item
             __is_new: true,
             __is_dirty: true,
             content: afterContent,
             __is_new: true,
             __is_dirty: true,
             content: afterContent,
@@ -310,10 +326,11 @@ export const useListState = () => {
         };
 
         setItems(prevItems => {
         };
 
         setItems(prevItems => {
-            // Update current item
+            // Update current item - remove children and update content
             const updatedItems = updateItemInTree(prevItems, currentItem._uuid, item => ({
                 ...item,
                 content: beforeContent,
             const updatedItems = updateItemInTree(prevItems, currentItem._uuid, item => ({
                 ...item,
                 content: beforeContent,
+                _children: [], // Remove children from current item
                 __is_dirty: true
             }));
 
                 __is_dirty: true
             }));
 
@@ -446,8 +463,8 @@ export const useListState = () => {
                 __is_dirty: true
             }));
 
                 __is_dirty: true
             }));
 
-            // Insert after parent with updated level
-            const promotedItem = { ...currentItem, level: Math.max(0, currentItem.level - 1), __is_dirty: true };
+            // Insert after parent with updated level (also adjust descendants)
+            const promotedItem = adjustLevels(currentItem, -1);
             const insertAfterParent = (items: ItemProps[], parentUuid: string): ItemProps[] => {
                 for (let i = 0; i < items.length; i++) {
                     if (items[i]._uuid === parentUuid) {
             const insertAfterParent = (items: ItemProps[], parentUuid: string): ItemProps[] => {
                 for (let i = 0; i < items.length; i++) {
                     if (items[i]._uuid === parentUuid) {
@@ -491,11 +508,7 @@ export const useListState = () => {
                 : reorderItems(prevItems.filter(item => item._uuid !== currentItem._uuid));
 
             // Add as child of previous sibling
                 : reorderItems(prevItems.filter(item => item._uuid !== currentItem._uuid));
 
             // Add as child of previous sibling
-            const demotedItem = { 
-                ...currentItem, 
-                level: currentItem.level + 1,
-                __is_dirty: true
-            };
+            const demotedItem = adjustLevels(currentItem, 1);
 
             result = updateItemInTree(result, previousSibling._uuid, sibling => ({
                 ...sibling,
 
             result = updateItemInTree(result, previousSibling._uuid, sibling => ({
                 ...sibling,
index ef34034ef18e433c92d89ef8df1b1e28459fb171..1b08b95e0fc8f688a2faab4cc2eea29ab50e09c9 100644 (file)
@@ -1,6 +1,10 @@
 import { h } from "preact";
 import { h } from "preact";
+import { useContext } from "preact/hooks";
+import { AppContext } from "../app/AppContext";
 
 const Login = () => {
 
 const Login = () => {
+    const { fetchData } = useContext(AppContext);
+    
     const handleSubmit = async (e: Event) => {
         e.preventDefault();
         const form = e.target as HTMLFormElement;
     const handleSubmit = async (e: Event) => {
         e.preventDefault();
         const form = e.target as HTMLFormElement;
@@ -12,17 +16,11 @@ const Login = () => {
         };
         
         try {
         };
         
         try {
-            const response = await fetch('/auth/login', {
-                method: 'POST',
-                headers: {
-                    'Content-Type': 'application/json'
-                },
-                credentials: 'include',
-                body: JSON.stringify(data)
-            });
+            const response = await fetchData('/auth/login', data);
             
             
-            if (!response.ok) {
-                throw new Error('Login failed');
+            if (!response) {
+                console.error('Login failed');
+                return;
             }
             
             // Handle successful login here
             }
             
             // Handle successful login here