├── .watchmanconfig ├── jest.config.js ├── .bundle └── config ├── react-native.config.js ├── tsconfig.json ├── src ├── hotel_booking │ ├── index.ts │ ├── README.md │ ├── SliderView.tsx │ ├── model │ │ └── hotel_list_data.ts │ ├── RangeSliderView.tsx │ ├── HotelListItem.tsx │ ├── CalendarPopupView.tsx │ ├── Switch.tsx │ ├── HotelHomeScreen.tsx │ └── FiltersModal.tsx ├── introduction_animation │ ├── index.ts │ ├── scenes │ │ ├── index.ts │ │ ├── WelcomeView.tsx │ │ ├── MoodDiaryView.tsx │ │ ├── RelaxView.tsx │ │ ├── CareView.tsx │ │ ├── TopBackSkipView.tsx │ │ ├── SplashView.tsx │ │ ├── components │ │ │ └── NextButtonArrow.tsx │ │ └── CenterNextButton.tsx │ ├── README.md │ └── IntroductionAnimationScreen.tsx ├── assets │ ├── home │ │ ├── helpImage.png │ │ ├── userImage.png │ │ ├── inviteImage.png │ │ ├── supportIcon.png │ │ ├── custom_drawer.png │ │ └── feedbackImage.png │ ├── hotel │ │ ├── hotel_1.png │ │ ├── hotel_2.png │ │ ├── hotel_3.png │ │ ├── hotel_4.png │ │ ├── hotel_5.png │ │ └── hotel_booking.png │ ├── fitness_app │ │ ├── area1.png │ │ ├── area2.png │ │ ├── area3.png │ │ ├── back.png │ │ ├── bell.png │ │ ├── eaten.png │ │ ├── glass.png │ │ ├── lunch.png │ │ ├── snack.png │ │ ├── tab_1.png │ │ ├── tab_2.png │ │ ├── tab_3.png │ │ ├── tab_4.png │ │ ├── bottle.png │ │ ├── burned.png │ │ ├── dinner.png │ │ ├── runner.png │ │ ├── tab_1s.png │ │ ├── tab_2s.png │ │ ├── tab_3s.png │ │ ├── tab_4s.png │ │ ├── breakfast.png │ │ └── fitness_app.png │ ├── fonts │ │ ├── WorkSans-Bold.ttf │ │ ├── WorkSans-Medium.ttf │ │ ├── WorkSans-Regular.ttf │ │ └── WorkSans-SemiBold.ttf │ ├── design_course │ │ ├── interFace1.png │ │ ├── interFace2.png │ │ ├── interFace3.png │ │ ├── interFace4.png │ │ ├── userImage.png │ │ ├── design_course.png │ │ └── webInterFace.png │ ├── introduction_animation │ │ ├── welcome.png │ │ ├── care_image.png │ │ ├── relax_image.png │ │ ├── mood_dairy_image.png │ │ ├── introduction_image.png │ │ └── introduction_animation.png │ └── index.ts ├── design_course │ ├── index.ts │ ├── README.md │ ├── model │ │ └── category.ts │ ├── PopulerCourseListView.tsx │ ├── CategoryListView.tsx │ ├── HomeDesignCourse.tsx │ └── CourseInfoScreen.tsx ├── Config.ts ├── util │ └── action.ts ├── index.ts ├── AppControlFlow.tsx ├── components │ ├── MyPressable.tsx │ └── Toast.tsx ├── InviteFriendScene.tsx ├── HelpScene.tsx ├── AppNavigator.tsx ├── FeedbackScene.tsx ├── HomeScene.tsx └── DrawerContent.tsx ├── .yarnrc.yml ├── app.json ├── android ├── app │ ├── debug.keystore │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── values │ │ │ │ │ ├── strings.xml │ │ │ │ │ └── styles.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── drawable │ │ │ │ │ └── rn_edit_text_material.xml │ │ │ ├── assets │ │ │ │ └── fonts │ │ │ │ │ ├── WorkSans-Bold.ttf │ │ │ │ │ ├── WorkSans-Medium.ttf │ │ │ │ │ ├── WorkSans-Regular.ttf │ │ │ │ │ └── WorkSans-SemiBold.ttf │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── react_native_ui_templates │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ └── MainApplication.kt │ │ │ └── AndroidManifest.xml │ │ └── debug │ │ │ └── AndroidManifest.xml │ ├── proguard-rules.pro │ └── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── settings.gradle ├── build.gradle ├── link-assets-manifest.json ├── gradle.properties └── gradlew.bat ├── ios ├── react_native_UI_Templates │ ├── Images.xcassets │ │ ├── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── PrivacyInfo.xcprivacy │ ├── Info.plist │ └── LaunchScreen.storyboard ├── react_native_UI_Templates.xcworkspace │ └── contents.xcworkspacedata ├── .xcode.env ├── link-assets-manifest.json ├── Podfile └── react_native_UI_Templates.xcodeproj │ └── xcshareddata │ └── xcschemes │ └── react_native_UI_Templates.xcscheme ├── babel.config.js ├── .github ├── FUNDING.yml └── workflows │ ├── build-android.yml │ └── build-ios-simulator.yml ├── .prettierrc.js ├── index.js ├── App.tsx ├── __tests__ └── App.test.tsx ├── .eslintrc.js ├── Gemfile ├── metro.config.js ├── LICENSE ├── .gitignore ├── package.json ├── README.md └── Gemfile.lock /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | assets: ['./src/assets/fonts'], 3 | }; 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@react-native/typescript-config/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/hotel_booking/index.ts: -------------------------------------------------------------------------------- 1 | export { default as HotelHomeScreen } from './HotelHomeScreen'; 2 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | compressionLevel: mixed 2 | 3 | enableGlobalCache: false 4 | 5 | nodeLinker: node-modules 6 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_native_ui_templates", 3 | "displayName": "react_native_ui_templates" 4 | } 5 | -------------------------------------------------------------------------------- /android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/debug.keystore -------------------------------------------------------------------------------- /src/introduction_animation/index.ts: -------------------------------------------------------------------------------- 1 | export { default as IntroductionAnimationScreen } from './IntroductionAnimationScreen'; 2 | -------------------------------------------------------------------------------- /src/assets/home/helpImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/home/helpImage.png -------------------------------------------------------------------------------- /src/assets/home/userImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/home/userImage.png -------------------------------------------------------------------------------- /src/assets/hotel/hotel_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/hotel/hotel_1.png -------------------------------------------------------------------------------- /src/assets/hotel/hotel_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/hotel/hotel_2.png -------------------------------------------------------------------------------- /src/assets/hotel/hotel_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/hotel/hotel_3.png -------------------------------------------------------------------------------- /src/assets/hotel/hotel_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/hotel/hotel_4.png -------------------------------------------------------------------------------- /src/assets/hotel/hotel_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/hotel/hotel_5.png -------------------------------------------------------------------------------- /src/assets/fitness_app/area1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/area1.png -------------------------------------------------------------------------------- /src/assets/fitness_app/area2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/area2.png -------------------------------------------------------------------------------- /src/assets/fitness_app/area3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/area3.png -------------------------------------------------------------------------------- /src/assets/fitness_app/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/back.png -------------------------------------------------------------------------------- /src/assets/fitness_app/bell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/bell.png -------------------------------------------------------------------------------- /src/assets/fitness_app/eaten.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/eaten.png -------------------------------------------------------------------------------- /src/assets/fitness_app/glass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/glass.png -------------------------------------------------------------------------------- /src/assets/fitness_app/lunch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/lunch.png -------------------------------------------------------------------------------- /src/assets/fitness_app/snack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/snack.png -------------------------------------------------------------------------------- /src/assets/fitness_app/tab_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/tab_1.png -------------------------------------------------------------------------------- /src/assets/fitness_app/tab_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/tab_2.png -------------------------------------------------------------------------------- /src/assets/fitness_app/tab_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/tab_3.png -------------------------------------------------------------------------------- /src/assets/fitness_app/tab_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/tab_4.png -------------------------------------------------------------------------------- /src/assets/home/inviteImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/home/inviteImage.png -------------------------------------------------------------------------------- /src/assets/home/supportIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/home/supportIcon.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | react_native_ui_templates 3 | 4 | -------------------------------------------------------------------------------- /src/assets/fitness_app/bottle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/bottle.png -------------------------------------------------------------------------------- /src/assets/fitness_app/burned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/burned.png -------------------------------------------------------------------------------- /src/assets/fitness_app/dinner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/dinner.png -------------------------------------------------------------------------------- /src/assets/fitness_app/runner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/runner.png -------------------------------------------------------------------------------- /src/assets/fitness_app/tab_1s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/tab_1s.png -------------------------------------------------------------------------------- /src/assets/fitness_app/tab_2s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/tab_2s.png -------------------------------------------------------------------------------- /src/assets/fitness_app/tab_3s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/tab_3s.png -------------------------------------------------------------------------------- /src/assets/fitness_app/tab_4s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/tab_4s.png -------------------------------------------------------------------------------- /src/assets/fonts/WorkSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fonts/WorkSans-Bold.ttf -------------------------------------------------------------------------------- /src/assets/home/custom_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/home/custom_drawer.png -------------------------------------------------------------------------------- /src/assets/home/feedbackImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/home/feedbackImage.png -------------------------------------------------------------------------------- /src/assets/hotel/hotel_booking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/hotel/hotel_booking.png -------------------------------------------------------------------------------- /ios/react_native_UI_Templates/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/fitness_app/breakfast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/breakfast.png -------------------------------------------------------------------------------- /src/assets/fonts/WorkSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fonts/WorkSans-Medium.ttf -------------------------------------------------------------------------------- /src/assets/fonts/WorkSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fonts/WorkSans-Regular.ttf -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | plugins: ['react-native-reanimated/plugin'], 4 | }; 5 | -------------------------------------------------------------------------------- /src/assets/design_course/interFace1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/design_course/interFace1.png -------------------------------------------------------------------------------- /src/assets/design_course/interFace2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/design_course/interFace2.png -------------------------------------------------------------------------------- /src/assets/design_course/interFace3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/design_course/interFace3.png -------------------------------------------------------------------------------- /src/assets/design_course/interFace4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/design_course/interFace4.png -------------------------------------------------------------------------------- /src/assets/design_course/userImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/design_course/userImage.png -------------------------------------------------------------------------------- /src/assets/fitness_app/fitness_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fitness_app/fitness_app.png -------------------------------------------------------------------------------- /src/assets/fonts/WorkSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/fonts/WorkSans-SemiBold.ttf -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/assets/design_course/design_course.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/design_course/design_course.png -------------------------------------------------------------------------------- /src/assets/design_course/webInterFace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/design_course/webInterFace.png -------------------------------------------------------------------------------- /src/assets/introduction_animation/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/introduction_animation/welcome.png -------------------------------------------------------------------------------- /src/design_course/index.ts: -------------------------------------------------------------------------------- 1 | export { default as HomeDesignCourse } from './HomeDesignCourse'; 2 | export { default as CourseInfoScreen } from './CourseInfoScreen'; 3 | -------------------------------------------------------------------------------- /src/Config.ts: -------------------------------------------------------------------------------- 1 | import { Platform } from 'react-native'; 2 | 3 | export default { 4 | isAndroid: Platform.OS === 'android', 5 | isIos: Platform.OS === 'ios', 6 | }; 7 | -------------------------------------------------------------------------------- /src/assets/introduction_animation/care_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/introduction_animation/care_image.png -------------------------------------------------------------------------------- /src/assets/introduction_animation/relax_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/introduction_animation/relax_image.png -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/WorkSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/assets/fonts/WorkSans-Bold.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/WorkSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/assets/fonts/WorkSans-Medium.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/WorkSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/assets/fonts/WorkSans-Regular.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/WorkSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/assets/fonts/WorkSans-SemiBold.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/assets/introduction_animation/mood_dairy_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/introduction_animation/mood_dairy_image.png -------------------------------------------------------------------------------- /src/assets/introduction_animation/introduction_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/introduction_animation/introduction_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /src/assets/introduction_animation/introduction_animation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/src/assets/introduction_animation/introduction_animation.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashu-Dubey/React-Native-UI-Templates/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [Aashu-Dubey] 4 | patreon: ashud 5 | buy_me_a_coffee: ashud 6 | custom: [aashud.gumroad.com/l/react-native-samples] 7 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: false, 4 | bracketSpacing: true, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | endOfLine: 'auto', 8 | }; 9 | -------------------------------------------------------------------------------- /src/util/action.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export const toastRef = React.createRef(); 4 | 5 | export const showToast = (text: string) => { 6 | toastRef.current?.show(text); 7 | }; 8 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native-gesture-handler'; 6 | import { AppRegistry } from 'react-native'; 7 | import App from './App'; 8 | import { name as appName } from './app.json'; 9 | 10 | AppRegistry.registerComponent(appName, () => App); 11 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /App.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | import React from 'react'; 9 | import AppControlFlow from './src/AppControlFlow'; 10 | 11 | const App = () => { 12 | return ; 13 | }; 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DrawerContent } from './DrawerContent'; 2 | 3 | export { default as HomeScene } from './HomeScene'; 4 | export { default as HelpScene } from './HelpScene'; 5 | export { default as FeedbackScene } from './FeedbackScene'; 6 | export { default as InviteFriendScene } from './InviteFriendScene'; 7 | -------------------------------------------------------------------------------- /__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import React from 'react'; 6 | import ReactTestRenderer from 'react-test-renderer'; 7 | import App from '../App'; 8 | 9 | test('renders correctly', async () => { 10 | await ReactTestRenderer.act(() => { 11 | ReactTestRenderer.create(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native', 4 | plugins: ['react-hooks'], 5 | rules: { 6 | 'react-native/no-inline-styles': 'off', 7 | 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks 8 | 'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /ios/react_native_UI_Templates.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } 2 | plugins { id("com.facebook.react.settings") } 3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } 4 | rootProject.name = 'react_native_ui_templates' 5 | include ':app' 6 | includeBuild('../node_modules/@react-native/gradle-plugin') 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | # Exclude problematic versions of cocoapods and activesupport that causes build failures. 7 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' 8 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' 9 | gem 'xcodeproj', '< 1.26.0' 10 | gem 'concurrent-ruby', '< 1.3.4' 11 | -------------------------------------------------------------------------------- /src/introduction_animation/scenes/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SplashView } from './SplashView'; 2 | export { default as RelaxView } from './RelaxView'; 3 | export { default as CareView } from './CareView'; 4 | export { default as MoodDiaryView } from './MoodDiaryView'; 5 | export { default as WelcomeView } from './WelcomeView'; 6 | export { default as TopBackSkipView } from './TopBackSkipView'; 7 | export { default as CenterNextButton } from './CenterNextButton'; 8 | -------------------------------------------------------------------------------- /metro.config.js: -------------------------------------------------------------------------------- 1 | const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); 2 | const { wrapWithReanimatedMetroConfig } = require('react-native-reanimated/metro-config'); 3 | 4 | /** 5 | * Metro configuration 6 | * https://reactnative.dev/docs/metro 7 | * 8 | * @type {import('@react-native/metro-config').MetroConfig} 9 | */ 10 | const config = {}; 11 | 12 | module.exports = wrapWithReanimatedMetroConfig(mergeConfig(getDefaultConfig(__dirname), config)); 13 | -------------------------------------------------------------------------------- /ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /src/AppControlFlow.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { NavigationContainer } from '@react-navigation/native'; 3 | import { SafeAreaProvider } from 'react-native-safe-area-context'; 4 | import AppNavigator from './AppNavigator'; 5 | import Toast from './components/Toast'; 6 | import { toastRef } from './util/action'; 7 | 8 | const AppControlFlow: React.FC = () => { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | }; 18 | 19 | export default AppControlFlow; 20 | -------------------------------------------------------------------------------- /ios/link-assets-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "migIndex": 1, 3 | "data": [ 4 | { 5 | "path": "src/assets/fonts/WorkSans-Bold.ttf", 6 | "sha1": "8aa832d11d326a9638d73123f13a291f9d17cbc2" 7 | }, 8 | { 9 | "path": "src/assets/fonts/WorkSans-Medium.ttf", 10 | "sha1": "8157befeb8f303271b9c754f55d9bee89d4caac7" 11 | }, 12 | { 13 | "path": "src/assets/fonts/WorkSans-Regular.ttf", 14 | "sha1": "dde5c5441ea6350524d0e0eb7058c8e672359279" 15 | }, 16 | { 17 | "path": "src/assets/fonts/WorkSans-SemiBold.ttf", 18 | "sha1": "08d3f4f2abb01cbe8252dba795e27416a05704d6" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "35.0.0" 4 | minSdkVersion = 24 5 | compileSdkVersion = 35 6 | targetSdkVersion = 35 7 | ndkVersion = "27.1.12297006" 8 | kotlinVersion = "2.0.21" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | } 19 | } 20 | 21 | apply plugin: "com.facebook.react.rootproject" 22 | -------------------------------------------------------------------------------- /android/link-assets-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "migIndex": 1, 3 | "data": [ 4 | { 5 | "path": "src/assets/fonts/WorkSans-Bold.ttf", 6 | "sha1": "8aa832d11d326a9638d73123f13a291f9d17cbc2" 7 | }, 8 | { 9 | "path": "src/assets/fonts/WorkSans-Medium.ttf", 10 | "sha1": "8157befeb8f303271b9c754f55d9bee89d4caac7" 11 | }, 12 | { 13 | "path": "src/assets/fonts/WorkSans-Regular.ttf", 14 | "sha1": "dde5c5441ea6350524d0e0eb7058c8e672359279" 15 | }, 16 | { 17 | "path": "src/assets/fonts/WorkSans-SemiBold.ttf", 18 | "sha1": "08d3f4f2abb01cbe8252dba795e27416a05704d6" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | -keep class com.facebook.hermes.unicode.** { *; } 13 | -keep class com.facebook.jni.** { *; } 14 | 15 | -keep class com.swmansion.reanimated.** { *; } 16 | -keep class com.facebook.react.turbomodule.** { *; } 17 | -------------------------------------------------------------------------------- /src/design_course/README.md: -------------------------------------------------------------------------------- 1 | # Design Course Template 2 | 3 |

4 | Design Course template | react-native 5 |

6 | 7 | A design course UI template showing the list of courses related to UI designs, with some interactive animations. 8 | 9 | ## 📦 Packages used 10 | 11 | 1. [react-native-vector-icons](https://github.com/oblador/react-native-vector-icons):- Google Material icons. 12 | 2. [react-native-safe-area-context](https://github.com/th3rdwave/react-native-safe-area-context):- Handle UI for iOS safe area. 13 | 14 | ## 🔗 Links 15 | 16 | - **Demo: [twitter](https://twitter.com/aashudubey_ad/status/1578846092694720512) \| [youtube](https://youtube.com/shorts/5G0obPHAdyc)** 17 | -------------------------------------------------------------------------------- /src/components/MyPressable.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Pressable, StyleProp, ViewStyle, PressableProps } from 'react-native'; 3 | import Config from '../Config'; 4 | 5 | interface Props extends PressableProps { 6 | style?: StyleProp; 7 | touchOpacity?: number; 8 | } 9 | 10 | const MyPressable: React.FC = ({ 11 | style, 12 | android_ripple = { color: 'lightgrey' }, 13 | touchOpacity = 0.4, 14 | children, 15 | ...restOfProps 16 | }) => { 17 | return ( 18 | [ 20 | style, 21 | { opacity: !Config.isAndroid && pressed ? touchOpacity : 1 }, 22 | ]} 23 | android_ripple={android_ripple} 24 | {...restOfProps} 25 | > 26 | {children} 27 | 28 | ); 29 | }; 30 | 31 | export default MyPressable; 32 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/react_native_ui_templates/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.react_native_ui_templates 2 | 3 | import com.facebook.react.ReactActivity 4 | import com.facebook.react.ReactActivityDelegate 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate 7 | 8 | class MainActivity : ReactActivity() { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | override fun getMainComponentName(): String = "react_native_ui_templates" 15 | 16 | /** 17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 19 | */ 20 | override fun createReactActivityDelegate(): ReactActivityDelegate = 21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 22 | } 23 | -------------------------------------------------------------------------------- /src/introduction_animation/README.md: -------------------------------------------------------------------------------- 1 | # Animated Onboarding Template 2 | 3 |

4 | Animated Onboarding template, Mental Wellness App | react-native 5 |

6 | 7 | An onboarding UI template with smooth animations, for a Mental Wellness App. 8 | 9 | ## 📦 Packages used 10 | 11 | 1. [react-native-vector-icons](https://github.com/oblador/react-native-vector-icons):- Google Material icons. 12 | 2. [react-native-safe-area-context](https://github.com/th3rdwave/react-native-safe-area-context):- Handle UI for iOS safe area. 13 | 14 | ## 🌻 Motivation 15 | 16 | Original UI design for this template on [Behance](). 17 | 18 | ## 🔗 Links 19 | 20 | - [UI on Behance]() 21 | - **Demo: [twitter](https://twitter.com/aashudubey_ad/status/1580260456215695360) \| [youtube](https://youtube.com/shorts/AOD9FyiSR3U)** 22 | -------------------------------------------------------------------------------- /ios/react_native_UI_Templates/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import React 3 | import React_RCTAppDelegate 4 | import ReactAppDependencyProvider 5 | 6 | @main 7 | class AppDelegate: RCTAppDelegate { 8 | override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 9 | self.moduleName = "react_native_ui_templates" 10 | self.dependencyProvider = RCTAppDependencyProvider() 11 | 12 | // You can add your custom initial props in the dictionary below. 13 | // They will be passed down to the ViewController used by React Native. 14 | self.initialProps = [:] 15 | 16 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 17 | } 18 | 19 | override func sourceURL(for bridge: RCTBridge) -> URL? { 20 | self.bundleURL() 21 | } 22 | 23 | override func bundleURL() -> URL? { 24 | #if DEBUG 25 | RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") 26 | #else 27 | Bundle.main.url(forResource: "main", withExtension: "jsbundle") 28 | #endif 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ashutosh Dubey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ios/react_native_UI_Templates/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ios/react_native_UI_Templates/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryUserDefaults 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | CA92.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategorySystemBootTime 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | 35F9.1 29 | 30 | 31 | 32 | NSPrivacyCollectedDataTypes 33 | 34 | NSPrivacyTracking 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Resolve react_native_pods.rb with node to allow for hoisting 2 | require Pod::Executable.execute_command('node', ['-p', 3 | 'require.resolve( 4 | "react-native/scripts/react_native_pods.rb", 5 | {paths: [process.argv[1]]}, 6 | )', __dir__]).strip 7 | 8 | platform :ios, min_ios_version_supported 9 | prepare_react_native_project! 10 | 11 | linkage = ENV['USE_FRAMEWORKS'] 12 | if linkage != nil 13 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 14 | use_frameworks! :linkage => linkage.to_sym 15 | end 16 | 17 | target 'react_native_ui_templates' do 18 | config = use_native_modules! 19 | 20 | use_react_native!( 21 | :path => config[:reactNativePath], 22 | # An absolute path to your application root. 23 | :app_path => "#{Pod::Config.instance.installation_root}/.." 24 | ) 25 | 26 | post_install do |installer| 27 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 28 | react_native_post_install( 29 | installer, 30 | config[:reactNativePath], 31 | :mac_catalyst_enabled => false, 32 | # :ccache_enabled => true 33 | ) 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /src/hotel_booking/README.md: -------------------------------------------------------------------------------- 1 | # Hotel Booking Template 2 | 3 |

4 | Hotel booking template | react-native 5 |

6 | 7 | 8 | A hotel booking UI template showing the list of hotels nearby with their ratings and other details, filter UI and custom interactive calendar view etc. 9 | 10 | ## 📦 Packages used 11 | 12 | 1. [@aashu-dubey/react-native-rating-bar](https://github.com/Aashu-Dubey/react-native-rating-bar):- Rating view for hotel list item. 13 | 2. [react-native-vector-icons](https://github.com/oblador/react-native-vector-icons):- Google Material icons 14 | 3. [@ptomasroos/react-native-multi-slider](https://github.com/ptomasroos/react-native-multi-slider):- Multi slider for hotel price range in the filters. 15 | 4. [@miblanchard/react-native-slider](https://github.com/miblanchard/react-native-slider):- Slider for hotel distance in the filters. 16 | 5. [@react-native-community/blur](https://github.com/react-native-community/react-native-blur):- Blur background for Calendar modal. 17 | 6. [react-native-safe-area-context](https://github.com/th3rdwave/react-native-safe-area-context):- Handle UI for iOS safe area. 18 | 19 | ## 🔗 Links 20 | 21 | - **Demo: [twitter](https://twitter.com/aashudubey_ad/status/1576292697173766145) \| [youtube](https://youtube.com/shorts/ioFcve0rYnc)** 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | **/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | .kotlin/ 37 | 38 | # node.js 39 | # 40 | node_modules/ 41 | npm-debug.log 42 | yarn-error.log 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | **/fastlane/report.xml 52 | **/fastlane/Preview.html 53 | **/fastlane/screenshots 54 | **/fastlane/test_output 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # Ruby / CocoaPods 60 | **/Pods/ 61 | /vendor/bundle/ 62 | 63 | # Temporary files created by Metro to check the health of the file watcher 64 | .metro-health-check* 65 | 66 | # testing 67 | /coverage 68 | 69 | # Yarn 70 | .yarn/* 71 | !.yarn/patches 72 | !.yarn/plugins 73 | !.yarn/releases 74 | !.yarn/sdks 75 | !.yarn/versions 76 | -------------------------------------------------------------------------------- /src/hotel_booking/SliderView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { StyleSheet, Text } from 'react-native'; 3 | import { Slider } from '@miblanchard/react-native-slider'; 4 | 5 | const SliderView: React.FC = () => { 6 | const [distValue, setDistValue] = useState(50.0); 7 | 8 | return ( 9 | ( 23 | 24 | Less than {(distValue / 10).toFixed(1)} km 25 | 26 | )} 27 | onValueChange={value => setDistValue(value[0])} 28 | /> 29 | ); 30 | }; 31 | 32 | const styles = StyleSheet.create({ 33 | thumbStyle: { 34 | height: 24, 35 | width: 24, 36 | borderRadius: 12, 37 | borderWidth: 2, 38 | borderColor: 'white', 39 | elevation: 8, 40 | shadowColor: 'black', 41 | shadowOffset: { width: 0, height: 0 }, 42 | shadowOpacity: 0.5, 43 | shadowRadius: 7.49, 44 | }, 45 | thumbText: { 46 | width: 170, 47 | color: 'black', 48 | textAlign: 'center', 49 | }, 50 | }); 51 | 52 | export default SliderView; 53 | -------------------------------------------------------------------------------- /src/assets/index.ts: -------------------------------------------------------------------------------- 1 | const AppImages = { 2 | support_icon: require('./home/supportIcon.png'), 3 | userImage: require('./home/userImage.png'), 4 | feedbackImage: require('./home/feedbackImage.png'), 5 | helpImage: require('./home/helpImage.png'), 6 | inviteImage: require('./home/inviteImage.png'), 7 | 8 | // hotel 9 | hotel_booking: require('./hotel/hotel_booking.png'), 10 | hotel_1: require('./hotel/hotel_1.png'), 11 | hotel_2: require('./hotel/hotel_2.png'), 12 | hotel_3: require('./hotel/hotel_3.png'), 13 | hotel_4: require('./hotel/hotel_4.png'), 14 | hotel_5: require('./hotel/hotel_5.png'), 15 | 16 | // fitness_app 17 | fitness_app: require('./fitness_app/fitness_app.png'), 18 | 19 | // design_course 20 | design_course: require('./design_course/design_course.png'), 21 | design_header_image: require('./design_course/userImage.png'), 22 | interFace1: require('./design_course/interFace1.png'), 23 | interFace2: require('./design_course/interFace2.png'), 24 | interFace3: require('./design_course/interFace3.png'), 25 | interFace4: require('./design_course/interFace4.png'), 26 | webInterFace: require('./design_course/webInterFace.png'), 27 | 28 | // Animation OnBoarding App 29 | introduction_animation: require('./introduction_animation/introduction_animation.png'), 30 | introduction_image: require('./introduction_animation/introduction_image.png'), 31 | relax_image: require('./introduction_animation/relax_image.png'), 32 | care_image: require('./introduction_animation/care_image.png'), 33 | mood_dairy_image: require('./introduction_animation/mood_dairy_image.png'), 34 | welcome: require('./introduction_animation/welcome.png'), 35 | }; 36 | 37 | export { AppImages }; 38 | -------------------------------------------------------------------------------- /src/hotel_booking/model/hotel_list_data.ts: -------------------------------------------------------------------------------- 1 | import { AppImages } from '../../assets'; 2 | 3 | export interface HotelListType { 4 | id: number; 5 | imagePath: any; 6 | titleTxt: string; 7 | subTxt: string; 8 | dist: number; 9 | reviews: number; 10 | rating: number; 11 | perNight: number; 12 | } 13 | 14 | export const HOTEL_LIST: HotelListType[] = [ 15 | // 1st item dummy for 'stickyHeaderIndices' 16 | { 17 | id: 0, 18 | imagePath: '', 19 | titleTxt: '', 20 | subTxt: '', 21 | dist: 0, 22 | reviews: 0, 23 | rating: 0, 24 | perNight: 0, 25 | }, 26 | { 27 | id: 1, 28 | imagePath: AppImages.hotel_1, 29 | titleTxt: 'Grand Royal Hotel', 30 | subTxt: 'Wembley, London', 31 | dist: 2.0, 32 | reviews: 80, 33 | rating: 4.4, 34 | perNight: 180, 35 | }, 36 | { 37 | id: 2, 38 | imagePath: AppImages.hotel_2, 39 | titleTxt: 'Queen Hotel', 40 | subTxt: 'Wembley, London', 41 | dist: 4.0, 42 | reviews: 74, 43 | rating: 4.5, 44 | perNight: 200, 45 | }, 46 | { 47 | id: 3, 48 | imagePath: AppImages.hotel_3, 49 | titleTxt: 'Grand Royal Hotel', 50 | subTxt: 'Wembley, London', 51 | dist: 3.0, 52 | reviews: 62, 53 | rating: 4.0, 54 | perNight: 60, 55 | }, 56 | { 57 | id: 4, 58 | imagePath: AppImages.hotel_4, 59 | titleTxt: 'Queen Hotel', 60 | subTxt: 'Wembley, London', 61 | dist: 7.0, 62 | reviews: 90, 63 | rating: 4.4, 64 | perNight: 170, 65 | }, 66 | { 67 | id: 5, 68 | imagePath: AppImages.hotel_5, 69 | titleTxt: 'Grand Royal Hotel', 70 | subTxt: 'Wembley, London', 71 | dist: 2.0, 72 | reviews: 240, 73 | rating: 4.5, 74 | perNight: 200, 75 | }, 76 | ]; 77 | -------------------------------------------------------------------------------- /src/design_course/model/category.ts: -------------------------------------------------------------------------------- 1 | import { AppImages } from '../../assets'; 2 | 3 | export interface CategoryType { 4 | id: number; 5 | imagePath: any; 6 | title: string; 7 | lessonCount: number; 8 | money: number; 9 | rating: number; 10 | } 11 | 12 | export const CATEGORY_LIST: CategoryType[] = [ 13 | { 14 | id: 0, 15 | imagePath: AppImages.interFace1, 16 | title: 'User interface Design', 17 | lessonCount: 24, 18 | money: 25, 19 | rating: 4.3, 20 | }, 21 | { 22 | id: 1, 23 | imagePath: AppImages.interFace2, 24 | title: 'User interface Design', 25 | lessonCount: 22, 26 | money: 18, 27 | rating: 4.6, 28 | }, 29 | { 30 | id: 2, 31 | imagePath: AppImages.interFace1, 32 | title: 'User interface Design', 33 | lessonCount: 24, 34 | money: 25, 35 | rating: 4.3, 36 | }, 37 | { 38 | id: 3, 39 | imagePath: AppImages.interFace2, 40 | title: 'User interface Design', 41 | lessonCount: 22, 42 | money: 18, 43 | rating: 4.6, 44 | }, 45 | ]; 46 | 47 | export const POPULAR_COURSE_LIST: CategoryType[] = [ 48 | { 49 | id: 0, 50 | imagePath: AppImages.interFace3, 51 | title: 'App Design Course', 52 | lessonCount: 12, 53 | money: 25, 54 | rating: 4.8, 55 | }, 56 | { 57 | id: 1, 58 | imagePath: AppImages.interFace4, 59 | title: 'Web Design Course', 60 | lessonCount: 28, 61 | money: 208, 62 | rating: 4.9, 63 | }, 64 | { 65 | id: 2, 66 | imagePath: AppImages.interFace3, 67 | title: 'App Design Course', 68 | lessonCount: 12, 69 | money: 25, 70 | rating: 4.8, 71 | }, 72 | { 73 | id: 3, 74 | imagePath: AppImages.interFace4, 75 | title: 'Web Design Course', 76 | lessonCount: 28, 77 | money: 208, 78 | rating: 4.9, 79 | }, 80 | ]; 81 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | 25 | # Use this property to specify which architecture you want to build. 26 | # You can also override it from the CLI using 27 | # ./gradlew -PreactNativeArchitectures=x86_64 28 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 29 | 30 | # Use this property to enable support to the new architecture. 31 | # This will allow you to use TurboModules and the Fabric render in 32 | # your application. You should enable this flag either if you want 33 | # to write custom TurboModules/Fabric components OR use libraries that 34 | # are providing them. 35 | newArchEnabled=true 36 | 37 | # Use this property to enable or disable the Hermes JS engine. 38 | # If set to false, you will be using JSC instead. 39 | hermesEnabled=true 40 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/react_native_ui_templates/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.react_native_ui_templates 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.react.soloader.OpenSourceMergedSoMapping 13 | import com.facebook.soloader.SoLoader 14 | 15 | class MainApplication : Application(), ReactApplication { 16 | 17 | override val reactNativeHost: ReactNativeHost = 18 | object : DefaultReactNativeHost(this) { 19 | override fun getPackages(): List = 20 | PackageList(this).packages.apply { 21 | // Packages that cannot be autolinked yet can be added manually here, for example: 22 | // add(MyReactNativePackage()) 23 | } 24 | 25 | override fun getJSMainModuleName(): String = "index" 26 | 27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 28 | 29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 31 | } 32 | 33 | override val reactHost: ReactHost 34 | get() = getDefaultReactHost(applicationContext, reactNativeHost) 35 | 36 | override fun onCreate() { 37 | super.onCreate() 38 | SoLoader.init(this, OpenSourceMergedSoMapping) 39 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 40 | // If you opted-in for the New Architecture, we load the native entry point for this app. 41 | load() 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_native_ui_templates", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "lint": "eslint .", 9 | "start": "react-native start", 10 | "test": "jest" 11 | }, 12 | "dependencies": { 13 | "@aashu-dubey/react-native-rating-bar": "^0.3.6", 14 | "@miblanchard/react-native-slider": "^2.6.0", 15 | "@ptomasroos/react-native-multi-slider": "^2.2.2", 16 | "@react-native-community/blur": "^4.4.1", 17 | "@react-navigation/drawer": "^7.1.2", 18 | "@react-navigation/native": "^7.0.15", 19 | "@react-navigation/stack": "^7.1.2", 20 | "react": "19.0.0", 21 | "react-native": "0.78.0", 22 | "react-native-gesture-handler": "^2.24.0", 23 | "react-native-reanimated": "^3.17.1", 24 | "react-native-safe-area-context": "^5.3.0", 25 | "react-native-screens": "^4.9.1", 26 | "react-native-vector-icons": "^10.2.0" 27 | }, 28 | "devDependencies": { 29 | "@babel/core": "^7.25.2", 30 | "@babel/preset-env": "^7.25.3", 31 | "@babel/runtime": "^7.25.0", 32 | "@react-native-community/cli": "15.0.1", 33 | "@react-native-community/cli-platform-android": "15.0.1", 34 | "@react-native-community/cli-platform-ios": "15.0.1", 35 | "@react-native/babel-preset": "0.78.0", 36 | "@react-native/eslint-config": "0.78.0", 37 | "@react-native/metro-config": "0.78.0", 38 | "@react-native/typescript-config": "0.78.0", 39 | "@types/jest": "^29.5.13", 40 | "@types/react": "^19.0.0", 41 | "@types/react-native-vector-icons": "^6.4.18", 42 | "@types/react-test-renderer": "^19.0.0", 43 | "eslint": "^8.19.0", 44 | "jest": "^29.6.3", 45 | "prettier": "2.8.8", 46 | "react-test-renderer": "19.0.0", 47 | "typescript": "5.0.4" 48 | }, 49 | "engines": { 50 | "node": ">=18" 51 | }, 52 | "packageManager": "yarn@4.2.2" 53 | } 54 | -------------------------------------------------------------------------------- /ios/react_native_UI_Templates/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | react_native_ui_templates 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSAllowsLocalNetworking 32 | 33 | 34 | NSLocationWhenInUseUsageDescription 35 | 36 | UIAppFonts 37 | 38 | WorkSans-Bold.ttf 39 | WorkSans-Medium.ttf 40 | WorkSans-Regular.ttf 41 | WorkSans-SemiBold.ttf 42 | MaterialIcons.ttf 43 | 44 | UILaunchStoryboardName 45 | LaunchScreen 46 | UIRequiredDeviceCapabilities 47 | 48 | arm64 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UIViewControllerBasedStatusBarAppearance 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /.github/workflows/build-android.yml: -------------------------------------------------------------------------------- 1 | name: Build an Android APK 2 | 3 | on: 4 | push: 5 | paths: 6 | - '*' 7 | - '.github/workflows/build-android.yml' 8 | - 'android/**' 9 | - 'src/**' 10 | - '!**/*.md' 11 | branches: 12 | - main 13 | 14 | jobs: 15 | build-apk: 16 | permissions: 17 | contents: write 18 | name: Build Android APK 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | # 'corepack enable' is needed for now till it's experimental, may remove the command once it becomes stable in later node releases 25 | - name: Enable Corepack 26 | run: corepack enable 27 | 28 | # Setup Web environment to install packages. 29 | - name: Setup Web environment 30 | uses: actions/setup-node@v4 31 | with: 32 | node-version: '22' 33 | cache: 'yarn' 34 | 35 | # Setup Java environment in order to build the Android app. 36 | - name: Setup Java environment 37 | uses: actions/setup-java@v4 38 | with: 39 | distribution: 'zulu' 40 | java-version: '17' 41 | 42 | # Setup gradle using official gradle action 43 | - name: Setup Gradle 44 | uses: gradle/actions/setup-gradle@v4 45 | with: 46 | add-job-summary: 'on-failure' 47 | 48 | - name: Restore node_modules from cache 49 | uses: actions/cache@v4 50 | with: 51 | path: node_modules 52 | key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} 53 | restore-keys: ${{ runner.os }}-node-modules- 54 | 55 | # Here '--immutable' will only use commited 'yarn.lock', and will throw error if some update is needed 56 | - name: Install node_modules 57 | run: yarn install --immutable 58 | 59 | # In some cases, Gradle is not executable by default, so we do this before the build process 60 | - name: Make gradlew executable 61 | working-directory: android 62 | run: chmod +x ./gradlew 63 | 64 | - name: Build Android release APK 65 | working-directory: android 66 | run: ./gradlew assembleRelease --no-daemon 67 | 68 | - name: Save apk file as artifact 69 | uses: actions/upload-artifact@v4 70 | with: 71 | name: rn-ui-templates 72 | path: android/app/build/outputs/apk/release/app-release.apk -------------------------------------------------------------------------------- /src/introduction_animation/scenes/WelcomeView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { StyleSheet, Text, Animated, useWindowDimensions } from 'react-native'; 3 | import { AppImages } from '../../assets'; 4 | 5 | interface Props { 6 | animationController: React.RefObject; 7 | } 8 | 9 | const IMAGE_WIDTH = 350; 10 | const IMAGE_HEIGHT = 350; 11 | 12 | const WelcomeView: React.FC = ({ animationController }) => { 13 | const window = useWindowDimensions(); 14 | 15 | const careRef = useRef(null); 16 | 17 | const slideAnim = animationController.current.interpolate({ 18 | inputRange: [0, 0.6, 0.8], 19 | outputRange: [window.width, window.width, 0], 20 | }); 21 | 22 | const textEndVal = 26 * 2; // 26 being text's height (font size) 23 | const welcomeTextAnim = animationController.current.interpolate({ 24 | inputRange: [0, 0.6, 0.8], 25 | outputRange: [textEndVal, textEndVal, 0], 26 | }); 27 | 28 | const imageEndVal = IMAGE_WIDTH * 4; 29 | const imageAnim = animationController.current.interpolate({ 30 | inputRange: [0, 0.6, 0.8], 31 | outputRange: [imageEndVal, imageEndVal, 0], 32 | }); 33 | 34 | return ( 35 | 38 | 42 | 46 | Welcome 47 | 48 | 49 | Stay organised and live stress-free with you-do app 50 | 51 | 52 | ); 53 | }; 54 | 55 | const styles = StyleSheet.create({ 56 | container: { 57 | position: 'absolute', 58 | left: 0, 59 | right: 0, 60 | alignItems: 'center', 61 | paddingBottom: 100, 62 | }, 63 | image: { 64 | maxWidth: IMAGE_WIDTH, 65 | maxHeight: IMAGE_HEIGHT, 66 | }, 67 | title: { 68 | color: 'black', 69 | fontSize: 26, 70 | textAlign: 'center', 71 | fontFamily: 'WorkSans-Bold', 72 | }, 73 | subtitle: { 74 | color: 'black', 75 | textAlign: 'center', 76 | fontFamily: 'WorkSans-Regular', 77 | paddingHorizontal: 64, 78 | paddingVertical: 16, 79 | }, 80 | }); 81 | 82 | export default WelcomeView; 83 | -------------------------------------------------------------------------------- /src/introduction_animation/scenes/MoodDiaryView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { StyleSheet, Text, Animated, useWindowDimensions } from 'react-native'; 3 | import { AppImages } from '../../assets'; 4 | 5 | interface Props { 6 | animationController: React.RefObject; 7 | } 8 | 9 | const IMAGE_WIDTH = 350; 10 | const IMAGE_HEIGHT = 250; 11 | 12 | const MoodDiaryView: React.FC = ({ animationController }) => { 13 | const window = useWindowDimensions(); 14 | 15 | const careRef = useRef(null); 16 | 17 | const slideAnim = animationController.current.interpolate({ 18 | inputRange: [0, 0.4, 0.6, 0.8], 19 | outputRange: [window.width, window.width, 0, -window.width], 20 | }); 21 | 22 | const textEndVal = window.width * 2; // 26 being text's height (font size) 23 | const textAnim = animationController.current.interpolate({ 24 | inputRange: [0, 0.4, 0.6, 0.8], 25 | outputRange: [textEndVal, textEndVal, 0, -textEndVal], 26 | }); 27 | 28 | const imageEndVal = IMAGE_WIDTH * 4; 29 | const imageAnim = animationController.current.interpolate({ 30 | inputRange: [0, 0.4, 0.6, 0.8], 31 | outputRange: [imageEndVal, imageEndVal, 0, -imageEndVal], 32 | }); 33 | 34 | return ( 35 | 38 | 39 | Mood Dairy 40 | 41 | 44 | Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod 45 | tempor incididunt ut labore 46 | 47 | 51 | 52 | ); 53 | }; 54 | 55 | const styles = StyleSheet.create({ 56 | container: { 57 | position: 'absolute', 58 | left: 0, 59 | right: 0, 60 | alignItems: 'center', 61 | paddingBottom: 100, 62 | }, 63 | title: { 64 | color: 'black', 65 | fontSize: 26, 66 | textAlign: 'center', 67 | fontFamily: 'WorkSans-Bold', 68 | }, 69 | subtitle: { 70 | color: 'black', 71 | textAlign: 'center', 72 | fontFamily: 'WorkSans-Regular', 73 | paddingHorizontal: 64, 74 | paddingVertical: 16, 75 | }, 76 | image: { 77 | maxWidth: IMAGE_WIDTH, 78 | maxHeight: IMAGE_HEIGHT, 79 | }, 80 | }); 81 | 82 | export default MoodDiaryView; 83 | -------------------------------------------------------------------------------- /src/introduction_animation/scenes/RelaxView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { StyleSheet, Text, Animated, useWindowDimensions } from 'react-native'; 3 | import { AppImages } from '../../assets'; 4 | 5 | interface Props { 6 | animationController: React.RefObject; 7 | } 8 | 9 | const IMAGE_WIDTH = 350; 10 | const IMAGE_HEIGHT = 250; 11 | 12 | const RelaxView: React.FC = ({ animationController }) => { 13 | const window = useWindowDimensions(); 14 | 15 | const relaxRef = useRef(null); 16 | 17 | const relaxAnimation = animationController.current.interpolate({ 18 | inputRange: [0, 0.2, 0.8], 19 | outputRange: [-(26 * 2), 0, 0], 20 | }); 21 | const textAnim = animationController.current.interpolate({ 22 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 23 | outputRange: [0, 0, -window.width * 2, 0, 0], 24 | }); 25 | const imageAnim = animationController.current.interpolate({ 26 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 27 | outputRange: [0, 0, -350 * 4, 0, 0], 28 | }); 29 | const slideAnim = animationController.current.interpolate({ 30 | inputRange: [0, 0.2, 0.4, 0.8], 31 | outputRange: [0, 0, -window.width, -window.width], 32 | }); 33 | 34 | return ( 35 | 38 | 42 | Relax 43 | 44 | 47 | Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod 48 | tempor incididunt ut labore 49 | 50 | 54 | 55 | ); 56 | }; 57 | 58 | const styles = StyleSheet.create({ 59 | container: { 60 | alignItems: 'center', 61 | paddingBottom: 100, 62 | }, 63 | title: { 64 | color: 'black', 65 | fontSize: 26, 66 | textAlign: 'center', 67 | fontFamily: 'WorkSans-Bold', 68 | }, 69 | subtitle: { 70 | color: 'black', 71 | textAlign: 'center', 72 | fontFamily: 'WorkSans-Regular', 73 | paddingHorizontal: 64, 74 | paddingVertical: 16, 75 | }, 76 | image: { 77 | maxWidth: IMAGE_WIDTH, 78 | maxHeight: IMAGE_HEIGHT, 79 | }, 80 | }); 81 | 82 | export default RelaxView; 83 | -------------------------------------------------------------------------------- /src/introduction_animation/scenes/CareView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { StyleSheet, Text, Animated, useWindowDimensions } from 'react-native'; 3 | import { AppImages } from '../../assets'; 4 | 5 | interface Props { 6 | animationController: React.RefObject; 7 | } 8 | 9 | const IMAGE_WIDTH = 350; 10 | const IMAGE_HEIGHT = 250; 11 | 12 | const CareView: React.FC = ({ animationController }) => { 13 | const window = useWindowDimensions(); 14 | 15 | const careRef = useRef(null); 16 | 17 | const slideAnim = animationController.current.interpolate({ 18 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 19 | outputRange: [window.width, window.width, 0, -window.width, -window.width], 20 | }); 21 | 22 | const careEndVal = 26 * 2; // 26 being text's height (font size) 23 | const careAnim = animationController.current.interpolate({ 24 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 25 | outputRange: [careEndVal, careEndVal, 0, -careEndVal, -careEndVal], 26 | }); 27 | 28 | const imageEndVal = IMAGE_WIDTH * 4; 29 | const imageAnim = animationController.current.interpolate({ 30 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 31 | outputRange: [imageEndVal, imageEndVal, 0, -imageEndVal, -imageEndVal], 32 | }); 33 | 34 | return ( 35 | 38 | 42 | 46 | Care 47 | 48 | 49 | Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod 50 | tempor incididunt ut labore 51 | 52 | 53 | ); 54 | }; 55 | 56 | const styles = StyleSheet.create({ 57 | container: { 58 | position: 'absolute', 59 | left: 0, 60 | right: 0, 61 | alignItems: 'center', 62 | paddingBottom: 100, 63 | }, 64 | image: { 65 | maxWidth: IMAGE_WIDTH, 66 | maxHeight: IMAGE_HEIGHT, 67 | }, 68 | title: { 69 | color: 'black', 70 | fontSize: 26, 71 | textAlign: 'center', 72 | fontFamily: 'WorkSans-Bold', 73 | }, 74 | subtitle: { 75 | color: 'black', 76 | textAlign: 'center', 77 | fontFamily: 'WorkSans-Regular', 78 | paddingHorizontal: 64, 79 | paddingVertical: 16, 80 | }, 81 | }); 82 | 83 | export default CareView; 84 | -------------------------------------------------------------------------------- /src/introduction_animation/scenes/TopBackSkipView.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, Text, Animated, StatusBar } from 'react-native'; 3 | import { useSafeAreaInsets } from 'react-native-safe-area-context'; 4 | import Icon from 'react-native-vector-icons/MaterialIcons'; 5 | import MyPressable from '../../components/MyPressable'; 6 | import Config from '../../Config'; 7 | 8 | interface Props { 9 | onBackClick: () => void; 10 | onSkipClick: () => void; 11 | animationController: React.RefObject; 12 | } 13 | 14 | const TopBackSkipView: React.FC = ({ 15 | onBackClick, 16 | onSkipClick, 17 | animationController, 18 | }) => { 19 | const { top } = useSafeAreaInsets(); 20 | const marginTop = Config.isIos ? top : StatusBar.currentHeight; 21 | 22 | const headerTranslateY = animationController.current.interpolate({ 23 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 24 | outputRange: [-(58 + (marginTop ?? 0)), 0, 0, 0, 0], 25 | }); 26 | const skipAnim = animationController.current.interpolate({ 27 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 28 | outputRange: [0, 0, 0, 0, 80], 29 | }); 30 | 31 | return ( 32 | 38 | onBackClick()} 42 | > 43 | 44 | 45 | 46 | 47 | onSkipClick()} 50 | > 51 | 52 | Skip 53 | 54 | 55 | 56 | 57 | ); 58 | }; 59 | 60 | const styles = StyleSheet.create({ 61 | buttonContainer: { 62 | height: 58, 63 | flexDirection: 'row', 64 | alignItems: 'center', 65 | justifyContent: 'space-between', 66 | paddingLeft: 8, 67 | paddingRight: 16, 68 | position: 'absolute', 69 | top: 0, 70 | left: 0, 71 | right: 0, 72 | }, 73 | backBtn: { 74 | width: 56, 75 | height: 56, 76 | borderRadius: 30, 77 | justifyContent: 'center', 78 | alignItems: 'center', 79 | }, 80 | }); 81 | 82 | export default TopBackSkipView; 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native UI Templates 2 | 3 | Free UI templates created in react-native. 4 | 5 |

6 | How to create project specific local plugin | Ionic 6 | Capacitor 7 |

8 | 9 | ## 🧬 Samples 10 | | Project | | 11 | | :--- | --- | 12 | | **[> Expo Snack](https://snack.expo.io/@ashu_dubey/react-native-ui-templates)** (Not handled for web yet). | | 13 | |

1. Hotel Booking

Shows the list of hotels nearby with their ratings and other details, filter UI and custom calendar view etc.

**[> Browse](./src/hotel_booking#readme)**
**> Demo: [twitter](https://twitter.com/aashudubey_ad/status/1576292697173766145) \| [youtube](https://youtube.com/shorts/ioFcve0rYnc)** | Hotel Booking Preview | 14 | |

2. Design Course

A minimal UI showing list of courses related to UI design.

**[> Browse](./src/design_course#readme)**
**> Demo: [twitter](https://twitter.com/aashudubey_ad/status/1578846092694720512) \| [youtube](https://youtube.com/shorts/5G0obPHAdyc)** | Design Course Preview | 15 | |

3. Animated Onboarding

An onboarding UI flow with smooth animations, for a Mental Wellness App.

**[> Browse](./src/introduction_animation#readme)**
**> Demo: [twitter](https://twitter.com/aashudubey_ad/status/1580260456215695360) \| [youtube](https://youtube.com/shorts/AOD9FyiSR3U)** | Animated Onboarding Preview | 16 | 17 | ## 💪🏼 Getting Started 18 | 19 | This project is built on react-native CLI, so make sure you've [set up development environment](https://reactnative.dev/docs/environment-setup). 20 | 21 | ```bash 22 | # clone the project and cd into it 23 | git clone https://github.com/Aashu-Dubey/React-Native-UI-Templates.git 24 | cd ./React-Native-UI-Templates 25 | 26 | # install dependencies 27 | yarn install 28 | 29 | # iOS only 30 | npx pod-install ios 31 | # or 32 | cd ios && pod install && cd .. 33 | 34 | # Run iOS 35 | npx react-native run-ios 36 | 37 | # Run Android 38 | npx react-native run-android 39 | 40 | ``` 41 | 42 | ## 🌻 Motivation 43 | 44 | This was initially started as my learning project and is inspired from the Flutter project [Best-Flutter-UI-Templates](https://github.com/mitesh77/Best-Flutter-UI-Templates). 45 | 46 | ## 🔗 Links 47 | 48 | - [Original Flutter project](https://github.com/mitesh77/Best-Flutter-UI-Templates) 49 | - [Ionic-UI-Templates](https://github.com/Aashu-Dubey/Ionic-UI-Templates): Ionic version of this project. 50 | - [Twitter Post](https://twitter.com/aashudubey_ad/status/1484571529644212224) 51 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.7) 5 | base64 6 | nkf 7 | rexml 8 | activesupport (6.1.7.10) 9 | concurrent-ruby (~> 1.0, >= 1.0.2) 10 | i18n (>= 1.6, < 2) 11 | minitest (>= 5.1) 12 | tzinfo (~> 2.0) 13 | zeitwerk (~> 2.3) 14 | addressable (2.8.7) 15 | public_suffix (>= 2.0.2, < 7.0) 16 | algoliasearch (1.27.5) 17 | httpclient (~> 2.8, >= 2.8.3) 18 | json (>= 1.5.1) 19 | atomos (0.1.3) 20 | base64 (0.2.0) 21 | claide (1.1.0) 22 | cocoapods (1.15.2) 23 | addressable (~> 2.8) 24 | claide (>= 1.0.2, < 2.0) 25 | cocoapods-core (= 1.15.2) 26 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 27 | cocoapods-downloader (>= 2.1, < 3.0) 28 | cocoapods-plugins (>= 1.0.0, < 2.0) 29 | cocoapods-search (>= 1.0.0, < 2.0) 30 | cocoapods-trunk (>= 1.6.0, < 2.0) 31 | cocoapods-try (>= 1.1.0, < 2.0) 32 | colored2 (~> 3.1) 33 | escape (~> 0.0.4) 34 | fourflusher (>= 2.3.0, < 3.0) 35 | gh_inspector (~> 1.0) 36 | molinillo (~> 0.8.0) 37 | nap (~> 1.0) 38 | ruby-macho (>= 2.3.0, < 3.0) 39 | xcodeproj (>= 1.23.0, < 2.0) 40 | cocoapods-core (1.15.2) 41 | activesupport (>= 5.0, < 8) 42 | addressable (~> 2.8) 43 | algoliasearch (~> 1.0) 44 | concurrent-ruby (~> 1.1) 45 | fuzzy_match (~> 2.0.4) 46 | nap (~> 1.0) 47 | netrc (~> 0.11) 48 | public_suffix (~> 4.0) 49 | typhoeus (~> 1.0) 50 | cocoapods-deintegrate (1.0.5) 51 | cocoapods-downloader (2.1) 52 | cocoapods-plugins (1.0.0) 53 | nap 54 | cocoapods-search (1.0.1) 55 | cocoapods-trunk (1.6.0) 56 | nap (>= 0.8, < 2.0) 57 | netrc (~> 0.11) 58 | cocoapods-try (1.2.0) 59 | colored2 (3.1.2) 60 | concurrent-ruby (1.3.3) 61 | escape (0.0.4) 62 | ethon (0.16.0) 63 | ffi (>= 1.15.0) 64 | ffi (1.17.1) 65 | fourflusher (2.3.1) 66 | fuzzy_match (2.0.4) 67 | gh_inspector (1.1.3) 68 | httpclient (2.9.0) 69 | mutex_m 70 | i18n (1.14.7) 71 | concurrent-ruby (~> 1.0) 72 | json (2.7.6) 73 | minitest (5.25.4) 74 | molinillo (0.8.0) 75 | mutex_m (0.3.0) 76 | nanaimo (0.3.0) 77 | nap (1.1.0) 78 | netrc (0.11.0) 79 | nkf (0.2.0) 80 | public_suffix (4.0.7) 81 | rexml (3.4.1) 82 | ruby-macho (2.5.1) 83 | typhoeus (1.4.1) 84 | ethon (>= 0.9.0) 85 | tzinfo (2.0.6) 86 | concurrent-ruby (~> 1.0) 87 | xcodeproj (1.25.1) 88 | CFPropertyList (>= 2.3.3, < 4.0) 89 | atomos (~> 0.1.3) 90 | claide (>= 1.0.2, < 2.0) 91 | colored2 (~> 3.1) 92 | nanaimo (~> 0.3.0) 93 | rexml (>= 3.3.6, < 4.0) 94 | zeitwerk (2.6.18) 95 | 96 | PLATFORMS 97 | ruby 98 | 99 | DEPENDENCIES 100 | activesupport (>= 6.1.7.5, != 7.1.0) 101 | cocoapods (>= 1.13, != 1.15.1, != 1.15.0) 102 | concurrent-ruby (< 1.3.4) 103 | xcodeproj (< 1.26.0) 104 | 105 | RUBY VERSION 106 | ruby 2.6.10p210 107 | 108 | BUNDLED WITH 109 | 1.17.2 110 | -------------------------------------------------------------------------------- /src/components/Toast.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useRef, useImperativeHandle, useEffect } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Animated, 7 | ToastAndroid, 8 | useWindowDimensions, 9 | Platform, 10 | } from 'react-native'; 11 | 12 | interface Props {} 13 | 14 | export const DURATION = { 15 | LENGTH_SHORT: 2000, 16 | FOREVER: 0, 17 | }; 18 | 19 | const Toast: React.FC = React.forwardRef((_props, ref) => { 20 | const { height } = useWindowDimensions(); 21 | 22 | const [isShow, setShow] = useState(false); 23 | const [toastText, setToastText] = useState(''); 24 | const opacityValue = useRef(new Animated.Value(1)).current; 25 | let animation: Animated.CompositeAnimation | null = null; 26 | let timer: NodeJS.Timeout | null = null; 27 | let isShowing: boolean = false; 28 | 29 | useEffect(() => { 30 | return () => { 31 | animation && animation.stop(); 32 | timer && clearTimeout(timer); 33 | }; 34 | }, [animation, timer]); 35 | 36 | useImperativeHandle(ref, () => ({ 37 | show: (text: string) => { 38 | Platform.OS === 'android' 39 | ? ToastAndroid.show(text, ToastAndroid.SHORT) 40 | : show(text); 41 | }, 42 | })); 43 | 44 | const show = (text: string) => { 45 | setShow(true); 46 | setToastText(text); 47 | 48 | animation = Animated.timing(opacityValue, { 49 | toValue: 1, 50 | duration: 500, 51 | useNativeDriver: true, 52 | }); 53 | animation.start(() => { 54 | isShowing = true; 55 | close(); 56 | }); 57 | }; 58 | 59 | const close = () => { 60 | let delay = DURATION.LENGTH_SHORT; 61 | 62 | if (!isShowing && !isShow) { 63 | return; 64 | } 65 | timer && clearTimeout(timer); 66 | timer = setTimeout(() => { 67 | animation = Animated.timing(opacityValue, { 68 | toValue: 0.0, 69 | duration: 500, 70 | useNativeDriver: true, 71 | }); 72 | animation.start(() => { 73 | setShow(false); 74 | isShowing = false; 75 | }); 76 | }, delay); 77 | }; 78 | 79 | return ( 80 | <> 81 | {isShow && Platform.OS !== 'android' && ( 82 | 86 | 87 | {toastText} 88 | 89 | 90 | )} 91 | 92 | ); 93 | }); 94 | 95 | const styles = StyleSheet.create({ 96 | container: { 97 | position: 'absolute', 98 | left: 0, 99 | right: 0, 100 | elevation: 999, 101 | alignItems: 'center', 102 | zIndex: 10000, 103 | }, 104 | content: { 105 | backgroundColor: 'rgba(0,0,0,0.6)', 106 | borderRadius: 12, 107 | padding: 10, 108 | bottom: 64, 109 | maxWidth: '80%', 110 | }, 111 | text: { 112 | fontSize: 14, 113 | color: '#f8f8f8', 114 | textAlign: 'center', 115 | paddingHorizontal: 8, 116 | paddingVertical: 4, 117 | }, 118 | }); 119 | 120 | export default Toast; 121 | -------------------------------------------------------------------------------- /src/InviteFriendScene.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Image, 7 | Platform, 8 | StatusBar, 9 | useWindowDimensions, 10 | } from 'react-native'; 11 | import { 12 | SafeAreaView, 13 | useSafeAreaInsets, 14 | } from 'react-native-safe-area-context'; 15 | import { useNavigation } from '@react-navigation/native'; 16 | import { DrawerNavigationProp } from '@react-navigation/drawer'; 17 | import Icon from 'react-native-vector-icons/MaterialIcons'; 18 | import MyPressable from './components/MyPressable'; 19 | import { AppImages } from './assets'; 20 | 21 | const InviteFriendScene: React.FC = () => { 22 | const { width } = useWindowDimensions(); 23 | const navigation = useNavigation>(); 24 | const { top } = useSafeAreaInsets(); 25 | 26 | const imageSize = width - 32; 27 | const marginTop = Platform.OS === 'ios' ? top : StatusBar.currentHeight ?? 24; 28 | 29 | return ( 30 | 34 | 42 | Invite Your Friends 43 | 44 | Are you one of those who makes everything{'\n'} at the last moment? 45 | 46 | 47 | 48 | 49 | Share 50 | 51 | 52 | 53 | navigation.toggleDrawer()} 57 | > 58 | 59 | 60 | 61 | ); 62 | }; 63 | 64 | const styles = StyleSheet.create({ 65 | image: { 66 | backgroundColor: '#FEFEFE', 67 | alignSelf: 'center', 68 | }, 69 | title: { 70 | color: 'black', 71 | fontSize: 20, 72 | fontFamily: 'WorkSans-Bold', 73 | textAlign: 'center', 74 | paddingTop: 8, 75 | }, 76 | subTitle: { 77 | color: 'black', 78 | fontSize: 16, 79 | fontFamily: 'WorkSans-Regular', 80 | textAlign: 'center', 81 | paddingTop: 16, 82 | }, 83 | button: { 84 | flexDirection: 'row', 85 | width: 140, 86 | height: 40, 87 | padding: 8, 88 | backgroundColor: 'dodgerblue', 89 | borderRadius: 4, 90 | elevation: 8, 91 | alignItems: 'center', 92 | justifyContent: 'center', 93 | }, 94 | buttonText: { 95 | color: 'white', 96 | fontWeight: '500', 97 | textAlign: 'center', 98 | padding: 4, 99 | }, 100 | menuBtn: { 101 | position: 'absolute', 102 | padding: 8, 103 | left: 8, 104 | }, 105 | }); 106 | 107 | export default InviteFriendScene; 108 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /src/HelpScene.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Image, 7 | Platform, 8 | StatusBar, 9 | useWindowDimensions, 10 | } from 'react-native'; 11 | import { 12 | SafeAreaView, 13 | useSafeAreaInsets, 14 | } from 'react-native-safe-area-context'; 15 | import { useNavigation } from '@react-navigation/native'; 16 | import { DrawerNavigationProp } from '@react-navigation/drawer'; 17 | import Icon from 'react-native-vector-icons/MaterialIcons'; 18 | import MyPressable from './components/MyPressable'; 19 | import { AppImages } from './assets'; 20 | 21 | const HelpScene: React.FC = () => { 22 | const { width } = useWindowDimensions(); 23 | const navigation = useNavigation>(); 24 | const { top } = useSafeAreaInsets(); 25 | 26 | const imageSize = width - 32; 27 | const marginTop = Platform.OS === 'ios' ? top : StatusBar.currentHeight ?? 24; 28 | 29 | return ( 30 | 34 | 42 | How can we help you? 43 | 44 | It looks like you are experiencing problems{'\n'}with our sign up 45 | process. We are here to{'\n'}help so please get in touch with us 46 | 47 | 48 | 49 | Chat with Us 50 | 51 | 52 | 53 | navigation.openDrawer()} 57 | > 58 | 59 | 60 | 61 | ); 62 | }; 63 | 64 | const styles = StyleSheet.create({ 65 | image: { 66 | backgroundColor: '#FEFEFE', 67 | alignSelf: 'center', 68 | }, 69 | title: { 70 | color: 'black', 71 | fontSize: 20, 72 | fontFamily: 'WorkSans-Bold', 73 | textAlign: 'center', 74 | paddingTop: 8, 75 | }, 76 | subTitle: { 77 | color: 'black', 78 | fontSize: 16, 79 | fontFamily: 'WorkSans-Regular', 80 | textAlign: 'center', 81 | paddingTop: 16, 82 | }, 83 | buttonContainer: { 84 | flex: 1, 85 | justifyContent: 'center', 86 | alignItems: 'center', 87 | }, 88 | button: { 89 | width: 140, 90 | height: 40, 91 | padding: 8, 92 | backgroundColor: 'dodgerblue', 93 | borderRadius: 4, 94 | elevation: 8, 95 | justifyContent: 'center', 96 | }, 97 | buttonText: { 98 | color: 'white', 99 | fontWeight: '500', 100 | textAlign: 'center', 101 | padding: 4, 102 | }, 103 | menuBtn: { 104 | position: 'absolute', 105 | padding: 8, 106 | left: 8, 107 | }, 108 | }); 109 | 110 | export default HelpScene; 111 | -------------------------------------------------------------------------------- /src/introduction_animation/scenes/SplashView.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Image, 7 | Animated, 8 | useWindowDimensions, 9 | ScrollView, 10 | } from 'react-native'; 11 | import { useSafeAreaInsets } from 'react-native-safe-area-context'; 12 | import MyPressable from '../../components/MyPressable'; 13 | import { AppImages } from '../../assets'; 14 | 15 | interface Props { 16 | onNextClick: () => void; 17 | animationController: React.RefObject; 18 | } 19 | 20 | const SplashView: React.FC = ({ onNextClick, animationController }) => { 21 | const window = useWindowDimensions(); 22 | const insets = useSafeAreaInsets(); 23 | 24 | const splashTranslateY = animationController.current.interpolate({ 25 | inputRange: [0, 0.2, 0.8], 26 | outputRange: [0, -window.height, -window.height], 27 | }); 28 | 29 | const introImageData = Image.resolveAssetSource(AppImages.introduction_image); 30 | 31 | return ( 32 | 35 | 36 | 37 | 47 | 48 | Clearhead 49 | 50 | Lorem ipsum dolor sit amet,consectetur{'\n'}adipiscing elit,sed do 51 | eiusmod tempor{'\n'}incididunt ut labore 52 | 53 | 54 | 55 | 56 | 57 | onNextClick()} 62 | > 63 | Let's begin 64 | 65 | 66 | 67 | 68 | ); 69 | }; 70 | 71 | const styles = StyleSheet.create({ 72 | title: { 73 | color: 'black', 74 | fontSize: 25, 75 | textAlign: 'center', 76 | fontFamily: 'WorkSans-Bold', 77 | paddingVertical: 8, 78 | }, 79 | subtitle: { 80 | color: 'black', 81 | textAlign: 'center', 82 | fontFamily: 'WorkSans-Regular', 83 | paddingHorizontal: 24, 84 | }, 85 | footer: { 86 | flexGrow: 1, 87 | justifyContent: 'center', 88 | paddingTop: 8, 89 | }, 90 | buttonContainer: { 91 | borderRadius: 38, 92 | overflow: 'hidden', 93 | alignSelf: 'center', 94 | }, 95 | button: { 96 | height: 58, 97 | backgroundColor: 'rgb(21, 32, 54)', 98 | paddingVertical: 16, 99 | paddingHorizontal: 56, 100 | }, 101 | buttonText: { 102 | fontSize: 18, 103 | fontFamily: 'WorkSans-Regular', 104 | color: 'white', 105 | }, 106 | }); 107 | 108 | export default SplashView; 109 | -------------------------------------------------------------------------------- /src/AppNavigator.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StatusBar, StyleSheet, useWindowDimensions } from 'react-native'; 3 | import { createDrawerNavigator } from '@react-navigation/drawer'; 4 | import { createStackNavigator } from '@react-navigation/stack'; 5 | // import { createNativeStackNavigator } from '@react-navigation/native-stack'; 6 | import { 7 | HomeScene, 8 | DrawerContent, 9 | HelpScene, 10 | FeedbackScene, 11 | InviteFriendScene, 12 | } from '.'; 13 | import { CourseInfoScreen, HomeDesignCourse } from './design_course'; 14 | import { IntroductionAnimationScreen } from './introduction_animation'; 15 | import HotelHomeScreen from './hotel_booking/HotelHomeScreen'; 16 | 17 | const Drawer = createDrawerNavigator(); 18 | /** 19 | * TODO:- Temporarily using r-nav-stack instead of r-nav-native-stack cause of following issue: 20 | * https://github.com/react-navigation/react-navigation/issues/10941 21 | * Replace with r-nav-native-stack, once this is fixed. 22 | */ 23 | const Stack = createStackNavigator(); 24 | // const Stack = createNativeStackNavigator(); 25 | 26 | const DrawerNavigator: React.FC = () => { 27 | const window = useWindowDimensions(); 28 | 29 | return ( 30 | } 44 | // this is just to enable shadow/elevation style on drawer, as it fallback to JS drawer solution instead of native one (v6) 45 | // as explained here:- https://github.com/react-navigation/react-navigation/issues/10946#issuecomment-1287082343 46 | detachInactiveScreens={false} 47 | > 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | }; 55 | 56 | export default () => { 57 | return ( 58 | <> 59 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 79 | 80 | 81 | ); 82 | }; 83 | 84 | const styles = StyleSheet.create({ 85 | drawerSceneContainer: { 86 | elevation: 24, 87 | shadowColor: 'grey', 88 | shadowOffset: { width: 0, height: 12 }, 89 | shadowOpacity: 0.58, 90 | shadowRadius: 16.0, 91 | }, 92 | }); 93 | -------------------------------------------------------------------------------- /ios/react_native_UI_Templates.xcodeproj/xcshareddata/xcschemes/react_native_UI_Templates.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /.github/workflows/build-ios-simulator.yml: -------------------------------------------------------------------------------- 1 | name: Create an iOS Simulator build 2 | 3 | on: 4 | push: 5 | paths: 6 | - '*' 7 | - '.github/workflows/build-ios-simulator.yml' 8 | - 'ios/**' 9 | - 'src/**' 10 | - '!**/*.md' 11 | branches: 12 | - main 13 | 14 | jobs: 15 | build-ios-simulator: 16 | name: Create an iOS Simulator build 17 | runs-on: macos-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | # 'corepack enable' is needed for now till it's experimental, may remove the command once it becomes stable in later node releases 23 | - name: Enable Corepack 24 | run: corepack enable 25 | 26 | # Setup Web environment to install packages. 27 | - name: Setup Web environment 28 | uses: actions/setup-node@v4 29 | with: 30 | node-version: '22' 31 | cache: 'yarn' 32 | 33 | - uses: hendrikmuhs/ccache-action@v1.2 34 | name: Xcode Compile Cache 35 | with: 36 | key: ${{ runner.os }}-ccache # makes a unique key w/related restore key internally 37 | create-symlink: true 38 | max-size: 1500M 39 | 40 | - name: Restore node_modules from cache 41 | uses: actions/cache@v4 42 | with: 43 | path: node_modules 44 | key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} 45 | restore-keys: ${{ runner.os }}-node-modules- 46 | 47 | # Here '--immutable' will only use commited 'yarn.lock', and will throw error if some update is needed 48 | - name: Install node_modules 49 | run: yarn install --immutable 50 | 51 | - name: Restore Pods cache 52 | uses: actions/cache@v4 53 | with: 54 | path: | 55 | ios/Pods 56 | ~/Library/Caches/CocoaPods 57 | ~/.cocoapods 58 | key: ${{ runner.os }}-pods-${{ hashFiles('ios/Podfile.lock') }} 59 | restore-keys: ${{ runner.os }}-pods- 60 | 61 | - name: Restore build artifacts from cache 62 | uses: actions/cache@v4 63 | with: 64 | path: ios/build 65 | key: ${{ runner.os }}-ios-derived-data-${{ hashFiles('ios/Podfile.lock') }} 66 | restore-keys: ${{ runner.os }}-ios-derived-data- 67 | 68 | - name: Install Pod files 69 | run: npx pod-install ios 70 | 71 | - name: Install xcpretty 72 | run: gem install xcpretty 73 | 74 | - name: Run simulator build command 75 | working-directory: ios 76 | run: | 77 | export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros 78 | export CCACHE_FILECLONE=true 79 | export CCACHE_DEPEND=true 80 | export CCACHE_INODECACHE=true 81 | export CCACHE_LIMIT_MULTIPLE=0.95 82 | ccache -s 83 | set -o pipefail 84 | xcodebuild \ 85 | CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \ 86 | -scheme react_native_UI_Templates \ 87 | -workspace react_native_UI_Templates.xcworkspace \ 88 | -sdk iphonesimulator \ 89 | -configuration Release \ 90 | -derivedDataPath build | xcpretty 91 | ccache -s 92 | 93 | - name: Store build .app file as zip 94 | working-directory: ios 95 | run: | 96 | cd build/Build/Products/Release-iphonesimulator 97 | mkdir -p output 98 | zip -r -y -o output/react_native_ui_templates.zip react_native_ui_templates.app 99 | 100 | - name: Save build file as artifact 101 | uses: actions/upload-artifact@v4 102 | with: 103 | name: rn_ui_templates_ios 104 | path: ios/build/Build/Products/Release-iphonesimulator/output 105 | -------------------------------------------------------------------------------- /src/design_course/PopulerCourseListView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Animated, 7 | ListRenderItemInfo, 8 | Image, 9 | } from 'react-native'; 10 | import Icon from 'react-native-vector-icons/MaterialIcons'; 11 | import MyPressable from '../components/MyPressable'; 12 | import { CategoryType } from './model/category'; 13 | 14 | interface Props { 15 | data: ListRenderItemInfo; 16 | onScreenClicked: () => void; 17 | } 18 | 19 | const PopulerCourseListView: React.FC = ({ data, onScreenClicked }) => { 20 | const { index, item } = data; 21 | 22 | const translateY = useRef(new Animated.Value(50)).current; 23 | const opacity = useRef(new Animated.Value(0)).current; 24 | 25 | useEffect(() => { 26 | Animated.parallel([ 27 | Animated.timing(translateY, { 28 | toValue: 0, 29 | duration: 1000, 30 | delay: index * (1000 / 3), 31 | useNativeDriver: true, 32 | }), 33 | Animated.timing(opacity, { 34 | toValue: 1, 35 | duration: 1000, 36 | delay: index * (1000 / 3), 37 | useNativeDriver: true, 38 | }), 39 | ]).start(); 40 | }); 41 | 42 | return ( 43 | 47 | 52 | 53 | 54 | 55 | {item.title} 56 | 57 | 58 | {item.lessonCount} lesson 59 | 60 | {item.rating} 61 | 62 | 63 | 64 | 65 | 66 | 70 | 71 | 72 | 73 | 74 | 75 | ); 76 | }; 77 | 78 | const styles = StyleSheet.create({ 79 | container: { 80 | flex: 1, 81 | borderRadius: 16, 82 | overflow: 'hidden', 83 | marginHorizontal: 16, 84 | }, 85 | bgColorView: { 86 | flex: 1, 87 | marginBottom: 48, 88 | borderRadius: 16, 89 | backgroundColor: '#F8FAFB', 90 | }, 91 | title: { 92 | fontSize: 16, 93 | fontFamily: 'WorkSans-SemiBold', 94 | letterSpacing: 0.27, 95 | color: 'rgb(23, 38, 42)', 96 | }, 97 | lessionCountRatingContainer: { 98 | flexDirection: 'row', 99 | alignItems: 'center', 100 | paddingTop: 8, 101 | }, 102 | textStyle: { 103 | fontSize: 18, 104 | fontFamily: 'WorkSans-Regular', 105 | letterSpacing: 0.27, 106 | color: 'rgb(58, 81, 96)', 107 | }, 108 | imageContainer: { 109 | borderRadius: 16, 110 | marginHorizontal: 16, 111 | marginBottom: 4, 112 | backgroundColor: 'white', 113 | elevation: 6, 114 | shadowColor: 'grey', 115 | shadowOffset: { width: 0, height: 0 }, 116 | shadowOpacity: 0.22, 117 | shadowRadius: 6.0, 118 | }, 119 | }); 120 | 121 | export default PopulerCourseListView; 122 | -------------------------------------------------------------------------------- /src/introduction_animation/scenes/components/NextButtonArrow.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { StyleSheet, Text, Animated } from 'react-native'; 3 | import Icon from 'react-native-vector-icons/MaterialIcons'; 4 | import MyPressable from '../../../components/MyPressable'; 5 | 6 | interface Props { 7 | onBtnPress: () => void; 8 | animationController: React.MutableRefObject; 9 | } 10 | 11 | const IconPressable = Animated.createAnimatedComponent(Icon); 12 | 13 | /* 14 | * TODO:- find better solution for this animation so we don't have to use 'useNativeDriver: false' in 'IntroductionAnimationScreen.tsx' as width doesn't support it yet 15 | */ 16 | const NextButtonArrow: React.FC = ({ 17 | onBtnPress, 18 | animationController, 19 | }) => { 20 | const arrowAnim = useRef>( 21 | new Animated.Value(0), 22 | ); 23 | 24 | arrowAnim.current = animationController.current.interpolate({ 25 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 26 | outputRange: [0, 0, 0, 0, 1], 27 | }); 28 | 29 | // for transition from arrow to sign up 30 | const transitionAnim = arrowAnim.current.interpolate({ 31 | inputRange: [0, 0.85, 1], 32 | outputRange: [36, 0, 0], 33 | }); 34 | const opacityAnim = arrowAnim.current.interpolate({ 35 | inputRange: [0, 0.7, 1], 36 | outputRange: [0, 0, 1], 37 | }); 38 | const iconTransitionAnim = arrowAnim.current.interpolate({ 39 | inputRange: [0, 0.35, 0.85, 1], // or [0, 0.85, 1], 40 | outputRange: [0, 0, -36, -36], // or [0, 0, -36] 41 | }); 42 | const iconOpacityAnim = arrowAnim.current.interpolate({ 43 | inputRange: [0, 0.7, 1], 44 | outputRange: [1, 0, 0], 45 | }); 46 | // end 47 | 48 | const widthAnim = arrowAnim.current.interpolate({ 49 | inputRange: [0, 1], 50 | outputRange: [58, 258], 51 | }); 52 | 53 | const marginBottomAnim = arrowAnim.current.interpolate({ 54 | inputRange: [0, 1], 55 | outputRange: [38, 0], 56 | }); 57 | 58 | const radiusAnim = arrowAnim.current.interpolate({ 59 | inputRange: [0, 1], 60 | outputRange: [40, 8], 61 | }); 62 | 63 | return ( 64 | 74 | onBtnPress()} 78 | > 79 | 88 | Sign Up 89 | 90 | 91 | 92 | 104 | 105 | 106 | ); 107 | }; 108 | 109 | const styles = StyleSheet.create({ 110 | container: { 111 | height: 58, 112 | backgroundColor: 'rgb(21, 32, 54)', 113 | overflow: 'hidden', 114 | }, 115 | signupContainer: { 116 | flexDirection: 'row', 117 | justifyContent: 'space-between', 118 | paddingHorizontal: 16, 119 | }, 120 | signupText: { 121 | fontSize: 18, 122 | fontFamily: 'WorkSans-Medium', 123 | color: 'white', 124 | }, 125 | icon: { 126 | position: 'absolute', 127 | alignSelf: 'center', 128 | }, 129 | }); 130 | 131 | export default NextButtonArrow; 132 | -------------------------------------------------------------------------------- /src/design_course/CategoryListView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Animated, 7 | Image, 8 | ListRenderItemInfo, 9 | } from 'react-native'; 10 | import Icon from 'react-native-vector-icons/MaterialIcons'; 11 | import MyPressable from '../components/MyPressable'; 12 | import { CategoryType } from './model/category'; 13 | 14 | interface Props { 15 | data: ListRenderItemInfo; 16 | onScreenClicked: () => void; 17 | } 18 | 19 | const CategoryListView: React.FC = ({ data, onScreenClicked }) => { 20 | const { index, item } = data; 21 | 22 | const translateX = useRef(new Animated.Value(50)); 23 | const opacity = useRef(new Animated.Value(0)); 24 | 25 | useEffect(() => { 26 | Animated.parallel([ 27 | Animated.timing(translateX.current, { 28 | toValue: 0, 29 | duration: 1000, 30 | delay: index * (1000 / 3), 31 | useNativeDriver: true, 32 | }), 33 | Animated.timing(opacity.current, { 34 | toValue: 1, 35 | duration: 1000, 36 | delay: index * (1000 / 3), 37 | useNativeDriver: true, 38 | }), 39 | ]).start(); 40 | }, [index]); 41 | 42 | return ( 43 | 52 | 57 | 58 | 59 | 62 | 63 | 67 | 68 | 69 | {item.title} 70 | 71 | 72 | {item.lessonCount} lesson 73 | 74 | {item.rating} 75 | 76 | 77 | 78 | 79 | ${item.money} 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | ); 90 | }; 91 | 92 | const styles = StyleSheet.create({ 93 | container: { borderRadius: 16, overflow: 'hidden' }, 94 | bgColorView: { 95 | flex: 1, 96 | marginLeft: 48, 97 | borderRadius: 16, 98 | backgroundColor: '#F8FAFB', 99 | }, 100 | title: { 101 | fontSize: 16, 102 | fontFamily: 'WorkSans-SemiBold', 103 | letterSpacing: 0.27, 104 | color: 'rgb(23, 38, 42)', 105 | }, 106 | lessionCountRatingContainer: { 107 | flexDirection: 'row', 108 | alignItems: 'center', 109 | paddingRight: 16, 110 | paddingBottom: 8, 111 | }, 112 | textStyle: { 113 | fontSize: 18, 114 | fontFamily: 'WorkSans-Regular', 115 | letterSpacing: 0.27, 116 | color: 'rgb(58, 81, 96)', 117 | }, 118 | moneyText: { 119 | flex: 1, 120 | fontFamily: 'WorkSans-SemiBold', 121 | color: 'rgb(0, 182, 240)', 122 | }, 123 | addIconView: { 124 | padding: 4, 125 | backgroundColor: 'rgb(0, 182, 240)', 126 | borderRadius: 8, 127 | }, 128 | }); 129 | 130 | export default CategoryListView; 131 | -------------------------------------------------------------------------------- /src/FeedbackScene.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | TextInput, 7 | Platform, 8 | StatusBar, 9 | Image, 10 | KeyboardAvoidingView, 11 | useWindowDimensions, 12 | ScrollView, 13 | } from 'react-native'; 14 | import { 15 | SafeAreaView, 16 | useSafeAreaInsets, 17 | } from 'react-native-safe-area-context'; 18 | import { useNavigation } from '@react-navigation/native'; 19 | import { DrawerNavigationProp } from '@react-navigation/drawer'; 20 | import Icon from 'react-native-vector-icons/MaterialIcons'; 21 | import MyPressable from './components/MyPressable'; 22 | import { AppImages } from './assets'; 23 | 24 | const FeedbackScene: React.FC = () => { 25 | const { width } = useWindowDimensions(); 26 | const navigation = useNavigation>(); 27 | const { top } = useSafeAreaInsets(); 28 | 29 | const imageSize = width - 32; 30 | const marginTop = Platform.OS === 'ios' ? top : StatusBar.currentHeight ?? 24; 31 | 32 | return ( 33 | 37 | 38 | 39 | 47 | Your FeedBack 48 | 49 | Give your best time for this moment. 50 | 51 | 52 | 58 | 59 | 60 | 61 | Send 62 | 63 | 64 | 65 | 66 | navigation.openDrawer()} 70 | > 71 | 72 | 73 | 74 | ); 75 | }; 76 | 77 | const styles = StyleSheet.create({ 78 | image: { 79 | backgroundColor: '#FEFEFE', 80 | alignSelf: 'center', 81 | }, 82 | title: { 83 | color: 'black', 84 | fontSize: 20, 85 | fontFamily: 'WorkSans-Bold', 86 | textAlign: 'center', 87 | paddingTop: 8, 88 | }, 89 | subTitle: { 90 | color: 'black', 91 | fontSize: 16, 92 | fontFamily: 'WorkSans-Regular', 93 | textAlign: 'center', 94 | paddingTop: 16, 95 | }, 96 | inputContainer: { 97 | minHeight: 80, 98 | maxHeight: 160, 99 | marginTop: 16, 100 | marginHorizontal: 32, 101 | padding: 16, 102 | backgroundColor: 'white', 103 | borderRadius: 8, 104 | elevation: 8, 105 | shadowColor: 'rgba(158, 158, 158, 0.8)', 106 | shadowOffset: { width: 4, height: 4 }, 107 | shadowOpacity: 0.8, 108 | shadowRadius: 8, 109 | }, 110 | input: { 111 | height: 48, 112 | color: 'black', 113 | fontSize: 16, 114 | fontFamily: 'WorkSans-Regular', 115 | textAlignVertical: 'top', 116 | }, 117 | button: { 118 | width: 120, 119 | height: 40, 120 | padding: 8, 121 | marginTop: 16, 122 | alignSelf: 'center', 123 | justifyContent: 'center', 124 | backgroundColor: 'dodgerblue', 125 | borderRadius: 4, 126 | elevation: 8, 127 | }, 128 | buttonText: { 129 | color: 'white', 130 | fontWeight: '500', 131 | textAlign: 'center', 132 | padding: 4, 133 | }, 134 | menuBtn: { 135 | position: 'absolute', 136 | padding: 8, 137 | left: 8, 138 | }, 139 | }); 140 | 141 | export default FeedbackScene; 142 | -------------------------------------------------------------------------------- /src/introduction_animation/IntroductionAnimationScreen.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useEffect, useRef, useState } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | useWindowDimensions, 6 | Animated, 7 | Easing, 8 | StatusBar, 9 | } from 'react-native'; 10 | import { useNavigation } from '@react-navigation/native'; 11 | import { 12 | SplashView, 13 | RelaxView, 14 | CareView, 15 | MoodDiaryView, 16 | WelcomeView, 17 | TopBackSkipView, 18 | CenterNextButton, 19 | } from './scenes'; 20 | 21 | const IntroductionAnimationScreen: React.FC = () => { 22 | const navigation = useNavigation(); 23 | const window = useWindowDimensions(); 24 | 25 | const [currentPage, setCurrentPage] = useState(0); 26 | 27 | const animationController = useRef(new Animated.Value(0)); 28 | const animValue = useRef(0); 29 | 30 | useEffect(() => { 31 | animationController.current.addListener(({ value }) => { 32 | animValue.current = value; 33 | setCurrentPage(value); 34 | }); 35 | }, []); 36 | 37 | const relaxTranslateY = animationController.current.interpolate({ 38 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 39 | outputRange: [window.height, 0, 0, 0, 0], 40 | }); 41 | 42 | const playAnimation = useCallback( 43 | (toValue: number, duration: number = 1600) => { 44 | Animated.timing(animationController.current, { 45 | toValue, 46 | duration, 47 | easing: Easing.bezier(0.4, 0.0, 0.2, 1.0), 48 | // here it is false only cause of width animation in 'NextButtonArrow.tsx', as width doesn't support useNativeDriver: true 49 | // TODO:- find better solution so we can use true here and animation also work 50 | useNativeDriver: false, 51 | }).start(); 52 | }, 53 | [], 54 | ); 55 | 56 | const onNextClick = useCallback(() => { 57 | let toValue; 58 | if (animValue.current === 0) { 59 | toValue = 0.2; 60 | } else if (animValue.current >= 0 && animValue.current <= 0.2) { 61 | toValue = 0.4; 62 | } else if (animValue.current > 0.2 && animValue.current <= 0.4) { 63 | toValue = 0.6; 64 | } else if (animValue.current > 0.4 && animValue.current <= 0.6) { 65 | toValue = 0.8; 66 | } else if (animValue.current > 0.6 && animValue.current <= 0.8) { 67 | navigation.goBack(); 68 | } 69 | 70 | toValue !== undefined && playAnimation(toValue); 71 | }, [playAnimation, navigation]); 72 | 73 | const onBackClick = useCallback(() => { 74 | let toValue; 75 | if (animValue.current >= 0.2 && animValue.current < 0.4) { 76 | toValue = 0.0; 77 | } else if (animValue.current >= 0.4 && animValue.current < 0.6) { 78 | toValue = 0.2; 79 | } else if (animValue.current >= 0.6 && animValue.current < 0.8) { 80 | toValue = 0.4; 81 | } else if (animValue.current === 0.8) { 82 | toValue = 0.6; 83 | } 84 | 85 | toValue !== undefined && playAnimation(toValue); 86 | }, [playAnimation]); 87 | 88 | const onSkipClick = useCallback(() => { 89 | playAnimation(0.8, 1200); 90 | }, [playAnimation]); 91 | 92 | return ( 93 | 94 | 0 ? 'dark' : 'light'}-content`} /> 95 | 96 | 97 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | ); 117 | }; 118 | 119 | const styles = StyleSheet.create({ 120 | scenesContainer: { 121 | justifyContent: 'center', 122 | ...StyleSheet.absoluteFillObject, 123 | }, 124 | }); 125 | 126 | export default IntroductionAnimationScreen; 127 | -------------------------------------------------------------------------------- /ios/react_native_UI_Templates/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/hotel_booking/RangeSliderView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | useWindowDimensions, 7 | StyleProp, 8 | ViewStyle, 9 | } from 'react-native'; 10 | import MultiSlider, { LabelProps } from '@ptomasroos/react-native-multi-slider'; 11 | 12 | const customMarker = (triangleStyle: StyleProp) => ( 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | 20 | const RangeSliderView: React.FC = () => { 21 | const { width } = useWindowDimensions(); 22 | 23 | const { containerStyle, trackStyle, selectedStyle } = styles; 24 | 25 | const customLabel = useCallback( 26 | (prop: LabelProps) => { 27 | const { 28 | oneMarkerValue, 29 | twoMarkerValue, 30 | oneMarkerLeftPosition, 31 | twoMarkerLeftPosition, 32 | } = prop; 33 | const leftLabelDistance = oneMarkerLeftPosition - (width - 32) / 2 + 3; 34 | const rightLabelDistance = twoMarkerLeftPosition - 18 / 2 + 3; 35 | 36 | return ( 37 | 38 | {Number.isFinite(oneMarkerLeftPosition) && 39 | Number.isFinite(oneMarkerValue) && ( 40 | 41 | ${oneMarkerValue} 42 | 43 | )} 44 | 45 | {Number.isFinite(twoMarkerLeftPosition) && 46 | Number.isFinite(twoMarkerValue) && ( 47 | 53 | ${twoMarkerValue} 54 | 55 | )} 56 | 57 | ); 58 | }, 59 | [width], 60 | ); 61 | 62 | return ( 63 | customMarker(styles.triangleLeftStyle)} 72 | customMarkerRight={_ => customMarker(styles.triangleRightStyle)} 73 | enableLabel 74 | customLabel={customLabel} 75 | /> 76 | ); 77 | }; 78 | 79 | const styles = StyleSheet.create({ 80 | containerStyle: { 81 | flex: 1, 82 | justifyContent: 'center', 83 | marginHorizontal: 16, 84 | marginBottom: 8, 85 | alignSelf: 'center', 86 | }, 87 | trackStyle: { 88 | backgroundColor: 'lightgrey', 89 | height: 4, 90 | borderRadius: 8, 91 | }, 92 | selectedStyle: { 93 | backgroundColor: '#54D3C2', 94 | height: 6, 95 | borderRadius: 8, 96 | }, 97 | sliderLabel: { minWidth: 50, padding: 8 }, 98 | sliderLabelText: { 99 | color: 'black', 100 | textAlign: 'center', 101 | }, 102 | triangleRightStyle: { 103 | width: 0, 104 | height: 0, 105 | borderLeftWidth: 8, 106 | borderBottomWidth: 5, 107 | borderTopWidth: 5, 108 | borderStyle: 'solid', 109 | backgroundColor: 'transparent', 110 | borderLeftColor: 'white', 111 | borderBottomColor: 'transparent', 112 | borderTopColor: 'transparent', 113 | marginLeft: 7, 114 | }, 115 | triangleLeftStyle: { 116 | width: 0, 117 | height: 0, 118 | borderRightWidth: 8, 119 | borderBottomWidth: 5, 120 | borderTopWidth: 5, 121 | borderStyle: 'solid', 122 | backgroundColor: 'transparent', 123 | borderRightColor: 'white', 124 | borderBottomColor: 'transparent', 125 | borderTopColor: 'transparent', 126 | marginLeft: 5, 127 | }, 128 | markerStyle: { 129 | width: 24, 130 | height: 24, 131 | borderRadius: 12, 132 | backgroundColor: '#54D3C2', 133 | borderColor: 'white', 134 | borderWidth: 2, 135 | justifyContent: 'center', 136 | shadowColor: 'black', 137 | shadowOffset: { width: 0, height: 0 }, 138 | shadowOpacity: 0.5, 139 | shadowRadius: 7.49, 140 | }, 141 | shadowBg: { 142 | width: 30, 143 | height: 30, 144 | borderRadius: 15, 145 | // backgroundColor: 'rgba(128, 128, 128, 0.1)', 146 | justifyContent: 'center', 147 | alignItems: 'center', 148 | elevation: 12, 149 | }, 150 | }); 151 | 152 | export default RangeSliderView; 153 | -------------------------------------------------------------------------------- /src/hotel_booking/HotelListItem.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Image, 7 | Animated, 8 | ListRenderItemInfo, 9 | useWindowDimensions, 10 | } from 'react-native'; 11 | import { RatingBar } from '@aashu-dubey/react-native-rating-bar'; 12 | import Icon from 'react-native-vector-icons/MaterialIcons'; 13 | import { HotelListType } from './model/hotel_list_data'; 14 | 15 | interface Props { 16 | data: ListRenderItemInfo; 17 | } 18 | 19 | const HotelListItem: React.FC = ({ data }) => { 20 | const { item, index } = data; 21 | 22 | const { width } = useWindowDimensions(); 23 | 24 | const translateY = useRef(new Animated.Value(50)).current; 25 | const opacity = useRef(new Animated.Value(0)).current; 26 | 27 | const imageSize = width - 48; 28 | 29 | useEffect(() => { 30 | Animated.parallel([ 31 | Animated.timing(translateY, { 32 | toValue: 0, 33 | duration: 400, 34 | delay: index * (400 / 3), 35 | useNativeDriver: true, 36 | }), 37 | Animated.timing(opacity, { 38 | toValue: 1, 39 | duration: 400, 40 | delay: index * (400 / 3), 41 | useNativeDriver: true, 42 | }), 43 | ]).start(); 44 | }); 45 | 46 | return ( 47 | 50 | 51 | 56 | 62 | 63 | 64 | 65 | {item.titleTxt} 66 | ${item.perNight} 67 | 68 | 69 | 70 | {item.subTxt} 71 | 72 | 73 | {Number(item.dist.toPrecision(2))} km to city 74 | 75 | 76 | /per night 77 | 78 | 79 | , 88 | half: , 89 | empty: , 90 | }} 91 | /> 92 | {item.reviews} Reviews 93 | 94 | 95 | 96 | ); 97 | }; 98 | 99 | const textStyle = { 100 | color: 'rgba(128,128,128, 0.6)', 101 | fontFamily: 'WorkSans-Regular', 102 | }; 103 | const styles = StyleSheet.create({ 104 | container: { 105 | backgroundColor: 'white', 106 | marginVertical: 12, 107 | marginHorizontal: 24, 108 | borderRadius: 16, 109 | elevation: 8, 110 | shadowColor: 'grey', 111 | shadowOffset: { width: 4, height: 4 }, 112 | shadowOpacity: 0.3, 113 | shadowRadius: 12, 114 | }, 115 | imageContainer: { 116 | borderTopLeftRadius: 16, 117 | borderTopRightRadius: 16, 118 | overflow: 'hidden', 119 | }, 120 | title: { 121 | flex: 1, 122 | color: 'black', 123 | fontSize: 22, 124 | fontFamily: 'WorkSans-SemiBold', 125 | }, 126 | subText: { 127 | flex: 1, 128 | flexDirection: 'row', 129 | alignItems: 'center', 130 | paddingRight: 4, 131 | marginTop: 4, 132 | }, 133 | perNightPrice: { 134 | color: 'black', 135 | fontSize: 22, 136 | fontFamily: 'WorkSans-SemiBold', 137 | }, 138 | perNightText: { ...textStyle, color: 'black', marginTop: 4 }, 139 | ratingContainer: { 140 | flexDirection: 'row', 141 | marginTop: 4, 142 | alignItems: 'center', 143 | }, 144 | review: { 145 | ...textStyle, 146 | marginLeft: 8, 147 | }, 148 | }); 149 | 150 | export default HotelListItem; 151 | -------------------------------------------------------------------------------- /src/introduction_animation/scenes/CenterNextButton.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useMemo, useRef, useState } from 'react'; 2 | import { StyleSheet, Text, Animated } from 'react-native'; 3 | import { useSafeAreaInsets } from 'react-native-safe-area-context'; 4 | import NextButtonArrow from './components/NextButtonArrow'; 5 | 6 | interface Props { 7 | onNextClick: () => void; 8 | animationController: React.RefObject; 9 | } 10 | 11 | interface DotIndicatorProps { 12 | index: number; 13 | selectedIndex: number; 14 | } 15 | const DotIndicator: React.FC = ({ 16 | index, 17 | selectedIndex, 18 | }) => { 19 | const activeIndexRef = useRef(new Animated.Value(0)); 20 | 21 | useEffect(() => { 22 | Animated.timing(activeIndexRef.current, { 23 | toValue: index === selectedIndex ? 1 : 0, 24 | duration: 480, 25 | useNativeDriver: false, 26 | }).start(); 27 | }, [selectedIndex, index]); 28 | 29 | const bgColor = activeIndexRef.current.interpolate({ 30 | inputRange: [0, 1], 31 | outputRange: ['#E3E4E4', '#132137'], 32 | }); 33 | 34 | return ( 35 | 38 | ); 39 | }; 40 | 41 | const CenterNextButton: React.FC = ({ 42 | onNextClick, 43 | animationController, 44 | }) => { 45 | const opacity = useRef(new Animated.Value(0)); 46 | const currentOpacity = useRef(0); 47 | 48 | const [selectedIndex, setSelectedIndex] = useState(0); 49 | 50 | const { bottom } = useSafeAreaInsets(); 51 | const paddingBottom = 16 + bottom; 52 | 53 | const dots = useMemo(() => [0, 1, 2, 3], []); 54 | 55 | useEffect(() => { 56 | // I think this condition could be better? 57 | animationController.current.addListener(({ value }) => { 58 | const isVisible = value >= 0.2 && value <= 0.6; 59 | if ( 60 | (isVisible && currentOpacity.current === 0) || 61 | (!isVisible && currentOpacity.current === 1) 62 | ) { 63 | Animated.timing(opacity.current, { 64 | toValue: isVisible ? 1 : 0, 65 | duration: 480, 66 | useNativeDriver: true, 67 | }).start(); 68 | currentOpacity.current = isVisible ? 1 : 0; 69 | } 70 | 71 | if (value >= 0.7) { 72 | setSelectedIndex(3); 73 | } else if (value >= 0.5) { 74 | setSelectedIndex(2); 75 | } else if (value >= 0.3) { 76 | setSelectedIndex(1); 77 | } else if (value >= 0.1) { 78 | setSelectedIndex(0); 79 | } 80 | }); 81 | }, [animationController]); 82 | 83 | const topViewAnim = animationController.current.interpolate({ 84 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 85 | outputRange: [96 * 5, 0, 0, 0, 0], // 96 is total height of next button view 86 | }); 87 | const loginTextMoveAnimation = animationController.current.interpolate({ 88 | inputRange: [0, 0.2, 0.4, 0.6, 0.8], 89 | outputRange: [30 * 5, 30 * 5, 30 * 5, 30 * 5, 0], // 96 is total height of next button view 90 | }); 91 | 92 | return ( 93 | 99 | 102 | {dots.map(item => ( 103 | 108 | ))} 109 | 110 | 111 | 112 | 113 | 119 | 120 | Already have an account?{' '} 121 | 122 | Login 123 | 124 | 125 | ); 126 | }; 127 | 128 | const styles = StyleSheet.create({ 129 | container: { 130 | alignItems: 'center', 131 | position: 'absolute', 132 | bottom: 0, 133 | left: 0, 134 | right: 0, 135 | }, 136 | dotsContainer: { 137 | flexDirection: 'row', 138 | marginBottom: 16, 139 | }, 140 | pageIndicator: { 141 | width: 10, 142 | height: 10, 143 | borderRadius: 5, 144 | margin: 4, 145 | }, 146 | footerTextContainer: { 147 | flexDirection: 'row', 148 | marginTop: 8, 149 | }, 150 | loginText: { 151 | color: '#132137', 152 | fontSize: 16, 153 | fontFamily: 'WorkSans-Bold', 154 | }, 155 | }); 156 | 157 | export default CenterNextButton; 158 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "org.jetbrains.kotlin.android" 3 | apply plugin: "com.facebook.react" 4 | 5 | /** 6 | * This is the configuration block to customize your React Native Android app. 7 | * By default you don't need to apply any configuration, just uncomment the lines you need. 8 | */ 9 | react { 10 | /* Folders */ 11 | // The root of your project, i.e. where "package.json" lives. Default is '../..' 12 | // root = file("../../") 13 | // The folder where the react-native NPM package is. Default is ../../node_modules/react-native 14 | // reactNativeDir = file("../../node_modules/react-native") 15 | // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen 16 | // codegenDir = file("../../node_modules/@react-native/codegen") 17 | // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js 18 | // cliFile = file("../../node_modules/react-native/cli.js") 19 | 20 | /* Variants */ 21 | // The list of variants to that are debuggable. For those we're going to 22 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'. 23 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. 24 | // debuggableVariants = ["liteDebug", "prodDebug"] 25 | 26 | /* Bundling */ 27 | // A list containing the node command and its flags. Default is just 'node'. 28 | // nodeExecutableAndArgs = ["node"] 29 | // 30 | // The command to run when bundling. By default is 'bundle' 31 | // bundleCommand = "ram-bundle" 32 | // 33 | // The path to the CLI configuration file. Default is empty. 34 | // bundleConfig = file(../rn-cli.config.js) 35 | // 36 | // The name of the generated asset file containing your JS bundle 37 | // bundleAssetName = "MyApplication.android.bundle" 38 | // 39 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' 40 | // entryFile = file("../js/MyApplication.android.js") 41 | // 42 | // A list of extra flags to pass to the 'bundle' commands. 43 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle 44 | // extraPackagerArgs = [] 45 | 46 | /* Hermes Commands */ 47 | // The hermes compiler command to run. By default it is 'hermesc' 48 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" 49 | // 50 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" 51 | // hermesFlags = ["-O", "-output-source-map"] 52 | 53 | /* Autolinking */ 54 | autolinkLibrariesWithApp() 55 | } 56 | 57 | project.ext.vectoricons = [ 58 | iconFontNames: [ 'MaterialIcons.ttf' ] 59 | ] 60 | apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" 61 | 62 | 63 | /** 64 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. 65 | */ 66 | def enableProguardInReleaseBuilds = false 67 | 68 | /** 69 | * The preferred build flavor of JavaScriptCore (JSC) 70 | * 71 | * For example, to use the international variant, you can use: 72 | * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+` 73 | * 74 | * The international variant includes ICU i18n library and necessary data 75 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 76 | * give correct results when using with locales other than en-US. Note that 77 | * this variant is about 6MiB larger per architecture than default. 78 | */ 79 | def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' 80 | 81 | android { 82 | ndkVersion rootProject.ext.ndkVersion 83 | buildToolsVersion rootProject.ext.buildToolsVersion 84 | compileSdk rootProject.ext.compileSdkVersion 85 | 86 | namespace "com.react_native_ui_templates" 87 | defaultConfig { 88 | applicationId "com.react_native_ui_templates" 89 | minSdkVersion rootProject.ext.minSdkVersion 90 | targetSdkVersion rootProject.ext.targetSdkVersion 91 | versionCode 1 92 | versionName "1.0" 93 | } 94 | signingConfigs { 95 | debug { 96 | storeFile file('debug.keystore') 97 | storePassword 'android' 98 | keyAlias 'androiddebugkey' 99 | keyPassword 'android' 100 | } 101 | } 102 | buildTypes { 103 | debug { 104 | signingConfig signingConfigs.debug 105 | } 106 | release { 107 | // Caution! In production, you need to generate your own keystore file. 108 | // see https://reactnative.dev/docs/signed-apk-android. 109 | signingConfig signingConfigs.debug 110 | minifyEnabled enableProguardInReleaseBuilds 111 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 112 | } 113 | } 114 | } 115 | 116 | dependencies { 117 | // The version of react-native is set by the React Native Gradle Plugin 118 | implementation("com.facebook.react:react-android") 119 | 120 | if (hermesEnabled.toBoolean()) { 121 | implementation("com.facebook.react:hermes-android") 122 | } else { 123 | implementation jscFlavor 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/hotel_booking/CalendarPopupView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Modal, 7 | SafeAreaView, 8 | TouchableWithoutFeedback, 9 | } from 'react-native'; 10 | import { BlurView } from '@react-native-community/blur'; 11 | import CustomCalendar from './CustomCalendar'; 12 | import MyPressable from '../components/MyPressable'; 13 | 14 | interface Props { 15 | showCal: boolean; 16 | setShowCal: any; 17 | minimumDate: Date | null; 18 | initialStartDate: Date | null; 19 | initialEndDate: Date | null; 20 | onApplyClick: (startData: Date | null, endData: Date | null) => void; 21 | } 22 | 23 | const HALF_MONTHS = [ 24 | 'Jan', 25 | 'Feb', 26 | 'Mar', 27 | 'Apr', 28 | 'May', 29 | 'Jun', 30 | 'July', 31 | 'Aug', 32 | 'Sep', 33 | 'Oct', 34 | 'Nov', 35 | 'Dec', 36 | ]; 37 | 38 | const WEEKS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; 39 | 40 | const CustomerCalendar: React.FC = ({ 41 | showCal, 42 | setShowCal, 43 | minimumDate, 44 | initialStartDate, 45 | initialEndDate, 46 | onApplyClick, 47 | }) => { 48 | const [startDate, setStartDate] = useState(initialStartDate); 49 | const [endDate, setEndDate] = useState(initialEndDate); 50 | 51 | const formattedDate = (date: Date | null) => { 52 | return date 53 | ? `${WEEKS[date?.getDay()]}, ${String(date.getDate()).padStart(2, '0')} ${ 54 | HALF_MONTHS[date.getMonth()] 55 | }` 56 | : '--/--'; 57 | }; 58 | 59 | return ( 60 | setShowCal(false)} 66 | > 67 | setShowCal(false)} 70 | > 71 | 72 | 78 | {}}> 79 | 82 | 83 | 84 | From 85 | 86 | {formattedDate(startDate)} 87 | 88 | 89 | 90 | 91 | To 92 | 93 | {formattedDate(endDate)} 94 | 95 | 96 | 97 | 98 | 99 | { 104 | setStartDate(startDateData); 105 | setEndDate(endDateData); 106 | }} 107 | /> 108 | 109 | 110 | 111 | { 115 | onApplyClick(startDate, endDate); 116 | setShowCal(false); 117 | }} 118 | > 119 | Apply 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | ); 129 | }; 130 | 131 | const styles = StyleSheet.create({ 132 | containerStyle: { 133 | flex: 1, 134 | justifyContent: 'center', 135 | backgroundColor: 'rgba(0,0,0, 0.5)', 136 | }, 137 | timelineContainerStyle: { 138 | flex: 1, 139 | alignItems: 'center', 140 | justifyContent: 'center', 141 | }, 142 | fromToTextStyle: { 143 | fontSize: 16, 144 | fontFamily: 'WorkSans-Regular', 145 | color: 'rgba(128, 128, 128, 0.8)', 146 | marginBottom: 4, 147 | }, 148 | startEndDateTextStyles: { 149 | color: 'black', 150 | fontSize: 16, 151 | fontFamily: 'WorkSans-Bold', 152 | }, 153 | applyBtnContainer: { 154 | backgroundColor: '#54D3C2', 155 | borderRadius: 24, 156 | elevation: 8, 157 | overflow: 'hidden', 158 | }, 159 | applyBtn: { 160 | height: 48, 161 | alignItems: 'center', 162 | justifyContent: 'center', 163 | borderRadius: 24, 164 | }, 165 | applyBtnShadow: { 166 | backgroundColor: '#54D3C2', 167 | borderRadius: 24, 168 | margin: 16, 169 | marginTop: 8, 170 | shadowColor: 'grey', 171 | shadowOffset: { width: 4, height: 4 }, 172 | shadowOpacity: 0.6, 173 | shadowRadius: 8, 174 | }, 175 | applyBtnText: { 176 | fontSize: 18, 177 | color: 'white', 178 | fontFamily: 'WorkSans-Medium', 179 | }, 180 | verticleDivider: { 181 | height: 74, 182 | width: 1, 183 | backgroundColor: 'grey', 184 | opacity: 0.4, 185 | }, 186 | }); 187 | 188 | export default CustomerCalendar; 189 | -------------------------------------------------------------------------------- /src/HomeScene.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef, useState } from 'react'; 2 | import { 3 | StyleSheet, 4 | Image, 5 | Animated, 6 | ListRenderItemInfo, 7 | View, 8 | Text, 9 | FlatList, 10 | Easing, 11 | useWindowDimensions, 12 | GestureResponderEvent, 13 | } from 'react-native'; 14 | import { 15 | SafeAreaView, 16 | useSafeAreaInsets, 17 | } from 'react-native-safe-area-context'; 18 | import { useNavigation } from '@react-navigation/native'; 19 | import Icon from 'react-native-vector-icons/MaterialIcons'; 20 | import MyPressable from './components/MyPressable'; 21 | import { AppImages } from './assets'; 22 | import { showToast } from './util/action'; 23 | 24 | const DEMOS = [ 25 | { 26 | name: 'onBoarding', 27 | background: AppImages.introduction_animation, 28 | screenName: 'onBoarding', 29 | }, 30 | { 31 | name: 'hotel', 32 | background: AppImages.hotel_booking, 33 | screenName: 'Hotel', 34 | }, 35 | { 36 | name: 'fitness_app', 37 | background: AppImages.fitness_app, 38 | screenName: '', 39 | }, 40 | { 41 | name: 'design_course', 42 | background: AppImages.design_course, 43 | screenName: 'DesignCourse', 44 | }, 45 | ]; 46 | 47 | interface ListItemProps { 48 | data: ListRenderItemInfo<(typeof DEMOS)[0]>; 49 | isGrid: boolean; 50 | onScreenClicked: ((event: GestureResponderEvent) => void) | null | undefined; 51 | } 52 | 53 | const ListItem: React.FC = ({ 54 | data, 55 | isGrid, 56 | onScreenClicked, 57 | }) => { 58 | const { index, item } = data; 59 | 60 | const { width } = useWindowDimensions(); 61 | 62 | const translateY = useRef(new Animated.Value(50)).current; 63 | const opacity = useRef(new Animated.Value(0)).current; 64 | 65 | useEffect(() => { 66 | Animated.parallel([ 67 | Animated.timing(translateY, { 68 | toValue: 0, 69 | duration: 1000, 70 | delay: index * (1000 / 3), 71 | easing: Easing.bezier(0.4, 0.0, 0.2, 1.0), 72 | useNativeDriver: true, 73 | }), 74 | Animated.timing(opacity, { 75 | toValue: 1, 76 | duration: 1000, 77 | delay: index * (1000 / 3), 78 | useNativeDriver: true, 79 | }), 80 | ]).start(); 81 | }); 82 | 83 | const itemWidth = isGrid ? (width - 36) / 2 : width - 24; 84 | 85 | return ( 86 | 96 | 104 | 105 | 111 | 112 | ); 113 | }; 114 | 115 | const HomeScene: React.FC = () => { 116 | const navigation = useNavigation(); 117 | const inset = useSafeAreaInsets(); 118 | 119 | const [isGrid, setGrid] = useState(true); 120 | 121 | const onTemplateClicked = (temp: (typeof DEMOS)[0]) => { 122 | if (temp.screenName) { 123 | navigation.navigate(temp.screenName); 124 | } else { 125 | showToast('Coming soon...'); 126 | } 127 | }; 128 | 129 | return ( 130 | 134 | 135 | navigation.toggleDrawer()} 140 | > 141 | 142 | 143 | React-Native UI 144 | setGrid(!isGrid)} 149 | > 150 | 155 | 156 | 157 | 158 | ( 166 | onTemplateClicked(data.item)} 169 | /> 170 | )} 171 | keyExtractor={item => item.name} 172 | /> 173 | 174 | ); 175 | }; 176 | 177 | const styles = StyleSheet.create({ 178 | headerContainer: { 179 | height: 52, 180 | flexDirection: 'row', 181 | alignItems: 'center', 182 | paddingHorizontal: 8, 183 | paddingBottom: 0, 184 | }, 185 | headerText: { 186 | flex: 1, 187 | color: 'black', 188 | fontSize: 22, 189 | fontFamily: 'WorkSans-Bold', 190 | textAlign: 'center', 191 | textAlignVertical: 'center', 192 | }, 193 | demoImg: { 194 | width: '100%', 195 | height: '100%', 196 | borderRadius: 4, 197 | }, 198 | demoPressable: { 199 | ...StyleSheet.absoluteFillObject, 200 | backgroundColor: 'rgba(128,128,128,0.1)', 201 | borderRadius: 4, 202 | }, 203 | }); 204 | 205 | export default HomeScene; 206 | -------------------------------------------------------------------------------- /src/hotel_booking/Switch.tsx: -------------------------------------------------------------------------------- 1 | // This component is taken from wix/react-native-ui-lib. 2 | // ref:- "https://github.com/wix/react-native-ui-lib/blob/master/src/components/switch/index.tsx" 3 | import React, { Component } from 'react'; 4 | import { 5 | TouchableOpacity, 6 | StyleSheet, 7 | Animated, 8 | Easing, 9 | StyleProp, 10 | ViewStyle, 11 | I18nManager, 12 | } from 'react-native'; 13 | 14 | const INNER_PADDING = 2; 15 | const DEFAULT_WIDTH = 50; 16 | const DEFAULT_HEIGHT = 30; 17 | const DEFAULT_THUMB_SIZE = 26; 18 | 19 | export type SwitchProps = { 20 | /** 21 | * The value of the switch. If true the switch will be turned on. Default value is false 22 | */ 23 | value?: boolean; 24 | /** 25 | * Invoked with the new value when the value changes 26 | */ 27 | onValueChange?: (value: boolean) => void; 28 | /** 29 | * Whether the switch should be disabled 30 | */ 31 | disabled?: boolean; 32 | /** 33 | * The Switch width 34 | */ 35 | width?: number; 36 | /** 37 | * The Switch height 38 | */ 39 | height?: number; 40 | /** 41 | * The Switch background color when it's turned on 42 | */ 43 | onColor?: string; 44 | /** 45 | * The Switch background color when it's turned off 46 | */ 47 | offColor?: string; 48 | /** 49 | * The Switch background color when it's disabled 50 | */ 51 | disabledColor?: string; 52 | /** 53 | * The Switch's thumb color 54 | */ 55 | thumbColor?: string; 56 | /** 57 | * The Switch's thumb size (width & height) 58 | */ 59 | thumbSize?: number; 60 | /** 61 | * The Switch's thumb style 62 | */ 63 | thumbStyle?: object /* | number | [] */; 64 | style?: StyleProp; 65 | testID?: string; 66 | }; 67 | 68 | /** 69 | * Switch component for toggling boolean value related to some context 70 | */ 71 | class Switch extends Component { 72 | static displayName = 'Switch'; 73 | 74 | state = { 75 | thumbPosition: new Animated.Value(this.props.value ? 1 : 0), 76 | }; 77 | 78 | styles = createStyles(this.props); 79 | 80 | componentDidUpdate(prevProps: SwitchProps) { 81 | const { value } = this.props; 82 | if (prevProps.value !== value) { 83 | this.toggle(value); 84 | } 85 | } 86 | 87 | getAccessibilityProps() { 88 | const { disabled, value } = this.props; 89 | 90 | return { 91 | accessible: true, 92 | accessibilityRole: 'switch', 93 | accessibilityState: { 94 | disabled, 95 | checked: value ? 'checked' : 'unchecked', 96 | }, 97 | accessibilityValue: { text: value ? '1' : '0' }, 98 | }; 99 | } 100 | 101 | toggle(value?: boolean) { 102 | const { thumbPosition } = this.state; 103 | 104 | Animated.timing(thumbPosition, { 105 | toValue: value ? 1 : 0, 106 | duration: 200, 107 | easing: Easing.bezier(0.77, 0.0, 0.175, 1.0), 108 | useNativeDriver: true, 109 | }).start(); 110 | } 111 | 112 | onPress = () => { 113 | const { disabled } = this.props; 114 | 115 | if (!disabled) { 116 | this.props.onValueChange?.(!this.props.value); 117 | } 118 | }; 119 | 120 | calcThumbOnPosition() { 121 | const props = this.props; 122 | const width = props.width || DEFAULT_WIDTH; 123 | const thumbSize = props.thumbSize || DEFAULT_THUMB_SIZE; 124 | let position = width - (2 * INNER_PADDING + thumbSize); 125 | position *= I18nManager.isRTL ? -1 : 1; 126 | return position; 127 | } 128 | 129 | getSwitchStyle() { 130 | const { 131 | value, 132 | onColor, 133 | offColor, 134 | style: propsStyle, 135 | disabled, 136 | disabledColor, 137 | } = this.props; 138 | const style: SwitchProps['style'] = [this.styles.switch]; 139 | 140 | if (disabled) { 141 | style.push( 142 | disabledColor 143 | ? { backgroundColor: disabledColor } 144 | : this.styles.switchDisabled, 145 | ); 146 | } else if (value) { 147 | style.push(onColor ? { backgroundColor: onColor } : this.styles.switchOn); 148 | } else { 149 | style.push( 150 | offColor ? { backgroundColor: offColor } : this.styles.switchOff, 151 | ); 152 | } 153 | 154 | style.push(propsStyle); 155 | return style; 156 | } 157 | 158 | renderThumb() { 159 | const { thumbStyle } = this.props; 160 | const { thumbPosition } = this.state; 161 | 162 | const interpolatedTranslateX = thumbPosition.interpolate({ 163 | inputRange: [0, 1], 164 | outputRange: [0, this.calcThumbOnPosition()], 165 | }); 166 | 167 | const thumbPositionStyle = { 168 | transform: [{ translateX: interpolatedTranslateX }], 169 | }; 170 | 171 | return ( 172 | 175 | ); 176 | } 177 | 178 | render() { 179 | return ( 180 | // @ts-ignore 181 | 187 | {this.renderThumb()} 188 | 189 | ); 190 | } 191 | } 192 | 193 | function createStyles({ 194 | width = DEFAULT_WIDTH, 195 | height = DEFAULT_HEIGHT, 196 | onColor = '#54D3C2', 197 | offColor = 'rgba(158,158,158, 0.3)', // 'lightgrey' 198 | disabledColor = 'lightgrey', 199 | thumbColor = 'white', 200 | thumbSize = DEFAULT_THUMB_SIZE, 201 | }) { 202 | return StyleSheet.create({ 203 | switch: { 204 | width, 205 | height, 206 | borderRadius: 999, 207 | justifyContent: 'center', 208 | padding: INNER_PADDING, 209 | }, 210 | switchOn: { 211 | backgroundColor: onColor, 212 | }, 213 | switchOff: { 214 | backgroundColor: offColor, 215 | }, 216 | switchDisabled: { 217 | backgroundColor: disabledColor, 218 | }, 219 | thumb: { 220 | width: thumbSize, 221 | height: thumbSize, 222 | borderRadius: thumbSize / 2, 223 | backgroundColor: thumbColor, 224 | }, 225 | }); 226 | } 227 | 228 | export default Switch; 229 | -------------------------------------------------------------------------------- /src/design_course/HomeDesignCourse.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | StatusBar, 7 | Image, 8 | TextInput, 9 | useWindowDimensions, 10 | FlatList, 11 | } from 'react-native'; 12 | import { useSafeAreaInsets } from 'react-native-safe-area-context'; 13 | import { useNavigation } from '@react-navigation/native'; 14 | import Icon from 'react-native-vector-icons/MaterialIcons'; 15 | import CategoryListView from './CategoryListView'; 16 | import PopulerCourseListView from './PopulerCourseListView'; 17 | import MyPressable from '../components/MyPressable'; 18 | import { CATEGORY_LIST, POPULAR_COURSE_LIST } from './model/category'; 19 | import { AppImages } from '../assets'; 20 | import Config from '../Config'; 21 | 22 | interface CategoryBtn { 23 | text: string; 24 | selectedCat: string; 25 | onPress: () => void; 26 | } 27 | 28 | const CATEGORIES = ['Ui/Ux', 'Coding', 'Basic UI']; 29 | 30 | const CategoryButton = ({ text, selectedCat, onPress }: CategoryBtn) => ( 31 | <> 32 | 33 | 34 | 35 | {text} 36 | 37 | 38 | 39 | {text !== CATEGORIES[2] && } 40 | 41 | ); 42 | 43 | const HomeDesignCourse: React.FC = () => { 44 | const { width } = useWindowDimensions(); 45 | const insets = useSafeAreaInsets(); 46 | const navigation = useNavigation(); 47 | 48 | const [selectedCategory, setSelectedCategory] = useState('Ui/Ux'); 49 | 50 | const paddingTop = Config.isIos 51 | ? Math.max(insets.top, 20) 52 | : StatusBar.currentHeight; 53 | 54 | const renderScrollableHeader = ( 55 | <> 56 | 57 | 58 | 68 | 69 | 70 | 71 | Category 72 | 73 | {CATEGORIES.map(text => ( 74 | setSelectedCategory(text)} 79 | /> 80 | ))} 81 | 82 | 83 | ( 89 | navigation.navigate('CourseInfo')} 92 | /> 93 | )} 94 | keyExtractor={item => item.id.toString()} 95 | /> 96 | Popular Course 97 | 98 | ); 99 | 100 | return ( 101 | 102 | 103 | 104 | 105 | Choose your 106 | Design Course 107 | 108 | 112 | 113 | 114 | } 125 | renderItem={data => ( 126 | navigation.navigate('CourseInfo')} 129 | /> 130 | )} 131 | keyExtractor={item => item.id.toString()} 132 | /> 133 | 134 | ); 135 | }; 136 | 137 | const styles = StyleSheet.create({ 138 | searchInputMainContainer: { 139 | marginTop: 8, 140 | marginLeft: 18, 141 | height: 64, 142 | }, 143 | searchInputContainer: { 144 | flexDirection: 'row', 145 | backgroundColor: '#F8FAFB', 146 | marginVertical: 8, 147 | borderRadius: 13, 148 | paddingHorizontal: 16, 149 | alignItems: 'center', 150 | }, 151 | searchInput: { 152 | flex: 1, 153 | fontSize: 16, 154 | fontFamily: 'WorkSans-SemiBold', 155 | color: 'dodgerblue', 156 | }, 157 | sectionHeaderText: { 158 | color: 'black', 159 | fontSize: 22, 160 | fontFamily: 'WorkSans-SemiBold', 161 | letterSpacing: 0.27, 162 | paddingTop: 8, 163 | paddingLeft: 18, 164 | paddingRight: 16, 165 | marginBottom: 16, 166 | }, 167 | categoryRowContainer: { 168 | flexDirection: 'row', 169 | paddingHorizontal: 16, 170 | marginBottom: 8, 171 | }, 172 | header: { 173 | flexDirection: 'row', 174 | paddingTop: 8, 175 | paddingHorizontal: 18, 176 | }, 177 | headerTextNormal: { 178 | color: 'grey', 179 | fontFamily: 'WorkSans-Regular', 180 | letterSpacing: 0.2, 181 | }, 182 | headerTextBold: { 183 | color: 'black', 184 | fontSize: 22, 185 | fontFamily: 'WorkSans-Bold', 186 | letterSpacing: 0.2, 187 | }, 188 | }); 189 | 190 | const styleCatrgory = (selected: boolean) => 191 | StyleSheet.create({ 192 | categoryBtnContainer: { 193 | flex: 1, 194 | overflow: 'hidden', 195 | borderRadius: 24, 196 | borderColor: 'rgb(0, 182, 240)', 197 | borderWidth: 1, 198 | backgroundColor: selected ? 'rgb(0, 182, 240)' : 'transparent', 199 | }, 200 | categoryBtnText: { 201 | padding: 18, 202 | paddingVertical: 12, 203 | fontSize: 12, 204 | fontFamily: 'WorkSans-SemiBold', 205 | letterSpacing: 0.27, 206 | alignSelf: 'center', 207 | color: selected ? 'white' : 'rgb(0, 182, 240)', 208 | }, 209 | }); 210 | 211 | export default HomeDesignCourse; 212 | -------------------------------------------------------------------------------- /src/DrawerContent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | useWindowDimensions, 7 | Image, 8 | ViewStyle, 9 | StyleProp, 10 | } from 'react-native'; 11 | import { SafeAreaView } from 'react-native-safe-area-context'; 12 | import { 13 | DrawerContentComponentProps, 14 | DrawerContentScrollView, 15 | useDrawerProgress, 16 | } from '@react-navigation/drawer'; 17 | import { DrawerActions, NavigationState } from '@react-navigation/native'; 18 | import Animated, { 19 | AnimatedStyle, 20 | interpolate, 21 | SharedValue, 22 | useAnimatedStyle, 23 | } from 'react-native-reanimated'; 24 | import Icon from 'react-native-vector-icons/MaterialIcons'; 25 | import MyPressable from './components/MyPressable'; 26 | import { AppImages } from './assets'; 27 | 28 | type DrawerScene = { 29 | label: string; 30 | icon: any; 31 | isAssetIcon?: boolean; 32 | routeKey?: string; 33 | }; 34 | 35 | interface DrawerItemProps extends DrawerScene { 36 | bgAnimStyle: AnimatedStyle>; 37 | } 38 | 39 | const DRAWER_SCENES: DrawerScene[] = [ 40 | { label: 'Home', icon: 'home', routeKey: 'home' }, 41 | { 42 | label: 'Help', 43 | icon: AppImages.support_icon, 44 | isAssetIcon: true, 45 | routeKey: 'help', 46 | }, 47 | { label: 'Feedback', icon: 'help', routeKey: 'feedback' }, 48 | { label: 'Invite Friend', icon: 'group', routeKey: 'invite_friend' }, 49 | { label: 'Rate the app', icon: 'share' }, 50 | { label: 'About Us', icon: 'info' }, 51 | ]; 52 | 53 | const getActiveRouteState = ( 54 | routes: NavigationState['routes'], 55 | index: number, 56 | routeKey: string, 57 | ) => routes[index].name.toLowerCase().indexOf(routeKey?.toLowerCase()) >= 0; 58 | 59 | const DrawerItemRow: React.FC< 60 | DrawerItemProps & DrawerContentComponentProps 61 | > = props => { 62 | const { 63 | state, 64 | label, 65 | icon, 66 | isAssetIcon = false, 67 | routeKey, 68 | bgAnimStyle, 69 | } = props; 70 | const { routes, index } = state; 71 | 72 | const sceneOptions = props.descriptors[routes[index].key]?.options; 73 | 74 | const window = useWindowDimensions(); 75 | const rowWidth = (window.width * 0.75 * 80) / 100; 76 | 77 | const focused = routeKey 78 | ? getActiveRouteState(routes, index, routeKey) 79 | : false; 80 | 81 | const tintColor = focused 82 | ? sceneOptions?.drawerActiveBackgroundColor 83 | : 'black'; 84 | 85 | return ( 86 | 90 | routeKey 91 | ? props.navigation.navigate(routeKey) 92 | : props.navigation.dispatch(DrawerActions.closeDrawer()) 93 | } 94 | > 95 | 107 | 108 | {isAssetIcon ? ( 109 | 114 | ) : ( 115 | 116 | )} 117 | 121 | {label} 122 | 123 | 124 | 125 | ); 126 | }; 127 | 128 | const DrawerContent: React.FC = props => { 129 | const window = useWindowDimensions(); 130 | const rowWidth = (window.width * 0.75 * 80) / 100; 131 | const progress = useDrawerProgress(); 132 | 133 | const drawerStyle = useAnimatedStyle(() => { 134 | const drawerProgress = progress as SharedValue; 135 | 136 | return { 137 | transform: [ 138 | { rotate: `${interpolate(drawerProgress.value, [0, 1], [0.2, 0])}rad` }, 139 | { scale: interpolate(drawerProgress.value, [0, 1], [0.9, 1]) }, 140 | ], 141 | }; 142 | }, []); 143 | const bgAnimStyle = useAnimatedStyle(() => { 144 | const drawerProgress = progress as SharedValue; 145 | 146 | return { 147 | transform: [ 148 | { 149 | translateX: interpolate(drawerProgress.value, [0, 1], [-rowWidth, 0]), 150 | }, 151 | ], 152 | }; 153 | }, []); 154 | 155 | return ( 156 | 157 | 158 | 161 | 165 | 166 | Chris Hemsworth 167 | 168 | 169 | 170 | 174 | {DRAWER_SCENES.map(scene => ( 175 | 179 | ))} 180 | 181 | 182 | 183 | Sign Out 184 | 185 | 186 | 187 | ); 188 | }; 189 | 190 | const styles = StyleSheet.create({ 191 | userName: { 192 | fontSize: 18, 193 | color: '#3A5160', 194 | fontFamily: 'WorkSans-SemiBold', 195 | paddingTop: 8, 196 | paddingLeft: 4, 197 | }, 198 | drawerRowStyle: { 199 | marginHorizontal: 0, 200 | paddingVertical: 8, 201 | justifyContent: 'center', 202 | overflow: 'hidden', 203 | }, 204 | drawerRowbackViewStyle: { 205 | opacity: 0.3, 206 | height: 48, 207 | borderRadius: 24, 208 | borderTopStartRadius: 0, 209 | borderBottomStartRadius: 0, 210 | }, 211 | drawerRowTextStyle: { 212 | fontSize: 16, 213 | marginLeft: 10, 214 | fontWeight: '500', 215 | }, 216 | drawerRowContentContainer: { 217 | flexDirection: 'row', 218 | padding: 8, 219 | paddingHorizontal: 16, 220 | position: 'absolute', 221 | }, 222 | drawerAvatarStyle: { 223 | width: 120, 224 | height: 120, 225 | borderRadius: 60, 226 | }, 227 | avatarShadow: { 228 | backgroundColor: 'white', 229 | elevation: 24, 230 | shadowColor: '#3A5160', 231 | shadowOffset: { width: 2, height: 4 }, 232 | shadowOpacity: 0.6, 233 | shadowRadius: 8, 234 | }, 235 | divider: { 236 | backgroundColor: 'darkgrey', 237 | height: StyleSheet.hairlineWidth, 238 | }, 239 | signOutBtnStyle: { 240 | flexDirection: 'row', 241 | padding: 16, 242 | borderTopWidth: StyleSheet.hairlineWidth, 243 | borderColor: 'darkgrey', 244 | }, 245 | signOutText: { 246 | flex: 1, 247 | color: 'black', 248 | fontSize: 16, 249 | fontFamily: 'WorkSans-SemiBold', 250 | }, 251 | }); 252 | 253 | export default DrawerContent; 254 | -------------------------------------------------------------------------------- /src/hotel_booking/HotelHomeScreen.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useState } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | TextInput, 7 | FlatList, 8 | useWindowDimensions, 9 | ListRenderItemInfo, 10 | } from 'react-native'; 11 | import { useSafeAreaInsets } from 'react-native-safe-area-context'; 12 | import { useNavigation } from '@react-navigation/native'; 13 | import Icon from 'react-native-vector-icons/MaterialIcons'; 14 | import CustomerCalendar from './CalendarPopupView'; 15 | import FilterModal from './FiltersModal'; 16 | import HotelListItem from './HotelListItem'; 17 | import MyPressable from '../components/MyPressable'; 18 | import { HOTEL_LIST, HotelListType } from './model/hotel_list_data'; 19 | 20 | const HALF_MONTHS = [ 21 | 'Jan', 22 | 'Feb', 23 | 'Mar', 24 | 'Apr', 25 | 'May', 26 | 'Jun', 27 | 'July', 28 | 'Aug', 29 | 'Sep', 30 | 'Oct', 31 | 'Nov', 32 | 'Dec', 33 | ]; 34 | 35 | const HotelHomeScreen: React.FC = () => { 36 | const window = useWindowDimensions(); 37 | const inset = useSafeAreaInsets(); 38 | const navigation = useNavigation(); 39 | 40 | const [startDate, setStartDate] = useState(new Date()); 41 | const [endDate, setEndDate] = useState(() => { 42 | const date = new Date(); 43 | date.setDate(date.getDate() + 5); 44 | return date; 45 | }); 46 | const [showCal, setShowCal] = useState(false); 47 | const [showFilter, setShowFilter] = useState(false); 48 | 49 | const contentHeader = ( 50 | 51 | 52 | 58 | 59 | 64 | 65 | 66 | 67 | 68 | 69 | setShowCal(true)} 73 | > 74 | Choose date 75 | 76 | {`${String(startDate.getDate()).padStart(2, '0')}, ${ 77 | HALF_MONTHS[startDate.getMonth()] 78 | } - ${String(endDate.getDate()).padStart(2, '0')}, ${ 79 | HALF_MONTHS[endDate.getMonth()] 80 | }`} 81 | 82 | 83 | 84 | 85 | Number of Rooms 86 | 1 Room - 2 Adults 87 | 88 | 89 | 90 | ); 91 | 92 | const renderItem = useCallback( 93 | (data: ListRenderItemInfo) => 94 | data.index > 0 ? ( 95 | 96 | ) : ( 97 | 98 | 530 hotels found 99 | 100 | setShowFilter(true)} 103 | > 104 | Filter 105 | 111 | 112 | 113 | 114 | ), 115 | [], 116 | ); 117 | 118 | return ( 119 | <> 120 | {/* Header */} 121 | 127 | 128 | 133 | 134 | 135 | 136 | 142 | 143 | Explore 144 | 145 | 146 | 147 | 153 | 159 | 160 | 161 | 162 | 163 | item.id.toString()} 171 | /> 172 | 173 | 174 | { 180 | if (startData != null && endData != null) { 181 | setStartDate(startData); 182 | setEndDate(endData); 183 | } 184 | }} 185 | /> 186 | 187 | 188 | ); 189 | }; 190 | 191 | const styles = StyleSheet.create({ 192 | header: { 193 | flexDirection: 'row', 194 | alignItems: 'center', 195 | backgroundColor: 'white', 196 | paddingHorizontal: 8, 197 | borderBottomWidth: StyleSheet.hairlineWidth, 198 | borderBottomColor: 'lightgrey', 199 | }, 200 | headerLeft: { 201 | alignItems: 'flex-start', 202 | flexGrow: 1, 203 | flexBasis: 0, 204 | }, 205 | headerTitle: { 206 | color: 'black', 207 | fontSize: 22, 208 | fontFamily: 'WorkSans-SemiBold', 209 | textAlign: 'center', 210 | }, 211 | headerRight: { 212 | flexDirection: 'row', 213 | justifyContent: 'flex-end', 214 | flexGrow: 1, 215 | flexBasis: 0, 216 | }, 217 | container: { 218 | flex: 1, 219 | backgroundColor: 'rgb(242, 242, 242)', 220 | }, 221 | list: { 222 | flexGrow: 1, 223 | backgroundColor: 'white', 224 | }, 225 | searchInput: { 226 | flex: 1, 227 | backgroundColor: 'white', 228 | borderRadius: 32, 229 | paddingHorizontal: 16, 230 | paddingVertical: 12, 231 | marginRight: 16, 232 | color: 'black', 233 | fontSize: 18, 234 | elevation: 8, 235 | shadowColor: 'lightgrey', 236 | shadowOffset: { width: 0, height: 4 }, 237 | shadowOpacity: 0.3, 238 | shadowRadius: 4.65, 239 | }, 240 | searchBtnContainer: { 241 | borderRadius: 36, 242 | elevation: 12, 243 | }, 244 | searchBtn: { 245 | padding: 12, 246 | backgroundColor: '#54D3C2', 247 | borderRadius: 36, 248 | shadowColor: 'grey', 249 | shadowOffset: { width: 4, height: 4 }, 250 | shadowOpacity: 0.3, 251 | shadowRadius: 12, 252 | }, 253 | headerDetailContainer: { 254 | flexDirection: 'row', 255 | paddingHorizontal: 16, 256 | paddingBottom: 16, 257 | }, 258 | headerDetailTitle: { 259 | color: 'darkgrey', 260 | fontSize: 16, 261 | marginBottom: 8, 262 | fontFamily: 'WorkSans-Regular', 263 | }, 264 | sectionText: { 265 | color: 'black', 266 | fontSize: 16, 267 | fontFamily: 'WorkSans-Regular', 268 | }, 269 | verticalDivider: { 270 | width: 1, 271 | backgroundColor: 'darkgrey', 272 | marginRight: 8, 273 | marginVertical: 8, 274 | }, 275 | headerSectionContainer: { 276 | flex: 1, 277 | paddingHorizontal: 8, 278 | paddingVertical: 4, 279 | }, 280 | stickyHeaderContainer: { 281 | backgroundColor: 'white', 282 | flexDirection: 'row', 283 | paddingHorizontal: 24, 284 | paddingVertical: 8, 285 | }, 286 | hotelCountText: { 287 | flex: 1, 288 | color: 'black', 289 | fontSize: 16, 290 | alignSelf: 'center', 291 | fontFamily: 'WorkSans-Regular', 292 | }, 293 | }); 294 | 295 | export default HotelHomeScreen; 296 | -------------------------------------------------------------------------------- /src/hotel_booking/FiltersModal.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | Modal, 7 | SafeAreaView, 8 | StatusBar, 9 | ScrollView, 10 | } from 'react-native'; 11 | import Icon from 'react-native-vector-icons/MaterialIcons'; 12 | import RangeSliderView from './RangeSliderView'; 13 | import SliderView from './SliderView'; 14 | import MyPressable from '../components/MyPressable'; 15 | import MySwitch from './Switch'; 16 | import Config from '../Config'; 17 | 18 | interface Props { 19 | showFilter: boolean; 20 | setShowFilter: any; 21 | } 22 | 23 | const popularFList = [ 24 | { titleTxt: 'Free Breakfast', isSelected: false }, 25 | { titleTxt: 'Free Parking', isSelected: false }, 26 | { titleTxt: 'Pool', isSelected: true }, 27 | { titleTxt: 'Pet Friendly', isSelected: false }, 28 | { titleTxt: 'Free wifi', isSelected: false }, 29 | ]; 30 | 31 | const accomodation_List = [ 32 | { titleTxt: 'All', isSelected: false }, 33 | { titleTxt: 'Apartment', isSelected: false }, 34 | { titleTxt: 'Home', isSelected: true }, 35 | { titleTxt: 'Villa', isSelected: false }, 36 | { titleTxt: 'Hotel', isSelected: false }, 37 | { titleTxt: 'Resort', isSelected: false }, 38 | ]; 39 | 40 | const FilterModal: React.FC = ({ showFilter, setShowFilter }) => { 41 | const [popularFilterList, setPopularFilterList] = useState(popularFList); 42 | const [accomodationList, setAccomodationList] = useState(accomodation_List); 43 | 44 | const getPList = () => { 45 | const noList: React.JSX.Element[] = []; 46 | let count = 0; 47 | const columnCount = 2; 48 | 49 | for (let i = 0; i < popularFilterList.length / columnCount; i++) { 50 | const listUI: React.JSX.Element[] = []; 51 | for (let j = 0; j < columnCount; j++) { 52 | const data = popularFilterList[count]; 53 | listUI.push( 54 | 58 | { 62 | data.isSelected = !data.isSelected; 63 | setPopularFilterList([...popularFilterList]); 64 | }} 65 | > 66 | 71 | {data.titleTxt} 72 | 73 | , 74 | ); 75 | 76 | if (count < popularFilterList.length - 1) { 77 | count += 1; 78 | } else { 79 | break; 80 | } 81 | } 82 | noList.push( 83 | 84 | {listUI} 85 | , 86 | ); 87 | } 88 | 89 | return noList; 90 | }; 91 | 92 | const checkAppPosition = (index: number) => { 93 | if (index === 0) { 94 | const isAllSelected = accomodationList[0].isSelected; 95 | accomodationList.forEach(d => (d.isSelected = !isAllSelected)); 96 | } else { 97 | accomodationList[index].isSelected = !accomodationList[index].isSelected; 98 | 99 | let count = 0; 100 | for (let i = 0; i < accomodationList.length; i++) { 101 | if (i !== 0) { 102 | const data = accomodationList[i]; 103 | if (data.isSelected) { 104 | count += 1; 105 | } 106 | } 107 | } 108 | 109 | accomodationList[0].isSelected = count === accomodationList.length - 1; 110 | } 111 | 112 | setAccomodationList([...accomodationList]); 113 | }; 114 | 115 | const getAccomodationListUI = () => { 116 | const noList: React.JSX.Element[] = []; 117 | for (let i = 0; i < accomodationList.length; i++) { 118 | const data = accomodationList[i]; 119 | noList.push( 120 | 121 | checkAppPosition(i)} 125 | > 126 | {data.titleTxt} 127 | checkAppPosition(i)} 133 | /> 134 | 135 | , 136 | ); 137 | if (i === 0) { 138 | noList.push(); 139 | } 140 | } 141 | return noList; 142 | }; 143 | 144 | return ( 145 | setShowFilter(false)} 150 | > 151 | 152 | 153 | 154 | 155 | setShowFilter(false)} 160 | > 161 | 162 | 163 | 164 | Filters 165 | 166 | 167 | 168 | 169 | 173 | Price (for 1 night) 174 | 175 | 176 | 177 | 178 | Popular filters 179 | 180 | {getPList()} 181 | 182 | 183 | 186 | Distance from city center 187 | 188 | 189 | 190 | 191 | 194 | Type of Accommodation 195 | 196 | 197 | {getAccomodationListUI()} 198 | 199 | 200 | 201 | 202 | 203 | 204 | setShowFilter(false)} 208 | > 209 | Apply 210 | 211 | 212 | 213 | 214 | 215 | ); 216 | }; 217 | 218 | const styles = StyleSheet.create({ 219 | header: { 220 | flexDirection: 'row', 221 | alignItems: 'center', 222 | padding: 8, 223 | }, 224 | headerText: { 225 | color: 'black', 226 | fontSize: 22, 227 | fontFamily: 'WorkSans-Bold', 228 | textAlign: 'center', 229 | textAlignVertical: 'center', 230 | }, 231 | headerShadow: { 232 | height: Config.isAndroid ? 0.2 : 1, 233 | elevation: 4, 234 | backgroundColor: 'lightgrey', 235 | }, 236 | divider: { height: StyleSheet.hairlineWidth, backgroundColor: 'lightgrey' }, 237 | sectionTitle: { 238 | fontSize: 18, 239 | fontFamily: 'WorkSans-Regular', 240 | color: 'darkgrey', 241 | paddingHorizontal: 16, 242 | }, 243 | checkBoxBtn: { 244 | alignSelf: 'flex-start', 245 | alignItems: 'center', 246 | flexDirection: 'row', 247 | padding: 8, 248 | }, 249 | checkTitle: { 250 | color: 'black', 251 | marginStart: 4, 252 | fontFamily: 'WorkSans-Regular', 253 | }, 254 | switchText: { 255 | flex: 1, 256 | color: 'black', 257 | fontFamily: 'WorkSans-Regular', 258 | alignSelf: 'center', 259 | }, 260 | buttonContainer: { 261 | backgroundColor: '#54D3C2', 262 | borderRadius: 24, 263 | elevation: 8, 264 | overflow: 'hidden', 265 | }, 266 | button: { 267 | height: 48, 268 | alignItems: 'center', 269 | justifyContent: 'center', 270 | borderRadius: 24, 271 | }, 272 | applyBtnShadow: { 273 | backgroundColor: '#54D3C2', 274 | borderRadius: 24, 275 | margin: 16, 276 | marginTop: 8, 277 | shadowColor: 'grey', 278 | shadowOffset: { width: 4, height: 4 }, 279 | shadowOpacity: 0.6, 280 | shadowRadius: 8, 281 | }, 282 | buttonText: { 283 | fontSize: 18, 284 | color: 'white', 285 | fontFamily: 'WorkSans-Medium', 286 | }, 287 | }); 288 | 289 | export default FilterModal; 290 | -------------------------------------------------------------------------------- /src/design_course/CourseInfoScreen.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef } from 'react'; 2 | import { 3 | StyleSheet, 4 | View, 5 | Text, 6 | StatusBar, 7 | ImageBackground, 8 | useWindowDimensions, 9 | ScrollView, 10 | Platform, 11 | Animated, 12 | Easing, 13 | } from 'react-native'; 14 | import { useSafeAreaInsets } from 'react-native-safe-area-context'; 15 | import { useNavigation } from '@react-navigation/native'; 16 | import Icon from 'react-native-vector-icons/MaterialIcons'; 17 | import MyPressable from '../components/MyPressable'; 18 | import { AppImages } from '../assets'; 19 | import Config from '../Config'; 20 | 21 | const infoHeight = 364.0; 22 | 23 | const CourseInfoScreen: React.FC = () => { 24 | const window = useWindowDimensions(); 25 | const navigation = useNavigation(); 26 | const insets = useSafeAreaInsets(); 27 | 28 | const favIconScale = useRef(new Animated.Value(0.1)); 29 | const opacity1 = useRef(new Animated.Value(0)); 30 | const opacity2 = useRef(new Animated.Value(0)); 31 | const opacity3 = useRef(new Animated.Value(0)); 32 | 33 | // const tempHeight = window.height - window.width / 1.2 + 24.0; 34 | const marginTop = Config.isIos 35 | ? Math.max(insets.top, 20) 36 | : StatusBar.currentHeight; 37 | 38 | useEffect(() => { 39 | Animated.timing(favIconScale.current, { 40 | toValue: 1, 41 | duration: 1000, 42 | easing: Easing.out(Easing.cubic), 43 | useNativeDriver: true, 44 | }).start(); 45 | 46 | Animated.parallel([ 47 | Animated.timing(opacity1.current, { 48 | toValue: 1, 49 | duration: 500, 50 | delay: 200, 51 | useNativeDriver: true, 52 | }), 53 | Animated.timing(opacity2.current, { 54 | toValue: 1, 55 | duration: 500, 56 | delay: 400, 57 | useNativeDriver: true, 58 | }), 59 | Animated.timing(opacity3.current, { 60 | toValue: 1, 61 | duration: 500, 62 | delay: 600, 63 | useNativeDriver: true, 64 | }), 65 | ]).start(); 66 | }, []); 67 | 68 | const getTimeBoxUI = (text1: string, text2: string) => ( 69 | 70 | {text1} 71 | {text2} 72 | 73 | ); 74 | 75 | return ( 76 | 77 | 78 | 83 | 89 | infoHeight ? tempHeight : infoHeight, 95 | }} 96 | > 97 | {'Web Design\nCourse'} 98 | 99 | $28.99 100 | 4.3 101 | 102 | 103 | 107 | {getTimeBoxUI('24', 'Classes')} 108 | {getTimeBoxUI('2 hours', 'Time')} 109 | {getTimeBoxUI('24', 'Seat')} 110 | 111 | 115 | Lorem ipsum is simply dummy text of printing & typesetting 116 | industry, Lorem ipsum is simply dummy text of printing & 117 | typesetting industry. 118 | 119 | 120 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | Join Course 134 | 135 | 136 | 137 | 138 | 139 | 148 | 149 | 150 | 151 | navigation.goBack()} 155 | > 156 | 157 | 158 | 159 | 160 | ); 161 | }; 162 | 163 | const styles = StyleSheet.create({ 164 | contentContainer: { 165 | flex: 1, 166 | backgroundColor: 'white', 167 | borderTopLeftRadius: 32, 168 | borderTopRightRadius: 32, 169 | shadowColor: 'grey', 170 | shadowOffset: { width: 1.1, height: 1.1 }, 171 | shadowOpacity: 0.2, 172 | shadowRadius: 10.0, 173 | elevation: 16, 174 | }, 175 | scrollContainer: { 176 | borderTopLeftRadius: 32, 177 | borderTopRightRadius: 32, 178 | paddingHorizontal: 8, 179 | }, 180 | courseTitle: { 181 | color: 'black', 182 | fontSize: 22, 183 | fontFamily: 'WorkSans-SemiBold', 184 | letterSpacing: 0.27, 185 | paddingTop: 32, 186 | paddingLeft: 18, 187 | paddingRight: 16, 188 | }, 189 | priceRatingContainer: { 190 | flexDirection: 'row', 191 | paddingHorizontal: 16, 192 | paddingTop: 12, 193 | paddingBottom: 8, 194 | alignItems: 'center', 195 | }, 196 | price: { 197 | flex: 1, 198 | color: 'rgb(0, 182, 240)', 199 | }, 200 | textStyle: { 201 | fontSize: 22, 202 | fontFamily: 'WorkSans-Regular', 203 | color: 'darkslategrey', 204 | letterSpacing: 0.27, 205 | }, 206 | timeBoxContainer: { 207 | backgroundColor: 'white', 208 | borderRadius: 16, 209 | alignItems: 'center', 210 | margin: 8, 211 | paddingHorizontal: 18, 212 | paddingVertical: 12, 213 | elevation: 8, 214 | shadowColor: 'grey', 215 | shadowOffset: { width: 1.1, height: 1.1 }, 216 | shadowOpacity: 0.22, 217 | shadowRadius: 8.0, 218 | }, 219 | timeBoxTitle: { 220 | fontSize: 14, 221 | fontFamily: 'WorkSans-SemiBold', 222 | color: 'rgb(0, 182, 240)', 223 | }, 224 | boxesContainer: { 225 | flexDirection: 'row', 226 | padding: 8, 227 | }, 228 | courseDescription: { 229 | flex: 1, 230 | fontSize: 14, 231 | fontFamily: 'WorkSans-Regular', 232 | textAlign: 'justify', 233 | color: 'darkslategrey', 234 | letterSpacing: 0.27, 235 | paddingHorizontal: 16, 236 | paddingVertical: 8, 237 | }, 238 | footerContainer: { 239 | flexDirection: 'row', 240 | paddingHorizontal: 24, 241 | // paddingBottom: 16, 242 | }, 243 | addView: { 244 | width: 48, 245 | height: 48, 246 | borderColor: 'lightgrey', 247 | borderWidth: 1, 248 | borderRadius: 16, 249 | justifyContent: 'center', 250 | alignItems: 'center', 251 | }, 252 | joinCourse: { 253 | flex: 1, 254 | borderRadius: 16, 255 | backgroundColor: 'rgb(0, 182, 240)', 256 | elevation: 4, 257 | shadowColor: 'rgb(0, 182, 240)', 258 | shadowOffset: { width: 1.1, height: 1.1 }, 259 | shadowOpacity: 0.5, 260 | shadowRadius: 10.0, 261 | ...Platform.select({ android: { overflow: 'hidden' } }), 262 | }, 263 | joinCourseText: { 264 | padding: 18, 265 | paddingVertical: 12, 266 | fontSize: 18, 267 | fontFamily: 'WorkSans-SemiBold', 268 | alignSelf: 'center', 269 | color: 'white', 270 | }, 271 | favoriteIcon: { 272 | position: 'absolute', 273 | right: 35, 274 | width: 60, 275 | height: 60, 276 | borderRadius: 30, 277 | backgroundColor: 'rgb(0, 182, 240)', 278 | justifyContent: 'center', 279 | alignItems: 'center', 280 | elevation: 18, 281 | shadowColor: 'black', 282 | shadowOffset: { width: 0, height: 5 }, 283 | shadowOpacity: 0.34, 284 | shadowRadius: 6.27, 285 | }, 286 | backBtn: { 287 | position: 'absolute', 288 | width: 56, 289 | height: 56, 290 | borderRadius: 30, 291 | justifyContent: 'center', 292 | alignItems: 'center', 293 | }, 294 | }); 295 | 296 | export default CourseInfoScreen; 297 | --------------------------------------------------------------------------------