diff --git a/app.json b/app.json index 87eb2768..cfeb688c 100644 --- a/app.json +++ b/app.json @@ -6,9 +6,7 @@ "softwareKeyboardLayoutMode": "pan", "googleServicesFile": "./google-services.json" }, - "assetBundlePatterns": [ - "**/*" - ], + "assetBundlePatterns": ["**/*"], "ios": { "buildNumber": "20", "config": { @@ -55,4 +53,4 @@ "bundler": "metro" } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 0a76f229..b962cc2a 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,7 @@ "expo-device": "~6.0.2", "expo-font": "~12.0.5", "expo-haptics": "~13.0.1", + "expo-image-picker": "~15.0.5", "expo-linear-gradient": "~13.0.2", "expo-linking": "~6.3.1", "expo-local-authentication": "~14.0.1", diff --git a/src/components/FeaturedIcon.tsx b/src/components/FeaturedIcon.tsx index 22005967..cfd01759 100644 --- a/src/components/FeaturedIcon.tsx +++ b/src/components/FeaturedIcon.tsx @@ -1,5 +1,5 @@ import { Box, Icon } from '@baca/design-system' -import { IconNames } from '@baca/types/icon' +import { IconNames } from '@baca/types' type FeatureIconSize = 'sm' | 'md' | 'lg' | 'xl' diff --git a/src/components/index.ts b/src/components/index.ts index d211f686..cfd0fc8d 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -12,3 +12,10 @@ export * from './LanguagePicker' export * from './Modal' export * from './StatusBar' export * from './Version' + +export * from './screens/profile/ProfileControlledInput' +export * from './screens/profile/ProfileDeleteAccountButton' +export * from './screens/profile/ProfileDetailsForm' +export * from './screens/profile/ProfileEditImage' +export * from './screens/profile/ProfileHeader' +export * from './screens/profile/ProfilePasswordForm' diff --git a/src/components/screens/profile/ProfileControlledInput.tsx b/src/components/screens/profile/ProfileControlledInput.tsx new file mode 100644 index 00000000..dd87aca4 --- /dev/null +++ b/src/components/screens/profile/ProfileControlledInput.tsx @@ -0,0 +1,37 @@ +import { ControlledField } from '@baca/components/organisms/ControlledField' +import { isWeb } from '@baca/constants' +import { Box, Text } from '@baca/design-system' +import { useWeb } from '@baca/hooks' +import { ProfileControlledInputProps } from '@baca/types' + +export const ProfileControlledInput = ({ + label, + name, + isDisabled = false, + ...rest +}: ProfileControlledInputProps) => { + const { shouldApplyMobileStyles } = useWeb() + + return ( + + + {label} + + + + + + ) +} diff --git a/src/components/screens/profile/ProfileDeleteAccountButton.tsx b/src/components/screens/profile/ProfileDeleteAccountButton.tsx new file mode 100644 index 00000000..a5544f6f --- /dev/null +++ b/src/components/screens/profile/ProfileDeleteAccountButton.tsx @@ -0,0 +1,72 @@ +import { useAuthControllerDelete } from '@baca/api/query/auth/auth' +import { Button, Text, Spacer, Row, Box, useBottomSheet } from '@baca/design-system' +import { useCallback, useTranslation } from '@baca/hooks' +import { signOut } from '@baca/store/auth' +import { showErrorToast } from '@baca/utils' + +export const ProfileDeleteAccountButton = () => { + const { t } = useTranslation() + const { mutateAsync: removeUserAccount, isLoading } = useAuthControllerDelete() + + const { bottomSheetComponentRenderFunction, closeBottomSheet, presentBottomSheet } = + useBottomSheet({ + title: '', + isDivider: false, + }) + + const handleRemoveUserAccount = useCallback(async () => { + try { + await removeUserAccount() + signOut() + } catch { + showErrorToast({ + description: t('errors.something_went_wrong'), + }) + } + }, [removeUserAccount, t]) + + const bottomSheet = bottomSheetComponentRenderFunction( + + + {t('profile_screen.are_you_sure')} + + + {t('profile_screen.remove_account_desc')} + + + + + + + , + { + name: 'delete-bin-line', + color: 'featured.icon.light.fg.error', + bgColor: 'bg.error.secondary', + } + ) + + return ( + + + {bottomSheet} + + ) +} diff --git a/src/components/screens/profile/ProfileDetailsForm.tsx b/src/components/screens/profile/ProfileDetailsForm.tsx new file mode 100644 index 00000000..0574a0c9 --- /dev/null +++ b/src/components/screens/profile/ProfileDetailsForm.tsx @@ -0,0 +1,62 @@ +import { Box, Button, Spacer, Row } from '@baca/design-system' +import { useUpdateProfileForm } from '@baca/hooks' +import { useRouter } from 'expo-router' +import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' + +import { ProfileControlledInput } from './ProfileControlledInput' + +export const ProfileDetailsForm = () => { + const { t } = useTranslation() + const { control, errors, setFocus, submit, isSubmitting } = useUpdateProfileForm() + const { back } = useRouter() + + const focusLastNameInput = useCallback(() => setFocus('lastName'), [setFocus]) + + return ( + + + + + + + + {t('common.cancel')} + + + + + + + ) +} diff --git a/src/components/screens/profile/ProfileEditImage.tsx b/src/components/screens/profile/ProfileEditImage.tsx new file mode 100644 index 00000000..5ab78b6e --- /dev/null +++ b/src/components/screens/profile/ProfileEditImage.tsx @@ -0,0 +1,79 @@ +import { Box, Text, Button, Row, themeColors } from '@baca/design-system' +import * as ImagePicker from 'expo-image-picker' +import { t } from 'i18next' +import { useState, useCallback } from 'react' +import { Image, StyleSheet } from 'react-native' + +export const ProfileEditImage: React.FC = () => { + const [image, setImage] = useState(null) + + const pickImage = useCallback(async () => { + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + allowsEditing: true, + aspect: [4, 3], + quality: 1, + }) + + if (!result.canceled && result.assets && result.assets.length > 0) { + setImage(result.assets[0].uri) + } + }, []) + + return ( + + + {t('profile_screen.your_photo')} + + {t('profile_screen.your_photo_description')} + + + + {image ? ( + + ) : ( + + + {t('profile_screen.photo_innerText')} + + + )} + + + + ) +} + +const styles = StyleSheet.create({ + container: { + alignItems: 'flex-start', + flexDirection: 'row', + flexWrap: 'wrap', + justifyContent: 'space-between', + maxWidth: 800, + }, + image: { + height: '100%', + width: '100%', + }, + imageContainer: { + borderRadius: 32, + height: 64, + marginBottom: 10, + marginRight: 82, + overflow: 'hidden', + width: 64, + }, + placeholder: { + alignItems: 'center', + backgroundColor: themeColors.primitives['Gray neutral']['50'], + height: '100%', + justifyContent: 'center', + }, + textContainer: { + flex: 1, + marginBottom: 30, + maxWidth: 260, + minWidth: 260, + }, +}) diff --git a/src/components/screens/profile/ProfileHeader.tsx b/src/components/screens/profile/ProfileHeader.tsx new file mode 100644 index 00000000..14d9f9ad --- /dev/null +++ b/src/components/screens/profile/ProfileHeader.tsx @@ -0,0 +1,14 @@ +import { Box, Text } from '@baca/design-system' +import { useTranslation } from '@baca/hooks' + +export const ProfileHeader = () => { + const { t } = useTranslation() + return ( + + {t('profile_screen.profile')} + + {t('profile_screen.update_your_details')} + + + ) +} diff --git a/src/components/screens/profile/ProfilePasswordForm.tsx b/src/components/screens/profile/ProfilePasswordForm.tsx new file mode 100644 index 00000000..b5479bbb --- /dev/null +++ b/src/components/screens/profile/ProfilePasswordForm.tsx @@ -0,0 +1,54 @@ +import { Box, Button, Row } from '@baca/design-system' +import { useCallback } from '@baca/hooks' +import { useUpdatePasswordForm } from '@baca/hooks/forms' +import { usePasswordValidation } from '@baca/hooks/usePasswordValidation' +import { useTranslation } from 'react-i18next' +import { Keyboard } from 'react-native' + +import { ProfileControlledInput } from './ProfileControlledInput' + +export const ProfilePasswordForm = () => { + const { t } = useTranslation() + const { control, errors, submit, isSubmitting, setFocus } = useUpdatePasswordForm() + + const { isPasswordError, passwordSuggestions, validationFn } = usePasswordValidation() + + const focusNewPasswordInput = useCallback(() => setFocus('password'), [setFocus]) + + return ( + + + + {passwordSuggestions} + + + + + ) +} diff --git a/src/design-system/bottomSheets/types.ts b/src/design-system/bottomSheets/types.ts index 5837fd17..328a9c74 100644 --- a/src/design-system/bottomSheets/types.ts +++ b/src/design-system/bottomSheets/types.ts @@ -1,4 +1,4 @@ -import { IconNames } from '@baca/types/icon' +import { IconNames } from '@baca/types' import { BottomSheetModal } from '@gorhom/bottom-sheet' import { RefObject } from 'react' diff --git a/src/design-system/components/Button/Button.tsx b/src/design-system/components/Button/Button.tsx index c21d8d70..ab5b7451 100644 --- a/src/design-system/components/Button/Button.tsx +++ b/src/design-system/components/Button/Button.tsx @@ -1,5 +1,5 @@ import { useTheme } from '@baca/hooks' -import { IconNames } from '@baca/types/icon' +import { IconNames } from '@baca/types' import { getColorValue } from '@baca/utils' import { useMemo, diff --git a/src/design-system/components/Icon.tsx b/src/design-system/components/Icon.tsx index 28c5913f..fb1e9d32 100644 --- a/src/design-system/components/Icon.tsx +++ b/src/design-system/components/Icon.tsx @@ -1,5 +1,5 @@ import { useTheme } from '@baca/hooks' -import { IconNames } from '@baca/types/icon' +import { IconNames } from '@baca/types' import { getColorValue } from '@baca/utils' import { createIconSetFromIcoMoon } from '@expo/vector-icons' import iconJson from 'assets/icomoon/selection.json' diff --git a/src/design-system/components/types.ts b/src/design-system/components/types.ts index fb1e7b57..0893a537 100644 --- a/src/design-system/components/types.ts +++ b/src/design-system/components/types.ts @@ -1,5 +1,5 @@ import { FontWeight, TextFontSize, _appTheme } from '@baca/design-system' -import { IconNames } from '@baca/types/icon' +import { IconNames } from '@baca/types' import { DimensionValue, TextStyle, ViewProps, ViewStyle, TextInputProps } from 'react-native' import { BoxProps } from './Box' diff --git a/src/hooks/forms/index.ts b/src/hooks/forms/index.ts index 1388b190..b2656f4c 100644 --- a/src/hooks/forms/index.ts +++ b/src/hooks/forms/index.ts @@ -4,3 +4,4 @@ export * from './useSignInForm' export * from './useSignUpForm' export * from './useTestForm' export * from './useUpdateProfileForm' +export * from './useUpdatePasswordForm' diff --git a/src/hooks/forms/useTestForm.ts b/src/hooks/forms/useTestForm.ts index 7b604a2d..8e74b1b0 100644 --- a/src/hooks/forms/useTestForm.ts +++ b/src/hooks/forms/useTestForm.ts @@ -1,4 +1,4 @@ -import { TestFormValues } from '@baca/types/testForm' +import { TestFormValues } from '@baca/types' import { isError } from '@tanstack/react-query' import { useState } from 'react' import { FieldPath, useForm } from 'react-hook-form' diff --git a/src/hooks/forms/useUpdatePasswordForm.ts b/src/hooks/forms/useUpdatePasswordForm.ts new file mode 100644 index 00000000..d11fa675 --- /dev/null +++ b/src/hooks/forms/useUpdatePasswordForm.ts @@ -0,0 +1,56 @@ +import { useAuthControllerUpdate } from '@baca/api/query/auth/auth' +import { AuthUpdateDto } from '@baca/api/types' +import { handleFormError, hapticImpact, showSuccessToast } from '@baca/utils' +import { useForm } from 'react-hook-form' +import { useTranslation } from 'react-i18next' + +const defaultValues: AuthUpdateDto = { + oldPassword: '', + password: '', +} + +export const useUpdatePasswordForm = () => { + const { t } = useTranslation() + const { mutate: updatePasswordMutation, isLoading } = useAuthControllerUpdate() + + const { + control, + formState: { errors }, + handleSubmit, + reset, + setFocus, + setError: setFormError, + } = useForm({ + mode: 'onChange', + defaultValues, + }) + + const onSubmit = (data: AuthUpdateDto) => { + updatePasswordMutation( + { data }, + { + onSuccess: () => { + showSuccessToast({ description: t('toast.success.profile_updated') }) + reset(defaultValues) + }, + onError: (e) => { + handleFormError( + e as unknown as keyof AuthUpdateDto, + ({ field, description }) => { + setFormError(field, { message: description }) + } + ) + hapticImpact() + }, + } + ) + } + + return { + control, + errors, + isSubmitting: isLoading, + setFocus, + submit: handleSubmit(onSubmit), + } +} diff --git a/src/hooks/useCheckForAppUpdate.ts b/src/hooks/useCheckForAppUpdate.ts index 743d72b1..129cd0b5 100644 --- a/src/hooks/useCheckForAppUpdate.ts +++ b/src/hooks/useCheckForAppUpdate.ts @@ -5,7 +5,10 @@ import * as Application from 'expo-application' import { useEffect, useState } from 'react' import { Platform, Alert, Linking } from 'react-native' -const currentVersion = Application.nativeApplicationVersion || 'unknown' +// FIXME: Remove '100.100.100' when you'll build real app +// For now backend is using youtube app to check for updates +// In real app this should be replaced with real version +const currentVersion = '100.100.100' || Application.nativeApplicationVersion || 'unknown' const { OS } = Platform export const useCheckForAppUpdate = () => { diff --git a/src/hooks/usePasswordValidation.tsx b/src/hooks/usePasswordValidation.tsx index c89a1c96..cf8a638f 100644 --- a/src/hooks/usePasswordValidation.tsx +++ b/src/hooks/usePasswordValidation.tsx @@ -1,6 +1,6 @@ import { REGEX } from '@baca/constants' import { Box, Icon, Row, Text } from '@baca/design-system' -import { IconNames } from '@baca/types/icon' +import { IconNames } from '@baca/types' import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' diff --git a/src/hooks/useSecurePassword.ts b/src/hooks/useSecurePassword.ts index 1ee96a1d..2fcf1488 100644 --- a/src/hooks/useSecurePassword.ts +++ b/src/hooks/useSecurePassword.ts @@ -1,4 +1,4 @@ -import { IconNames } from '@baca/types/icon' +import { IconNames } from '@baca/types' import { useCallback, useState } from 'react' export const useSecurePassword = (type?: 'text' | 'password') => { diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 26a6c44a..3894e7c4 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -11,25 +11,28 @@ "title": "Your current session expired" } }, + "app_information": "Shake your device to open developer menu", "bottom_tabs": { - "home": "Home", "categories": "Categories", + "details": "Details", "example": "Example", - "settings": "Settings", + "home": "Home", "profile": "Profile", - "details": "Details" + "settings": "Settings" }, "common": { "add": "Add", "back": "Back", "cancel": "Cancel", + "change": "Change", "continue": "Continue", "go_back": "Go back", "remove": "Remove", "save": "Save", "search": "Search", "try_again_later": "Please try again later", - "try_again": "Try again" + "try_again": "Try again", + "upload": "Upload" }, "errors": { "invalid_email": "Niepoprawny adres e-mail", @@ -56,6 +59,8 @@ "email": "E-mail address", "first_name": "First name", "last_name": "Last name", + "new_password": "New password", + "old_password": "Old password", "password": "Password" }, "placeholders": { @@ -64,6 +69,8 @@ "email": "Enter your email", "first_name": "Enter your first name", "last_name": "Enter your last name", + "new_password": "Enter new password", + "old_password": "Enter current password", "password": "Password" }, "select": {}, @@ -75,6 +82,7 @@ "required": "This field is required" } }, + "hello": "Welcome", "navigation": { "screen_titles": { "application_info": "ApplicationInfo", @@ -90,8 +98,8 @@ "home": "Home", "main_tab": "MainTab", "not_found": "Not Found", - "resetLinkSent": "Reset link sent", "profile": "Profile", + "resetLinkSent": "Reset link sent", "settings": "Settings", "sign_in": "Sign in", "sign_up": "Sign up", @@ -133,8 +141,8 @@ "link_destructive": "Button link destructive", "link_gray": "Button link gray", "loading": "Button loading", - "primary": "Button primary", "primary_destructive": "Button primary destructive", + "primary": "Button primary", "secondary_color": "Button secondary color", "secondary_destructive": "Button secondary destructive", "secondary_gray": "Button secondary gray", @@ -158,14 +166,14 @@ "test_notification": "Test notification", "typography": { "label": "Typography", - "xs": "xs", - "sm": "sm", - "md": "md", - "lg": "lg", - "xl": "xl", "2xl": "2xl", "3xl": "3xl", - "4xl": "4xl" + "4xl": "4xl", + "lg": "lg", + "md": "md", + "sm": "sm", + "xl": "xl", + "xs": "xs" } }, "confirm_email_screen": { @@ -226,15 +234,18 @@ "settings_screen": { "copy_push_token": "Copy push token", "current_theme": "Current theme: {{theme}}", - "sign_out": "Sign out!", - "selected": " - selected" + "selected": " - selected", + "sign_out": "Sign out!" }, "profile_screen": { + "are_you_sure": "Are you sure?", + "photo_innerText": "No Image", "profile": "Profile", - "update_your_details": "Update your personal details here.", + "remove_account_desc": "This action cannot be undone.\n\nYou will lose access to your account. If you have an active subscription you will lose access to it.\n\nPlease make sure you are certain about this action.", "remove_account": "Remove account", - "are_you_sure": "Are you sure?", - "remove_account_desc": "This action cannot be undone.\n\nYou will lose access to your account. If you have an active subscription you will lose access to it.\n\nPlease make sure you are certain about this action." + "update_your_details": "Update your personal details here.", + "your_photo_description": "This will be displayed on your profile.", + "your_photo": "Your photo" }, "sign_in_screen": { "do_not_have_an_account": "Don't have an account?", @@ -299,11 +310,9 @@ "surname_placeholder": "Surname", "which_music": "what kind of music do you listen ?" }, + "thanks": "Thank you for using the best template for expo apps", "typography_screen": { "display_font_size": "Display fontSize: ", "text_font_size": "Text fontSize: " - }, - "hello": "Welcome", - "thanks": "Thank you for using the best template for expo apps", - "app_information": "Shake your device to open developer menu" + } } diff --git a/src/i18n/translations/pl.json b/src/i18n/translations/pl.json index c9ebd6af..1e255276 100644 --- a/src/i18n/translations/pl.json +++ b/src/i18n/translations/pl.json @@ -11,25 +11,28 @@ "title": "Twoja sesja wygasła" } }, + "app_information": "Potrząśnij swoim urządzeniem, by otworzyć menu dewelopera", "bottom_tabs": { - "home": "Home", "categories": "Kategorie", + "details": "Detale", "example": "Przykłady", - "settings": "Ustawienia", + "home": "Home", "profile": "Profil", - "details": "Detale" + "settings": "Ustawienia" }, "common": { "add": "Dodaj", "back": "Cofnij", "cancel": "Anuluj", + "change": "Zmień", "continue": "Kontynuuj", "go_back": "Cofnij", "remove": "Usuń", "save": "Zapisz", "search": "Szukaj", "try_again_later": "Proszę spróbuj ponownie później", - "try_again": "Spróbuj ponownie" + "try_again": "Spróbuj ponownie", + "upload": "Prześlij" }, "errors": { "invalid_email": "Niepoprawny adres e-mail", @@ -56,6 +59,8 @@ "email": "Adres e-mail", "first_name": "Imię", "last_name": "Nazwisko", + "new_password": "Nowe hasło", + "old_password": "Stare hasło", "password": "Hasło" }, "placeholders": { @@ -64,6 +69,8 @@ "email": "Podaj adres e-mail", "first_name": "Podaj swoje imię", "last_name": "Podaj swoje nazwisko", + "new_password": "Podaj nowe hasło", + "old_password": "Podaj stare hasło", "password": "Hasło" }, "select": {}, @@ -75,6 +82,7 @@ "required": "Pole wymagane" } }, + "hello": "Witaj", "navigation": { "screen_titles": { "application_info": "ApplicationInfo", @@ -90,8 +98,8 @@ "home": "Home", "main_tab": "MainTab", "not_found": "NotFound", - "resetLinkSent": "Link wysłany", "profile": "Profil użytkownika", + "resetLinkSent": "Link wysłany", "settings": "Settings", "sign_in": "Sign in", "sign_up": "Sign up", @@ -126,18 +134,6 @@ "colors_label": "Kolory" }, "components_screen": { - "test_notification": "Test notification", - "typography": { - "label": "Typography", - "xs": "xs", - "sm": "sm", - "md": "md", - "lg": "lg", - "xl": "xl", - "2xl": "2xl", - "3xl": "3xl", - "4xl": "4xl" - }, "button_variants": { "disabled": "Button disabled", "header": "Button variants", @@ -145,8 +141,8 @@ "link_destructive": "Button link destructive", "link_gray": "Button link gray", "loading": "Button loading", - "primary": "Button primary", "primary_destructive": "Button primary destructive", + "primary": "Button primary", "secondary_color": "Button secondary color", "secondary_destructive": "Button secondary destructive", "secondary_gray": "Button secondary gray", @@ -166,6 +162,18 @@ "notification": { "description": "by react-native-notificated 🎉", "title": "In-app notification example" + }, + "test_notification": "Test notification", + "typography": { + "label": "Typography", + "2xl": "2xl", + "3xl": "3xl", + "4xl": "4xl", + "lg": "lg", + "md": "md", + "sm": "sm", + "xl": "xl", + "xs": "xs" } }, "confirm_email_screen": { @@ -175,10 +183,10 @@ "verification_succeed": "Adres e-mail został pomyślnie potwierdzony." }, "details_screen": { - "title": "To jest przykładowy widok", + "awesome": "Wspaniale 🎉", "open_bottom_sheet": "Otwórz BottomSheetModal", "screen_params": "Parametry widoku: {{params}}", - "awesome": "Wspaniale 🎉" + "title": "To jest przykładowy widok" }, "examples_screen": { "go_to_application_info": "Idź do ApplicationInfo", @@ -202,10 +210,10 @@ "details": "Detale" }, "landing_screen": { - "login_cta": "Zaloguj się", - "sign_up": "Zarejestruj się", "go_to_blog": "Otwórz blog", - "go_to_form": "Otwórz pełno ekranowy formularz full" + "go_to_form": "Otwórz pełno ekranowy formularz full", + "login_cta": "Zaloguj się", + "sign_up": "Zarejestruj się" }, "reset_password_complete": { "password_reset": "Reset hasła", @@ -229,11 +237,14 @@ "sign_out": "Wyloguj!" }, "profile_screen": { + "are_you_sure": "Jesteś pewny/a?", + "photo_innerText": "Bez Zdjęcia", "profile": "Profil", - "update_your_details": "Zaktualizuj swoje dane osobowe tutaj.", + "remove_account_desc": "Tej akcji nie można cofnąć.\n\nUtracisz dostęp do swojego konta. Jeśli masz aktywną subskrypcję, utracisz do niej dostęp.\n\nUpewnij się, że jesteś pewien tej akcji", "remove_account": "Usuń konto", - "are_you_sure": "Jesteś pewny/a?", - "remove_account_desc": "Tej akcji nie można cofnąć.\n\nUtracisz dostęp do swojego konta. Jeśli masz aktywną subskrypcję, utracisz do niej dostęp.\n\nUpewnij się, że jesteś pewien tej akcji" + "update_your_details": "Zaktualizuj swoje dane osobowe tutaj.", + "your_photo_description": "To będzie wyświetlane na twoim profilu.", + "your_photo": "Twoje zdjęcie" }, "sign_in_screen": { "do_not_have_an_account": "Nie masz konta?", @@ -298,11 +309,9 @@ "surname_placeholder": "Nazwisko", "which_music": "Jakiej muzyki słuchasz ?" }, + "thanks": "Dzięki za używanie najlepszej templatki dla aplikacji expo", "typography_screen": { "display_font_size": "Display fontSize: ", "text_font_size": "Text fontSize: " - }, - "hello": "Witaj", - "thanks": "Dzięki za używanie najlepszej templatki dla aplikacji expo", - "app_information": "Potrząśnij swoim urządzeniem, by otworzyć menu dewelopera" + } } diff --git a/src/navigation/tabNavigator/components/SideBarTabItem.tsx b/src/navigation/tabNavigator/components/SideBarTabItem.tsx index 758b8dde..fde2f692 100644 --- a/src/navigation/tabNavigator/components/SideBarTabItem.tsx +++ b/src/navigation/tabNavigator/components/SideBarTabItem.tsx @@ -1,5 +1,5 @@ import { Icon, Row, Text } from '@baca/design-system' -import { IconNames } from '@baca/types/icon' +import { IconNames } from '@baca/types' import { Platform, StyleSheet } from 'react-native' import { TabBarItemWrapper } from './TabBarItemWrapper' diff --git a/src/navigation/tabNavigator/navigation-config.ts b/src/navigation/tabNavigator/navigation-config.ts index 5e0a6f8b..edada444 100644 --- a/src/navigation/tabNavigator/navigation-config.ts +++ b/src/navigation/tabNavigator/navigation-config.ts @@ -1,5 +1,4 @@ -import { I18nKeys } from '@baca/types/i18next' -import { IconNames } from '@baca/types/icon' +import { I18nKeys, IconNames } from '@baca/types' type Tab = { // This will be passed to translations object and translated in the app diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 193b8b86..6a037a8a 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -1,186 +1,33 @@ -import { useAuthControllerDelete } from '@baca/api/query/auth/auth' -import { ControlledField } from '@baca/components' -import { isWeb } from '@baca/constants' -import { Button, Text, Spacer, Row, Box, useBottomSheet } from '@baca/design-system' import { - useCallback, - useTranslation, - useUpdateProfileForm, - useScreenOptions, - useWeb, -} from '@baca/hooks' -import { signOut } from '@baca/store/auth' -import { showErrorToast } from '@baca/utils' -import { useRouter } from 'expo-router' + ProfileDeleteAccountButton, + ProfileDetailsForm, + ProfileEditImage, + ProfileHeader, + ProfilePasswordForm, +} from '@baca/components' +import { Box, ScrollView, Spacer } from '@baca/design-system' +import { useTranslation, useScreenOptions } from '@baca/hooks' export const ProfileScreen = () => { const { t } = useTranslation() - const { back } = useRouter() - const { shouldApplyMobileStyles } = useWeb() - const { mutateAsync: removeUserAccount, isLoading } = useAuthControllerDelete() - const { control, errors, isSubmitting, setFocus, submit } = useUpdateProfileForm() - - const { bottomSheetComponentRenderFunction, closeBottomSheet, presentBottomSheet } = - useBottomSheet({ - title: '', - isDivider: false, - }) - - const handleRemoveUserAccount = useCallback(async () => { - try { - await removeUserAccount() - signOut() - } catch { - showErrorToast({ - description: t('errors.something_went_wrong'), - }) - } - }, [removeUserAccount, t]) - - const bottomSheet = bottomSheetComponentRenderFunction( - - - {t('profile_screen.are_you_sure')} - - - {t('profile_screen.remove_account_desc')} - - - - - - - , - { - name: 'delete-bin-line', - color: 'featured.icon.light.fg.error', - bgColor: 'bg.error.secondary', - } - ) useScreenOptions({ title: t('navigation.screen_titles.profile'), }) - const focusLastNameInput = useCallback(() => setFocus('lastName'), [setFocus]) - return ( - - {t('profile_screen.profile')} - - - {t('profile_screen.update_your_details')} - - - - - {t('form.labels.first_name')} - - - - - - {t('form.labels.last_name')} - - - - - - {t('form.labels.last_name')} - - - - - - - {t('common.cancel')} - - - - - - - - - {bottomSheet} + + + + + + + + + + + - + ) } diff --git a/src/screens/auth/SignUpScreen.tsx b/src/screens/auth/SignUpScreen.tsx index e0312370..a2e8bf79 100644 --- a/src/screens/auth/SignUpScreen.tsx +++ b/src/screens/auth/SignUpScreen.tsx @@ -1,11 +1,10 @@ import { CompanyLogo, ControlledField, FormWrapper, SocialButtons } from '@baca/components' import { Box, Button, Center, Display, Row, Spacer, Text } from '@baca/design-system' import { useCallback, useSignUpForm, useState, useTranslation } from '@baca/hooks' +import { usePasswordValidation } from '@baca/hooks/usePasswordValidation' import { router } from 'expo-router' import { Keyboard } from 'react-native' -import { usePasswordValidation } from '../../hooks/usePasswordValidation' - const navigateToLogIn = () => { router.navigate('/sign-in') } diff --git a/src/types/ProfileInputProps.ts b/src/types/ProfileInputProps.ts new file mode 100644 index 00000000..c3dff3c1 --- /dev/null +++ b/src/types/ProfileInputProps.ts @@ -0,0 +1,16 @@ +import { Control, FieldErrors, RegisterOptions } from 'react-hook-form' + +export type ProfileControlledInputProps = { + control: Control + errors: FieldErrors + isDisabled?: boolean + isInvalid?: boolean + isRequired?: boolean + label: string + name: string + onFocus?: () => void + onSubmitEditing?: () => void + placeholder: string + rules?: RegisterOptions + type?: 'text' | 'password' | undefined +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 00000000..6bbcf636 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,4 @@ +export * from './i18next' +export * from './icon' +export * from './ProfileInputProps' +export * from './testForm' diff --git a/yarn.lock b/yarn.lock index 6f9b7985..707cf7e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6298,6 +6298,18 @@ expo-haptics@~13.0.1: resolved "https://registry.yarnpkg.com/expo-haptics/-/expo-haptics-13.0.1.tgz#35679c7fde4ae1c21ae3bc2d2cb34c266049dc2c" integrity sha512-qG0EOLDE4bROVT3DtUSyV9g3iB3YFu9j3711X7SNNEnBDXc+2/p3wGDPTnJvPW0ao6HG3/McAOrBQA5hVSdWng== +expo-image-loader@~4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/expo-image-loader/-/expo-image-loader-4.7.0.tgz#d403106822de80bda12d644c82b7a3b7983c0f0b" + integrity sha512-cx+MxxsAMGl9AiWnQUzrkJMJH4eNOGlu7XkLGnAXSJrRoIiciGaKqzeaD326IyCTV+Z1fXvIliSgNW+DscvD8g== + +expo-image-picker@~15.0.5: + version "15.0.5" + resolved "https://registry.yarnpkg.com/expo-image-picker/-/expo-image-picker-15.0.5.tgz#8a3d4c3ecdb5bcf58f09e024597dd69edf7baa9c" + integrity sha512-Qqp16udsadx/YpNcNaWzfbmO0tbMxyX9bS1aFiDVC+Zffh8LY8S4HJJcnWqSC2TeuAl+9SxUwTloJagvPeMBBw== + dependencies: + expo-image-loader "~4.7.0" + expo-json-utils@~0.13.0: version "0.13.1" resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-0.13.1.tgz#e49b697198e11c573d346f08ab91c467095934a9"