Skip to content

Commit

Permalink
feat: blood sugar pager widget
Browse files Browse the repository at this point in the history
  • Loading branch information
trevorpfiz committed Aug 12, 2024
1 parent 4bd331e commit a82de0f
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 110 deletions.
6 changes: 3 additions & 3 deletions apps/expo/src/app/(app)/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ const TabsLayout = () => {
tabBarIcon: ({ size }) => (
<View
style={{
width: size + 10,
height: size + 10,
width: size + 20,
height: size + 20,
borderRadius: 9999,
backgroundColor: colors.blue[600],
justifyContent: "center",
alignItems: "center",
top: 10,
top: 12,
}}
>
<Plus size={size} color="white" />
Expand Down
17 changes: 13 additions & 4 deletions apps/expo/src/app/(app)/(tabs)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { ScrollView } from "react-native-gesture-handler";
import { SafeAreaView } from "react-native-safe-area-context";

import MyChart from "~/components/charts/line-chart";
import BloodSugarWidget from "~/components/home/blood-sugar-widget";
import { DaySlider } from "~/components/home/day-slider";
import HomeHeader from "~/components/home/home-header";
import { OverviewPager } from "~/components/home/overview-pager";
import { TempWidget } from "~/components/home/temp-widget";
import Timeline from "~/components/home/timeline";
import { Separator } from "~/components/ui/separator";

Expand All @@ -25,15 +27,22 @@ export default function HomeScreen() {
{/* Main Content */}
<ScrollView style={{ flex: 1 }} showsVerticalScrollIndicator={true}>
{/* Overview Pager */}
<View className="h-64">
<OverviewPager />
<View className="h-64 flex-1">
<OverviewPager>
<BloodSugarWidget />
<TempWidget />
</OverviewPager>
</View>

{/* CGM Chart */}
<MyChart />
<View className="flex-1">
<MyChart />
</View>

{/* Timeline */}
<Timeline />
<View className="flex-1">
<Timeline />
</View>

{/* Zones */}
</ScrollView>
Expand Down
63 changes: 63 additions & 0 deletions apps/expo/src/components/home/blood-sugar-widget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { View } from "react-native";

import type { MacrosData } from "~/data/macros";
import { Text } from "~/components/ui/text";
import { mockMacrosData } from "~/data/macros";
import { useColorScheme } from "~/lib/use-color-scheme";
import { cn, getBloodSugarColors } from "~/lib/utils";

const MacroItem = ({ label, value }: MacrosData) => (
<View className="flex-row">
<Text className="text-sm font-semibold">{value}</Text>
<Text className="text-sm text-gray-500">{label}</Text>
</View>
);

export default function BloodSugarWidget() {
const { colorScheme } = useColorScheme();
const isDark = colorScheme === "dark";

const bloodSugar = 194;
const bloodSugarColors = getBloodSugarColors(bloodSugar, isDark);

return (
<View className="flex-col items-center gap-4 pb-4">
{/* Blood Sugar */}
<View
className={cn("h-32 w-32 items-center justify-center rounded-full")}
style={{ backgroundColor: bloodSugarColors.background }}
>
<Text className="mb-1 text-xs" style={{ color: bloodSugarColors.text }}>
9:40 AM
</Text>
<View className="flex-row items-baseline">
<Text
className="text-3xl font-bold"
style={{ color: bloodSugarColors.text }}
>
{bloodSugar}
</Text>
<Text
className="ml-1 text-sm"
style={{ color: bloodSugarColors.text }}
>
</Text>
</View>
<Text className="mt-1 text-xs" style={{ color: bloodSugarColors.text }}>
mg/dL
</Text>
</View>

{/* Macros */}
<View className="flex-row items-center justify-center gap-4">
<Text className="text-sm font-medium">Daily Macros:</Text>
<View className="flex-row gap-2">
{mockMacrosData.map((macro, index) => (
<MacroItem key={index} {...macro} />
))}
</View>
</View>
</View>
);
}
41 changes: 10 additions & 31 deletions apps/expo/src/components/home/overview-pager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,25 @@ import Animated, {
} from "react-native-reanimated";

import PagingDots from "~/components/paging/paging-dots";
import { Text } from "~/components/ui/text";
import usePagerScrollHandler from "~/hooks/use-page-scroll-handler";

const AnimatedPagerView = Animated.createAnimatedComponent(PagerView);

const INTRO_DATA = [
{
key: "1",
title: "App showcase ✨",
description:
"Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
},
{
key: "2",
title: "Introduction screen 🎉",
description:
"Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. ",
},
{
key: "3",
title: "And can be anything 🎈",
description:
"Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. ",
},
];
const OverviewPager = (props: { children: React.ReactNode }) => {
const { children } = props;

const OverviewPager = () => {
const { width } = useWindowDimensions();
const ref = React.useRef<PagerView>(null);
const positionSharedValue = useSharedValue(0);
const scrollOffsetSharedValue = useSharedValue(0);

const widgetCount = React.Children.count(children);

const scrollX = useDerivedValue(() => {
const interpolatedValue = interpolate(
positionSharedValue.value + scrollOffsetSharedValue.value,
[0, INTRO_DATA.length],
[0, INTRO_DATA.length * width],
[0, widgetCount],
[0, widgetCount * width],
{
extrapolateRight: Extrapolation.CLAMP,
},
Expand All @@ -72,17 +54,14 @@ const OverviewPager = () => {
orientation="horizontal"
useNext={false}
>
{INTRO_DATA.map(({ key }) => (
<View
key={key}
className="content-center items-center justify-center p-5"
>
<Text>{`Page Index: ${key}`}</Text>
{React.Children.map(children, (child, index) => (
<View key={index} className="flex-1 justify-center">
{child}
</View>
))}
</AnimatedPagerView>
<View>
<PagingDots data={INTRO_DATA} scrollX={scrollX} dotType="expanding" />
<PagingDots count={widgetCount} scrollX={scrollX} dotType="expanding" />
</View>
</View>
);
Expand Down
40 changes: 40 additions & 0 deletions apps/expo/src/components/home/temp-widget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";
import { View } from "react-native";

import { Text } from "~/components/ui/text";

const INTRO_DATA = [
{
key: "1",
title: "App showcase ✨",
description:
"Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
},
{
key: "2",
title: "Introduction screen 🎉",
description:
"Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. ",
},
{
key: "3",
title: "And can be anything 🎈",
description:
"Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. ",
},
];

const TempWidget = () => {
return (
<View>
{INTRO_DATA.map((item) => (
<View key={item.key} className="p-4">
<Text className="mb-2 text-xl font-bold">{item.title}</Text>
<Text className="text-base">{item.description}</Text>
</View>
))}
</View>
);
};

export { TempWidget };
6 changes: 3 additions & 3 deletions apps/expo/src/components/paging/expanding-dot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Animated, {

import type { PagingDotsProps } from "./paging-dots";

type Props = Omit<PagingDotsProps, "data" | "style" | "dotType"> & {
type Props = Omit<PagingDotsProps, "count" | "style" | "dotType"> & {
index: number;
};

Expand All @@ -19,11 +19,11 @@ const ExpandingDot: React.FC<Props> = ({
dotStyle,
inactiveDotOpacity = 0.5,
inactiveDotColor = "#347af0",
expandingDotWidth = 20,
expandingDotWidth = 32,
activeDotColor = "#347af0",
}) => {
const { width } = useWindowDimensions();
const dotWidth = (dotStyle?.width as number) || 10;
const dotWidth = (dotStyle?.width as number) || 16;

const inputRange = [(index - 1) * width, index * width, (index + 1) * width];

Expand Down
28 changes: 21 additions & 7 deletions apps/expo/src/components/paging/paging-dots.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import type { StyleProp, ViewStyle } from "react-native";
import type { SharedValue } from "react-native-reanimated";
import { StyleSheet, View } from "react-native";
import colors, { black, white } from "tailwindcss/colors";

import { useColorScheme } from "~/lib/use-color-scheme";
import ExpandingDot from "./expanding-dot";
import ScalingDot from "./scaling-dot";

export interface PagingDotsProps {
data: object[];
count: number;
scrollX: SharedValue<number>;
dotStyle?: ViewStyle;
inactiveDotOpacity?: number;
Expand All @@ -15,22 +17,34 @@ export interface PagingDotsProps {
activeDotColor?: string;
expandingDotWidth?: number;
style?: StyleProp<ViewStyle>;
dotType?: "scaling" | "expanding" | null | undefined;
dotType?: "expanding" | "scaling" | null | undefined;
}

const PagingDots: React.FC<PagingDotsProps> = ({
data,
count,
style,
dotType = "scaling",
dotType = "expanding",
...rest
}) => {
const { colorScheme } = useColorScheme();
const isDark = colorScheme === "dark";

const DotComponent = dotType === "expanding" ? ExpandingDot : ScalingDot;

const inactiveDotColor = isDark ? colors.gray[500] : colors.gray[300];
const activeDotColor = isDark ? white : black;

return (
<View style={[styles.container, style]}>
{data.map((_, index) => {
return <DotComponent key={`dot-${index}`} index={index} {...rest} />;
})}
{Array.from({ length: count }).map((_, index) => (
<DotComponent
key={`dot-${index}`}
index={index}
inactiveDotColor={inactiveDotColor}
activeDotColor={activeDotColor}
{...rest}
/>
))}
</View>
);
};
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/src/components/paging/scaling-dot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Animated, {

import type { PagingDotsProps } from "./paging-dots";

type Props = Omit<PagingDotsProps, "data" | "style" | "dotType"> & {
type Props = Omit<PagingDotsProps, "count" | "style" | "dotType"> & {
index: number;
};

Expand Down
Loading

0 comments on commit a82de0f

Please sign in to comment.