@imksh/create 1.0.30 → 1.0.32
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/README.md +2 -0
- package/package.json +1 -1
- package/src/commands/create.js +2 -0
- package/src/index.js +1 -1
- package/src/utils/askTemplate.js +2 -1
- package/templates/layers/electron/base/electron/main.js +262 -0
- package/templates/layers/electron/base/electron/preload.js +37 -0
- package/templates/layers/electron/base/electron-builder.json5 +68 -0
- package/templates/layers/electron/javascript/_gitignore +38 -0
- package/templates/layers/electron/javascript/package.json +49 -0
- package/templates/layers/electron/javascript/src/components/layout/SidebarLayout.jsx +43 -0
- package/templates/layers/electron/javascript/src/components/ui/TitleBar.jsx +130 -0
- package/templates/layers/electron/javascript/src/config/appConfig.js +51 -0
- package/templates/layers/electron/javascript/src/hooks/useElectron.js +68 -0
- package/templates/layers/electron/javascript/src/main.jsx +17 -0
- package/templates/layers/electron/javascript/src/store/useUiStore.js +59 -0
- package/templates/layers/electron/javascript/vite.config.js +29 -0
- package/templates/layers/electron/typescript/_gitignore +38 -0
- package/templates/layers/electron/typescript/electron/main.ts +213 -0
- package/templates/layers/electron/typescript/electron/preload.ts +52 -0
- package/templates/layers/electron/typescript/package.json +52 -0
- package/templates/layers/electron/typescript/src/components/layout/SidebarLayout.tsx +42 -0
- package/templates/layers/electron/typescript/src/components/ui/TitleBar.tsx +120 -0
- package/templates/layers/electron/typescript/src/config/appConfig.ts +52 -0
- package/templates/layers/electron/typescript/src/hooks/useElectron.ts +68 -0
- package/templates/layers/electron/typescript/src/main.tsx +17 -0
- package/templates/layers/electron/typescript/src/store/useUiStore.ts +97 -0
- package/templates/layers/electron/typescript/src/vite-env.d.ts +13 -0
- package/templates/layers/electron/typescript/tsconfig.json +25 -0
- package/templates/layers/electron/typescript/tsconfig.node.json +11 -0
- package/templates/layers/electron/typescript/vite.config.ts +29 -0
- package/templates/layers/next/javascript/package.json +8 -2
- package/templates/layers/next/javascript/src/components/common/Breadcrumbs.jsx +44 -6
- package/templates/layers/next/javascript/src/components/common/Loading.jsx +1 -0
- package/templates/layers/next/javascript/src/components/common/LottieIcon.jsx +1 -0
- package/templates/layers/next/javascript/src/components/common/Pagination.jsx +170 -0
- package/templates/layers/next/javascript/src/components/common/SidebarModal.jsx +180 -0
- package/templates/layers/next/javascript/src/components/common/StatsCard.jsx +168 -0
- package/templates/layers/next/javascript/src/components/common/Table.jsx +191 -41
- package/templates/layers/next/javascript/src/components/common/Tabs.jsx +187 -0
- package/templates/layers/next/javascript/src/components/common/ToggleSwitch.jsx +4 -3
- package/templates/layers/next/javascript/src/components/layout/ProtectedRoute.jsx +2 -1
- package/templates/layers/next/javascript/src/components/layout/PublicLayout.jsx +3 -6
- package/templates/layers/next/javascript/src/components/layout/SidebarLayout.jsx +4 -17
- package/templates/layers/next/javascript/src/components/modals/ConfirmModal.jsx +4 -12
- package/templates/layers/next/javascript/src/components/modals/Modal.jsx +50 -19
- package/templates/layers/next/javascript/src/components/ui/Input.jsx +50 -0
- package/templates/layers/next/{typescript/src/components/ui/sidebar.tsx → javascript/src/components/ui/Sidebar.jsx} +65 -53
- package/templates/layers/next/javascript/src/components/ui/SidebarHeader.jsx +11 -6
- package/templates/layers/next/javascript/src/config/appConfig.js +4 -4
- package/templates/layers/next/javascript/src/hooks/useWindowSize.js +2 -3
- package/templates/layers/next/javascript/src/store/useUiStore.js +9 -4
- package/templates/layers/next/typescript/.eslintrc.json +12 -0
- package/templates/layers/next/typescript/package.json +14 -3
- package/templates/layers/next/typescript/src/components/common/Breadcrumbs.tsx +57 -8
- package/templates/layers/next/typescript/src/components/common/Loading.tsx +2 -1
- package/templates/layers/next/typescript/src/components/common/LottieIcon.tsx +2 -2
- package/templates/layers/next/typescript/src/components/common/Pagination.tsx +186 -0
- package/templates/layers/next/typescript/src/components/common/SidebarModal.tsx +200 -0
- package/templates/layers/next/typescript/src/components/common/StatsCard.tsx +232 -0
- package/templates/layers/next/typescript/src/components/common/Table.tsx +205 -39
- package/templates/layers/next/typescript/src/components/common/Tabs.tsx +190 -0
- package/templates/layers/next/typescript/src/components/common/ToggleSwitch.tsx +12 -8
- package/templates/layers/next/typescript/src/components/layout/PublicLayout.tsx +8 -6
- package/templates/layers/next/typescript/src/components/layout/SidebarLayout.tsx +8 -17
- package/templates/layers/next/typescript/src/components/modals/ConfirmModal.tsx +3 -1
- package/templates/layers/next/typescript/src/components/modals/Modal.tsx +67 -21
- package/templates/layers/next/typescript/src/components/ui/Button.tsx +1 -0
- package/templates/layers/next/typescript/src/components/ui/Header.tsx +2 -2
- package/templates/layers/next/typescript/src/components/ui/Input.tsx +40 -60
- package/templates/layers/next/{javascript/src/components/ui/sidebar.jsx → typescript/src/components/ui/Sidebar.tsx} +77 -44
- package/templates/layers/next/typescript/src/components/ui/SidebarHeader.tsx +16 -10
- package/templates/layers/next/typescript/src/config/appConfig.ts +4 -4
- package/templates/layers/next/typescript/src/hooks/usePwaInstall.ts +10 -4
- package/templates/layers/next/typescript/src/hooks/useWindowSize.ts +2 -3
- package/templates/layers/next/typescript/src/services/authService.ts +1 -1
- package/templates/layers/next/typescript/src/store/useAuthStore.ts +24 -9
- package/templates/layers/next/typescript/src/store/useUiStore.ts +14 -4
- package/templates/layers/node/javascript/.env.example +3 -1
- package/templates/layers/node/javascript/package.json +12 -3
- package/templates/layers/node/javascript/src/app.js +2 -1
- package/templates/layers/node/javascript/src/controllers/auth.controller.js +106 -168
- package/templates/layers/node/javascript/src/controllers/push.controller.js +51 -58
- package/templates/layers/node/javascript/src/controllers/upload.controller.js +12 -19
- package/templates/layers/node/javascript/src/middleware/auth.middleware.js +5 -11
- package/templates/layers/node/javascript/src/middleware/errorHandler.js +6 -4
- package/templates/layers/node/javascript/src/routes/auth.route.js +2 -0
- package/templates/layers/node/javascript/src/services/auth.service.js +159 -164
- package/templates/layers/node/javascript/src/utils/ApiError.js +20 -0
- package/templates/layers/node/javascript/src/utils/SuccessResponse.js +15 -0
- package/templates/layers/node/javascript/src/utils/apiResponse.js +4 -0
- package/templates/layers/node/javascript/src/utils/asyncHandler.js +5 -0
- package/templates/layers/node/typescript/.env.example +3 -1
- package/templates/layers/node/typescript/.eslintrc.cjs +28 -0
- package/templates/layers/node/typescript/package-lock.json +2 -2
- package/templates/layers/node/typescript/package.json +17 -3
- package/templates/layers/node/typescript/src/app.ts +3 -2
- package/templates/layers/node/typescript/src/config/db.ts +3 -2
- package/templates/layers/node/typescript/src/config/socket.ts +5 -4
- package/templates/layers/node/typescript/src/controllers/auth.controller.ts +104 -132
- package/templates/layers/node/typescript/src/controllers/push.controller.ts +52 -59
- package/templates/layers/node/typescript/src/controllers/upload.controller.ts +12 -19
- package/templates/layers/node/typescript/src/middleware/auth.middleware.ts +13 -7
- package/templates/layers/node/typescript/src/middleware/errorHandler.ts +18 -5
- package/templates/layers/node/typescript/src/middleware/rateLimiter.ts +2 -2
- package/templates/layers/node/typescript/src/routes/auth.route.ts +2 -0
- package/templates/layers/node/typescript/src/services/auth.service.ts +86 -43
- package/templates/layers/node/typescript/src/types/express.d.ts +5 -3
- package/templates/layers/node/typescript/src/utils/ApiError.ts +25 -0
- package/templates/layers/node/typescript/src/utils/SuccessResponse.ts +17 -0
- package/templates/layers/node/typescript/src/utils/apiResponse.ts +4 -0
- package/templates/layers/node/typescript/src/utils/asyncHandler.ts +13 -0
- package/templates/layers/node/typescript/src/utils/cloudinaryUpload.ts +18 -7
- package/templates/layers/node/typescript/src/utils/expoNotification.ts +1 -1
- package/templates/layers/node/typescript/src/utils/genOtpToken.ts +7 -1
- package/templates/layers/node/typescript/src/utils/jwt.ts +8 -2
- package/templates/layers/node/typescript/src/utils/logger.ts +2 -1
- package/templates/layers/node/typescript/src/utils/pushHelper.ts +13 -9
- package/templates/layers/node-prisma/javascript/.env.example +3 -1
- package/templates/layers/node-prisma/javascript/package.json +11 -2
- package/templates/layers/node-prisma/javascript/src/app.js +2 -1
- package/templates/layers/node-prisma/javascript/src/controllers/auth.controller.js +90 -135
- package/templates/layers/node-prisma/javascript/src/controllers/push.controller.js +64 -76
- package/templates/layers/node-prisma/javascript/src/controllers/upload.controller.js +12 -19
- package/templates/layers/node-prisma/javascript/src/middleware/auth.middleware.js +5 -4
- package/templates/layers/node-prisma/javascript/src/middleware/errorHandler.js +6 -4
- package/templates/layers/node-prisma/javascript/src/routes/auth.route.js +2 -0
- package/templates/layers/node-prisma/javascript/src/services/auth.service.js +145 -122
- package/templates/layers/node-prisma/javascript/src/utils/ApiError.js +20 -0
- package/templates/layers/node-prisma/javascript/src/utils/SuccessResponse.js +15 -0
- package/templates/layers/node-prisma/javascript/src/utils/apiResponse.js +4 -0
- package/templates/layers/node-prisma/javascript/src/utils/asyncHandler.js +5 -0
- package/templates/layers/node-prisma/typescript/.env.example +3 -1
- package/templates/layers/node-prisma/typescript/.eslintrc.cjs +28 -0
- package/templates/layers/node-prisma/typescript/package.json +19 -5
- package/templates/layers/node-prisma/typescript/src/app.ts +3 -2
- package/templates/layers/node-prisma/typescript/src/config/prisma.ts +3 -2
- package/templates/layers/node-prisma/typescript/src/config/socket.ts +5 -4
- package/templates/layers/node-prisma/typescript/src/controllers/auth.controller.ts +89 -105
- package/templates/layers/node-prisma/typescript/src/controllers/push.controller.ts +67 -83
- package/templates/layers/node-prisma/typescript/src/controllers/upload.controller.ts +12 -19
- package/templates/layers/node-prisma/typescript/src/middleware/auth.middleware.ts +9 -13
- package/templates/layers/node-prisma/typescript/src/middleware/errorHandler.ts +18 -5
- package/templates/layers/node-prisma/typescript/src/middleware/rateLimiter.ts +2 -2
- package/templates/layers/node-prisma/typescript/src/routes/auth.route.ts +2 -0
- package/templates/layers/node-prisma/typescript/src/services/auth.service.ts +83 -31
- package/templates/layers/node-prisma/typescript/src/types/express.d.ts +5 -3
- package/templates/layers/node-prisma/typescript/src/utils/ApiError.ts +25 -0
- package/templates/layers/node-prisma/typescript/src/utils/SuccessResponse.ts +17 -0
- package/templates/layers/node-prisma/typescript/src/utils/apiResponse.ts +4 -0
- package/templates/layers/node-prisma/typescript/src/utils/asyncHandler.ts +13 -0
- package/templates/layers/node-prisma/typescript/src/utils/cloudinaryUpload.ts +18 -7
- package/templates/layers/node-prisma/typescript/src/utils/genOtpToken.ts +7 -1
- package/templates/layers/node-prisma/typescript/src/utils/jwt.ts +8 -2
- package/templates/layers/node-prisma/typescript/src/utils/logger.ts +2 -1
- package/templates/layers/node-prisma/typescript/src/utils/pushHelper.ts +10 -6
- package/templates/layers/prisma/javascript/package.json +8 -0
- package/templates/layers/prisma/typescript/package.json +14 -1
- package/templates/layers/prisma/typescript/prisma/schema.prisma +35 -10
- package/templates/layers/prisma/typescript/src/config/db.ts +3 -2
- package/templates/layers/react/javascript/package.json +6 -0
- package/templates/layers/react/javascript/src/components/common/Breadcrumbs.jsx +62 -58
- package/templates/layers/react/javascript/src/components/common/Pagination.jsx +164 -76
- package/templates/layers/react/javascript/src/components/common/SidebarModal.jsx +179 -0
- package/templates/layers/react/javascript/src/components/common/StatsCard.jsx +167 -0
- package/templates/layers/react/javascript/src/components/common/Table.jsx +248 -132
- package/templates/layers/react/javascript/src/components/common/Tabs.jsx +164 -112
- package/templates/layers/react/javascript/src/components/common/ToggleSwitch.jsx +3 -3
- package/templates/layers/react/javascript/src/components/layout/SidebarLayout.jsx +4 -12
- package/templates/layers/react/javascript/src/components/modals/Modal.jsx +53 -18
- package/templates/layers/react/javascript/src/components/ui/Input.jsx +49 -0
- package/templates/layers/react/javascript/src/components/ui/Sidebar.jsx +215 -0
- package/templates/layers/react/javascript/src/components/ui/SidebarHeader.jsx +25 -30
- package/templates/layers/react/javascript/src/config/appConfig.js +3 -3
- package/templates/layers/react/javascript/src/hooks/useWindowSize.js +2 -2
- package/templates/layers/react/typescript/.eslintrc.cjs +20 -0
- package/templates/layers/react/typescript/package.json +11 -2
- package/templates/layers/react/typescript/src/components/common/Breadcrumbs.tsx +32 -6
- package/templates/layers/react/typescript/src/components/common/Pagination.tsx +151 -57
- package/templates/layers/react/typescript/src/components/common/SidebarModal.tsx +199 -0
- package/templates/layers/react/typescript/src/components/common/StatsCard.tsx +231 -0
- package/templates/layers/react/typescript/src/components/common/Table.tsx +201 -38
- package/templates/layers/react/typescript/src/components/common/Tabs.tsx +56 -12
- package/templates/layers/react/typescript/src/components/common/ToggleSwitch.tsx +15 -3
- package/templates/layers/react/typescript/src/components/layout/SidebarLayout.tsx +3 -6
- package/templates/layers/react/typescript/src/components/modals/Modal.tsx +151 -0
- package/templates/layers/react/typescript/src/components/ui/Input.tsx +58 -0
- package/templates/layers/react/typescript/src/components/ui/Sidebar.tsx +116 -53
- package/templates/layers/react/typescript/src/components/ui/SidebarHeader.tsx +5 -4
- package/templates/layers/react/typescript/src/config/appConfig.ts +3 -3
- package/templates/layers/react/typescript/src/hooks/useWindowSize.ts +2 -3
- package/templates/layers/react/typescript/src/main.tsx +11 -11
- package/templates/layers/react/typescript/src/services/authService.ts +1 -1
- package/templates/layers/react/typescript/src/store/useAuthStore.ts +24 -9
- package/templates/layers/react-native/base/app.json +9 -22
- package/templates/layers/react-native/base/eslint.config.js +5 -1
- package/templates/layers/react-native/base/package.json +11 -1
- package/templates/layers/react-native/base/src/app/(auth)/edit-profile.tsx +7 -7
- package/templates/layers/react-native/base/src/app/(auth)/login.tsx +31 -7
- package/templates/layers/react-native/base/src/app/(tabs)/_layout.tsx +3 -3
- package/templates/layers/react-native/base/src/app/(tabs)/index.tsx +6 -5
- package/templates/layers/react-native/base/src/app/_layout.tsx +3 -3
- package/templates/layers/react-native/base/src/app/doc-viewer.tsx +3 -3
- package/templates/layers/react-native/base/src/components/common/ConfirmationToast.tsx +58 -40
- package/templates/layers/react-native/base/src/components/common/GoogleAuthButton.tsx +144 -0
- package/templates/layers/react-native/base/src/components/common/LocationLoader.tsx +64 -9
- package/templates/layers/react-native/base/src/components/common/Typography.tsx +54 -19
- package/templates/layers/react-native/base/src/components/ui/ClassicTabBar.tsx +15 -12
- package/templates/layers/react-native/base/src/components/ui/CustomTabBar.tsx +84 -90
- package/templates/layers/react-native/base/src/components/ui/Drawer.tsx +344 -0
- package/templates/layers/react-native/base/src/components/ui/Sidebar.tsx +4 -4
- package/templates/layers/react-native/base/src/components/ui/buttons/Button.tsx +29 -6
- package/templates/layers/react-native/base/src/components/ui/data-display/Accordion.tsx +2 -2
- package/templates/layers/react-native/base/src/components/ui/data-display/Badge.tsx +1 -2
- package/templates/layers/react-native/base/src/components/ui/data-display/Image.tsx +3 -3
- package/templates/layers/react-native/base/src/components/ui/data-display/SwipeableRow.tsx +28 -7
- package/templates/layers/react-native/base/src/components/ui/feedback/GestureWrapper.tsx +11 -4
- package/templates/layers/react-native/base/src/components/ui/inputs/DatePicker.tsx +3 -3
- package/templates/layers/react-native/base/src/components/ui/inputs/ImagePickerModal.tsx +45 -19
- package/templates/layers/react-native/base/src/components/ui/inputs/Input.tsx +28 -9
- package/templates/layers/react-native/base/src/components/ui/inputs/SearchablePicker.tsx +199 -0
- package/templates/layers/react-native/base/src/components/ui/inputs/Switch.tsx +7 -7
- package/templates/layers/react-native/base/src/components/ui/inputs/WebLocationPicker.tsx +146 -72
- package/templates/layers/react-native/base/src/config/api.ts +5 -5
- package/templates/layers/react-native/base/src/config/appConfig.ts +1 -1
- package/templates/layers/react-native/base/src/services/auth.service.ts +3 -1
- package/templates/layers/react-native/base/src/services/permission.service.ts +0 -2
- package/templates/layers/react-native/base/src/services/socket.service.ts +0 -7
- package/templates/layers/react-native/base/src/store/useAuthStore.ts +61 -16
- package/templates/layers/react-native/base/src/store/useNotificationStore.ts +36 -42
- package/templates/layers/react-native/base/src/types/images.d.ts +7 -5
- package/templates/layers/react-native/base/src/utils/fileDownload.ts +206 -0
- package/templates/layers/react-native/base/src/utils/storage.ts +1 -1
- package/templates/presets/electron/preset.json +9 -0
- package/templates/presets/electron-ts/preset.json +9 -0
- package/templates/presets/production-fullstack/overrides/client/package.json +9 -0
- package/templates/presets/production-fullstack/overrides/mobile/app.json +2 -15
- package/templates/presets/production-fullstack/overrides/mobile/package.json +11 -1
- package/templates/presets/production-fullstack/overrides/mobile/src/app/_layout.tsx +3 -3
- package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/Drawer.tsx +344 -0
- package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/inputs/DatePicker.tsx +3 -3
- package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/inputs/ImagePickerModal.tsx +3 -3
- package/templates/presets/production-fullstack/overrides/server/package.json +11 -2
- package/templates/layers/react/javascript/src/components/ui/sidebar.jsx +0 -169
- package/templates/layers/react-native/base/src/components/ui/BottomModal.tsx +0 -176
- package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/BottomModal.tsx +0 -159
- /package/templates/layers/react-native/base/assets/images/logo/{logoWithBg.png → icon.png} +0 -0
|
@@ -2,13 +2,17 @@ import React, { useState, useCallback } from "react";
|
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { useAuthStore } from "../../store/useAuthStore";
|
|
4
4
|
import { Txt } from "../../components/common/Typography";
|
|
5
|
-
import {
|
|
5
|
+
import { router, useFocusEffect } from "expo-router";
|
|
6
6
|
import ScrollContainer from "../../components/ui/layout/ScrollContainer";
|
|
7
7
|
import Input from "../../components/ui/inputs/Input";
|
|
8
8
|
import Button from "../../components/ui/buttons/Button";
|
|
9
9
|
import Tabs from "../../components/ui/navigation/Tabs";
|
|
10
10
|
import Image from "@/components/ui/data-display/Image";
|
|
11
11
|
import logo from "../../../assets/images/logo/logo.png";
|
|
12
|
+
import GoogleAuthButton from "../../components/common/GoogleAuthButton";
|
|
13
|
+
import { ActivityIndicator } from "react-native-paper";
|
|
14
|
+
import { useColorScheme } from "nativewind";
|
|
15
|
+
import { Colors } from "@/constants/Colors";
|
|
12
16
|
|
|
13
17
|
export default function LoginScreen() {
|
|
14
18
|
const {
|
|
@@ -22,6 +26,9 @@ export default function LoginScreen() {
|
|
|
22
26
|
clearError,
|
|
23
27
|
demoLogin,
|
|
24
28
|
} = useAuthStore();
|
|
29
|
+
const { colorScheme } = useColorScheme();
|
|
30
|
+
const colors = Colors[colorScheme ?? "light"];
|
|
31
|
+
const [isNavigating, setIsNavigating] = useState(false);
|
|
25
32
|
|
|
26
33
|
useFocusEffect(
|
|
27
34
|
useCallback(() => {
|
|
@@ -55,13 +62,13 @@ export default function LoginScreen() {
|
|
|
55
62
|
};
|
|
56
63
|
|
|
57
64
|
const handleSubmit = async () => {
|
|
58
|
-
let ok;
|
|
65
|
+
let ok = false;
|
|
59
66
|
if (mode === "login") {
|
|
60
67
|
ok = await login(form.email, form.password);
|
|
61
68
|
} else {
|
|
62
69
|
if (!otpSent) {
|
|
63
|
-
|
|
64
|
-
if (
|
|
70
|
+
const sent = await sendOtp(form.email);
|
|
71
|
+
if (sent) {
|
|
65
72
|
setOtpSent(true);
|
|
66
73
|
setTimer(60);
|
|
67
74
|
}
|
|
@@ -69,10 +76,17 @@ export default function LoginScreen() {
|
|
|
69
76
|
ok = await signup(form.name, form.email, form.password, form.otp);
|
|
70
77
|
}
|
|
71
78
|
}
|
|
79
|
+
if (ok && (mode === "login" || otpSent)) {
|
|
80
|
+
setIsNavigating(true);
|
|
81
|
+
}
|
|
72
82
|
};
|
|
73
83
|
|
|
74
|
-
if (!isCheckingAuth && user) {
|
|
75
|
-
return
|
|
84
|
+
if (isNavigating || (!isCheckingAuth && user)) {
|
|
85
|
+
return (
|
|
86
|
+
<View className="flex-1 bg-base-100 items-center justify-center">
|
|
87
|
+
<ActivityIndicator size="large" color={colors.primary} />
|
|
88
|
+
</View>
|
|
89
|
+
);
|
|
76
90
|
}
|
|
77
91
|
|
|
78
92
|
return (
|
|
@@ -204,7 +218,10 @@ export default function LoginScreen() {
|
|
|
204
218
|
<View className="mt-2">
|
|
205
219
|
<Button
|
|
206
220
|
label="Demo Login"
|
|
207
|
-
onPress={() =>
|
|
221
|
+
onPress={async () => {
|
|
222
|
+
await demoLogin();
|
|
223
|
+
setIsNavigating(true);
|
|
224
|
+
}}
|
|
208
225
|
isLoading={loading}
|
|
209
226
|
variant="outline"
|
|
210
227
|
isFullWidth
|
|
@@ -212,6 +229,13 @@ export default function LoginScreen() {
|
|
|
212
229
|
</View>
|
|
213
230
|
)}
|
|
214
231
|
|
|
232
|
+
<GoogleAuthButton
|
|
233
|
+
isLogin={mode === "login"}
|
|
234
|
+
onSuccess={() => {
|
|
235
|
+
setIsNavigating(true);
|
|
236
|
+
}}
|
|
237
|
+
/>
|
|
238
|
+
|
|
215
239
|
{mode === "signup" && otpSent && (
|
|
216
240
|
<View className="mt-2">
|
|
217
241
|
<Button
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Tabs
|
|
1
|
+
import { Tabs } from "expo-router";
|
|
2
2
|
import { useColorScheme } from "nativewind";
|
|
3
3
|
import { Colors } from "../../constants/Colors";
|
|
4
4
|
import CustomTabBar from "../../components/ui/CustomTabBar";
|
|
@@ -10,7 +10,7 @@ const TabLayout = () => {
|
|
|
10
10
|
const { user, isCheckingAuth } = useAuthStore();
|
|
11
11
|
|
|
12
12
|
if (!isCheckingAuth && !user) {
|
|
13
|
-
return
|
|
13
|
+
return null;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
return (
|
|
@@ -19,7 +19,7 @@ const TabLayout = () => {
|
|
|
19
19
|
<CustomTabBar
|
|
20
20
|
{...props}
|
|
21
21
|
showCenterButton={false}
|
|
22
|
-
onCenterButtonPress={() =>
|
|
22
|
+
onCenterButtonPress={() => {}}
|
|
23
23
|
/>
|
|
24
24
|
)}
|
|
25
25
|
screenOptions={{
|
|
@@ -38,7 +38,7 @@ import CircularProgress from "@/components/ui/feedback/CircularProgress";
|
|
|
38
38
|
import Skeleton from "@/components/ui/feedback/Skeleton";
|
|
39
39
|
import { GestureWrapper } from "@/components/ui/feedback/GestureWrapper";
|
|
40
40
|
|
|
41
|
-
import
|
|
41
|
+
import Drawer from "@/components/ui/Drawer";
|
|
42
42
|
import Tabs from "@/components/ui/navigation/Tabs";
|
|
43
43
|
import { useColorScheme } from "nativewind";
|
|
44
44
|
import { Colors } from "@/constants/Colors";
|
|
@@ -424,11 +424,12 @@ const Index = () => {
|
|
|
424
424
|
<FloatingActionButton icon="add" onPress={() => setIsModalOpen(true)} />
|
|
425
425
|
</View>
|
|
426
426
|
|
|
427
|
-
{/* Interactive
|
|
428
|
-
<
|
|
427
|
+
{/* Interactive Drawer */}
|
|
428
|
+
<Drawer
|
|
429
429
|
isOpen={isModalOpen}
|
|
430
430
|
onClose={() => setIsModalOpen(false)}
|
|
431
|
-
|
|
431
|
+
position="bottom"
|
|
432
|
+
sizePercent={0.45}
|
|
432
433
|
>
|
|
433
434
|
<VStack spacing={20} className="px-4 py-2">
|
|
434
435
|
<View className="h-16 w-16 bg-primary/10 rounded-full items-center justify-center self-center mb-2">
|
|
@@ -456,7 +457,7 @@ const Index = () => {
|
|
|
456
457
|
onPress={() => setIsModalOpen(false)}
|
|
457
458
|
/>
|
|
458
459
|
</VStack>
|
|
459
|
-
</
|
|
460
|
+
</Drawer>
|
|
460
461
|
</View>
|
|
461
462
|
);
|
|
462
463
|
};
|
|
@@ -63,8 +63,8 @@ export default function RootLayout() {
|
|
|
63
63
|
if (!user && !inAuthGroup) {
|
|
64
64
|
// Redirect to the auth group
|
|
65
65
|
router.replace("/(auth)/login");
|
|
66
|
-
} else if (user && inAuthGroup) {
|
|
67
|
-
// Redirect away from auth
|
|
66
|
+
} else if (user && (inAuthGroup || !segments[0])) {
|
|
67
|
+
// Redirect away from auth or root to main app tabs
|
|
68
68
|
router.replace("/(tabs)");
|
|
69
69
|
}
|
|
70
70
|
}, [user, isCheckingAuth, segments]);
|
|
@@ -99,8 +99,8 @@ export default function RootLayout() {
|
|
|
99
99
|
/>
|
|
100
100
|
</Stack>
|
|
101
101
|
</BiometricLock>
|
|
102
|
-
<Toast />
|
|
103
102
|
</PaperProvider>
|
|
103
|
+
<Toast />
|
|
104
104
|
</GestureHandlerRootView>
|
|
105
105
|
);
|
|
106
106
|
}
|
|
@@ -162,9 +162,9 @@ export default function DocViewerScreen() {
|
|
|
162
162
|
onPageChanged={(page) => {
|
|
163
163
|
setCurrentPage(page);
|
|
164
164
|
}}
|
|
165
|
-
onError={(error:
|
|
166
|
-
|
|
167
|
-
if (
|
|
165
|
+
onError={(error: unknown) => {
|
|
166
|
+
const err = error as { message?: string };
|
|
167
|
+
if (err?.message?.toLowerCase().includes('password')) {
|
|
168
168
|
setIsPasswordRequired(true);
|
|
169
169
|
setErrorMsg('Incorrect password. Please try again.');
|
|
170
170
|
}
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { View, TouchableOpacity } from "react-native";
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import { Txt } from "./Typography";
|
|
4
4
|
|
|
5
5
|
import { useColorScheme } from "nativewind";
|
|
6
6
|
import { Colors } from "../../constants/Colors";
|
|
7
|
+
import { useTranslation } from "react-i18next";
|
|
8
|
+
|
|
9
|
+
import { Portal } from "react-native-paper";
|
|
10
|
+
|
|
11
|
+
export interface ConfirmationToastProps {
|
|
12
|
+
name?: string;
|
|
13
|
+
message: string;
|
|
14
|
+
fun: () => void;
|
|
15
|
+
setShow: (show: boolean) => void;
|
|
16
|
+
cancleText?: string;
|
|
17
|
+
confirmText?: string;
|
|
18
|
+
}
|
|
7
19
|
|
|
8
20
|
export default function ConfirmationToast({
|
|
9
21
|
name,
|
|
10
22
|
message,
|
|
11
23
|
fun,
|
|
12
|
-
icon,
|
|
13
24
|
setShow,
|
|
14
|
-
|
|
25
|
+
cancleText,
|
|
26
|
+
confirmText,
|
|
27
|
+
}: ConfirmationToastProps) {
|
|
28
|
+
const { t } = useTranslation();
|
|
29
|
+
const cText = cancleText ?? t("common.cancel");
|
|
30
|
+
const confText = confirmText ?? t("common.confirm");
|
|
15
31
|
const { colorScheme } = useColorScheme();
|
|
16
32
|
const colors = Colors[colorScheme ?? "light"];
|
|
17
33
|
|
|
@@ -21,47 +37,49 @@ export default function ConfirmationToast({
|
|
|
21
37
|
};
|
|
22
38
|
|
|
23
39
|
return (
|
|
24
|
-
<
|
|
25
|
-
<View
|
|
26
|
-
className="my-4 pt-8 bg-base-100"
|
|
27
|
-
style={{
|
|
28
|
-
borderRadius: 20,
|
|
29
|
-
shadowColor: "#000",
|
|
30
|
-
shadowOffset: {
|
|
31
|
-
width: 0,
|
|
32
|
-
height: 4,
|
|
33
|
-
},
|
|
34
|
-
shadowOpacity: 0.1,
|
|
35
|
-
shadowRadius: 8,
|
|
36
|
-
elevation: 8,
|
|
37
|
-
}}
|
|
38
|
-
>
|
|
39
|
-
<View className="justify-center items-center px-8">
|
|
40
|
-
<Txt variant="h1">{name}</Txt>
|
|
41
|
-
<Txt variant="body" className="mt-4" style={{ textAlign: "center" }}>
|
|
42
|
-
{message}
|
|
43
|
-
</Txt>
|
|
44
|
-
</View>
|
|
40
|
+
<Portal>
|
|
41
|
+
<View className="absolute inset-0 justify-center items-center bg-black/40 z-50">
|
|
45
42
|
<View
|
|
46
|
-
className="
|
|
47
|
-
style={{
|
|
43
|
+
className="w-[90%] pt-8 bg-base-100"
|
|
44
|
+
style={{
|
|
45
|
+
borderRadius: 20,
|
|
46
|
+
shadowColor: "#000",
|
|
47
|
+
shadowOffset: {
|
|
48
|
+
width: 0,
|
|
49
|
+
height: 4,
|
|
50
|
+
},
|
|
51
|
+
shadowOpacity: 0.1,
|
|
52
|
+
shadowRadius: 8,
|
|
53
|
+
elevation: 8,
|
|
54
|
+
}}
|
|
48
55
|
>
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
style={{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
style={{ borderLeftWidth: 1, borderLeftColor: colors.base300 }}
|
|
59
|
-
onPress={ok}
|
|
56
|
+
<View className="justify-center items-center px-8">
|
|
57
|
+
<Txt variant="xl">{name}</Txt>
|
|
58
|
+
<Txt variant="sm" className="mt-4" style={{ textAlign: "center" }}>
|
|
59
|
+
{message}
|
|
60
|
+
</Txt>
|
|
61
|
+
</View>
|
|
62
|
+
<View
|
|
63
|
+
className="flex-row mt-8"
|
|
64
|
+
style={{ borderTopWidth: 1, borderTopColor: colors.base300 }}
|
|
60
65
|
>
|
|
61
|
-
<
|
|
62
|
-
|
|
66
|
+
<TouchableOpacity
|
|
67
|
+
className="w-[50%] justify-center items-center h-20"
|
|
68
|
+
style={{ borderRightWidth: 1, borderRightColor: colors.base300 }}
|
|
69
|
+
onPress={() => setShow(false)}
|
|
70
|
+
>
|
|
71
|
+
<Txt variant="sm">{cText}</Txt>
|
|
72
|
+
</TouchableOpacity>
|
|
73
|
+
<TouchableOpacity
|
|
74
|
+
className="w-[50%] justify-center items-center"
|
|
75
|
+
style={{ borderLeftWidth: 1, borderLeftColor: colors.base300 }}
|
|
76
|
+
onPress={ok}
|
|
77
|
+
>
|
|
78
|
+
<Txt variant="sm">{confText}</Txt>
|
|
79
|
+
</TouchableOpacity>
|
|
80
|
+
</View>
|
|
63
81
|
</View>
|
|
64
82
|
</View>
|
|
65
|
-
</
|
|
83
|
+
</Portal>
|
|
66
84
|
);
|
|
67
85
|
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { TouchableOpacity, View, ActivityIndicator } from "react-native";
|
|
3
|
+
import Constants from "expo-constants";
|
|
4
|
+
import { useColorScheme } from "nativewind";
|
|
5
|
+
import { Colors } from "../../../constants/Colors";
|
|
6
|
+
import { Txt } from "./Typography";
|
|
7
|
+
import { useAuthStore } from "../../../store/useAuthStore";
|
|
8
|
+
import { toast } from "../../../utils/toast";
|
|
9
|
+
import { Ionicons } from "@expo/vector-icons";
|
|
10
|
+
|
|
11
|
+
const isExpoGo = Constants.appOwnership === "expo";
|
|
12
|
+
|
|
13
|
+
interface GoogleSigninType {
|
|
14
|
+
configure: (options: Record<string, unknown>) => void;
|
|
15
|
+
hasPlayServices: (options: { showPlayServicesUpdateDialog: boolean }) => Promise<boolean>;
|
|
16
|
+
signIn: () => Promise<{ data?: { idToken?: string }; idToken?: string }>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface StatusCodesType {
|
|
20
|
+
SIGN_IN_CANCELLED: string;
|
|
21
|
+
IN_PROGRESS: string;
|
|
22
|
+
PLAY_SERVICES_NOT_AVAILABLE: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let GoogleSignin: GoogleSigninType | undefined;
|
|
26
|
+
let statusCodes: StatusCodesType | undefined;
|
|
27
|
+
|
|
28
|
+
if (!isExpoGo) {
|
|
29
|
+
try {
|
|
30
|
+
const googleModule = require("@react-native-google-signin/google-signin");
|
|
31
|
+
GoogleSignin = googleModule.GoogleSignin;
|
|
32
|
+
statusCodes = googleModule.statusCodes;
|
|
33
|
+
} catch {
|
|
34
|
+
// Module not found or not supported in current environment
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface GoogleAuthButtonProps {
|
|
39
|
+
onSuccess?: () => void;
|
|
40
|
+
label?: string;
|
|
41
|
+
isLogin?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default function GoogleAuthButton({
|
|
45
|
+
onSuccess,
|
|
46
|
+
label,
|
|
47
|
+
isLogin = true,
|
|
48
|
+
}: GoogleAuthButtonProps) {
|
|
49
|
+
const { colorScheme } = useColorScheme();
|
|
50
|
+
const colors = Colors[colorScheme ?? "light"];
|
|
51
|
+
const { googleLogin } = useAuthStore();
|
|
52
|
+
const [loading, setLoading] = useState(false);
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (!isExpoGo && GoogleSignin) {
|
|
56
|
+
GoogleSignin.configure({
|
|
57
|
+
webClientId: process.env.EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID || "",
|
|
58
|
+
iosClientId: process.env.EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID || "",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
const handlePress = async () => {
|
|
64
|
+
if (isExpoGo) {
|
|
65
|
+
toast.info(
|
|
66
|
+
"Expo Go",
|
|
67
|
+
"Google Sign-In is not supported in Expo Go. Please use a custom dev client."
|
|
68
|
+
);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!GoogleSignin) {
|
|
73
|
+
toast.error("Error", "Google Sign-In module is not loaded.");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
setLoading(true);
|
|
79
|
+
await GoogleSignin.hasPlayServices();
|
|
80
|
+
|
|
81
|
+
// Force account selection every time
|
|
82
|
+
try {
|
|
83
|
+
await GoogleSignin.signOut();
|
|
84
|
+
} catch {
|
|
85
|
+
// Ignore if already signed out
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const userInfo = await GoogleSignin.signIn();
|
|
89
|
+
const idToken = userInfo.data?.idToken;
|
|
90
|
+
|
|
91
|
+
if (!idToken) {
|
|
92
|
+
throw new Error("No ID token returned from Google");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const ok = await googleLogin(idToken);
|
|
96
|
+
if (ok) {
|
|
97
|
+
const currentUser = useAuthStore.getState().user;
|
|
98
|
+
toast.success("Success", `Welcome back, ${currentUser?.name || "User"}`);
|
|
99
|
+
onSuccess?.();
|
|
100
|
+
} else {
|
|
101
|
+
toast.error("Error", "Google authentication failed");
|
|
102
|
+
}
|
|
103
|
+
} catch (error: unknown) {
|
|
104
|
+
const err = error as { code?: string; message?: string };
|
|
105
|
+
if (err.code === statusCodes?.SIGN_IN_CANCELLED) {
|
|
106
|
+
// user cancelled the login flow
|
|
107
|
+
} else if (err.code === statusCodes?.IN_PROGRESS) {
|
|
108
|
+
// operation (e.g. sign in) is in progress already
|
|
109
|
+
} else if (err.code === statusCodes?.PLAY_SERVICES_NOT_AVAILABLE) {
|
|
110
|
+
// play services not available or outdated
|
|
111
|
+
toast.error("Error", "Google Play Services not available");
|
|
112
|
+
} else {
|
|
113
|
+
// some other error happened
|
|
114
|
+
toast.error("Error", err.message || "An unexpected error occurred");
|
|
115
|
+
}
|
|
116
|
+
} finally {
|
|
117
|
+
setLoading(false);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<TouchableOpacity
|
|
123
|
+
activeOpacity={0.8}
|
|
124
|
+
onPress={handlePress}
|
|
125
|
+
disabled={loading}
|
|
126
|
+
className="w-full flex-row items-center justify-center py-4 rounded-xl mt-4 border"
|
|
127
|
+
style={{
|
|
128
|
+
backgroundColor: colors.base100,
|
|
129
|
+
borderColor: colors.base300,
|
|
130
|
+
}}
|
|
131
|
+
>
|
|
132
|
+
{loading ? (
|
|
133
|
+
<ActivityIndicator color={colors.primary} />
|
|
134
|
+
) : (
|
|
135
|
+
<View className="flex-row items-center justify-center gap-2">
|
|
136
|
+
<Ionicons name="logo-google" size={20} color={colors.baseContent} />
|
|
137
|
+
<Txt className="font-semibold text-base text-base-content">
|
|
138
|
+
{label || (isLogin ? "Continue with Google" : "Sign up with Google")}
|
|
139
|
+
</Txt>
|
|
140
|
+
</View>
|
|
141
|
+
)}
|
|
142
|
+
</TouchableOpacity>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, ReactElement, useState } from "react";
|
|
2
|
-
import { View, Dimensions, StyleSheet } from "react-native";
|
|
2
|
+
import { View, Dimensions, StyleSheet, DimensionValue } from "react-native";
|
|
3
3
|
import { Ionicons } from "@expo/vector-icons";
|
|
4
4
|
import { Txt } from "./Typography";
|
|
5
5
|
import { useColorScheme } from "nativewind";
|
|
@@ -49,21 +49,41 @@ const DARK_MAP = {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
// ─── Map Primitives ───
|
|
52
|
-
|
|
52
|
+
interface MapShapeProps {
|
|
53
|
+
top: number;
|
|
54
|
+
left: number;
|
|
55
|
+
w: number;
|
|
56
|
+
h: number;
|
|
57
|
+
rx?: number;
|
|
58
|
+
dark?: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const Water = ({ top, left, w, h, rx = 8, dark }: MapShapeProps) => (
|
|
53
62
|
<View style={{
|
|
54
63
|
position: "absolute", top, left, width: w, height: h,
|
|
55
64
|
backgroundColor: dark ? DARK_MAP.water : LIGHT_MAP.water,
|
|
56
65
|
borderRadius: rx, opacity: 0.9,
|
|
57
66
|
}} />
|
|
58
67
|
);
|
|
59
|
-
|
|
68
|
+
|
|
69
|
+
const Park = ({ top, left, w, h, rx = 6, dark }: MapShapeProps) => (
|
|
60
70
|
<View style={{
|
|
61
71
|
position: "absolute", top, left, width: w, height: h,
|
|
62
72
|
backgroundColor: dark ? DARK_MAP.park : LIGHT_MAP.park,
|
|
63
73
|
borderRadius: rx, opacity: dark ? 0.6 : 0.55,
|
|
64
74
|
}} />
|
|
65
75
|
);
|
|
66
|
-
|
|
76
|
+
|
|
77
|
+
interface BlockProps {
|
|
78
|
+
top: number;
|
|
79
|
+
left: number;
|
|
80
|
+
w: number;
|
|
81
|
+
h: number;
|
|
82
|
+
shade?: number;
|
|
83
|
+
dark?: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const Block = ({ top, left, w, h, shade = 0, dark }: BlockProps) => {
|
|
67
87
|
const palette = dark ? DARK_MAP.block : LIGHT_MAP.block;
|
|
68
88
|
return (
|
|
69
89
|
<View style={{
|
|
@@ -73,7 +93,17 @@ const Block = ({ top, left, w, h, shade = 0, dark }: any) => {
|
|
|
73
93
|
}} />
|
|
74
94
|
);
|
|
75
95
|
};
|
|
76
|
-
|
|
96
|
+
|
|
97
|
+
interface RoadProps {
|
|
98
|
+
top: number;
|
|
99
|
+
left: number;
|
|
100
|
+
w: number;
|
|
101
|
+
h: number;
|
|
102
|
+
major?: boolean;
|
|
103
|
+
dark?: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const Road = ({ top, left, w, h, major = false, dark }: RoadProps) => (
|
|
77
107
|
<View style={{
|
|
78
108
|
position: "absolute", top, left, width: w, height: h,
|
|
79
109
|
backgroundColor: major ? (dark ? DARK_MAP.road : LIGHT_MAP.road)
|
|
@@ -81,7 +111,15 @@ const Road = ({ top, left, w, h, major = false, dark }: any) => (
|
|
|
81
111
|
opacity: major ? 0.95 : 0.75,
|
|
82
112
|
}} />
|
|
83
113
|
);
|
|
84
|
-
|
|
114
|
+
|
|
115
|
+
interface LaneDashProps {
|
|
116
|
+
top: number;
|
|
117
|
+
left: number;
|
|
118
|
+
vertical?: boolean;
|
|
119
|
+
dark?: boolean;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const LaneDash = ({ top, left, vertical = false, dark }: LaneDashProps) => (
|
|
85
123
|
<View style={{
|
|
86
124
|
position: "absolute", top, left,
|
|
87
125
|
width: vertical ? 2 : 12, height: vertical ? 12 : 2,
|
|
@@ -154,7 +192,16 @@ const MapWorld = ({ dark }: { dark: boolean }) => {
|
|
|
154
192
|
};
|
|
155
193
|
|
|
156
194
|
// ─── MOVING TRAFFIC DOT ───
|
|
157
|
-
|
|
195
|
+
interface TrafficDotProps {
|
|
196
|
+
startX: number;
|
|
197
|
+
startY: number;
|
|
198
|
+
endX: number;
|
|
199
|
+
endY: number;
|
|
200
|
+
delay: number;
|
|
201
|
+
color: string;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const TrafficDot = ({ startX, startY, endX, endY, delay, color }: TrafficDotProps) => {
|
|
158
205
|
const x = useSharedValue(startX);
|
|
159
206
|
const y = useSharedValue(startY);
|
|
160
207
|
|
|
@@ -181,7 +228,15 @@ const TrafficDot = ({ startX, startY, endX, endY, delay, color }: any) => {
|
|
|
181
228
|
};
|
|
182
229
|
|
|
183
230
|
// ─── PROPERTY PRICE PIN ───
|
|
184
|
-
|
|
231
|
+
interface PropertyPinProps {
|
|
232
|
+
top: number;
|
|
233
|
+
left: number;
|
|
234
|
+
delay: number;
|
|
235
|
+
price: string;
|
|
236
|
+
color: string;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const PropertyPin = ({ top, left, delay, price, color }: PropertyPinProps) => {
|
|
185
240
|
const scale = useSharedValue(0);
|
|
186
241
|
const opacity = useSharedValue(0);
|
|
187
242
|
const bounce = useSharedValue(0);
|
|
@@ -328,7 +383,7 @@ const AltitudeBar = ({ primary }: { primary: string }) => {
|
|
|
328
383
|
}, []);
|
|
329
384
|
|
|
330
385
|
const barStyle = useAnimatedStyle(() => ({
|
|
331
|
-
height: `${prog.value * 100}%` as
|
|
386
|
+
height: `${prog.value * 100}%` as DimensionValue,
|
|
332
387
|
opacity: interpolate(prog.value, [0, 0.1], [0, 1], Extrapolation.CLAMP),
|
|
333
388
|
}));
|
|
334
389
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Text, TextProps } from "react-native";
|
|
1
|
+
import { Text, TextProps, TextStyle } from "react-native";
|
|
3
2
|
export const FontFamily = {
|
|
4
3
|
regular: "InterRegular",
|
|
5
4
|
medium: "InterMedium",
|
|
@@ -80,30 +79,65 @@ export const Txt = ({
|
|
|
80
79
|
const hasColorClass = className.split(" ").some((c) => {
|
|
81
80
|
if (!c.startsWith("text-")) return false;
|
|
82
81
|
const val = c.substring(5).split("/")[0]; // handle potential opacity suffix like text-white/80
|
|
83
|
-
const
|
|
84
|
-
|
|
82
|
+
const nonColors = [
|
|
83
|
+
"xxs",
|
|
84
|
+
"xs",
|
|
85
|
+
"sm",
|
|
86
|
+
"base",
|
|
87
|
+
"md",
|
|
88
|
+
"lg",
|
|
89
|
+
"xl",
|
|
90
|
+
"2xl",
|
|
91
|
+
"3xl",
|
|
92
|
+
"4xl",
|
|
93
|
+
"5xl",
|
|
94
|
+
"6xl",
|
|
95
|
+
"7xl",
|
|
96
|
+
"caption",
|
|
97
|
+
"center",
|
|
98
|
+
"left",
|
|
99
|
+
"right",
|
|
100
|
+
"justify",
|
|
101
|
+
"start",
|
|
102
|
+
"end",
|
|
103
|
+
"wrap",
|
|
104
|
+
"nowrap",
|
|
105
|
+
"balance",
|
|
106
|
+
"pretty",
|
|
107
|
+
"clip",
|
|
108
|
+
"ellipsis",
|
|
109
|
+
"truncate",
|
|
110
|
+
];
|
|
111
|
+
return !nonColors.includes(val);
|
|
85
112
|
});
|
|
86
|
-
const defaultColorClass =
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
113
|
+
const defaultColorClass =
|
|
114
|
+
hasColorClass || color
|
|
115
|
+
? ""
|
|
116
|
+
: variant === "xs" || variant === "caption"
|
|
117
|
+
? "text-secondary"
|
|
118
|
+
: "text-base-content";
|
|
119
|
+
|
|
120
|
+
const customStyles: TextStyle = {};
|
|
93
121
|
if (color) customStyles.color = color;
|
|
94
122
|
if (align) customStyles.textAlign = align;
|
|
95
123
|
|
|
96
124
|
// Intercept font weight classes from Nativewind or weight prop
|
|
97
125
|
let finalClassName = className;
|
|
98
|
-
|
|
99
|
-
const resolvedWeight = weight || (
|
|
100
|
-
finalClassName.includes("font-black") || finalClassName.includes("font-extrabold") ? "black" :
|
|
101
|
-
finalClassName.includes("font-bold") ? "bold" :
|
|
102
|
-
finalClassName.includes("font-semibold") ? "semibold" :
|
|
103
|
-
finalClassName.includes("font-medium") ? "medium" : null
|
|
104
|
-
);
|
|
105
126
|
|
|
106
|
-
|
|
127
|
+
const resolvedWeight =
|
|
128
|
+
weight ||
|
|
129
|
+
(finalClassName.includes("font-black") ||
|
|
130
|
+
finalClassName.includes("font-extrabold")
|
|
131
|
+
? "black"
|
|
132
|
+
: finalClassName.includes("font-bold")
|
|
133
|
+
? "bold"
|
|
134
|
+
: finalClassName.includes("font-semibold")
|
|
135
|
+
? "semibold"
|
|
136
|
+
: finalClassName.includes("font-medium")
|
|
137
|
+
? "medium"
|
|
138
|
+
: null);
|
|
139
|
+
|
|
140
|
+
if (resolvedWeight === "black") {
|
|
107
141
|
customStyles.fontFamily = FontFamily.extrabold;
|
|
108
142
|
customStyles.fontWeight = "normal"; // Prevent Android fallback
|
|
109
143
|
} else if (resolvedWeight === "bold") {
|
|
@@ -132,6 +166,7 @@ export const Txt = ({
|
|
|
132
166
|
<Text
|
|
133
167
|
className={`${defaultColorClass} ${finalClassName}`}
|
|
134
168
|
style={[baseStyle, customStyles, style]}
|
|
169
|
+
textBreakStrategy="simple"
|
|
135
170
|
{...props}
|
|
136
171
|
>
|
|
137
172
|
{children}
|