Merge pull request #48 from djwesty/djwesty/39
Consistent Application Styling #39
This commit is contained in:
commit
93cc07c28c
@ -1,7 +1,35 @@
|
|||||||
|
import AppContext, { IAppContext } from "@/util/context";
|
||||||
|
import { MaterialIcons } from "@expo/vector-icons";
|
||||||
import { Stack } from "expo-router";
|
import { Stack } from "expo-router";
|
||||||
import React from "react";
|
import React, { useMemo, useState } from "react";
|
||||||
|
|
||||||
|
const RootLayout: React.FC = () => {
|
||||||
|
const [showSettings, setShowSettings] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const ctx = useMemo<IAppContext>(
|
||||||
|
() => ({
|
||||||
|
showSettings,
|
||||||
|
}),
|
||||||
|
[showSettings]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppContext.Provider value={ctx}>
|
||||||
|
<Stack
|
||||||
|
screenOptions={{
|
||||||
|
headerShown: true,
|
||||||
|
title: "Poker Chips Helper",
|
||||||
|
headerRight: () => (
|
||||||
|
<MaterialIcons
|
||||||
|
name="settings"
|
||||||
|
onPress={() => setShowSettings(!showSettings)}
|
||||||
|
size={30}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</AppContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const RootLayout: React.FC = () => (
|
|
||||||
<Stack screenOptions={{ headerShown: true, title: "Poker Chips Helper" }} />
|
|
||||||
);
|
|
||||||
export default RootLayout;
|
export default RootLayout;
|
||||||
|
175
app/index.tsx
175
app/index.tsx
@ -1,14 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useContext, useMemo } from "react";
|
||||||
import {
|
import { ScrollView, Alert } from "react-native";
|
||||||
ScrollView,
|
import Button from "@/containers/Button";
|
||||||
Text,
|
|
||||||
Alert,
|
|
||||||
Button,
|
|
||||||
View,
|
|
||||||
StyleSheet,
|
|
||||||
TouchableOpacity,
|
|
||||||
} from "react-native";
|
|
||||||
import { FontAwesome } from "@expo/vector-icons";
|
|
||||||
import PlayerSelector from "@/components/PlayerSelector";
|
import PlayerSelector from "@/components/PlayerSelector";
|
||||||
import BuyInSelector from "@/components/BuyInSelector";
|
import BuyInSelector from "@/components/BuyInSelector";
|
||||||
import ChipsSelector from "@/components/ChipsSelector";
|
import ChipsSelector from "@/components/ChipsSelector";
|
||||||
@ -20,14 +12,9 @@ import {
|
|||||||
savePersistentState,
|
savePersistentState,
|
||||||
loadPersistentState,
|
loadPersistentState,
|
||||||
} from "@/components/PersistentState";
|
} from "@/components/PersistentState";
|
||||||
|
import styles from "@/styles/styles";
|
||||||
export enum COLORS {
|
import Section from "@/containers/Section";
|
||||||
"white",
|
import AppContext from "@/util/context";
|
||||||
"red",
|
|
||||||
"green",
|
|
||||||
"blue",
|
|
||||||
"black",
|
|
||||||
}
|
|
||||||
|
|
||||||
const IndexScreen: React.FC = () => {
|
const IndexScreen: React.FC = () => {
|
||||||
const [playerCount, setPlayerCount] = useState(2);
|
const [playerCount, setPlayerCount] = useState(2);
|
||||||
@ -35,7 +22,8 @@ const IndexScreen: React.FC = () => {
|
|||||||
const [numberOfChips, setNumberOfChips] = useState<number>(5);
|
const [numberOfChips, setNumberOfChips] = useState<number>(5);
|
||||||
const [totalChipsCount, setTotalChipsCount] = useState<number[]>([]);
|
const [totalChipsCount, setTotalChipsCount] = useState<number[]>([]);
|
||||||
const [selectedCurrency, setSelectedCurrency] = useState<string>("$");
|
const [selectedCurrency, setSelectedCurrency] = useState<string>("$");
|
||||||
const [isSettingsVisible, setIsSettingsVisible] = useState(false);
|
const context = useContext(AppContext);
|
||||||
|
const isSettingsVisible = useMemo(() => context.showSettings, [context]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadPersistentData = async () => {
|
const loadPersistentData = async () => {
|
||||||
@ -104,96 +92,85 @@ const IndexScreen: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView contentContainerStyle={{ padding: 20, flexGrow: 1 }}>
|
<ScrollView
|
||||||
<View style={styles.header}>
|
style={styles.scrollView}
|
||||||
<TouchableOpacity
|
contentContainerStyle={styles.scrollViewContent}
|
||||||
onPress={() => setIsSettingsVisible(!isSettingsVisible)}
|
>
|
||||||
>
|
|
||||||
<Text>
|
|
||||||
<FontAwesome name="cog" size={30} color="black" />
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{isSettingsVisible && (
|
{isSettingsVisible && (
|
||||||
<View style={styles.settingsContainer}>
|
<Section title={"Select Currency"} iconName={"attach-money"}>
|
||||||
<CurrencySelector
|
<CurrencySelector
|
||||||
selectedCurrency={selectedCurrency}
|
selectedCurrency={selectedCurrency}
|
||||||
setSelectedCurrency={setSelectedCurrency}
|
setSelectedCurrency={setSelectedCurrency}
|
||||||
/>
|
/>
|
||||||
</View>
|
</Section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<PlayerSelector
|
<Section
|
||||||
playerCount={playerCount}
|
title={"Select the number of players"}
|
||||||
setPlayerCount={setPlayerCount}
|
iconName={"people"}
|
||||||
/>
|
orientation="row"
|
||||||
|
>
|
||||||
<BuyInSelector
|
<PlayerSelector
|
||||||
selectedCurrency={selectedCurrency}
|
playerCount={playerCount}
|
||||||
setBuyInAmount={setBuyInAmount}
|
setPlayerCount={setPlayerCount}
|
||||||
/>
|
|
||||||
|
|
||||||
<ChipDetection
|
|
||||||
updateChipCount={(chipData) => {
|
|
||||||
const chipCountArray = Object.values(chipData);
|
|
||||||
setTotalChipsCount(chipCountArray);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ChipsSelector
|
|
||||||
totalChipsCount={totalChipsCount}
|
|
||||||
setTotalChipsCount={setTotalChipsCount}
|
|
||||||
numberOfChips={numberOfChips}
|
|
||||||
setNumberOfChips={setNumberOfChips}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ChipDistributionSummary
|
|
||||||
playerCount={playerCount}
|
|
||||||
buyInAmount={buyInAmount}
|
|
||||||
totalChipsCount={totalChipsCount}
|
|
||||||
selectedCurrency={selectedCurrency}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<View style={styles.buttonContainer}>
|
|
||||||
<Button
|
|
||||||
title="Save to Slot 1"
|
|
||||||
onPress={() => handleSave("SLOT1")}
|
|
||||||
disabled={buyInAmount === null}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
</Section>
|
||||||
title="Save to Slot 2"
|
|
||||||
onPress={() => handleSave("SLOT2")}
|
<Section title={"Select buy-in amount"} iconName={"monetization-on"}>
|
||||||
disabled={buyInAmount === null}
|
<BuyInSelector
|
||||||
|
selectedCurrency={selectedCurrency}
|
||||||
|
setBuyInAmount={setBuyInAmount}
|
||||||
/>
|
/>
|
||||||
<Button title="Load from Slot 1" onPress={() => handleLoad("SLOT1")} />
|
</Section>
|
||||||
<Button title="Load from Slot 2" onPress={() => handleLoad("SLOT2")} />
|
|
||||||
</View>
|
<Section title={"Automatic Chip Detection"} iconName={"camera-alt"}>
|
||||||
|
<ChipDetection
|
||||||
|
updateChipCount={(chipData) => {
|
||||||
|
const chipCountArray = Object.values(chipData);
|
||||||
|
setTotalChipsCount(chipCountArray);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section title={"Manual Chip Adjustment"} iconName={"account-balance"}>
|
||||||
|
<ChipsSelector
|
||||||
|
totalChipsCount={totalChipsCount}
|
||||||
|
setTotalChipsCount={setTotalChipsCount}
|
||||||
|
numberOfChips={numberOfChips}
|
||||||
|
setNumberOfChips={setNumberOfChips}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section
|
||||||
|
title={"Distribution & Denomination"}
|
||||||
|
iconName={"currency-exchange"}
|
||||||
|
>
|
||||||
|
<ChipDistributionSummary
|
||||||
|
playerCount={playerCount}
|
||||||
|
buyInAmount={buyInAmount}
|
||||||
|
totalChipsCount={totalChipsCount}
|
||||||
|
selectedCurrency={selectedCurrency}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section title={"Save + Load"} iconName={"save"} orientation="row">
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
title={"Save\nSlot 1"}
|
||||||
|
onPress={() => handleSave("SLOT1")}
|
||||||
|
disabled={buyInAmount === null}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
title={"Save\nSlot 2"}
|
||||||
|
onPress={() => handleSave("SLOT2")}
|
||||||
|
disabled={buyInAmount === null}
|
||||||
|
/>
|
||||||
|
<Button title={"Load\nSlot 1"} onPress={() => handleLoad("SLOT1")} />
|
||||||
|
<Button title={"Load\nSlot 2"} onPress={() => handleLoad("SLOT2")} />
|
||||||
|
</>
|
||||||
|
</Section>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
header: {
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "flex-end",
|
|
||||||
alignItems: "center",
|
|
||||||
marginBottom: 20,
|
|
||||||
},
|
|
||||||
settingsContainer: {
|
|
||||||
marginBottom: 20,
|
|
||||||
padding: 10,
|
|
||||||
backgroundColor: "#f5f5f5",
|
|
||||||
borderRadius: 5,
|
|
||||||
},
|
|
||||||
settingTitle: {
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: "bold",
|
|
||||||
marginBottom: 10,
|
|
||||||
},
|
|
||||||
buttonContainer: {
|
|
||||||
marginTop: 20,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default IndexScreen;
|
export default IndexScreen;
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import { View, Text, TextInput } from "react-native";
|
||||||
View,
|
import styles, { COLORS } from "@/styles/styles";
|
||||||
Text,
|
import Button from "@/containers/Button";
|
||||||
TextInput,
|
|
||||||
TouchableOpacity,
|
|
||||||
StyleSheet,
|
|
||||||
} from "react-native";
|
|
||||||
import { MaterialIcons } from "@expo/vector-icons";
|
|
||||||
|
|
||||||
interface BuyInSelectorProps {
|
interface BuyInSelectorProps {
|
||||||
setBuyInAmount: React.Dispatch<React.SetStateAction<number>>;
|
setBuyInAmount: React.Dispatch<React.SetStateAction<number>>;
|
||||||
@ -42,31 +37,19 @@ const BuyInSelector: React.FC<BuyInSelectorProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<>
|
||||||
<View style={styles.header}>
|
<View style={{ ...styles.container, flexDirection: "row" }}>
|
||||||
<MaterialIcons name="monetization-on" size={30} color="green" />
|
|
||||||
<Text style={styles.title}>Select Buy-in Amount:</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={styles.optionsContainer}>
|
|
||||||
{defaultBuyInOptions.map((amount) => (
|
{defaultBuyInOptions.map((amount) => (
|
||||||
<TouchableOpacity
|
<Button
|
||||||
key={amount}
|
key={amount}
|
||||||
style={[
|
color={buyInAmount === amount ? COLORS.PRIMARY : COLORS.SECONDARY}
|
||||||
styles.buyInButton,
|
|
||||||
buyInAmount === amount ? styles.selectedButton : null,
|
|
||||||
]}
|
|
||||||
onPress={() => handleBuyInSelection(amount)}
|
onPress={() => handleBuyInSelection(amount)}
|
||||||
>
|
title={`${selectedCurrency} ${amount}`}
|
||||||
<Text style={styles.buttonText}>
|
></Button>
|
||||||
{selectedCurrency} {amount}{" "}
|
|
||||||
{/* Display the selected currency before the amount */}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={styles.orText}>Or enter a custom amount:</Text>
|
<Text style={styles.p}>Or enter a custom amount:</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={styles.input}
|
style={styles.input}
|
||||||
value={customAmount}
|
value={customAmount}
|
||||||
@ -75,60 +58,12 @@ const BuyInSelector: React.FC<BuyInSelectorProps> = ({
|
|||||||
keyboardType="numeric"
|
keyboardType="numeric"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Text style={styles.selectionText}>
|
<Text style={styles.h2}>
|
||||||
Selected Buy-in:{" "}
|
Selected Buy-in:{" "}
|
||||||
{buyInAmount !== null ? `${selectedCurrency} ${buyInAmount}` : "None"}{" "}
|
{buyInAmount !== null ? `${selectedCurrency} ${buyInAmount}` : "None"}
|
||||||
{/* Display the currency here */}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
marginBottom: 10,
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
fontSize: 22,
|
|
||||||
marginLeft: 10,
|
|
||||||
},
|
|
||||||
optionsContainer: {
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-around",
|
|
||||||
marginVertical: 10,
|
|
||||||
},
|
|
||||||
buyInButton: {
|
|
||||||
backgroundColor: "#ddd",
|
|
||||||
padding: 10,
|
|
||||||
borderRadius: 5,
|
|
||||||
},
|
|
||||||
selectedButton: {
|
|
||||||
backgroundColor: "#4caf50",
|
|
||||||
},
|
|
||||||
buttonText: {
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
|
||||||
orText: {
|
|
||||||
marginTop: 10,
|
|
||||||
textAlign: "center",
|
|
||||||
},
|
|
||||||
input: {
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: "#ccc",
|
|
||||||
padding: 8,
|
|
||||||
marginVertical: 10,
|
|
||||||
borderRadius: 5,
|
|
||||||
},
|
|
||||||
selectionText: {
|
|
||||||
marginTop: 15,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: "bold",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default BuyInSelector;
|
export default BuyInSelector;
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import { Image, ActivityIndicator, Text, View } from "react-native";
|
||||||
View,
|
import Button from "@/containers/Button";
|
||||||
Button,
|
|
||||||
Image,
|
|
||||||
ActivityIndicator,
|
|
||||||
Text,
|
|
||||||
ScrollView,
|
|
||||||
} from "react-native";
|
|
||||||
import * as ImagePicker from "expo-image-picker";
|
import * as ImagePicker from "expo-image-picker";
|
||||||
|
|
||||||
const ChipDetection = ({ updateChipCount }) => {
|
const ChipDetection = ({
|
||||||
|
updateChipCount,
|
||||||
|
}: {
|
||||||
|
updateChipCount: () => void;
|
||||||
|
}) => {
|
||||||
const [imageUri, setImageUri] = useState(null);
|
const [imageUri, setImageUri] = useState(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
@ -113,9 +112,11 @@ const ChipDetection = ({ updateChipCount }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView contentContainerStyle={{ padding: 20, alignItems: "center" }}>
|
<>
|
||||||
<Button title="Pick an Image" onPress={pickImage} />
|
<View style={{ flexDirection: "row", justifyContent: "space-evenly" }}>
|
||||||
<Button title="Take a Photo" onPress={takePhoto} />
|
<Button title="Pick an Image" onPress={pickImage} />
|
||||||
|
<Button title="Take a Photo" onPress={takePhoto} />
|
||||||
|
</View>
|
||||||
{imageUri && (
|
{imageUri && (
|
||||||
<Image
|
<Image
|
||||||
source={{ uri: imageUri }}
|
source={{ uri: imageUri }}
|
||||||
@ -124,7 +125,7 @@ const ChipDetection = ({ updateChipCount }) => {
|
|||||||
)}
|
)}
|
||||||
{loading && <ActivityIndicator size="large" color="blue" />}
|
{loading && <ActivityIndicator size="large" color="blue" />}
|
||||||
{error && <Text style={{ color: "red", marginTop: 10 }}>{error}</Text>}
|
{error && <Text style={{ color: "red", marginTop: 10 }}>{error}</Text>}
|
||||||
</ScrollView>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { View, Text, StyleSheet } from "react-native";
|
import { View, Text, StyleSheet } from "react-native";
|
||||||
import { ColorValue } from "react-native";
|
import { ColorValue } from "react-native";
|
||||||
|
import styles from "@/styles/styles";
|
||||||
|
|
||||||
interface ChipDistributionSummaryProps {
|
interface ChipDistributionSummaryProps {
|
||||||
playerCount: number;
|
playerCount: number;
|
||||||
@ -15,7 +16,7 @@ const ChipDistributionSummary = ({
|
|||||||
buyInAmount,
|
buyInAmount,
|
||||||
totalChipsCount,
|
totalChipsCount,
|
||||||
colors = ["white", "red", "green", "blue", "black"],
|
colors = ["white", "red", "green", "blue", "black"],
|
||||||
selectedCurrency,
|
selectedCurrency = "$",
|
||||||
}: ChipDistributionSummaryProps) => {
|
}: ChipDistributionSummaryProps) => {
|
||||||
const validDenominations: validDenomination[] = [
|
const validDenominations: validDenomination[] = [
|
||||||
0.05, 0.1, 0.25, 0.5, 1, 2, 2.5, 5, 10, 20, 50, 100,
|
0.05, 0.1, 0.25, 0.5, 1, 2, 2.5, 5, 10, 20, 50, 100,
|
||||||
@ -153,84 +154,32 @@ const ChipDistributionSummary = ({
|
|||||||
}, [totalChipsCount, maxDenomination, buyInAmount, playerCount]);
|
}, [totalChipsCount, maxDenomination, buyInAmount, playerCount]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<>
|
||||||
<Text style={styles.title}>Distribution & Denomination</Text>
|
<View style={styles.container}>
|
||||||
<Text style={styles.subTitle}>
|
|
||||||
{selectedCurrency} {potValue} Pot
|
|
||||||
</Text>
|
|
||||||
<View style={styles.chipContainer}>
|
|
||||||
{totalChipsCount.map((_, index) => (
|
{totalChipsCount.map((_, index) => (
|
||||||
<View style={styles.chipRow} key={index}>
|
<View style={{ flexDirection: "row" }} key={index}>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
...styles.chipText,
|
...styles.h2,
|
||||||
color: colors[index],
|
color: colors[index],
|
||||||
...(colors[index] === "white" && styles.whiteShadow),
|
...(colors[index] === "white" && styles.shadow),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{distributions[index]} chips:
|
{`${distributions[index]} chips: ${selectedCurrency}${denominations[index]} each`}
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
...styles.chipText,
|
|
||||||
color: colors[index],
|
|
||||||
...(colors[index] === "white" && styles.whiteShadow),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{selectedCurrency} {denominations[index]} each
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.chipText}>
|
<View style={{ flexDirection: "row", justifyContent: "space-between" }}>
|
||||||
Total Value: {selectedCurrency} {totalValue}
|
<Text style={styles.p}>
|
||||||
</Text>
|
Total Value: {selectedCurrency} {totalValue}
|
||||||
</View>
|
</Text>
|
||||||
|
<Text style={styles.p}>
|
||||||
|
{selectedCurrency} {potValue} Pot
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
marginTop: 20,
|
|
||||||
padding: 15,
|
|
||||||
borderRadius: 10,
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: "bold",
|
|
||||||
marginBottom: 10,
|
|
||||||
},
|
|
||||||
subTitle: {
|
|
||||||
fontSize: 16,
|
|
||||||
color: "gray",
|
|
||||||
fontWeight: "bold",
|
|
||||||
marginBottom: 10,
|
|
||||||
},
|
|
||||||
chipContainer: {
|
|
||||||
marginTop: 10,
|
|
||||||
},
|
|
||||||
chipRow: {
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "center",
|
|
||||||
gap: 10,
|
|
||||||
},
|
|
||||||
chipText: {
|
|
||||||
fontSize: 20,
|
|
||||||
marginVertical: 2,
|
|
||||||
fontWeight: "bold",
|
|
||||||
},
|
|
||||||
whiteShadow: {
|
|
||||||
textShadowColor: "black",
|
|
||||||
textShadowOffset: { width: 0, height: 0 },
|
|
||||||
textShadowRadius: 10,
|
|
||||||
},
|
|
||||||
noDataText: {
|
|
||||||
fontSize: 16,
|
|
||||||
color: "gray",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default ChipDistributionSummary;
|
export default ChipDistributionSummary;
|
||||||
|
@ -4,10 +4,14 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Button,
|
|
||||||
ColorValue,
|
ColorValue,
|
||||||
Modal,
|
Modal,
|
||||||
|
TouchableOpacity,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
|
import Button from "@/containers/Button";
|
||||||
|
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
|
import styles from "@/styles/styles";
|
||||||
|
|
||||||
const colors: ColorValue[] = ["white", "red", "green", "blue", "black"];
|
const colors: ColorValue[] = ["white", "red", "green", "blue", "black"];
|
||||||
|
|
||||||
const ChipInputModal = ({
|
const ChipInputModal = ({
|
||||||
@ -31,16 +35,27 @@ const ChipInputModal = ({
|
|||||||
setValue(totalChipsCount[colorIdx]);
|
setValue(totalChipsCount[colorIdx]);
|
||||||
}, [colorIdx]);
|
}, [colorIdx]);
|
||||||
|
|
||||||
|
const shadow = useMemo(() => color === "white", [color]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
visible={showModal[0]}
|
visible={showModal[0]}
|
||||||
onRequestClose={() => setShowModal([false, color])}
|
onRequestClose={() => setShowModal([false, color])}
|
||||||
|
style={styles.modal}
|
||||||
|
presentationStyle="fullScreen"
|
||||||
|
animationType="slide"
|
||||||
>
|
>
|
||||||
{value !== undefined && (
|
{value !== undefined && (
|
||||||
<>
|
<>
|
||||||
<Text>Number of {showModal[1]?.toString()} chips</Text>
|
<Text style={styles.h2}>
|
||||||
|
Number of {showModal[1]?.toString()} chips
|
||||||
|
</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={{ color: showModal[1] }}
|
style={{
|
||||||
|
...styles.input,
|
||||||
|
color: showModal[1],
|
||||||
|
...(shadow ? styles.shadow : {}),
|
||||||
|
}}
|
||||||
keyboardType="numeric"
|
keyboardType="numeric"
|
||||||
value={value.toString()}
|
value={value.toString()}
|
||||||
onChangeText={(v) => {
|
onChangeText={(v) => {
|
||||||
@ -71,14 +86,25 @@ const Chip = ({
|
|||||||
count: number;
|
count: number;
|
||||||
setShowModal: React.Dispatch<React.SetStateAction<[boolean, ColorValue]>>;
|
setShowModal: React.Dispatch<React.SetStateAction<[boolean, ColorValue]>>;
|
||||||
}) => {
|
}) => {
|
||||||
|
const shadow = useMemo(() => color === "white", [color]);
|
||||||
return (
|
return (
|
||||||
<Text
|
<TouchableOpacity
|
||||||
key={color.toString()}
|
|
||||||
onPress={() => setShowModal([true, color])}
|
onPress={() => setShowModal([true, color])}
|
||||||
style={[{ color: color }, styles.chip]}
|
style={{ alignItems: "center" }}
|
||||||
>
|
>
|
||||||
{count}
|
<MaterialCommunityIcons
|
||||||
</Text>
|
name="poker-chip"
|
||||||
|
size={24}
|
||||||
|
color={color}
|
||||||
|
style={shadow ? styles.shadow : {}}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
key={color.toString()}
|
||||||
|
style={[{ color: color }, styles.h2, shadow ? styles.shadow : {}]}
|
||||||
|
>
|
||||||
|
{count}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,34 +160,31 @@ const ChipsSelector = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View style={styles.container}>
|
<View style={[styles.container, { flexDirection: "row" }]}>
|
||||||
<Text style={styles.title}>Chips you have</Text>
|
{colorsUsed.map((color) => (
|
||||||
<View style={styles.chipContainer}>
|
<Chip
|
||||||
{colorsUsed.map((color) => (
|
key={color.toString()}
|
||||||
<Chip
|
color={color}
|
||||||
key={color.toString()}
|
count={totalChipsCount[colors.indexOf(color)] ?? 0}
|
||||||
color={color}
|
setShowModal={setShowModal}
|
||||||
count={totalChipsCount[colors.indexOf(color)] ?? 0}
|
|
||||||
setShowModal={setShowModal}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</View>
|
|
||||||
<View style={styles.buttonContainer}>
|
|
||||||
<Button
|
|
||||||
title="-"
|
|
||||||
onPress={() => {
|
|
||||||
setNumberOfChips(Math.max(1, numberOfChips - 1));
|
|
||||||
}}
|
|
||||||
disabled={numberOfChips == 1}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
))}
|
||||||
title="+"
|
</View>
|
||||||
onPress={() => {
|
<View style={[styles.container, { flexDirection: "row" }]}>
|
||||||
setNumberOfChips(Math.min(5, numberOfChips + 1));
|
<Button
|
||||||
}}
|
title="-"
|
||||||
disabled={numberOfChips == 5}
|
onPress={() => {
|
||||||
/>
|
setNumberOfChips(Math.max(1, numberOfChips - 1));
|
||||||
</View>
|
}}
|
||||||
|
disabled={numberOfChips == 1}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
title="+"
|
||||||
|
onPress={() => {
|
||||||
|
setNumberOfChips(Math.min(5, numberOfChips + 1));
|
||||||
|
}}
|
||||||
|
disabled={numberOfChips == 5}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<ChipInputModal
|
<ChipInputModal
|
||||||
@ -174,7 +197,7 @@ const ChipsSelector = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles1 = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
marginBottom: 20,
|
marginBottom: 20,
|
||||||
gap: 10,
|
gap: 10,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { View, StyleSheet, Text } from "react-native";
|
|
||||||
import { Picker } from "@react-native-picker/picker";
|
import { Picker } from "@react-native-picker/picker";
|
||||||
|
import styles from "@/styles/styles";
|
||||||
|
|
||||||
interface CurrencySelectorProps {
|
interface CurrencySelectorProps {
|
||||||
selectedCurrency: string;
|
selectedCurrency: string;
|
||||||
@ -12,8 +12,7 @@ const CurrencySelector: React.FC<CurrencySelectorProps> = ({
|
|||||||
setSelectedCurrency,
|
setSelectedCurrency,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<>
|
||||||
<Text style={styles.title}>Select Currency:</Text>
|
|
||||||
<Picker
|
<Picker
|
||||||
selectedValue={selectedCurrency}
|
selectedValue={selectedCurrency}
|
||||||
onValueChange={(itemValue) => setSelectedCurrency(itemValue)}
|
onValueChange={(itemValue) => setSelectedCurrency(itemValue)}
|
||||||
@ -25,22 +24,8 @@ const CurrencySelector: React.FC<CurrencySelectorProps> = ({
|
|||||||
<Picker.Item label="Pound (£)" value="£" />
|
<Picker.Item label="Pound (£)" value="£" />
|
||||||
<Picker.Item label="INR (₹)" value="₹" />
|
<Picker.Item label="INR (₹)" value="₹" />
|
||||||
</Picker>
|
</Picker>
|
||||||
</View>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
marginBottom: 20,
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
fontSize: 18,
|
|
||||||
marginBottom: 10,
|
|
||||||
},
|
|
||||||
picker: {
|
|
||||||
height: 50,
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default CurrencySelector;
|
export default CurrencySelector;
|
||||||
|
@ -1,64 +1,43 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { View, Text, Button, Image, StyleSheet } from "react-native";
|
import { View, Text } from "react-native";
|
||||||
|
import Button from "@/containers/Button";
|
||||||
|
import styles from "@/styles/styles";
|
||||||
|
|
||||||
interface PlayerSelectorProps {
|
interface PlayerSelectorProps {
|
||||||
playerCount: number;
|
playerCount: number;
|
||||||
setPlayerCount: React.Dispatch<React.SetStateAction<number>>;
|
setPlayerCount: React.Dispatch<React.SetStateAction<number>>;
|
||||||
}
|
}
|
||||||
|
const MIN = 2;
|
||||||
|
const MAX = 8;
|
||||||
const PlayerSelector: React.FC<PlayerSelectorProps> = ({
|
const PlayerSelector: React.FC<PlayerSelectorProps> = ({
|
||||||
playerCount,
|
playerCount,
|
||||||
setPlayerCount,
|
setPlayerCount,
|
||||||
}) => {
|
}) => {
|
||||||
const increasePlayers = () => {
|
const increasePlayers = () => {
|
||||||
if (playerCount < 8) setPlayerCount(playerCount + 1);
|
if (playerCount < MAX) setPlayerCount(playerCount + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const decreasePlayers = () => {
|
const decreasePlayers = () => {
|
||||||
if (playerCount > 2) setPlayerCount(playerCount - 1);
|
if (playerCount > MIN) setPlayerCount(playerCount - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<>
|
||||||
<View style={styles.header}>
|
<Text style={styles.h1}>{playerCount}</Text>
|
||||||
<Image
|
<View style={{ flexDirection: "row", gap: 10 }}>
|
||||||
source={{
|
<Button
|
||||||
uri: "https://static.thenounproject.com/png/3890959-200.png",
|
title="-"
|
||||||
}}
|
onPress={decreasePlayers}
|
||||||
style={styles.icon}
|
disabled={playerCount <= MIN}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
title="+"
|
||||||
|
onPress={increasePlayers}
|
||||||
|
disabled={playerCount >= MAX}
|
||||||
/>
|
/>
|
||||||
<Text style={styles.title}>Select Number of Players:</Text>
|
|
||||||
</View>
|
</View>
|
||||||
|
</>
|
||||||
<Text style={styles.playerCount}>{playerCount}</Text>
|
|
||||||
<View style={{ flexDirection: "row" }}>
|
|
||||||
<Button title="-" onPress={decreasePlayers} />
|
|
||||||
<Button title="+" onPress={increasePlayers} />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
fontSize: 18,
|
|
||||||
marginLeft: 10, // Spacing between icon and text
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
width: 48, // Increased size
|
|
||||||
height: 48, // Increased size
|
|
||||||
},
|
|
||||||
playerCount: {
|
|
||||||
fontSize: 24,
|
|
||||||
marginVertical: 10,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default PlayerSelector;
|
export default PlayerSelector;
|
||||||
|
@ -32,7 +32,6 @@ describe("BuyInSelector Component", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("renders the buy-in options and input correctly", () => {
|
it("renders the buy-in options and input correctly", () => {
|
||||||
expect(getByText("Select Buy-in Amount:")).toBeTruthy();
|
|
||||||
expect(getByText("$ 10")).toBeTruthy();
|
expect(getByText("$ 10")).toBeTruthy();
|
||||||
expect(getByText("$ 25")).toBeTruthy();
|
expect(getByText("$ 25")).toBeTruthy();
|
||||||
expect(getByText("$ 50")).toBeTruthy();
|
expect(getByText("$ 50")).toBeTruthy();
|
||||||
|
@ -12,26 +12,20 @@ describe("ChipDistributionSummary Component", () => {
|
|||||||
const expectedDistribution = [2, 2, 1, 2, 2];
|
const expectedDistribution = [2, 2, 1, 2, 2];
|
||||||
const expectedDenominations = [0.5, 1, 2, 2.5, 5];
|
const expectedDenominations = [0.5, 1, 2, 2.5, 5];
|
||||||
|
|
||||||
const { getByText, getAllByText } = render(
|
const { getByText } = render(
|
||||||
<ChipDistributionSummary
|
<ChipDistributionSummary
|
||||||
playerCount={playerCount}
|
playerCount={playerCount}
|
||||||
buyInAmount={buyInAmount}
|
buyInAmount={buyInAmount}
|
||||||
totalChipsCount={totalChipsCount}
|
totalChipsCount={totalChipsCount}
|
||||||
|
selectedCurrency={"$"}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(getByText("Distribution & Denomination")).toBeTruthy();
|
|
||||||
|
|
||||||
expectedDistribution.forEach((count, index) => {
|
expectedDistribution.forEach((count, index) => {
|
||||||
// Ensure "X chips:" appears correctly
|
const regex = new RegExp(
|
||||||
expect(getAllByText(new RegExp(`^${count}\\s+chips:`, "i"))).toBeTruthy();
|
`^${count}\\s+chips:\\s+\\$${expectedDenominations[index]}\\s+each$`
|
||||||
|
);
|
||||||
// Ensure value format matches the rendered output
|
expect(getByText(regex)).toBeTruthy();
|
||||||
expect(
|
|
||||||
getByText(
|
|
||||||
new RegExp(`^\\s*${expectedDenominations[index]}\\s+each$`, "i")
|
|
||||||
)
|
|
||||||
).toBeTruthy();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -40,6 +34,7 @@ describe("ChipDistributionSummary Component", () => {
|
|||||||
<ChipDistributionSummary
|
<ChipDistributionSummary
|
||||||
playerCount={0}
|
playerCount={0}
|
||||||
buyInAmount={20}
|
buyInAmount={20}
|
||||||
|
selectedCurrency={"$"}
|
||||||
totalChipsCount={[]}
|
totalChipsCount={[]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -66,6 +61,7 @@ describe("ChipDistributionSummary Component", () => {
|
|||||||
playerCount={playerCount}
|
playerCount={playerCount}
|
||||||
buyInAmount={100}
|
buyInAmount={100}
|
||||||
totalChipsCount={totalChipsCount}
|
totalChipsCount={totalChipsCount}
|
||||||
|
selectedCurrency={"$"}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -10,6 +10,13 @@ import ChipsSelector from "@/components/ChipsSelector";
|
|||||||
|
|
||||||
const TOTAL_CHIPS_COUNT = [100, 80, 60, 40, 20];
|
const TOTAL_CHIPS_COUNT = [100, 80, 60, 40, 20];
|
||||||
|
|
||||||
|
jest.mock("@expo/vector-icons", () => {
|
||||||
|
const { Text } = require("react-native");
|
||||||
|
return {
|
||||||
|
MaterialCommunityIcons: () => <Text>TestIcon</Text>,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const mocktTotalChipsCount = jest.fn();
|
const mocktTotalChipsCount = jest.fn();
|
||||||
const mockSetNumberOfChips = jest.fn();
|
const mockSetNumberOfChips = jest.fn();
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ describe("CurrencySelector Component", () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(getByText("Select Currency:")).toBeTruthy(); // Check label exists
|
|
||||||
expect(getByTestId("currency-picker")).toBeTruthy(); // Check Picker exists
|
expect(getByTestId("currency-picker")).toBeTruthy(); // Check Picker exists
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ describe("PlayerSelector Component", () => {
|
|||||||
<PlayerSelector playerCount={4} setPlayerCount={setPlayerCount} />
|
<PlayerSelector playerCount={4} setPlayerCount={setPlayerCount} />
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(getByText("Select Number of Players:")).toBeTruthy();
|
|
||||||
expect(getByText("4")).toBeTruthy();
|
expect(getByText("4")).toBeTruthy();
|
||||||
expect(getByRole("button", { name: "-" })).toBeTruthy();
|
expect(getByRole("button", { name: "-" })).toBeTruthy();
|
||||||
expect(getByRole("button", { name: "+" })).toBeTruthy();
|
expect(getByRole("button", { name: "+" })).toBeTruthy();
|
||||||
|
9
containers/Button.tsx
Normal file
9
containers/Button.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { ButtonProps, Button } from "react-native";
|
||||||
|
import { COLORS } from "@/styles/styles";
|
||||||
|
|
||||||
|
// More styling can be done, or swap this out with more flexible component like a TouchableOpacity if needed
|
||||||
|
const AppButton = (props: ButtonProps) => (
|
||||||
|
<Button color={COLORS.PRIMARY} {...props} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export default AppButton;
|
67
containers/Section.tsx
Normal file
67
containers/Section.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { View, Text, StyleSheet } from "react-native";
|
||||||
|
import React from "react";
|
||||||
|
import { MaterialIcons } from "@expo/vector-icons";
|
||||||
|
import globalStyles from "@/styles/styles";
|
||||||
|
|
||||||
|
const titleCase = (input: string) =>
|
||||||
|
input
|
||||||
|
.split(" ")
|
||||||
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
//Higher Order Component (HOC) for styling purposes
|
||||||
|
const Section = ({
|
||||||
|
title,
|
||||||
|
iconName,
|
||||||
|
children,
|
||||||
|
orientation = "column",
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
iconName: string | any;
|
||||||
|
children: React.JSX.Element;
|
||||||
|
orientation?: "row" | "column";
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<MaterialIcons
|
||||||
|
style={styles.icon}
|
||||||
|
name={iconName}
|
||||||
|
size={30}
|
||||||
|
color={"black"}
|
||||||
|
/>
|
||||||
|
<Text style={styles.title}>{titleCase(title)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{ ...styles.content, flexDirection: orientation }}>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
marginBottom: 20,
|
||||||
|
display: "flex",
|
||||||
|
alignContent: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 5,
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
icon: {},
|
||||||
|
title: {
|
||||||
|
...globalStyles.h1,
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-evenly",
|
||||||
|
gap: 5,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Section;
|
32
containers/__tests__/Section.test.tsx
Normal file
32
containers/__tests__/Section.test.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { render, screen } from "@testing-library/react-native";
|
||||||
|
import Section from "../Section";
|
||||||
|
import { Text } from "react-native";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
jest.mock("@expo/vector-icons", () => {
|
||||||
|
const { Text } = require("react-native");
|
||||||
|
return {
|
||||||
|
MaterialIcons: () => <Text testID={"test-icon"}>TestIcon</Text>,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const TITLE = "Select the weather";
|
||||||
|
const rend = () =>
|
||||||
|
render(
|
||||||
|
<Section title={TITLE} iconName={"test-icon"}>
|
||||||
|
<Text>child</Text>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
describe("tests for the Section HOC Component", () => {
|
||||||
|
it("everything expected appears", () => {
|
||||||
|
rend();
|
||||||
|
const title = screen.getByText(/select the weather/i);
|
||||||
|
expect(title).toBeTruthy();
|
||||||
|
|
||||||
|
const child = screen.getByText("child");
|
||||||
|
expect(child).toBeTruthy();
|
||||||
|
|
||||||
|
const icon = screen.getByTestId("test-icon");
|
||||||
|
expect(icon).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
59
styles/styles.ts
Normal file
59
styles/styles.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
|
||||||
|
export const COLORS = {
|
||||||
|
PRIMARY: "#007bff",
|
||||||
|
SECONDARY: "#6c757d",
|
||||||
|
SUCCESS: "#28a745",
|
||||||
|
DANGER: "#dc3545",
|
||||||
|
WARNING: "#ffc107",
|
||||||
|
};
|
||||||
|
|
||||||
|
const lightStyles = StyleSheet.create({});
|
||||||
|
const darkStyles = StyleSheet.create({});
|
||||||
|
|
||||||
|
const GlobalStyles = StyleSheet.create({
|
||||||
|
scrollView: {},
|
||||||
|
scrollViewContent: {
|
||||||
|
padding: 15,
|
||||||
|
},
|
||||||
|
|
||||||
|
container: {
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 10,
|
||||||
|
},
|
||||||
|
|
||||||
|
h1: { fontSize: 20, fontWeight: "bold" },
|
||||||
|
h2: { fontSize: 18, fontWeight: "normal" },
|
||||||
|
p: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#333",
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#ccc",
|
||||||
|
padding: 8,
|
||||||
|
marginVertical: 10,
|
||||||
|
borderRadius: 5,
|
||||||
|
},
|
||||||
|
modal: {},
|
||||||
|
|
||||||
|
button: {
|
||||||
|
backgroundColor: "#007bff",
|
||||||
|
padding: 10,
|
||||||
|
borderRadius: 5,
|
||||||
|
},
|
||||||
|
shadow: {
|
||||||
|
textShadowColor: "black",
|
||||||
|
textShadowOffset: { width: 0, height: 0 },
|
||||||
|
textShadowRadius: 10,
|
||||||
|
},
|
||||||
|
picker: {
|
||||||
|
height: 50,
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default GlobalStyles;
|
13
util/context.ts
Normal file
13
util/context.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import React, { createContext } from "react";
|
||||||
|
|
||||||
|
export interface IAppContext {
|
||||||
|
showSettings: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultContext: IAppContext = {
|
||||||
|
showSettings: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppContext = createContext<IAppContext>(defaultContext);
|
||||||
|
|
||||||
|
export default AppContext;
|
Loading…
Reference in New Issue
Block a user