From 67581346cd5e51cc7c5ca483d856d42b0067c565 Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Sun, 5 May 2024 22:18:45 -0700 Subject: [PATCH 1/4] [update(state)][decks]: update deck loading state DESCRIPTION: This commit updates the state management for decks to include a loading state. ISSUES: Still loading too slowly. --- .gitignore | 1 + src/context/hooks/useDebounce.jsx | 29 +++ src/context/hooks/useFormSubmission.jsx | 4 +- src/context/hooks/useRCFormHook.jsx | 15 +- src/context/hooks/useSelectorActions.jsx | 42 ++-- src/context/state/useAuthManager.jsx | 75 +++++-- src/context/state/useManager.jsx | 3 +- src/data/formsConfig.jsx | 62 ++++-- src/data/index.jsx | 4 +- .../REUSABLE_COMPONENTS/MDBOX/index.jsx | 2 +- .../RCLOADINGBUTTON/index.jsx | 2 +- .../RCTYPOGRAPHY/index.jsx | 15 ++ .../RC_FORMS/RCDynamicForm.jsx | 58 ++++-- .../REUSABLE_COMPONENTS/RC_FORMS/RCInput.jsx | 99 +++++++--- .../RC_OTHER/RCInfoItem.jsx | 22 ++- .../utils/system-utils/LoadingIndicator.js | 2 +- .../utils/system-utils/LoadingOverlay.jsx | 7 +- .../utils/system-utils/SkeletonVariants.jsx | 23 +++ .../collection/PortfolioViewLayout/index.jsx | 2 +- src/layout/deck/DeckListItem.jsx | 135 +++++++------ src/layout/deck/index.jsx | 184 ++++++++++-------- src/layout/home/HeroChartSection.jsx | 10 +- src/layout/navigation/index.jsx | 1 + 23 files changed, 534 insertions(+), 263 deletions(-) create mode 100644 src/context/hooks/useDebounce.jsx diff --git a/.gitignore b/.gitignore index 4fa3ceb..6af3306 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ package-lock.json # production /build /future-additions +/dev # misc .DS_Store diff --git a/src/context/hooks/useDebounce.jsx b/src/context/hooks/useDebounce.jsx new file mode 100644 index 0000000..e79ba2b --- /dev/null +++ b/src/context/hooks/useDebounce.jsx @@ -0,0 +1,29 @@ +import { useState, useEffect } from 'react'; +/** + * useDebounce hook + * + * @param {any} value - The value to be debounced. + * @param {number} delay - The number of milliseconds to delay. + * @returns {any} - The debounced value after the specified delay. + */ +function useDebounce(value, delay) { + // State and setters for debounced value + const [debouncedValue, setDebouncedValue] = useState(value); + const [delayTime, setDelayTime] = useState(delay || 500); + + useEffect(() => { + // Update debounced value after the specified delay + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + // Cleanup function to cancel the timeout if value or delay changes + return () => { + clearTimeout(handler); + }; + }, [value, delay]); // Only re-run effect if value or delay changes + + return debouncedValue; +} + +export default useDebounce; diff --git a/src/context/hooks/useFormSubmission.jsx b/src/context/hooks/useFormSubmission.jsx index 62261f2..8997f58 100644 --- a/src/context/hooks/useFormSubmission.jsx +++ b/src/context/hooks/useFormSubmission.jsx @@ -1,5 +1,5 @@ import { useCallback, useState } from 'react'; -import { handleValidation, zodSchemas } from 'data'; +import { handleSchemaValidation, zodSchemas } from 'data'; const useFormSubmission = (formHandlers, formKey) => { const [isSubmitting, setIsSubmitting] = useState(false); @@ -9,7 +9,7 @@ const useFormSubmission = (formHandlers, formKey) => { setIsSubmitting(true); console.log('[ACTIVE FORM]', formKey); console.log('[FORM DATA]', formData); - const validationResult = handleValidation(activeSchema, formData); + const validationResult = handleSchemaValidation(activeSchema, formData); if (!validationResult.success) { console.error('[INVALID RESULT]', validationResult); setIsSubmitting(false); diff --git a/src/context/hooks/useRCFormHook.jsx b/src/context/hooks/useRCFormHook.jsx index dda478f..efed4ef 100644 --- a/src/context/hooks/useRCFormHook.jsx +++ b/src/context/hooks/useRCFormHook.jsx @@ -1,9 +1,8 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; -import { useEffect } from 'react'; -import { formFields, zodSchemas } from 'data'; +import { zodSchemas } from 'data'; -const useRCFormHook = (schemaKey, initialData) => { +const useRCFormHook = (schemaKey) => { const schema = zodSchemas[schemaKey]; const defaultValues = Object.keys(schema.shape).reduce((acc, key) => { const fieldDefinition = schema.shape[key]; @@ -19,17 +18,9 @@ const useRCFormHook = (schemaKey, initialData) => { const methods = useForm({ resolver: zodResolver(schema), - defaultValues: !initialData ? defaultValues : null, + defaultValues, }); - // useEffect(() => { - // console.log( - // // `[1] ${schemaKey} SCHEMA REGISTERED: ${schema}`, - // // `[2] FORMSTATE REGISTERED: ${JSON.stringify(methods.formState)}`, - // `[3] VALUES: ${JSON.stringify(methods.getValues())}` - // ); - // }, [methods.formState]); - return methods; }; diff --git a/src/context/hooks/useSelectorActions.jsx b/src/context/hooks/useSelectorActions.jsx index ea9b32c..f946b2a 100644 --- a/src/context/hooks/useSelectorActions.jsx +++ b/src/context/hooks/useSelectorActions.jsx @@ -11,6 +11,7 @@ function useSelectorActions() { handleSelectCollection, selectedDeck, handleSelectDeck, + fetchDeckById, } = useManager(); const [time, setTime] = useState('24hr'); const [stat, setStat] = useState('highpoint'); @@ -25,17 +26,14 @@ function useSelectorActions() { light: 'light', dark: 'dark', }; - const handleSelectChange = (e, selectorName, context) => { - console.log( - 'SELECTOR VALUES CHANGED', - e.target.value, - selectorName, - context - ); + const handleSelectChange = async (e, selectorName, context) => { + console.log('SELECTOR VALUES CHANGED', e, selectorName, context); const selectedCollectionId = localStorage.getItem('selectedCollectionId'); const selectedDeckId = localStorage.getItem('selectedDeckId'); const selected = localStorage.getItem('selected' + context); const selectedCollection = JSON.parse(selected); + const selectedDeck = JSON.parse(selected); + // setTags(selectedDeck.tags); switch (selectorName) { case 'timeRange': setTime(e.target.value); @@ -94,22 +92,34 @@ function useSelectorActions() { handleSelectCollection(selectedCollection); break; case 'tags': - const newTag = { id: nanoid(), label: e.target.value }; - const updatedTags = [...tags, newTag]; - console.log('NEW TAG', updatedTags); - const { name, description, color } = selected; - // selectedDeck.tags = updatedTags; + let updatedTags = [...selectedDeck.tags]; // Copy current tags to manipulate + const { name, description, color } = selectedDeck; + + if (e.type === 'add') { + const newTag = { id: nanoid(), label: e.target.value }; + if (!updatedTags.some((tag) => tag.label === newTag.label)) { + // Check if tag already exists by label + updatedTags.push(newTag); // Add new tag if not present + } + } else if (e.type === 'delete') { + updatedTags = updatedTags.filter( + (tag) => tag.id !== e.target.value.id + ); // Remove tag by id + } + + // Update tags in state and backend setTags(updatedTags); // Update local state - updateEntityField( + await updateEntityField( 'decks', selectedDeckId, ['tags', 'name', 'description', 'color'], [updatedTags, name, description, color] ); // Persist tags update - handleSelectDeck(selectedDeck); - - e.target.value = ''; // Clear the input after adding a tag + const updatedDeck = await fetchDeckById(selectedDeckId); + console.log('UPDATED DECK', updatedDeck); + handleSelectDeck(updatedDeck); + // e.target.value = ''; // Clear the input after adding a tag break; case 'deck': default: diff --git a/src/context/state/useAuthManager.jsx b/src/context/state/useAuthManager.jsx index 90d3afc..bab6447 100644 --- a/src/context/state/useAuthManager.jsx +++ b/src/context/state/useAuthManager.jsx @@ -24,12 +24,11 @@ function useAuthManager() { [accessToken, refreshToken, true, authData, authData.userId], { path: '/' } ); - handleSetUser(authData); // Adjust according to your implementation + handleSetUser(authData); navigate('/home'); }, - [handleSetUser, navigate] + [addCookies, handleSetUser, navigate] ); - const clearAuthCookies = useCallback(() => { deleteCookies([ 'accessToken', @@ -38,17 +37,23 @@ function useAuthManager() { 'authUser', 'isLoggedIn', ]); - localStorage.clear(); // Clear all local storage data + localStorage.clear(); navigate('/login'); - }, [navigate, deleteCookies]); - + }, [deleteCookies, navigate]); const decodeAndSetUser = useCallback( (accessToken) => { const decoded = jwt_decode(accessToken); - handleSetUser(decoded); // Adjust according to your implementation + handleSetUser(decoded); }, [handleSetUser] ); + // const decodeAndSetUser = useCallback( + // (accessToken) => { + // const decoded = jwt_decode(accessToken); + // handleSetUser(decoded); // Adjust according to your implementation + // }, + // [handleSetUser] + // ); const executeAuthAction = useCallback( async (endpoint, requestData) => { @@ -93,7 +98,6 @@ function useAuthManager() { }, [executeAuthAction] ); - const logout = useCallback(async () => { await executeAuthAction('signout', { userId: authUser.userId, @@ -101,7 +105,25 @@ function useAuthManager() { refreshToken: refreshToken, }); clearAuthCookies(); - }, []); + setLoggingOut(true); + handleRemoveUser(); + }, [ + executeAuthAction, + clearAuthCookies, + handleRemoveUser, + authUser, + accessToken, + refreshToken, + ]); + + // const logout = useCallback(async () => { + // await executeAuthAction('signout', { + // userId: authUser.userId, + // accessToken: accessToken, + // refreshToken: refreshToken, + // }); + // clearAuthCookies(); + // }, []); useEffect(() => { if (!isLoggedIn || !accessToken) return; @@ -109,6 +131,24 @@ function useAuthManager() { decodeAndSetUser(accessToken); } }, []); + // const checkTokenValidity = useCallback(() => { + // console.log('Checking token validity...', { accessToken }); + // if (!accessToken) { + // navigate('/login'); + // return; + // } + // try { + // const { exp } = jwt_decode(accessToken); + // const isTokenExpired = Date.now() >= exp * 1000; + // if (isTokenExpired) { + // logout(); + // setLoggingOut(true); + // handleRemoveUser(); + // } + // } catch (error) { + // console.error('Token validation error:', error); + // } + // }, [user.accessToken]); const checkTokenValidity = useCallback(() => { console.log('Checking token validity...', { accessToken }); if (!accessToken) { @@ -120,18 +160,25 @@ function useAuthManager() { const isTokenExpired = Date.now() >= exp * 1000; if (isTokenExpired) { logout(); - setLoggingOut(true); - handleRemoveUser(); } } catch (error) { console.error('Token validation error:', error); } - }, [user.accessToken]); + }, [accessToken, logout, navigate]); + // useEffect(() => { + // if (!isLoggedIn) return; + // checkTokenValidity(); + // }, [checkTokenValidity]); useEffect(() => { if (!isLoggedIn) return; - checkTokenValidity(); - }, [checkTokenValidity]); + decodeAndSetUser(accessToken); + const intervalId = setInterval(() => { + checkTokenValidity(); + }, 300000); // 300000 ms = 5 minutes + + return () => clearInterval(intervalId); // Clean up the interval on component unmount + }, [isLoggedIn, accessToken, checkTokenValidity, decodeAndSetUser]); return { login, logout, signup }; } diff --git a/src/context/state/useManager.jsx b/src/context/state/useManager.jsx index 357367d..b695800 100644 --- a/src/context/state/useManager.jsx +++ b/src/context/state/useManager.jsx @@ -250,8 +250,9 @@ const useManager = () => { const fetchSingleEntity = useCallback( async (entity, id) => { try { + const cleanedId = encodeURIComponent(id.replace(/"/g, '')); const response = await fetchWrapper( - createApiUrl(entity, `get/${id}`), + createApiUrl(entity, `get/${cleanedId}`), 'GET', null, `fetch${entity}`.toLocaleUpperCase() diff --git a/src/data/formsConfig.jsx b/src/data/formsConfig.jsx index 004bce4..c91c827 100644 --- a/src/data/formsConfig.jsx +++ b/src/data/formsConfig.jsx @@ -112,7 +112,7 @@ const loginFormFields = { label: 'Username', name: 'username', type: 'text', - placeHolder: 'Username', + placeholder: 'Username', helperText: 'Enter your username', defaultValue: '', rules: { @@ -128,7 +128,7 @@ const loginFormFields = { name: 'password', type: 'password', helperText: 'Enter your password', - placeHolder: 'Password', + placeholder: 'Password', defaultValue: '', rules: { required: true, @@ -145,7 +145,7 @@ const signupFormFields = { label: 'First Name', name: 'firstName', type: 'text', - placeHolder: 'first name', + placeholder: 'first name', defaultValue: '', rules: { required: true, @@ -157,7 +157,7 @@ const signupFormFields = { label: 'Last Name', name: 'lastName', type: 'text', - placeHolder: 'last name', + placeholder: 'last name', defaultValue: '', rules: { required: true, @@ -169,7 +169,7 @@ const signupFormFields = { label: 'Email', name: 'email', type: 'email', - placeHolder: 'email', + placeholder: 'email', defaultValue: '', rules: { required: true, @@ -186,7 +186,7 @@ const addDeckFormFields = { name: 'name', label: 'Name', type: 'text', - placeHolder: 'Enter deck name', + placeholder: 'Enter deck name', defaultValue: '', rules: { required: true, @@ -200,7 +200,7 @@ const addDeckFormFields = { name: 'description', label: 'Description', type: 'multiline', - placeHolder: 'Enter deck description', + placeholder: 'Enter deck description', defaultValue: '', rules: { required: true, @@ -237,6 +237,7 @@ const updateDeckFormFields = { label: 'Color', name: 'color', type: 'select', + placeholder: 'Select a color', defaultValue: 'blue', rules: { required: false, @@ -263,7 +264,7 @@ const collectionFormFields = { name: 'name', label: 'Name', type: 'text', - placeHolder: 'Enter collection name', + placeholder: 'Enter collection name', defaultValue: '', rules: { required: true, @@ -276,7 +277,7 @@ const collectionFormFields = { name: 'description', label: 'Description', type: 'multiline', - placeHolder: 'Enter collection description', + placeholder: 'Enter collection description', defaultValue: '', rules: { required: true, @@ -394,7 +395,7 @@ const authSwitchFormFields = { authSwitch: { label: 'Auth Switch', type: 'switch', - placeHolder: 'Auth Switch', + placeholder: 'Auth Switch', name: 'authSwitch', defaultValue: false, rules: { @@ -540,15 +541,45 @@ const zodSchemas = { // -------------------------- ZOD VALIDATION FUNCTIONS ------------------------- // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- -const handleValidation = (schema, formData) => { +const handleSchemaValidation = (schema, formData) => { const result = schema.safeParse(formData); if (result.success) { console.log('Validation successful', formData); return { success: true, data: formData }; - } else { - console.error('Validation errors', result.error.errors); - return { success: false, errors: result.error.errors }; } + if (result.error) { + console.log('Validation failed', result.error.errors); + return { + success: false, + errors: result.error.errors, + message: 'Validation failed', + }; + } +}; +const handleFieldValidation = (fieldRules, value) => { + const rules = fieldRules; + const [error, setError] = []; + if (rules.required && !value) { + setError('This field is required'); + return 'This field is required'; + } + if (rules.minLength && value.length < rules.minLength) { + setError(`This field must be at least ${rules.minLength} characters`); + return `This field must be at least ${rules.minLength} characters`; + } + if (rules.maxLength && value.length > rules.maxLength) { + setError(`This field must not be more than ${rules.maxLength} characters`); + return `This field must be less than ${rules.maxLength} characters`; + } + if (rules.password) { + // const passwordRegex = new RegExp( + // '^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])' + // ); + // if (!passwordRegex.test(value)) { + // return 'Password must contain at least one uppercase, lowercase, number, and special character'; + // } + } + // return console.log('Validation passed'); }; // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- @@ -609,6 +640,7 @@ export { formFields, zodSchemas, configOptions, - handleValidation, + handleSchemaValidation, + handleFieldValidation, getFormFieldHandlers, }; diff --git a/src/data/index.jsx b/src/data/index.jsx index 5d9a3ec..7e8ca5c 100644 --- a/src/data/index.jsx +++ b/src/data/index.jsx @@ -9,7 +9,7 @@ import { formFields, zodSchemas, configOptions, - handleValidation, + handleSchemaValidation, getFormFieldHandlers, } from './formsConfig'; export { @@ -25,6 +25,6 @@ export { zodSchemas, configOptions, DeckBuilderIcon, - handleValidation, + handleSchemaValidation, getFormFieldHandlers, }; diff --git a/src/layout/REUSABLE_COMPONENTS/MDBOX/index.jsx b/src/layout/REUSABLE_COMPONENTS/MDBOX/index.jsx index edbbb6a..faaaf3e 100644 --- a/src/layout/REUSABLE_COMPONENTS/MDBOX/index.jsx +++ b/src/layout/REUSABLE_COMPONENTS/MDBOX/index.jsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import MDBoxRoot from './MDBoxRoot'; +import MDBoxRoot from './MDBoxRoot.jsx'; import React from 'react'; const MDBox = React.forwardRef( diff --git a/src/layout/REUSABLE_COMPONENTS/RCLOADINGBUTTON/index.jsx b/src/layout/REUSABLE_COMPONENTS/RCLOADINGBUTTON/index.jsx index 6161dd7..0dd21f6 100644 --- a/src/layout/REUSABLE_COMPONENTS/RCLOADINGBUTTON/index.jsx +++ b/src/layout/REUSABLE_COMPONENTS/RCLOADINGBUTTON/index.jsx @@ -20,7 +20,7 @@ const ButtonContainer = ({ children, withContainer }) => ( const labelContent = (loading, icon, label) => loading ? ( - + {label} ) : ( diff --git a/src/layout/REUSABLE_COMPONENTS/RCTYPOGRAPHY/index.jsx b/src/layout/REUSABLE_COMPONENTS/RCTYPOGRAPHY/index.jsx index a8e590d..b956fd7 100644 --- a/src/layout/REUSABLE_COMPONENTS/RCTYPOGRAPHY/index.jsx +++ b/src/layout/REUSABLE_COMPONENTS/RCTYPOGRAPHY/index.jsx @@ -2,6 +2,21 @@ import PropTypes from 'prop-types'; import RCTypographyRoot from './RCTypographyRoot'; import React from 'react'; +/** + * A reusable typography component. + * + * @component + * @param {string} color - Options: primary, secondary, tertiary, error, warning, info, success, light, dark, text, white, inherit. + * @param {boolean} fontWeight - Options: false, regular, medium, bold. + * @param {string} textTransform - Options: none, capitalize, uppercase, lowercase. + * @param {string} verticalAlign - Options: unset, baseline, sub, super, text-top, text-bottom, middle, top, bottom. + * @param {boolean} textGradient - Whether to apply a text gradient to the typography. + * @param {number} opacity - Options: 0 - 1. + * @param {ReactNode} children - The content of the typography. + * @param {object} rest - Additional props to be spread on the root element. + * @param {React.Ref} ref - The ref to be forwarded to the root element. + * @returns {JSX.Element} The rendered typography component. + */ const RCTypography = React.forwardRef( ( { diff --git a/src/layout/REUSABLE_COMPONENTS/RC_FORMS/RCDynamicForm.jsx b/src/layout/REUSABLE_COMPONENTS/RC_FORMS/RCDynamicForm.jsx index 424ae3c..2f05bf1 100644 --- a/src/layout/REUSABLE_COMPONENTS/RC_FORMS/RCDynamicForm.jsx +++ b/src/layout/REUSABLE_COMPONENTS/RC_FORMS/RCDynamicForm.jsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-empty-function */ import React, { useEffect, useState } from 'react'; -import { Box, InputAdornment, Tooltip } from '@mui/material'; +import { Box, InputAdornment, LinearProgress, Tooltip } from '@mui/material'; import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'; import { Controller } from 'react-hook-form'; @@ -14,9 +14,11 @@ import { useFormSubmission, useRCFormHook, useMode, + useManager, } from 'context'; -import { getFormFieldHandlers } from 'data'; +import { getFormFieldHandlers, handleValidation } from 'data'; import { RCInput, RCLoadingButton } from '..'; +import { handleFieldValidation } from 'data/formsConfig'; const RCDynamicForm = ({ formKey, @@ -27,25 +29,35 @@ const RCDynamicForm = ({ additonalData, }) => { const { theme } = useMode(); + const { status } = useManager(); const { isMobile } = useBreakpoint(); - const methods = useRCFormHook(formKey, initialData); + // const dataRef = React.useRef(initialData || {}); + const methods = useRCFormHook(formKey); const { onSubmit } = useFormSubmission(getFormFieldHandlers(), formKey); - // State and Effects const [isMounted, setIsMounted] = useState(false); - const [formData, setFormData] = useState(initialData); - useEffect(() => { setIsMounted(true); + initialData && console.log('Mounted with initialData:', initialData); // Logging to debug initialData structure + inputs && console.log('Mounted with inputs:', inputs); // Logging to debug inputs structure + methods && console.log('Methods:', methods); // Logging to debug methods structure + methods.getValues() && console.log('Values:', methods.getValues()); // Logging to debug formValues structure return () => { setIsMounted(false); }; }, []); - useEffect(() => { - setFormData(initialData); - methods.reset(initialData); // Reset form with new initial data - }, [initialData, methods]); - + if (initialData) { + methods.reset(initialData); + } + }, []); + // useEffect(() => { + // // CHECK SUBMITTING STATUS + // console.log('SUBMITTING STATUS:', methods.formState.isSubmitting); + // }, [methods.formState.isSubmitting]); + useEffect(() => { + // CHECK VALIDATION STATUS + console.log('VALIDATION STATUS:', methods.formState.isValid); + }, [methods.formState.isValid]); const optionsForUi = userInterfaceOptions ? userInterfaceOptions : {}; if (!inputs || typeof inputs !== 'object') { @@ -80,15 +92,21 @@ const RCDynamicForm = ({ render={({ field, fieldState: { error } }) => ( { + // handleFieldValidation(field, e.target.value); + // field.onChange(e.target.value); + // }} /> )} /> @@ -124,7 +146,7 @@ const RCDynamicForm = ({ // ? optionsForUi?.updateActions?.handleSubmit // : handleSubmit(onSubmit) // } - loading={isSubmitting} + loading={isSubmitting || status === 'loading'} withContainer={false} fullWidth={true} circular={true} @@ -151,8 +173,8 @@ const RCDynamicForm = ({ )} + {/* {methods.formState.isSubmitting || + (status === 'loading' && ( + + + + ))} */} ); }; diff --git a/src/layout/REUSABLE_COMPONENTS/RC_FORMS/RCInput.jsx b/src/layout/REUSABLE_COMPONENTS/RC_FORMS/RCInput.jsx index c2c6292..e3287ab 100644 --- a/src/layout/REUSABLE_COMPONENTS/RC_FORMS/RCInput.jsx +++ b/src/layout/REUSABLE_COMPONENTS/RC_FORMS/RCInput.jsx @@ -27,22 +27,28 @@ import { useSelectorActions, } from 'context'; import { RCSwitch } from '..'; +import { zodSchemas } from 'data'; +import { handleFieldValidation } from 'data/formsConfig'; const RCInput = React.forwardRef( ( { type = 'text', options = [], - onChange = () => {}, + onChange, initialValue = '', value = '', + rules = {}, placeholder = '', + loading = false, error = false, helperText = '', label = '', name = '', context = '', - InputProps = {}, + InputProps = { + formKey: '', + }, withContainer = false, // Default value for withContainer prop ...rest }, @@ -53,21 +59,38 @@ const RCInput = React.forwardRef( const { handleSelectChange, setTags, tags } = useSelectorActions(); const { updateEntityField } = useManager(); const [inputValue, setInputValue] = useState(''); + // const activeSchema = zodSchemas[formKey]; + const handleKeyDown = (event) => { if (event.key === 'Enter' && inputValue.trim()) { event.preventDefault(); console.log(`[INPUT]: ${inputValue}`); console.log(`[EVENT]: ${event.target.value}`); console.log(`[EVENT]: ${event}`); - handleSelectChange({ target: { value: inputValue } }, 'tags', 'decks'); + handleSelectChange( + { + type: 'add', // Define event type as 'add' + target: { value: inputValue }, + }, + 'tags', + 'Deck' + ); setInputValue(''); } }; const handleDeleteTag = (tagToDelete) => () => { - const updatedTags = tags.filter((tag) => tag.id !== tagToDelete.id); - setTags(updatedTags); // Update local state - updateEntityField('decks', 'deckId', 'tags', updatedTags); // Persist tags update + console.log(`[TAG TO DELETE]: ${tagToDelete}`); + handleSelectChange( + { + type: 'delete', // Define event type as 'delete' + target: { + value: tagToDelete, + }, + }, + 'tags', + 'Deck' + ); }; const { newPalette, functions } = theme; const { @@ -131,10 +154,17 @@ const RCInput = React.forwardRef( fullWidth placeholder={placeholder} onChange={(e) => onChange(e.target.value)} - value={value || ''} + // onChange={(e) => { + // e.preventDefault(); + // console.log(`[FIELD]: ${rules}`); + // // handleFieldValidation(rules, e.target.value); + // handleInputChange(e); + // }} + value={value} InputLabelProps={{ shrink: !initialValue ? undefined : true, }} + autoComplete="off" fontSize={isMobile ? '1rem' : '1.25rem'} error={!!error} helperText={helperText} @@ -144,15 +174,18 @@ const RCInput = React.forwardRef( case 'select': return ( - {label} + + {label} +