Add quiz behind #12

Merged
anthony.richard merged 1 commits from Quiz_Behind into Common_Quizz 4 months ago

@ -1,57 +1,107 @@
import BackButton from "@/components/BackButton"; import BackButton from "@/components/BackButton";
import { toBgColor, toTextColor } from "@/components/Constants"; import { toBgColor, toTextColor } from "@/components/Constants";
import WeightQuestion, {
WeightQuestionRef,
} from "@/components/quiz/WeightQuestion";
import React, { useRef, useState } from "react";
import { View } from "react-native";
import Button from "@/components/ui/Button"; import Button from "@/components/ui/Button";
import Screen from "@/components/ui/Screen"; import Screen from "@/components/ui/Screen";
import Text from "@/components/ui/Text"; import Text from "@/components/ui/Text";
import React from "react"; import FrequencyQuestion, {
import { View } from "react-native"; FrequencyQuestionRef,
import FrequencyQuestion from "@/components/quiz/FrequencyQuestion"; } from "@/components/quiz/FrequencyQuestion";
import GoalQuestion from "@/components/quiz/GoalQuestion"; import GoalQuestion, { GoalQuestionRef } from "@/components/quiz/GoalQuestion";
import GenderQuestion from "@/components/quiz/GenderQuestion"; import GenderQuestion, {
import WeightQuestion from "@/components/quiz/WeightQuestion"; GenderQuestionRef,
import HeightQuestion from "@/components/quiz/HeightQuestion"; } from "@/components/quiz/GenderQuestion";
import AgeQuestion from "@/components/quiz/AgeQuestion"; import HeightQuestion, {
import BeginnerQuestion from "@/components/quiz/BeginnerQuestion"; HeightQuestionRef,
import LvlQuestion from "@/components/quiz/LvlQuestion"; } from "@/components/quiz/HeightQuestion";
import SleepQuestion from "@/components/quiz/SleepQuestion"; import AgeQuestion, { AgeQuestionRef } from "@/components/quiz/AgeQuestion";
import SportQuestion from "@/components/quiz/SportQuestion"; import BeginnerQuestion, {
BeginnerQuestionRef,
} from "@/components/quiz/BeginnerQuestion";
import ActivityQuestion, {
ActivityQuestionRef,
} from "@/components/quiz/ActivityQuestion";
import SportQuestion, {
SportQuestionRef,
} from "@/components/quiz/SportQuestion";
import SleepQuestion, {
SleepQuestionRef,
} from "@/components/quiz/SleepQuestion";
export default function Quiz() { export default function Quiz() {
const [currentQuestionIndex, setCurrentQuestionIndex] = React.useState(0); const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const goalRef = useRef<GoalQuestionRef>(null);
const genderRef = useRef<GenderQuestionRef>(null);
const weightRef = useRef<WeightQuestionRef>(null);
const heightRef = useRef<HeightQuestionRef>(null);
const ageRef = useRef<AgeQuestionRef>(null);
const beginnerRef = useRef<BeginnerQuestionRef>(null);
const activityRef = useRef<ActivityQuestionRef>(null);
const frequencyRef = useRef<FrequencyQuestionRef>(null);
const sportQuestionRef = useRef<SportQuestionRef>(null);
const sleepQuestionRef = useRef<SleepQuestionRef>(null);
interface Question<T = any> { interface Question<T = any> {
component: React.ForwardRefExoticComponent<T & React.RefAttributes<any>>; component: React.ForwardRefExoticComponent<T & React.RefAttributes<any>>;
props: T; props: T;
} }
const questions: Question[] = [ const questions: Question[] = [
{ component: GoalQuestion, props: {} }, { component: GoalQuestion, props: { ref: goalRef } },
{ component: GenderQuestion, props: {} }, { component: GenderQuestion, props: { ref: genderRef } },
{ component: WeightQuestion, props: {} }, {
{ component: HeightQuestion, props: {} }, component: WeightQuestion,
{ component: AgeQuestion, props: {} }, props: { ref: weightRef },
{ component: BeginnerQuestion, props: {} }, },
{ component: LvlQuestion, props: {} }, { component: HeightQuestion, props: { ref: heightRef } },
{ component: FrequencyQuestion, props: { isMale: true } }, { component: AgeQuestion, props: { ref: ageRef } },
{ component: SportQuestion, props: {} }, { component: BeginnerQuestion, props: { ref: beginnerRef } },
{ component: SleepQuestion, props: {} }, { component: ActivityQuestion, props: { ref: activityRef } },
//{ component: IllnessQuestion, props: {} },
{
component: FrequencyQuestion,
props: { ref: frequencyRef, isMale: genderRef.current?.getAnswer() },
},
{ component: SportQuestion, props: { ref: sportQuestionRef } },
{ component: SleepQuestion, props: { ref: sleepQuestionRef } },
]; ];
const goBack = () => {
if (currentQuestionIndex >= 1) {
setCurrentQuestionIndex(currentQuestionIndex - 1);
}
};
const goNext = () => { const goNext = () => {
if (currentQuestionIndex < questions.length - 1) { if (currentQuestionIndex < questions.length - 1) {
setCurrentQuestionIndex(currentQuestionIndex + 1); setCurrentQuestionIndex(currentQuestionIndex + 1);
} else {
collect();
} }
}; };
const collect = () => {
console.log("Goal:", goalRef.current?.getAnswer());
console.log("Sexe:", genderRef.current?.getAnswer());
console.log("Weight:", weightRef.current?.getAnswer());
console.log("Height:", heightRef.current?.getAnswer());
console.log("Age:", ageRef.current?.getAnswer());
console.log("Beginner:", beginnerRef.current?.getAnswer());
console.log("Activity:", activityRef.current?.getAnswer());
console.log("Frequency:", frequencyRef.current?.getAnswer());
console.log("Sport:", sportQuestionRef.current?.getAnswer());
console.log("Sleep:", sleepQuestionRef.current?.getAnswer());
};
return ( return (
<Screen> <Screen>
<View className="gap-4 justify-between h-full"> <View className="gap-4 justify-between h-full">
<View className="flex-row justify-between items-center"> <View className="flex-row justify-between items-center gap-4">
<BackButton onPress={goBack} /> <BackButton
className="mt-2"
onPress={() => setCurrentQuestionIndex((i) => Math.max(i - 1, 0))}
/>
<Text size="2xl" weight="bold">
Questionnaire
</Text>
<View className={"px-4 py-2 rounded-2xl" + " " + toBgColor("blue")}> <View className={"px-4 py-2 rounded-2xl" + " " + toBgColor("blue")}>
<Text className={toTextColor("blue")} weight="bold"> <Text className={toTextColor("blue")} weight="bold">
{currentQuestionIndex + 1} sur {questions.length} {currentQuestionIndex + 1} sur {questions.length}
@ -66,7 +116,9 @@ export default function Quiz() {
}) })
)} )}
<Button afterIcon="arrowright" onPress={goNext}> <Button afterIcon="arrowright" onPress={goNext}>
Suivant {currentQuestionIndex == questions.length - 1
? "Terminer"
: "Suivant"}
</Button> </Button>
</View> </View>
</Screen> </Screen>

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

@ -1,26 +1,26 @@
import { router } from "expo-router"; import { router } from "expo-router";
import Button from "./ui/Button"; import Button from "./ui/Button";
import { TouchableOpacityProps } from "react-native"; import { ButtonProps } from "./ui/Button";
import { AntDesign } from "@expo/vector-icons"; import { AntDesign } from "@expo/vector-icons";
import React from "react"; import React from "react";
import { AntDesignIconNames } from "./Icons"; import { AntDesignIconNames } from "./Icons";
interface Props extends TouchableOpacityProps { interface Props extends ButtonProps {
icon?: AntDesignIconNames; icon?: AntDesignIconNames;
} }
export default React.forwardRef<any, Props>( export default React.forwardRef<any, Props>(
(props, ref): React.ReactElement => { ({ icon, onPress, className, ...props }, ref): React.ReactElement => {
const { icon, onPress } = props;
const defaultOnPress = () => { const defaultOnPress = () => {
router.back(); router.back();
}; };
return ( return (
<Button <Button
className="h-16 w-16 mb-4" className={"h-16 w-16 mb-4" + " " + className}
onPress={onPress ?? defaultOnPress} onPress={onPress ?? defaultOnPress}
{...ref} {...ref}
{...props}
> >
<AntDesign name={icon ?? "arrowleft"} size={24} /> <AntDesign name={icon ?? "arrowleft"} size={24} />
</Button> </Button>

@ -0,0 +1,149 @@
import React, { forwardRef } from "react";
import { View, TouchableOpacity, ViewProps } from "react-native";
import Text from "./ui/Text";
import {
AntDesign,
Entypo,
FontAwesome6,
Ionicons,
MaterialCommunityIcons,
} from "@expo/vector-icons";
import {
AntDesignIconNames,
CommunityIconNames,
EntypoIconNames,
FontAwesome6IconNames,
FontAwesomeIconNames,
IonIconNames,
} from "./Icons";
export type CheckBoxDirection = "row" | "col";
interface CheckBoxProps extends ViewProps {
label?: string;
onChange: () => void;
antIcon?: AntDesignIconNames;
entypoIcon?: EntypoIconNames;
fontAwesomeIcon?: FontAwesomeIconNames;
fontAwesome6Icon?: FontAwesome6IconNames;
communityIcon?: CommunityIconNames;
IonIcon?: IonIconNames;
value: boolean;
isCheckIconVisible?: boolean;
endText?: string;
direction?: CheckBoxDirection;
}
export default forwardRef<any, CheckBoxProps>(
(
{
label,
onChange,
antIcon,
entypoIcon,
fontAwesomeIcon,
fontAwesome6Icon,
communityIcon,
IonIcon,
value,
isCheckIconVisible,
endText,
direction,
className,
...props
},
ref
) => {
return (
<TouchableOpacity
onPress={onChange}
className={
"items-center p-4 rounded-3xl" +
" " +
((direction ?? "row") == "row"
? "flex-row justify-between gap-4"
: "justify-center gap-1") +
" " +
(value
? "bg-orange-600 border-4 border-orange-300"
: "bg-gray-300 border-4 border-gray-300") +
" " +
(className ?? "")
}
{...props}
{...ref}
>
<View>
{antIcon ? (
<AntDesign
name={antIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
{entypoIcon ? (
<Entypo
name={entypoIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
{communityIcon ? (
<MaterialCommunityIcons
name={communityIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
{fontAwesomeIcon ? (
<FontAwesome6
name={fontAwesomeIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
{fontAwesome6Icon ? (
<FontAwesome6
name={fontAwesome6Icon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
{IonIcon ? (
<Ionicons
name={IonIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
</View>
{label != null ? (
<Text
weight="bold"
color={value ? "white" : "black"}
className={(direction ?? "row") == "row" ? "flex-1" : ""}
>
{label}
</Text>
) : null}
{isCheckIconVisible ? (
<View
className={
"h-5 w-5 rounded border justify-center items-center" +
" " +
(value ? "border-white" : "border-black")
}
>
{value && <View className="h-2 w-2 bg-white" />}
</View>
) : null}
{endText != null ? (
<Text color={value ? "white" : "black"}>{endText}</Text>
) : null}
</TouchableOpacity>
);
}
);

@ -1,68 +0,0 @@
import React, {Component} from "react";
import {View, Text, TouchableOpacity, Image} from "react-native";
import {
AntDesign,
Entypo,
FontAwesome6,
MaterialCommunityIcons,
} from "@expo/vector-icons";
import {
AntDesignIconNames,
CommunityIconNames,
EntypoIconNames,
FontAwesomeIconNames,
} from "./Icons";
interface CheckButtonProps {
label: string;
value: boolean;
onChange: () => void;
antIcon?: AntDesignIconNames;
entypoIcon?: EntypoIconNames;
fontAwesomeIcon?: FontAwesomeIconNames;
communityIcon?: CommunityIconNames;
}
const CheckButton: React.FC<CheckButtonProps> = ({ label, value, onChange, antIcon,
entypoIcon,
fontAwesomeIcon,
communityIcon, }) => {
return (
<View style={{ flexBasis: "33.33%"}}>
<TouchableOpacity onPress={onChange} className={`p-5 m-1 rounded-3xl ${value ? 'bg-orange-600 border-4 border-orange-300' : 'bg-gray-300 border-4 border-gray-300'} items-center`}>
{antIcon ? (
<AntDesign
name={antIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
{entypoIcon ? (
<Entypo
name={entypoIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
{communityIcon ? (
<MaterialCommunityIcons
name={communityIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
{fontAwesomeIcon ? (
<FontAwesome6
name={fontAwesomeIcon}
size={30}
color={value ? "white" : "black"}
/>
) : null}
<Text className={`${value ? 'text-white' : 'text-black'}`}>{label}</Text>
</TouchableOpacity>
</View>
);
};
export default CheckButton;

@ -1,34 +0,0 @@
import React, {Component} from "react";
import {View, Text, TouchableOpacity, Image} from "react-native";
import {AntDesign, FontAwesome6} from "@expo/vector-icons";
import {AntDesignIconNames} from "./Icons";
interface CheckBoxProps {
label: string;
value: boolean;
onChange: () => void;
icon: AntDesignIconNames | string;
}
const CheckBox: React.FC<CheckBoxProps> = ({ label, value, onChange, icon }) => {
let AwesomIconList = ["weight-scale", "beer"];
return (
<TouchableOpacity onPress={onChange} className={`p-5 m-1 rounded-3xl ${value ? 'bg-orange-600 border-4 border-orange-300' : 'bg-gray-300 border-4 border-gray-300'} flex-row items-center`}>
<View className="mr-2.5">
{AwesomIconList.includes(icon) ? (
<FontAwesome6 name={icon} size={30} color={value ? "white" : "black"}/>
) : (
<AntDesign name={icon ?? "arrowleft"} size={30} color={value ? "white" : "black"}/>
)}
</View>
<Text className={`${value ? 'text-white' : 'text-black'} flex-1`}>{label}</Text>
<View className={`h-5 w-5 rounded border ${value ? 'border-white' : 'border-black'} items-center justify-center mr-2.5`}>
{value && <View className="h-2 w-2 bg-white" />}
</View>
</TouchableOpacity>
);
};
export default CheckBox;

@ -1,3 +1,26 @@
import { AntDesign } from "@expo/vector-icons"; import {
AntDesign,
Entypo,
FontAwesome,
Ionicons,
MaterialCommunityIcons,
} from "@expo/vector-icons";
export type AntDesignIconNames = keyof typeof AntDesign.glyphMap; export type AntDesignIconNames = keyof typeof AntDesign.glyphMap;
export type EntypoIconNames = keyof typeof Entypo.glyphMap;
export type FontAwesomeIconNames = keyof typeof FontAwesome.glyphMap;
export type FontAwesome6IconNames =
| "person-running"
| "person-walking"
| "person-hiking"
| "skateboarding"
| "bike"
| "basketball"
| "heart"
| "yoga"
| "setting"
| "beer"
| "shield-heart"
| "weight-scale";
export type CommunityIconNames = keyof typeof MaterialCommunityIcons.glyphMap;
export type IonIconNames = keyof typeof Ionicons.glyphMap;

@ -8,9 +8,7 @@ interface Props extends ExtendedTextProps {
} }
export default React.forwardRef<any, Props>( export default React.forwardRef<any, Props>(
(props, ref): React.ReactElement => { ({ isVisible, ...props }, ref): React.ReactElement => {
const { isVisible, ...rest } = props;
const buildClassName = (): string => { const buildClassName = (): string => {
return ( return (
"flex-row items-center gap-2 bg-red-300 p-4 border-2 border-red-500 rounded-3xl" + "flex-row items-center gap-2 bg-red-300 p-4 border-2 border-red-500 rounded-3xl" +
@ -22,7 +20,7 @@ export default React.forwardRef<any, Props>(
return ( return (
<View className={buildClassName()} {...ref}> <View className={buildClassName()} {...ref}>
<MaterialIcons name="error" size={24} color={"red"} /> <MaterialIcons name="error" size={24} color={"red"} />
<Text position="center" weight="bold" {...rest} /> <Text position="center" weight="bold" {...props} />
</View> </View>
); );
} }

@ -12,8 +12,8 @@ interface Props extends FormInputProps {
} }
export default React.forwardRef<any, Props>( export default React.forwardRef<any, Props>(
(props, ref): React.ReactElement => { (
const { {
onBlur, onBlur,
onChangeText, onChangeText,
value, value,
@ -22,9 +22,10 @@ export default React.forwardRef<any, Props>(
label, label,
placeholder, placeholder,
onPress, onPress,
...rest ...props
} = props; },
ref
): React.ReactElement => {
return ( return (
<View className="gap-2"> <View className="gap-2">
<Text weight="bold">{label}</Text> <Text weight="bold">{label}</Text>
@ -37,7 +38,7 @@ export default React.forwardRef<any, Props>(
onChangeText={onChangeText} onChangeText={onChangeText}
value={value} value={value}
{...ref} {...ref}
{...rest} {...props}
/> />
{afterIcon != null ? ( {afterIcon != null ? (
<AntDesign name={afterIcon} size={24} onPress={onPress} /> <AntDesign name={afterIcon} size={24} onPress={onPress} />

@ -10,8 +10,7 @@ import { useSession } from "@/ctx";
import { router } from "expo-router"; import { router } from "expo-router";
export default React.forwardRef<any, ViewProps>( export default React.forwardRef<any, ViewProps>(
(props, ref): React.ReactElement => { ({ ...props }, ref): React.ReactElement => {
const { ...rest } = props;
const [email, setEmail] = React.useState(""); const [email, setEmail] = React.useState("");
const [password, setPassword] = React.useState(""); const [password, setPassword] = React.useState("");
const [error, setError] = React.useState(""); const [error, setError] = React.useState("");
@ -47,7 +46,7 @@ export default React.forwardRef<any, ViewProps>(
}; };
return ( return (
<View className="gap-4" {...ref} {...rest}> <View className="gap-4" {...ref} {...props}>
<View className="gap-4"> <View className="gap-4">
<TextInput <TextInput
beforeIcon="mail" beforeIcon="mail"

@ -2,8 +2,10 @@ import React, { useState } from "react";
import FormInput, { FormInputProps } from "./FormInput"; import FormInput, { FormInputProps } from "./FormInput";
export default React.forwardRef<any, FormInputProps>( export default React.forwardRef<any, FormInputProps>(
(props, ref): React.ReactElement => { (
const { onBlur, onChangeText, value, label, ...rest } = props; { onBlur, onChangeText, value, label, ...props },
ref
): React.ReactElement => {
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const toggleShowPassword = () => { const toggleShowPassword = () => {
@ -22,7 +24,7 @@ export default React.forwardRef<any, FormInputProps>(
onPress={toggleShowPassword} onPress={toggleShowPassword}
secureTextEntry={!showPassword} secureTextEntry={!showPassword}
{...ref} {...ref}
{...rest} {...props}
/> />
); );
} }

@ -8,8 +8,7 @@ import { EMPTY_FIELD, INVALID_EMAIL, NOT_MATCHING_PASSWORD } from "../Errors";
import FormError from "./FormError"; import FormError from "./FormError";
export default React.forwardRef<any, ViewProps>( export default React.forwardRef<any, ViewProps>(
(props, ref): React.ReactElement => { ({ ...props }, ref): React.ReactElement => {
const { ...rest } = props;
const [email, setEmail] = React.useState(""); const [email, setEmail] = React.useState("");
const [password, setPassword] = React.useState(""); const [password, setPassword] = React.useState("");
const [confirmPassword, setConfirmPassword] = React.useState(""); const [confirmPassword, setConfirmPassword] = React.useState("");
@ -52,7 +51,7 @@ export default React.forwardRef<any, ViewProps>(
}; };
return ( return (
<View className="gap-4" {...ref} {...rest}> <View className="gap-4" {...ref} {...props}>
<View className="gap-4"> <View className="gap-4">
<TextInput <TextInput
beforeIcon="mail" beforeIcon="mail"

@ -12,11 +12,9 @@ interface Props extends ModalProps {
} }
export default React.forwardRef<any, Props>( export default React.forwardRef<any, Props>(
(props, ref): React.ReactElement => { ({ email, onPress, ...props }, ref): React.ReactElement => {
const { email, onPress, ...rest } = props;
return ( return (
<Modal {...ref} animationType="fade" {...rest}> <Modal {...ref} animationType="fade" {...props}>
<Screen> <Screen>
<BackButton onPress={onPress} /> <BackButton onPress={onPress} />
<View className="gap-4"> <View className="gap-4">

@ -1,76 +1,76 @@
import React from "react"; import React, { useImperativeHandle, useState } from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import Checkbox from "../CheckboxComponent"; import Checkbox from "../CheckBox";
import { View } from "react-native"; import { View } from "react-native";
import {FontAwesome6} from "@expo/vector-icons"; import {
CommunityIconNames,
AntDesignIconNames,
EntypoIconNames,
FontAwesome6IconNames,
} from "../Icons";
import { ESportLevel, SportLevels } from "@/model/enums/Enums";
export default React.forwardRef<any, QuestionChildProps>( export interface ActivityQuestionRef {
(props, ref): React.ReactElement => { getAnswer: () => ESportLevel;
const { ...rest } = props;
const [checkedOne, setCheckedOne] = React.useState(true);
const [checkedTwo, setCheckedTwo] = React.useState(false);
const [checkedThree, setCheckedThree] = React.useState(false);
const [checkedFour, setCheckedFour] = React.useState(false);
const [checkedFive, setCheckedFive] = React.useState(false);
const handleChangeOne = () => {
if(!checkedOne) {
setCheckedOne(!checkedOne);
setCheckedTwo(false);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
}
};
const handleChangeTwo = () => {
if(!checkedTwo) {
setCheckedOne(false);
setCheckedTwo(!checkedTwo);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
}
};
const handleChangeThree = () => {
if(!checkedThree) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(!checkedThree);
setCheckedFour(false);
setCheckedFive(false);
} }
export default React.forwardRef<ActivityQuestionRef, QuestionChildProps>(
({ ...props }, ref): React.ReactElement => {
const [checkedItems, setCheckedItems] = useState([
true,
...Array(4).fill(false),
]);
const handleChange = (index: number) => {
const newCheckedState = checkedItems.map((_, i) => i === index);
setCheckedItems(newCheckedState);
}; };
const handleChangeFour = () => {
if(!checkedFour) { useImperativeHandle(ref, () => ({
setCheckedOne(false); getAnswer: () => {
setCheckedTwo(false); var selected = 0;
setCheckedThree(false); checkedItems.forEach((item, index) => {
setCheckedFour(!checkedFour); if (item) {
setCheckedFive(false); selected = index;
} }
}; });
const handleChangeFive = () => { return SportLevels[SportLevels.length - 1 - selected];
if(!checkedFive) { },
setCheckedOne(false); }));
setCheckedTwo(false);
setCheckedThree(false); interface IData {
setCheckedFour(false); label: string;
setCheckedFive(!checkedFive); commIcon?: CommunityIconNames;
antIcon?: AntDesignIconNames;
entypoIcon?: EntypoIconNames;
fontAwesomeIcon?: FontAwesome6IconNames;
} }
};
const data: IData[] = [
{ label: "Athlète", antIcon: "smile-circle" },
{ label: "Très sportif", antIcon: "smileo" },
{ label: "Un peu sportif", antIcon: "meh" },
{ label: "Peu sportif", antIcon: "frowno" },
{ label: "Pas du tout sportif", antIcon: "frown" },
];
return ( return (
<Question <Question
question="Comment estimez-vous votre niveau d'activité ?" question="Comment estimez-vous votre niveau d'activité ?"
{...ref} {...ref}
{...rest} {...props}
> >
<View> <View className="gap-2">
<Checkbox label="Athlète" value={checkedOne} onChange={handleChangeOne} icon={"smile-circle"} /> {data.map((item, index) => (
<Checkbox label="Très sportif" value={checkedTwo} onChange={handleChangeTwo} icon={"smileo"} /> <Checkbox
<Checkbox label="Un peu sportif" value={checkedThree} onChange={handleChangeThree} icon={"meh"} /> key={index}
<Checkbox label="Peu sportif" value={checkedFour} onChange={handleChangeFour} icon={"frowno"} /> label={item.label}
<Checkbox label="Pas du tout sportif" value={checkedFive} onChange={handleChangeFive} icon={"frown"} /> value={checkedItems[index]}
onChange={() => handleChange(index)}
antIcon={item.antIcon}
endText={(data.length - index).toString()}
/>
))}
</View> </View>
</Question> </Question>
); );

@ -1,38 +1,53 @@
import React from "react"; import React, {
forwardRef,
ReactElement,
useImperativeHandle,
useState,
} from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import Slider from "../ui/Slider"; import Slider from "../ui/Slider";
import { View } from "react-native"; import { View } from "react-native";
import Text from "../ui/Text"; import Text from "../ui/Text";
export default React.forwardRef<any, QuestionChildProps>(
(props, ref): React.ReactElement => {
const MIN_AGE = 18; const MIN_AGE = 18;
const MAX_AGE = 100; const MAX_AGE = 100;
const [age, setAge] = React.useState(MIN_AGE);
export interface AgeQuestionRef {
getAnswer: () => number;
}
export default forwardRef<AgeQuestionRef, QuestionChildProps>(
(props, ref): ReactElement => {
const [answer, setAnswer] = useState<number>(MIN_AGE);
useImperativeHandle(ref, () => ({
getAnswer: () => answer,
}));
return ( return (
<Question question="Quel âge avez-vous ?" {...ref} {...props}> <Question question="Quel âge avez-vous ?" {...ref} {...props}>
<View className="flex-row justify-center"> <View className="flex-row justify-center">
{age <= MIN_AGE ? ( {answer <= MIN_AGE ? (
<Text className="mt-8" size="4xl"> <Text className="mt-8" size="4xl">
- de - de
</Text> </Text>
) : null} ) : null}
{age >= MAX_AGE ? ( {answer >= MAX_AGE ? (
<Text className="mt-8" size="4xl"> <Text className="mt-8" size="4xl">
+ de + de
</Text> </Text>
) : null} ) : null}
<Text size="8xl" weight="bold"> <Text size="8xl" weight="bold">
{age} {answer}
</Text> </Text>
<Text className="mt-8" size="4xl"> <Text className="mt-8 ml-1" size="4xl">
ans ans
</Text> </Text>
</View> </View>
<Slider <Slider
minimumValue={MIN_AGE} minimumValue={MIN_AGE}
maximumValue={MAX_AGE} maximumValue={MAX_AGE}
onValueChange={setAge} onValueChange={setAnswer}
/> />
</Question> </Question>
); );

@ -1,15 +1,35 @@
import React from "react"; import React, {
forwardRef,
ReactElement,
useImperativeHandle,
useState,
} from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import SegmentedControl from "../ui/SegmentedControl"; import { Image, View } from "react-native";
import { Image } from "react-native";
//@ts-ignore //@ts-ignore
import BenchImage from "@/assets/images/bench.png"; import BenchImage from "@/assets/images/bench.png";
import CheckBox from "../CheckBox";
export default React.forwardRef<any, QuestionChildProps>( export interface BeginnerQuestionRef {
(props, ref): React.ReactElement => { getAnswer: () => boolean;
const ANSWERS = ["Non", "Oui"]; }
const [answer, setAnswer] = React.useState("Oui");
export default forwardRef<BeginnerQuestionRef, QuestionChildProps>(
(props, ref): ReactElement => {
const [answer, setAnswer] = useState<boolean>(false);
useImperativeHandle(ref, () => ({
getAnswer: () => answer,
}));
function handleChangeOne() {
setAnswer(true);
}
function handleChangeTwo() {
setAnswer(false);
}
return ( return (
<Question <Question
@ -18,11 +38,21 @@ export default React.forwardRef<any, QuestionChildProps>(
{...props} {...props}
> >
<Image className="self-center" source={BenchImage} alt="" /> <Image className="self-center" source={BenchImage} alt="" />
<SegmentedControl <View>
values={ANSWERS} <CheckBox
selectedIndex={ANSWERS.indexOf(answer)} className=""
onValueChange={setAnswer} label="Oui"
value={answer}
onChange={handleChangeOne}
fontAwesomeIcon={"check"}
/>
<CheckBox
label="Non"
value={!answer}
onChange={handleChangeTwo}
entypoIcon={"cross"}
/> />
</View>
</Question> </Question>
); );
} }

@ -1,20 +1,33 @@
import React from "react"; import React, { useImperativeHandle } from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import Text from "../ui/Text"; import Text from "../ui/Text";
import SegmentedControl from "../ui/SegmentedControl"; import SegmentedControl from "../ui/SegmentedControl";
import { View } from "react-native"; import { View } from "react-native";
const ANSWERS = ["1", "2", "3", "4", "5"];
export interface FrequencyQuestionRef {
getAnswer: () => number;
}
export interface FrequencyQuestionProps extends QuestionChildProps { export interface FrequencyQuestionProps extends QuestionChildProps {
isMale: boolean; isMale: boolean;
} }
export default React.forwardRef<any, FrequencyQuestionProps>( export default React.forwardRef<FrequencyQuestionRef, FrequencyQuestionProps>(
(props, ref): React.ReactElement => { ({ isMale, ...props }, ref): React.ReactElement => {
const { isMale, ...rest } = props;
const ANSWERS = ["1", "2", "3", "4", "5"];
const [answer, setAnswer] = React.useState("1"); const [answer, setAnswer] = React.useState("1");
useImperativeHandle(ref, () => ({
getAnswer: () => parseInt(answer),
}));
return ( return (
<Question question="Nombre de séance(s) par semaine ?" {...ref} {...rest}> <Question
question="Nombre de séance(s) par semaine ?"
{...ref}
{...props}
>
<View className="items-center"> <View className="items-center">
<Text size="2xl"> <Text size="2xl">
Je suis {isMale ? "prêt" : "prête"} à m'entraîner Je suis {isMale ? "prêt" : "prête"} à m'entraîner

@ -1,49 +1,53 @@
import React from "react"; import React, {
forwardRef,
ReactElement,
useImperativeHandle,
useState,
} from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import Checkbox from "../CheckboxComponent"; import Checkbox from "../CheckBox";
import { View } from "react-native"; import { View } from "react-native";
import {FontAwesome6} from "@expo/vector-icons";
export default React.forwardRef<any, QuestionChildProps>( export interface GenderQuestionRef {
(props, ref): React.ReactElement => { getAnswer: () => boolean;
const { ...rest } = props; }
export default forwardRef<GenderQuestionRef, QuestionChildProps>(
({ ...props }, ref): ReactElement => {
const [answer, setAnswer] = useState(true);
useImperativeHandle(ref, () => ({
getAnswer: () => answer,
}));
const [checkedOne, setCheckedOne] = React.useState(false);
const [checkedTwo, setCheckedTwo] = React.useState(false);
const [checkedThree, setCheckedThree] = React.useState(true);
const handleChangeOne = () => { const handleChangeOne = () => {
if(!checkedOne) setAnswer(true);
{
setCheckedOne(!checkedOne);
setCheckedTwo(false);
setCheckedThree(false);
}
}; };
const handleChangeTwo = () => { const handleChangeTwo = () => {
if(!checkedTwo) { setAnswer(false);
setCheckedOne(false);
setCheckedTwo(!checkedTwo);
setCheckedThree(false);
}
};
const handleChangeThree = () => {
if(!checkedThree) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(!checkedThree);
}
}; };
return ( return (
<Question <Question
question="Quel est votre genre physiologique ?" question="Quel est votre genre physiologique ?"
{...ref} {...ref}
{...rest} {...props}
> >
<View> <View className="gap-2">
<Checkbox label="Homme" value={checkedOne} onChange={handleChangeOne} icon={"man"} /> <Checkbox
<Checkbox label="Femme" value={checkedTwo} onChange={handleChangeTwo} icon={"woman"} /> label="Homme"
<Checkbox label="Je ne préfère pas répondre" value={checkedThree} onChange={handleChangeThree} icon={"minuscircle"} /> value={answer}
onChange={handleChangeOne}
antIcon={"man"}
isCheckIconVisible={true}
/>
<Checkbox
label="Femme"
value={!answer}
onChange={handleChangeTwo}
antIcon={"woman"}
isCheckIconVisible={true}
/>
</View> </View>
</Question> </Question>
); );

@ -1,46 +1,86 @@
import React from "react"; import React, {
forwardRef,
ReactElement,
useImperativeHandle,
useState,
} from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import Checkbox from "../CheckboxComponent";
import { View } from "react-native"; import { View } from "react-native";
import {FontAwesome6} from "@expo/vector-icons"; import {
CommunityIconNames,
AntDesignIconNames,
EntypoIconNames,
FontAwesome6IconNames,
IonIconNames,
} from "../Icons";
import CheckBox from "../CheckBox";
import { EGoal, Goals } from "@/model/enums/Enums";
export default React.forwardRef<any, QuestionChildProps>( export interface GoalQuestionRef {
(props, ref): React.ReactElement => { getAnswer: () => EGoal;
const { ...rest } = props; }
const [checkedOne, setCheckedOne] = React.useState(true); export default forwardRef<GoalQuestionRef, QuestionChildProps>(
const [checkedTwo, setCheckedTwo] = React.useState(false); ({ ...props }, ref): ReactElement => {
const [checkedThree, setCheckedThree] = React.useState(false); const [checkedItems, setCheckedItems] = useState([
const [checkedFour, setCheckedFour] = React.useState(false); true,
const [checkedFive, setCheckedFive] = React.useState(false); ...Array(4).fill(false),
const handleChangeOne = () => { ]);
setCheckedOne(!checkedOne);
}; interface IData {
const handleChangeTwo = () => { label: string;
setCheckedTwo(!checkedTwo); commIcon?: CommunityIconNames;
}; antIcon?: AntDesignIconNames;
const handleChangeThree = () => { entypoIcon?: EntypoIconNames;
setCheckedThree(!checkedThree); fontAwesomeIcon?: FontAwesome6IconNames;
}; ionIcon?: IonIconNames;
const handleChangeFour = () => { }
setCheckedFour(!checkedFour);
}; const data: IData[] = [
const handleChangeFive = () => { { label: "Perte de poids", commIcon: "weight" },
setCheckedFive(!checkedFive); { label: "Renforcement musculaire", commIcon: "arm-flex-outline" },
{ label: "Prise de masse", ionIcon: "beer-outline" },
{ label: "Amélioration endurance", fontAwesomeIcon: "shield-heart" },
{ label: "Maintenir en forme", antIcon: "linechart" },
];
const handleChange = (index: number) => {
const newCheckedState = checkedItems.map((_, i) => i === index);
setCheckedItems(newCheckedState);
}; };
useImperativeHandle(ref, () => ({
getAnswer: () => {
var selected = 0;
checkedItems.forEach((item, index) => {
if (item) {
selected = index;
}
});
return Goals[selected];
},
}));
return ( return (
<Question <Question
question="Quel est votre objectif dans l'application ?" question="Quel est votre objectif dans l'application ?"
{...ref} {...ref}
{...rest} {...props}
> >
<View> <View className="gap-2">
<Checkbox label="Perte de poids" value={checkedOne} onChange={handleChangeOne} icon="weight-scale" /> {data.map((item, index) => (
<Checkbox label="Renforcement musculaire" value={checkedTwo} onChange={handleChangeTwo} icon={"rest"} /> <CheckBox
<Checkbox label="Prise de masse" value={checkedThree} onChange={handleChangeThree} icon="beer" /> key={index}
<Checkbox label="Amélioration endurance" value={checkedFour} onChange={handleChangeFour} icon={"linechart"} /> label={item.label}
<Checkbox label="Maintenir en forme" value={checkedFive} onChange={handleChangeFive} icon={"linechart"} /> value={checkedItems[index]}
onChange={() => handleChange(index)}
fontAwesome6Icon={item.fontAwesomeIcon}
communityIcon={item.commIcon}
antIcon={item.antIcon}
entypoIcon={item.entypoIcon}
IonIcon={item.ionIcon}
/>
))}
</View> </View>
</Question> </Question>
); );

@ -1,17 +1,32 @@
import React from "react"; import React, {
forwardRef,
ReactElement,
useImperativeHandle,
useState,
} from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import Slider from "../ui/Slider"; import Slider from "../ui/Slider";
import Text from "../ui/Text"; import Text from "../ui/Text";
import { View } from "react-native"; import { View } from "react-native";
import SegmentedControl from "../ui/SegmentedControl"; import SegmentedControl from "../ui/SegmentedControl";
export default React.forwardRef<any, QuestionChildProps>(
(props, ref): React.ReactElement => {
const MIN_HEIGHT = 120; const MIN_HEIGHT = 120;
const MAX_HEIGHT = 250; const MAX_HEIGHT = 250;
export interface HeightQuestionRef {
getAnswer: () => number;
}
export default forwardRef<HeightQuestionRef, QuestionChildProps>(
({ ...props }, ref): ReactElement => {
const [answer, setAnswer] = useState<number>(MIN_HEIGHT);
const UNITS = ["cm", "inch"]; const UNITS = ["cm", "inch"];
const [height, setHeight] = React.useState(MIN_HEIGHT); const [unit, setUnit] = useState<string>("cm");
const [unit, setUnit] = React.useState("cm");
useImperativeHandle(ref, () => ({
getAnswer: () => answer,
}));
return ( return (
<Question question="Quel est votre taille ?" {...ref} {...props}> <Question question="Quel est votre taille ?" {...ref} {...props}>
<SegmentedControl <SegmentedControl
@ -20,18 +35,18 @@ export default React.forwardRef<any, QuestionChildProps>(
onValueChange={setUnit} onValueChange={setUnit}
/> />
<View className="flex-row justify-center"> <View className="flex-row justify-center">
{height <= MIN_HEIGHT ? ( {answer <= MIN_HEIGHT ? (
<Text className="mt-8" size="4xl"> <Text className="mt-8" size="4xl">
- de - de
</Text> </Text>
) : null} ) : null}
{height >= MAX_HEIGHT ? ( {answer >= MAX_HEIGHT ? (
<Text className="mt-8" size="4xl"> <Text className="mt-8" size="4xl">
+ de + de
</Text> </Text>
) : null} ) : null}
<Text size="8xl" weight="bold"> <Text size="8xl" weight="bold">
{height} {answer}
</Text> </Text>
<Text className="mt-8" size="4xl"> <Text className="mt-8" size="4xl">
{unit} {unit}
@ -40,7 +55,7 @@ export default React.forwardRef<any, QuestionChildProps>(
<Slider <Slider
minimumValue={MIN_HEIGHT} minimumValue={MIN_HEIGHT}
maximumValue={MAX_HEIGHT} maximumValue={MAX_HEIGHT}
onValueChange={setHeight} onValueChange={setAnswer}
/> />
</Question> </Question>
); );

@ -0,0 +1,54 @@
import React, { useState } from "react";
import Question, { QuestionChildProps } from "./Question";
import { Image, View, Text } from "react-native";
import { MultiSelect } from "react-native-element-dropdown";
//@ts-ignore
import WheelChair from "@/assets/images/wheelchair.png";
import { EHealthProblem } from "@/model/enums/Enums";
export default React.forwardRef<any, QuestionChildProps>(
({ ...props }, ref) => {
const [selected, setSelected] = useState<string[]>([]);
type DataItem = {
label: string;
value: EHealthProblem;
};
const data: DataItem[] = [
{ label: "Arthrose", value: "ARTHROSE" },
{ label: "Migraine", value: "MIGRAINE" },
];
const renderItem = (item: { label: string }) => {
return (
<View className="p-4">
<Text>{item.label}</Text>
</View>
);
};
return (
<Question
question="Avez-vous des problèmes physiques ?"
{...props}
{...ref}
>
<Image className="self-center" source={WheelChair} alt="" />
<View className="border-2 border-orange-500 rounded-3xl p-4">
<MultiSelect
data={data}
labelField="label"
valueField="value"
placeholder="Selectionnez un problème physique "
searchPlaceholder="Search..."
value={selected}
onChange={setSelected}
renderItem={renderItem}
/>
</View>
</Question>
);
}
);

@ -1,15 +0,0 @@
import React from "react";
import Question, { QuestionChildProps } from "./Question";
export default React.forwardRef<any, QuestionChildProps>(
(props, ref): React.ReactElement => {
const { ...rest } = props;
return (
<Question
question="Comment estimez vous votre niveau d'activité ?"
{...ref}
{...rest}
></Question>
);
}
);

@ -11,14 +11,13 @@ interface QuestionProps extends QuestionChildProps {
} }
export default React.forwardRef<any, QuestionProps>( export default React.forwardRef<any, QuestionProps>(
(props, ref): React.ReactElement => { ({ question, isVisible, children, ...props }, ref): React.ReactElement => {
const { question, isVisible, children, ...rest } = props;
const getClassName = () => { const getClassName = () => {
return "gap-6" + " " + (isVisible ? "block" : "hidden"); return "gap-6" + " " + (isVisible ? "block" : "hidden");
}; };
return ( return (
<View className={getClassName()} {...ref} {...rest}> <View className={getClassName()} {...ref} {...props}>
<Text size="4xl" position="center" weight="bold"> <Text size="4xl" position="center" weight="bold">
{question} {question}
</Text> </Text>

@ -1,76 +1,89 @@
import React from "react"; import React, { useImperativeHandle, useState } from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import Checkbox from "../CheckboxComponent"; import Checkbox from "../CheckBox";
import { View } from "react-native"; import { View } from "react-native";
import {FontAwesome6} from "@expo/vector-icons"; import { ESleepLevel, SleepLevels } from "@/model/enums/Enums";
import { AntDesignIconNames } from "../Icons";
export default React.forwardRef<any, QuestionChildProps>( export interface SleepQuestionRef {
(props, ref): React.ReactElement => { getAnswer: () => ESleepLevel;
const { ...rest } = props;
const [checkedOne, setCheckedOne] = React.useState(true);
const [checkedTwo, setCheckedTwo] = React.useState(false);
const [checkedThree, setCheckedThree] = React.useState(false);
const [checkedFour, setCheckedFour] = React.useState(false);
const [checkedFive, setCheckedFive] = React.useState(false);
const handleChangeOne = () => {
if(!checkedOne) {
setCheckedOne(!checkedOne);
setCheckedTwo(false);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
}
};
const handleChangeTwo = () => {
if(!checkedTwo) {
setCheckedOne(false);
setCheckedTwo(!checkedTwo);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
}
};
const handleChangeThree = () => {
if(!checkedThree) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(!checkedThree);
setCheckedFour(false);
setCheckedFive(false);
} }
export default React.forwardRef<SleepQuestionRef, QuestionChildProps>(
({ ...props }, ref): React.ReactElement => {
const [checkedItems, setCheckedItems] = useState([
true,
...Array(4).fill(false),
]);
const handleChange = (index: number) => {
const newCheckedState = checkedItems.map((_, i) => i === index);
setCheckedItems(newCheckedState);
}; };
const handleChangeFour = () => {
if(!checkedFour) { useImperativeHandle(ref, () => ({
setCheckedOne(false); getAnswer: () => {
setCheckedTwo(false); var selected = 0;
setCheckedThree(false); checkedItems.forEach((item, index) => {
setCheckedFour(!checkedFour); if (item) {
setCheckedFive(false); selected = index;
} }
}; });
const handleChangeFive = () => { return SleepLevels[SleepLevels.length - 1 - selected];
if(!checkedFive) { },
setCheckedOne(false); }));
setCheckedTwo(false);
setCheckedThree(false); interface IData {
setCheckedFour(false); label: string;
setCheckedFive(!checkedFive); icon: AntDesignIconNames;
endText: string;
} }
};
const data: IData[] = [
{
label: "Excellent",
icon: "smile-circle",
endText: ">8 heures",
},
{
label: "Bien",
icon: "smileo",
endText: "7-8 heures",
},
{
label: "Mauvaise",
icon: "meh",
endText: "6-7 heures",
},
{
label: "Très mauvaise",
icon: "frowno",
endText: "3-4 heures",
},
{
label: "Insomniaque",
icon: "frown",
endText: "<2 heures",
},
];
return ( return (
<Question <Question
question="Quelle est la qualité de votre sommeil ?" question="Quelle est la qualité de votre sommeil ?"
{...ref} {...ref}
{...rest} {...props}
> >
<View> <View className="gap-2">
<Checkbox label="Excellente" value={checkedOne} onChange={handleChangeOne} icon={"smile-circle"} /> {data.map((item, index) => (
<Checkbox label="Bien" value={checkedTwo} onChange={handleChangeTwo} icon={"smileo"} /> <Checkbox
<Checkbox label="Mauvaise" value={checkedThree} onChange={handleChangeThree} icon={"meh"} /> key={index}
<Checkbox label="Très mauvaise" value={checkedFour} onChange={handleChangeFour} icon={"frowno"} /> label={item.label}
<Checkbox label="Insomniaque" value={checkedFive} onChange={handleChangeFive} icon={"frown"} /> value={checkedItems[index]}
onChange={() => handleChange(index)}
antIcon={item.icon}
endText={item.endText}
/>
))}
</View> </View>
</Question> </Question>
); );

@ -1,158 +1,84 @@
import React from "react"; import React, {
forwardRef,
ReactElement,
useImperativeHandle,
useState,
} from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import CheckButton from "../CheckButtonComponent";
import { View } from "react-native"; import { View } from "react-native";
import {FontAwesome6} from "@expo/vector-icons"; import CheckBox from "../CheckBox";
import {
AntDesignIconNames,
CommunityIconNames,
EntypoIconNames,
FontAwesome6IconNames,
} from "../Icons";
import { ESport, Sports } from "@/model/enums/Enums";
export default React.forwardRef<any, QuestionChildProps>( export interface SportQuestionRef {
(props, ref): React.ReactElement => { getAnswer: () => ESport;
const { ...rest } = props;
const [checkedOne, setCheckedOne] = React.useState(true);
const [checkedTwo, setCheckedTwo] = React.useState(false);
const [checkedThree, setCheckedThree] = React.useState(false);
const [checkedFour, setCheckedFour] = React.useState(false);
const [checkedFive, setCheckedFive] = React.useState(false);
const [checkedSix, setCheckedSix] = React.useState(false);
const [checkedSeven, setCheckedSeven] = React.useState(false);
const [checkedEight, setCheckedEight] = React.useState(false);
const [checkedNine, setCheckedNine] = React.useState(false);
const handleChangeOne = () => {
if(!checkedOne) {
setCheckedOne(!checkedOne);
setCheckedTwo(false);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
setCheckedSix(false);
setCheckedSeven(false);
setCheckedEight(false);
setCheckedNine(false);
}
};
const handleChangeTwo = () => {
if(!checkedTwo) {
setCheckedOne(false);
setCheckedTwo(!checkedTwo);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
setCheckedSix(false);
setCheckedSeven(false);
setCheckedEight(false);
setCheckedNine(false);
}
};
const handleChangeThree = () => {
if(!checkedThree) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(!checkedThree);
setCheckedFour(false);
setCheckedFive(false);
setCheckedSix(false);
setCheckedSeven(false);
setCheckedEight(false);
setCheckedNine(false);
}
};
const handleChangeFour = () => {
if(!checkedFour) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(false);
setCheckedFour(!checkedFour);
setCheckedFive(false);
setCheckedSix(false);
setCheckedSeven(false);
setCheckedEight(false);
setCheckedNine(false);
}
};
const handleChangeFive = () => {
if(!checkedFive) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(!checkedFive);
setCheckedSix(false);
setCheckedSeven(false);
setCheckedEight(false);
setCheckedNine(false);
}
};
const handleChangeSix = () => {
if(!checkedSix) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
setCheckedSix(!checkedSix);
setCheckedSeven(false);
setCheckedEight(false);
setCheckedNine(false);
}
};
const handleChangeSeven = () => {
if(!checkedSeven) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
setCheckedSix(false);
setCheckedSeven(!checkedSeven);
setCheckedEight(false);
setCheckedNine(false);
}
};
const handleChangeEight = () => {
if(!checkedEight) {
setCheckedOne(false);
setCheckedTwo(false);
setCheckedThree(false);
setCheckedFour(false);
setCheckedFive(false);
setCheckedSix(false);
setCheckedSeven(false);
setCheckedEight(!checkedEight);
setCheckedNine(false);
} }
export default forwardRef<SportQuestionRef, QuestionChildProps>(
(props, ref): ReactElement => {
const [checkedItems, setCheckedItems] = useState([
true,
...Array(8).fill(false),
]);
const handleChange = (index: number) => {
const newCheckedState = checkedItems.map((_, i) => i === index);
setCheckedItems(newCheckedState);
}; };
const handleChangeNine = () => {
if(!checkedNine) { useImperativeHandle(ref, () => ({
setCheckedOne(false); getAnswer: () => {
setCheckedTwo(false); var selected = 0;
setCheckedThree(false); checkedItems.forEach((item, index) => {
setCheckedFour(false); if (item) {
setCheckedFive(false); selected = index;
setCheckedSix(false);
setCheckedSeven(false);
setCheckedEight(false);
setCheckedNine(!checkedNine);
} }
}; });
return Sports[selected];
},
}));
return ( interface IData {
<Question label: string;
question="Quel sport ?" commIcon?: CommunityIconNames;
{...ref} antIcon?: AntDesignIconNames;
{...rest} entypoIcon?: EntypoIconNames;
> fontAwesomeIcon?: FontAwesome6IconNames;
<View className={`flex-wrap flex-row`}> }
<CheckButton label="Course" value={checkedOne} onChange={handleChangeOne} fontAwesomeIcon={"person-running"} />
<CheckButton label="Marche" value={checkedTwo} onChange={handleChangeTwo} fontAwesomeIcon={"person-walking"} />
<CheckButton label="Rando" value={checkedThree} onChange={handleChangeThree} fontAwesomeIcon={"person-hiking"} />
<CheckButton label="Skate" value={checkedFour} onChange={handleChangeFour} communityIcon={"skateboarding"} /> const data: IData[] = [
<CheckButton label="Cyclisme" value={checkedFive} onChange={handleChangeFive} communityIcon={"bike"} /> { label: "Course", fontAwesomeIcon: "person-running" },
<CheckButton label="Basket" value={checkedSix} onChange={handleChangeSix} fontAwesomeIcon={"basketball"} /> { label: "Marche", fontAwesomeIcon: "person-walking" },
{ label: "Rando", fontAwesomeIcon: "person-hiking" },
{ label: "Skate", commIcon: "skateboarding" },
{ label: "Cyclisme", commIcon: "bike" },
{ label: "Basket", fontAwesomeIcon: "basketball" },
{ label: "Cardio", antIcon: "heart" },
{ label: "Yoga", commIcon: "yoga" },
{ label: "Autre", entypoIcon: "dots-three-horizontal" },
];
<CheckButton label="Cardio" value={checkedSeven} onChange={handleChangeSeven} antIcon={"heart"} /> return (
<CheckButton label="Yoga" value={checkedEight} onChange={handleChangeEight} communityIcon={"yoga"} /> <Question question="Quel sport pratiquez-vous ?" {...ref} {...props}>
<CheckButton label="Autre" value={checkedNine} onChange={handleChangeNine} antIcon={"setting"} /> <View className="flex-row justify-center flex-wrap gap-2">
{data.map((item, index) => (
<CheckBox
key={index}
label={item.label}
value={checkedItems[index]}
onChange={() => handleChange(index)}
fontAwesome6Icon={item.fontAwesomeIcon}
communityIcon={item.commIcon}
antIcon={item.antIcon}
entypoIcon={item.entypoIcon}
direction="col"
/>
))}
</View> </View>
</Question> </Question>
); );

@ -1,37 +1,52 @@
import React from "react"; import React, {
forwardRef,
ReactElement,
useImperativeHandle,
useState,
} from "react";
import Question, { QuestionChildProps } from "./Question"; import Question, { QuestionChildProps } from "./Question";
import Slider from "../ui/Slider"; import Slider from "../ui/Slider";
import Text from "../ui/Text"; import Text from "../ui/Text";
import { View } from "react-native"; import { View } from "react-native";
import SegmentedControl from "../ui/SegmentedControl"; import SegmentedControl from "../ui/SegmentedControl";
export default React.forwardRef<any, QuestionChildProps>(
(props, ref): React.ReactElement => {
const MIN_WEIGHT = 40; const MIN_WEIGHT = 40;
const MAX_WEIGHT = 200; const MAX_WEIGHT = 200;
export interface WeightQuestionRef {
getAnswer: () => number;
}
const WeightQuestion = forwardRef<WeightQuestionRef, QuestionChildProps>(
(props, ref): ReactElement => {
const UNITS = ["kg", "lb"]; const UNITS = ["kg", "lb"];
const [weight, setWeight] = React.useState(MIN_WEIGHT); const [answer, setAnswer] = useState<number>(MIN_WEIGHT);
const [unit, setUnit] = React.useState("kg"); const [unit, setUnit] = useState<string>("kg");
useImperativeHandle(ref, () => ({
getAnswer: () => answer,
}));
return ( return (
<Question question="Quel est votre poids ?" {...ref} {...props}> <Question question="Quel est votre poids ?" {...props}>
<SegmentedControl <SegmentedControl
values={UNITS} values={UNITS}
selectedIndex={UNITS.indexOf(unit)} selectedIndex={UNITS.indexOf(unit)}
onValueChange={setUnit} onValueChange={setUnit}
/> />
<View className="flex-row justify-center gap-2"> <View className="flex-row justify-center gap-2">
{weight <= MIN_WEIGHT ? ( {answer <= MIN_WEIGHT && (
<Text className="mt-8" size="4xl"> <Text className="mt-8" size="4xl">
- de - de
</Text> </Text>
) : null} )}
{weight >= MAX_WEIGHT ? ( {answer >= MAX_WEIGHT && (
<Text className="mt-8" size="4xl"> <Text className="mt-8" size="4xl">
+ de + de
</Text> </Text>
) : null} )}
<Text size="8xl" weight="bold"> <Text size="8xl" weight="bold">
{weight} {answer}
</Text> </Text>
<Text className="mt-8" size="4xl"> <Text className="mt-8" size="4xl">
{unit} {unit}
@ -40,9 +55,11 @@ export default React.forwardRef<any, QuestionChildProps>(
<Slider <Slider
minimumValue={MIN_WEIGHT} minimumValue={MIN_WEIGHT}
maximumValue={MAX_WEIGHT} maximumValue={MAX_WEIGHT}
onValueChange={setWeight} onValueChange={setAnswer}
/> />
</Question> </Question>
); );
} }
); );
export default WeightQuestion;

@ -8,7 +8,7 @@ import { Size } from "../Constants";
export type ButtonStyle = "default" | "outline" | "secondary"; export type ButtonStyle = "default" | "outline" | "secondary";
//@ts-ignore //@ts-ignore
interface Props extends TouchableOpacityProps { export interface ButtonProps extends TouchableOpacityProps {
size?: Size; size?: Size;
style?: ButtonStyle; style?: ButtonStyle;
insideClassName?: string; insideClassName?: string;
@ -16,9 +16,9 @@ interface Props extends TouchableOpacityProps {
afterIcon?: AntDesignIconNames; afterIcon?: AntDesignIconNames;
} }
export default React.forwardRef<any, Props>( export default React.forwardRef<any, ButtonProps>(
(props, ref): React.ReactElement => { (
const { {
size, size,
style, style,
beforeIcon, beforeIcon,
@ -27,9 +27,10 @@ export default React.forwardRef<any, Props>(
className, className,
insideClassName, insideClassName,
children, children,
...rest ...props
} = props; },
ref
): React.ReactElement => {
const getButtonStyle = (): string => { const getButtonStyle = (): string => {
switch (style ?? "default") { switch (style ?? "default") {
case "default": case "default":
@ -83,7 +84,7 @@ export default React.forwardRef<any, Props>(
}; };
return ( return (
<View className={getButtonStyle()} {...ref} {...rest}> <View className={getButtonStyle()} {...ref} {...props}>
<TouchableOpacity <TouchableOpacity
className={"flex-row justify-center items-center gap-2 p-4 w-full"} className={"flex-row justify-center items-center gap-2 p-4 w-full"}
onPress={onPress} onPress={onPress}

@ -3,10 +3,9 @@ import { SafeAreaView } from "react-native-safe-area-context";
import React from "react"; import React from "react";
export default React.forwardRef<any, ViewProps>( export default React.forwardRef<any, ViewProps>(
(props, ref): React.ReactElement => { ({ children, ...props }, ref): React.ReactElement => {
const { children, ...rest } = props;
return ( return (
<SafeAreaView className={"h-full p-4"} {...ref} {...rest}> <SafeAreaView className={"h-full p-4"} {...ref} {...props}>
<View>{children}</View> <View>{children}</View>
</SafeAreaView> </SafeAreaView>
); );

@ -2,8 +2,7 @@ import React from "react";
import Slider, { SliderProps } from "@react-native-community/slider"; import Slider, { SliderProps } from "@react-native-community/slider";
export default React.forwardRef<any, SliderProps>( export default React.forwardRef<any, SliderProps>(
(props, ref): React.ReactElement => { ({ ...props }, ref): React.ReactElement => {
const { ...rest } = props;
return ( return (
<Slider <Slider
step={1} step={1}
@ -11,7 +10,7 @@ export default React.forwardRef<any, SliderProps>(
minimumTrackTintColor="#F97316" minimumTrackTintColor="#F97316"
maximumTrackTintColor="#F97316" maximumTrackTintColor="#F97316"
{...ref} {...ref}
{...rest} {...props}
/> />
); );
} }

@ -20,18 +20,10 @@ export interface ExtendedTextProps extends TextProps {
} }
export default React.forwardRef<any, ExtendedTextProps>( export default React.forwardRef<any, ExtendedTextProps>(
(props, ref): React.ReactElement => { (
const { { position, color, size, weight, isLink, className, children, ...props },
position, ref
color, ): React.ReactElement => {
size,
weight,
isLink,
className,
children,
...rest
} = props;
const buildClassName = () => { const buildClassName = () => {
const textSize = toTextSize(size ?? "lg"); const textSize = toTextSize(size ?? "lg");
const textColor = toTextColor(color ?? "black"); const textColor = toTextColor(color ?? "black");
@ -54,7 +46,7 @@ export default React.forwardRef<any, ExtendedTextProps>(
}; };
return ( return (
<Text className={buildClassName()} {...ref} {...rest}> <Text className={buildClassName()} {...ref} {...props}>
{children} {children}
</Text> </Text>
); );

@ -0,0 +1,146 @@
import {
EHealthProblem,
ESleepLevel,
ESport,
ESportLevel,
} from "./enums/Enums";
export class User {
private _name: string;
private _age: number;
private _height: number;
private _weight: number;
private _sexe: boolean; // true = Male, false = Female
private _logo: string;
private _nbSessionPerWeek: number;
private _goal: string;
private _healthProblems: EHealthProblem[];
private _sport: ESport;
private _sleepLevel: ESleepLevel;
private _sportLevel: ESportLevel;
constructor(
name: string,
age: number,
height: number,
weight: number,
sexe: boolean,
logo: string,
nbSessionPerWeek: number,
goal: string,
healthProblems: EHealthProblem[],
sport: ESport,
sleepLevel: ESleepLevel,
sportLevel: ESportLevel
) {
this._name = name;
this._age = age;
this._height = height;
this._weight = weight;
this._sexe = sexe;
this._logo = logo;
this._nbSessionPerWeek = nbSessionPerWeek;
this._goal = goal;
this._healthProblems = healthProblems;
this._sport = sport;
this._sleepLevel = sleepLevel;
this._sportLevel = sportLevel;
}
get name(): string {
return this._name;
}
get age(): number {
return this._age;
}
get height(): number {
return this._height;
}
get weight(): number {
return this._weight;
}
get sexe(): boolean {
return this._sexe;
}
get logo(): string {
return this._logo;
}
get nbSessionPerWeek(): number {
return this._nbSessionPerWeek;
}
get goals(): string {
return this._goal;
}
get healthProblems(): EHealthProblem[] {
return this._healthProblems;
}
get sports(): ESport {
return this._sport;
}
get sleepLevel(): ESleepLevel {
return this._sleepLevel;
}
get sportLevel(): ESportLevel {
return this._sportLevel;
}
// Setters
set name(value: string) {
this._name = value;
}
set age(value: number) {
this._age = value;
}
set height(value: number) {
this._height = value;
}
set weight(value: number) {
this._weight = value;
}
set sexe(value: boolean) {
this._sexe = value;
}
set logo(value: string) {
this._logo = value;
}
set nbSessionPerWeek(value: number) {
this._nbSessionPerWeek = value;
}
set goals(value: string) {
this._goal = value;
}
set healthProblems(value: EHealthProblem[]) {
this._healthProblems = value;
}
set sports(value: ESport) {
this._sport = value;
}
set sleepLevel(value: ESleepLevel) {
this._sleepLevel = value;
}
set sportLevel(value: ESportLevel) {
this._sportLevel = value;
}
}

@ -0,0 +1,42 @@
export const Goals = [
"WEIGHT_LOSE",
"IMPROVE_MUSCLE",
"WEIGHT_GAIN",
"IMPROVE_STAMINA",
"KEEP_FIT",
] as const;
export const SportLevels = [
"NOT_SPORTY",
"BEGINNER",
"SPORTY",
"VERY_SPORTY",
"PERFORMER",
] as const;
export const Sports = [
"RUNNING",
"WALKING",
"RANDO",
"SKATEBOARD",
"BIKING",
"BASKETBALL",
"CARDIO",
"YOGA",
"ELSE",
] as const;
export const SleepLevels = [
"TERRIBLE",
"VERY_BAD",
"BAD",
"GOOD",
"EXCELLENT",
] as const;
export type EGoal = (typeof Goals)[number];
export type ESportLevel = (typeof SportLevels)[number];
export type ESport = (typeof Sports)[number];
export type ESleepLevel = (typeof SleepLevels)[number];
export type EHealthProblem = "ARTHROSE" | "MIGRAINE";

17
package-lock.json generated

@ -37,6 +37,7 @@
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-native": "0.76.6", "react-native": "0.76.6",
"react-native-element-dropdown": "^2.12.4",
"react-native-gesture-handler": "^2.20.2", "react-native-gesture-handler": "^2.20.2",
"react-native-gifted-charts": "^1.4.54", "react-native-gifted-charts": "^1.4.54",
"react-native-reanimated": "^3.16.7", "react-native-reanimated": "^3.16.7",
@ -12247,6 +12248,22 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/react-native-element-dropdown": {
"version": "2.12.4",
"resolved": "https://registry.npmjs.org/react-native-element-dropdown/-/react-native-element-dropdown-2.12.4.tgz",
"integrity": "sha512-abZc5SVji9FIt7fjojRYrbuvp03CoeZJrgvezQoDoSOrpiTqkX69ix5m+j06W2AVncA0VWvbT+vCMam8SoVadw==",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.21"
},
"engines": {
"node": ">= 16.0.0"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-gesture-handler": { "node_modules/react-native-gesture-handler": {
"version": "2.22.0", "version": "2.22.0",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.22.0.tgz", "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.22.0.tgz",

@ -44,6 +44,7 @@
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-native": "0.76.6", "react-native": "0.76.6",
"react-native-element-dropdown": "^2.12.4",
"react-native-gesture-handler": "^2.20.2", "react-native-gesture-handler": "^2.20.2",
"react-native-gifted-charts": "^1.4.54", "react-native-gifted-charts": "^1.4.54",
"react-native-reanimated": "^3.16.7", "react-native-reanimated": "^3.16.7",

Loading…
Cancel
Save