Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jksaunders committed May 24, 2020
1 parent 1b629e2 commit 83dbe27
Show file tree
Hide file tree
Showing 14 changed files with 217 additions and 22 deletions.
16 changes: 16 additions & 0 deletions app/components/error-section/error-section.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from "react"
import { storiesOf } from "@storybook/react-native"
import { StoryScreen, Story, UseCase } from "../../../storybook/views"
import { ErrorSection } from "./error-section"

declare var module

storiesOf("ErrorSection", module)
.addDecorator(fn => <StoryScreen>{fn()}</StoryScreen>)
.add("Style Presets", () => (
<Story>
<UseCase text="Primary" usage="The primary.">
<ErrorSection text="ErrorSection" />
</UseCase>
</Story>
))
7 changes: 7 additions & 0 deletions app/components/error-section/error-section.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ViewStyle } from "react-native"

export const errorSectionStyles = {
WRAPPER: {
justifyContent: 'center'
} as ViewStyle
}
34 changes: 34 additions & 0 deletions app/components/error-section/error-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { FunctionComponent as Component, useEffect } from "react"
import { View } from "react-native"
import { Text } from "../"
// import { observer } from "mobx-react-lite"
import { useStores } from "../../models"
import { errorSectionStyles as styles } from "./error-section.styles"
import { observer } from "mobx-react-lite"

export interface ErrorSectionProps {}

/**
* This is a React functional component, ready to
*
* Component description here for TypeScript tips.
*/
export const ErrorSection: Component<ErrorSectionProps> = observer(props => {
const { dialogStore } = useStores()

useEffect(() => {
if (dialogStore.dialog) {
setTimeout(() => {
dialogStore.setDialog(undefined)
}, 2000)
}
}, [dialogStore.dialog])

return (
<View style={styles.WRAPPER}>
{dialogStore.dialog && (
<Text>{dialogStore.dialog}</Text>
)}
</View>
)
})
1 change: 1 addition & 0 deletions app/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from "./switch/switch"
export * from "./text/text"
export * from "./text-field/text-field"
export * from "./wallpaper/wallpaper"
export * from "./error-section/error-section"
7 changes: 7 additions & 0 deletions app/models/dialog-store/dialog-store.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { DialogStoreModel, DialogStore } from "./dialog-store"

test("can be created", () => {
const instance: DialogStore = DialogStoreModel.create({})

expect(instance).toBeTruthy()
})
36 changes: 36 additions & 0 deletions app/models/dialog-store/dialog-store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Instance, SnapshotOut, types, flow } from "mobx-state-tree"
import { withEnvironment } from "../extensions/with-environment"

/**
* Model description here for TypeScript hints.
*/
export const DialogStoreModel = types
.model("DialogStore")
.props({
dialog: types.maybe(types.string),
})
.extend(withEnvironment)
.views(self => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars
.actions(self => ({
setDialog: flow(function * (dialog) {
self.dialog = dialog
}),
}))
.actions(self => ({
initializeStore: flow(function * () {
self.environment.setDialog = dialog => self.setDialog(dialog)
}),
}))

/**
* Un-comment the following to omit model attributes from your snapshots (and from async storage).
* Useful for sensitive data like passwords, or transitive state like whether a modal is open.
* Note that you'll need to import `omit` from ramda, which is already included in the project!
* .postProcessSnapshot(omit(["password", "socialSecurityNumber", "creditCardNumber"]))
*/

type DialogStoreType = Instance<typeof DialogStoreModel>
export interface DialogStore extends DialogStoreType {}
type DialogStoreSnapshotType = SnapshotOut<typeof DialogStoreModel>
export interface DialogStoreSnapshot extends DialogStoreSnapshotType {}
38 changes: 34 additions & 4 deletions app/models/environment.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
import { Api } from "../services/api"
import axios from 'axios'

let ReactotronDev
if (__DEV__) {
const { Reactotron } = require("../services/reactotron")
ReactotronDev = Reactotron
}

type AxiosClientProps = {
onError: (error: string) => void,
root: string,
}

class AxiosClient {
onError: (error: string) => void
root: string

constructor(props: AxiosClientProps) {
console.log('constructor')
this.onError = props.onError
this.root = props.root
}

get(endpoint: string) {
axios.get(`${this.root}${endpoint}`)
.then(result => console.log('Result', result))
.catch((error) => this.onError(error.message))
}
}

/**
* The environment is a place where services and shared dependencies between
* models live. They are made available to every model via dependency injection.
Expand All @@ -17,15 +39,21 @@ export class Environment {
// dev-only services
this.reactotron = new ReactotronDev()
}
this.api = new Api()
this.api = new AxiosClient({
root: 'https://jsonplaceholder.typicode.com',
onError: (error) => {
if (this.setDialog) {
this.setDialog(error)
}
}
})
}

async setup() {
// allow each service to setup
if (__DEV__) {
await this.reactotron.setup()
}
await this.api.setup()
}

/**
Expand All @@ -36,5 +64,7 @@ export class Environment {
/**
* Our api.
*/
api: Api
api: AxiosClient

setDialog: (dialog: any) => void
}
1 change: 1 addition & 0 deletions app/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from "./extensions/with-status"
export * from "./root-store/root-store"
export * from "./root-store/root-store-context"
export * from "./root-store/setup-root-store"
export * from "./dialog-store/dialog-store"
2 changes: 2 additions & 0 deletions app/models/root-store/root-store.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { DialogStoreModel } from "../dialog-store/dialog-store"
import { Instance, SnapshotOut, types } from "mobx-state-tree"

/**
* A RootStore model.
*/
// prettier-ignore
export const RootStoreModel = types.model("RootStore").props({
dialogStore: types.optional(DialogStoreModel, {}),

})

Expand Down
6 changes: 6 additions & 0 deletions app/models/root-store/setup-root-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ export async function setupRootStore() {
__DEV__ && console.tron.error(e.message, null)
}

Object.keys(rootStore).forEach(key => {
if (rootStore[key] && typeof rootStore[key].initializeStore === 'function') {
rootStore[key].initializeStore()
}
})

// reactotron logging
if (__DEV__) {
env.reactotron.setRootStore(rootStore, data)
Expand Down
35 changes: 18 additions & 17 deletions app/screens/welcome-screen/welcome-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import React, { FunctionComponent as Component } from "react"
import { View, Image, ViewStyle, TextStyle, ImageStyle, SafeAreaView } from "react-native"
import { useNavigation } from "@react-navigation/native"
import { observer } from "mobx-react-lite"
import { Button, Header, Screen, Text, Wallpaper } from "../../components"
import { Button, Header, Screen, Text, Wallpaper, ErrorSection } from "../../components"
import { color, spacing } from "../../theme"
import { useStores } from "../../models"
const bowserLogo = require("./bowser.png")

const FULL: ViewStyle = { flex: 1 }
Expand Down Expand Up @@ -79,34 +80,34 @@ export const WelcomeScreen: Component = observer(function WelcomeScreen() {
const navigation = useNavigation()
const nextScreen = () => navigation.navigate("demo")

const { dialogStore } = useStores()

return (
<View style={FULL}>
<Wallpaper />
<Screen style={CONTAINER} preset="scroll" backgroundColor={color.transparent}>
<Header headerTx="welcomeScreen.poweredBy" style={HEADER} titleStyle={HEADER_TITLE} />
<Text style={TITLE_WRAPPER}>
<Text style={TITLE} text="Your new app, " />
<Text style={ALMOST} text="almost" />
<Text style={TITLE} text="!" />
</Text>
<Text style={TITLE} preset="header" tx="welcomeScreen.readyForLaunch" />
<Image source={bowserLogo} style={BOWSER} />
<Text style={CONTENT}>
This probably isn't what your app is going to look like. Unless your designer handed you
this screen and, in that case, congrats! You're ready to ship.
</Text>
<Text style={CONTENT}>
For everyone else, this is where you'll see a live preview of your fully functioning app
using Ignite.
Try a request!
</Text>
<ErrorSection />
</Screen>
<SafeAreaView style={FOOTER}>
<View style={FOOTER_CONTENT}>
<Button
style={CONTINUE}
textStyle={CONTINUE_TEXT}
tx="welcomeScreen.continue"
onPress={nextScreen}
text="Valid API request"
onPress={() => {
dialogStore.environment.api.get('/users')
}}
/>
<Button
style={CONTINUE}
textStyle={CONTINUE_TEXT}
text="Invalid API request"
onPress={() => {
dialogStore.environment.api.get('/invalid')
}}
/>
</View>
</SafeAreaView>
Expand Down
54 changes: 53 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@react-native-community/masked-view": "0.1.5",
"@react-navigation/native": "^5.1.5",
"apisauce": "1.1.1",
"axios": "^0.19.2",
"i18n-js": "^3.0.11",
"lodash.throttle": "4.1.1",
"mobx": "^4.15.4",
Expand Down
1 change: 1 addition & 0 deletions storybook/storybook-registry.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require("../app/components/error-section/error-section.story")
require("../app/components/text/text.story")
require("../app/components/button/button.story")
require("../app/components/form-row/form-row.story")
Expand Down

0 comments on commit 83dbe27

Please sign in to comment.