newcandies 0.1.26 → 0.1.28
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/expo-router/cozynotes/src/app/+not-found.tsx +32 -0
- package/templates/app-briefs/expo-router/cozynotes/src/components/screens/home/note-card.tsx +13 -18
- package/templates/app-briefs/expo-router/cozynotes/src/components/ui/back-button.tsx +2 -2
- package/templates/app-briefs/expo-router/flourish/src/app/_layout.tsx +3 -3
- package/templates/app-briefs/expo-router/flourish/src/app/index.tsx +12 -0
- package/templates/app-briefs/expo-router/flourish/src/app/(tabs)/_layout.tsx +0 -71
- package/templates/app-briefs/expo-router/flourish/src/app/(tabs)/explore.tsx +0 -24
- package/templates/app-briefs/expo-router/flourish/src/app/(tabs)/index.tsx +0 -102
- package/templates/app-briefs/expo-router/flourish/src/app/(tabs)/profile.tsx +0 -25
- package/templates/app-briefs/expo-router/flourish/src/app/(tabs)/search.tsx +0 -24
- package/templates/app-briefs/expo-router/flourish/src/app/plant/[id].tsx +0 -48
package/package.json
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Ionicons } from '@expo/vector-icons';
|
|
2
|
+
import { Link, Stack } from 'expo-router';
|
|
3
|
+
import { Pressable, Text, View } from 'react-native';
|
|
4
|
+
import Screen from '~/components/ui/screen';
|
|
5
|
+
import Squircle from '~/components/ui/squircle';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export default function NotFoundScreen() {
|
|
10
|
+
return (
|
|
11
|
+
<Screen>
|
|
12
|
+
<Stack.Screen options={{ title: 'Not Found', headerShown: false }} />
|
|
13
|
+
<View className="flex-1 items-center justify-center px-8">
|
|
14
|
+
<Ionicons name="alert-circle-outline" size={80} color="black" />
|
|
15
|
+
<Text className="mt-6 text-2xl font-bold text-foreground">Page Not Found</Text>
|
|
16
|
+
<Text className="mt-2 text-center text-muted-foreground">
|
|
17
|
+
{"The page you're looking for doesn't exist."}
|
|
18
|
+
</Text>
|
|
19
|
+
<Link href="/" asChild>
|
|
20
|
+
<Pressable className="mt-8">
|
|
21
|
+
<Squircle
|
|
22
|
+
cornerSmoothing={1}
|
|
23
|
+
className="bg-primary px-6 py-3"
|
|
24
|
+
style={{ borderRadius: 14 }}>
|
|
25
|
+
<Text className="font-semibold text-primary-foreground">Go to Home</Text>
|
|
26
|
+
</Squircle>
|
|
27
|
+
</Pressable>
|
|
28
|
+
</Link>
|
|
29
|
+
</View>
|
|
30
|
+
</Screen>
|
|
31
|
+
);
|
|
32
|
+
}
|
package/templates/app-briefs/expo-router/cozynotes/src/components/screens/home/note-card.tsx
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { Ionicons } from '@expo/vector-icons';
|
|
2
2
|
import { Link } from 'expo-router';
|
|
3
3
|
import { Pressable, View } from 'react-native';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
5
|
|
|
5
6
|
import Squircle from '~/components/ui/squircle';
|
|
6
7
|
import Text from '~/components/ui/text';
|
|
7
|
-
import { Note } from '~/lib/constants';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get the rotation for the note card
|
|
12
|
+
*/
|
|
10
13
|
const getRotation = (index: number) => {
|
|
11
14
|
const rotations = [-4, 3, -2, 5, -3, 2, -5, 4];
|
|
12
15
|
return rotations[index % rotations.length];
|
|
13
|
-
};
|
|
16
|
+
};
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Get the offset for the note card
|
|
20
|
+
*/
|
|
16
21
|
const getOffset = (index: number) => {
|
|
17
22
|
const offsets = [-50, 60, -40, 70, -55, 50, -35, 65];
|
|
18
23
|
return offsets[index % offsets.length];
|
|
@@ -25,33 +30,23 @@ const NoteCard = ({ note, index }: { note: Note; index: number }) => {
|
|
|
25
30
|
return (
|
|
26
31
|
<Link href={{ pathname: '/note/[id]', params: { id: note.id } }} asChild>
|
|
27
32
|
<Pressable
|
|
33
|
+
className={twMerge('-mb-[60px] self-center')}
|
|
28
34
|
style={{
|
|
29
|
-
marginBottom: -60,
|
|
30
|
-
alignSelf: 'center',
|
|
31
35
|
marginLeft: offsetX,
|
|
32
36
|
transform: [{ rotate: `${rotation}deg` }],
|
|
33
37
|
zIndex: index,
|
|
34
38
|
}}>
|
|
35
39
|
<Squircle
|
|
36
40
|
cornerSmoothing={1}
|
|
37
|
-
className="bg-card"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
height: 324,
|
|
41
|
-
borderRadius: 24,
|
|
42
|
-
padding: 20,
|
|
43
|
-
}}>
|
|
44
|
-
{/* Menu dots */}
|
|
45
|
-
<View style={{ position: 'absolute', top: 16, right: 16 }}>
|
|
46
|
-
<Ionicons name="ellipsis-horizontal" size={18} color="var(--color-muted-foreground)" />
|
|
41
|
+
className="h-80 w-60 rounded-3xl bg-card p-5">
|
|
42
|
+
<View className="absolute right-4 top-4">
|
|
43
|
+
<Ionicons name="ellipsis-horizontal" size={18} color="black" />
|
|
47
44
|
</View>
|
|
48
45
|
|
|
49
|
-
{/* Title */}
|
|
50
46
|
<Text variant="subtitle" className="mb-2 mr-10" numberOfLines={2}>
|
|
51
47
|
{note.title}
|
|
52
48
|
</Text>
|
|
53
49
|
|
|
54
|
-
{/* Content */}
|
|
55
50
|
<Text variant="note" className="opacity-90" numberOfLines={10}>
|
|
56
51
|
{note.content}
|
|
57
52
|
</Text>
|
|
@@ -13,8 +13,8 @@ const BackButton = ({ icon = 'chevron-back' }: BackButtonProps) => {
|
|
|
13
13
|
<Pressable onPress={() => router.back()}>
|
|
14
14
|
<Squircle
|
|
15
15
|
cornerSmoothing={1}
|
|
16
|
-
className="size-12 items-center justify-center bg-card rounded-
|
|
17
|
-
<Ionicons name={icon} size={26} color="
|
|
16
|
+
className="size-12 items-center justify-center bg-card rounded-xl">
|
|
17
|
+
<Ionicons name={icon} size={26} color="black" />
|
|
18
18
|
</Squircle>
|
|
19
19
|
</Pressable>
|
|
20
20
|
);
|
|
@@ -13,9 +13,9 @@ export default function RootLayout() {
|
|
|
13
13
|
<KeyboardProvider>
|
|
14
14
|
<BottomSheetModalProvider>
|
|
15
15
|
<Stack>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
<Stack>
|
|
17
|
+
<Stack.Screen name="index" />
|
|
18
|
+
</Stack>
|
|
19
19
|
<Toaster />
|
|
20
20
|
</BottomSheetModalProvider>
|
|
21
21
|
</KeyboardProvider>
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import IonIcons from "@expo/vector-icons/Ionicons";
|
|
2
|
-
import { Tabs } from "expo-router";
|
|
3
|
-
import { useCSSVariable } from "uniwind";
|
|
4
|
-
|
|
5
|
-
function TabBarIcon(props: {
|
|
6
|
-
name: React.ComponentProps<typeof IonIcons>["name"];
|
|
7
|
-
color: string;
|
|
8
|
-
}) {
|
|
9
|
-
return <IonIcons size={28} style={{ marginBottom: -4 }} {...props} />;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default function TabLayout() {
|
|
13
|
-
const backgroundColor = useCSSVariable("--color-muted") as string;
|
|
14
|
-
const primaryColor = useCSSVariable("--color-primary") as string;
|
|
15
|
-
const tabBarActiveTintColor = useCSSVariable(
|
|
16
|
-
"--color-muted-foreground"
|
|
17
|
-
) as string;
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<Tabs
|
|
21
|
-
screenOptions={{
|
|
22
|
-
headerShown: false,
|
|
23
|
-
tabBarActiveTintColor: primaryColor,
|
|
24
|
-
tabBarInactiveTintColor: tabBarActiveTintColor,
|
|
25
|
-
tabBarStyle: {
|
|
26
|
-
backgroundColor,
|
|
27
|
-
},
|
|
28
|
-
}}
|
|
29
|
-
>
|
|
30
|
-
<Tabs.Screen
|
|
31
|
-
name="index"
|
|
32
|
-
options={{
|
|
33
|
-
title: "Home",
|
|
34
|
-
headerShown: false,
|
|
35
|
-
tabBarShowLabel: false,
|
|
36
|
-
tabBarIcon: ({ color }) => (
|
|
37
|
-
<TabBarIcon name="partly-sunny" color={color} />
|
|
38
|
-
),
|
|
39
|
-
}}
|
|
40
|
-
/>
|
|
41
|
-
<Tabs.Screen
|
|
42
|
-
name="explore"
|
|
43
|
-
options={{
|
|
44
|
-
title: "Explore",
|
|
45
|
-
headerShown: false,
|
|
46
|
-
tabBarShowLabel: false,
|
|
47
|
-
tabBarIcon: ({ color }) => <TabBarIcon name="grid" color={color} />,
|
|
48
|
-
}}
|
|
49
|
-
/>
|
|
50
|
-
<Tabs.Screen
|
|
51
|
-
name="search"
|
|
52
|
-
options={{
|
|
53
|
-
title: "Search",
|
|
54
|
-
headerShown: false,
|
|
55
|
-
tabBarShowLabel: false,
|
|
56
|
-
tabBarIcon: ({ color }) => <TabBarIcon name="search" color={color} />,
|
|
57
|
-
}}
|
|
58
|
-
/>
|
|
59
|
-
<Tabs.Screen
|
|
60
|
-
name="profile"
|
|
61
|
-
options={{
|
|
62
|
-
title: "Profile",
|
|
63
|
-
headerShown: false,
|
|
64
|
-
tabBarShowLabel: false,
|
|
65
|
-
tabBarIcon: ({ color }) => <TabBarIcon name="person" color={color} />,
|
|
66
|
-
}}
|
|
67
|
-
/>
|
|
68
|
-
</Tabs>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { View } from "react-native";
|
|
2
|
-
import { Screen } from "~/components/ui/screen";
|
|
3
|
-
import Text from "~/components/ui/text";
|
|
4
|
-
|
|
5
|
-
export default function Explore() {
|
|
6
|
-
// TODO: Implement the Explore screen
|
|
7
|
-
// - Add category filters (Indoor, Outdoor, Low Water, Pet Safe, Beginner)
|
|
8
|
-
// - Display plants in a vertical list with larger cards
|
|
9
|
-
// - Navigate to plant detail on press
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Screen>
|
|
13
|
-
<View className="px-5 pt-4 pb-4">
|
|
14
|
-
<Text variant="display" className="text-primary">
|
|
15
|
-
Explore
|
|
16
|
-
</Text>
|
|
17
|
-
<Text className="text-muted-foreground mt-2">
|
|
18
|
-
Build this screen to browse plants by category
|
|
19
|
-
</Text>
|
|
20
|
-
</View>
|
|
21
|
-
</Screen>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { View, Image, Pressable, FlatList } from "react-native";
|
|
2
|
-
import { Screen } from "~/components/ui/screen";
|
|
3
|
-
import Text from "~/components/ui/text";
|
|
4
|
-
import { Squircle } from "~/components/ui/squircle";
|
|
5
|
-
import { customPlants } from "~/lib/constants";
|
|
6
|
-
import { useRouter } from "expo-router";
|
|
7
|
-
import { format } from "date-fns";
|
|
8
|
-
import { getWeekDays } from "~/lib/utils";
|
|
9
|
-
|
|
10
|
-
const now = new Date();
|
|
11
|
-
const weekDays = getWeekDays(now);
|
|
12
|
-
|
|
13
|
-
const HomeHeader = () => {
|
|
14
|
-
return (
|
|
15
|
-
<View className="px-5 pt-4 pb-4">
|
|
16
|
-
<View className="flex-row justify-between items-start mb-5">
|
|
17
|
-
<View className="flex-row items-center gap-2">
|
|
18
|
-
<Text variant="display" className="text-4xl">{format(now, "EEE")}</Text>
|
|
19
|
-
<View className="w-3 h-3 rounded-full bg-accent" />
|
|
20
|
-
</View>
|
|
21
|
-
|
|
22
|
-
<View className="items-end">
|
|
23
|
-
<Text variant="subtitle">{format(now, "MMMM d")}</Text>
|
|
24
|
-
<Text className="text-lg text-foreground/70">{format(now, "yyyy")}</Text>
|
|
25
|
-
</View>
|
|
26
|
-
</View>
|
|
27
|
-
|
|
28
|
-
<View className="flex-row justify-between">
|
|
29
|
-
{weekDays.map((day, index) => (
|
|
30
|
-
<View key={index} className="items-center">
|
|
31
|
-
{day.isToday ? (
|
|
32
|
-
<Squircle
|
|
33
|
-
className="bg-primary px-2 py-2 items-center rounded-xl"
|
|
34
|
-
cornerSmoothing={1}
|
|
35
|
-
>
|
|
36
|
-
<Text className="text-lg font-bold text-primary-foreground">
|
|
37
|
-
{day.date}
|
|
38
|
-
</Text>
|
|
39
|
-
<Text className="text-xs font-medium text-secondary mt-1">
|
|
40
|
-
{day.day}
|
|
41
|
-
</Text>
|
|
42
|
-
</Squircle>
|
|
43
|
-
) : (
|
|
44
|
-
<View className="px-2 py-2 items-center">
|
|
45
|
-
<Text className="text-lg font-medium text-primary/40">
|
|
46
|
-
{day.date}
|
|
47
|
-
</Text>
|
|
48
|
-
<Text className="text-xs font-medium text-primary/30 mt-1">
|
|
49
|
-
{day.day}
|
|
50
|
-
</Text>
|
|
51
|
-
</View>
|
|
52
|
-
)}
|
|
53
|
-
</View>
|
|
54
|
-
))}
|
|
55
|
-
</View>
|
|
56
|
-
</View>
|
|
57
|
-
);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const PlantCard = ({ item, onPress }: { item: Plant; onPress?: () => void }) => (
|
|
61
|
-
<Pressable onPress={onPress} className="flex-1">
|
|
62
|
-
<Squircle className="bg-primary overflow-hidden rounded-3xl p-2" cornerSmoothing={1}>
|
|
63
|
-
<Squircle className="overflow-hidden rounded-2xl w-full aspect-square" cornerSmoothing={1}>
|
|
64
|
-
<Image source={{ uri: item.coverImg }} className="w-full h-full" resizeMode="cover" />
|
|
65
|
-
</Squircle>
|
|
66
|
-
<View className="px-1 py-2">
|
|
67
|
-
<Text variant="body-secondary" className="text-primary-foreground">{item.name}</Text>
|
|
68
|
-
</View>
|
|
69
|
-
</Squircle>
|
|
70
|
-
</Pressable>
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const ListHeader = () => (
|
|
74
|
-
<>
|
|
75
|
-
<HomeHeader />
|
|
76
|
-
<View className="px-5 pb-4">
|
|
77
|
-
<Text variant="subtitle" className="text-primary">Our Plants</Text>
|
|
78
|
-
</View>
|
|
79
|
-
</>
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
export default function Index() {
|
|
83
|
-
const router = useRouter();
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<Screen>
|
|
87
|
-
<FlatList
|
|
88
|
-
data={customPlants}
|
|
89
|
-
numColumns={2}
|
|
90
|
-
keyExtractor={(item) => item.id}
|
|
91
|
-
renderItem={({ item }) => (
|
|
92
|
-
<PlantCard item={item} onPress={() => router.push(`/plant/${item.id}`)} />
|
|
93
|
-
)}
|
|
94
|
-
ListHeaderComponent={ListHeader}
|
|
95
|
-
columnWrapperClassName="gap-4 px-5"
|
|
96
|
-
contentContainerClassName="gap-4 pb-8"
|
|
97
|
-
showsVerticalScrollIndicator={false}
|
|
98
|
-
/>
|
|
99
|
-
</Screen>
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { View } from "react-native";
|
|
2
|
-
import { Screen } from "~/components/ui/screen";
|
|
3
|
-
import Text from "~/components/ui/text";
|
|
4
|
-
|
|
5
|
-
export default function Profile() {
|
|
6
|
-
// TODO: Implement the Profile screen
|
|
7
|
-
// - Display user avatar and name
|
|
8
|
-
// - Show plant stats (plants owned, waterings)
|
|
9
|
-
// - Add "Currently..." status card
|
|
10
|
-
// - Include Edit Profile button
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<Screen>
|
|
14
|
-
<View className="px-5 pt-4">
|
|
15
|
-
<Text variant="display" className="text-primary">
|
|
16
|
-
Profile
|
|
17
|
-
</Text>
|
|
18
|
-
<Text className="text-muted-foreground mt-2">
|
|
19
|
-
Build this screen to show user profile
|
|
20
|
-
</Text>
|
|
21
|
-
</View>
|
|
22
|
-
</Screen>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { View } from "react-native";
|
|
2
|
-
import { Screen } from "~/components/ui/screen";
|
|
3
|
-
import Text from "~/components/ui/text";
|
|
4
|
-
|
|
5
|
-
export default function Search() {
|
|
6
|
-
// TODO: Implement the Search screen
|
|
7
|
-
// - Add a search input with icon
|
|
8
|
-
// - Filter plants by name as user types
|
|
9
|
-
// - Display matching results
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Screen>
|
|
13
|
-
<View className="px-5 pt-4">
|
|
14
|
-
<Text variant="display" className="text-primary">
|
|
15
|
-
Search
|
|
16
|
-
</Text>
|
|
17
|
-
<Text className="text-muted-foreground mt-2">
|
|
18
|
-
Build this screen to search for plants
|
|
19
|
-
</Text>
|
|
20
|
-
</View>
|
|
21
|
-
</Screen>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { View } from "react-native";
|
|
2
|
-
import { Stack, useLocalSearchParams } from "expo-router";
|
|
3
|
-
import { Screen } from "~/components/ui/screen";
|
|
4
|
-
import Text from "~/components/ui/text";
|
|
5
|
-
import { customPlants } from "~/lib/constants";
|
|
6
|
-
|
|
7
|
-
export default function PlantDetails() {
|
|
8
|
-
const { id } = useLocalSearchParams<{ id: string }>();
|
|
9
|
-
|
|
10
|
-
const plant = customPlants.find((p) => p.id === id);
|
|
11
|
-
|
|
12
|
-
if (!plant) {
|
|
13
|
-
return (
|
|
14
|
-
<>
|
|
15
|
-
<Stack.Screen options={{ headerShown: false }} />
|
|
16
|
-
<Screen className="flex-1 items-center justify-center bg-background">
|
|
17
|
-
<Text>Plant not found</Text>
|
|
18
|
-
</Screen>
|
|
19
|
-
</>
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// TODO: Implement the Plant Details screen
|
|
24
|
-
// - Add back button navigation
|
|
25
|
-
// - Display plant image in a stacked card design
|
|
26
|
-
// - Show plant name and scientific name
|
|
27
|
-
// - Add quick info pills (water needs, light needs)
|
|
28
|
-
// - Display "About this plant" card with description
|
|
29
|
-
// - Show care details (water frequency, growth rate, maintenance)
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<>
|
|
33
|
-
<Stack.Screen options={{ headerShown: false }} />
|
|
34
|
-
<Screen className="flex-1 bg-background">
|
|
35
|
-
<View className="px-5 pt-4">
|
|
36
|
-
<Text variant="display">{plant.name}</Text>
|
|
37
|
-
<Text className="text-muted-foreground mt-1">
|
|
38
|
-
{plant.scientificName}
|
|
39
|
-
</Text>
|
|
40
|
-
<Text className="text-muted-foreground mt-4">
|
|
41
|
-
Build this screen to show plant details
|
|
42
|
-
</Text>
|
|
43
|
-
</View>
|
|
44
|
-
</Screen>
|
|
45
|
-
</>
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|