newcandies 0.1.21 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/app-briefs/react-query/sproutsy/src/api/README.md +3 -0
- package/templates/app-briefs/react-query/sproutsy/src/app/(tabs)/explore.tsx +6 -75
- package/templates/app-briefs/react-query/sproutsy/src/app/(tabs)/index.tsx +7 -38
- package/templates/app-briefs/react-query/sproutsy/src/app/_layout.tsx +7 -9
- package/templates/app-briefs/react-query/sproutsy/src/app/plant/[id].tsx +9 -79
- package/templates/app-briefs/react-query/sproutsy/src/api/api-provider.tsx +0 -15
- package/templates/app-briefs/react-query/sproutsy/src/api/client.ts +0 -8
- package/templates/app-briefs/react-query/sproutsy/src/api/plants/index.ts +0 -18
- package/templates/app-briefs/react-query/sproutsy/src/api/plants/usePlants.ts +0 -46
- package/templates/app-briefs/react-query/sproutsy/src/components/screens/home/home-header.tsx +0 -38
- package/templates/app-briefs/react-query/sproutsy/src/components/screens/shared/item-separator.tsx +0 -7
- package/templates/app-briefs/react-query/sproutsy/src/components/screens/shared/plant-card.tsx +0 -70
- package/templates/app-briefs/react-query/sproutsy/src/components/screens/shared/query-state.tsx +0 -50
package/package.json
CHANGED
|
@@ -1,84 +1,15 @@
|
|
|
1
|
-
import { Ionicons } from "@expo/vector-icons";
|
|
2
|
-
import { FlashList } from "@shopify/flash-list";
|
|
3
|
-
import { useRouter } from "expo-router";
|
|
4
|
-
import { ActivityIndicator, RefreshControl, View } from "react-native";
|
|
5
|
-
import { usePlants } from "~/api/plants/usePlants";
|
|
6
|
-
import ItemSeparator from "~/components/screens/shared/item-separator";
|
|
7
|
-
import PlantCard from "~/components/screens/shared/plant-card";
|
|
8
|
-
import QueryState from "~/components/screens/shared/query-state";
|
|
9
1
|
import { Screen } from "~/components/ui/screen";
|
|
10
2
|
import Text from "~/components/ui/text";
|
|
11
3
|
|
|
12
4
|
export default function Two() {
|
|
13
|
-
const router = useRouter();
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
plants,
|
|
17
|
-
status,
|
|
18
|
-
error,
|
|
19
|
-
fetchNextPage,
|
|
20
|
-
hasNextPage,
|
|
21
|
-
isFetchingNextPage,
|
|
22
|
-
refetch,
|
|
23
|
-
isRefetching,
|
|
24
|
-
} = usePlants({ pageSize: 10 });
|
|
25
|
-
|
|
26
|
-
const renderItem = ({ item }: { item: Plant }) => (
|
|
27
|
-
<PlantCard
|
|
28
|
-
id={item.id}
|
|
29
|
-
name={item.name}
|
|
30
|
-
scientificName={item.scientificName}
|
|
31
|
-
coverImg={item.coverImg}
|
|
32
|
-
maintenance={item.maintenance}
|
|
33
|
-
onPress={() => router.push(`/plant/${item.id}`)}
|
|
34
|
-
/>
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
const onEndReached = () => {
|
|
38
|
-
if (hasNextPage && !isFetchingNextPage) {
|
|
39
|
-
fetchNextPage();
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
if (status === "error") {
|
|
44
|
-
return (
|
|
45
|
-
<QueryState
|
|
46
|
-
isError={true}
|
|
47
|
-
error={
|
|
48
|
-
error instanceof Error ? error : new Error("Failed to load plants")
|
|
49
|
-
}
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
5
|
return (
|
|
55
6
|
<Screen>
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
</
|
|
62
|
-
<FlashList
|
|
63
|
-
data={plants}
|
|
64
|
-
renderItem={renderItem}
|
|
65
|
-
keyExtractor={(item: Plant) => item.id}
|
|
66
|
-
className="px-4"
|
|
67
|
-
showsVerticalScrollIndicator={false}
|
|
68
|
-
ItemSeparatorComponent={ItemSeparator}
|
|
69
|
-
onEndReached={onEndReached}
|
|
70
|
-
onEndReachedThreshold={0.5}
|
|
71
|
-
ListFooterComponent={
|
|
72
|
-
isFetchingNextPage ? (
|
|
73
|
-
<View className="py-4 items-center">
|
|
74
|
-
<ActivityIndicator size="small" />
|
|
75
|
-
</View>
|
|
76
|
-
) : null
|
|
77
|
-
}
|
|
78
|
-
refreshControl={
|
|
79
|
-
<RefreshControl onRefresh={refetch} refreshing={isRefetching} />
|
|
80
|
-
}
|
|
81
|
-
/>
|
|
7
|
+
<Text variant="title" className="px-4">
|
|
8
|
+
Explore tab
|
|
9
|
+
</Text>
|
|
10
|
+
<Text className="px-4 text-base text-muted-foreground">
|
|
11
|
+
Build your infinite list or discovery UI here.
|
|
12
|
+
</Text>
|
|
82
13
|
</Screen>
|
|
83
14
|
);
|
|
84
15
|
}
|
|
@@ -1,46 +1,15 @@
|
|
|
1
|
-
import { FlashList, ListRenderItem } from "@shopify/flash-list";
|
|
2
|
-
import { useQuery } from "@tanstack/react-query";
|
|
3
|
-
import { useRouter } from "expo-router";
|
|
4
|
-
import { getPlants } from "~/api/plants";
|
|
5
|
-
import { HomeHeader } from "~/components/screens/home/home-header";
|
|
6
|
-
import ItemSeparator from "~/components/screens/shared/item-separator";
|
|
7
|
-
import PlantCard from "~/components/screens/shared/plant-card";
|
|
8
|
-
import QueryState from "~/components/screens/shared/query-state";
|
|
9
1
|
import { Screen } from "~/components/ui/screen";
|
|
2
|
+
import Text from "~/components/ui/text";
|
|
10
3
|
|
|
11
4
|
export default function Index() {
|
|
12
|
-
const router = useRouter();
|
|
13
|
-
const { data, isPending, isError, error } = useQuery<PlantsResponse>({
|
|
14
|
-
queryKey: ["plants"],
|
|
15
|
-
queryFn: getPlants,
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const renderItem = ({ item }: { item: Plant }) => (
|
|
19
|
-
<PlantCard
|
|
20
|
-
id={item.id}
|
|
21
|
-
name={item.name}
|
|
22
|
-
scientificName={item.scientificName}
|
|
23
|
-
coverImg={item.coverImg}
|
|
24
|
-
maintenance={item.maintenance}
|
|
25
|
-
onPress={() => router.push(`/plant/${item.id}`)}
|
|
26
|
-
/>
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
if (isPending || isError) {
|
|
30
|
-
return <QueryState isPending={isPending} isError={isError} error={error} />;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
5
|
return (
|
|
34
6
|
<Screen>
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
renderItem={renderItem}
|
|
42
|
-
className="px-4"
|
|
43
|
-
/>
|
|
7
|
+
<Text variant="title" className="px-4">
|
|
8
|
+
Sproutsy Home
|
|
9
|
+
</Text>
|
|
10
|
+
<Text className="px-4 text-base text-muted-foreground">
|
|
11
|
+
Replace this placeholder with your plant feed UI.
|
|
12
|
+
</Text>
|
|
44
13
|
</Screen>
|
|
45
14
|
);
|
|
46
15
|
}
|
|
@@ -4,7 +4,6 @@ import { GestureHandlerRootView } from "react-native-gesture-handler";
|
|
|
4
4
|
import { KeyboardProvider } from "react-native-keyboard-controller";
|
|
5
5
|
import "react-native-reanimated";
|
|
6
6
|
import { Toaster } from "sonner-native";
|
|
7
|
-
import APIProvider from "~/api/api-provider";
|
|
8
7
|
import "../../global.css";
|
|
9
8
|
import { StyleSheet } from "react-native";
|
|
10
9
|
|
|
@@ -12,14 +11,13 @@ export default function RootLayout() {
|
|
|
12
11
|
return (
|
|
13
12
|
<GestureHandlerRootView style={styles.container}>
|
|
14
13
|
<KeyboardProvider>
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</APIProvider>
|
|
14
|
+
<BottomSheetModalProvider>
|
|
15
|
+
{/* TODO: Wrap your API/query providers here */}
|
|
16
|
+
<Stack>
|
|
17
|
+
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
|
18
|
+
</Stack>
|
|
19
|
+
<Toaster />
|
|
20
|
+
</BottomSheetModalProvider>
|
|
23
21
|
</KeyboardProvider>
|
|
24
22
|
</GestureHandlerRootView>
|
|
25
23
|
);
|
|
@@ -1,91 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useQuery } from "@tanstack/react-query";
|
|
3
|
-
import { Stack, useLocalSearchParams, useRouter } from "expo-router";
|
|
4
|
-
import { Image, Pressable, ScrollView, View } from "react-native";
|
|
5
|
-
import { getPlantById } from "~/api/plants";
|
|
6
|
-
import QueryState from "~/components/screens/shared/query-state";
|
|
1
|
+
import { Stack, useLocalSearchParams } from "expo-router";
|
|
7
2
|
import { Screen } from "~/components/ui/screen";
|
|
8
|
-
import { Squircle } from "~/components/ui/squircle";
|
|
9
3
|
import Text from "~/components/ui/text";
|
|
10
4
|
|
|
11
5
|
export default function PlantDetails() {
|
|
12
6
|
const { id } = useLocalSearchParams<{ id: string }>();
|
|
13
|
-
const router = useRouter();
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
data: plant,
|
|
17
|
-
isPending,
|
|
18
|
-
isError,
|
|
19
|
-
error,
|
|
20
|
-
} = useQuery<Plant>({
|
|
21
|
-
queryKey: ["plant", id],
|
|
22
|
-
queryFn: () => getPlantById(id!),
|
|
23
|
-
enabled: !!id,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
if (isPending || isError || !plant) {
|
|
27
|
-
return (
|
|
28
|
-
<QueryState
|
|
29
|
-
isPending={isPending}
|
|
30
|
-
isError={isError || !plant}
|
|
31
|
-
error={error}
|
|
32
|
-
errorMessage="Error"
|
|
33
|
-
/>
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
7
|
|
|
37
8
|
return (
|
|
38
9
|
<>
|
|
39
10
|
<Stack.Screen options={{ headerShown: false }} />
|
|
40
|
-
<Screen className="flex-1
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<Pressable
|
|
49
|
-
onPress={() => router.back()}
|
|
50
|
-
className="absolute top-4 left-4 w-10 h-10 rounded-full bg-white justify-center items-center"
|
|
51
|
-
>
|
|
52
|
-
<Ionicons name="chevron-back" size={24} color={"black"} />
|
|
53
|
-
</Pressable>
|
|
54
|
-
</View>
|
|
55
|
-
|
|
56
|
-
<View className="p-6 bg-primary-foreground">
|
|
57
|
-
<Text variant="display">{plant.name}</Text>
|
|
58
|
-
<Text variant="subtitle" className="text-primary mb-4">
|
|
59
|
-
{plant.scientificName}
|
|
60
|
-
</Text>
|
|
61
|
-
|
|
62
|
-
<Text variant="title" className="text-primary mb-6">
|
|
63
|
-
${(plant.price / 100).toFixed(2)}
|
|
64
|
-
</Text>
|
|
65
|
-
|
|
66
|
-
<View className="mb-6">
|
|
67
|
-
<Text variant="subtitle" className="mb-2">
|
|
68
|
-
About
|
|
69
|
-
</Text>
|
|
70
|
-
<Text className="leading-6">{plant.description}</Text>
|
|
71
|
-
</View>
|
|
72
|
-
|
|
73
|
-
{plant.specialCare && (
|
|
74
|
-
<View className="mb-6">
|
|
75
|
-
<Text variant="subtitle" className="mb-3">
|
|
76
|
-
Special Care
|
|
77
|
-
</Text>
|
|
78
|
-
<Squircle
|
|
79
|
-
cornerSmoothing={1}
|
|
80
|
-
className="bg-white p-6"
|
|
81
|
-
style={{ borderRadius: 16 }}
|
|
82
|
-
>
|
|
83
|
-
<Text className="leading-6">{plant.specialCare}</Text>
|
|
84
|
-
</Squircle>
|
|
85
|
-
</View>
|
|
86
|
-
)}
|
|
87
|
-
</View>
|
|
88
|
-
</ScrollView>
|
|
11
|
+
<Screen className="flex-1 items-center justify-center bg-background px-6">
|
|
12
|
+
<Text variant="title" className="mb-2">
|
|
13
|
+
Plant details
|
|
14
|
+
</Text>
|
|
15
|
+
<Text className="text-center text-muted-foreground">
|
|
16
|
+
Use the ID param ({id ?? "?"}) to fetch the selected plant and display
|
|
17
|
+
its details here.
|
|
18
|
+
</Text>
|
|
89
19
|
</Screen>
|
|
90
20
|
</>
|
|
91
21
|
);
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
3
|
-
import { useTanStackQueryDevTools } from "@rozenite/tanstack-query-plugin";
|
|
4
|
-
|
|
5
|
-
const queryClient = new QueryClient();
|
|
6
|
-
|
|
7
|
-
const APIProvider = ({ children }: { children: ReactNode }) => {
|
|
8
|
-
useTanStackQueryDevTools(queryClient);
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
12
|
-
);
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export default APIProvider;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { client } from "../client";
|
|
2
|
-
|
|
3
|
-
export const getPlants = async () => {
|
|
4
|
-
const response = await client.get("/plants/");
|
|
5
|
-
return response.data;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export const listPlants = async (page: number = 1, pageSize: number = 20) => {
|
|
9
|
-
const response = await client.get("/plants/", {
|
|
10
|
-
params: { page, limit:pageSize },
|
|
11
|
-
});
|
|
12
|
-
return response.data;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const getPlantById = async (id: string) => {
|
|
16
|
-
const response = await client.get(`/plants/${id}`);
|
|
17
|
-
return response.data.data;
|
|
18
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { useInfiniteQuery } from "@tanstack/react-query";
|
|
2
|
-
import { listPlants } from ".";
|
|
3
|
-
|
|
4
|
-
interface UsePlantsOptions {
|
|
5
|
-
pageSize?: number;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const usePlants = (options: UsePlantsOptions = {}) => {
|
|
9
|
-
const { pageSize = 10 } = options;
|
|
10
|
-
|
|
11
|
-
const {
|
|
12
|
-
data,
|
|
13
|
-
fetchNextPage,
|
|
14
|
-
hasNextPage,
|
|
15
|
-
isFetchingNextPage,
|
|
16
|
-
refetch,
|
|
17
|
-
isRefetching,
|
|
18
|
-
isLoading,
|
|
19
|
-
status,
|
|
20
|
-
error,
|
|
21
|
-
} = useInfiniteQuery({
|
|
22
|
-
queryKey: ["plants-list", pageSize],
|
|
23
|
-
queryFn: ({ pageParam = 1 }) => listPlants(pageParam, pageSize),
|
|
24
|
-
initialPageParam: 1,
|
|
25
|
-
getNextPageParam: (lastPage: PlantsResponse, _, lastPageParam) => {
|
|
26
|
-
if (lastPage.metadata.currentPage >= lastPage.metadata.lastPage) {
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
return lastPageParam + 1;
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const plants: Plant[] = data?.pages.flatMap((page) => page.plants) ?? [];
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
plants,
|
|
37
|
-
status,
|
|
38
|
-
error,
|
|
39
|
-
isLoading,
|
|
40
|
-
refetch,
|
|
41
|
-
isRefetching,
|
|
42
|
-
isFetchingNextPage,
|
|
43
|
-
hasNextPage,
|
|
44
|
-
fetchNextPage,
|
|
45
|
-
};
|
|
46
|
-
};
|
package/templates/app-briefs/react-query/sproutsy/src/components/screens/home/home-header.tsx
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Image, View } from "react-native";
|
|
2
|
-
import Text from "~/components/ui/text";
|
|
3
|
-
|
|
4
|
-
const getDate = () => {
|
|
5
|
-
const date = new Date();
|
|
6
|
-
return {
|
|
7
|
-
weekday: date.toLocaleString("en-US", { weekday: "long" }),
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const HomeHeader = () => {
|
|
12
|
-
const { weekday } = getDate();
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<View className="px-6 pt-2">
|
|
16
|
-
<View className="flex-row items-center justify-between mb-6">
|
|
17
|
-
<View className="flex-row items-center gap-3">
|
|
18
|
-
<Image
|
|
19
|
-
source={require("assets/images/sproutsies-logo.png")}
|
|
20
|
-
style={{ width: 24, height: 24 }}
|
|
21
|
-
resizeMode="contain"
|
|
22
|
-
/>
|
|
23
|
-
<Image
|
|
24
|
-
source={require("assets/images/sproutsy-main-logo.png")}
|
|
25
|
-
style={{ height: 24, width: 124 }}
|
|
26
|
-
resizeMode="contain"
|
|
27
|
-
/>
|
|
28
|
-
</View>
|
|
29
|
-
<View className="items-end">
|
|
30
|
-
<Text variant="caption-primary" className="text-muted-foreground">
|
|
31
|
-
Happy
|
|
32
|
-
</Text>
|
|
33
|
-
<Text variant="subtitle-primary">{weekday}</Text>
|
|
34
|
-
</View>
|
|
35
|
-
</View>
|
|
36
|
-
</View>
|
|
37
|
-
);
|
|
38
|
-
};
|
package/templates/app-briefs/react-query/sproutsy/src/components/screens/shared/plant-card.tsx
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Ionicons } from "@expo/vector-icons";
|
|
2
|
-
import { Image, Pressable, View } from "react-native";
|
|
3
|
-
import { Squircle } from "~/components/ui/squircle";
|
|
4
|
-
import Text from "~/components/ui/text";
|
|
5
|
-
|
|
6
|
-
type PlantCardProps = {
|
|
7
|
-
id: string;
|
|
8
|
-
name: string;
|
|
9
|
-
scientificName: string;
|
|
10
|
-
coverImg: string;
|
|
11
|
-
maintenance?: string;
|
|
12
|
-
onPress?: () => void;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const PlantCard = ({
|
|
16
|
-
name,
|
|
17
|
-
scientificName,
|
|
18
|
-
coverImg,
|
|
19
|
-
maintenance,
|
|
20
|
-
onPress,
|
|
21
|
-
}: PlantCardProps) => {
|
|
22
|
-
return (
|
|
23
|
-
<Pressable onPress={onPress}>
|
|
24
|
-
<Squircle cornerSmoothing={1} className="overflow-hidden rounded-3xl">
|
|
25
|
-
<View className="bg-background">
|
|
26
|
-
<Image
|
|
27
|
-
source={{ uri: coverImg }}
|
|
28
|
-
className="h-[356] w-full"
|
|
29
|
-
resizeMode="cover"
|
|
30
|
-
/>
|
|
31
|
-
|
|
32
|
-
<View className="flex-1 bg-card p-4 justify-end">
|
|
33
|
-
<Text variant="subtitle" className="text-card-foreground mb-3">
|
|
34
|
-
{name}
|
|
35
|
-
</Text>
|
|
36
|
-
<View className="flex-row justify-between items-center gap-2">
|
|
37
|
-
<View className="flex-1 flex-row items-center gap-2">
|
|
38
|
-
<View className="w-5 h-5 bg-overlay items-center justify-center rounded-full">
|
|
39
|
-
<Ionicons name="flask" size={12} color="white" />
|
|
40
|
-
</View>
|
|
41
|
-
<View className="flex-1">
|
|
42
|
-
<Text variant="caption">Scientific</Text>
|
|
43
|
-
<Text variant="caption" numberOfLines={1}>
|
|
44
|
-
{scientificName}
|
|
45
|
-
</Text>
|
|
46
|
-
</View>
|
|
47
|
-
</View>
|
|
48
|
-
{maintenance && (
|
|
49
|
-
<Squircle
|
|
50
|
-
cornerSmoothing={1}
|
|
51
|
-
className="bg-overlay-muted px-3 py-1 flex-row items-center gap-2 rounded-xl"
|
|
52
|
-
>
|
|
53
|
-
<Ionicons name="shield-checkmark" size={12} color="white" />
|
|
54
|
-
<View>
|
|
55
|
-
<Text variant="caption">Care</Text>
|
|
56
|
-
<Text className="text-card-foreground" variant="caption-primary">
|
|
57
|
-
{maintenance.toLowerCase()}
|
|
58
|
-
</Text>
|
|
59
|
-
</View>
|
|
60
|
-
</Squircle>
|
|
61
|
-
)}
|
|
62
|
-
</View>
|
|
63
|
-
</View>
|
|
64
|
-
</View>
|
|
65
|
-
</Squircle>
|
|
66
|
-
</Pressable>
|
|
67
|
-
);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export default PlantCard;
|
package/templates/app-briefs/react-query/sproutsy/src/components/screens/shared/query-state.tsx
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { View, ActivityIndicator } from "react-native";
|
|
2
|
-
import { Stack } from "expo-router";
|
|
3
|
-
import { Screen } from "~/components/ui/screen";
|
|
4
|
-
import Text from "~/components/ui/text";
|
|
5
|
-
|
|
6
|
-
interface QueryStateProps {
|
|
7
|
-
isPending?: boolean;
|
|
8
|
-
isError?: boolean;
|
|
9
|
-
error?: Error | null;
|
|
10
|
-
errorMessage?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const QueryState = ({
|
|
14
|
-
isPending,
|
|
15
|
-
isError,
|
|
16
|
-
error,
|
|
17
|
-
errorMessage = "Something went wrong",
|
|
18
|
-
}: QueryStateProps) => {
|
|
19
|
-
if (isPending) {
|
|
20
|
-
return (
|
|
21
|
-
<>
|
|
22
|
-
<Stack.Screen options={{ headerShown: false }} />
|
|
23
|
-
<Screen>
|
|
24
|
-
<View className="flex-1 items-center justify-center">
|
|
25
|
-
<ActivityIndicator size="large" />
|
|
26
|
-
</View>
|
|
27
|
-
</Screen>
|
|
28
|
-
</>
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (isError) {
|
|
33
|
-
return (
|
|
34
|
-
<>
|
|
35
|
-
<Stack.Screen options={{ headerShown: false }} />
|
|
36
|
-
<Screen>
|
|
37
|
-
<View className="flex-1 items-center justify-center">
|
|
38
|
-
<Text className="text-lg font-medium text-red-500">
|
|
39
|
-
{error?.message || errorMessage}
|
|
40
|
-
</Text>
|
|
41
|
-
</View>
|
|
42
|
-
</Screen>
|
|
43
|
-
</>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return null;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export default QueryState;
|