newcandies 0.1.32 → 0.1.34

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.
Files changed (62) hide show
  1. package/dist/index.js +17 -9
  2. package/package.json +1 -1
  3. package/templates/boilerplate/holidia/.vscode/settings.json +1 -0
  4. package/templates/boilerplate/holidia/.vscode/snippets.code-snippets +144 -0
  5. package/templates/boilerplate/holidia/.zed/settings.json +7 -0
  6. package/templates/boilerplate/holidia/README.md +25 -2
  7. package/templates/boilerplate/holidia/app/(tabs)/_layout.tsx +0 -0
  8. package/templates/boilerplate/holidia/app/(tabs)/bookings.tsx +0 -0
  9. package/templates/boilerplate/holidia/app/(tabs)/favorite.tsx +0 -0
  10. package/templates/boilerplate/holidia/app/(tabs)/index.tsx +0 -0
  11. package/templates/boilerplate/holidia/app/(tabs)/profile.tsx +0 -0
  12. package/templates/boilerplate/holidia/app/+html.tsx +46 -0
  13. package/templates/boilerplate/holidia/app/+not-found.tsx +23 -0
  14. package/templates/boilerplate/holidia/app/_layout.tsx +0 -0
  15. package/templates/boilerplate/holidia/app/checkout.tsx +0 -0
  16. package/templates/boilerplate/holidia/app/login.tsx +0 -0
  17. package/templates/boilerplate/holidia/app/payment-successful.tsx +0 -0
  18. package/templates/boilerplate/holidia/app/properties/[id].tsx +264 -0
  19. package/templates/boilerplate/holidia/app/search.tsx +0 -0
  20. package/templates/boilerplate/holidia/app/signup.tsx +0 -0
  21. package/templates/boilerplate/holidia/app/welcome.tsx +0 -0
  22. package/templates/boilerplate/holidia/app-env.d.ts +2 -0
  23. package/templates/boilerplate/holidia/app.json +66 -0
  24. package/templates/boilerplate/holidia/assets/adaptive-icon.png +0 -0
  25. package/templates/boilerplate/holidia/assets/favicon.png +0 -0
  26. package/templates/boilerplate/holidia/assets/icon.png +0 -0
  27. package/templates/boilerplate/holidia/assets/logo.png +0 -0
  28. package/templates/boilerplate/holidia/assets/logo.svg +46 -0
  29. package/templates/boilerplate/holidia/assets/splash.png +0 -0
  30. package/templates/boilerplate/holidia/babel.config.js +5 -6
  31. package/templates/boilerplate/holidia/cesconfig.json +35 -0
  32. package/templates/boilerplate/holidia/components/container.tsx +11 -0
  33. package/templates/boilerplate/holidia/core/api/api-provider.tsx +0 -0
  34. package/templates/boilerplate/holidia/core/api/client.ts +0 -0
  35. package/templates/boilerplate/holidia/core/auth/index.ts +0 -0
  36. package/templates/boilerplate/holidia/core/constants/data.ts +559 -0
  37. package/templates/boilerplate/holidia/core/constants/index.ts +0 -0
  38. package/templates/boilerplate/holidia/core/hooks/use-image-colors.ts +0 -0
  39. package/templates/boilerplate/holidia/core/hooks/use-toggle-favorite.ts +0 -0
  40. package/templates/boilerplate/holidia/core/storage.ts +0 -0
  41. package/templates/boilerplate/holidia/core/store/index.ts +0 -0
  42. package/templates/boilerplate/holidia/core/theme/calendar-theme.ts +0 -0
  43. package/templates/boilerplate/holidia/core/theme/colors.ts +2 -0
  44. package/templates/boilerplate/holidia/core/theme/use-theme-config.ts +0 -0
  45. package/templates/boilerplate/holidia/core/types/index.d.ts +63 -0
  46. package/templates/boilerplate/holidia/core/types/lib.d.ts +4 -0
  47. package/templates/boilerplate/holidia/core/utils/layout.ts +0 -0
  48. package/templates/boilerplate/holidia/core/utils/log.ts +0 -0
  49. package/templates/boilerplate/holidia/eas.json +18 -0
  50. package/templates/boilerplate/holidia/env.development +2 -0
  51. package/templates/boilerplate/holidia/env.prod +2 -0
  52. package/templates/boilerplate/holidia/global.css +0 -1
  53. package/templates/boilerplate/holidia/metro.config.js +6 -4
  54. package/templates/boilerplate/holidia/nativewind-env.d.ts +3 -0
  55. package/templates/boilerplate/holidia/package.json +74 -21
  56. package/templates/boilerplate/holidia/prettier.config.js +10 -0
  57. package/templates/boilerplate/holidia/tailwind.config.js +6 -7
  58. package/templates/boilerplate/holidia/tsconfig.json +11 -0
  59. package/templates/registry.json +2 -0
  60. package/templates/boilerplate/holidia/src/app/_layout.tsx +0 -16
  61. package/templates/boilerplate/holidia/src/app/holi.tsx +0 -9
  62. package/templates/boilerplate/holidia/src/app/index.tsx +0 -34
package/dist/index.js CHANGED
@@ -156,9 +156,12 @@ async function main() {
156
156
  await fs.writeJSON(path.join(dest, "app.json"), mergedApp, { spaces: 2 });
157
157
  }
158
158
  }
159
- const envPath = path.join(dest, "env");
160
- if (await fs.pathExists(envPath)) {
161
- await fs.move(envPath, path.join(dest, ".env"), { overwrite: true });
159
+ const destFiles = await fs.readdir(dest);
160
+ for (const file of destFiles) {
161
+ if (file === "env" || file.startsWith("env.")) {
162
+ const newName = "." + file;
163
+ await fs.move(path.join(dest, file), path.join(dest, newName), { overwrite: true });
164
+ }
162
165
  }
163
166
  const pkgPath = path.join(dest, "package.json");
164
167
  if (await fs.pathExists(pkgPath)) {
@@ -177,12 +180,14 @@ async function main() {
177
180
  await fs.writeJSON(appJsonPath, appJson, { spaces: 2 });
178
181
  }
179
182
  s.stop("Files ready");
180
- if (project.install) {
183
+ const shouldInstall = project.install && !selectedItem.skipInstall;
184
+ const shouldPrebuild = opts.prebuild !== false && !selectedItem.skipPrebuild;
185
+ if (shouldInstall) {
181
186
  const si = p.spinner();
182
187
  si.start("Installing dependencies");
183
188
  await installDeps(project.pm, dest);
184
189
  si.stop("Installed");
185
- if (opts.prebuild !== false) {
190
+ if (shouldPrebuild) {
186
191
  const sp = p.spinner();
187
192
  sp.start("Generating ios/android (expo prebuild)");
188
193
  try {
@@ -193,12 +198,15 @@ async function main() {
193
198
  }
194
199
  }
195
200
  }
196
- p.outro([
201
+ const runCmd = (cmd) => ` ${project.pm} ${project.pm === "npm" ? "run " : ""}${cmd}`;
202
+ const nextSteps = [
197
203
  pc.green("Next steps:"),
198
204
  ` cd ${project.name}`,
199
- project.install ? "" : ` ${project.pm} install`,
200
- ` ${project.pm} ${project.pm === "npm" ? "run " : ""}start`
201
- ].filter(Boolean).join("\n"));
205
+ !shouldInstall ? ` ${project.pm} install` : null,
206
+ !shouldPrebuild ? runCmd("prebuild --clean") : null,
207
+ runCmd("start")
208
+ ];
209
+ p.outro(nextSteps.filter(Boolean).join("\n"));
202
210
  }
203
211
  async function installDeps(pm, cwd) {
204
212
  const cmd = pm === "bun" ? "bun" : pm;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newcandies",
3
- "version": "0.1.32",
3
+ "version": "0.1.34",
4
4
  "description": "Scaffold Expo Router + Uniwind React Native apps with layered templates.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,144 @@
1
+ {
2
+ "View": {
3
+ "prefix": "v",
4
+ "body": ["<View className=\"$1\">", " $2", "</View>"],
5
+ "description": "A Simple View",
6
+ },
7
+ "ViewRow": {
8
+ "prefix": "vr",
9
+ "body": ["<View className=\"flex flex-row items-center justify-center\">", " $1", "</View>"],
10
+ "description": "A Simple Row View",
11
+ },
12
+ "Text": {
13
+ "prefix": "t",
14
+ "body": ["<Text variant=\"body\" className=\"text-center\">", " $1", "</Text>"],
15
+ "description": "A Simple Text",
16
+ },
17
+ "export *": {
18
+ "prefix": "ex *",
19
+ "body": ["export * from './$1';"],
20
+ "description": "export *",
21
+ },
22
+ "Component": {
23
+ "prefix": "co",
24
+ "body": [
25
+ "import { View } from 'react-native';",
26
+ "",
27
+ "import Text from '~/components/text';",
28
+ "",
29
+ "type Props = {",
30
+ " $2",
31
+ "};",
32
+ "const ${1:CompName} = ({}: Props) => {",
33
+ " return (",
34
+ " <View>",
35
+ " <Text>${1:CompName} Component</Text>",
36
+ " </View>",
37
+ " );",
38
+ "};",
39
+ "",
40
+ "export default ${1:CompName};",
41
+ ],
42
+ "description": "Default Export Component",
43
+ },
44
+ "useQuery with variables": {
45
+ "prefix": "useqv",
46
+ "body": [
47
+ "import type { AxiosError } from 'axios';",
48
+ "import { createQuery } from 'react-query-kit';",
49
+ "",
50
+ "import { client } from '../common';",
51
+ "",
52
+ "type Variables = { $3 };",
53
+ "type Response = { $4 };",
54
+ "",
55
+ "export const use$1 = createQuery<Response, Variables, AxiosError>({",
56
+ " queryKey: ['$2'],",
57
+ " fetcher: (variables) => {",
58
+ " return client",
59
+ " .get(`$2/\\${variables.$5}`)",
60
+ " .then((response) => response.data);",
61
+ " },",
62
+ "});",
63
+ ],
64
+ "description": "useQuery with variables",
65
+ },
66
+ "useQuery": {
67
+ "prefix": "useq",
68
+ "body": [
69
+ "import type { AxiosError } from 'axios';",
70
+ "import { createQuery } from 'react-query-kit';",
71
+ "",
72
+ "import { client } from '../common';",
73
+ "",
74
+ "type Response = { $3 };",
75
+ "type Variables = void;",
76
+ "",
77
+ "export const use$1 = createQuery<Response, Variables, AxiosError>({",
78
+ " queryKey: ['$2'],",
79
+ " fetcher: () => {",
80
+ " return client.get(`$2`).then((response) => response.data.posts);",
81
+ " },",
82
+ "});",
83
+ ],
84
+ "description": "useQuery",
85
+ },
86
+ "useInfiniteQuery": {
87
+ "prefix": "useiq",
88
+ "body": [
89
+ "import type { AxiosError } from 'axios';",
90
+ "import { createInfiniteQuery } from 'react-query-kit';",
91
+ "",
92
+ "import { client } from '../common/client';",
93
+ "import { DEFAULT_LIMIT, getNextPageParam } from '../common/utils';",
94
+ "import type { PaginateQuery } from '../types';",
95
+ "",
96
+ "type Response = void;",
97
+ "type Variables = PaginateQuery<$3>;",
98
+ "",
99
+ "export const use$1 = createInfiniteQuery<Response, Variables, AxiosError>({",
100
+ " queryKey: ['$2'],",
101
+ " fetcher: (_variables, { pageParam }) => {",
102
+ " return client({",
103
+ " url: `/$2/`,",
104
+ " method: 'GET',",
105
+ " params: {",
106
+ " limit: DEFAULT_LIMIT,",
107
+ " offset: pageParam",
108
+ " }",
109
+ " }).then((response) => response.data);",
110
+ " },",
111
+ " getNextPageParam,",
112
+ " initialPageParam: 0",
113
+ "});",
114
+ ],
115
+ "description": "useInfiniteQuery",
116
+ },
117
+ "useMutation": {
118
+ "prefix": "usem",
119
+ "body": [
120
+ "import type { AxiosError } from 'axios';",
121
+ "import { createMutation } from 'react-query-kit';",
122
+ "",
123
+ "import { client } from '../common';",
124
+ "",
125
+ "type Variables = { $3 };",
126
+ "type Response = { $4 };",
127
+ "",
128
+ "export const use$1 = createMutation<Response, Variables, AxiosError>({",
129
+ " mutationFn: async (variables) =>",
130
+ " client({",
131
+ " url: '$2',",
132
+ " method: 'POST',",
133
+ " data: variables",
134
+ " }).then((response) => response.data)",
135
+ "});",
136
+ ],
137
+ "description": "useMutation",
138
+ },
139
+ "export default": {
140
+ "prefix": "expd",
141
+ "body": ["export default $1;"],
142
+ "description": "Export Default",
143
+ },
144
+ }
@@ -0,0 +1,7 @@
1
+ // Folder-specific settings
2
+ //
3
+ // For a full list of overridable settings, and general information on folder-specific settings,
4
+ // see the documentation: https://zed.dev/docs/configuring-zed#settings-files
5
+ {
6
+ "current_line_highlight": "line"
7
+ }
@@ -1,3 +1,26 @@
1
- # Holidia template
1
+ # Holidia App
2
2
 
3
- Adds a sample screen at `app/holi.tsx`. Extra deps will include React Query and AsyncStorage.
3
+ Holidia app boilerplate with NativeWind styling.
4
+
5
+
6
+ ## Installation
7
+
8
+ 1. Install dependencies:
9
+ ```bash
10
+ pnpm install
11
+ ```
12
+
13
+ 2. Prebuild the project:
14
+ ```bash
15
+ pnpm prebuild --clean
16
+ ```
17
+
18
+ 3. Run the app:
19
+ - For Android:
20
+ ```bash
21
+ pnpm android
22
+ ```
23
+ - For iOS:
24
+ ```bash
25
+ pnpm ios
26
+ ```
@@ -0,0 +1,46 @@
1
+ import { ScrollViewStyleReset } from 'expo-router/html';
2
+
3
+ // This file is web-only and used to configure the root HTML for every
4
+ // web page during static rendering.
5
+ // The contents of this function only run in Node.js environments and
6
+ // do not have access to the DOM or browser APIs.
7
+ export default function Root({ children }: { children: React.ReactNode }) {
8
+ return (
9
+ <html lang="en">
10
+ <head>
11
+ <meta charSet="utf-8" />
12
+ <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
13
+
14
+ {/*
15
+ This viewport disables scaling which makes the mobile website act more like a native app.
16
+ However this does reduce built-in accessibility. If you want to enable scaling, use this instead:
17
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
18
+ */}
19
+ <meta
20
+ name="viewport"
21
+ content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1.00001,viewport-fit=cover"
22
+ />
23
+ {/*
24
+ Disable body scrolling on web. This makes ScrollView components work closer to how they do on native.
25
+ However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line.
26
+ */}
27
+ <ScrollViewStyleReset />
28
+
29
+ {/* Using raw CSS styles as an escape-hatch to ensure the background color never flickers in dark-mode. */}
30
+ <style dangerouslySetInnerHTML={{ __html: responsiveBackground }} />
31
+ {/* Add any additional <head> elements that you want globally available on web... */}
32
+ </head>
33
+ <body>{children}</body>
34
+ </html>
35
+ );
36
+ }
37
+
38
+ const responsiveBackground = `
39
+ body {
40
+ background-color: #fff;
41
+ }
42
+ @media (prefers-color-scheme: dark) {
43
+ body {
44
+ background-color: #000;
45
+ }
46
+ }`;
@@ -0,0 +1,23 @@
1
+ import { Link, Stack } from 'expo-router';
2
+ import { Text, View } from 'react-native';
3
+
4
+ export default function NotFoundScreen() {
5
+ return (
6
+ <>
7
+ <Stack.Screen options={{ title: 'Oops!' }} />
8
+ <View className={styles.container}>
9
+ <Text className={styles.title}>This screen doesn't exist.</Text>
10
+ <Link href="/" className={styles.link}>
11
+ <Text className={styles.linkText}>Go to home screen!</Text>
12
+ </Link>
13
+ </View>
14
+ </>
15
+ );
16
+ }
17
+
18
+ const styles = {
19
+ container: `items-center flex-1 justify-center p-5`,
20
+ title: `text-xl font-bold`,
21
+ link: `mt-4 pt-4`,
22
+ linkText: `text-base text-[#2e78b7]`,
23
+ };
File without changes
File without changes
File without changes
@@ -0,0 +1,264 @@
1
+ import Ionicons from '@expo/vector-icons/Ionicons';
2
+ import BottomSheet, {
3
+ BottomSheetBackdrop,
4
+ BottomSheetBackdropProps,
5
+ BottomSheetView,
6
+ } from '@gorhom/bottom-sheet';
7
+ import { Calendar, fromDateId, toDateId, useDateRange } from '@marceloterreiro/flash-calendar';
8
+ import { nanoid } from 'nanoid/non-secure';
9
+ import { toast } from 'sonner-native';
10
+
11
+ import { useQuery } from '@tanstack/react-query';
12
+ import {
13
+ addMonths,
14
+ differenceInDays,
15
+ isBefore,
16
+ isSameMonth,
17
+ startOfMonth,
18
+ subMonths,
19
+ } from 'date-fns';
20
+ import { router, useLocalSearchParams } from 'expo-router';
21
+ import { SquircleButton } from 'expo-squircle-view';
22
+ import { useCallback, useMemo, useRef, useState } from 'react';
23
+ import { Pressable, ScrollView, View } from 'react-native';
24
+ import Container from '~/components/container';
25
+ import Header from '~/components/header';
26
+ import LoadingIndicator from '~/components/loading-indicator';
27
+ import AmenitiesList from '~/components/property/amenities-list';
28
+ import PropertyImage from '~/components/property/property-image';
29
+ import Text from '~/components/text';
30
+ import { client } from '~/core/api/client';
31
+ import { today } from '~/core/constants';
32
+ import useShoppingCartStore from '~/core/store';
33
+ import { calendarTheme } from '~/core/theme/calendar-theme';
34
+ import { PRIMARY } from '~/core/theme/colors';
35
+
36
+ type Props = {};
37
+ const Property = ({}: Props) => {
38
+ const { id } = useLocalSearchParams();
39
+
40
+ const { data: property, isLoading } = useQuery<Property>({
41
+ queryKey: ['property' + id],
42
+ queryFn: async () => {
43
+ const { data } = await client.get(`/properties/${id}`);
44
+ return data.property;
45
+ },
46
+ });
47
+
48
+ const { addItem } = useShoppingCartStore();
49
+
50
+ const { calendarActiveDateRanges, onCalendarDayPress } = useDateRange();
51
+
52
+ console.log({ calendarActiveDateRanges });
53
+
54
+ const bottomSheetRef = useRef<BottomSheet>(null);
55
+
56
+ const snapPoints = useMemo(() => ['60%'], []);
57
+
58
+ const renderBackdrop = useCallback((props: BottomSheetBackdropProps) => {
59
+ return (
60
+ <BottomSheetBackdrop
61
+ {...props}
62
+ disappearsOnIndex={-1}
63
+ appearsOnIndex={0}
64
+ pressBehavior={'close'}
65
+ />
66
+ );
67
+ }, []);
68
+
69
+ const calculateDays = () => {
70
+ if (!calendarActiveDateRanges[0]?.startId) return 0;
71
+ if (!calendarActiveDateRanges[0]?.endId) return 1;
72
+
73
+ const startDate = new Date(calendarActiveDateRanges[0].startId);
74
+ const endDate = new Date(calendarActiveDateRanges[0].endId);
75
+
76
+ return differenceInDays(endDate, startDate) + 1;
77
+ };
78
+
79
+ const hasSelectedDates = Boolean(calendarActiveDateRanges[0]?.startId);
80
+ const [calendarMonthId, setCalendarMonthId] = useState(today);
81
+
82
+ const nextMonth = () => {
83
+ const month = addMonths(calendarMonthId, 1);
84
+ setCalendarMonthId(toDateId(month));
85
+ };
86
+
87
+ const currentDisplayMonth = fromDateId(calendarMonthId);
88
+ const canGoBack =
89
+ !isSameMonth(currentDisplayMonth, today) && !isBefore(currentDisplayMonth, startOfMonth(today));
90
+
91
+ const prevMonth = () => {
92
+ if (canGoBack) {
93
+ const month = subMonths(calendarMonthId, 1);
94
+ setCalendarMonthId(toDateId(month));
95
+ }
96
+ };
97
+ if (isLoading || !property) {
98
+ return <LoadingIndicator />;
99
+ }
100
+ const days = calculateDays();
101
+ const totalPrice = days * property.price_per_night;
102
+
103
+ return (
104
+ <Container>
105
+ <Header title="Property" />
106
+ <ScrollView className="flex-1 bg-gray-100 p-4">
107
+ <PropertyImage
108
+ imageUrl={property?.images[1]}
109
+ isFavorite={property?.is_favorite}
110
+ rating={5}
111
+ />
112
+ <View className="flex flex-row items-center justify-between">
113
+ <Text variant="subtitle-primary" className="mt-4">
114
+ {property.name}
115
+ </Text>
116
+ <View className="flex flex-row items-center justify-center">
117
+ <Ionicons name="pricetag" size={12} color={PRIMARY} />
118
+ <Text variant="body-primary" className="ml-2">
119
+ ${property.price_per_night} per night
120
+ </Text>
121
+ </View>
122
+ </View>
123
+ <View className="flex flex-row items-center">
124
+ <Ionicons name="location" size={16} color={PRIMARY} />
125
+ <Text variant="body-primary" className="">
126
+ {property.city}, {property.country}
127
+ </Text>
128
+ </View>
129
+ <Text variant="body" className="mt-1 text-gray-700">
130
+ {property.description}
131
+ </Text>
132
+ <AmenitiesList amenities={property.amenities} />
133
+ </ScrollView>
134
+
135
+ <BottomSheet
136
+ ref={bottomSheetRef}
137
+ snapPoints={snapPoints}
138
+ backdropComponent={renderBackdrop}
139
+ index={-1}
140
+ enablePanDownToClose={true}
141
+ enableDynamicSizing={false}>
142
+ <BottomSheetView style={{ flex: 1 }}>
143
+ <View className="my-4 flex flex-row items-center justify-between px-4">
144
+ <View className="flex flex-row items-center justify-center">
145
+ <Ionicons name="wallet" color={PRIMARY} size={24} />
146
+ <Text variant="subtitle" className="mx-4">
147
+ Price : ${hasSelectedDates ? totalPrice : property.price_per_night}
148
+ {!hasSelectedDates && ' per night'}
149
+ </Text>
150
+ </View>
151
+ </View>
152
+ <BottomSheetView style={{ flex: 1, paddingHorizontal: 4, position: 'relative' }}>
153
+ <View className="mt-20 flex flex-row justify-between">
154
+ <Pressable onPress={prevMonth} disabled={!canGoBack}>
155
+ <Ionicons name="arrow-back" size={24} color={canGoBack ? PRIMARY : 'gray'} />
156
+ </Pressable>
157
+ <Pressable onPress={nextMonth}>
158
+ <Ionicons name="arrow-forward" size={24} color={PRIMARY} />
159
+ </Pressable>
160
+ </View>
161
+
162
+ <Calendar
163
+ calendarMonthId={calendarMonthId}
164
+ calendarActiveDateRanges={calendarActiveDateRanges}
165
+ calendarMinDateId={today}
166
+ onCalendarDayPress={onCalendarDayPress}
167
+ theme={calendarTheme}
168
+ />
169
+ <SquircleButton
170
+ backgroundColor={PRIMARY}
171
+ cornerSmoothing={100}
172
+ onPress={() => {
173
+ bottomSheetRef.current?.close();
174
+
175
+ if (!hasSelectedDates || !calendarActiveDateRanges[0]?.startId) {
176
+ console.log('error: please select dates');
177
+ return;
178
+ }
179
+
180
+ const cartItem: ICartItem = {
181
+ id: 'cart' + nanoid(),
182
+ image: property.images[0],
183
+ name: property.name,
184
+ product: property.id,
185
+ price_per_night: property.price_per_night,
186
+ quantity: 1,
187
+ startDate: calendarActiveDateRanges[0].startId,
188
+ endDate:
189
+ calendarActiveDateRanges[0]?.endId ?? calendarActiveDateRanges[0].startId,
190
+ days: calculateDays(),
191
+ };
192
+ addItem(cartItem);
193
+ bottomSheetRef.current?.close();
194
+ }}
195
+ preserveSmoothing
196
+ className="m-8 flex flex-row items-center justify-center px-4 "
197
+ style={{
198
+ paddingVertical: 16,
199
+ position: 'absolute',
200
+ bottom: -120,
201
+ left: 0,
202
+ right: 0,
203
+ }}
204
+ borderRadius={24}>
205
+ <Ionicons name="checkmark-circle" size={20} color={'white'} />
206
+ <Text variant="button" className="mx-2 text-center">
207
+ Confirm
208
+ </Text>
209
+ </SquircleButton>
210
+ </BottomSheetView>
211
+ </BottomSheetView>
212
+ </BottomSheet>
213
+
214
+ <View className="bottom-0 left-0 right-0 -z-10 mx-4 mt-auto flex flex-row items-center justify-center py-2">
215
+ {hasSelectedDates ? (
216
+ <Pressable
217
+ className="mr-4"
218
+ onPress={() => {
219
+ bottomSheetRef.current?.expand();
220
+ }}>
221
+ <View className="flex flex-row items-center">
222
+ <Ionicons name="pricetag" color={PRIMARY} size={16} />
223
+ <Text variant="body-primary" className="text-center">
224
+ ${totalPrice}
225
+ </Text>
226
+ </View>
227
+ <Text variant="caption" className="text-center underline">
228
+ {days === 1 ? '1 Night' : `${days} nights`}
229
+ </Text>
230
+ </Pressable>
231
+ ) : (
232
+ <Pressable
233
+ className="mr-4 flex flex-row items-center"
234
+ onPress={() => {
235
+ bottomSheetRef.current?.expand();
236
+ }}>
237
+ <Ionicons name="calendar-outline" size={24} color={PRIMARY} />
238
+ <Text variant="body-primary" className="ml-2 text-center underline">
239
+ Select dates
240
+ </Text>
241
+ </Pressable>
242
+ )}
243
+ <SquircleButton
244
+ onPress={() => {
245
+ toast.success('Property added to cart');
246
+ router.push('/checkout');
247
+ }}
248
+ className="flex-grow"
249
+ backgroundColor={PRIMARY}
250
+ borderRadius={16}
251
+ style={{
252
+ paddingVertical: 16,
253
+ marginVertical: 4,
254
+ }}>
255
+ <Text variant="button" className="text-center">
256
+ Book Now
257
+ </Text>
258
+ </SquircleButton>
259
+ </View>
260
+ </Container>
261
+ );
262
+ };
263
+
264
+ export default Property;
File without changes
File without changes
File without changes
@@ -0,0 +1,2 @@
1
+ // @ts-ignore
2
+ /// <reference types="nativewind/types" />