├── .eslintrc.js
├── .gitignore
├── .watchmanconfig
├── App.js
├── README.md
├── app.json
├── assets
├── fonts
│ └── NotoSans-Regular.ttf
├── icon.png
└── splash.png
├── babel.config.js
├── components
└── Button.js
└── package.json
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "extends": "airbnb"
3 | };
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/**/*
2 | .expo/*
3 | npm-debug.*
4 | *.jks
5 | *.p12
6 | *.key
7 | *.mobileprovision
8 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
3 | import Btn from "./components/Button";
4 | import { LinearGradient } from "expo";
5 | import { Feather } from "@expo/vector-icons";
6 |
7 | export default class App extends React.Component {
8 | state = {
9 | value: null,
10 | displayValue: "0",
11 | colorView: true,
12 | waitingForOperand: false,
13 | operator: null,
14 | bts: " "
15 | };
16 |
17 | inputDigit = digit => {
18 | const { displayValue, waitingForOperand } = this.state;
19 |
20 | if (waitingForOperand) {
21 | this.setState({
22 | displayValue: String(digit),
23 | waitingForOperand: false
24 | });
25 | } else {
26 | this.setState({
27 | displayValue:
28 | displayValue === "0" ? String(digit) : displayValue + digit
29 | });
30 | }
31 | };
32 |
33 | inputDot = () => {
34 | const { displayValue, waitingForOperand } = this.state;
35 |
36 | if (waitingForOperand) {
37 | this.setState({
38 | displayValue: ".",
39 | waitingForOperand: false
40 | });
41 | } else if (displayValue.indexOf(".") === -1) {
42 | this.setState({
43 | displayValue: displayValue + ".",
44 | waitingForOperand: false
45 | });
46 | }
47 | };
48 |
49 | toggleColor = () => {
50 | this.setState({
51 | colorView: !this.state.colorView
52 | });
53 | };
54 |
55 | clearDisplay = () => {
56 | this.setState({
57 | displayValue: "0",
58 | bts: " "
59 | });
60 | };
61 |
62 | toggleSign = () => {
63 | const { displayValue } = this.state;
64 |
65 | this.setState({
66 | displayValue:
67 | displayValue.charAt(0) === "-"
68 | ? displayValue.substr(1)
69 | : "-" + displayValue
70 | });
71 | };
72 |
73 | inputPercent = () => {
74 | const { displayValue } = this.state;
75 | const value = parseFloat(displayValue);
76 | this.setState({
77 | displayValue: String(value / 100)
78 | });
79 | };
80 |
81 | performOperation = nextOperator => {
82 | const { displayValue, operator, value } = this.state;
83 |
84 | const nextValue = parseFloat(displayValue);
85 |
86 | const operations = {
87 | "/": (prevValue, nextValue) => prevValue / nextValue,
88 | x: (prevValue, nextValue) => prevValue * nextValue,
89 | "+": (prevValue, nextValue) => prevValue + nextValue,
90 | "-": (prevValue, nextValue) => prevValue - nextValue,
91 | "=": (prevValue, nextValue) => nextValue
92 | };
93 |
94 | if (value == null) {
95 | this.setState({
96 | value: nextValue
97 | });
98 | } else if (operator) {
99 | const currentValue = value || 0;
100 | const computedValue = operations[operator](currentValue, nextValue);
101 |
102 | this.setState({
103 | value: computedValue,
104 | displayValue: String(computedValue),
105 | bts: operator === "=" ? " " : `${currentValue} ${operator} ${nextValue}`
106 | });
107 | }
108 |
109 | this.setState({
110 | waitingForOperand: true,
111 | operator: nextOperator
112 | });
113 | };
114 |
115 | render() {
116 | const { displayValue } = this.state;
117 | return (
118 |
119 |
128 |
129 | {this.state.colorView ? (
130 |
138 | ) : (
139 |
147 | )}
148 |
153 | {this.state.bts}
154 |
155 | {displayValue}
156 |
157 |
158 |
159 |
167 |
168 |
173 |
178 |
183 | this.performOperation("/")}
187 | />
188 |
189 |
190 |
191 | this.inputDigit(7)}
194 | colorText={this.state.colorView}
195 | />
196 | this.inputDigit(8)}
199 | colorText={this.state.colorView}
200 | />
201 | this.inputDigit(9)}
204 | colorText={this.state.colorView}
205 | />
206 | this.performOperation("x")}
210 | />
211 |
212 |
213 | this.inputDigit(4)}
216 | colorText={this.state.colorView}
217 | />
218 | this.inputDigit(5)}
221 | colorText={this.state.colorView}
222 | />
223 | this.inputDigit(6)}
226 | colorText={this.state.colorView}
227 | />
228 | this.performOperation("-")}
232 | />
233 |
234 |
235 | this.inputDigit(1)}
238 | colorText={this.state.colorView}
239 | />
240 | this.inputDigit(2)}
243 | colorText={this.state.colorView}
244 | />
245 | this.inputDigit(3)}
248 | colorText={this.state.colorView}
249 | />
250 | this.performOperation("+")}
254 | />
255 |
256 |
257 |
258 | this.inputDigit(0)}
262 | zero
263 | />
264 |
265 |
270 |
280 | this.performOperation("=")}
283 | >
284 |
288 | {"="}
289 |
290 |
291 |
292 |
293 |
294 |
295 | );
296 | }
297 | }
298 |
299 | const styles = StyleSheet.create({
300 | container: {
301 | flex: 1
302 | },
303 | number: {
304 | color: "#fff",
305 | textAlign: "right",
306 | padding: 10,
307 | fontSize: 36
308 | // borderBottomWidth: 0.5,
309 | // borderColor: "#19153E"
310 | },
311 | top: {
312 | paddingTop: 120
313 | },
314 | bottom: {
315 | flex: 1
316 | },
317 | row: {
318 | flex: 1,
319 | flexDirection: "row",
320 | borderBottomWidth: 0.2,
321 | borderColor: "#19153E"
322 | },
323 | button: {
324 | flex: 1,
325 | alignItems: "center",
326 | justifyContent: "center"
327 | },
328 | numberBTS: {
329 | color: "#6191FF",
330 | textAlign: "right",
331 | padding: 10,
332 | fontSize: 26
333 | },
334 | numberBTSL: {
335 | color: "#FDFCFC",
336 | textAlign: "right",
337 | padding: 10,
338 | fontSize: 26
339 | }
340 | });
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Modern Twin Calculator w/React Native
2 |
3 |
4 | Modern Calculator with Day/Night Switch help stand out in dark and light area
5 |
6 | Scan the QR code from the above link with your Expo App with Android/Iphone
7 |
8 | ### How to Load the App
9 | ```
10 | git clone https://github.com/oliver-gomes/react-native-calculator-new.git
11 | npm install
12 | npm start
13 | ```
14 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "Calculator App",
4 | "slug": "calculator",
5 | "privacy": "public",
6 | "sdkVersion": "32.0.0",
7 | "platforms": [
8 | "ios",
9 | "android"
10 | ],
11 | "version": "1.0.0",
12 | "orientation": "portrait",
13 | "icon": "./assets/icon.png",
14 | "splash": {
15 | "image": "./assets/splash.png",
16 | "resizeMode": "contain",
17 | "backgroundColor": "#ffffff"
18 | },
19 | "updates": {
20 | "fallbackToCacheTimeout": 0
21 | },
22 | "assetBundlePatterns": [
23 | "**/*"
24 | ],
25 | "ios": {
26 | "supportsTablet": true
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/assets/fonts/NotoSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlanBinu007/react-native-calculator-new/486e5c5585cd43bc9144c13fcee5e53651840512/assets/fonts/NotoSans-Regular.ttf
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlanBinu007/react-native-calculator-new/486e5c5585cd43bc9144c13fcee5e53651840512/assets/icon.png
--------------------------------------------------------------------------------
/assets/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlanBinu007/react-native-calculator-new/486e5c5585cd43bc9144c13fcee5e53651840512/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 |
--------------------------------------------------------------------------------
/components/Button.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
3 |
4 | const Btn = ({ text, colorText, onPress, zero }) => {
5 | return (
6 |
10 | {text}
11 |
12 | );
13 | };
14 | const styles = StyleSheet.create({
15 | container: {
16 | flex: 1,
17 | alignItems: "center",
18 | justifyContent: "center",
19 | borderRightWidth: 0.5,
20 | borderColor: "#19153E"
21 | },
22 | zeroContainer: {
23 | flex: 2,
24 | alignItems: "center",
25 | justifyContent: "center",
26 | borderRightWidth: 0.5,
27 | borderColor: "#19153E"
28 | },
29 | textLight: {
30 | fontSize: 34,
31 | color: "#fff"
32 | },
33 | textDark: {
34 | fontSize: 34,
35 | color: "#575757"
36 | }
37 | });
38 | export default Btn;
39 |
--------------------------------------------------------------------------------
/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 | "eject": "expo eject"
8 | },
9 | "name": "Calculator App",
10 | "dependencies": {
11 | "eslint": "^5.13.0",
12 | "expo": "^32.0.0",
13 | "react": "16.5.0",
14 | "react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
15 | "react-redux": "^6.0.0",
16 | "redux": "^4.0.1"
17 | },
18 | "devDependencies": {
19 | "babel-preset-expo": "^5.0.0",
20 | "eslint": "^5.13.0",
21 | "eslint-config-airbnb": "^17.1.0",
22 | "eslint-plugin-import": "^2.16.0",
23 | "eslint-plugin-jsx-a11y": "^6.2.0",
24 | "eslint-plugin-react": "^7.12.4"
25 | },
26 | "private": true
27 | }
28 |
--------------------------------------------------------------------------------