123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- import React, { useEffect, useState } from 'react';
- import { arrayOf, bool, func, number, shape, string } from "prop-types";
- import { useTranslation } from "react-i18next";
- import ImageUpload from "../Images/ImageUpload";
- import { useAuth0, withAuthenticationRequired } from "@auth0/auth0-react";
- import { LoadingBody } from "../Loading";
- import SelectMealCategory from "./SelectMealCategory";
- import SelectMealTags from "./SelectMealTags";
- import OutlinedTextField from "../util/OutlinedTextField";
- import { fetchAndUpdateMealsFromUser } from "./meals.util";
- /** component is used by AddMeal and EditMeal and provides their shared core elements: text and photo input as well as choosing a category and adding tags.
- * Does not handle communication to server. */
- const EditMealCore = (props) => {
- const { t } = useTranslation();
- const { user } = useAuth0();
- const {
- updateMeal,
- meal: {
- _id: mealId,
- title,
- recipeLink,
- comment,
- images,
- tags,
- category,
- },
- isSecondary,
- autoFocusFirstInput,
- setImagesLoading,
- setLoadingImagesTakesLong,
- loadingImagesTakesLongAfter,
- } = props;
- const [placeholder, setPlaceholder] = useState(t('Recipe, instructions, comments, etc.'));
- const [, updateState] = useState();
- const forceUpdate = React.useCallback(() => updateState({}), []);
- const [loadingImagesTakesLongTimeout, setLoadingImagesTakesLongTimeout] = useState(0);
- const onChangeUploadedImages = (newUploadedImages) => {
- console.log('updated uploadedImages', newUploadedImages);
- updateMeal('images', newUploadedImages);
- forceUpdate(); // I don't know why the component does not rerender on state change but this solution fixes it. Source: https://stackoverflow.com/questions/53215285/how-can-i-force-component-to-re-render-with-hooks-in-react
- }
- useEffect(() => {
- if (user) {
- fetchAndUpdateMealsFromUser(user.sub, meals => {
- if (meals.length < 3) setPlaceholder(t('You can use this field to add a recipe in text form, instructions, experience or other comments.'));
- })
- }
- // eslint-disable-next-line
- }, [user]);
- const setLoadingAndStartTimeout = (value) => {
- if(setImagesLoading) setImagesLoading(value);
- if(setLoadingImagesTakesLong) {
- if (value === true) {
- setLoadingImagesTakesLongTimeout(setTimeout(() => {
- setLoadingImagesTakesLong(true);
- }, loadingImagesTakesLongAfter));
- }
- if (value === false) {
- clearTimeout(loadingImagesTakesLongTimeout);
- setLoadingImagesTakesLongTimeout(0);
- setLoadingImagesTakesLong(false);
- }
- }
- };
- return (
- <>
- <OutlinedTextField name="title"
- value={title}
- label={t('Meal Title')}
- onChange={e => updateMeal('title', e.target.value)}
- isSecondary={isSecondary}
- autoFocus={autoFocusFirstInput}
- required />
- <OutlinedTextField name="recipeLink" value={recipeLink} label={t('Link to Recipe')} onChange={e => updateMeal('recipeLink', e.target.value)} isSecondary={isSecondary} />
- <OutlinedTextField multiline
- rowsMax={10}
- rows={1}
- name="comment"
- placeholder={placeholder}
- value={comment}
- onChange={e => updateMeal('comment', e.target.value)}
- isSecondary={isSecondary} />
- <SelectMealCategory currentCategory={category} updateMeal={updateMeal} />
- <SelectMealTags own currentTags={tags} updateTags={(newTags) => {updateMeal('tags', newTags)}} allowCreate />
- <ImageUpload multiple
- uploadedImages={images}
- category="mealImages"
- categoryId={mealId}
- onChangeUploadedImages={onChangeUploadedImages}
- imageName={title}
- tags={tags}
- setLoading={setLoadingAndStartTimeout} />
- </>
- );
- }
- EditMealCore.propTypes = {
- /** setState function of the parent component's meal that takes key and value of attribute and updates it */
- updateMeal: func.isRequired,
- /** meal to be edited */
- meal: shape({
- _id: string,
- userId: string,
- title: string,
- images: arrayOf(shape({
- name: string,
- url: string,
- })),
- recipeLink: string,
- comment: string,
- category: string,
- tags: arrayOf(string),
- }).isRequired,
- /** whether to use primary or secondary color scheme */
- isSecondary: bool,
- /** whether to autofocus title input (will open keyboard on smartphones) */
- autoFocusFirstInput: bool,
- /** this is a function to update the state of the calling component. It will receive false, if all images of the meal have been uploaded, and true otherwise */
- setImagesLoading: func,
- /** this is a function to update the state of the calling component. It will receive true, if all images have not loaded after the specified interval */
- setLoadingImagesTakesLong: func,
- /** interval for setLoadingImagesTakesLong */
- loadingImagesTakesLongAfter: number,
- }
- EditMealCore.defaultProps = {
- isSecondary: false,
- autoFocusFirstInput: false,
- setImagesLoading: undefined,
- setLoadingImagesTakesLong: undefined,
- loadingImagesTakesLongAfter: 6000,
- }
- export default withAuthenticationRequired(EditMealCore, {
- onRedirecting: () => <LoadingBody />,
- });
|