I am trying to follow and create the right order in my if statement for my error, isloading and template values.
I recieve errors through: const [error, doRetry] = useTemplates();
isLoading through: const isLoading = !templates;
and my templates through a prop "templates" which are mapped here:
{templates.map((item) => (
<TemplateCard
id={item._id}
title={item.text}
description={item.description}
img={item.imgURL}
classNameToAdd={styles.cardContainer}
key={item.order}
onSelectCard={onSelected}
onDeselectCard={onDeselected}
/>
))}
I return my values here:
return (
<div style={sideScrollContainer}>
<SideScrollContainer>{test}</SideScrollContainer>
</div>
What would be the correct way of organizing my if statement in order to:
- If I recieve an error show the error
- If no templates are shown yet show the loader.
- If there are no errors and templates are not loading show the templates.
I did it this way but it is not working, can someone enlighten me please?
let test;
if (error) {
actionButtonClassName = `${styles.actionActive}`;
test = (
<div style={loader}>
<span style={pStyle}>
<Trans>errorProduced</Trans>
</span>
<MenuButton
style={actionButton}
className={`${styles.actionActive}`}
onClick={doRetry}
classNameOnPressed={styles.onPressed}
>
<Trans>Retry</Trans>
</MenuButton>
</div>
);
} else if (isLoading) {
test = (
<div style={loader}>
<i className="fa fa-circle-o-notch fa-spin fa-2x fa-fw"></i>
</div>
);
} else if (templates) {
test = (
<div style={templateCards}>
{templates.map((item) => (
<TemplateCard
id={item._id}
title={item.text}
description={item.description}
img={item.imgURL}
classNameToAdd={styles.cardContainer}
key={item.order}
onSelectCard={onSelected}
onDeselectCard={onDeselected}
/>
))}
</div>
);
}
This is my useTemplates file.
const useTemplates = () => {
const [result, setResult] = useState<[TemplateWithId[]?, Error?, Function?]>([]);
// used to retringer the useEffect
const [forceRerenderFlag, getForceRerenderFlag] = useState(true);
const doRetry = () => {
// changes the value so that useEffect retriggers
getForceRerenderFlag(!forceRerenderFlag);
};
useEffect(() => {
Meteor.call(
GET_PUBLIC_TEMPLATES,
i18n.locale,
(error?: Error, result?: TemplateWithId[]) => {
// returns the results sorted by template.order field
if (result)
result.sort((templateA, templateB) => templateA.order - templateB.order);
setResult([result, error, doRetry]);
},
);
}, [forceRerenderFlag]);
return result;
};
export default useTemplates;
Whole template file.
import React, { useState } from "react";
import TemplateCard from "/imports/cuadds/client/components/modals/templates/TemplateCard";
import MenuButton from "/imports/cuadds/client/components/common/menubutton/MenuButton";
import useWindowResponsiveValues from "/imports/cuadds/client/components/common/hooks/useWindowResponsiveValues";
import {
DESKTOP_NARROW,
TABLET,
PHONE_WIDE,
PHONE,
} from "/imports/cuadds/client/components/pages/onboarding/AspectRatios";
import SideScrollContainer from "/imports/cuadds/client/components/common/scrollContainer/SideScrollContainer";
import { t, Trans } from "@lingui/macro";
import useTemplates from "./useTemplates";
import { ROOT_ITEM_ACCESSED } from "/imports/cuadds/constants/onboardingLevels";
import styles from "./styles/templatepage.m.css";
type Props = {
trainingLevel: number | undefined;
templates?: TemplateWithId[];
onOnboardingComplete: Function;
};
const MIN_NUM_OF_OPTIONS = 3;
const TemplateList = ({ trainingLevel, templates, onOnboardingComplete }: Props) => {
const { aspectRatio, vmin } = useWindowResponsiveValues();
const [error, doRetry] = useTemplates();
let [selectedTemplatesIds, setSelectedTemplatesIds] = useState<string[]>([]);
const isLoading = !templates;
const onSelected = (id: string) => {
const index = selectedTemplatesIds.indexOf(id);
if (index === -1) {
selectedTemplatesIds = [...selectedTemplatesIds, id];
setSelectedTemplatesIds(selectedTemplatesIds);
}
};
const onDeselected = (id: string) => {
const index = selectedTemplatesIds.indexOf(id);
if (index !== -1) {
selectedTemplatesIds = selectedTemplatesIds.slice();
selectedTemplatesIds.splice(index, 1);
setSelectedTemplatesIds(selectedTemplatesIds);
}
};
const actionButton = {
fontSize: 2.8 * vmin,
height: 6 * vmin,
paddingBottom: 0.4 * vmin,
width: 45 * vmin,
borderRadius: 1 * vmin,
fontWeight: 600,
};
const pStyle = {
fontSize: 2.8 * vmin,
color: "#3b3b3b",
};
const sideScrollContainer = {
width: "100vw",
marginTop: 2 * vmin,
marginBottom: 3.2 * vmin,
};
const templateCards: React.CSSProperties = {
whiteSpace: "nowrap",
paddingTop: 0.5 * vmin,
paddingBottom: 4 * vmin,
marginTop: 2 * vmin,
marginBottom: -1 * vmin,
display: "inline-flex",
};
const loader: React.CSSProperties = {
color: "#C5C5C5",
fontSize: 22,
height: 28.5 * vmin,
padding: 1.5 * vmin,
margin: "11px 0",
};
if (aspectRatio < DESKTOP_NARROW && aspectRatio >= TABLET) {
actionButton.fontSize = 2.9 * vmin;
actionButton.paddingBottom = 0.3 * vmin;
loader.height = 31 * vmin;
} else if (aspectRatio < TABLET && aspectRatio >= PHONE_WIDE) {
actionButton.fontSize = 3.7 * vmin;
actionButton.width = 60 * vmin;
actionButton.height = 7.5 * vmin;
actionButton.paddingBottom = 0.3 * vmin;
loader.height = 40 * vmin;
} else if (aspectRatio < PHONE_WIDE && aspectRatio >= PHONE) {
actionButton.fontSize = 4.1 * vmin;
actionButton.width = 68 * vmin;
actionButton.height = 9 * vmin;
actionButton.paddingBottom = 0.4 * vmin;
templateCards.marginBottom = 1 * vmin;
loader.height = 46 * vmin;
loader.padding = 1.6 * vmin;
} else if (aspectRatio < PHONE) {
actionButton.fontSize = 4.8 * vmin;
actionButton.width = 78 * vmin;
actionButton.height = 11 * vmin;
actionButton.paddingBottom = 0.5 * vmin;
templateCards.marginBottom = 1.7 * vmin;
loader.height = 59.2 * vmin;
loader.padding = 2.2 * vmin;
}
const numOfTemplates = templates ? templates.length : 0;
// makes sure we have enough templates to be over the minimum, otherise the user get's stuck
const minNumOfOptions =
numOfTemplates < MIN_NUM_OF_OPTIONS ? numOfTemplates : MIN_NUM_OF_OPTIONS;
const firstTimeOnOnboarding =
trainingLevel !== undefined ? trainingLevel < ROOT_ITEM_ACCESSED : true;
let buttonText;
if (firstTimeOnOnboarding) {
if (selectedTemplatesIds.length < minNumOfOptions) {
buttonText =
t`SelectMore` + " (" + (minNumOfOptions - selectedTemplatesIds.length) + ")";
} else {
buttonText =
t`SelectDone` +
" " +
// don't show the number if there's only one, otherwise it says "...your 1 cuadds!"
(selectedTemplatesIds.length > 1 ? selectedTemplatesIds.length + " " : "") +
"cuadds!";
}
} else {
// if the user is re-watching the onboarding, don't force them to select templates
buttonText = t`AlreadyDone`;
}
let actionButtonClassName;
/**
* if it's loading or on their first time onboarding the user didn't select enough templates.
* If it's not the first time onboarding, the user is re-watching it, so we don't want to force
* them to select templates, they should be able to continue directly.
*/
if (isLoading || (firstTimeOnOnboarding && selectedTemplatesIds.length < minNumOfOptions)) {
// shows the button in gray and inactive
actionButtonClassName = `${styles.actionInactive}`;
} else {
// shows the button in blue and active
actionButtonClassName = `${styles.actionActive}`;
}
let test;
if (!error) {
console.log("error");
actionButtonClassName = `${styles.actionActive}`;
test = (
<div style={loader}>
<span style={pStyle}>
<Trans>errorProduced</Trans>
</span>
<MenuButton
style={actionButton}
className={`${styles.actionActive}`}
onClick={doRetry}
classNameOnPressed={styles.onPressed}
>
<Trans>Retry</Trans>
</MenuButton>
</div>
);
} else if (isLoading) {
console.log("loading");
test = (
<div style={loader}>
<i className="fa fa-circle-o-notch fa-spin fa-2x fa-fw"></i>
</div>
);
} else {
test = (
<div style={templateCards}>
{templates.map((item) => (
<TemplateCard
id={item._id}
title={item.text}
description={item.description}
img={item.imgURL}
classNameToAdd={styles.cardContainer}
key={item.order}
onSelectCard={onSelected}
onDeselectCard={onDeselected}
/>
))}
</div>
);
}
const onActionButtonClick = () => {
onOnboardingComplete(selectedTemplatesIds);
};
return (
<>
<div style={sideScrollContainer}>
<SideScrollContainer>{test}</SideScrollContainer>
</div>
<MenuButton
onClick={onActionButtonClick}
style={actionButton}
className={actionButtonClassName}
classNameOnPressed={styles.onPressed}
>
{buttonText}
</MenuButton>
</>
);
};
export default TemplateList;
Aucun commentaire:
Enregistrer un commentaire