Compare commits
1 Commits
main
...
matija_cha
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c6ec9eda4 |
6
.github/workflows/ci-cd.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: yarn
|
||||
cache: npm
|
||||
|
||||
- name: Setup Expo and EAS
|
||||
uses: expo/expo-github-action@v8
|
||||
@ -34,7 +34,7 @@ jobs:
|
||||
token: ${{ secrets.EXPO_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --immutable
|
||||
run: npm ci --legacy-peer-deps
|
||||
|
||||
- name: Prebuild, Build and Submit
|
||||
run: yarn prebuild-build-submit-ios-cicd
|
||||
run: npm run prebuild-build-submit-ios-cicd
|
||||
|
||||
1
.gitignore
vendored
@ -21,4 +21,3 @@ expo-env.d.ts
|
||||
/ios/GoogleService-Info.plist
|
||||
/ios/cally.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
|
||||
expo-env.d.ts
|
||||
./android
|
||||
|
||||
6
.idea/git_toolbox_blame.xml
generated
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxBlameSettings">
|
||||
<option name="version" value="2" />
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/inspectionProfiles/Project_Default.xml
generated
@ -1,7 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="t" enabled="true" level="TEXT ATTRIBUTES" enabled_by_default="true" editorAttributes="CONSIDERATION_ATTRIBUTES" />
|
||||
</profile>
|
||||
</component>
|
||||
6
.idea/jsLinters/eslint.xml
generated
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EslintConfiguration">
|
||||
<option name="fix-on-save" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
85
.idea/jsLinters/jshint.xml
generated
@ -1,85 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JSHintConfiguration" version="2.13.6" use-config-file="false">
|
||||
<option asi="false" />
|
||||
<option bitwise="true" />
|
||||
<option boss="false" />
|
||||
<option browser="true" />
|
||||
<option browserify="false" />
|
||||
<option camelcase="true" />
|
||||
<option couch="false" />
|
||||
<option curly="true" />
|
||||
<option debug="false" />
|
||||
<option devel="false" />
|
||||
<option dojo="false" />
|
||||
<option elision="false" />
|
||||
<option enforceall="false" />
|
||||
<option eqeqeq="true" />
|
||||
<option eqnull="false" />
|
||||
<option es3="false" />
|
||||
<option es5="false" />
|
||||
<option esnext="false" />
|
||||
<option evil="false" />
|
||||
<option expr="false" />
|
||||
<option forin="true" />
|
||||
<option freeze="true" />
|
||||
<option funcscope="false" />
|
||||
<option futurehostile="false" />
|
||||
<option gcl="false" />
|
||||
<option globalstrict="false" />
|
||||
<option immed="false" />
|
||||
<option iterator="false" />
|
||||
<option jasmine="false" />
|
||||
<option jquery="false" />
|
||||
<option lastsemic="false" />
|
||||
<option latedef="false" />
|
||||
<option laxbreak="false" />
|
||||
<option laxcomma="false" />
|
||||
<option loopfunc="false" />
|
||||
<option maxerr="50" />
|
||||
<option mocha="false" />
|
||||
<option module="false" />
|
||||
<option mootools="false" />
|
||||
<option moz="false" />
|
||||
<option multistr="false" />
|
||||
<option newcap="false" />
|
||||
<option noarg="true" />
|
||||
<option nocomma="false" />
|
||||
<option node="false" />
|
||||
<option noempty="true" />
|
||||
<option nomen="false" />
|
||||
<option nonbsp="false" />
|
||||
<option nonew="true" />
|
||||
<option nonstandard="false" />
|
||||
<option notypeof="false" />
|
||||
<option noyield="false" />
|
||||
<option onevar="false" />
|
||||
<option passfail="false" />
|
||||
<option phantom="false" />
|
||||
<option plusplus="false" />
|
||||
<option proto="false" />
|
||||
<option prototypejs="false" />
|
||||
<option qunit="false" />
|
||||
<option quotmark="false" />
|
||||
<option rhino="false" />
|
||||
<option scripturl="false" />
|
||||
<option shadow="false" />
|
||||
<option shelljs="false" />
|
||||
<option singleGroups="false" />
|
||||
<option smarttabs="false" />
|
||||
<option strict="true" />
|
||||
<option sub="false" />
|
||||
<option supernew="false" />
|
||||
<option trailing="false" />
|
||||
<option typed="false" />
|
||||
<option undef="true" />
|
||||
<option unused="false" />
|
||||
<option validthis="false" />
|
||||
<option varstmt="false" />
|
||||
<option white="false" />
|
||||
<option withstmt="false" />
|
||||
<option worker="false" />
|
||||
<option wsh="false" />
|
||||
<option yui="false" />
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/material_theme_project_new.xml
generated
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MaterialThemeProjectNewConfig">
|
||||
<option name="metadata">
|
||||
<MTProjectMetadataState>
|
||||
<option name="migrated" value="true" />
|
||||
<option name="pristineConfig" value="false" />
|
||||
<option name="userId" value="-7d3b2185:193a8bd7023:-7ffe" />
|
||||
</MTProjectMetadataState>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@ -1,4 +1,5 @@
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: "org.jetbrains.kotlin.android"
|
||||
apply plugin: "com.facebook.react"
|
||||
|
||||
@ -20,12 +21,12 @@ react {
|
||||
bundleCommand = "export:embed"
|
||||
|
||||
/* Folders */
|
||||
// The root of your project, i.e. where "package.json" lives. Default is '../..'
|
||||
// root = file("../../")
|
||||
// The folder where the react-native NPM package is. Default is ../../node_modules/react-native
|
||||
// reactNativeDir = file("../../node_modules/react-native")
|
||||
// The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
|
||||
// codegenDir = file("../../node_modules/@react-native/codegen")
|
||||
// The root of your project, i.e. where "package.json" lives. Default is '..'
|
||||
// root = file("../")
|
||||
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
|
||||
// reactNativeDir = file("../node_modules/react-native")
|
||||
// The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
|
||||
// codegenDir = file("../node_modules/@react-native/codegen")
|
||||
|
||||
/* Variants */
|
||||
// The list of variants to that are debuggable. For those we're going to
|
||||
@ -57,9 +58,6 @@ react {
|
||||
//
|
||||
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
|
||||
// hermesFlags = ["-O", "-output-source-map"]
|
||||
|
||||
/* Autolinking */
|
||||
autolinkLibrariesWithApp()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,6 +91,9 @@ android {
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
manifestPlaceholders = [
|
||||
appAuthRedirectScheme: "callyplanner"
|
||||
]
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
@ -121,9 +122,6 @@ android {
|
||||
useLegacyPackaging (findProperty('expo.useLegacyPackaging')?.toBoolean() ?: false)
|
||||
}
|
||||
}
|
||||
androidResources {
|
||||
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||
}
|
||||
}
|
||||
|
||||
// Apply static values from `gradle.properties` to the `android.packagingOptions`
|
||||
@ -175,5 +173,7 @@ dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
applyNativeModulesAppBuildGradle(project)
|
||||
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
@ -1,12 +1,10 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_CALENDAR"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<queries>
|
||||
<intent>
|
||||
@ -15,7 +13,7 @@
|
||||
<data android:scheme="https"/>
|
||||
</intent>
|
||||
</queries>
|
||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true">
|
||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme">
|
||||
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="default"/>
|
||||
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/notification_icon_color"/>
|
||||
<meta-data android:name="expo.modules.notifications.default_notification_color" android:resource="@color/notification_icon_color"/>
|
||||
@ -24,7 +22,7 @@
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://u.expo.dev/bdb8c57b-25bb-4d36-b3b8-5b09c5092f52"/>
|
||||
<activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode|locale|layoutDirection" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
|
||||
<activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
@ -33,10 +31,12 @@
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="callyplanner"/>
|
||||
<data android:scheme="myapp"/>
|
||||
<data android:scheme="com.cally.app"/>
|
||||
<data android:scheme="exp+cally"/>
|
||||
<data android:scheme="callyplanner"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
|
||||
</application>
|
||||
</manifest>
|
||||
@ -1,5 +1,4 @@
|
||||
package com.cally.app
|
||||
import expo.modules.splashscreen.SplashScreenManager
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
@ -16,10 +15,7 @@ class MainActivity : ReactActivity() {
|
||||
// Set the theme to AppTheme BEFORE onCreate to support
|
||||
// coloring the background, status bar, and navigation bar.
|
||||
// This is required for expo-splash-screen.
|
||||
// setTheme(R.style.AppTheme);
|
||||
// @generated begin expo-splashscreen - expo prebuild (DO NOT MODIFY) sync-f3ff59a738c56c9a6119210cb55f0b613eb8b6af
|
||||
SplashScreenManager.registerOnActivity(this)
|
||||
// @generated end expo-splashscreen
|
||||
setTheme(R.style.AppTheme);
|
||||
super.onCreate(null)
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ import com.facebook.react.ReactPackage
|
||||
import com.facebook.react.ReactHost
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
||||
import com.facebook.soloader.SoLoader
|
||||
|
||||
import expo.modules.ApplicationLifecycleDispatcher
|
||||
@ -22,10 +21,9 @@ class MainApplication : Application(), ReactApplication {
|
||||
this,
|
||||
object : DefaultReactNativeHost(this) {
|
||||
override fun getPackages(): List<ReactPackage> {
|
||||
val packages = PackageList(this).packages
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
// packages.add(new MyReactNativePackage());
|
||||
return packages
|
||||
return PackageList(this).packages
|
||||
}
|
||||
|
||||
override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"
|
||||
@ -42,7 +40,7 @@ class MainApplication : Application(), ReactApplication {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
SoLoader.init(this, OpenSourceMergedSoMapping)
|
||||
SoLoader.init(this, false)
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||
load()
|
||||
|
||||
BIN
android/app/src/main/res/drawable-hdpi/splashscreen_image.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 40 KiB |
BIN
android/app/src/main/res/drawable-mdpi/splashscreen_image.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 21 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/splashscreen_image.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 62 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 112 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 170 KiB |
@ -1,6 +1,3 @@
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/splashscreen_background"/>
|
||||
<item>
|
||||
<bitmap android:gravity="center" android:src="@drawable/splashscreen_logo"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 13 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 163 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 21 KiB |
@ -1,6 +1,6 @@
|
||||
<resources>
|
||||
<color name="splashscreen_background">#ffffff</color>
|
||||
<color name="iconBackground">#FFFFFF</color>
|
||||
<color name="iconBackground">#ffffff</color>
|
||||
<color name="colorPrimary">#023c69</color>
|
||||
<color name="colorPrimaryDark">#ffffff</color>
|
||||
<color name="notification_icon_color">#ffffff</color>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">\"Cally \"</string>
|
||||
<string name="app_name">Cally - Family Planner</string>
|
||||
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
||||
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
||||
<string name="expo_system_ui_user_interface_style" translatable="false">light</string>
|
||||
|
||||
@ -11,9 +11,7 @@
|
||||
<item name="android:textColorHint">#c8c8c8</item>
|
||||
<item name="android:textColor">@android:color/black</item>
|
||||
</style>
|
||||
<style name="Theme.App.SplashScreen" parent="Theme.SplashScreen">
|
||||
<item name="windowSplashScreenBackground">@color/splashscreen_background</item>
|
||||
<item name="windowSplashScreenAnimatedIcon">@drawable/splashscreen_logo</item>
|
||||
<item name="postSplashScreenTheme">@style/AppTheme</item>
|
||||
<style name="Theme.App.SplashScreen" parent="AppTheme">
|
||||
<item name="android:windowBackground">@drawable/splashscreen</item>
|
||||
</style>
|
||||
</resources>
|
||||
@ -2,11 +2,11 @@
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
buildToolsVersion = findProperty('android.buildToolsVersion') ?: '35.0.0'
|
||||
minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '24')
|
||||
compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '35')
|
||||
buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0'
|
||||
minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23')
|
||||
compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34')
|
||||
targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34')
|
||||
kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.24'
|
||||
kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.23'
|
||||
|
||||
ndkVersion = "26.1.10909125"
|
||||
}
|
||||
@ -16,10 +16,10 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.2'
|
||||
classpath 'com.google.gms:google-services:4.4.1'
|
||||
classpath('com.android.tools.build:gradle')
|
||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
||||
classpath('com.google.gms:google-services:4.4.2')
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,3 +41,7 @@ allprojects {
|
||||
maven { url 'https://www.jitpack.io' }
|
||||
}
|
||||
}
|
||||
// @generated begin expo-camera-import - expo prebuild (DO NOT MODIFY) sync-f244f4f3d8bf7229102e8f992b525b8602c74770
|
||||
def expoCameraMavenPath = new File(["node", "--print", "require.resolve('expo-camera/package.json')"].execute(null, rootDir).text.trim(), "../android/maven")
|
||||
allprojects { repositories { maven { url(expoCameraMavenPath) } } }
|
||||
// @generated end expo-camera-import
|
||||
@ -22,6 +22,9 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
|
||||
# Enable AAPT2 PNG crunching
|
||||
android.enablePngCrunchInReleaseBuilds=true
|
||||
|
||||
|
||||
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
7
android/gradlew
vendored
Normal file → Executable file
@ -15,8 +15,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@ -57,7 +55,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@ -86,8 +84,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
2
android/gradlew.bat
vendored
@ -13,8 +13,6 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
|
||||
@ -1,27 +1,4 @@
|
||||
pluginManagement {
|
||||
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json')"].execute(null, rootDir).text.trim()).getParentFile().toString())
|
||||
}
|
||||
plugins { id("com.facebook.react.settings") }
|
||||
|
||||
extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
|
||||
if (System.getenv('EXPO_USE_COMMUNITY_AUTOLINKING') == '1') {
|
||||
ex.autolinkLibrariesFromCommand()
|
||||
} else {
|
||||
def command = [
|
||||
'node',
|
||||
'--no-warnings',
|
||||
'--eval',
|
||||
'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))',
|
||||
'react-native-config',
|
||||
'--json',
|
||||
'--platform',
|
||||
'android'
|
||||
].toList()
|
||||
ex.autolinkLibrariesFromCommand(command)
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = 'Cally '
|
||||
rootProject.name = 'Cally - Family Planner'
|
||||
|
||||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
@ -34,5 +11,8 @@ dependencyResolutionManagement {
|
||||
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
|
||||
useExpoModules()
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
applyNativeModulesSettingsGradle(settings)
|
||||
|
||||
include ':app'
|
||||
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile())
|
||||
|
||||
26
app.json
@ -1,10 +1,9 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "Cally ",
|
||||
"name": "Cally - Family Planner",
|
||||
"slug": "cally",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"owner": "tomira",
|
||||
"icon": "./assets/images/icon.png",
|
||||
"scheme": "callyplanner",
|
||||
"userInterfaceStyle": "light",
|
||||
@ -17,19 +16,15 @@
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.cally.app",
|
||||
"googleServicesFile": "./ios/GoogleService-Info.plist",
|
||||
"buildNumber": "100",
|
||||
"usesAppleSignIn": true,
|
||||
"infoPlist": {
|
||||
"ITSAppUsesNonExemptEncryption": false
|
||||
}
|
||||
"buildNumber": "28"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||
"backgroundColor": "#FFFFFF"
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"package": "com.cally.app",
|
||||
"googleServicesFile": "./google-services.json",
|
||||
"googleServicesFile": "./android/app/google-services.json",
|
||||
"permissions": [
|
||||
"android.permission.CAMERA",
|
||||
"android.permission.RECORD_AUDIO"
|
||||
@ -68,18 +63,7 @@
|
||||
"defaultChannel": "default"
|
||||
}
|
||||
],
|
||||
[
|
||||
"expo-calendar",
|
||||
{
|
||||
"calendarPermission": "The app needs to access your calendar."
|
||||
}
|
||||
],
|
||||
[
|
||||
"expo-apple-authentication"
|
||||
],
|
||||
"expo-font",
|
||||
"expo-localization",
|
||||
"./plugins/withPodfile"
|
||||
"expo-font"
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true
|
||||
|
||||
@ -1,362 +1,208 @@
|
||||
import React, {memo, useCallback, useMemo} from "react";
|
||||
import {Drawer} from "expo-router/drawer";
|
||||
import React from "react";
|
||||
import { Drawer } from "expo-router/drawer";
|
||||
import { useSignOut } from "@/hooks/firebase/useSignOut";
|
||||
import {
|
||||
DrawerContentComponentProps,
|
||||
DrawerContentScrollView,
|
||||
DrawerNavigationOptions,
|
||||
DrawerNavigationProp
|
||||
DrawerContentScrollView,
|
||||
DrawerItem,
|
||||
DrawerItemList,
|
||||
} from "@react-navigation/drawer";
|
||||
import {ImageBackground, Pressable, StyleSheet} from "react-native";
|
||||
import {Button, ButtonSize, Text, View} from "react-native-ui-lib";
|
||||
import * as Device from "expo-device";
|
||||
import {DeviceType} from "expo-device";
|
||||
import {useSetAtom} from "jotai";
|
||||
import {Ionicons} from "@expo/vector-icons";
|
||||
import {ParamListBase, RouteProp, Theme} from '@react-navigation/native';
|
||||
|
||||
import {useSignOut} from "@/hooks/firebase/useSignOut";
|
||||
import {CalendarHeader} from "@/components/pages/calendar/CalendarHeader";
|
||||
import { Button, View, Text, ButtonSize } from "react-native-ui-lib";
|
||||
import { StyleSheet } from "react-native";
|
||||
import Feather from "@expo/vector-icons/Feather";
|
||||
import DrawerButton from "@/components/shared/DrawerButton";
|
||||
import DrawerIcon from "@/assets/svgs/DrawerIcon";
|
||||
import {
|
||||
AntDesign,
|
||||
FontAwesome6,
|
||||
MaterialCommunityIcons,
|
||||
Octicons,
|
||||
} from "@expo/vector-icons";
|
||||
import MenuIcon from "@/assets/svgs/MenuIcon";
|
||||
import { router } from "expo-router";
|
||||
import NavGroceryIcon from "@/assets/svgs/NavGroceryIcon";
|
||||
import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
|
||||
import NavBrainDumpIcon from "@/assets/svgs/NavBrainDumpIcon";
|
||||
import NavCalendarIcon from "@/assets/svgs/NavCalendarIcon";
|
||||
import NavSettingsIcon from "@/assets/svgs/NavSettingsIcon";
|
||||
import FeedbackNavIcon from "@/assets/svgs/FeedbackNavIcon";
|
||||
import {
|
||||
isFamilyViewAtom,
|
||||
settingsPageIndex,
|
||||
toDosPageIndex,
|
||||
userSettingsView,
|
||||
} from "@/components/pages/calendar/atoms";
|
||||
import ViewSwitch from "@/components/pages/(tablet_pages)/ViewSwitch";
|
||||
|
||||
const isTablet = Device.deviceType === DeviceType.TABLET;
|
||||
|
||||
type DrawerParamList = {
|
||||
index: undefined;
|
||||
calendar: undefined;
|
||||
brain_dump: undefined;
|
||||
settings: undefined;
|
||||
grocery: undefined;
|
||||
reminders: undefined;
|
||||
todos: undefined;
|
||||
notifications: undefined;
|
||||
feedback: undefined;
|
||||
};
|
||||
|
||||
type DrawerScreenNavigationProp = DrawerNavigationProp<DrawerParamList>;
|
||||
|
||||
interface DrawerButtonConfig {
|
||||
id: string;
|
||||
title: string;
|
||||
color: string;
|
||||
bgColor: string;
|
||||
icon: React.FC;
|
||||
route: keyof DrawerParamList;
|
||||
}
|
||||
|
||||
const DRAWER_BUTTONS: DrawerButtonConfig[] = [
|
||||
{
|
||||
id: 'calendar',
|
||||
title: 'Calendar',
|
||||
color: 'rgb(7, 184, 199)',
|
||||
bgColor: 'rgb(231, 248, 250)',
|
||||
icon: NavCalendarIcon,
|
||||
route: 'calendar'
|
||||
},
|
||||
{
|
||||
id: 'grocery',
|
||||
title: 'Groceries',
|
||||
color: '#50be0c',
|
||||
bgColor: '#eef9e7',
|
||||
icon: NavGroceryIcon,
|
||||
route: 'grocery'
|
||||
},
|
||||
{
|
||||
id: 'feedback',
|
||||
title: 'Feedback',
|
||||
color: '#ea156d',
|
||||
bgColor: '#fdedf4',
|
||||
icon: FeedbackNavIcon,
|
||||
route: 'feedback'
|
||||
},
|
||||
{
|
||||
id: 'todos',
|
||||
title: 'To Dos',
|
||||
color: '#8005eb',
|
||||
bgColor: '#f3e6fd',
|
||||
icon: NavToDosIcon,
|
||||
route: 'todos'
|
||||
},
|
||||
{
|
||||
id: 'brain_dump',
|
||||
title: 'Brain Dump',
|
||||
color: '#e0ca03',
|
||||
bgColor: '#fffacb',
|
||||
icon: NavBrainDumpIcon,
|
||||
route: 'brain_dump'
|
||||
},
|
||||
{
|
||||
id: 'notifications',
|
||||
title: 'Notifications',
|
||||
color: '#ffa200',
|
||||
bgColor: '#ffdda1',
|
||||
icon: () => <Ionicons name="notifications-outline" size={24} color="#ffa200"/>,
|
||||
route: 'notifications'
|
||||
}
|
||||
];
|
||||
|
||||
interface DrawerContentProps {
|
||||
props: DrawerContentComponentProps;
|
||||
}
|
||||
|
||||
const DrawerContent: React.FC<DrawerContentProps> = ({props}) => {
|
||||
const {mutateAsync: signOut} = useSignOut();
|
||||
const setIsFamilyView = useSetAtom(isFamilyViewAtom);
|
||||
const setPageIndex = useSetAtom(settingsPageIndex);
|
||||
const setUserView = useSetAtom(userSettingsView);
|
||||
const setToDosIndex = useSetAtom(toDosPageIndex);
|
||||
|
||||
const handleNavigation = useCallback((route: keyof DrawerParamList) => {
|
||||
props.navigation.navigate(route);
|
||||
setPageIndex(0);
|
||||
setToDosIndex(0);
|
||||
setUserView(true);
|
||||
setIsFamilyView(false);
|
||||
}, [props.navigation, setPageIndex, setToDosIndex, setUserView, setIsFamilyView]);
|
||||
|
||||
const renderDrawerButtons = () => {
|
||||
const midPoint = Math.ceil(DRAWER_BUTTONS.length / 2);
|
||||
const leftButtons = DRAWER_BUTTONS.slice(0, midPoint);
|
||||
const rightButtons = DRAWER_BUTTONS.slice(midPoint);
|
||||
export default function TabLayout() {
|
||||
const { mutateAsync: signOut } = useSignOut();
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
initialRouteName={"index"}
|
||||
screenOptions={{
|
||||
headerShown: true,
|
||||
drawerStyle: {
|
||||
width: "90%",
|
||||
backgroundColor: "#f9f8f7",
|
||||
height: "100%",
|
||||
},
|
||||
drawerIcon: () => <MenuIcon />,
|
||||
}}
|
||||
drawerContent={(props) => {
|
||||
return (
|
||||
<View row paddingH-30>
|
||||
<View flex-1 paddingR-5>
|
||||
{leftButtons.map(button => (
|
||||
<DrawerButton
|
||||
key={button.id}
|
||||
title={button.title}
|
||||
color={button.color}
|
||||
bgColor={button.bgColor}
|
||||
pressFunc={() => handleNavigation(button.route)}
|
||||
icon={<button.icon/>}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
<View flex-1>
|
||||
{rightButtons.map(button => (
|
||||
<DrawerButton
|
||||
key={button.id}
|
||||
title={button.title}
|
||||
color={button.color}
|
||||
bgColor={button.bgColor}
|
||||
pressFunc={() => handleNavigation(button.route)}
|
||||
icon={<button.icon/>}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
<DrawerContentScrollView {...props} style={{ height: "100%" }}>
|
||||
<View centerH centerV margin-30>
|
||||
<Text style={styles.title}>Welcome to Cally</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<DrawerContentScrollView {...props}>
|
||||
<View centerV marginH-30 marginT-20 marginB-20 row>
|
||||
<ImageBackground
|
||||
source={require("../../assets/images/splash.png")}
|
||||
style={styles.logo}
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
paddingHorizontal: 30,
|
||||
}}
|
||||
>
|
||||
<View style={{ flex: 1, paddingRight: 5 }}>
|
||||
<DrawerButton
|
||||
title={"Calendar"}
|
||||
color="rgb(7, 184, 199)"
|
||||
bgColor={"rgb(231, 248, 250)"}
|
||||
pressFunc={() => props.navigation.navigate("calendar")}
|
||||
icon={<NavCalendarIcon />}
|
||||
/>
|
||||
<Text style={styles.title}>Welcome to Cally</Text>
|
||||
<DrawerButton
|
||||
color="#50be0c"
|
||||
title={"Groceries"}
|
||||
bgColor={"#eef9e7"}
|
||||
pressFunc={() => props.navigation.navigate("grocery")}
|
||||
icon={<NavGroceryIcon />}
|
||||
/>
|
||||
</View>
|
||||
<View style={{ flex: 1 }}>
|
||||
{/*<DrawerButton
|
||||
color="#fd1775"
|
||||
title={"My Reminders"}
|
||||
bgColor={"#ffe8f2"}
|
||||
pressFunc={() => props.navigation.navigate("reminders")}
|
||||
icon={
|
||||
<FontAwesome6
|
||||
name="clock-rotate-left"
|
||||
size={28}
|
||||
color="#fd1775"
|
||||
/>
|
||||
}
|
||||
/>*/}
|
||||
<DrawerButton
|
||||
color="#8005eb"
|
||||
title={"To Do's"}
|
||||
bgColor={"#f3e6fd"}
|
||||
pressFunc={() => props.navigation.navigate("todos")}
|
||||
icon={<NavToDosIcon />}
|
||||
/>
|
||||
<DrawerButton
|
||||
color="#e0ca03"
|
||||
title={"Brain Dump"}
|
||||
bgColor={"#fffacb"}
|
||||
pressFunc={() => props.navigation.navigate("brain_dump")}
|
||||
icon={<NavBrainDumpIcon />}
|
||||
/>
|
||||
{/*<DrawerItem label="Logout" onPress={() => signOut()} />*/}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{renderDrawerButtons()}
|
||||
|
||||
<Button
|
||||
onPress={() => handleNavigation('settings')}
|
||||
label="Manage Settings"
|
||||
labelStyle={styles.label}
|
||||
iconSource={() => (
|
||||
<View style={styles.settingsIcon}>
|
||||
<NavSettingsIcon/>
|
||||
</View>
|
||||
)}
|
||||
backgroundColor="white"
|
||||
color="#464039"
|
||||
paddingV-30
|
||||
marginH-30
|
||||
borderRadius={18.55}
|
||||
style={{elevation: 0}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
size={ButtonSize.large}
|
||||
style={styles.signOutButton}
|
||||
label="Sign out of Cally"
|
||||
color="#fd1775"
|
||||
labelStyle={styles.signOut}
|
||||
onPress={() => signOut()}
|
||||
/>
|
||||
</DrawerContentScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
interface HeaderRightProps {
|
||||
route: RouteProp<DrawerParamList>;
|
||||
navigation: DrawerScreenNavigationProp;
|
||||
}
|
||||
|
||||
const HeaderRight: React.FC<HeaderRightProps> = memo(({route, navigation}) => {
|
||||
const showViewSwitch = ["calendar", "todos", "index"].includes(route.name);
|
||||
const isCalendarPage = ["calendar", "index"].includes(route.name);
|
||||
|
||||
if (!isTablet || !showViewSwitch) {
|
||||
return isCalendarPage ? <CalendarHeader/> : null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View marginR-16 row centerV>
|
||||
{isTablet && isCalendarPage && (
|
||||
<View flex-1 center>
|
||||
<CalendarHeader/>
|
||||
</View>
|
||||
)}
|
||||
<ViewSwitch navigation={navigation}/>
|
||||
</View>
|
||||
)
|
||||
});
|
||||
|
||||
interface DrawerScreen {
|
||||
name: keyof DrawerParamList;
|
||||
title: string;
|
||||
hideInDrawer?: boolean;
|
||||
}
|
||||
|
||||
const DRAWER_SCREENS: DrawerScreen[] = [
|
||||
{name: 'index', title: 'Calendar'},
|
||||
{name: 'calendar', title: 'Calendar', hideInDrawer: true},
|
||||
{name: 'brain_dump', title: 'Brain Dump'},
|
||||
{name: 'settings', title: 'Settings'},
|
||||
{name: 'grocery', title: 'Groceries'},
|
||||
{name: 'reminders', title: 'Reminders'},
|
||||
{name: 'todos', title: isTablet ? 'Family To Dos' : 'To Dos'},
|
||||
{name: 'notifications', title: 'Notifications'},
|
||||
{name: 'feedback', title: 'Feedback'}
|
||||
];
|
||||
|
||||
const TabLayout: React.FC = () => {
|
||||
const screenOptions = useMemo(() => {
|
||||
return ({route, navigation}: {
|
||||
route: RouteProp<ParamListBase, string>;
|
||||
navigation: DrawerNavigationProp<ParamListBase, string>;
|
||||
theme: Theme;
|
||||
}): DrawerNavigationOptions => ({
|
||||
lazy: true,
|
||||
headerShown: true,
|
||||
headerTitleAlign: "left",
|
||||
headerTitle: ({children}) => {
|
||||
const isCalendarRoute = ["calendar", "index"].includes(route.name);
|
||||
if (isCalendarRoute) return null;
|
||||
|
||||
return (
|
||||
<View flexG centerV paddingL-10>
|
||||
<Text style={styles.headerTitle}>
|
||||
{children}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
headerLeft: () => (
|
||||
<Pressable
|
||||
onPress={() => navigation.toggleDrawer()}
|
||||
hitSlop={{top: 10, bottom: 10, left: 10, right: 10}}
|
||||
style={({pressed}) => [styles.drawerTrigger, {opacity: pressed ? 0.4 : 1}]}
|
||||
onPress={() => props.navigation.navigate("settings")}
|
||||
label={"Manage Settings"}
|
||||
labelStyle={styles.label}
|
||||
iconSource={() => (
|
||||
<View
|
||||
backgroundColor="#ededed"
|
||||
width={60}
|
||||
height={60}
|
||||
style={{ borderRadius: 50 }}
|
||||
marginR-10
|
||||
centerV
|
||||
centerH
|
||||
>
|
||||
<DrawerIcon/>
|
||||
</Pressable>
|
||||
),
|
||||
headerRight: () => <HeaderRight
|
||||
route={route as RouteProp<DrawerParamList>}
|
||||
navigation={navigation as DrawerNavigationProp<DrawerParamList>}
|
||||
/>,
|
||||
drawerStyle: styles.drawer,
|
||||
});
|
||||
}, []);
|
||||
<NavSettingsIcon />
|
||||
</View>
|
||||
)}
|
||||
backgroundColor="white"
|
||||
color="#464039"
|
||||
paddingV-30
|
||||
marginH-30
|
||||
marginB-10
|
||||
borderRadius={18.55}
|
||||
style={{ elevation: 0 }}
|
||||
/>
|
||||
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
initialRouteName="index"
|
||||
detachInactiveScreens
|
||||
screenOptions={screenOptions}
|
||||
drawerContent={(props) => <DrawerContent props={props}/>}
|
||||
>
|
||||
{DRAWER_SCREENS.map(screen => (
|
||||
<Drawer.Screen
|
||||
key={screen.name}
|
||||
name={screen.name}
|
||||
options={{
|
||||
drawerLabel: screen.title,
|
||||
title: screen.title,
|
||||
...(screen.hideInDrawer && {drawerItemStyle: {display: 'none'}}),
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
<Button
|
||||
size={ButtonSize.large}
|
||||
marginH-30
|
||||
paddingV-15
|
||||
style={{
|
||||
marginTop: "42%",
|
||||
backgroundColor: "transparent",
|
||||
borderWidth: 1.3,
|
||||
borderColor: "#fd1775",
|
||||
}}
|
||||
label="Sign out of Cally"
|
||||
color="#fd1775"
|
||||
labelStyle={styles.signOut}
|
||||
onPress={() => signOut()}
|
||||
/>
|
||||
</DrawerContentScrollView>
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Drawer.Screen
|
||||
name="index"
|
||||
options={{
|
||||
drawerLabel: "Calendar",
|
||||
title: "Calendar",
|
||||
}}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="calendar"
|
||||
options={{
|
||||
drawerLabel: "Calendar",
|
||||
title: "Calendar",
|
||||
drawerItemStyle: { display: "none" },
|
||||
}}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="brain_dump"
|
||||
options={{
|
||||
drawerLabel: "Brain Dump",
|
||||
title: "Brain Dump",
|
||||
}}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="settings"
|
||||
options={{
|
||||
drawerLabel: "Settings",
|
||||
title: "Settings",
|
||||
}}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="grocery"
|
||||
options={{
|
||||
drawerLabel: "Grocery",
|
||||
title: "Grocery",
|
||||
}}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="reminders"
|
||||
options={{
|
||||
drawerLabel: "Reminders",
|
||||
title: "Reminders",
|
||||
}}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="todos"
|
||||
options={{
|
||||
drawerLabel: "To-Do",
|
||||
title: "To-Do's",
|
||||
}}
|
||||
/>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
drawer: {
|
||||
width: isTablet ? "30%" : "90%",
|
||||
backgroundColor: "#f9f8f7",
|
||||
height: "100%",
|
||||
},
|
||||
drawerTrigger: {
|
||||
marginLeft: 16,
|
||||
},
|
||||
headerTitle: {
|
||||
fontFamily: "Manrope_600SemiBold",
|
||||
fontSize: isTablet ? 22 : 17,
|
||||
},
|
||||
logo: {
|
||||
backgroundColor: "transparent",
|
||||
height: 51.43,
|
||||
aspectRatio: 1,
|
||||
marginRight: 8,
|
||||
},
|
||||
settingsIcon: {
|
||||
backgroundColor: "#ededed",
|
||||
width: 60,
|
||||
height: 60,
|
||||
borderRadius: 50,
|
||||
marginRight: 10,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
signOutButton: {
|
||||
marginTop: 50,
|
||||
marginHorizontal: 10,
|
||||
paddingVertical: 15,
|
||||
backgroundColor: "transparent",
|
||||
borderWidth: 1.3,
|
||||
borderColor: "#fd1775",
|
||||
},
|
||||
signOut: {
|
||||
fontFamily: "Poppins_500Medium",
|
||||
fontSize: 15,
|
||||
},
|
||||
label: {
|
||||
fontFamily: "Poppins_400Medium",
|
||||
fontSize: 15,
|
||||
},
|
||||
title: {
|
||||
fontSize: 26.13,
|
||||
fontFamily: "Manrope_600SemiBold",
|
||||
color: "#262627",
|
||||
},
|
||||
signOut: { fontFamily: "Poppins_500Medium", fontSize: 15 },
|
||||
label: { fontFamily: "Poppins_400Medium", fontSize: 15 },
|
||||
title: {
|
||||
fontSize: 26.13,
|
||||
fontFamily: 'Manrope_600SemiBold',
|
||||
color: "#262627"
|
||||
}
|
||||
});
|
||||
|
||||
export default TabLayout;
|
||||
@ -1,13 +1,14 @@
|
||||
import {BrainDumpProvider} from "@/contexts/DumpContext";
|
||||
import {View} from "react-native-ui-lib";
|
||||
import BrainDumpPage from "@/components/pages/brain_dump/BrainDumpPage";
|
||||
import { BrainDumpProvider } from "@/contexts/DumpContext";
|
||||
import { ScrollView } from "react-native-gesture-handler";
|
||||
import { View } from "react-native-ui-lib";
|
||||
|
||||
export default function Screen() {
|
||||
return (
|
||||
<BrainDumpProvider>
|
||||
<View>
|
||||
<BrainDumpPage/>
|
||||
</View>
|
||||
</BrainDumpProvider>
|
||||
);
|
||||
return (
|
||||
<BrainDumpProvider>
|
||||
<View>
|
||||
<BrainDumpPage />
|
||||
</View>
|
||||
</BrainDumpProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,92 +1,14 @@
|
||||
import React, {useEffect} from "react";
|
||||
import {RefreshControl, ScrollView, View} from "react-native";
|
||||
import React from "react";
|
||||
import { CalendarProvider } from "@/contexts/CalendarContext"; // Import the new CalendarPage component
|
||||
import CalendarPage from "@/components/pages/calendar/CalendarPage";
|
||||
import TabletCalendarPage from "@/components/pages/(tablet_pages)/calendar/TabletCalendarPage";
|
||||
import * as Device from "expo-device";
|
||||
import {DeviceType} from "expo-device";
|
||||
import {useCalSync} from "@/hooks/useCalSync";
|
||||
import {colorMap} from "@/constants/colorMap";
|
||||
import {useSetAtom} from "jotai";
|
||||
import {selectedUserAtom} from "@/components/pages/calendar/atoms";
|
||||
import {useAuthContext} from "@/contexts/AuthContext";
|
||||
import { SettingsContextProvider } from "@/contexts/SettingsContext";
|
||||
|
||||
export default function Screen() {
|
||||
const isTablet = Device.deviceType === DeviceType.TABLET;
|
||||
const {resyncAllCalendars, isSyncing} = useCalSync();
|
||||
const setSelectedUser = useSetAtom(selectedUserAtom);
|
||||
const {profileData} = useAuthContext()
|
||||
|
||||
useEffect(() => {
|
||||
if (!isTablet && profileData) setSelectedUser({
|
||||
uid: profileData.uid!,
|
||||
firstName: profileData.firstName,
|
||||
lastName: profileData.lastName,
|
||||
eventColor: profileData?.eventColor!
|
||||
})
|
||||
}, [])
|
||||
|
||||
|
||||
const onRefresh = React.useCallback(async () => {
|
||||
try {
|
||||
await resyncAllCalendars();
|
||||
} catch (error) {
|
||||
console.error("Refresh failed:", error);
|
||||
}
|
||||
}, [resyncAllCalendars]);
|
||||
|
||||
const refreshControl = (
|
||||
<RefreshControl
|
||||
colors={[
|
||||
colorMap.pink,
|
||||
colorMap.green,
|
||||
colorMap.orange,
|
||||
colorMap.purple,
|
||||
colorMap.teal,
|
||||
]}
|
||||
tintColor={colorMap.pink}
|
||||
progressBackgroundColor="white"
|
||||
refreshing={isSyncing}
|
||||
onRefresh={onRefresh}
|
||||
style={isTablet ? {
|
||||
position: "absolute",
|
||||
left: "50%",
|
||||
transform: [{translateX: -20}],
|
||||
} : undefined}
|
||||
/>
|
||||
);
|
||||
|
||||
if (isTablet) {
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<View style={{flex: 1, zIndex: 0}}>
|
||||
<TabletCalendarPage/>
|
||||
</View>
|
||||
<ScrollView
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: "15%",
|
||||
height: "9%",
|
||||
width: "62%",
|
||||
zIndex: 50,
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
contentContainerStyle={{
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
paddingRight: 200,
|
||||
}}
|
||||
bounces={true}
|
||||
showsVerticalScrollIndicator={false}
|
||||
pointerEvents={isSyncing ? "auto" : "none"}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<CalendarPage/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<SettingsContextProvider>
|
||||
<CalendarProvider>
|
||||
<CalendarPage />
|
||||
</CalendarProvider>
|
||||
</SettingsContextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
import {Stack} from "expo-router";
|
||||
|
||||
export default function StackLayout () {
|
||||
return <Stack screenOptions={{headerShown: false}}/>
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
import FeedbackPage from "@/components/pages/feedback/FeedbackPage";
|
||||
import { FeedbackProvider } from "@/contexts/FeedbackContext";
|
||||
import { View } from "react-native-ui-lib";
|
||||
|
||||
export default function Screen() {
|
||||
return (
|
||||
<FeedbackProvider>
|
||||
<View>
|
||||
<FeedbackPage />
|
||||
</View>
|
||||
</FeedbackProvider>
|
||||
);
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
import {Stack} from "expo-router";
|
||||
|
||||
export default function StackLayout () {
|
||||
return <Stack screenOptions={{headerShown: false}}/>
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
import NotificationsPage from "@/components/pages/notifications/NotificationsPage";
|
||||
|
||||
export default function Screen() {
|
||||
return (
|
||||
<NotificationsPage/>
|
||||
);
|
||||
}
|
||||
@ -1,8 +1,11 @@
|
||||
import SettingsPage from "@/components/pages/settings/SettingsPage";
|
||||
import {SettingsContextProvider} from "@/contexts/SettingsContext";
|
||||
import React from "react";
|
||||
|
||||
export default function Screen() {
|
||||
return (
|
||||
<SettingsPage/>
|
||||
<SettingsContextProvider>
|
||||
<SettingsPage/>
|
||||
</SettingsContextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
import TabletChoresPage from "@/components/pages/(tablet_pages)/chores/TabletChoresPage";
|
||||
import AddChore from "@/components/pages/todos/AddChore";
|
||||
import ProgressCard from "@/components/pages/todos/ProgressCard";
|
||||
import ToDoItem from "@/components/pages/todos/ToDoItem";
|
||||
import ToDosList from "@/components/pages/todos/ToDosList";
|
||||
import ToDosPage from "@/components/pages/todos/ToDosPage";
|
||||
import {ToDosContextProvider} from "@/contexts/ToDosContext";
|
||||
import * as Device from "expo-device";
|
||||
import HeaderTemplate from "@/components/shared/HeaderTemplate";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import { ToDosContextProvider, useToDosContext } from "@/contexts/ToDosContext";
|
||||
import { AntDesign } from "@expo/vector-icons";
|
||||
import { ScrollView } from "react-native-gesture-handler";
|
||||
import { Button, ButtonSize, View, Text } from "react-native-ui-lib";
|
||||
|
||||
export default function Screen() {
|
||||
return (
|
||||
<ToDosContextProvider>
|
||||
{Device.deviceType === Device.DeviceType.TABLET ? (
|
||||
<TabletChoresPage/>
|
||||
) : (
|
||||
<ToDosPage/>
|
||||
)}
|
||||
</ToDosContextProvider>
|
||||
);
|
||||
return (
|
||||
<ToDosContextProvider>
|
||||
<ToDosPage />
|
||||
</ToDosContextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,117 +0,0 @@
|
||||
import { SafeAreaView } from "react-native-safe-area-context";
|
||||
import { Button, Text, View, DateTimePicker } from "react-native-ui-lib";
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "expo-router";
|
||||
import { Platform, StyleSheet } from "react-native";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
|
||||
|
||||
export default function BirthdayScreen() {
|
||||
const router = useRouter();
|
||||
const { user } = useAuthContext();
|
||||
const [date, setDate] = useState(new Date());
|
||||
const { mutateAsync: updateUserData } = useUpdateUserData();
|
||||
|
||||
const onDateChange = (event: any, selectedDate?: Date) => {
|
||||
const currentDate = selectedDate || date;
|
||||
setDate(currentDate);
|
||||
};
|
||||
|
||||
const handleContinue = async () => {
|
||||
try {
|
||||
updateUserData({
|
||||
newUserData: {
|
||||
birthday: date,
|
||||
},
|
||||
}).then(() => router.push("/(unauth)/cal_sync"));
|
||||
} catch (error) {
|
||||
console.error("Error saving birthday:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const getMaxDate = () => {
|
||||
const date = new Date();
|
||||
date.setFullYear(date.getFullYear() - 3); // Minimum age: 3 years
|
||||
return date;
|
||||
};
|
||||
|
||||
const getMinDate = () => {
|
||||
const date = new Date();
|
||||
date.setFullYear(date.getFullYear() - 18); // Maximum age: 18 years
|
||||
return date;
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1 }}>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: 21,
|
||||
paddingBottom: 45,
|
||||
paddingTop: "20%",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<View gap-13 width={"100%"} marginB-20>
|
||||
<Text style={{ fontSize: 40, fontFamily: "Manrope_600SemiBold" }}>
|
||||
When's your birthday?
|
||||
</Text>
|
||||
<Text color={"#919191"} style={{ fontSize: 20 }}>
|
||||
We'll use this to celebrate your special day!
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View width={"100%"} flexG>
|
||||
<DateTimePicker
|
||||
value={date}
|
||||
mode="date"
|
||||
minimumDate={getMinDate()}
|
||||
maximumDate={getMaxDate()}
|
||||
onChange={(date) => {
|
||||
if (date) {
|
||||
const validDate = new Date(date);
|
||||
if (!isNaN(validDate.getTime())) {
|
||||
setDate(validDate);
|
||||
}
|
||||
}
|
||||
}}
|
||||
style={styles.textfield}
|
||||
textAlign="center"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View flexG />
|
||||
|
||||
<View width={"100%"}>
|
||||
<Button
|
||||
label="Continue"
|
||||
onPress={handleContinue}
|
||||
style={{
|
||||
height: 50,
|
||||
}}
|
||||
backgroundColor="#fd1775"
|
||||
labelStyle={{
|
||||
fontFamily: "PlusJakartaSans_600SemiBold",
|
||||
fontSize: 16,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
textfield: {
|
||||
backgroundColor: "white",
|
||||
marginVertical: 100,
|
||||
padding: 30,
|
||||
height: 44,
|
||||
borderRadius: 50,
|
||||
fontFamily: "PlusJakartaSans_300Light",
|
||||
fontSize: 15,
|
||||
color: "#919191",
|
||||
alignContent: "center",
|
||||
},
|
||||
});
|
||||
@ -1,256 +0,0 @@
|
||||
import {SafeAreaView} from "react-native-safe-area-context";
|
||||
import {Button, Text, View} from "react-native-ui-lib";
|
||||
import React, { useEffect } from "react";
|
||||
import {useCalSync} from "@/hooks/useCalSync";
|
||||
import GoogleIcon from "@/assets/svgs/GoogleIcon";
|
||||
import AppleIcon from "@/assets/svgs/AppleIcon";
|
||||
import OutlookIcon from "@/assets/svgs/OutlookIcon";
|
||||
import {useAuthContext} from "@/contexts/AuthContext";
|
||||
import {StyleSheet} from "react-native";
|
||||
import { useGetHouseholdName } from "@/hooks/firebase/useGetHouseholdName";
|
||||
|
||||
export default function Screen() {
|
||||
const {profileData, setRedirectOverride} = useAuthContext()
|
||||
const {handleStartGoogleSignIn, handleAppleSignIn, handleMicrosoftSignIn} = useCalSync()
|
||||
const {data: householdName, refetch} = useGetHouseholdName(profileData?.familyId);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
refetch();
|
||||
}, [profileData?.familyId])
|
||||
|
||||
const hasSomeCalendarsSynced =
|
||||
!!profileData?.appleAccounts || !!profileData?.microsoftAccounts || !!profileData?.googleAccounts
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{flex: 1}}>
|
||||
<View style={{flex: 1, padding: 21, paddingBottom: 45, paddingTop: "20%", alignItems: "center"}}>
|
||||
<View gap-13 width={"100%"} marginB-20>
|
||||
{householdName && <Text style={{fontSize: 25, fontFamily: 'Manrope_600SemiBold'}}>
|
||||
You Joined The {householdName} Household
|
||||
</Text>}
|
||||
<Text style={{fontSize: 40, fontFamily: 'Manrope_600SemiBold'}}>
|
||||
Let's get started!
|
||||
</Text>
|
||||
<Text color={"#919191"} style={{fontSize: 20}}>
|
||||
Add your calendar below to sync events to your Cally calendar
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View width={"100%"} gap-1>
|
||||
{!profileData?.googleAccounts && (
|
||||
<Button
|
||||
onPress={() => handleStartGoogleSignIn()}
|
||||
label={"Connect Google account"}
|
||||
labelStyle={styles.addCalLbl}
|
||||
labelProps={{
|
||||
numberOfLines: 2,
|
||||
}}
|
||||
iconSource={() => (
|
||||
<View marginR-15>
|
||||
<GoogleIcon/>
|
||||
</View>
|
||||
)}
|
||||
style={styles.addCalBtn}
|
||||
color="black"
|
||||
text70BL
|
||||
/>
|
||||
)}
|
||||
|
||||
{profileData?.googleAccounts
|
||||
? Object.keys(profileData?.googleAccounts)?.map((googleMail) => {
|
||||
const googleToken = profileData?.googleAccounts?.[googleMail]?.accessToken;
|
||||
return (
|
||||
googleToken && (
|
||||
<Button
|
||||
key={googleMail}
|
||||
disabled
|
||||
label={`Connected ${googleMail}`}
|
||||
labelStyle={styles.addCalLbl}
|
||||
labelProps={{
|
||||
numberOfLines: 2,
|
||||
}}
|
||||
iconSource={() => (
|
||||
<View marginR-15>
|
||||
<GoogleIcon/>
|
||||
</View>
|
||||
)}
|
||||
style={styles.addCalBtn}
|
||||
color="black"
|
||||
text70BL
|
||||
/>
|
||||
)
|
||||
);
|
||||
})
|
||||
: null}
|
||||
|
||||
{!profileData?.appleAccounts && (
|
||||
<Button
|
||||
onPress={() => handleAppleSignIn()}
|
||||
label={"Connect Apple"}
|
||||
labelStyle={styles.addCalLbl}
|
||||
labelProps={{
|
||||
numberOfLines: 2,
|
||||
}}
|
||||
iconSource={() => (
|
||||
<View marginR-15>
|
||||
<AppleIcon/>
|
||||
</View>
|
||||
)}
|
||||
style={styles.addCalBtn}
|
||||
color="black"
|
||||
text70BL
|
||||
/>
|
||||
)}
|
||||
|
||||
{profileData?.appleAccounts
|
||||
? Object.keys(profileData?.appleAccounts)?.map((appleEmail) => {
|
||||
const appleToken = profileData?.appleAccounts?.[appleEmail!];
|
||||
return (
|
||||
appleToken && (
|
||||
<Button
|
||||
key={appleEmail}
|
||||
disabled
|
||||
label={`Connected Apple Calendar`}
|
||||
labelStyle={styles.addCalLbl}
|
||||
labelProps={{
|
||||
numberOfLines: 2,
|
||||
}}
|
||||
iconSource={() => (
|
||||
<View marginR-15>
|
||||
<AppleIcon/>
|
||||
</View>
|
||||
)}
|
||||
style={styles.addCalBtn}
|
||||
color="black"
|
||||
text70BL
|
||||
/>
|
||||
)
|
||||
);
|
||||
})
|
||||
: null}
|
||||
|
||||
{!profileData?.microsoftAccounts && (
|
||||
<Button
|
||||
onPress={() => handleMicrosoftSignIn()}
|
||||
label={"Connect Outlook"}
|
||||
labelStyle={styles.addCalLbl}
|
||||
labelProps={{
|
||||
numberOfLines: 2,
|
||||
}}
|
||||
iconSource={() => (
|
||||
<View marginR-15>
|
||||
<OutlookIcon/>
|
||||
</View>
|
||||
)}
|
||||
style={styles.addCalBtn}
|
||||
color="black"
|
||||
text70BL
|
||||
/>
|
||||
)}
|
||||
|
||||
{profileData?.microsoftAccounts
|
||||
? Object.keys(profileData?.microsoftAccounts)?.map(
|
||||
(microsoftEmail) => {
|
||||
const microsoftToken =
|
||||
profileData?.microsoftAccounts?.[microsoftEmail];
|
||||
return (
|
||||
microsoftToken && (
|
||||
<Button
|
||||
key={microsoftEmail}
|
||||
|
||||
label={`Connected ${microsoftEmail}`}
|
||||
labelStyle={styles.addCalLbl}
|
||||
labelProps={{
|
||||
numberOfLines: 2,
|
||||
}}
|
||||
iconSource={() => (
|
||||
<View marginR-15>
|
||||
<OutlookIcon/>
|
||||
</View>
|
||||
)}
|
||||
style={styles.addCalBtn}
|
||||
color="black"
|
||||
text70BL
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
: null}
|
||||
</View>
|
||||
|
||||
<View flexG/>
|
||||
|
||||
<View width={"100%"}>
|
||||
<Button
|
||||
label={hasSomeCalendarsSynced ? "Continue" : "Skip this step"}
|
||||
onPress={() => setRedirectOverride(false)}
|
||||
marginT-50
|
||||
labelStyle={{
|
||||
fontFamily: "PlusJakartaSans_600SemiBold",
|
||||
fontSize: 16,
|
||||
}}
|
||||
style={{height: 50}}
|
||||
backgroundColor="#fd1775"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
addCalBtn: {
|
||||
backgroundColor: "#ffffff",
|
||||
marginBottom: 15,
|
||||
justifyContent: "flex-start",
|
||||
paddingLeft: 25,
|
||||
},
|
||||
backBtn: {
|
||||
backgroundColor: "red",
|
||||
marginLeft: -2,
|
||||
justifyContent: "flex-start",
|
||||
},
|
||||
card: {
|
||||
backgroundColor: "white",
|
||||
width: "100%",
|
||||
padding: 20,
|
||||
paddingBottom: 30,
|
||||
marginTop: 20,
|
||||
borderRadius: 12,
|
||||
},
|
||||
noPaddingCard: {
|
||||
backgroundColor: "white",
|
||||
width: "100%",
|
||||
marginTop: 20,
|
||||
borderRadius: 12,
|
||||
},
|
||||
colorBox: {
|
||||
aspectRatio: 1,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: 51,
|
||||
borderRadius: 12,
|
||||
},
|
||||
checkbox: {
|
||||
borderRadius: 50,
|
||||
},
|
||||
addCalLbl: {
|
||||
fontSize: 16,
|
||||
fontFamily: "PlusJakartaSan_500Medium",
|
||||
flexWrap: "wrap",
|
||||
width: "75%",
|
||||
textAlign: "left",
|
||||
lineHeight: 20,
|
||||
overflow: "visible",
|
||||
},
|
||||
subTitle: {
|
||||
fontFamily: "Manrope_600SemiBold",
|
||||
fontSize: 18,
|
||||
},
|
||||
cardTitle: {
|
||||
fontFamily: "Manrope_500Medium",
|
||||
fontSize: 15,
|
||||
},
|
||||
});
|
||||
@ -1,229 +0,0 @@
|
||||
import { SafeAreaView } from "react-native-safe-area-context";
|
||||
import {
|
||||
Button,
|
||||
Colors,
|
||||
Dialog,
|
||||
LoaderScreen,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native-ui-lib";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useRouter } from "expo-router";
|
||||
import QRIcon from "@/assets/svgs/QRIcon";
|
||||
import { Camera, CameraView } from "expo-camera";
|
||||
import { useLoginWithQrCode } from "@/hooks/firebase/useLoginWithQrCode";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import debounce from "debounce";
|
||||
import * as Device from "expo-device";
|
||||
import { DeviceType } from "expo-device";
|
||||
import { Dimensions } from "react-native";
|
||||
|
||||
export default function Screen() {
|
||||
const router = useRouter();
|
||||
const { setRedirectOverride } = useAuthContext();
|
||||
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
|
||||
const [showCameraDialog, setShowCameraDialog] = useState<boolean>(false);
|
||||
|
||||
const isTablet: boolean = Device.deviceType === DeviceType.TABLET;
|
||||
const [isPortrait, setIsPortrait] = useState(() => {
|
||||
const dim = Dimensions.get('screen');
|
||||
return dim.height >= dim.width;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = Dimensions.addEventListener('change', ({ screen }) => {
|
||||
setIsPortrait(screen.height >= screen.width);
|
||||
});
|
||||
|
||||
return () => subscription.remove();
|
||||
}, []);
|
||||
|
||||
const getTopPadding = () => {
|
||||
if (Device.deviceType === DeviceType.TABLET) {
|
||||
return isPortrait ? "50%" : "15%";
|
||||
}
|
||||
return "20%"; // non-tablet case, regardless of orientation
|
||||
};
|
||||
|
||||
const { mutateAsync: signInWithQrCode, isLoading } = useLoginWithQrCode();
|
||||
|
||||
const debouncedRouterReplace = useCallback(
|
||||
debounce(() => {
|
||||
router.push("/(unauth)/birthday_page");
|
||||
}, 300),
|
||||
[]
|
||||
);
|
||||
|
||||
const handleQrCodeScanned = async ({ data }: { data: string }) => {
|
||||
setShowCameraDialog(false);
|
||||
setRedirectOverride(true);
|
||||
try {
|
||||
await signInWithQrCode({ userId: data });
|
||||
debouncedRouterReplace();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
const getCameraPermissions = async (callback: () => void) => {
|
||||
const { status } = await Camera.requestCameraPermissionsAsync();
|
||||
setHasPermission(status === "granted");
|
||||
if (status === "granted") {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpenQrCodeDialog = () => {
|
||||
getCameraPermissions(() => setShowCameraDialog(true));
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, alignItems: "center" }}>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: 21,
|
||||
paddingBottom: 45,
|
||||
paddingTop: isLoading ? "20%" : getTopPadding(),
|
||||
width: isTablet ? 629 : '100%'
|
||||
}}
|
||||
>
|
||||
<View center>
|
||||
<Text style={{ fontSize: 30, fontFamily: "Manrope_600SemiBold" }}>
|
||||
Get started with Cally
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View width={"100%"} gap-30>
|
||||
<View>
|
||||
<Button
|
||||
label="Scan QR Code"
|
||||
marginT-50
|
||||
labelStyle={{
|
||||
fontFamily: "PlusJakartaSans_400Regular",
|
||||
fontSize: 16,
|
||||
marginLeft: 10,
|
||||
}}
|
||||
iconSource={() => <QRIcon color={"#07B8C7"} />}
|
||||
onPress={handleOpenQrCodeDialog}
|
||||
style={{ height: 50 }}
|
||||
color={Colors.black}
|
||||
backgroundColor={Colors.white}
|
||||
/>
|
||||
{/* GOOGLE LOGIN HERE */}
|
||||
</View>
|
||||
|
||||
<View row center gap-20>
|
||||
<View flexG style={{ backgroundColor: "#E2E2E2", height: 2 }} />
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 16,
|
||||
fontFamily: "PlusJakartaSans_300Light",
|
||||
color: "#7A7A7A",
|
||||
}}
|
||||
>
|
||||
or
|
||||
</Text>
|
||||
<View flexG style={{ backgroundColor: "#E2E2E2", height: 2 }} />
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<Button
|
||||
label="Continue with Email"
|
||||
labelStyle={{
|
||||
fontFamily: "PlusJakartaSans_400Regular",
|
||||
fontSize: 16,
|
||||
marginLeft: 10,
|
||||
}}
|
||||
onPress={() => router.push("/(unauth)/sign_up")}
|
||||
style={{
|
||||
height: 50,
|
||||
borderStyle: "solid",
|
||||
borderColor: "#E2E2E2",
|
||||
borderWidth: 2,
|
||||
}}
|
||||
color={Colors.black}
|
||||
backgroundColor={"transparent"}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{isTablet ? (
|
||||
<View marginT-30 />
|
||||
) : (
|
||||
<View flexG />
|
||||
)}
|
||||
|
||||
<View row centerH gap-5>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: "PlusJakartaSans_300Light",
|
||||
fontSize: 16,
|
||||
color: "#484848",
|
||||
}}
|
||||
center
|
||||
>
|
||||
Already have an account?
|
||||
</Text>
|
||||
|
||||
<Button
|
||||
label="Log in"
|
||||
link
|
||||
onPress={() => router.push("/(unauth)/sign_in")}
|
||||
labelStyle={[
|
||||
{
|
||||
fontFamily: "PlusJakartaSans_500Medium",
|
||||
fontSize: 16,
|
||||
color: "#919191",
|
||||
},
|
||||
{ fontSize: 16, textDecorationLine: "none", color: "#fd1775" },
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Legacy, move into separate component */}
|
||||
{/* Camera Dialog */}
|
||||
<Dialog
|
||||
visible={showCameraDialog}
|
||||
onDismiss={() => setShowCameraDialog(false)}
|
||||
bottom
|
||||
width="100%"
|
||||
height="70%"
|
||||
containerStyle={{ padding: 15, backgroundColor: "white" }}
|
||||
>
|
||||
<Text center style={{ fontSize: 16 }} marginB-15>
|
||||
Scan a QR code presented from your family member of provider.
|
||||
</Text>
|
||||
{hasPermission === null ? (
|
||||
<Text>Requesting camera permissions...</Text>
|
||||
) : !hasPermission ? (
|
||||
<Text>No access to camera</Text>
|
||||
) : (
|
||||
<CameraView
|
||||
style={{ flex: 1, borderRadius: 15 }}
|
||||
onBarcodeScanned={handleQrCodeScanned}
|
||||
barcodeScannerSettings={{
|
||||
barcodeTypes: ["qr"],
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
label="Cancel"
|
||||
onPress={() => setShowCameraDialog(false)}
|
||||
backgroundColor="#fd1775"
|
||||
style={{ margin: 10, marginBottom: 30 }}
|
||||
/>
|
||||
</Dialog>
|
||||
|
||||
{isLoading && (
|
||||
<LoaderScreen
|
||||
overlay
|
||||
message={"Signing in..."}
|
||||
backgroundColor={Colors.white}
|
||||
color={Colors.grey40}
|
||||
/>
|
||||
)}
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
import { SafeAreaView } from "react-native-safe-area-context";
|
||||
import { Button, Text, View, TextField } from "react-native-ui-lib";
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "expo-router";
|
||||
import { StyleSheet } from "react-native";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import { useUpdateHouseholdName } from "@/hooks/firebase/useUpdateHouseholdName";
|
||||
|
||||
export default function NewHouseholdScreen() {
|
||||
const router = useRouter();
|
||||
const { user, profileData } = useAuthContext();
|
||||
const [householdName, setHouseholdName] = useState("");
|
||||
const { mutateAsync: newHousehold } = useUpdateHouseholdName();
|
||||
|
||||
const handleContinue = async () => {
|
||||
try {
|
||||
if(profileData?.familyId)
|
||||
newHousehold({familyId: profileData?.familyId, name: householdName}).then(() => router.push("/(unauth)/cal_sync"));
|
||||
} catch (error) {
|
||||
console.error("Error saving household name:", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1 }}>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: 21,
|
||||
paddingBottom: 45,
|
||||
paddingTop: "20%",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<View gap-13 width={"100%"} marginB-20>
|
||||
<Text style={{ fontSize: 40, fontFamily: "Manrope_600SemiBold" }}>
|
||||
Name your household
|
||||
</Text>
|
||||
<Text color={"#919191"} style={{ fontSize: 20 }}>
|
||||
Give your family group a unique name!
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View width={"100%"} flexG>
|
||||
<TextField
|
||||
value={householdName}
|
||||
onChangeText={setHouseholdName}
|
||||
placeholder="Enter household name"
|
||||
style={styles.textfield}
|
||||
textAlign="center"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View flexG />
|
||||
|
||||
<View width={"100%"}>
|
||||
<Button
|
||||
label="Continue"
|
||||
onPress={handleContinue}
|
||||
style={{
|
||||
height: 50,
|
||||
}}
|
||||
backgroundColor="#fd1775"
|
||||
labelStyle={{
|
||||
fontFamily: "PlusJakartaSans_600SemiBold",
|
||||
fontSize: 16,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
textfield: {
|
||||
backgroundColor: "white",
|
||||
marginVertical: 100,
|
||||
padding: 30,
|
||||
height: 44,
|
||||
borderRadius: 50,
|
||||
fontFamily: "PlusJakartaSans_300Light",
|
||||
fontSize: 15,
|
||||
color: "#919191",
|
||||
alignContent: "center",
|
||||
},
|
||||
});
|
||||
@ -1,46 +1,10 @@
|
||||
import Entry from "@/components/pages/main/Entry";
|
||||
import {SafeAreaView} from "react-native-safe-area-context";
|
||||
import {Button, Image, Text, View} from "react-native-ui-lib";
|
||||
import React from "react";
|
||||
import {useRouter} from "expo-router";
|
||||
import * as Device from "expo-device";
|
||||
import { DeviceType } from "expo-device";
|
||||
|
||||
export default function Screen() {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{flex: 1}}>
|
||||
<View style={{flex: 1, padding: 21, paddingBottom: 45, paddingTop: "20%", alignItems: "center"}}>
|
||||
<View>
|
||||
<Image source={require("../../assets/images/splash.png")}/>
|
||||
</View>
|
||||
|
||||
<View center gap-13>
|
||||
<Text style={{fontSize: 40, fontFamily: 'Manrope_600SemiBold', marginLeft: 5}}>
|
||||
Welcome to Cally
|
||||
</Text>
|
||||
<Text center color={"#919191"} style={{fontSize: 20, maxWidth: 250}}>
|
||||
Lightening Mental Loads,
|
||||
One Family at a Time
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View flexG/>
|
||||
|
||||
<View width={"100%"} centerH>
|
||||
<Button
|
||||
label="Continue"
|
||||
marginT-50
|
||||
labelStyle={{
|
||||
fontFamily: "PlusJakartaSans_600SemiBold",
|
||||
fontSize: 16,
|
||||
}}
|
||||
onPress={() => router.push("/(unauth)/get_started")}
|
||||
style={{height: 50, width: Device.deviceType === DeviceType.TABLET ? 629 : "100%"}}
|
||||
backgroundColor="#fd1775"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<SafeAreaView>
|
||||
<Entry/>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
}
|
||||
0
app/(unauth)/onboarding_flow/_layout.tsx
Normal file
@ -1,5 +1,5 @@
|
||||
import Entry from "@/components/pages/main/Entry";
|
||||
|
||||
export default function Screen() {
|
||||
return <Entry />;
|
||||
return <Entry />;
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
import React from "react";
|
||||
import {ResetPasswordPage} from "@/components/pages/main/ResetPasswordPage";
|
||||
|
||||
export default function Screen() {
|
||||
return <ResetPasswordPage/>
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
import SignInPage from "@/components/pages/main/SignInPage";
|
||||
import React from "react";
|
||||
|
||||
export default function Screen() {
|
||||
return <SignInPage/>
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
import React from "react";
|
||||
import SignUpPage from "@/components/pages/main/SignUpPage";
|
||||
|
||||
export default function Screen() {
|
||||
return (
|
||||
<SignUpPage/>
|
||||
)
|
||||
}
|
||||
464
app/_layout.tsx
@ -1,6 +1,170 @@
|
||||
import React, {useEffect} from "react";
|
||||
import {DefaultTheme, ThemeProvider} from "@react-navigation/native";
|
||||
import React, { useEffect } from "react";
|
||||
import { DefaultTheme, ThemeProvider } from "@react-navigation/native";
|
||||
import {
|
||||
useFonts,
|
||||
Manrope_200ExtraLight,
|
||||
Manrope_300Light,
|
||||
Manrope_400Regular,
|
||||
Manrope_500Medium,
|
||||
Manrope_600SemiBold,
|
||||
Manrope_700Bold,
|
||||
Manrope_800ExtraBold,
|
||||
} from "@expo-google-fonts/manrope";
|
||||
import {
|
||||
PlusJakartaSans_200ExtraLight,
|
||||
PlusJakartaSans_300Light,
|
||||
PlusJakartaSans_400Regular,
|
||||
PlusJakartaSans_500Medium,
|
||||
PlusJakartaSans_600SemiBold,
|
||||
PlusJakartaSans_700Bold,
|
||||
PlusJakartaSans_800ExtraBold,
|
||||
PlusJakartaSans_200ExtraLight_Italic,
|
||||
PlusJakartaSans_300Light_Italic,
|
||||
PlusJakartaSans_400Regular_Italic,
|
||||
PlusJakartaSans_500Medium_Italic,
|
||||
PlusJakartaSans_600SemiBold_Italic,
|
||||
PlusJakartaSans_700Bold_Italic,
|
||||
PlusJakartaSans_800ExtraBold_Italic,
|
||||
} from "@expo-google-fonts/plus-jakarta-sans";
|
||||
import {
|
||||
Poppins_100Thin,
|
||||
Poppins_100Thin_Italic,
|
||||
Poppins_200ExtraLight,
|
||||
Poppins_200ExtraLight_Italic,
|
||||
Poppins_300Light,
|
||||
Poppins_300Light_Italic,
|
||||
Poppins_400Regular,
|
||||
Poppins_400Regular_Italic,
|
||||
Poppins_500Medium,
|
||||
Poppins_500Medium_Italic,
|
||||
Poppins_600SemiBold,
|
||||
Poppins_600SemiBold_Italic,
|
||||
Poppins_700Bold,
|
||||
Poppins_700Bold_Italic,
|
||||
Poppins_800ExtraBold,
|
||||
Poppins_800ExtraBold_Italic,
|
||||
Poppins_900Black,
|
||||
Poppins_900Black_Italic,
|
||||
} from "@expo-google-fonts/poppins";
|
||||
import { Stack } from "expo-router";
|
||||
import * as SplashScreen from "expo-splash-screen";
|
||||
import "react-native-reanimated";
|
||||
import { AuthContextProvider } from "@/contexts/AuthContext";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import {
|
||||
ThemeManager,
|
||||
Typography,
|
||||
Toast,
|
||||
TextProps,
|
||||
} from "react-native-ui-lib";
|
||||
import functions from "@react-native-firebase/functions";
|
||||
import auth from "@react-native-firebase/auth";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
if (__DEV__) {
|
||||
functions().useEmulator("localhost", 5001);
|
||||
firestore().useEmulator("localhost", 5471);
|
||||
auth().useEmulator("http://localhost:9099");
|
||||
}
|
||||
|
||||
type TextStyleBase =
|
||||
| "text10"
|
||||
| "text20"
|
||||
| "text30"
|
||||
| "text40"
|
||||
| "text50"
|
||||
| "text60"
|
||||
| "text70"
|
||||
| "text80"
|
||||
| "text90"
|
||||
| "text100";
|
||||
type TextStyleModifier = "R" | "M" | "BO" | "H" | "BL" | "L";
|
||||
type TextStyle = TextStyleBase | `${TextStyleBase}${TextStyleModifier}`;
|
||||
|
||||
type TextStyleProps = {
|
||||
[K in TextStyle]?: boolean;
|
||||
};
|
||||
|
||||
type ExtendedTextProps = TextProps & TextStyleProps;
|
||||
|
||||
interface FontStyle {
|
||||
fontFamily: string;
|
||||
fontSize: number;
|
||||
}
|
||||
|
||||
const getManropeFontStyle = (style: TextStyle): FontStyle => {
|
||||
let fontFamily: string;
|
||||
let fontSize: number;
|
||||
|
||||
if (style.includes("L") || style.includes("BL"))
|
||||
fontFamily = "Manrope_300Light";
|
||||
else if (style.includes("R")) fontFamily = "Manrope_400Regular";
|
||||
else if (style.includes("M")) fontFamily = "Manrope_500Medium";
|
||||
else if (style.includes("BO") || style.includes("H"))
|
||||
fontFamily = "Manrope_700Bold";
|
||||
else {
|
||||
const baseStyle = style.slice(0, 6) as TextStyleBase;
|
||||
switch (baseStyle) {
|
||||
case "text10":
|
||||
case "text20":
|
||||
fontFamily = "Manrope_700Bold";
|
||||
break;
|
||||
case "text30":
|
||||
case "text40":
|
||||
fontFamily = "Manrope_600SemiBold";
|
||||
break;
|
||||
case "text50":
|
||||
fontFamily = "Manrope_400Regular";
|
||||
break;
|
||||
default:
|
||||
fontFamily = "Manrope_300Light";
|
||||
}
|
||||
}
|
||||
|
||||
switch (style.slice(0, 6) as TextStyleBase) {
|
||||
case "text10":
|
||||
fontSize = 64;
|
||||
break;
|
||||
case "text20":
|
||||
fontSize = 50;
|
||||
break;
|
||||
case "text30":
|
||||
fontSize = 36;
|
||||
break;
|
||||
case "text40":
|
||||
fontSize = 28;
|
||||
break;
|
||||
case "text50":
|
||||
fontSize = 24;
|
||||
break;
|
||||
case "text60":
|
||||
fontSize = 20;
|
||||
break;
|
||||
case "text70":
|
||||
fontSize = 16;
|
||||
break;
|
||||
case "text80":
|
||||
fontSize = 14;
|
||||
break;
|
||||
case "text90":
|
||||
fontSize = 12;
|
||||
break;
|
||||
case "text100":
|
||||
fontSize = 10;
|
||||
break;
|
||||
default:
|
||||
fontSize = 16;
|
||||
}
|
||||
|
||||
return { fontFamily, fontSize };
|
||||
};
|
||||
|
||||
export default function RootLayout() {
|
||||
const [loaded] = useFonts({
|
||||
Manrope_200ExtraLight,
|
||||
Manrope_300Light,
|
||||
Manrope_400Regular,
|
||||
@ -8,25 +172,20 @@ import {
|
||||
Manrope_600SemiBold,
|
||||
Manrope_700Bold,
|
||||
Manrope_800ExtraBold,
|
||||
useFonts,
|
||||
} from "@expo-google-fonts/manrope";
|
||||
import {
|
||||
PlusJakartaSans_200ExtraLight,
|
||||
PlusJakartaSans_200ExtraLight_Italic,
|
||||
PlusJakartaSans_300Light,
|
||||
PlusJakartaSans_300Light_Italic,
|
||||
PlusJakartaSans_400Regular,
|
||||
PlusJakartaSans_400Regular_Italic,
|
||||
PlusJakartaSans_500Medium,
|
||||
PlusJakartaSans_500Medium_Italic,
|
||||
PlusJakartaSans_600SemiBold,
|
||||
PlusJakartaSans_600SemiBold_Italic,
|
||||
PlusJakartaSans_700Bold,
|
||||
PlusJakartaSans_700Bold_Italic,
|
||||
PlusJakartaSans_800ExtraBold,
|
||||
PlusJakartaSans_200ExtraLight_Italic,
|
||||
PlusJakartaSans_300Light_Italic,
|
||||
PlusJakartaSans_400Regular_Italic,
|
||||
PlusJakartaSans_500Medium_Italic,
|
||||
PlusJakartaSans_600SemiBold_Italic,
|
||||
PlusJakartaSans_700Bold_Italic,
|
||||
PlusJakartaSans_800ExtraBold_Italic,
|
||||
} from "@expo-google-fonts/plus-jakarta-sans";
|
||||
import {
|
||||
Poppins_100Thin,
|
||||
Poppins_100Thin_Italic,
|
||||
Poppins_200ExtraLight,
|
||||
@ -45,233 +204,72 @@ import {
|
||||
Poppins_800ExtraBold_Italic,
|
||||
Poppins_900Black,
|
||||
Poppins_900Black_Italic,
|
||||
} from "@expo-google-fonts/poppins";
|
||||
import {Stack} from "expo-router";
|
||||
import * as SplashScreen from "expo-splash-screen";
|
||||
import "react-native-reanimated";
|
||||
import {AuthContextProvider} from "@/contexts/AuthContext";
|
||||
import {TextProps, ThemeManager, Toast, Typography,} from "react-native-ui-lib";
|
||||
import {Platform} from 'react-native';
|
||||
import KeyboardManager from 'react-native-keyboard-manager';
|
||||
import {enableScreens, enableFreeze} from 'react-native-screens';
|
||||
import {PersistQueryClientProvider} from "@/contexts/PersistQueryClientProvider";
|
||||
import auth from "@react-native-firebase/auth";
|
||||
import firestore from '@react-native-firebase/firestore';
|
||||
import functions from '@react-native-firebase/functions';
|
||||
});
|
||||
|
||||
enableScreens(true)
|
||||
enableFreeze(true)
|
||||
useEffect(() => {
|
||||
if (loaded) {
|
||||
SplashScreen.hideAsync();
|
||||
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
const typographies: Partial<Record<TextStyle, FontStyle>> = {};
|
||||
(
|
||||
[
|
||||
"text10",
|
||||
"text20",
|
||||
"text30",
|
||||
"text40",
|
||||
"text50",
|
||||
"text60",
|
||||
"text70",
|
||||
"text80",
|
||||
"text90",
|
||||
"text100",
|
||||
] as const
|
||||
).forEach((baseStyle) => {
|
||||
typographies[baseStyle] = getManropeFontStyle(baseStyle);
|
||||
(["R", "M", "BO", "H", "BL", "L"] as const).forEach((modifier) => {
|
||||
const style = `${baseStyle}${modifier}` as TextStyle;
|
||||
typographies[style] = getManropeFontStyle(style);
|
||||
});
|
||||
});
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
KeyboardManager.setEnable(true);
|
||||
KeyboardManager.setToolbarPreviousNextButtonEnable(true);
|
||||
}
|
||||
Typography.loadTypographies(typographies);
|
||||
|
||||
if (__DEV__) {
|
||||
// functions().useEmulator("localhost", 5001);
|
||||
// firestore().useEmulator("localhost", 5471);
|
||||
// auth().useEmulator("http://localhost:9099");
|
||||
}
|
||||
ThemeManager.setComponentTheme(
|
||||
"Text",
|
||||
(props: ExtendedTextProps, context: unknown) => {
|
||||
const textStyle = (
|
||||
Object.keys(props) as Array<keyof ExtendedTextProps>
|
||||
).find((key) => typographies[key as TextStyle]) as
|
||||
| TextStyle
|
||||
| undefined;
|
||||
|
||||
type TextStyleBase =
|
||||
| "text10"
|
||||
| "text20"
|
||||
| "text30"
|
||||
| "text40"
|
||||
| "text50"
|
||||
| "text60"
|
||||
| "text70"
|
||||
| "text80"
|
||||
| "text90"
|
||||
| "text100";
|
||||
type TextStyleModifier = "R" | "M" | "BO" | "H" | "BL" | "L";
|
||||
type TextStyle = TextStyleBase | `${TextStyleBase}${TextStyleModifier}`;
|
||||
|
||||
type TextStyleProps = {
|
||||
[K in TextStyle]?: boolean;
|
||||
};
|
||||
|
||||
type ExtendedTextProps = TextProps & TextStyleProps;
|
||||
|
||||
interface FontStyle {
|
||||
fontFamily: string;
|
||||
fontSize: number;
|
||||
}
|
||||
|
||||
const getManropeFontStyle = (style: TextStyle): FontStyle => {
|
||||
let fontFamily: string;
|
||||
let fontSize: number;
|
||||
|
||||
if (style.includes("L") || style.includes("BL"))
|
||||
fontFamily = "Manrope_300Light";
|
||||
else if (style.includes("R")) fontFamily = "Manrope_400Regular";
|
||||
else if (style.includes("M")) fontFamily = "Manrope_500Medium";
|
||||
else if (style.includes("BO") || style.includes("H"))
|
||||
fontFamily = "Manrope_700Bold";
|
||||
else {
|
||||
const baseStyle = style.slice(0, 6) as TextStyleBase;
|
||||
switch (baseStyle) {
|
||||
case "text10":
|
||||
case "text20":
|
||||
fontFamily = "Manrope_700Bold";
|
||||
break;
|
||||
case "text30":
|
||||
case "text40":
|
||||
fontFamily = "Manrope_600SemiBold";
|
||||
break;
|
||||
case "text50":
|
||||
fontFamily = "Manrope_400Regular";
|
||||
break;
|
||||
default:
|
||||
fontFamily = "Manrope_300Light";
|
||||
return {
|
||||
style: [
|
||||
Typography.text50,
|
||||
textStyle ? typographies[textStyle] : undefined,
|
||||
],
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
}, [loaded]);
|
||||
|
||||
switch (style.slice(0, 6) as TextStyleBase) {
|
||||
case "text10":
|
||||
fontSize = 64;
|
||||
break;
|
||||
case "text20":
|
||||
fontSize = 50;
|
||||
break;
|
||||
case "text30":
|
||||
fontSize = 36;
|
||||
break;
|
||||
case "text40":
|
||||
fontSize = 28;
|
||||
break;
|
||||
case "text50":
|
||||
fontSize = 24;
|
||||
break;
|
||||
case "text60":
|
||||
fontSize = 20;
|
||||
break;
|
||||
case "text70":
|
||||
fontSize = 16;
|
||||
break;
|
||||
case "text80":
|
||||
fontSize = 14;
|
||||
break;
|
||||
case "text90":
|
||||
fontSize = 12;
|
||||
break;
|
||||
case "text100":
|
||||
fontSize = 10;
|
||||
break;
|
||||
default:
|
||||
fontSize = 16;
|
||||
}
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {fontFamily, fontSize};
|
||||
};
|
||||
|
||||
export default function RootLayout() {
|
||||
const [loaded] = useFonts({
|
||||
Manrope_200ExtraLight,
|
||||
Manrope_300Light,
|
||||
Manrope_400Regular,
|
||||
Manrope_500Medium,
|
||||
Manrope_600SemiBold,
|
||||
Manrope_700Bold,
|
||||
Manrope_800ExtraBold,
|
||||
PlusJakartaSans_200ExtraLight,
|
||||
PlusJakartaSans_300Light,
|
||||
PlusJakartaSans_400Regular,
|
||||
PlusJakartaSans_500Medium,
|
||||
PlusJakartaSans_600SemiBold,
|
||||
PlusJakartaSans_700Bold,
|
||||
PlusJakartaSans_800ExtraBold,
|
||||
PlusJakartaSans_200ExtraLight_Italic,
|
||||
PlusJakartaSans_300Light_Italic,
|
||||
PlusJakartaSans_400Regular_Italic,
|
||||
PlusJakartaSans_500Medium_Italic,
|
||||
PlusJakartaSans_600SemiBold_Italic,
|
||||
PlusJakartaSans_700Bold_Italic,
|
||||
PlusJakartaSans_800ExtraBold_Italic,
|
||||
Poppins_100Thin,
|
||||
Poppins_100Thin_Italic,
|
||||
Poppins_200ExtraLight,
|
||||
Poppins_200ExtraLight_Italic,
|
||||
Poppins_300Light,
|
||||
Poppins_300Light_Italic,
|
||||
Poppins_400Regular,
|
||||
Poppins_400Regular_Italic,
|
||||
Poppins_500Medium,
|
||||
Poppins_500Medium_Italic,
|
||||
Poppins_600SemiBold,
|
||||
Poppins_600SemiBold_Italic,
|
||||
Poppins_700Bold,
|
||||
Poppins_700Bold_Italic,
|
||||
Poppins_800ExtraBold,
|
||||
Poppins_800ExtraBold_Italic,
|
||||
Poppins_900Black,
|
||||
Poppins_900Black_Italic,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (loaded) {
|
||||
const typographies: Partial<Record<TextStyle, FontStyle>> = {};
|
||||
(
|
||||
[
|
||||
"text10",
|
||||
"text20",
|
||||
"text30",
|
||||
"text40",
|
||||
"text50",
|
||||
"text60",
|
||||
"text70",
|
||||
"text80",
|
||||
"text90",
|
||||
"text100",
|
||||
] as const
|
||||
).forEach((baseStyle) => {
|
||||
typographies[baseStyle] = getManropeFontStyle(baseStyle);
|
||||
(["R", "M", "BO", "H", "BL", "L"] as const).forEach((modifier) => {
|
||||
const style = `${baseStyle}${modifier}` as TextStyle;
|
||||
typographies[style] = getManropeFontStyle(style);
|
||||
});
|
||||
});
|
||||
|
||||
Typography.loadTypographies(typographies);
|
||||
|
||||
ThemeManager.setComponentTheme(
|
||||
"Text",
|
||||
(props: ExtendedTextProps) => {
|
||||
const textStyle = (
|
||||
Object.keys(props) as Array<keyof ExtendedTextProps>
|
||||
).find((key) => typographies[key as TextStyle]) as
|
||||
| TextStyle
|
||||
| undefined;
|
||||
|
||||
return {
|
||||
style: [
|
||||
Typography.text50,
|
||||
textStyle ? typographies[textStyle] : undefined,
|
||||
],
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
}, [loaded]);
|
||||
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<PersistQueryClientProvider>
|
||||
<AuthContextProvider>
|
||||
<ThemeProvider value={DefaultTheme}>
|
||||
<Stack>
|
||||
<Stack.Screen name="(auth)" options={{headerShown: false}}/>
|
||||
<Stack.Screen name="(unauth)" options={{headerShown: false}}/>
|
||||
<Stack.Screen name="+not-found"/>
|
||||
</Stack>
|
||||
<Toast/>
|
||||
</ThemeProvider>
|
||||
</AuthContextProvider>
|
||||
</PersistQueryClientProvider>
|
||||
);
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthContextProvider>
|
||||
<ThemeProvider value={DefaultTheme}>
|
||||
<Stack>
|
||||
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
|
||||
<Stack.Screen name="(unauth)" options={{ headerShown: false }} />
|
||||
<Stack.Screen name="+not-found" />
|
||||
</Stack>
|
||||
<Toast />
|
||||
</ThemeProvider>
|
||||
</AuthContextProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB |
BIN
assets/images/splash-clock.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 46 KiB |
@ -1,19 +0,0 @@
|
||||
import * as React from "react"
|
||||
import Svg, { SvgProps, Path } from "react-native-svg"
|
||||
const ArrowRightIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={9}
|
||||
height={15}
|
||||
viewBox="0 0 9 15"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke="#ACACAC"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={2}
|
||||
d="M1.272 1.803 7.16 7.69a.16.16 0 0 1 0 .226l-5.887 5.887"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
export default ArrowRightIcon
|
||||
@ -4,7 +4,6 @@ const CalendarIcon: React.FC<SvgProps> = (props) => (
|
||||
<Svg
|
||||
width={props.width || 21}
|
||||
height={props.height || 21}
|
||||
viewBox="0 0 21 21"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
import * as React from "react"
|
||||
import Svg, { SvgProps, Path } from "react-native-svg"
|
||||
const CheckmarkIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={13}
|
||||
height={10}
|
||||
viewBox="0 0 13 10"
|
||||
fill={props.color || "white"}
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke="#fff"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={1.95}
|
||||
d="m1.48 5.489 3.2 3.178 7.2-7.15"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
export default CheckmarkIcon
|
||||
@ -1,22 +0,0 @@
|
||||
import * as React from "react";
|
||||
import Svg, { SvgProps, Path } from "react-native-svg";
|
||||
const CircledXIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={props.width || 22}
|
||||
height={props.height || 21}
|
||||
viewBox="0 0 22 21"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke={props.color || "#BBB"}
|
||||
d="M11 20.5c5.523 0 10-4.477 10-10S16.523.5 11 .5 1 4.977 1 10.5s4.477 10 10 10Z"
|
||||
/>
|
||||
<Path
|
||||
stroke={props.color || "#BBB"}
|
||||
strokeLinecap="round"
|
||||
d="m13.75 7.75-5.5 5.5m0-5.5 5.5 5.5"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
export default CircledXIcon;
|
||||
@ -1,20 +0,0 @@
|
||||
import * as React from "react"
|
||||
import Svg, { SvgProps, Path } from "react-native-svg"
|
||||
const ClockOIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={props.height || 22}
|
||||
height={props.height || 22}
|
||||
viewBox="0 0 22 22"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke={props.color || "#919191"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M11 5.444V11l1.667 2.778M21 11c0 5.523-4.477 10-10 10S1 16.523 1 11 5.477 1 11 1s10 4.477 10 10Z"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
export default ClockOIcon
|
||||
@ -5,14 +5,13 @@ const CloseXIcon: React.FC<SvgProps> = (props) => (
|
||||
width={15}
|
||||
height={15}
|
||||
fill="none"
|
||||
viewBox="0 0 15 15"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke="#AAA"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={props.strokeWidth || 1.394}
|
||||
strokeWidth={1.394}
|
||||
d="m1.573 1.543 12.544 12.544M1.573 14.087 14.117 1.543"
|
||||
/>
|
||||
</Svg>
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
import * as React from "react"
|
||||
import Svg, { SvgProps, Path } from "react-native-svg"
|
||||
const DrawerIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={27}
|
||||
height={18}
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke="#83807F"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2.7}
|
||||
d="M2 1.995h22.667M2 9.14h14.167M2 16.285h7.083"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
export default DrawerIcon
|
||||
@ -1,20 +0,0 @@
|
||||
import * as React from "react";
|
||||
import Svg, { SvgProps, Path } from "react-native-svg";
|
||||
const DropdownIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={props.width || 15}
|
||||
height={props.height || 11}
|
||||
fill="none"
|
||||
viewBox="0 0 15 11"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke={props.color || "#FD1775"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={props.strokeWidth || 1.393}
|
||||
d="M4.713 1.318h9.056m-9.056 4.18h9.056m-9.056 4.18h9.056M1.23 1.667h.697V.97H1.23v.696Zm0 4.18h.697V5.15H1.23v.696Zm0 4.18h.697V9.33H1.23v.696Z"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
export default DropdownIcon;
|
||||
@ -1,17 +0,0 @@
|
||||
import * as React from "react"
|
||||
import Svg, { SvgProps, Path } from "react-native-svg"
|
||||
const EmailIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 16}
|
||||
viewBox="0 0 20 16"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
fill={props.color || "#fff"}
|
||||
d="M19.948 2.385a2.767 2.767 0 0 0-.76-1.422A2.768 2.768 0 0 0 17.225.15H2.774A2.772 2.772 0 0 0 0 2.925v10.15c0 .389.083.763.23 1.101a2.719 2.719 0 0 0 .774 1.035c.48.398 1.1.638 1.77.638h14.452a2.755 2.755 0 0 0 1.961-.813c.245-.245.447-.537.586-.86v-.002c.147-.338.227-.71.227-1.1V2.925c0-.182-.018-.363-.052-.539ZM1.817 1.967a1.34 1.34 0 0 1 .957-.397h14.452a1.335 1.335 0 0 1 1.079.54l-7.575 6.6a1.11 1.11 0 0 1-1.46 0L1.698 2.107c.034-.048.075-.095.119-.139Zm-.398 11.107V3.575l5.482 4.782-5.479 4.777c-.003-.018-.003-.039-.003-.06Zm15.807 1.355H2.774c-.245 0-.475-.064-.67-.178l5.78-5.037.54.47a2.406 2.406 0 0 0 3.155 0l.54-.47 5.778 5.037a1.338 1.338 0 0 1-.671.178Zm1.355-1.354c0 .02 0 .04-.003.059L13.1 8.36l5.48-4.782v9.497Z"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
export default EmailIcon
|
||||
@ -1,20 +0,0 @@
|
||||
import * as React from "react"
|
||||
import Svg, { SvgProps, Path } from "react-native-svg"
|
||||
const FeedbackNavIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={25}
|
||||
height={25}
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke="#ea156d"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={1.5}
|
||||
d="M10.5 21H4a7.001 7.001 0 0 1 6-6.93m6.498 2.142c-.7-.78-1.867-.989-2.744-.275-.877.713-1 1.906-.311 2.75.388.476 1.312 1.311 2.042 1.948.347.302.52.453.73.515.178.053.387.053.566 0 .21-.061.382-.213.729-.515.73-.637 1.654-1.472 2.043-1.948.688-.844.58-2.044-.312-2.75-.892-.706-2.044-.504-2.743.275ZM15 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
export default FeedbackNavIcon
|
||||
@ -1,17 +0,0 @@
|
||||
import * as React from "react";
|
||||
import Svg, { SvgProps, Path } from "react-native-svg";
|
||||
const MenuDotsIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={props.width || 4}
|
||||
height={props.height || 15}
|
||||
viewBox="0 0 4 15"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
fill={props.color || "#7C7C7C"}
|
||||
d="M.88 7.563a1.56 1.56 0 1 0 3.12 0 1.56 1.56 0 0 0-3.12 0Zm0-5.2A1.56 1.56 0 1 0 4 2.426a1.56 1.56 0 0 0-3.12-.063Zm0 10.4A1.56 1.56 0 1 0 4 12.701a1.56 1.56 0 0 0-3.12.062Z"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
export default MenuDotsIcon;
|
||||
@ -7,8 +7,8 @@ interface MenuIconProps extends SvgProps {
|
||||
|
||||
const MenuIcon: React.FC<MenuIconProps> = (props) => (
|
||||
<Svg
|
||||
width={props.width || 24}
|
||||
height={props.height || 16}
|
||||
width={24}
|
||||
height={16}
|
||||
viewBox="0 0 24 16"
|
||||
fill="none"
|
||||
{...props}
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import * as React from "react";
|
||||
import Svg, { Path, SvgProps } from "react-native-svg";
|
||||
import * as React from "react"
|
||||
import Svg, { Path, SvgProps } from "react-native-svg"
|
||||
const NavBrainDumpIcon: React.FC<SvgProps> = (props) => (
|
||||
<Svg
|
||||
width={props.width || 22}
|
||||
height={props.height || 28}
|
||||
viewBox="0 0 22 28"
|
||||
width={22}
|
||||
height={28}
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke={props.color || "#F90"}
|
||||
stroke="#F90"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeMiterlimit={10}
|
||||
@ -17,7 +16,7 @@ const NavBrainDumpIcon: React.FC<SvgProps> = (props) => (
|
||||
d="M21.1.859H3.994C2.284.859.976 2.167.976 3.877c0 1.71 1.308 3.019 3.018 3.019H21.1V27.02"
|
||||
/>
|
||||
<Path
|
||||
stroke={props.color || "#F90"}
|
||||
stroke="#F90"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeMiterlimit={10}
|
||||
@ -25,7 +24,7 @@ const NavBrainDumpIcon: React.FC<SvgProps> = (props) => (
|
||||
d="M21.1 27.021H3.994c-1.71 0-3.018-1.308-3.018-3.018V3.878M21.097 3.878H3.991"
|
||||
/>
|
||||
<Path
|
||||
stroke={props.color || "#F90"}
|
||||
stroke="#F90"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeMiterlimit={10}
|
||||
@ -33,5 +32,5 @@ const NavBrainDumpIcon: React.FC<SvgProps> = (props) => (
|
||||
d="M6.007 6.897v12.075l3.019-1.006 3.018 1.006V6.897"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
export default NavBrainDumpIcon;
|
||||
)
|
||||
export default NavBrainDumpIcon
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import * as React from "react";
|
||||
import Svg, { Path, SvgProps } from "react-native-svg";
|
||||
import * as React from "react"
|
||||
import Svg, { Path, SvgProps } from "react-native-svg"
|
||||
const NavCalendarIcon: React.FC<SvgProps> = (props) => (
|
||||
<Svg
|
||||
width={props.width || 28}
|
||||
height={props.height || 28}
|
||||
width={28}
|
||||
height={28}
|
||||
viewBox="0 0 28 28"
|
||||
fill="none"
|
||||
{...props}
|
||||
@ -16,5 +16,5 @@ const NavCalendarIcon: React.FC<SvgProps> = (props) => (
|
||||
d="M1.825 10.075h25.043m-5.565 5.567L7.39 15.64m4.638 5.566H7.39m0-19.478V4.51m13.913-2.782V4.51M6.277 26.77h16.139c1.558 0 2.337 0 2.933-.303.523-.267.949-.692 1.216-1.216.303-.595.303-1.375.303-2.933V8.962c0-1.558 0-2.337-.303-2.933a2.782 2.782 0 0 0-1.216-1.216c-.596-.303-1.375-.303-2.933-.303H6.277c-1.558 0-2.337 0-2.933.303-.523.267-.949.693-1.216 1.216-.303.596-.303 1.375-.303 2.933v13.356c0 1.558 0 2.338.303 2.933.267.523.693.95 1.216 1.216.596.303 1.375.303 2.933.303Z"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
export default NavCalendarIcon;
|
||||
)
|
||||
export default NavCalendarIcon
|
||||
|
||||
@ -2,18 +2,17 @@ import * as React from "react";
|
||||
import Svg, { Path, SvgProps } from "react-native-svg";
|
||||
const NavGroceryIcon: React.FC<SvgProps> = (props) => (
|
||||
<Svg
|
||||
width={props.width || 29}
|
||||
height={props.width || 32}
|
||||
viewBox="0 0 29 32"
|
||||
width={29}
|
||||
height={32}
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
fill={props.color || "#50BE0C"}
|
||||
fill="#50BE0C"
|
||||
d="M27.8 12c-.888-2.27-2.662-4.14-4.983-4.956-2.518-.883-5.143-.382-7.636.307-.047-1.362.068-2.728.262-4.076.11-.761.634-2.335-.668-2.389-1.081-.045-1.084 1.402-1.19 2.14-.203 1.416-.323 2.85-.284 4.281-.599-.1-1.19-.322-1.787-.446a13.485 13.485 0 0 0-2.704-.3c-1.752 0-3.48.465-4.922 1.479C1.09 10.01 0 13.446.046 16.747c.052 3.575 1.263 6.99 3.3 9.905.899 1.288 1.932 2.522 3.21 3.451 1.241.903 2.628 1.325 4.133 1.54.64.093 1.29.096 1.927-.009.557-.09 1.078-.325 1.63-.419.417-.07 1.005.258 1.408.348a6.297 6.297 0 0 0 2.096.107c2.563-.292 4.594-1.449 6.28-3.387 3.71-4.264 5.921-10.791 3.77-16.284Zm-1.69 8.743c-.474 1.663-1.225 3.182-2.195 4.608-.86 1.263-1.855 2.514-3.131 3.377-1.172.79-2.76 1.223-4.173 1.093-.719-.065-1.373-.41-2.087-.478-.8-.076-1.538.352-2.318.459-3.064.416-5.485-1.665-7.146-3.972-2.04-2.831-3.249-6.214-3.134-9.732.106-3.223 1.643-6.55 4.998-7.432 1.678-.44 3.446-.188 5.099.238.715.183 1.454.48 2.196.52.572.066 1.2-.196 1.74-.344 3.233-.89 6.873-1.105 9.124 1.855 2.08 2.732 1.925 6.666 1.027 9.808Z"
|
||||
/>
|
||||
<Path
|
||||
fill={props.color || "#50BE0C"}
|
||||
fill="#50BE0C"
|
||||
d="M12 17.966c-.778.285-1.977.71-2.432 1.454.11-.183.221-.363-.002.002-.222.365-.113.186-.001.003-.668 1.099.272 2.53 1.547 2.347 1.258-.18 1.378-1.419 1.364-2.443a8.822 8.822 0 0 0-.095-1.282c-.043-.264-.157-.164-.382-.08ZM18.096 18.917c-.435-.304-.919-.542-1.405-.752-.118-.05-.698-.375-.832-.297.018-.01.036-.021 0 0-.036.023-.02.012-.001.001-.11.07-.096.609-.104.716a9.003 9.003 0 0 0-.01 1.534c.1 1.117 1.049 2.082 2.228 1.517 1.165-.558 1.095-2.04.124-2.719ZM12.223 3.815C12.343.28 8.347-.271 6.922.432c.371 4.075 3.48 4.164 5.301 3.383Z"
|
||||
/>
|
||||
</Svg>
|
||||
|
||||
@ -3,7 +3,7 @@ import Svg, { Path, SvgProps } from "react-native-svg"
|
||||
const NavToDosIcon: React.FC<SvgProps> = (props) => (
|
||||
<Svg
|
||||
width={props.width || 30}
|
||||
height={props.height || 30}
|
||||
height={props.width || 30}
|
||||
viewBox="0 0 30 30"
|
||||
fill="none"
|
||||
{...props}
|
||||
|
||||
@ -3,8 +3,8 @@ import Svg, { Path, LinearGradient, Stop, SvgProps } from "react-native-svg";
|
||||
|
||||
const OutlookIcon: React.FC<SvgProps> = (props) => (
|
||||
<Svg
|
||||
width={props.width || 34}
|
||||
height={props.height || 34}
|
||||
width={34}
|
||||
height={34}
|
||||
viewBox="0 0 48 48"
|
||||
{...props}
|
||||
>
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
import * as React from "react";
|
||||
import Svg, { SvgProps, Path } from "react-native-svg";
|
||||
const PlusIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={props.width || 14}
|
||||
height={props.height || 15}
|
||||
viewBox="0 0 14 15"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke="#fff"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M1 7.632h12m-6-6v12"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
export default PlusIcon;
|
||||
@ -1,20 +0,0 @@
|
||||
import * as React from "react"
|
||||
import Svg, { SvgProps, Path } from "react-native-svg"
|
||||
const QRIcon = (props: SvgProps) => (
|
||||
<Svg
|
||||
width={props.width || 19}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 19 20"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<Path
|
||||
stroke={props.color || "#fff"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={1.764}
|
||||
d="M5.086 10.441h4.41v4.41m-7.93-4.41h-.008m4.418 4.41h-.008m3.536 3.528h-.008m7.946-7.938h-.008m-15.876 4.41H2.88m9.702-4.41h1.764M1.557 18.38h4.41M9.497 1.621v5.292m4.939 11.466h1.587c.494 0 .741 0 .93-.096.166-.085.3-.22.385-.386.097-.188.097-.435.097-.93V15.38c0-.494 0-.74-.097-.93a.882.882 0 0 0-.385-.385c-.189-.096-.436-.096-.93-.096h-1.587c-.494 0-.741 0-.93.096a.881.881 0 0 0-.385.386c-.096.188-.096.435-.096.93v1.587c0 .494 0 .74.096.93.084.166.22.3.385.385.189.096.436.096.93.096Zm0-11.466h1.587c.494 0 .741 0 .93-.096.166-.085.3-.22.385-.385.097-.19.097-.436.097-.93V3.914c0-.494 0-.74-.097-.93a.882.882 0 0 0-.385-.385c-.189-.096-.436-.096-.93-.096h-1.587c-.494 0-.741 0-.93.096a.881.881 0 0 0-.385.386c-.096.188-.096.435-.096.93v1.587c0 .494 0 .74.096.93.084.165.22.3.385.385.189.096.436.096.93.096Zm-11.466 0h1.587c.494 0 .741 0 .93-.096.166-.085.3-.22.385-.385.097-.19.097-.436.097-.93V3.914c0-.494 0-.74-.097-.93a.882.882 0 0 0-.385-.385c-.189-.096-.436-.096-.93-.096H2.97c-.494 0-.741 0-.93.096a.882.882 0 0 0-.385.386c-.096.188-.096.435-.096.93v1.587c0 .494 0 .74.096.93.084.165.22.3.385.385.189.096.436.096.93.096Z"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
export default QRIcon
|
||||