Skip to content

Commit 26d1761

Browse files
committed
ft: Book mark article and allow user to filter from default categories provided.
1 parent 8f18d7a commit 26d1761

File tree

12 files changed

+469
-98
lines changed

12 files changed

+469
-98
lines changed

app/(app)/ActionMenu/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export default function Index() {
168168
<Image
169169
style={{ width: "100%", height: "100%", borderRadius: 100 }}
170170
source={{
171-
uri:authType !== "email" && authType !== "apple"
171+
uri:authType && authType !== "apple"
172172
? otherAuthImageUrl
173173
: `${CDNURL + userData?.id + "/" + profilePhoto}`,
174174
}}

app/(app)/Articles/ArticleSeeAll.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { ThemeContext } from "@/ctx/ThemeContext";
1919

2020
export default function SeeAllArticles() {
2121
const { theme, changeTheme } = useContext(ThemeContext);
22+
const [selectedCategory, setSelectedCategory] = useState("Newest");
23+
const categories = ["all", "Health", "Covid", "Lifestyle", "News"]; // Example categories
2224

2325
return (
2426
<SafeAreaView
@@ -93,10 +95,6 @@ export default function SeeAllArticles() {
9395
</TouchableOpacity>
9496
</View>
9597
</View>
96-
<View style={{ padding: 5 }}>
97-
<FieldComponent />
98-
</View>
99-
10098
<ScrollView
10199
style={{ marginTop: 10 }}
102100
showsVerticalScrollIndicator={false}
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
import React, { ReactNode, useContext, useEffect, useState } from "react";
2+
import {
3+
View,
4+
Text,
5+
SafeAreaView,
6+
TouchableOpacity,
7+
Pressable,
8+
FlatList,
9+
Image,
10+
} from "react-native";
11+
import { router } from "expo-router";
12+
import FieldComponent from "@/components/FieldComponent";
13+
import {
14+
Ionicons,
15+
MaterialCommunityIcons,
16+
MaterialIcons,
17+
} from "@expo/vector-icons";
18+
import { ThemeContext } from "@/ctx/ThemeContext";
19+
import { AuthContext } from "@/ctx/AuthContext";
20+
import { fetchPatientData } from "@/utils/LoggedInUser";
21+
import { supabase } from "@/lib/supabase";
22+
import Typography from "@/constants/Typography";
23+
import { ActivityIndicator } from "react-native";
24+
25+
interface Article {
26+
created_at: ReactNode;
27+
id: string;
28+
title: string;
29+
category: string;
30+
image: string;
31+
description: string;
32+
}
33+
34+
type FetchError = string | null;
35+
type FetchArticle = Article[] | null;
36+
37+
38+
export default function BookMarkedArticles() {
39+
const { theme} = useContext(ThemeContext);
40+
const { userId, email } = useContext(AuthContext);
41+
const [patientData, setPatientData] = useState([]);
42+
const [fetchError, setFetchError] = useState<FetchError>(null);
43+
const [fetchArticle, setFetchArticle] = useState<FetchArticle>(null);
44+
const [IsLoading, setIsLoading] = useState(true);
45+
const [selectedCategory, setSelectedCategory] = useState('All');
46+
const categories = ['All', 'Health', 'Covid-19', 'Lifestyle', 'Medical'];
47+
48+
useEffect(() => {
49+
if (userId) {
50+
fetchPatientData(userId, setPatientData);
51+
}
52+
}, [userId]);
53+
54+
useEffect(() => {
55+
const fetchArticles = async () => {
56+
try {
57+
if (!patientData[0]?.id) {
58+
setIsLoading(false);
59+
setFetchArticle(null);
60+
setFetchError("User ID not available");
61+
return;
62+
}
63+
64+
let response;
65+
if (selectedCategory === 'All') {
66+
response = await supabase.from('marked_articles').select('Articles(*)');
67+
} else {
68+
response = await supabase
69+
.from('marked_articles')
70+
.select('Articles(*)')
71+
.eq('user_id', patientData[0]?.id)
72+
.eq('category', selectedCategory);
73+
}
74+
75+
const { data, error } = response;
76+
77+
if (error) {
78+
setFetchError("Could not fetch articles");
79+
setFetchArticle(null);
80+
} else {
81+
setIsLoading(false);
82+
setFetchArticle(data);
83+
setFetchError(null);
84+
}
85+
} catch (error) {
86+
console.error('Error fetching articles:', error.message);
87+
setFetchError("Could not fetch articles");
88+
setFetchArticle(null);
89+
}
90+
};
91+
92+
fetchArticles();
93+
}, [selectedCategory, patientData]);
94+
95+
96+
const handleArticlePress = (articleId: string) => {
97+
router.push({
98+
pathname: "(app)/Articles/[ArticleDetails]",
99+
params: { id: articleId },
100+
});
101+
};
102+
103+
104+
105+
return (
106+
<SafeAreaView
107+
style={{
108+
paddingTop: 40,
109+
backgroundColor: theme === "light" ? "#FFFFFF" : "#181A20",
110+
height: "100%",
111+
}}
112+
>
113+
<View>
114+
<View
115+
style={{
116+
display: "flex",
117+
flexDirection: "row",
118+
justifyContent: "space-between",
119+
}}
120+
>
121+
<View
122+
style={{
123+
display: "flex",
124+
flexDirection: "row",
125+
gap: 15,
126+
padding: 15,
127+
}}
128+
>
129+
<Pressable
130+
onPress={() => router.back()}
131+
style={{
132+
paddingTop: 5,
133+
}}
134+
>
135+
<MaterialIcons
136+
name="arrow-back"
137+
size={23}
138+
style={{
139+
alignSelf: "center",
140+
color: theme === "light" ? "#212121" : "#FFFFFF",
141+
}}
142+
/>
143+
</Pressable>
144+
<Text
145+
style={{
146+
fontSize: 24,
147+
color: theme === "light" ? "#212121" : "#FFFFFF",
148+
}}
149+
>
150+
Book Marked
151+
</Text>
152+
</View>
153+
<View
154+
style={{
155+
display: "flex",
156+
flexDirection: "row",
157+
gap: 15,
158+
padding: 15,
159+
}}
160+
>
161+
<TouchableOpacity>
162+
<Ionicons
163+
name="search-outline"
164+
size={24}
165+
style={{ color: theme === "light" ? "#212121" : "#FFFFFF" }}
166+
/>
167+
</TouchableOpacity>
168+
169+
<TouchableOpacity>
170+
<MaterialCommunityIcons
171+
name="dots-horizontal-circle-outline"
172+
size={24}
173+
style={{ color: theme === "light" ? "#212121" : "#FFFFFF" }}
174+
/>
175+
</TouchableOpacity>
176+
</View>
177+
</View>
178+
179+
<View>
180+
<View style={{ padding: 5 }}>
181+
<FieldComponent
182+
categories={categories}
183+
selectedCategory={selectedCategory}
184+
onSelectCategory={setSelectedCategory}
185+
/>
186+
</View>
187+
</View>
188+
189+
<View
190+
style={{ marginTop: 10 }}
191+
>
192+
{IsLoading ? (
193+
<ActivityIndicator
194+
color="#246BFD"
195+
size="large"
196+
style={{ marginLeft: "5%", marginTop: "80%" }}
197+
/>
198+
) : (
199+
<View style={{ padding: 10, gap: 16 }}>
200+
{fetchError && <Text>{fetchError}</Text>}
201+
202+
{fetchArticle &&
203+
<FlatList
204+
data={fetchArticle}
205+
renderItem={({ item }) => (
206+
<TouchableOpacity
207+
key={item.id}
208+
onPress={() => handleArticlePress(item.Articles?.id)}
209+
style={{ flexDirection: "row", gap: 16, marginBottom: 10 }}
210+
>
211+
<Image
212+
style={{ height: 120, width: 120, borderRadius: 20 }}
213+
source={{ uri: item?.Articles?.image }}
214+
/>
215+
<View
216+
style={{
217+
flex: 1,
218+
justifyContent: "space-between",
219+
paddingRight: 15,
220+
}}
221+
>
222+
<Text
223+
style={[
224+
Typography.medium.xSmall,
225+
{
226+
color: theme === "light" ? "#424242" : "#FFFFFF",
227+
fontSize: 10,
228+
},
229+
]}
230+
>
231+
{item?.Articles?.created_at}
232+
</Text>
233+
<Text
234+
style={[
235+
Typography.bold.large,
236+
{
237+
fontSize: 16,
238+
color: theme === "light" ? "#212121" : "#FFFFFF",
239+
},
240+
]}
241+
numberOfLines={3}
242+
>
243+
{item?.Articles?.title}
244+
</Text>
245+
<Text
246+
style={{
247+
color: theme === "light" ? "#246BFD" : "#246BFD",
248+
fontSize: 10,
249+
backgroundColor: "rgba(36, 107, 253, 0.08)",
250+
borderRadius: 6,
251+
height: 24,
252+
width: 59,
253+
textAlign: "center",
254+
padding: 5,
255+
marginTop: 10,
256+
}}
257+
>
258+
{item?.Articles?.category}
259+
</Text>
260+
</View>
261+
</TouchableOpacity>
262+
)}
263+
keyExtractor={(item, index) => item?.Articles?.id}
264+
/>
265+
}
266+
</View>
267+
)}
268+
</View>
269+
</View>
270+
</SafeAreaView>
271+
);
272+
}

0 commit comments

Comments
 (0)