Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"react-native-keyboard-controller": "^1.17.5",
"react-native-linear-gradient": "^2.6.2",
"react-native-localize": "^2.2.4",
"react-native-markdown-display": "^7.0.2",
"react-native-modal": "^13.0.1",
"react-native-modal-datetime-picker": "^18.0.0",
"react-native-multiple-select": "^0.5.12",
Expand Down
156 changes: 156 additions & 0 deletions app/src/components/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import React, { useState } from "react";
import { View, Text, TouchableOpacity, LayoutAnimation, Platform, UIManager } from "react-native";
import Markdown from "react-native-markdown-display";
import ArrowUpSvg from "../../assets/svg/icon/ArrowUp";
import { mergeClassNames } from "@/utils/className";
import { typography } from "@/utils/typography";
import { TW_COLORS } from "@/utils/constants";

// Enable LayoutAnimation on Android
if (Platform.OS === "android" && UIManager.setLayoutAnimationEnabledExperimental) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}

export interface AccordionItem {
title: string;
description: string; // Markdown content
}

interface AccordionProps {
items: AccordionItem[];
}

interface AccordionItemComponentProps {
item: AccordionItem;
isExpanded: boolean;
showDivider?: boolean;
onToggle: () => void;
}

const AccordionItemComponent: React.FC<AccordionItemComponentProps> = ({ item, isExpanded, onToggle, showDivider }) => {
const handleToggle = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
onToggle();
};

const markdownStyles = {
body: {
fontSize: 16,
lineHeight: 24,
color: TW_COLORS.CNAM_PRIMARY_800,
fontFamily: "SourceSans3",
},
heading1: {
fontSize: 24,
lineHeight: 32,
fontWeight: "700" as const,
color: TW_COLORS.CNAM_PRIMARY_800,
marginBottom: 12,
fontFamily: "SourceSans3",
},
heading2: {
fontSize: 20,
lineHeight: 30,
fontWeight: "700" as const,
color: TW_COLORS.CNAM_PRIMARY_800,
marginBottom: 8,
fontFamily: "SourceSans3",
},
heading3: {
fontSize: 18,
lineHeight: 26,
fontWeight: "700" as const,
color: TW_COLORS.CNAM_PRIMARY_800,
marginBottom: 6,
fontFamily: "SourceSans3",
},
paragraph: {
fontSize: 16,
lineHeight: 24,
color: TW_COLORS.CNAM_PRIMARY_800,
marginBottom: 8,
fontFamily: "SourceSans3",
},
strong: {
fontWeight: "600" as const,
color: TW_COLORS.CNAM_PRIMARY_800,
},
list_item: {
fontSize: 16,
lineHeight: 24,
color: "#3D6874",
marginBottom: 4,
fontFamily: "SourceSans3",
},
bullet_list: {
marginBottom: 8,
},
ordered_list: {
marginBottom: 8,
},
};

return (
<View>
<TouchableOpacity onPress={handleToggle} className="flex-row items-center justify-between p-4 py-4">
<Text className={mergeClassNames(typography.textLgSemibold, "text-cnam-primary-950 flex-1 mr-3")}>{item.title}</Text>
<View
className="transition-transform duration-200"
style={{
transform: [{ rotate: isExpanded ? "0deg" : "180deg" }],
}}
>
<ArrowUpSvg width={20} height={20} color={TW_COLORS.CNAM_PRIMARY_900} />
</View>
</TouchableOpacity>

{isExpanded && (
<View className={mergeClassNames("px-4 pb-4")}>
<View>
<Markdown style={markdownStyles}>{item.description}</Markdown>
</View>
</View>
)}
{showDivider && <View className="h-[1] bg-cnam-primary-300 mx-4 mt-2"></View>}
</View>
);
};

export const Accordion: React.FC<AccordionProps> = ({ items }) => {
const [expandedItems, setExpandedItems] = useState<Set<number>>(new Set());

const toggleItem = (index: number) => {
const newExpandedItems = new Set(expandedItems);
if (newExpandedItems.has(index)) {
newExpandedItems.delete(index);
} else {
newExpandedItems.add(index);
}
setExpandedItems(newExpandedItems);
};

return (
<View
className={mergeClassNames("w-full border border-gray-300 rounded-xl bg-white")}
style={{
shadowColor: "#0A0D125F",
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.25,
shadowRadius: 6,
elevation: 4, // Android
}}
>
{items.map((item, index) => (
<AccordionItemComponent
showDivider={index != items.length - 1}
key={index}
item={item}
isExpanded={expandedItems.has(index)}
onToggle={() => toggleItem(index)}
/>
))}
</View>
);
};

export default Accordion;
50 changes: 50 additions & 0 deletions app/src/components/ListItem/NavigationListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { mergeClassNames } from "@/utils/className";
import { TW_COLORS } from "@/utils/constants";
import { typography } from "@/utils/typography";
import ArrowIcon from "@assets/svg/icon/Arrow";
import CheckMarkIcon from "@assets/svg/icon/check";
import React from "react";
import { TouchableOpacity, View, Text } from "react-native";

interface NavigationListItemProps {
disabled?: false;
icon: JSX.Element;
label: string;
onPress: () => any;
}

export default function NavigationListItem({ disabled, onPress, icon, label }: NavigationListItemProps) {
return (
<TouchableOpacity
disabled={disabled}
onPress={onPress}
className={mergeClassNames("flex-row items-center px-4 py-6 mb-3 bg-white rounded-xl border border-gray-300", disabled ? "bg-success-bg" : "")}
>
{/* Left Icon */}
<View
className={`
bg-cnam-cyan-50-lighten-90
rounded-full p-2 border w-8 h-8 items-center justify-center`}
style={{
borderColor: disabled ? TW_COLORS.SUCCESS.TEXT : TW_COLORS.CNAM_PRIMARY_800,
}}
>
{React.cloneElement(icon, {
color: disabled ? TW_COLORS.SUCCESS.TEXT : TW_COLORS.CNAM_PRIMARY_800,
width: 16,
height: 16,
})}
</View>

{/* Text */}
<Text
className={mergeClassNames(`flex-1 ml-4 ${typography.textMdMedium} text-cnam-primary-950`, disabled ? "line-through text-mood-text-4" : "")}
>
{label}
</Text>

{/* Right Arrow */}
<View className="text-gray-400">{disabled ? <CheckMarkIcon color={TW_COLORS.SUCCESS.TEXT} /> : <ArrowIcon />}</View>
</TouchableOpacity>
);
}
2 changes: 1 addition & 1 deletion app/src/components/drawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default ({ navigation, visible, onClick }) => {
<Text style={styles.title}>Jardin Mental</Text>
<DrawerItem badge={badgeNotesVersionVisible} title="Nouveautés" path="news" navigation={navigation} onClick={onClick} icon={<Star />} />
<Separator />
<DrawerItem title="Présentation" path="presentation" navigation={navigation} onClick={onClick} icon={<StickerSquare />} />
<DrawerItem title="Comment ça marche ?" path="faq" navigation={navigation} onClick={onClick} icon={<StickerSquare />} />
<DrawerItem title="Recommander Jardin&nbsp;Mental" onClick={recommendApp} icon={<Share />} />
<DrawerItem title="Parler à quelqu'un et s'informer" path="infos" navigation={navigation} onClick={onClick} icon={<Phone />} />
<DrawerItem title="Nous contacter" path="contact" navigation={navigation} onClick={onClick} icon={<MessageTextCircle />} />
Expand Down
4 changes: 4 additions & 0 deletions app/src/navigation/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ import { StatusBarProvider, useStatusBarInternal } from "../context/StatusBarCon
import { TW_COLORS } from "@/utils/constants";
import SurveyV1 from "../scenes/survey/daySurvey";
import SurveySuccessScreen from "../scenes/survey/SurveySuccessScreen";
import FaqMainScreen from "@/scenes/faq/FaqMainScreen";
import FaqDetailScreen from "@/scenes/faq/FaqDetailScreen";

const Stack = createStackNavigator();

Expand Down Expand Up @@ -218,6 +220,8 @@ class Router extends React.Component<RouterProps> {
}}
>
<Stack.Screen name="presentation" component={Presentation} />
<Stack.Screen name="faq" component={FaqMainScreen} />
<Stack.Screen name="faq-detail" component={FaqDetailScreen} />
<Stack.Screen name="day-survey" component={SurveyV1} />
<Stack.Screen name="day-survey-v2" component={SurveyNavigator} />
<Stack.Screen name="survey-success" component={SurveySuccessScreen} />
Expand Down
Loading
Loading