track meal and add water implemented
This commit is contained in:
1 parent
b0d751540e
commit
ec370a3c17
169 files changed
+17981
-5
No files matched your search
@@ -1,15 +1,23 @@
|
||||
import { View, Text, StyleSheet, ScrollView, RefreshControl, Image } from "react-native";
|
||||
import { useUser } from "@clerk/clerk-expo";
|
||||
import { LinearGradient } from "expo-linear-gradient";
|
||||
import { useState, useCallback } from "react";
|
||||
import { useState, useCallback, useEffect } from "react";
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { theme } from "../../styles/theme";
|
||||
import { ActivityWidget } from "../../components/ActivityWidget";
|
||||
import { QuickActionGrid } from "../../components/QuickActionGrid";
|
||||
import { TrackMealModal } from "../../components/TrackMealModal";
|
||||
import { AddWaterModal } from "../../components/AddWaterModal";
|
||||
import { HydrationWidget } from "../../components/HydrationWidget";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
|
||||
export default function HomeScreen() {
|
||||
const { user } = useUser();
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [trackMealModalVisible, setTrackMealModalVisible] = useState(false);
|
||||
const [addWaterModalVisible, setAddWaterModalVisible] = useState(false);
|
||||
const [calories, setCalories] = useState(0);
|
||||
const [waterIntake, setWaterIntake] = useState(0);
|
||||
|
||||
const onRefresh = useCallback(() => {
|
||||
setRefreshing(true);
|
||||
@@ -25,6 +33,65 @@ export default function HomeScreen() {
|
||||
return "Good Evening";
|
||||
};
|
||||
|
||||
const handleSaveMeal = (meal: { type: string; name: string; calories: number }) => {
|
||||
setCalories(prev => prev + meal.calories);
|
||||
setTrackMealModalVisible(false);
|
||||
};
|
||||
|
||||
const handleAddWater = (amount: number) => {
|
||||
setWaterIntake(prev => prev + amount);
|
||||
setAddWaterModalVisible(false);
|
||||
};
|
||||
|
||||
const handleResetCalories = () => {
|
||||
setCalories(0);
|
||||
};
|
||||
|
||||
const handleResetWater = () => {
|
||||
setWaterIntake(0);
|
||||
};
|
||||
|
||||
const resetAllCounters = async () => {
|
||||
setCalories(0);
|
||||
setWaterIntake(0);
|
||||
const today = new Date().toDateString();
|
||||
await AsyncStorage.setItem('lastResetDate', today);
|
||||
};
|
||||
|
||||
// Check for midnight reset
|
||||
useEffect(() => {
|
||||
const checkAndResetIfNeeded = async () => {
|
||||
const lastResetDate = await AsyncStorage.getItem('lastResetDate');
|
||||
const today = new Date().toDateString();
|
||||
|
||||
if (lastResetDate !== today) {
|
||||
await resetAllCounters();
|
||||
}
|
||||
};
|
||||
|
||||
checkAndResetIfNeeded();
|
||||
|
||||
// Calculate time until midnight
|
||||
const now = new Date();
|
||||
const midnight = new Date();
|
||||
midnight.setHours(24, 0, 0, 0);
|
||||
const timeUntilMidnight = midnight.getTime() - now.getTime();
|
||||
|
||||
// Set timer for midnight reset
|
||||
const midnightTimer = setTimeout(async () => {
|
||||
await resetAllCounters();
|
||||
|
||||
// Set up daily interval after first midnight
|
||||
const dailyInterval = setInterval(async () => {
|
||||
await resetAllCounters();
|
||||
}, 24 * 60 * 60 * 1000); // 24 hours
|
||||
|
||||
return () => clearInterval(dailyInterval);
|
||||
}, timeUntilMidnight);
|
||||
|
||||
return () => clearTimeout(midnightTimer);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView
|
||||
@@ -53,12 +120,35 @@ export default function HomeScreen() {
|
||||
{/* Activity Widget */}
|
||||
<ActivityWidget
|
||||
steps={8432}
|
||||
calories={640}
|
||||
calories={calories}
|
||||
duration={45}
|
||||
/>
|
||||
|
||||
{/* Hydration Widget */}
|
||||
<HydrationWidget
|
||||
current={waterIntake}
|
||||
goal={2500}
|
||||
/>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<QuickActionGrid />
|
||||
<QuickActionGrid
|
||||
onTrackMealPress={() => setTrackMealModalVisible(true)}
|
||||
onAddWaterPress={() => setAddWaterModalVisible(true)}
|
||||
/>
|
||||
|
||||
<TrackMealModal
|
||||
visible={trackMealModalVisible}
|
||||
onClose={() => setTrackMealModalVisible(false)}
|
||||
onSave={handleSaveMeal}
|
||||
onResetData={handleResetCalories}
|
||||
/>
|
||||
|
||||
<AddWaterModal
|
||||
visible={addWaterModalVisible}
|
||||
onClose={() => setAddWaterModalVisible(false)}
|
||||
onAdd={handleAddWater}
|
||||
onResetData={handleResetWater}
|
||||
/>
|
||||
|
||||
{/* Recent Activity Section */}
|
||||
<View style={styles.section}>
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { View, Text, StyleSheet, Modal, TouchableOpacity, TextInput, KeyboardAvoidingView, Platform } from 'react-native';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { theme } from '../styles/theme';
|
||||
|
||||
interface AddWaterModalProps {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
onAdd: (amount: number) => void;
|
||||
onResetData?: () => void;
|
||||
}
|
||||
|
||||
const QUICK_AMOUNTS = [
|
||||
{ label: 'Small Glass', amount: 250, icon: 'water-outline' },
|
||||
{ label: 'Large Glass', amount: 500, icon: 'water' },
|
||||
{ label: 'Bottle', amount: 750, icon: 'flask' },
|
||||
];
|
||||
|
||||
export function AddWaterModal({ visible, onClose, onAdd, onResetData }: AddWaterModalProps) {
|
||||
const [customAmount, setCustomAmount] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setCustomAmount('');
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
const handleReset = () => {
|
||||
setCustomAmount('');
|
||||
if (onResetData) {
|
||||
onResetData();
|
||||
}
|
||||
};
|
||||
|
||||
const handleAdd = (amount: number) => {
|
||||
onAdd(amount);
|
||||
setCustomAmount('');
|
||||
};
|
||||
|
||||
const handleCustomAdd = () => {
|
||||
const amount = parseInt(customAmount, 10);
|
||||
if (amount > 0) {
|
||||
handleAdd(amount);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
transparent
|
||||
animationType="slide"
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
style={styles.modalContainer}
|
||||
>
|
||||
<View style={styles.contentContainer}>
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
||||
<Ionicons name="close" size={24} color={theme.colors.gray500} />
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.title}>Add Water</Text>
|
||||
<TouchableOpacity onPress={handleReset}>
|
||||
<Text style={styles.resetText}>Reset</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<Text style={styles.subtitle}>Quick Add</Text>
|
||||
<View style={styles.quickAddContainer}>
|
||||
{QUICK_AMOUNTS.map((item) => (
|
||||
<TouchableOpacity
|
||||
key={item.amount}
|
||||
onPress={() => handleAdd(item.amount)}
|
||||
style={styles.quickAddItem}
|
||||
>
|
||||
<View style={styles.quickAddIcon}>
|
||||
<Ionicons name={item.icon as any} size={24} color={theme.colors.primary} />
|
||||
</View>
|
||||
<Text style={styles.quickAddLabel}>{item.label}</Text>
|
||||
<Text style={styles.quickAddAmount}>{item.amount}ml</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
|
||||
<Text style={styles.subtitle}>Custom Amount</Text>
|
||||
<View style={styles.customInputContainer}>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="e.g., 300"
|
||||
value={customAmount}
|
||||
onChangeText={setCustomAmount}
|
||||
keyboardType="number-pad"
|
||||
placeholderTextColor={theme.colors.gray400}
|
||||
/>
|
||||
<Text style={styles.unit}>ml</Text>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity onPress={handleCustomAdd} style={styles.addButtonContainer}>
|
||||
<LinearGradient
|
||||
colors={theme.gradients.ocean}
|
||||
style={styles.addButton}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
>
|
||||
<Text style={styles.addButtonText}>Add Water</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
modalContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'flex-end',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
contentContainer: {
|
||||
backgroundColor: '#fff',
|
||||
borderTopLeftRadius: 32,
|
||||
borderTopRightRadius: 32,
|
||||
padding: 24,
|
||||
paddingBottom: 40,
|
||||
...theme.shadows.strong,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
title: {
|
||||
fontSize: 24,
|
||||
fontWeight: '700',
|
||||
color: theme.colors.gray900,
|
||||
},
|
||||
closeButton: {
|
||||
padding: 4,
|
||||
},
|
||||
resetText: {
|
||||
fontSize: 16,
|
||||
color: theme.colors.primary,
|
||||
fontWeight: '600',
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: theme.colors.gray700,
|
||||
marginBottom: 16,
|
||||
},
|
||||
quickAddContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 32,
|
||||
gap: 12,
|
||||
},
|
||||
quickAddItem: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
padding: 16,
|
||||
backgroundColor: theme.colors.gray50,
|
||||
borderRadius: 20,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.gray200,
|
||||
},
|
||||
quickAddIcon: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 24,
|
||||
backgroundColor: '#e0f2fe',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginBottom: 8,
|
||||
},
|
||||
quickAddLabel: {
|
||||
fontSize: 12,
|
||||
fontWeight: '600',
|
||||
color: theme.colors.gray800,
|
||||
marginBottom: 2,
|
||||
textAlign: 'center',
|
||||
},
|
||||
quickAddAmount: {
|
||||
fontSize: 12,
|
||||
color: theme.colors.gray500,
|
||||
},
|
||||
customInputContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 32,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.gray50,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.gray200,
|
||||
borderRadius: 16,
|
||||
padding: 16,
|
||||
fontSize: 16,
|
||||
color: theme.colors.gray900,
|
||||
marginRight: 12,
|
||||
},
|
||||
unit: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: theme.colors.gray500,
|
||||
},
|
||||
addButtonContainer: {
|
||||
marginTop: 8,
|
||||
},
|
||||
addButton: {
|
||||
paddingVertical: 16,
|
||||
borderRadius: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
addButtonText: {
|
||||
color: '#fff',
|
||||
fontSize: 18,
|
||||
fontWeight: '700',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,120 @@
|
||||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { theme } from '../styles/theme';
|
||||
|
||||
interface HydrationWidgetProps {
|
||||
current: number; // in ml
|
||||
goal: number; // in ml
|
||||
}
|
||||
|
||||
export function HydrationWidget({ current, goal }: HydrationWidgetProps) {
|
||||
const percentage = Math.min(Math.max(current / goal, 0), 1);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<LinearGradient
|
||||
colors={['#e0f2fe', '#dbeafe']} // Light blue background
|
||||
style={[styles.card, theme.shadows.subtle]}
|
||||
>
|
||||
<View style={styles.content}>
|
||||
<View style={styles.iconContainer}>
|
||||
<LinearGradient
|
||||
colors={theme.gradients.ocean}
|
||||
style={styles.icon}
|
||||
>
|
||||
<Ionicons name="water" size={24} color="#fff" />
|
||||
</LinearGradient>
|
||||
</View>
|
||||
|
||||
<View style={styles.info}>
|
||||
<Text style={styles.title}>Hydration</Text>
|
||||
<Text style={styles.subtitle}>{current} / {goal} ml</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.percentageContainer}>
|
||||
<Text style={styles.percentage}>{Math.round(percentage * 100)}%</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.progressContainer}>
|
||||
<View style={styles.progressBarBg}>
|
||||
<LinearGradient
|
||||
colors={theme.gradients.ocean}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
style={[styles.progressBarFill, { width: `${percentage * 100}%` }]}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginHorizontal: 20,
|
||||
marginBottom: 24,
|
||||
},
|
||||
card: {
|
||||
borderRadius: 24,
|
||||
padding: 20,
|
||||
borderWidth: 1,
|
||||
borderColor: '#bfdbfe',
|
||||
},
|
||||
content: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
iconContainer: {
|
||||
marginRight: 16,
|
||||
},
|
||||
icon: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 16,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
info: {
|
||||
flex: 1,
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
fontWeight: '700',
|
||||
color: theme.colors.gray900,
|
||||
marginBottom: 4,
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
color: theme.colors.gray600,
|
||||
fontWeight: '500',
|
||||
},
|
||||
percentageContainer: {
|
||||
backgroundColor: '#fff',
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 12,
|
||||
},
|
||||
percentage: {
|
||||
fontSize: 14,
|
||||
fontWeight: '700',
|
||||
color: theme.colors.primary,
|
||||
},
|
||||
progressContainer: {
|
||||
height: 8,
|
||||
},
|
||||
progressBarBg: {
|
||||
height: 8,
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.5)',
|
||||
borderRadius: 4,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
progressBarFill: {
|
||||
height: '100%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
});
|
||||
@@ -36,7 +36,12 @@ function QuickActionItem({ icon, label, gradient, onPress }: QuickActionProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export function QuickActionGrid() {
|
||||
interface QuickActionGridProps {
|
||||
onTrackMealPress?: () => void;
|
||||
onAddWaterPress?: () => void;
|
||||
}
|
||||
|
||||
export function QuickActionGrid({ onTrackMealPress, onAddWaterPress }: QuickActionGridProps) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.sectionTitle}>Quick Actions</Text>
|
||||
@@ -50,11 +55,13 @@ export function QuickActionGrid() {
|
||||
icon="restaurant"
|
||||
label="Track Meal"
|
||||
gradient={theme.gradients.success}
|
||||
onPress={onTrackMealPress}
|
||||
/>
|
||||
<QuickActionItem
|
||||
icon="water"
|
||||
label="Add Water"
|
||||
gradient={theme.gradients.ocean}
|
||||
onPress={onAddWaterPress}
|
||||
/>
|
||||
<QuickActionItem
|
||||
icon="scan"
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { View, Text, StyleSheet, Modal, TouchableOpacity, TextInput, KeyboardAvoidingView, Platform, ScrollView } from 'react-native';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { theme } from '../styles/theme';
|
||||
|
||||
interface TrackMealModalProps {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (meal: { type: string; name: string; calories: number }) => void;
|
||||
onResetData?: () => void;
|
||||
}
|
||||
|
||||
const MEAL_TYPES = ['Breakfast', 'Lunch', 'Dinner', 'Snack'];
|
||||
|
||||
export function TrackMealModal({ visible, onClose, onSave, onResetData }: TrackMealModalProps) {
|
||||
const [selectedType, setSelectedType] = useState('Breakfast');
|
||||
const [foodName, setFoodName] = useState('');
|
||||
const [calories, setCalories] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setFoodName('');
|
||||
setCalories('');
|
||||
setSelectedType('Breakfast');
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
const handleReset = () => {
|
||||
setFoodName('');
|
||||
setCalories('');
|
||||
setSelectedType('Breakfast');
|
||||
if (onResetData) {
|
||||
onResetData();
|
||||
}
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
if (!foodName || !calories) return;
|
||||
|
||||
onSave({
|
||||
type: selectedType,
|
||||
name: foodName,
|
||||
calories: parseInt(calories, 10)
|
||||
});
|
||||
|
||||
// Reset form
|
||||
setFoodName('');
|
||||
setCalories('');
|
||||
setSelectedType('Breakfast');
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
transparent
|
||||
animationType="slide"
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
style={styles.modalContainer}
|
||||
>
|
||||
<View style={styles.contentContainer}>
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
||||
<Ionicons name="close" size={24} color={theme.colors.gray500} />
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.title}>Track Meal</Text>
|
||||
<TouchableOpacity onPress={handleReset}>
|
||||
<Text style={styles.resetText}>Reset</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{/* Meal Type Selection */}
|
||||
<Text style={styles.label}>Meal Type</Text>
|
||||
<View style={styles.typeContainer}>
|
||||
{MEAL_TYPES.map((type) => (
|
||||
<TouchableOpacity
|
||||
key={type}
|
||||
onPress={() => setSelectedType(type)}
|
||||
style={[
|
||||
styles.typeButton,
|
||||
selectedType === type && styles.typeButtonActive
|
||||
]}
|
||||
>
|
||||
<Text style={[
|
||||
styles.typeText,
|
||||
selectedType === type && styles.typeTextActive
|
||||
]}>{type}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* Food Name Input */}
|
||||
<Text style={styles.label}>Food Name</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="e.g., Oatmeal with Berries"
|
||||
value={foodName}
|
||||
onChangeText={setFoodName}
|
||||
placeholderTextColor={theme.colors.gray400}
|
||||
/>
|
||||
|
||||
{/* Calories Input */}
|
||||
<Text style={styles.label}>Calories</Text>
|
||||
<View style={styles.caloriesInputContainer}>
|
||||
<TextInput
|
||||
style={[styles.input, styles.caloriesInput]}
|
||||
placeholder="0"
|
||||
value={calories}
|
||||
onChangeText={setCalories}
|
||||
keyboardType="number-pad"
|
||||
placeholderTextColor={theme.colors.gray400}
|
||||
/>
|
||||
<Text style={styles.caloriesUnit}>kcal</Text>
|
||||
</View>
|
||||
|
||||
{/* Save Button */}
|
||||
<TouchableOpacity onPress={handleSave} style={styles.saveButtonContainer}>
|
||||
<LinearGradient
|
||||
colors={theme.gradients.primary}
|
||||
style={styles.saveButton}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
>
|
||||
<Text style={styles.saveButtonText}>Save Meal</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
modalContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'flex-end',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
contentContainer: {
|
||||
backgroundColor: '#fff',
|
||||
borderTopLeftRadius: 32,
|
||||
borderTopRightRadius: 32,
|
||||
padding: 24,
|
||||
minHeight: '60%',
|
||||
...theme.shadows.strong,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
title: {
|
||||
fontSize: 24,
|
||||
fontWeight: '700',
|
||||
color: theme.colors.gray900,
|
||||
},
|
||||
closeButton: {
|
||||
padding: 4,
|
||||
},
|
||||
resetText: {
|
||||
fontSize: 16,
|
||||
color: theme.colors.primary,
|
||||
fontWeight: '600',
|
||||
},
|
||||
label: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: theme.colors.gray700,
|
||||
marginBottom: 12,
|
||||
marginTop: 8,
|
||||
},
|
||||
typeContainer: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: 8,
|
||||
marginBottom: 24,
|
||||
},
|
||||
typeButton: {
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 20,
|
||||
backgroundColor: theme.colors.gray100,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.gray200,
|
||||
},
|
||||
typeButtonActive: {
|
||||
backgroundColor: theme.colors.primaryLight,
|
||||
borderColor: theme.colors.primary,
|
||||
},
|
||||
typeText: {
|
||||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
color: theme.colors.gray600,
|
||||
},
|
||||
typeTextActive: {
|
||||
color: '#fff',
|
||||
fontWeight: '600',
|
||||
},
|
||||
input: {
|
||||
backgroundColor: theme.colors.gray50,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.gray200,
|
||||
borderRadius: 16,
|
||||
padding: 16,
|
||||
fontSize: 16,
|
||||
color: theme.colors.gray900,
|
||||
marginBottom: 24,
|
||||
},
|
||||
caloriesInputContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 32,
|
||||
},
|
||||
caloriesInput: {
|
||||
flex: 1,
|
||||
marginBottom: 0,
|
||||
marginRight: 12,
|
||||
},
|
||||
caloriesUnit: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: theme.colors.gray500,
|
||||
},
|
||||
saveButtonContainer: {
|
||||
marginTop: 'auto',
|
||||
marginBottom: 24,
|
||||
},
|
||||
saveButton: {
|
||||
paddingVertical: 16,
|
||||
borderRadius: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
saveButtonText: {
|
||||
color: '#fff',
|
||||
fontSize: 18,
|
||||
fontWeight: '700',
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
export const API_BASE_URL = __DEV__
|
||||
? 'https://cd1b5e914b16.ngrok-free.app'
|
||||
? 'https://694d46f62d87.ngrok-free.app'
|
||||
: 'https://your-production-url.com'
|
||||
|
||||
export const API_ENDPOINTS = {
|
||||
|
||||
Reference in new issue
Block a user