extensible inputs on recipe add page
This commit is contained in:
@@ -51,7 +51,7 @@ const Friends: FC<{ targetUser?: IUser }> = ({ targetUser }) => {
|
|||||||
<>
|
<>
|
||||||
{ userList.length ?
|
{ userList.length ?
|
||||||
(
|
(
|
||||||
<Card extraStyles="flex-row">
|
<Card extraClasses="flex-row">
|
||||||
<h2>Friends ({ userList?.length ?? "0" }):</h2>
|
<h2>Friends ({ userList?.length ?? "0" }):</h2>
|
||||||
|
|
||||||
<div className="friends-list">
|
<div className="friends-list">
|
||||||
|
|||||||
47
client/src/components/derived/IngredientSelector.tsx
Normal file
47
client/src/components/derived/IngredientSelector.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { Autocomplete, TextField } from "@mui/material"
|
||||||
|
import { useRef, useState } from "react";
|
||||||
|
import { IIngredient } from "../../schemas";
|
||||||
|
import { Button } from "../ui";
|
||||||
|
|
||||||
|
interface IngredientSelectorProps {
|
||||||
|
position: number
|
||||||
|
ingredients: IIngredient[]
|
||||||
|
destroy: (position: number) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
function IngredientSelector({ position, ingredients, destroy }: IngredientSelectorProps) {
|
||||||
|
const [options, setOptions] = useState(ingredients.map(each => each.name));
|
||||||
|
const [newOptions, setNewOptions] = useState(new Array<string>());
|
||||||
|
const [selected, setSelected] = useState(new Array<string>());
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
|
<Autocomplete
|
||||||
|
autoHighlight
|
||||||
|
options={options}
|
||||||
|
className="ui-creatable-component"
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField
|
||||||
|
{...params}
|
||||||
|
variant="filled"
|
||||||
|
placeholder="Ingredient Name"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.code == 'Enter') {
|
||||||
|
const inputVal: string = e.target['value' as keyof EventTarget].toString();
|
||||||
|
console.log(inputVal)
|
||||||
|
if (inputVal.length) {
|
||||||
|
setSelected(prev => [...prev, inputVal])
|
||||||
|
setOptions((prev) => [...prev, inputVal]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* @ts-ignore */}
|
||||||
|
<Button onClick={() => destroy(position)}>Close</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IngredientSelector
|
||||||
@@ -1,34 +1,29 @@
|
|||||||
import { useCallback, useRef, useEffect, useState, createRef } from "react";
|
|
||||||
import { useAuthContext } from "../../context/AuthContext";
|
import { useAuthContext } from "../../context/AuthContext";
|
||||||
|
import { LegacyRef, MutableRefObject, useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { Button, Card, Divider, Form, Page, Panel } from "../ui"
|
import { Button, Card, Divider, Form, Page, Panel } from "../ui"
|
||||||
import { IIngredient, IRecipe } from "../../schemas";
|
import { IIngredient, IRecipe } from "../../schemas";
|
||||||
import API from "../../util/API";
|
import API from "../../util/API";
|
||||||
import Creatable from "react-select/creatable";
|
|
||||||
import { OptionType } from "../../util/types";
|
|
||||||
import { createOptionFromText, useSelectorContext } from "../../context/SelectorContext";
|
import { createOptionFromText, useSelectorContext } from "../../context/SelectorContext";
|
||||||
import { MultiValue } from "react-select";
|
import IngredientSelector from "../derived/IngredientSelector";
|
||||||
import { Autocomplete, Chip, TextField } from "@mui/material";
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
const AddRecipe = () => {
|
const AddRecipe = () => {
|
||||||
const { user, token } = useAuthContext();
|
const { user, token } = useAuthContext();
|
||||||
const {
|
const { data, setData, options, setOptions } = useSelectorContext();
|
||||||
data, setData, selector, setSelector,
|
const [ingredientFields, setIngredientFields] = useState<Array<JSX.Element>>([]);
|
||||||
options, setOptions, selected, setSelected,
|
|
||||||
onChange, onCreateOption
|
|
||||||
} = useSelectorContext();
|
|
||||||
|
|
||||||
const [triggerChange, setTriggerChange] = useState(false);
|
const [triggerChange, setTriggerChange] = useState(false);
|
||||||
const [optionCount, setOptionCount] = useState(0);
|
const [optionCount, setOptionCount] = useState(0);
|
||||||
const [form, setForm] = useState<JSX.Element>();
|
|
||||||
const [toast, setToast] = useState(<></>)
|
const [toast, setToast] = useState(<></>)
|
||||||
const [input, setInput] = useState<IRecipe>({ name: '', preptime: '', description: '', authoruserid: '' })
|
const [input, setInput] = useState<IRecipe>({ name: '', preptime: '', description: '', authoruserid: '' })
|
||||||
|
|
||||||
|
const initialIngredient = useRef(null);
|
||||||
|
|
||||||
// clear out selector state on page load
|
// clear out selector state on page load
|
||||||
useEffect(() => {
|
/* useEffect(() => {
|
||||||
setData(new Array<IIngredient>());
|
setData(new Array<IIngredient>());
|
||||||
setSelected(new Array<string>());
|
setSelected(new Array<string>());
|
||||||
setOptions(new Array<OptionType>());
|
setOptions(new Array<OptionType>());
|
||||||
}, [])
|
}, []) */
|
||||||
|
|
||||||
// store all ingredients on page mount
|
// store all ingredients on page mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -44,18 +39,14 @@ const AddRecipe = () => {
|
|||||||
return { label: each.name, value: each.id }
|
return { label: each.name, value: each.id }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setOptionCount(result.length);
|
setIngredientFields([<IngredientSelector key={v4()} position={optionCount} ingredients={result} destroy={destroySelector} />]);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, [token])
|
}, [token])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(selected);
|
|
||||||
}, [selected])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data.length) {
|
if (data.length) {
|
||||||
const autocompleteInstance = (
|
/* const autocompleteInstance = (
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
multiple
|
multiple
|
||||||
freeSolo
|
freeSolo
|
||||||
@@ -87,7 +78,7 @@ const AddRecipe = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)
|
) */
|
||||||
|
|
||||||
// create dropdown from new data
|
// create dropdown from new data
|
||||||
/*
|
/*
|
||||||
@@ -102,13 +93,13 @@ const AddRecipe = () => {
|
|||||||
/>
|
/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
data.length && setSelector(autocompleteInstance);
|
// data.length && setSelector(autocompleteInstance);
|
||||||
setTriggerChange(true);
|
setTriggerChange(true);
|
||||||
}
|
}
|
||||||
}, [data, options, selected])
|
}, [data, options])
|
||||||
|
|
||||||
// once the dropdown data has populated, mount it within the full form
|
// once the dropdown data has populated, mount it within the full form
|
||||||
useEffect(() => {
|
/* useEffect(() => {
|
||||||
triggerChange && setForm(
|
triggerChange && setForm(
|
||||||
<Form<IRecipe> _config={{
|
<Form<IRecipe> _config={{
|
||||||
parent: "AddRecipe",
|
parent: "AddRecipe",
|
||||||
@@ -118,10 +109,9 @@ const AddRecipe = () => {
|
|||||||
initialState: input,
|
initialState: input,
|
||||||
getState: getFormState,
|
getState: getFormState,
|
||||||
richTextInitialValue: "<p>Enter recipe details here!</p>",
|
richTextInitialValue: "<p>Enter recipe details here!</p>",
|
||||||
selectorInstance: selector
|
|
||||||
}} />
|
}} />
|
||||||
)
|
)
|
||||||
}, [triggerChange])
|
}, [triggerChange]) */
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(options);
|
console.log(options);
|
||||||
@@ -139,6 +129,7 @@ const AddRecipe = () => {
|
|||||||
}, [user])
|
}, [user])
|
||||||
|
|
||||||
// store input data from form
|
// store input data from form
|
||||||
|
/*
|
||||||
const getFormState = useCallback((data: IRecipe) => {
|
const getFormState = useCallback((data: IRecipe) => {
|
||||||
setInput(data);
|
setInput(data);
|
||||||
}, [input])
|
}, [input])
|
||||||
@@ -153,7 +144,11 @@ const AddRecipe = () => {
|
|||||||
setSelected((prev) => {
|
setSelected((prev) => {
|
||||||
return prev.filter(option => option !== target);
|
return prev.filter(option => option !== target);
|
||||||
})
|
})
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return;
|
||||||
|
}, [ingredientFields])
|
||||||
|
|
||||||
// submit handler
|
// submit handler
|
||||||
const handleCreate = async () => {
|
const handleCreate = async () => {
|
||||||
@@ -179,14 +174,70 @@ const AddRecipe = () => {
|
|||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const destroySelector = useCallback((position: number) => {
|
||||||
|
setIngredientFields((prev) => {
|
||||||
|
const newState = new Array<JSX.Element>();
|
||||||
|
|
||||||
|
for (let i = 0; i < prev.length; i++) {
|
||||||
|
if (i === position) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
newState.push(prev[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
})
|
||||||
|
}, [ingredientFields]);
|
||||||
|
|
||||||
|
function handleNewOption() {
|
||||||
|
setIngredientFields((prev) => [...prev, <IngredientSelector position={optionCount + 1} key={v4()} ingredients={data} destroy={destroySelector} />])
|
||||||
|
setOptionCount(prev => prev + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(optionCount);
|
||||||
|
}, [optionCount])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<h1>Add a New Recipe</h1>
|
<h1>Add a New Recipe</h1>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<Panel extraStyles="width-80">
|
<Panel id="create-recipe-panel" extraClasses="ui-form-component width-80">
|
||||||
{ form }
|
<div className="form-row">
|
||||||
|
<label>Recipe Name:</label>
|
||||||
|
<input />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-row">
|
||||||
|
<label>Prep Time:</label>
|
||||||
|
<input />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-row">
|
||||||
|
<label>Course:</label>
|
||||||
|
<input />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{ data && (
|
||||||
|
<Card extraClasses="form-row flex-row ingredient-card">
|
||||||
|
<label>Ingredients:</label>
|
||||||
|
<div id="ingredient-container">
|
||||||
|
{ ingredientFields }
|
||||||
|
<Button onClick={handleNewOption}>Add Ingredient</Button>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<div className="form-row">
|
||||||
|
<label>Description:</label>
|
||||||
|
{ "description here" }
|
||||||
|
</div>
|
||||||
|
|
||||||
<Button onClick={handleCreate}>Create Recipe!</Button>
|
<Button onClick={handleCreate}>Create Recipe!</Button>
|
||||||
|
|
||||||
<div id="toast">{ toast }</div>
|
<div id="toast">{ toast }</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { AuthContext, useAuthContext } from "../../context/AuthContext";
|
|||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { IUser, IUserAuth } from "../../schemas";
|
import { IUser, IUserAuth } from "../../schemas";
|
||||||
import { Button, Form, Page, Panel } from "../ui";
|
import { Button, Form, Page, Panel } from "../ui";
|
||||||
import { FormConfig } from "../ui/Form";
|
import { FormConfig } from "../ui/Form/Form";
|
||||||
import API from "../../util/API";
|
import API from "../../util/API";
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
@@ -41,7 +41,7 @@ export default function Login() {
|
|||||||
<Page>
|
<Page>
|
||||||
<h1>Hello! Nice to see you again.</h1>
|
<h1>Hello! Nice to see you again.</h1>
|
||||||
|
|
||||||
<Panel extraStyles="form-panel">
|
<Panel extraClasses="form-panel">
|
||||||
|
|
||||||
<Form<IUserAuth> _config={{
|
<Form<IUserAuth> _config={{
|
||||||
parent: 'login',
|
parent: 'login',
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { IUser } from "../../../schemas";
|
|||||||
import API from "../../../util/API";
|
import API from "../../../util/API";
|
||||||
import { Button, Page, Panel } from "../../ui";
|
import { Button, Page, Panel } from "../../ui";
|
||||||
import Divider from "../../ui/Divider";
|
import Divider from "../../ui/Divider";
|
||||||
import Form from "../../ui/Form";
|
import Form from "../../ui/Form/Form";
|
||||||
|
|
||||||
const blankUser: IUser = {
|
const blankUser: IUser = {
|
||||||
firstname: '',
|
firstname: '',
|
||||||
@@ -52,7 +52,7 @@ const AboutYou: RegisterVariantType = ({ transitionDisplay }) => {
|
|||||||
|
|
||||||
<h2>Tell us a bit about yourself:</h2>
|
<h2>Tell us a bit about yourself:</h2>
|
||||||
|
|
||||||
<Panel extraStyles="form-panel two-columns">
|
<Panel extraClasses="form-panel two-columns">
|
||||||
|
|
||||||
<Form<IUser> _config={{
|
<Form<IUser> _config={{
|
||||||
parent: "register",
|
parent: "register",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const Welcome = () => {
|
|||||||
const { user } = useAuthContext();
|
const { user } = useAuthContext();
|
||||||
|
|
||||||
const authUserActions = (
|
const authUserActions = (
|
||||||
<Panel extraStyles="inherit-background c-papyrus uppercase flexrow">
|
<Panel extraClasses="inherit-background c-papyrus uppercase flexrow">
|
||||||
<Button onClick={() => navigate('/explore')}>Browse Recipes</Button>
|
<Button onClick={() => navigate('/explore')}>Browse Recipes</Button>
|
||||||
<Button onClick={() => navigate('/subscriptions')}>Subscriptions</Button>
|
<Button onClick={() => navigate('/subscriptions')}>Subscriptions</Button>
|
||||||
<Button onClick={() => navigate('/grocery-list')}>Grocery Lists</Button>
|
<Button onClick={() => navigate('/grocery-list')}>Grocery Lists</Button>
|
||||||
@@ -16,27 +16,27 @@ const Welcome = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const callToRegister = (
|
const callToRegister = (
|
||||||
<Panel extraStyles="inherit-background c-papyrus uppercase">
|
<Panel extraClasses="inherit-background c-papyrus uppercase">
|
||||||
<h2>Ready to get started?</h2>
|
<h2>Ready to get started?</h2>
|
||||||
<Button onClick={() => navigate('/register')}>Register</Button>
|
<Button onClick={() => navigate('/register')}>Register</Button>
|
||||||
</Panel>
|
</Panel>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page extraStyles="narrow-dividers">
|
<Page extraClasses="narrow-dividers">
|
||||||
<Panel extraStyles='inherit-background c-papyrus uppercase'>
|
<Panel extraClasses='inherit-background c-papyrus uppercase'>
|
||||||
<h1>Welcome to Recipin</h1>
|
<h1>Welcome to Recipin</h1>
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<Panel extraStyles="inherit-background c-papyrus uppercase">
|
<Panel extraClasses="inherit-background c-papyrus uppercase">
|
||||||
<h2>Simple Recipe Management and Sharing for the Home</h2>
|
<h2>Simple Recipe Management and Sharing for the Home</h2>
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<Panel extraStyles="inherit-background c-papyrus uppercase">
|
<Panel extraClasses="inherit-background c-papyrus uppercase">
|
||||||
<h2>Build Shopping Lists Directly from Your Recipes</h2>
|
<h2>Build Shopping Lists Directly from Your Recipes</h2>
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FC, useEffect, useState } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
import Protect from "../../util/Protect";
|
import Protect from "../../util/Protect";
|
||||||
import Form from "./Form";
|
import Form from "./Form/Form";
|
||||||
|
|
||||||
interface BrowserProps {
|
interface BrowserProps {
|
||||||
children?: JSX.Element[]
|
children?: JSX.Element[]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { ButtonComponent } from "../../util/types"
|
import { ButtonComponent } from "../../util/types"
|
||||||
import "/src/sass/components/Button.scss";
|
import "/src/sass/components/Button.scss";
|
||||||
|
|
||||||
const Button: ButtonComponent = ({ onClick = (() => {}), children, extraStyles, disabled = false, disabledText = null }) => {
|
const Button: ButtonComponent = ({ onClick = (() => {}), children, extraClasses, disabled = false, disabledText = null }) => {
|
||||||
return (
|
return (
|
||||||
<button onClick={onClick} disabled={disabled} className={`ui-button ${extraStyles || ''}`}>
|
<button onClick={onClick} disabled={disabled} className={`ui-button ${extraClasses || ''}`}>
|
||||||
{ disabled ? (disabledText || children || "Button") : (children || "Button") }
|
{ disabled ? (disabledText || children || "Button") : (children || "Button") }
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
|
|
||||||
|
|
||||||
const Card: FC<{ children?: JSX.Element | JSX.Element[], extraStyles?: string }> = ({ children = <></>, extraStyles = ""}) => {
|
const Card: FC<{ children?: JSX.Element | JSX.Element[], extraClasses?: string }> = ({ children = <></>, extraClasses = ""}) => {
|
||||||
return (
|
return (
|
||||||
<div className={`ui-card ${extraStyles}`}>
|
<div className={`ui-card ${extraClasses}`}>
|
||||||
{ Array.isArray(children) ? <>{children}</> : children }
|
{ Array.isArray(children) ? <>{children}</> : children }
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { PortalBase } from "../../util/types";
|
|||||||
import "/src/sass/components/Dropdown.scss";
|
import "/src/sass/components/Dropdown.scss";
|
||||||
|
|
||||||
// expects to receive buttons as children
|
// expects to receive buttons as children
|
||||||
const Dropdown: FC<PortalBase> = ({ children, extraStyles = null }) => {
|
const Dropdown: FC<PortalBase> = ({ children, extraClasses = null }) => {
|
||||||
return (
|
return (
|
||||||
<Panel extraStyles={`ui-dropdown ${extraStyles}`}>
|
<Panel extraClasses={`ui-dropdown ${extraClasses}`}>
|
||||||
{ children }
|
{ children }
|
||||||
</Panel>
|
</Panel>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { ChangeEvent, FC, useEffect, useState } from "react"
|
import { ChangeEvent, FC, useEffect, useState } from "react"
|
||||||
import { v4 } from "uuid"
|
import { v4 } from "uuid"
|
||||||
import { useAuthContext } from "../../context/AuthContext";
|
import { useAuthContext } from "../../../context/AuthContext";
|
||||||
import { useSelectorContext } from "../../context/SelectorContext";
|
import { useSelectorContext } from "../../../context/SelectorContext";
|
||||||
import SelectorProvider from "../../context/SelectorProvider";
|
import SelectorProvider from "../../../context/SelectorProvider";
|
||||||
import { IIngredient, IUser } from "../../schemas";
|
import { IIngredient, IUser } from "../../../schemas";
|
||||||
import API from "../../util/API";
|
import API from "../../../util/API";
|
||||||
import RichText from "./RichText"
|
import RichText from "../RichText"
|
||||||
import Selector from "./Selector";
|
import Selector from "../Selector";
|
||||||
import "/src/sass/components/Form.scss";
|
import "/src/sass/components/Form.scss";
|
||||||
|
|
||||||
export interface FormConfig<T> {
|
export interface FormConfig<T> {
|
||||||
@@ -17,7 +17,7 @@ export interface FormConfig<T> {
|
|||||||
labels?: string[]
|
labels?: string[]
|
||||||
dataTypes?: string[]
|
dataTypes?: string[]
|
||||||
richTextInitialValue?: string
|
richTextInitialValue?: string
|
||||||
extraStyles?: string
|
extraClasses?: string
|
||||||
selectorInstance?: JSX.Element
|
selectorInstance?: JSX.Element
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ function Form<T>({ _config }: FormProps) {
|
|||||||
}, [config]);
|
}, [config]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`ui-form-component ${_config.extraStyles ?? ""}`}>
|
<div className={`ui-form-component ${_config.extraClasses ?? ""}`}>
|
||||||
{ contents }
|
{ contents }
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
38
client/src/components/ui/Form/FormRow.tsx
Normal file
38
client/src/components/ui/Form/FormRow.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
|
interface FormRowConfig {
|
||||||
|
parent: any
|
||||||
|
labelText: string
|
||||||
|
idx?: number
|
||||||
|
dataType?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function FormRow({ parent, labelText, idx, dataType = "string" }) {
|
||||||
|
const [row, setRow] = useState<JSX.Element>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
switch (dataType) {
|
||||||
|
case "TINYMCE":
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
default:
|
||||||
|
setRow(
|
||||||
|
<div className="form-row" id={`${parent}-row-${idx || v4()}`} key={v4()}>
|
||||||
|
<label htmlFor={`${parent}-${each}`}>{labelText}</label>
|
||||||
|
<input
|
||||||
|
type={dataType}
|
||||||
|
id={`${parent}-${each}`}
|
||||||
|
onChange={(e) => update(e, idx)}
|
||||||
|
value={state[i as keyof T] as string}>
|
||||||
|
</input>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<></>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -53,7 +53,7 @@ const LoggedIn = () => {
|
|||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
dropdownActive && (
|
dropdownActive && (
|
||||||
<Dropdown extraStyles="top-menu-bar actions-bar">
|
<Dropdown extraClasses="top-menu-bar actions-bar">
|
||||||
<Button onClick={() => handleOptionSelect('/add-recipe')}>Add a Recipe</Button>
|
<Button onClick={() => handleOptionSelect('/add-recipe')}>Add a Recipe</Button>
|
||||||
<Button onClick={() => handleOptionSelect("/add-friends")}>Add Friends</Button>
|
<Button onClick={() => handleOptionSelect("/add-friends")}>Add Friends</Button>
|
||||||
<Button onClick={() => handleOptionSelect('/collections')}>My Collections</Button>
|
<Button onClick={() => handleOptionSelect('/collections')}>My Collections</Button>
|
||||||
@@ -65,7 +65,7 @@ const LoggedIn = () => {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
searchActive && (
|
searchActive && (
|
||||||
<Dropdown extraStyles="top-menu-bar search-bar">
|
<Dropdown extraClasses="top-menu-bar search-bar">
|
||||||
<Button>Run Search</Button>
|
<Button>Run Search</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { PageComponent } from "../../util/types"
|
|||||||
import Navbar from "./Navbar";
|
import Navbar from "./Navbar";
|
||||||
import "/src/sass/components/Page.scss";
|
import "/src/sass/components/Page.scss";
|
||||||
|
|
||||||
const Page: PageComponent = ({ extraStyles, children }) => {
|
const Page: PageComponent = ({ extraClasses, children }) => {
|
||||||
return (
|
return (
|
||||||
<main id="view">
|
<main id="view">
|
||||||
<section className={`Page ${extraStyles || null}`}>
|
<section className={`Page ${extraClasses || null}`}>
|
||||||
{ children || null }
|
{ children || null }
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
import { PanelComponent } from "../../util/types";
|
import { PanelComponent } from "../../util/types";
|
||||||
import "/src/sass/components/Panel.scss";
|
import "/src/sass/components/Panel.scss";
|
||||||
|
|
||||||
const Panel: PanelComponent = ({ children, extraStyles }) => {
|
const Panel: PanelComponent = ({ children, extraClasses, id }) => {
|
||||||
return (
|
if (id) {
|
||||||
<div className={`Panel ${extraStyles || ''}`}>
|
return (
|
||||||
{ children || null }
|
<div id={id} className={`Panel ${extraClasses || ''}`}>
|
||||||
</div>
|
{ children || null }
|
||||||
)
|
</div>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div className={`Panel ${extraClasses || ''}`}>
|
||||||
|
{ children || null }
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Panel;
|
export default Panel;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FormConfig } from "./Form"
|
import { FormConfig } from "./Form/Form"
|
||||||
|
|
||||||
interface OptionType {
|
interface OptionType {
|
||||||
value: number
|
value: number
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { PortalBase } from "../../util/types";
|
import { PortalBase } from "../../util/types";
|
||||||
|
|
||||||
const Tooltip: FC<PortalBase> = ({ children, extraStyles = null }) => {
|
const Tooltip: FC<PortalBase> = ({ children, extraClasses = null }) => {
|
||||||
return (
|
return (
|
||||||
<aside className={`ui-tooltip ${extraStyles}`}>
|
<aside className={`ui-tooltip ${extraClasses}`}>
|
||||||
{ children }
|
{ children }
|
||||||
</aside>
|
</aside>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import API from "../../util/API";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
import Card from "./Card";
|
import Card from "./Card";
|
||||||
|
|
||||||
const UserCard: UserCardType = ({ extraStyles, targetUser }) => {
|
const UserCard: UserCardType = ({ extraClasses, targetUser }) => {
|
||||||
const [buttonVariant, setButtonVariant] = useState(<></>);
|
const [buttonVariant, setButtonVariant] = useState(<></>);
|
||||||
const { token } = useAuthContext();
|
const { token } = useAuthContext();
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ const UserCard: UserCardType = ({ extraStyles, targetUser }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card extraStyles={'user-card' + extraStyles}>
|
<Card extraClasses={'user-card' + extraClasses}>
|
||||||
<>
|
<>
|
||||||
<div className="avatar"></div>
|
<div className="avatar"></div>
|
||||||
<h3><a href={`/profile?id=${targetUser.id}`}>{targetUser.firstname} {targetUser.lastname.substring(0,1)}.</a></h3>
|
<h3><a href={`/profile?id=${targetUser.id}`}>{targetUser.firstname} {targetUser.lastname.substring(0,1)}.</a></h3>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Button from "./Button";
|
|||||||
import Card from "./Card";
|
import Card from "./Card";
|
||||||
import Divider from "./Divider";
|
import Divider from "./Divider";
|
||||||
import Dropdown from "./Dropdown";
|
import Dropdown from "./Dropdown";
|
||||||
import Form from "./Form";
|
import Form from "./Form/Form";
|
||||||
import Navbar from "./Navbar";
|
import Navbar from "./Navbar";
|
||||||
import Page from "./Page";
|
import Page from "./Page";
|
||||||
import Panel from "./Panel";
|
import Panel from "./Panel";
|
||||||
|
|||||||
@@ -7,7 +7,3 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: $richblack;
|
background-color: $richblack;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-creatable-component {
|
|
||||||
margin-bottom: 10rem;
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,8 @@ import { IUser } from "../schemas";
|
|||||||
|
|
||||||
export interface PortalBase {
|
export interface PortalBase {
|
||||||
children?: ReactNode | ReactNode[]
|
children?: ReactNode | ReactNode[]
|
||||||
extraStyles?: string
|
extraClasses?: string
|
||||||
|
id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ButtonParams extends PortalBase {
|
interface ButtonParams extends PortalBase {
|
||||||
|
|||||||
Reference in New Issue
Block a user