├── .expo-shared └── assets.json ├── .gitignore ├── App.tsx ├── app.json ├── assets ├── favicon.png ├── fonts │ ├── Gotham-Black.otf │ ├── Gotham-Bold.otf │ └── GothamMedium.ttf ├── icon.png ├── images │ └── boygirl.png └── splash.png ├── babel.config.js ├── package.json ├── react-native-redash.zip ├── src ├── Utils │ ├── AnswersBtn.tsx │ ├── Button.tsx │ └── index.ts └── components │ ├── Helper.ts │ ├── LoadAssets.tsx │ ├── Navigation.ts │ ├── OnBoarding │ ├── Welcome.tsx │ └── index.tsx │ ├── Question │ ├── Alert.tsx │ ├── Ansers.tsx │ ├── Question.tsx │ ├── QuestionSlide.tsx │ ├── QuizContainer.tsx │ ├── data.ts │ └── index.tsx │ ├── SvgIcons │ ├── Bad.tsx │ └── Good.tsx │ ├── index.ts │ └── theme.ts ├── tsconfig.json ├── yarn-error.log └── yarn.lock /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | 12 | # macOS 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import "react-native-gesture-handler"; 3 | import { StatusBar } from "expo-status-bar"; 4 | import { ThemeProvider } from "@shopify/restyle"; 5 | import { createStackNavigator } from "@react-navigation/stack"; 6 | import { SafeAreaProvider } from "react-native-safe-area-context"; 7 | 8 | import { LoadAssets, theme } from "./src/components"; 9 | import { OnBoardingNavigator } from "./src/components/OnBoarding"; 10 | import { QuestionNavigator } from "./src/components/Question"; 11 | 12 | import { welcomeAssets } from "./src/components/OnBoarding/Welcome"; 13 | 14 | const assets: number[] = [welcomeAssets]; 15 | 16 | const fonts = { 17 | "Gotham-Bold": require("./assets/fonts/Gotham-Bold.otf"), 18 | "Gotham-Medium": require("./assets/fonts/GothamMedium.ttf"), 19 | "Gotham-Black": require("./assets/fonts/Gotham-Black.otf"), 20 | }; 21 | 22 | export type AppStackRoutes = { 23 | OnBoarding: undefined; 24 | Question: undefined; 25 | }; 26 | 27 | const AppStack = createStackNavigator(); 28 | 29 | export default function App() { 30 | return ( 31 | 32 | 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "rnn-quiz-project", 4 | "slug": "rnn-quiz-project", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "splash": { 9 | "image": "./assets/splash.png", 10 | "resizeMode": "contain", 11 | "backgroundColor": "#ffffff" 12 | }, 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "supportsTablet": true 21 | }, 22 | "web": { 23 | "favicon": "./assets/favicon.png" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thellecodes/fullstack-quiz-app-react-native/7eb5f7d5836644d55f07d5bb0d2f489ae33da601/assets/favicon.png -------------------------------------------------------------------------------- /assets/fonts/Gotham-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thellecodes/fullstack-quiz-app-react-native/7eb5f7d5836644d55f07d5bb0d2f489ae33da601/assets/fonts/Gotham-Black.otf -------------------------------------------------------------------------------- /assets/fonts/Gotham-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thellecodes/fullstack-quiz-app-react-native/7eb5f7d5836644d55f07d5bb0d2f489ae33da601/assets/fonts/Gotham-Bold.otf -------------------------------------------------------------------------------- /assets/fonts/GothamMedium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thellecodes/fullstack-quiz-app-react-native/7eb5f7d5836644d55f07d5bb0d2f489ae33da601/assets/fonts/GothamMedium.ttf -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thellecodes/fullstack-quiz-app-react-native/7eb5f7d5836644d55f07d5bb0d2f489ae33da601/assets/icon.png -------------------------------------------------------------------------------- /assets/images/boygirl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thellecodes/fullstack-quiz-app-react-native/7eb5f7d5836644d55f07d5bb0d2f489ae33da601/assets/images/boygirl.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thellecodes/fullstack-quiz-app-react-native/7eb5f7d5836644d55f07d5bb0d2f489ae33da601/assets/splash.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "@expo/vector-icons": "^10.2.1", 12 | "@react-native-community/masked-view": "^0.1.10", 13 | "@react-navigation/native": "^5.7.3", 14 | "@react-navigation/stack": "^5.9.0", 15 | "@shopify/restyle": "^1.2.0", 16 | "expo": "~38.0.8", 17 | "expo-constants": "^9.1.1", 18 | "expo-linear-gradient": "~8.2.1", 19 | "expo-status-bar": "^1.0.2", 20 | "react": "~16.11.0", 21 | "react-dom": "~16.11.0", 22 | "react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz", 23 | "react-native-gesture-handler": "^1.8.0", 24 | "react-native-reanimated": "1.9.0", 25 | "react-native-redash": "14.2.1", 26 | "react-native-safe-area-context": "^3.1.8", 27 | "react-native-screens": "^2.11.0", 28 | "react-native-size-matters": "^0.3.1", 29 | "react-native-svg": "^12.1.0", 30 | "react-native-web": "~0.11.7", 31 | "styled-components": "^5.2.0" 32 | }, 33 | "devDependencies": { 34 | "@babel/core": "^7.8.6", 35 | "@types/react": "~16.9.41", 36 | "@types/react-native": "~0.62.13", 37 | "typescript": "~3.9.5" 38 | }, 39 | "private": true 40 | } 41 | -------------------------------------------------------------------------------- /react-native-redash.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thellecodes/fullstack-quiz-app-react-native/7eb5f7d5836644d55f07d5bb0d2f489ae33da601/react-native-redash.zip -------------------------------------------------------------------------------- /src/Utils/AnswersBtn.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Dimensions, StyleSheet } from "react-native"; 3 | import { RectButton } from "react-native-gesture-handler"; 4 | import { useTheme } from "@shopify/restyle"; 5 | import { Theme, Text, Box } from "../components/theme"; 6 | const { width } = Dimensions.get("window"); 7 | 8 | interface AnswerButtonProps { 9 | variant?: "default" | "primary"; 10 | answer?: string; 11 | clicked?: number | boolean; 12 | correct?: boolean; 13 | onPress?: () => void; 14 | } 15 | 16 | const styles = StyleSheet.create({ 17 | container: { 18 | borderRadius: 10, 19 | height: 50, 20 | width: 245, 21 | justifyContent: "center", 22 | alignItems: "center", 23 | marginBottom: 15, 24 | borderColor: "#000", 25 | borderWidth: 1, 26 | }, 27 | }); 28 | 29 | const AnswersBtn = ({ 30 | variant, 31 | answer, 32 | onPress, 33 | clicked, 34 | }: AnswerButtonProps) => { 35 | const theme = useTheme(); 36 | const backgroundColor = 37 | variant === "primary" ? theme.colors.button : theme.colors.grey; 38 | const color = variant === "primary" ? theme.colors.white : theme.colors.green; 39 | 40 | return ( 41 | 49 | 50 | {answer} 51 | 52 | 53 | ); 54 | }; 55 | 56 | AnswersBtn.defaultProps = { variant: "default" }; 57 | 58 | export default AnswersBtn; 59 | -------------------------------------------------------------------------------- /src/Utils/Button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { StyleSheet } from "react-native"; 3 | import { RectButton } from "react-native-gesture-handler"; 4 | import { useTheme } from "@shopify/restyle"; 5 | import { Theme, Text } from "../components/theme"; 6 | 7 | interface ButtonProps { 8 | variant?: "default" | "primary"; 9 | label?: string; 10 | onPress?: () => void; 11 | textTransform?: any; 12 | } 13 | 14 | const styles = StyleSheet.create({ 15 | container: { 16 | borderRadius: 50, 17 | height: 50, 18 | width: 245, 19 | justifyContent: "center", 20 | alignItems: "center", 21 | marginBottom: 15, 22 | }, 23 | }); 24 | 25 | const Button = ({ variant, label, onPress, textTransform }: ButtonProps) => { 26 | const theme = useTheme(); 27 | const backgroundColor = 28 | variant === "primary" ? theme.colors.button : theme.colors.grey; 29 | const color = variant === "primary" ? theme.colors.white : theme.colors.green; 30 | 31 | return ( 32 | 36 | 43 | {label} 44 | 45 | 46 | ); 47 | }; 48 | 49 | Button.defaultProps = { variant: "default" }; 50 | 51 | export default Button; 52 | -------------------------------------------------------------------------------- /src/Utils/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Button } from "./Button"; 2 | export { default as AnswerBtn } from "./AnswersBtn"; 3 | -------------------------------------------------------------------------------- /src/components/Helper.ts: -------------------------------------------------------------------------------- 1 | export const _ = null 2 | 3 | export enum QuestionsDifficulty { 4 | 5 | } 6 | 7 | export type QuizProps = { 8 | 9 | }; 10 | 11 | export type QuizPropsState = QuizProps & { answers: string[] }; 12 | 13 | export const grabQuizQuestions = async ( 14 | total_questions: number, 15 | difficulty: QuestionsDifficulty 16 | ): Promise => { 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/LoadAssets.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactElement, useCallback, useEffect, useState } from "react"; 2 | import { AsyncStorage } from "react-native"; 3 | import { AppLoading } from "expo"; 4 | import { Asset } from "expo-asset"; 5 | import * as Font from "expo-font"; 6 | import { InitialState, NavigationContainer } from "@react-navigation/native"; 7 | import Constants from "expo-constants"; 8 | import { StatusBar } from "expo-status-bar"; 9 | 10 | const NAVIGATION_STATE_KEY = `NAVIGATION_STATE_KEY-${Constants.manifest.sdkVersion}`; 11 | 12 | export type FontSource = Parameters[0]; 13 | const usePromiseAll = (promises: Promise[], cb: () => void) => 14 | useEffect(() => { 15 | (async () => { 16 | await Promise.all(promises); 17 | cb(); 18 | })(); 19 | }); 20 | 21 | const useLoadAssets = (assets: number[], fonts: FontSource): boolean => { 22 | const [ready, setReady] = useState(false); 23 | usePromiseAll( 24 | [Font.loadAsync(fonts), ...assets.map((asset) => Asset.loadAsync(asset))], 25 | () => setReady(true) 26 | ); 27 | return ready; 28 | }; 29 | 30 | interface LoadAssetsProps { 31 | fonts?: FontSource; 32 | assets?: number[]; 33 | children: ReactElement | ReactElement[]; 34 | } 35 | 36 | const LoadAssets = ({ assets, fonts, children }: LoadAssetsProps) => { 37 | const [isNavigationReady, setIsNavigationReady] = useState(!__DEV__); 38 | const [initialState, setInitialState] = useState(); 39 | const ready = useLoadAssets(assets || [], fonts || {}); 40 | useEffect(() => { 41 | const restoreState = async () => { 42 | try { 43 | const savedStateString = await AsyncStorage.getItem( 44 | NAVIGATION_STATE_KEY 45 | ); 46 | const state = savedStateString 47 | ? JSON.parse(savedStateString) 48 | : undefined; 49 | setInitialState(state); 50 | } finally { 51 | setIsNavigationReady(true); 52 | } 53 | }; 54 | 55 | if (!isNavigationReady) { 56 | restoreState(); 57 | } 58 | }, [isNavigationReady]); 59 | const onStateChange = useCallback( 60 | (state) => 61 | AsyncStorage.setItem(NAVIGATION_STATE_KEY, JSON.stringify(state)), 62 | [] 63 | ); 64 | if (!ready || !isNavigationReady) { 65 | return ; 66 | } 67 | return ( 68 | 69 | 70 | {children} 71 | 72 | ); 73 | }; 74 | 75 | export default LoadAssets; 76 | -------------------------------------------------------------------------------- /src/components/Navigation.ts: -------------------------------------------------------------------------------- 1 | import { ParamListBase, RouteProp } from "@react-navigation/native"; 2 | import { StackNavigationProp } from "@react-navigation/stack"; 3 | 4 | export interface StackNavigationProps< 5 | ParamList extends ParamListBase, 6 | RouteName extends keyof ParamList = string 7 | > { 8 | navigation: StackNavigationProp; 9 | route: RouteProp; 10 | } 11 | 12 | export type OnBoardingRoutes = { 13 | Welcome: undefined; 14 | }; 15 | 16 | export type QuestionRoutes = { 17 | MainQuestion: undefined; 18 | Quiz: undefined; 19 | }; 20 | -------------------------------------------------------------------------------- /src/components/OnBoarding/Welcome.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Dimensions, SafeAreaView, Image } from "react-native"; 3 | import Constants from "expo-constants"; 4 | 5 | /* Navigation Props*/ 6 | import { CompositeNavigationProp } from "@react-navigation/native"; 7 | import { StackNavigationProp } from "@react-navigation/stack"; 8 | import { OnBoardingRoutes } from "../Navigation"; 9 | import { AppStackRoutes } from "../../../App"; 10 | 11 | const { height, width } = Dimensions.get("window"); 12 | import { moderateScale, verticalScale } from "react-native-size-matters"; 13 | import Animated from "react-native-reanimated"; 14 | import { StatusBar } from "expo-status-bar"; 15 | 16 | export const welcomeAssets = require("../../../assets/images/boygirl.png"); 17 | 18 | /* Utils */ 19 | import theme, { Box, Text } from "../theme"; 20 | import { Button } from "../../Utils"; 21 | import QuizContainer from "../Question/QuizContainer"; 22 | interface WelcomeProps { 23 | navigation: CompositeNavigationProp< 24 | StackNavigationProp, 25 | StackNavigationProp 26 | >; 27 | } 28 | 29 | const Welcome = ({ navigation }: WelcomeProps) => { 30 | return ( 31 | 32 | 33 | 34 | 42 | 47 | 48 | 49 | 50 | 61 | 62 | 74 | 75 | Quiz App 76 | 77 | 78 | 84 | Improve your app building skills and upgrade your personal growth 85 | 86 | 87 |