diff --git a/components/boards/board.tsx b/components/boards/board.tsx index f968c06..62461c9 100644 --- a/components/boards/board.tsx +++ b/components/boards/board.tsx @@ -1,11 +1,12 @@ import Column from './column'; -import { getBoardTitleWidth, ItemTypes } from './boards'; import { toast } from 'react-toastify'; +import { getBoardTitleWidth, ItemTypes } from './boards'; import ConfirmAction from '../context-menus/confirm-action'; import { DragDropContext, Droppable } from 'react-beautiful-dnd'; import { forceFieldBlurOnPressEnter } from '../../shared/constants'; import React, { useState, useContext, useEffect, useRef } from 'react'; import { capitalizeAllWords, dev, formatDate, generateUniqueID, StateContext } from '../../pages/_app'; +import { Types } from '../../shared/types/types'; export const addBoardScrollBars = () => { let boardColumnItems = document.querySelectorAll(`.boardColumnItems`); @@ -76,9 +77,19 @@ export default function Board(props) { const expandCollapseBoard = (e, board) => { setBoard(prevBoard => { - return { - ...prevBoard, - expanded: !prevBoard.expanded, + if (board?.type == Types.Board) { + return { + ...prevBoard, + options: { + ...prevBoard?.options, + expanded: !prevBoard?.options?.expanded, + } + } + } else { + return { + ...prevBoard, + expanded: !prevBoard.expanded, + } } }); } @@ -102,11 +113,11 @@ export default function Board(props) { e.preventDefault(); setLoading(true); setSystemStatus(`Creating Column.`); - let newListID = `list_${board?.columnOrder.length + 1}`; + let newListID = `list_${board?.data?.columnIDs.length + 1}`; let columnID = `${newListID}_${generateUniqueID(IDs)}`; let formFields = e.target.children; - const newColumnOrder = Array.from(board?.columnOrder); + const newColumnOrder = Array.from(board?.data?.columnIDs); newColumnOrder.push(columnID); const newColumn = { @@ -162,13 +173,16 @@ export default function Board(props) { } if (type === `column`) { - const newColumnOrder = Array.from(board?.columnOrder); + const newColumnOrder = Array.from(board?.data?.columnIDs); newColumnOrder.splice(source.index, 1); newColumnOrder.splice(destination.index, 0, draggableId); setBoard({ ...board, - columnOrder: newColumnOrder, + data: { + ...board.data, + listIDs: newColumnOrder, + } }); return; } @@ -221,16 +235,16 @@ export default function Board(props) { }); } - // useEffect(() => { - // let thisBoard = boards.find(brd => brd.id == board.id); - // if (thisBoard) { - // setBoard(thisBoard); - // } - // }, [boards]) + useEffect(() => { + let thisBoard = boards.find(brd => brd.id == board.id); + if (thisBoard) { + setBoard(thisBoard); + } + }, [boards]) useEffect(() => { if (updates > 0) { - // dev() && board?.columnOrder && board?.columnOrder.length > 0 && console.log(`Updated Board`, board); + // dev() && board?.data?.columnIDs && board?.data?.columnIDs.length > 0 && console.log(`Updated Board`, board); setBoards(prevBoards => { return prevBoards.map(brd => { if (brd.id == board.id) { @@ -259,7 +273,7 @@ export default function Board(props) { setPage(`Boards`); setUpdates(updates + 1); // dev() && console.log(`Updates`, updates); - // dev() && board?.columnOrder && board?.columnOrder.length > 0 && console.log(`Board`, board); + // dev() && board?.data?.columnIDs && board?.data?.columnIDs.length > 0 && console.log(`Board`, board); }, [board]) @@ -268,14 +282,14 @@ export default function Board(props) {
-
-
+
+

{props.index + 1}

-

+

changeLabel(e, board, setBoard)} onKeyDown={(e) => forceFieldBlurOnPressEnter(e)} - style={{ width: board?.expanded ? (board.titleWidth ? board.titleWidth : `75px`) : `100%` }} - className={`boardNameField changeLabel textOverflow ${board?.expanded ? `expandedBoardChangeLabel` : `stretch collapsedBoardChangeLabel`}`} + style={{ width: (board?.expanded || board?.options?.expanded) ? (board.titleWidth ? board.titleWidth : `75px`) : `100%` }} + className={`boardNameField changeLabel textOverflow ${(board?.expanded || board?.options?.expanded) ? `expandedBoardChangeLabel` : `stretch collapsedBoardChangeLabel`}`} />

- {board?.expanded && <> + {(board?.expanded || board?.options?.expanded) && <>

- @@ -331,8 +345,8 @@ export default function Board(props) { |

-
- {board?.expanded && <> +
+ {(board?.expanded || board?.options?.expanded) && <>

Options @@ -340,7 +354,7 @@ export default function Board(props) {

}
- {board?.expanded && <> + {(board?.expanded || board?.options?.expanded) && <> {boards?.length > 1 && ( )}
@@ -412,11 +426,11 @@ export default function Board(props) {
- {board?.columnOrder && board?.columnOrder?.length > 0 && ( + {board?.data?.columnIDs && board?.data?.columnIDs?.length > 0 && ( {(provided, snapshot) => ( -
3 ? `moreBoard overflowingBoard` : ``)}`} ref={provided.innerRef} {...provided.droppableProps} style={props.style}> - {board?.columnOrder && board?.columnOrder.map((columnId, index) => { +
3 ? `moreBoard overflowingBoard` : ``)}`} ref={provided.innerRef} {...provided.droppableProps} style={props.style}> + {board?.data?.columnIDs && board?.data?.columnIDs.map((columnId, index) => { const column = board?.columns[columnId]; const items = column.itemIds.map(itemId => board?.items[itemId]); if (!column.itemType) column.itemType = ItemTypes.Item; diff --git a/components/boards/boards.tsx b/components/boards/boards.tsx index 80f2486..391fefd 100644 --- a/components/boards/boards.tsx +++ b/components/boards/boards.tsx @@ -1,13 +1,12 @@ import Board from './board'; import { toast } from 'react-toastify'; import { createBoard } from '../../shared/database'; -import { getBoardsFromBoardIds } from '../../firebase'; import MultiSelector from '../selector/multi-selector'; -import { useState, useEffect, useContext } from 'react'; import IVFSkeleton from '../loaders/skeleton/ivf_skeleton'; +import { useState, useEffect, useContext, useRef } from 'react'; import { capWords, dev, replaceAll, StateContext } from '../../pages/_app'; import { Droppable, Draggable, DragDropContext } from 'react-beautiful-dnd'; -import { findHighestNumberInArrayByKey, generateArray } from '../../shared/constants'; +import { findHighestNumberInArrayByKey, generateArray, isValid } from '../../shared/constants'; export enum ItemTypes { Item = `Item`, @@ -37,32 +36,30 @@ export default function Boards(props: any) { user, authState, setLoading, + usersGrids, IDs, setIDs, setSystemStatus, + setUsersGridsState, rte, router, setRte, - grids, gridsLoading, selectedGrids, setSelectedGrids, boards, userBoards, setBoards, boardsLoading, setBoardsLoading, + grids, gridsLoading, selectedGrids, selectedGrid, setSelectedGrids, } = useContext(StateContext); let { dbBoards = boards } = props; + const multiSelectorRef = useRef(null); let [updates, setUpdates] = useState(0); let [useSingleSelect, ] = useState(true); let [useGridSearchCreate, ] = useState(false); let [searchingGrid, setSearchingGrid] = useState(true); - - const setBoardsFromGrid = async (activeGrid) => { - setBoardsLoading(true); - let boardsForGrid = await getBoardsFromBoardIds(activeGrid?.data?.boardIDs); - setBoards(boardsForGrid); - setBoardsLoading(false); - } const updateSelectedGrids = async (updatedSelectedGrids) => { - setSelectedGrids(updatedSelectedGrids); - let activeGrid = updatedSelectedGrids[0]; - // updateUserFields() - if (activeGrid) setBoardsFromGrid(activeGrid); + let thisGrid = updatedSelectedGrids[0]; + setUsersGridsState(thisGrid?.id, usersGrids, false); + let userGridURL = `/user/${user?.rank}/grids/${thisGrid?.rank}`; + router.replace(userGridURL, undefined, { + shallow: true, + }); } const onDragEnd = (dragEndEvent) => { @@ -78,7 +75,7 @@ export default function Boards(props: any) { let updatedBoardsPositions = updatedBoards.map((brd, brdIndex) => ({ ...brd, position: brdIndex + 1 })); setBoards(updatedBoardsPositions); - // dev() && console.log(`Boards Drag`, updatedBoardsPositions); + dev() && console.log(`Boards Drag`, updatedBoardsPositions); } const addNewBoard = async (e) => { @@ -161,7 +158,7 @@ export default function Boards(props: any) {
1) ? `hasGridSelector ${useSingleSelect ? `withSingleSelect` : ``}` : ``}`} style={{ padding: 0, paddingBottom: 7 }}>

- {user != null ? user?.name + `s ` : ``}{selectedGrids.length == 1 ? selectedGrids[0]?.name + (!useGridSearchCreate ? ` Grid` : ``) : `Grids`} + {user != null ? user?.name + `s ` : ``}{(!gridsLoading && selectedGrids.length == 1) ? selectedGrids[0]?.name + (!useGridSearchCreate ? ` Grid` : ``) : `Grids`}

@@ -188,9 +185,9 @@ export default function Boards(props: any) { ) : grids?.length > 1 && ( (
{dbBoards && dbBoards?.length > 0 && dbBoards?.map((bord, bordIndex) => { - if (bord.expanded == null || bord.expanded == undefined) bord.expanded = true; + let boardDefaultExpanded = !isValid(bord?.expanded) || bord?.options?.expanded; + bord.expanded = boardDefaultExpanded; return ( {(provided, snapshot) => ( diff --git a/components/form.tsx b/components/form.tsx index 130250e..61e0d5e 100644 --- a/components/form.tsx +++ b/components/form.tsx @@ -71,6 +71,7 @@ export default function Form(props?: any) { const { id, navForm, className, style } = props; const { + devEnv, onSignIn, onSignOut, setContent, @@ -362,14 +363,7 @@ export default function Form(props?: any) { : <>} : <>} - {formButtonField( - `Users Loading`, - `usersSkeleton`, - user ? `Sign Out` : authState, - , - )} - - {user != null && ( + {devEnv && user != null && (
{formButtonField( `Users Loading`, @@ -383,6 +377,13 @@ export default function Form(props?: any) {
)} + {formButtonField( + `Users Loading`, + `usersSkeleton`, + user ? `Sign Out` : authState, + , + )} + {(authState == `Sign In` || authState == `Sign Up`) && ( formButtonField( `Users Loading`, diff --git a/components/grids/grid.tsx b/components/grids/grid.tsx index c0c1515..9a6dc5a 100644 --- a/components/grids/grid.tsx +++ b/components/grids/grid.tsx @@ -1,11 +1,7 @@ -import { useContext } from 'react'; import Boards from '../boards/boards'; -import { StateContext } from '../../pages/_app'; export default function Grid(props: any) { - let { user, selectedGrids} = useContext(StateContext); - let { grid, grid_id = user != null ? user?.lastSelectedGridID : selectedGrids?.length > 0 ? selectedGrids[0]?.id : ``, className = `gridComponent` } = props; - + let { className = `gridComponent` } = props; return (
diff --git a/components/grids/grids.tsx b/components/grids/grids.tsx index 1ed1d76..32ab2a9 100644 --- a/components/grids/grids.tsx +++ b/components/grids/grids.tsx @@ -1,5 +1,6 @@ import Grid from './grid'; -import { useContext } from 'react'; +// import { useRouter } from 'next/router'; +import { useContext, useEffect } from 'react'; import { StateContext } from '../../pages/_app'; // import { logToast } from '../../shared/constants'; // import { Grid as GridModel } from '../../shared/models/Grid'; @@ -8,9 +9,25 @@ import { StateContext } from '../../pages/_app'; // import { boardConverter, boardsTable, db, gridConverter, gridsTable } from '../../firebase'; export default function Grids(props: any) { + // let router = useRouter(); + // let { id, gridid } = router.query; let { className = `gridsComponent` } = props; let { user, selectedGrids } = useContext(StateContext); + // useEffect(() => { + // if (user != null) { + // if (id) { + // if (gridid) { + // if (usersGrids && usersGrids?.length > 0) { + // let thisGrid = usersGrids?.find(gr => String(gr?.rank) == String(gridid)); + // if (thisGrid) { + // setUsersGridsState(thisGrid?.id, usersGrids, false); + // } + // } + // } + // } + // } + // }, [user, usersGrids]) // useEffect(() => { // let gridsDatabaseRealtimeListener = null; diff --git a/components/profile/profile-grids.tsx b/components/profile/profile-grids.tsx index 9fde11b..d59ad0a 100644 --- a/components/profile/profile-grids.tsx +++ b/components/profile/profile-grids.tsx @@ -11,13 +11,14 @@ import IVFSkeleton from '../loaders/skeleton/ivf_skeleton'; export default function ProfileGrids(props: any) { let router = useRouter(); let { id, gridid } = router.query; - let { userItem = false, profileType = `Profile` } = props; let { user, users, usersLoading } = useContext(StateContext); + let { userItem = false, profileType = `Profile`, userOnUserGrids = true } = props; let [userIsQuery, setUserIsQuery] = useState(false); let [originalQuery, setOriginalQuery] = useState(``); let [profileLoading, setProfileLoading] = useState(true); let [profileToRender, setProfileToRender] = useState(user); + let [userOnGrids, setUserOnGrids] = useState(userOnUserGrids); const profileLoadingComponent = (label: string = `${profileType} Loading`) => { return ( @@ -48,8 +49,56 @@ export default function ProfileGrids(props: any) { } + // useEffect(() => { + // let userIsOnGrids = userItem == true && userOnUserGrids == true && user != null && id && window?.location?.href?.includes(`grids`); + // setUserOnGrids(userIsOnGrids); + // if (userIsOnGrids) return; + // if (id && !userOnGrids) { + // let quer = id?.toString(); + // setOriginalQuery(quer); + // let query = quer?.toLowerCase(); + + // const onCantFindUser = () => { + // setUserIsQuery(false); + // setProfileLoading(false); + // if (!userOnGrids) { + // console.log(`Cannot Find User for Query "${quer}"`); + // } + // } + + // if (users.length > 0) { + // let profQuery = users.find((prf: User) => ( + // stringMatch(prf?.name, query) + // || stringMatch(prf?.id, query) + // || stringMatch(prf?.ID, query) + // || stringMatch(prf?.uid, query) + // || stringMatch(prf?.uuid, query) + // || stringMatch(prf?.email, query) + // || stringMatch(prf?.rank?.toString(), query) + // )) + + // const onFoundUser = () => { + // setProfileLoading(false); + // setProfileToRender(profQuery); + // console.log(`Found User for Query "${quer}"`, profQuery); + // } + + // if (profQuery) { + // if (user != null) { + // if (stringMatch(user?.id, profQuery?.id)) { + // setUserIsQuery(true); + // console.log(`User is Profile Query "${quer}"`); + // } else onFoundUser(); + // } else onFoundUser(); + // } else onCantFindUser(); + // } else onCantFindUser(); + // } else { + // setProfileToRender(user); + // } + // }, [user, users]) + return <> - {user != null && id && window?.location?.href?.includes(`grids`) ? : usersLoading ? profileLoadingComponent(`Loading ${profileType}`) : ( + {(usersLoading || user != null) ? : (
{id ? <> diff --git a/components/profile/profile.tsx b/components/profile/profile.tsx index 197bd3d..a4fabeb 100644 --- a/components/profile/profile.tsx +++ b/components/profile/profile.tsx @@ -11,13 +11,14 @@ import IVFSkeleton from '../loaders/skeleton/ivf_skeleton'; export default function Profile(props: any) { let router = useRouter(); let { id, gridid } = router.query; - let { userItem = false, profileType = `Profile` } = props; let { user, users, usersLoading } = useContext(StateContext); + let { userItem = false, profileType = `Profile`, userOnUserGrids = true } = props; let [userIsQuery, setUserIsQuery] = useState(false); let [originalQuery, setOriginalQuery] = useState(``); let [profileLoading, setProfileLoading] = useState(true); let [profileToRender, setProfileToRender] = useState(user); + let [userOnGrids, setUserOnGrids] = useState(userOnUserGrids); const profileLoadingComponent = (label: string = `${profileType} Loading`) => { return ( @@ -49,8 +50,9 @@ export default function Profile(props: any) { } useEffect(() => { - let userOnGrids = user != null && id && window?.location?.href?.includes(`grids`); - if (userOnGrids) return; + let userIsOnGrids = userItem == true && userOnUserGrids == true && user != null && id && window?.location?.href?.includes(`grids`); + setUserOnGrids(userIsOnGrids); + if (userIsOnGrids) return; if (id && !userOnGrids) { let quer = id?.toString(); setOriginalQuery(quer); @@ -96,7 +98,7 @@ export default function Profile(props: any) { }, [user, users]) return <> - {user != null && id && window?.location?.href?.includes(`grids`) ? : usersLoading ? profileLoadingComponent(`Loading ${profileType}`) : ( + {(userOnGrids || usersLoading) ? : (
{id ? <> diff --git a/components/selector/multi-selector.tsx b/components/selector/multi-selector.tsx index f71a422..3f6481f 100644 --- a/components/selector/multi-selector.tsx +++ b/components/selector/multi-selector.tsx @@ -1,9 +1,10 @@ -import { useState } from 'react'; +import { forwardRef, useContext, useImperativeHandle, useState } from 'react'; import { styled } from '@mui/material/styles'; import { autocompleteClasses } from '@mui/material/Autocomplete'; import { AutocompleteGetTagProps, useAutocomplete } from '@mui/material'; import { GridTypes, Types } from '../../shared/types/types'; import { isValid } from '../../shared/constants'; +import { StateContext } from '../../pages/_app'; const InputWrapper = styled(`div`)( ({ theme }) => ` @@ -117,19 +118,19 @@ const Listbox = styled(`ul`)( `, ); -export default function MultiSelector(props) { +const MultiSelector = forwardRef((props: any, ref) => { let { id, options, onChange, - defaultValue, single = false, showClearAll = true, inputDisabled = false, hostClass = `multiSelectorContainer`, placeholder = `Start Typing or Click Here`, } = props; - const [activeOptions, setActiveOptions] = useState(defaultValue || []); + + let { activeOptions, setActiveOptions } = useContext(StateContext); const onChangeValue = (val) => { if (single) val = isValid(val) && val?.length > 0 ? [val[val.length - 1]] : []; @@ -138,6 +139,12 @@ export default function MultiSelector(props) { onChange(val); } + useImperativeHandle(ref, () => ({ + setValue: (newValues) => { + onChangeValue(newValues); + }, + })); + const { value, focused, @@ -240,4 +247,6 @@ export default function MultiSelector(props) {
); -} \ No newline at end of file +}) + +export default MultiSelector; \ No newline at end of file diff --git a/firebase.ts b/firebase.ts index b9eabe2..954521f 100644 --- a/firebase.ts +++ b/firebase.ts @@ -7,10 +7,10 @@ import { Task } from './shared/models/Task'; import { initializeApp } from 'firebase/app'; import { Board } from './shared/models/Board'; import { Email } from './shared/models/Email'; +import { Profile } from './shared/models/Profile'; import { logToast, userQueryFields } from './shared/constants'; import { GoogleAuthProvider, browserLocalPersistence, deleteUser, getAuth, setPersistence } from 'firebase/auth'; -import { collection, deleteDoc, doc, getDocs, getFirestore, onSnapshot, orderBy, query, setDoc, updateDoc, where, writeBatch } from 'firebase/firestore'; -import { Profile } from './shared/models/Profile'; +import { collection, deleteDoc, doc, getDocs, getFirestore, onSnapshot, orderBy, query, setDoc, updateDoc, where } from 'firebase/firestore'; export enum Environments { beta = `beta_`, @@ -70,15 +70,23 @@ export const listsTable = environment + Tables.lists; export const itemsTable = environment + Tables.items; export const tasksTable = environment + Tables.tasks; -export const usingCollections = { - users: usersTable, - grids: gridsTable, +export const gridDataCollections = { boards: boardsTable, lists: listsTable, items: itemsTable, tasks: tasksTable, } +export const userDataCollections = { + grids: gridsTable, + ...gridDataCollections, +} + +export const usingCollections = { + users: usersTable, + ...userDataCollections, +} + export const dbCollections = { ...usingCollections, emails: emailsTable, @@ -86,6 +94,8 @@ export const dbCollections = { } export const collectionNames = Object.values(usingCollections); +export const userDataCollectionNames = Object.values(userDataCollections); +export const gridDataCollectionNames = Object.values(gridDataCollections); export const userConverter = { toFirestore: (usr: User) => { diff --git a/pages/_app.js b/pages/_app.js index 1d9049f..91d1ccc 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -6,14 +6,19 @@ import { User } from '../shared/models/User'; import { toast, ToastContainer } from 'react-toastify'; import { isValid, logToast } from '../shared/constants'; import { AnimatePresence, motion } from 'framer-motion'; -import { collection, onSnapshot } from 'firebase/firestore'; -import { AuthStates, GridTypes } from '../shared/types/types'; -import { auth, db, userConverter, usersTable } from '../firebase'; +import { collection, onSnapshot, query, where } from 'firebase/firestore'; +import { AuthStates, GridTypes, Types } from '../shared/types/types'; import { createContext, useRef, useState, useEffect } from 'react'; import ContextMenu from '../components/context-menus/context-menu'; import { renderFirebaseAuthErrorMessage } from '../components/form'; import { seedUserData as generateSeedUserData } from '../shared/database'; import { onAuthStateChanged, signInWithEmailAndPassword, signOut } from 'firebase/auth'; +import { auth, db, userConverter, gridDataCollectionNames, usersTable, gridsTable, gridConverter } from '../firebase'; +import { Grid } from '../shared/models/Grid'; +import { Board } from '../shared/models/Board'; +import { List } from '../shared/models/List'; +import { Item } from '../shared/models/Item'; +import { Task } from '../shared/models/Task'; export const StateContext = createContext({}); @@ -373,6 +378,7 @@ export default function ProductIVF({ Component, pageProps, router }) { let menuRef = useRef(null); let loaded = useRef(false); let mobileMenuBreakPoint = 697; + let { id, gridid } = router.query; let [IDs, setIDs] = useState([]); let [rte, setRte] = useState(``); @@ -414,6 +420,7 @@ export default function ProductIVF({ Component, pageProps, router }) { let [userGrids, setUserGrids] = useState([]); let [selected, setSelected] = useState(null); let [userBoards, setUserBoards] = useState([]); + let [usersGrids, setUsersGrids] = useState([]); let [alertOpen, setAlertOpen] = useState(false); let [rearranging, setRearranging] = useState(false); let [boardLoaded, setBoardLoaded] = useState(false); @@ -422,11 +429,13 @@ export default function ProductIVF({ Component, pageProps, router }) { let [menuPosition, setMenuPosition] = useState(null); let [gridsLoading, setGridsLoading] = useState(true); let [usersLoading, setUsersLoading] = useState(true); + let [activeOptions, setActiveOptions] = useState([]); let [emailsLoading, setEmailsLoading] = useState(true); let [boardsLoading, setBoardsLoading] = useState(true); let [tasksFiltered, setTasksFiltered] = useState(false); let [boardCategories, setBoardCategories] = useState([]); let [profilesLoading, setProfilesLoading] = useState(true); + let [selectedGridData, setSelectedGridData] = useState(null); let [itemTypeMenuOpen, setItemTypeMenuOpen] = useState(false); let [completeFiltered, setCompleteFiltered] = useState(false); @@ -441,7 +450,10 @@ export default function ProductIVF({ Component, pageProps, router }) { const resetGridsBoards = () => { setGrids([]); setBoards([]); + setUserGrids([]); + setUsersGrids([]); setSelectedGrids([]); + setActiveOptions([]); setSelectedGrid(null); setGridsLoading(true); setBoardsLoading(true); @@ -550,13 +562,18 @@ export default function ProductIVF({ Component, pageProps, router }) { const signInUser = (usr, navigateToLastSelectedGrid = false) => { setUser(usr); setAuthState(AuthStates.Sign_Out); + if (navigateToLastSelectedGrid) { - const urlId = `${usr?.rank}-${usr?.name}-${usr?.uid}`; + const urlId = `${usr?.rank}`; + // const urlId = `${usr?.rank}-${usr?.name}-${usr?.uid}`; const userId = urlId || usr?.id; const gridId = usr?.lastSelectedGridID; - let { rank, name, uuid, uid } = extractIDDetails(gridId); - let gridUrlId = `${rank}-${name}-${uuid}`; - router.replace(`/user/${userId}/grids/${gridUrlId}`, undefined, { + let { rank } = extractIDDetails(gridId); + // let { name, uuid } = extractIDDetails(gridId); + let gridUrlId = `${rank}`; + // let gridUrlId = `${rank}-${name}-${uuid}`; + let userStartURL = `/user/${userId}/grids/${gridUrlId}`; + router.replace(userStartURL, undefined, { shallow: true, }); } @@ -589,10 +606,112 @@ export default function ProductIVF({ Component, pageProps, router }) { }); } + useEffect(() => { + if (selectedGridData?.selectedGrid && selectedGridData?.boards && selectedGridData?.lists && selectedGridData?.items && selectedGridData?.tasks) { + dev() && console.log(`Selected Grid Data`, selectedGridData); + let gridBoardsByID = selectedGridData?.selectedGrid?.data?.boardIDs?.map(bordID => { + let gridBoard = selectedGridData?.boards?.find(brd => brd?.id == bordID); + if (gridBoard) return new Board(gridBoard); + }) + setBoards(gridBoardsByID); + setBoardsLoading(false); + } + }, [selectedGridData]); + + useEffect(() => { + let unsubscribeUserData = {}; + let listenforGridsDataChanges = null; + if (selectedGrid != null) { + setBoardsLoading(true); + dev() && console.log(`Selected Grid`, selectedGrid); + for (const collectionName of gridDataCollectionNames) { + const gridData_Database = collection(db, collectionName); + const gridDataQuery = query(gridData_Database, where(`gridID`, `==`, selectedGrid?.id)); + if (unsubscribeUserData[collectionName] == null) { + unsubscribeUserData[collectionName] = onSnapshot(gridDataQuery, gridDataSnapshot => { + const gridDataDocs = gridDataSnapshot.docs.map(doc => ({ ...doc.data() })); + const formattedGridDataDocs = gridDataDocs?.sort((a, b) => a?.rank - b?.rank)?.map(doc => ({ ...doc, label: doc?.name, value: doc?.id })); + const modeledGridDataDocs = formattedGridDataDocs?.map(doc => { + if (doc?.type == Types.Board) { + return new Board(doc); + } else if (doc?.type == Types.List) { + return new List(doc); + } else if (doc?.type == Types.Item) { + return new Item(doc); + } else { + return new Task(doc); + } + }); + setSelectedGridData(prevGridData => ({ + ...prevGridData, + selectedGrid, + [collectionName]: modeledGridDataDocs, + })) + }); + } else { + setSelectedGridData(null); + unsubscribeUserData[collectionName] = null; + } + } + } else if (listenforGridsDataChanges != null) { + if (listenforGridsDataChanges != null) listenforGridsDataChanges(); + if (Object.keys(unsubscribeUserData)?.length > 0) Object.values(unsubscribeUserData).forEach(unsubscribe => unsubscribe()); + }; + return () => { + if (listenforGridsDataChanges != null) listenforGridsDataChanges(); + if (Object.keys(unsubscribeUserData)?.length > 0) Object.values(unsubscribeUserData).forEach(unsubscribe => unsubscribe()); + }; + }, [selectedGrid]) + + const setUsersGridsState = (lastSelectedGridID, usersGridsByID, updateGrids = true) => { + if (updateGrids == true) { + setGrids(usersGridsByID); + setUserGrids(usersGridsByID); + setUsersGrids(usersGridsByID); + } + let lastSelectedGrid = usersGridsByID?.find(gr => gr?.id == lastSelectedGridID); + if (lastSelectedGrid) { + setSelectedGrid(lastSelectedGrid); + setSelectedGrids([lastSelectedGrid]); + setActiveOptions([lastSelectedGrid]); + } + setGridsLoading(false); + } + + useEffect(() => { + let listenforUserGridsChanges = null; + if (user != null) { + const gridsDatabase = collection(db, gridsTable)?.withConverter(gridConverter); + const gridsQuery = query(gridsDatabase, where(`data.users`, `array-contains`, user?.email)); + if (listenforUserGridsChanges == null) listenforUserGridsChanges = onSnapshot(gridsQuery, gridsUpdates => { + setGridsLoading(true); + let userGridsFromDB = []; + gridsUpdates.forEach((doc) => userGridsFromDB.push({ ...doc.data() })); + userGridsFromDB = userGridsFromDB?.sort((a, b) => a?.rank - b?.rank)?.map(gr => new Grid({ ...gr, label: gr?.name, value: gr?.id })); + let usersGridsByID = user?.data?.gridIDs.map(gridID => { + let userGridByID = userGridsFromDB?.find(gr => gr?.id == gridID); + if (userGridByID) return userGridByID; + }) + if (id) { + if (gridid) { + if (usersGridsByID && usersGridsByID?.length > 0) { + let thisGrid = usersGridsByID?.find(gr => String(gr?.rank) == String(gridid)); + if (thisGrid) { + setUsersGridsState(thisGrid?.id, usersGridsByID); + } + } + } else setUsersGridsState(user?.lastSelectedGridID, usersGridsByID); + } else setUsersGridsState(user?.lastSelectedGridID, usersGridsByID); + dev() && console.log(`Grids`, usersGridsByID); + }) + } else if (listenforUserGridsChanges != null) listenforUserGridsChanges(); + return () => {if (listenforUserGridsChanges != null) listenforUserGridsChanges();}; + }, [user]) + useEffect(() => { let listenForUserAuthChanges = null; if (users?.length > 0) { - listenForUserAuthChanges = onAuthStateChanged(auth, async (usr) => { + if (listenForUserAuthChanges == null) listenForUserAuthChanges = onAuthStateChanged(auth, async (usr) => { if (usr) { if (usr?.uid) { let thisUser = users.find(us => us?.uid == usr?.uid); @@ -600,21 +719,18 @@ export default function ProductIVF({ Component, pageProps, router }) { } } }); - } else { - if (listenForUserAuthChanges != null) listenForUserAuthChanges(); - } - return () => { - if (listenForUserAuthChanges != null) listenForUserAuthChanges(); - } + } else if (listenForUserAuthChanges != null) listenForUserAuthChanges(); + return () => {if (listenForUserAuthChanges != null) listenForUserAuthChanges();}; }, [users]); useEffect(() => { const usersDatabase = collection(db, usersTable)?.withConverter(userConverter); const usersDatabaseRealtimeListener = onSnapshot(usersDatabase, async usersUpdates => { + // On Users Database Update setUsersLoading(true); let usersFromDB = []; usersUpdates.forEach((doc) => usersFromDB.push(new User({ ...doc.data() }))); - usersFromDB = usersFromDB.sort((a, b) => a?.rank - b?.rank); + usersFromDB = usersFromDB?.sort((a, b) => a?.rank - b?.rank); setUsers(usersFromDB); if (user != null) { let thisUser = usersFromDB?.find(usr => usr?.uid == user?.uid); @@ -622,12 +738,9 @@ export default function ProductIVF({ Component, pageProps, router }) { } setUsersLoading(false); dev() && console.log(`Users`, usersFromDB); - }, error => { - logToast(`Error on Get Users from Database`, error, true); - }) - return () => { - usersDatabaseRealtimeListener(); - } + // Finish Users Database Update + }, error => logToast(`Error on Get Users from Database`, error, true)); + return () => usersDatabaseRealtimeListener(); }, []) useEffect(() => { @@ -776,6 +889,7 @@ export default function ProductIVF({ Component, pageProps, router }) { seedUserData, signOutReset, getGridsBoards, + setUsersGridsState, // Grids & Boards menuRef, @@ -786,6 +900,7 @@ export default function ProductIVF({ Component, pageProps, router }) { boards, setBoards, selected, setSelected, userGrids, setUserGrids, + usersGrids, setUsersGrids, userBoards, setUserBoards, categories, setCategories, boardLoaded, setBoardLoaded, @@ -793,9 +908,11 @@ export default function ProductIVF({ Component, pageProps, router }) { gridsLoading, setGridsLoading, menuPosition, setMenuPosition, boardsLoading, setBoardsLoading, + activeOptions, setActiveOptions, selectedGrids, setSelectedGrids, tasksFiltered, setTasksFiltered, boardCategories, setBoardCategories, + selectedGridData, setSelectedGridData, completeFiltered, setCompleteFiltered, itemTypeMenuOpen, setItemTypeMenuOpen, }}> diff --git a/pages/user/[id]/index.mdx b/pages/user/[id]/index.mdx index 0819c1d..6a0799d 100644 --- a/pages/user/[id]/index.mdx +++ b/pages/user/[id]/index.mdx @@ -2,4 +2,4 @@ import Profile from '../../../components/profile/profile' # User - \ No newline at end of file + \ No newline at end of file diff --git a/pages/user/index.mdx b/pages/user/index.mdx index 0bda02c..8a2baa1 100644 --- a/pages/user/index.mdx +++ b/pages/user/index.mdx @@ -2,4 +2,4 @@ import Profile from '../../components/profile/profile' # User - \ No newline at end of file + \ No newline at end of file