make some components, almost done, need to do ui for notes/free play

This commit is contained in:
Loewy 2024-02-20 18:49:08 -08:00
parent 5cb1069c1c
commit 2505fc1bf7
6 changed files with 189 additions and 121 deletions

View File

@ -0,0 +1,26 @@
import React, { useState } from "react";
import { Image } from "react-native";
type ImageWithFallbackProps = {
source: { uri: string };
fallbackSource?: { uri: string };
style?: object;
};
const ImageWithFallback: React.FC<ImageWithFallbackProps> = ({
source,
fallbackSource,
style,
}) => {
const [imageSource, setImageSource] = useState(source);
const handleError = () => {
if (fallbackSource) {
setImageSource(fallbackSource);
}
};
return <Image source={imageSource} style={style} onError={handleError} />;
};
export default ImageWithFallback;

View File

@ -1,114 +0,0 @@
import React, { useState } from "react";
import { Image, StyleSheet, Text, View } from "react-native";
export default function SessionDetails() {
// Modal State
const [visible, setVisible] = useState<boolean>(false);
// Stats State
// TODO: needs to come from session context
const [sessionTitle, setSessionTitle] = useState<string>("Afternoon Session");
const [date, setDate] = useState<string>("Today at 2:37pm");
const [timePlayed, setTimePlayed] = useState("5:03:10");
const [medianRun, setMedianRun] = useState("7.3");
const [makeRate, setMakeRate] = useState("34%");
const [shotPacing, setShotPacing] = useState("0:00:26");
const [gameType, setGameType] = useState("Free Play");
const [notes, setNotes] = useState(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
);
return (
<View>
<View style={styles.headerSection}>
<Text style={styles.header}>{sessionTitle}</Text>
<Text>{date}</Text>
</View>
<Image
source={{ uri: "https://picsum.photos/200" }}
style={styles.image}
/>
<View style={styles.statsContainer}>
<View style={styles.statColumn}>
<View style={styles.statItem}>
<Text style={styles.statLabel}>TIME PLAYED</Text>
<Text style={styles.statValue}>{timePlayed}</Text>
</View>
<View style={styles.statItem}>
<Text style={styles.statLabel}>MEDIAN RUN</Text>
<Text style={styles.statValue}>{medianRun}</Text>
</View>
</View>
<View style={styles.statColumn}>
<View style={styles.statItem}>
<Text style={styles.statLabel}>MAKE RATE</Text>
<Text style={styles.statValue}>{makeRate}</Text>
</View>
<View style={styles.statItem}>
<Text style={styles.statLabel}>SHOT PACING</Text>
<Text style={styles.statValue}>{shotPacing}</Text>
</View>
</View>
</View>
{/* USE A BETTER SYSTEM FOR THE DIVIDER, COULD ATTACH TO OTHER COMPONENT */}
<View style={styles.horizontalDivider} />
<Text style={styles.gameType}>{gameType}</Text>
<Text style={styles.notes}>{notes}</Text>
</View>
);
}
const styles = StyleSheet.create({
headerSection: {
paddingHorizontal: 20,
paddingVertical: 15,
},
header: {
fontSize: 24,
fontWeight: "bold",
},
image: {
width: "100%",
height: 248,
},
statsContainer: {
flexDirection: "row",
justifyContent: "space-between",
padding: 20,
},
statColumn: {
flex: 1,
padding: 5,
},
statItem: {
borderLeftWidth: 0.5,
borderRightColor: "lightgrey",
marginBottom: 10,
},
statLabel: {
fontSize: 16,
color: "grey",
textAlign: "center",
},
statValue: {
fontSize: 28,
fontWeight: "bold",
textAlign: "center",
},
horizontalDivider: {
borderBottomWidth: 0.5,
color: "lightgrey",
width: "90%",
alignSelf: "center",
},
gameType: {
fontSize: 18,
textAlign: "center",
marginTop: 10,
},
notes: {
fontSize: 16,
color: "grey",
padding: 20,
},
});

View File

@ -0,0 +1,93 @@
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import { mock_session_details } from "../../../test/mock/charts/mock-data";
import ImageWithFallback from "../image/image-with-fallback";
import StatList from "./stat-item";
import Splash from "../../assets/splash.png";
export default function SessionDetails() {
// Remove mock destructure when data is piped through from BE
const {
sessionTitle,
date,
timePlayed,
medianRun,
makeRate,
shotPacing,
gameType,
notes,
} = mock_session_details;
const leftColumnStats = [
{ title: "TIME PLAYED", value: timePlayed },
{ title: "MEDIAN RUN", value: medianRun },
];
const rightColumnStats = [
{ title: "MAKE RATE", value: makeRate },
{ title: "SHOT PACING", value: shotPacing },
];
return (
<View>
<View style={styles.headerSection}>
<Text style={styles.header}>{sessionTitle}</Text>
<Text>{date}</Text>
</View>
<ImageWithFallback
source={{ uri: "https://picsum.photos/200" }}
fallbackSource={{ uri: Splash }}
style={styles.image}
/>
<View style={styles.statsContainer}>
<StatList items={leftColumnStats} style={styles.statColumn} />
<StatList items={rightColumnStats} style={styles.statColumn} />
</View>
{/* USE A BETTER SYSTEM FOR THE DIVIDER, COULD ATTACH TO OTHER COMPONENT */}
<View style={styles.horizontalDivider} />
<Text style={styles.gameType}>{gameType}</Text>
<Text style={styles.notes}>{notes}</Text>
</View>
);
}
const styles = StyleSheet.create({
headerSection: {
paddingHorizontal: 20,
paddingVertical: 15,
},
header: {
fontSize: 24,
fontWeight: "bold",
},
image: {
width: "100%",
height: 248,
},
statsContainer: {
flexDirection: "row",
justifyContent: "space-between",
padding: 20,
},
statColumn: {
flex: 1,
padding: 5,
},
horizontalDivider: {
borderBottomWidth: 0.5,
color: "lightgrey",
width: "90%",
alignSelf: "center",
},
gameType: {
fontSize: 18,
textAlign: "center",
marginTop: 10,
},
notes: {
fontSize: 16,
color: "grey",
padding: 20,
},
});

View File

@ -0,0 +1,50 @@
import React from "react";
import { StyleSheet, Text, View } from "react-native";
type StatItem = {
title: string;
value: string;
};
type StatListProps = {
items: StatItem[];
style?: object;
};
const StatList: React.FC<StatListProps> = ({ items, style }) => {
return (
<View style={[styles.container, style]}>
{items.map((item, index) => (
<View key={index} style={styles.item}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.value}>{item.value}</Text>
</View>
))}
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: "column",
flex: 1,
padding: 5,
},
item: {
borderLeftWidth: 0.5,
borderRightColor: "lightgrey",
marginBottom: 10,
},
title: {
fontSize: 16,
color: "grey",
textAlign: "center",
},
value: {
fontSize: 28,
fontWeight: "bold",
textAlign: "center",
},
});
export default StatList;

View File

@ -1,7 +1,14 @@
import Constants from "expo-constants"; import Constants from "expo-constants";
import { Platform, StyleSheet } from "react-native"; import { Platform, StyleSheet } from "react-native";
// GLOBAL STYLES
// STYLE CONSTS
let STATUS_BAR_HEIGHT: number;
Platform.OS === "android"
? (STATUS_BAR_HEIGHT = 24)
: (STATUS_BAR_HEIGHT = Constants.statusBarHeight | 24);
// GLOBALLY STYLED
export const globalInputStyles = StyleSheet.create({ export const globalInputStyles = StyleSheet.create({
input: { input: {
width: "100%", width: "100%",
@ -30,12 +37,6 @@ export const globalInputStyles = StyleSheet.create({
}, },
}); });
let STATUS_BAR_HEIGHT: number;
Platform.OS === "android"
? (STATUS_BAR_HEIGHT = 24)
: (STATUS_BAR_HEIGHT = Constants.statusBarHeight | 24);
// COLORS: // COLORS:
// can be made more granular to specify utility (ex: fontColors vs backgroundColors) // can be made more granular to specify utility (ex: fontColors vs backgroundColors)
export const colors = { export const colors = {
@ -55,6 +56,7 @@ export const tabIconColors = {
selected: "#598EBB", selected: "#598EBB",
}; };
// SHADOWS
export const shadows = { export const shadows = {
standard: { standard: {
shadowColor: "#000000", shadowColor: "#000000",

View File

@ -97,3 +97,14 @@ export const mockYData = [
]; ];
export const mockXValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; export const mockXValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
export const mock_session_details = {
sessionTitle: "Afternoon Session",
date: "Today at 2:37pm",
timePlayed: "5:03:10",
medianRun: "7.3",
makeRate: "34%",
shotPacing: "0:00:26",
gameType: "Free Play",
notes: "Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
};