Skip to content

NutriHub Mobile App Development Documentation

Onur edited this page May 8, 2025 · 1 revision

NutriHub Mobile App Development Documentation

Table of Contents


Codebase Structure and Architecture

Overview

NutriHub is a mobile application designed to educate users on affordable food options, meal preparation, and nutrition. The app aims to help users find budget-friendly grocery options, learn nutritious meal preparation techniques, and connect with local food resources. Built with React Native and Expo, NutriHub offers a cross-platform solution for both iOS and Android devices.

Current Features

  • Food catalog with nutritional information and scoring
  • Forum screen for posting recipes, nutritional tips and posts
  • Login screen with user authentication

Technology Stack

  • Framework: React Native with Expo
  • Language: TypeScript

Project Structure

src/
├── api/                     # API service layer (planned)
├── assets/                  # Static assets like images
├── components/              # Reusable UI components
│   ├── common/              # Generic UI components
│   ├── food/                # Food-specific components
│   └── forum/               # Forum-specific components
├── constants/               # Application constants
│   ├── foodConstants.ts     # Food-related constants
│   ├── forumConstants.ts    # Forum-related constants
│   └── theme.ts             # Theme constants
├── context/                 # React context providers
│   ├── AuthContext.tsx      # Authentication context
│   └── ThemeContext.tsx     # Theming context
├── hooks/                   # Custom React hooks
│   ├── useForm.ts           # Form handling hook
│   └── useFoodFilters.ts    # Food filtering hook
├── navigation/              # Navigation configuration
│   ├── AppNavigator.tsx     # Main app navigator
│   ├── MainTabNavigator.tsx # Tab navigation
│   └── types.ts             # Navigation type definitions
├── screens/                 # Application screens
│   ├── auth/                # Authentication screens
│   ├── food/                # Food-related screens
│   └── forum/               # Forum-related screens
├── services/                # Business logic services (planned)
├── types/                   # TypeScript type definitions
│   └── types.ts             # Common type definitions
└── utils/                   # Utility functions
    └── validation.ts        # Form validation utilities

Design System

Theme Structure

The app uses a hierarchical token-based design system defined in constants/theme.ts:

  1. Base Palette: Raw color values organized by color families:

    export const PALETTE = {
      PRIMARY: { DEFAULT: '#0B7A5C', LIGHT: '#12A97F', DARK: '#06624A' },
      SECONDARY: { DEFAULT: '#007AFF', LIGHT: '#4DA3FF', DARK: '#0055B3' },
      // ...additional color definitions
    };
  2. Semantic Tokens: Application-level tokens that map to UI contexts:

    export const LIGHT_THEME: Theme = {
      background: PALETTE.AMBER.DEFAULT,
      surface: PALETTE.NEUTRAL.WHITE,
      text: PALETTE.NEUTRAL.GRAY_900,
      // ...additional semantic mappings
    };
  3. Component-specific Values: Special purpose tokens for specific components.

The design system includes consistent definitions for:

  • Colors (light and dark themes)
  • Typography scales
  • Spacing constants
  • Border radius values
  • Shadow styles

Theme Context

The ThemeContext provides theme values and functionality throughout the app:

  • Current theme type ('light' or 'dark')
  • Theme colors based on current theme
  • Pre-computed text styles
  • Theme toggling functionality

Key Components

Common Components

Button

A flexible button component with multiple variants, sizes, and states:

  • Supports primary, secondary, outline, danger, success, and text variants
  • Multiple size options (small, default, large)
  • Optional icons with position control
  • Loading state support
  • Accessibility properties
<Button
  title="Submit"
  onPress={handleSubmit}
  variant="primary"
  size="large"
  fullWidth
  iconName="check"
  iconPosition="left"
/>

Card

A container component for displaying content with consistent styling:

  • Optional header and footer sections
  • Pressable capability
  • Elevation/shadow options
  • Customizable styling
<Card
  header={<Text>Card Title</Text>}
  footer={<Button title="Action" onPress={handleAction} />}
  onPress={handleCardPress}
  elevated
>
  <Text>Card content</Text>
</Card>

TextInput

A customizable text input component:

  • Label and helper text support
  • Error state display
  • Icon support
  • Password visibility toggle
  • Clear button option
<TextInput
  label="Email"
  value={email}
  onChangeText={setEmail}
  error={errors.email}
  iconName="email"
  keyboardType="email-address"
/>

Food Components

FoodItem

Displays food item information in multiple layout variants:

  • List layout for compact display
  • Grid layout for visual browsing
  • Detailed layout for comprehensive information
  • Shows nutrition score, dietary options, and price
  • Supports touch interaction
<FoodItem
  item={foodItem}
  onPress={handleFoodPress}
  variant="grid"
  showNutritionScore
  showDietaryOptions
  showPrice
/>

Forum Components

ForumPost

Displays forum posts with interaction options:

  • Author information and post date
  • Content preview with "read more" functionality
  • Tag badges
  • Like, comment, and share actions
  • Press interaction for post details
<ForumPost
  post={post}
  onPress={handlePostPress}
  onLike={handlePostLike}
  onComment={handlePostComment}
  onShare={handlePostShare}
  preview
  showTags
/>

Screens

Authentication Screens

LoginScreen

Handles user authentication:

  • Email and password input with validation
  • Error messaging
  • Loading state display
  • "Forgot password" and "Sign up" options

Food Screens

FoodScreen

Displays the food catalog with filtering and sorting:

  • Search functionality
  • Layout toggle (grid/list)
  • Sorting options
  • Empty state handling

Forum Screens

ForumScreen

Shows the community forum:

  • Post listing
  • New post creation button
  • Post interaction (like, comment, share)

Data Management

Context Providers

AuthContext

Manages authentication state:

  • User login and logout
  • Registration (planned)
  • Auth state persistence
  • Loading and error states

ThemeContext

Manages theme selection:

  • Light/dark theme switching
  • Theme persistence
  • Theme value access

Custom Hooks

useForm

Handles form state, validation, and submission:

  • Field values and errors
  • Touched field tracking
  • Validation rule application
  • Form submission handling
const {
  values,
  errors,
  touched,
  handleChange,
  handleBlur,
  handleSubmit,
  isValid,
  isSubmitting
} = useForm({
  initialValues: { email: '', password: '' },
  validationRules,
  onSubmit: handleLogin
});

useFoodFilters

Manages food item filtering and sorting:

  • Name filtering
  • Category filtering
  • Dietary option filtering
  • Price range filtering
  • Nutrition score filtering
  • Sorting options
const {
  filteredItems,
  setNameFilter,
  setCategoryFilter,
  setDietaryOptions,
  setPriceRange,
  setSortOption
} = useFoodFilters(foodItems);

Navigation

The app uses React Navigation with a structure consisting of:

  1. AppNavigator: The root navigator that handles authentication state

    • Shows LoginScreen when not logged in
    • Shows MainTabNavigator when logged in
  2. MainTabNavigator: Bottom tab navigation for main app sections

    • Home tab
    • Food tab
    • Forum tab

Additional nested navigators will be implemented as needed for section-specific flows.

Planned Implementations

API Integration

A structured API layer will be implemented to handle server communication:

  • Base API client with authentication handling
  • Endpoint-specific services
  • Request/response typing

Additional Screens

Planned screens to be implemented:

  • Registration Screen
  • Food Detail Screen
  • Forum Post Detail Screen
  • Forum Post Creation Screen
  • User Profile Screen

Services Layer

Business logic will be extracted into dedicated service modules:

  • Food Service (nutrition calculations, food filtering)
  • Forum Service (post interactions, content filtering)
  • User Service (profile management)

Key Concepts and Patterns

Component Composition

The application uses composition over inheritance for UI components:

  • Base components (Button, Card, TextInput) are composed to create more complex components
  • Component props allow for customization and extension

Theming and Styling

A consistent approach to theming and styling:

  • Theme context for global theme access
  • Semantic color naming for maintainability
  • Consistent spacing and sizing scales
  • Component-specific styling through props

Form Handling

A standardized approach to form handling:

  • useForm hook for form state management
  • Validation rules for field validation
  • Consistent error messaging

Type Safety

Strong TypeScript typing throughout the application:

  • Interface definitions for data models
  • Type definitions for component props
  • Type safety for navigation parameters
  • Enum and const types for constants

Contribution Guidelines

Introduction

This document provides guidelines for contributing to the NutriHub mobile app. It outlines the development workflow, coding standards, and best practices to ensure consistency and maintainability of the codebase. Following these guidelines will help maintain the extensibility of the application and make collaboration smoother for all team members.

Development Environment Setup

Prerequisites

To develop the NutriHub mobile app, you need the following tools:

  • Node.js & npm: Current LTS version
  • Expo CLI: For running and building the app
  • Visual Studio Code (recommended): With React Native and TypeScript extensions
  • Git: For version control

Getting Started

  1. Clone the repository:

    git clone https://github.com/bounswe/bounswe2025group9.git
    cd bounswe2025group9/mobile/nutrihub
  2. Install dependencies:

    npm install
  3. Start the development server:

    npx expo start
  4. Run on a device or emulator:

    • Scan the QR code with Expo Go on your device
    • Press 'a' for Android emulator
    • Press 'i' for iOS simulator

Project Structure and Architecture

NutriHub follows a structured architecture with clear separation of concerns. Familiarize yourself with the Codebase Structure and Architecture section above for a detailed overview.

Development Workflow

Branching Strategy

  • main: protected branch
  • Feature branches: Created from main for individual features
  • See the git contribution guide wiki page for more detail

Branch Naming Convention

Use the following pattern for branch names:

  • feature/[feature-name]: For new features
  • bugfix/[bug-name]: For bug fixes

Commit Message Guidelines

Write clear, descriptive commit messages:

  • Start with a capitalized verb
  • Keep the first line under 50 characters
  • Include a detailed description if necessary
  • Reference issue numbers when applicable

Example:

Add forum post creation screen

- Implement form for creating new posts
- Add validation for required fields
- Include tag selection functionality

Fixes #123

Pull Request Process

  1. Create a pull request from your feature branch to develop
  2. Fill out the PR template with:
    • Description of changes
    • Screenshot/video (for UI changes)
    • Testing performed
    • Related issues
  3. Request reviews from team members
  4. Address review comments
  5. Merge once approved and CI checks pass

Coding Standards

TypeScript Guidelines

  • Use TypeScript for all new files
  • Define interfaces for all data models
  • Use type annotations for function parameters and return types
  • Avoid using any type
  • Use union types for variables with multiple potential types
// Good
interface User {
  id: number;
  name: string;
  email: string;
}

function getUser(id: number): User | null {
  // implementation
}

// Avoid
function getUser(id): any {
  // implementation
}

React & React Native Guidelines

  • Use functional components with hooks
  • Extract reusable logic into custom hooks
  • Break down complex components into smaller, focused components
  • Use PascalCase for component names
  • Use camelCase for variables, functions, and instances
// Good
const UserProfile: React.FC<UserProfileProps> = ({ user }) => {
  const { theme } = useTheme();
  
  return (
    <View style={{ backgroundColor: theme.background }}>
      {/* component content */}
    </View>
  );
};

// Avoid
function userProfile(props) {
  const theme = useTheme().theme;
  
  return (
    <View style={{ backgroundColor: theme.background }}>
      {/* component content */}
    </View>
  );
}

File Structure

  • One component per file
  • Place related components in the same directory
  • Use index files to export multiple components from a directory
  • Keep files relatively small (under 300 lines when possible)

Naming Conventions

  • Files: Use PascalCase for components, camelCase for utilities
  • Components: Use PascalCase (e.g., Button.tsx)
  • Hooks: Use camelCase with use prefix (e.g., useForm.ts)
  • Contexts: Use PascalCase with Context suffix (e.g., ThemeContext.tsx)
  • Utilities: Use camelCase (e.g., validation.ts)

Import Order

Organize imports in the following order:

  1. React/React Native imports
  2. Third-party library imports
  3. Absolute imports from the project
  4. Relative imports

Separate each group with a blank line.

import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';

import { useNavigation } from '@react-navigation/native';
import { SafeAreaView } from 'react-native-safe-area-context';

import { SPACING } from '../../constants/theme';
import { useTheme } from '../../context/ThemeContext';

import Button from '../common/Button';
import TextInput from '../common/TextInput';

Theme System Usage

Using Theme Values

Always use the theme context to access theme values:

// Good
const { theme, textStyles } = useTheme();

<View style={{ backgroundColor: theme.background }}>
  <Text style={[styles.title, textStyles.heading2]}>Title</Text>
</View>

// Avoid
<View style={{ backgroundColor: '#FEFCE8' }}>
  <Text style={[styles.title, { fontSize: 28, fontWeight: 'bold' }]}>Title</Text>
</View>

Extending the Theme

When adding new theme values:

  1. Add the property to the Theme interface in constants/theme.ts
  2. Add the value to both LIGHT_THEME and DARK_THEME objects
  3. Document the purpose of the new theme property
// Add to Theme interface
export interface Theme {
  // existing properties
  newProperty: string;
}

// Add to both theme objects
export const LIGHT_THEME: Theme = {
  // existing properties
  newProperty: PALETTE.PRIMARY.LIGHT,
};

export const DARK_THEME: Theme = {
  // existing properties
  newProperty: PALETTE.PRIMARY.DARK,
};

Component Development

Creating New Components

When creating a new component:

  1. Place it in the appropriate directory (common, food, forum, etc.)
  2. Define a clear props interface with JSDoc comments
  3. Use the theme system for styling
  4. Include comprehensive JSDoc documentation
  5. Export the component as the default export
/**
 * CustomComponent
 * 
 * Description of what the component does.
 * 
 * Usage:
 * ```tsx
 * <CustomComponent 
 *   property="value"
 *   onEvent={handleEvent}
 * />
 * ```
 */

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { useTheme } from '../../context/ThemeContext';
import { SPACING } from '../../constants/theme';

interface CustomComponentProps {
  /**
   * Description of the property
   */
  property: string;
  
  /**
   * Event handler for when something happens
   */
  onEvent?: () => void;
}

const CustomComponent: React.FC<CustomComponentProps> = ({
  property,
  onEvent,
}) => {
  const { theme, textStyles } = useTheme();
  
  return (
    <View style={[styles.container, { backgroundColor: theme.surface }]}>
      <Text style={textStyles.body}>{property}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: SPACING.md,
  },
});

export default CustomComponent;

Extending Existing Components

When extending an existing component:

  1. Maintain backward compatibility
  2. Add new props as optional
  3. Document new functionality
  4. Update unit tests

Component Testing

For each component:

  1. Test primary functionality
  2. Test edge cases
  3. Test accessibility features

Screen Development

Creating New Screens

When creating a new screen:

  1. Place it in the appropriate directory (auth, food, forum, etc.)
  2. Use existing components when possible
  3. Keep business logic separate from UI
  4. Add the screen to the appropriate navigator
/**
 * NewScreen
 * 
 * Description of what the screen does.
 */

import React, { useState, useCallback } from 'react';
import { View, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useTheme } from '../../context/ThemeContext';
import { SPACING } from '../../constants/theme';

// Import components
import Button from '../../components/common/Button';
import TextInput from '../../components/common/TextInput';

const NewScreen: React.FC = () => {
  const { theme, textStyles } = useTheme();
  
  // Implementation...
  
  return (
    <SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
      {/* Screen content */}
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  // Additional styles...
});

export default NewScreen;

Navigation

When implementing navigation:

  1. Define types for route parameters
  2. Use type-safe navigation
  3. Add meaningful transition animations when appropriate
// In types.ts
export type StackParamList = {
  Home: undefined;
  Details: { id: number; title: string };
};

// In component
import { useNavigation, RouteProp } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import { StackParamList } from '../navigation/types';

type DetailsScreenNavigationProp = StackNavigationProp<StackParamList, 'Details'>;
type DetailsScreenRouteProp = RouteProp<StackParamList, 'Details'>;

const Component: React.FC = () => {
  const navigation = useNavigation<DetailsScreenNavigationProp>();
  
  const handlePress = () => {
    navigation.navigate('Details', { id: 123, title: 'Item Title' });
  };
  
  // Implementation...
};

Documentation

Code Documentation

  • Use JSDoc comments for functions, components, and interfaces
  • Document all props for components
  • Include usage examples for complex components
  • Explain non-obvious code with inline comments
/**
 * Calculates a nutrition score based on nutritional content.
 * 
 * The score is calculated using:
 * - 30% from protein content
 * - 30% from carbohydrate quality
 * - 40% from overall nutrient balance
 * 
 * @param {NutritionData} data - The nutritional data
 * @returns {number} A score from 0-10, with 10 being the highest quality
 */
function calculateNutritionScore(data: NutritionData): number {
  // Implementation...
}

Documentation Updates

When making changes:

  1. Update relevant documentation to reflect your changes
  2. Add documentation for new features
  3. Update examples if APIs change
  4. Update the README if necessary

Performance Considerations

Rendering Optimization

  • Use useMemo to memoize expensive calculations
  • Use useCallback to prevent unnecessary re-renders
  • Use React.memo for pure components
  • Use FlatList for rendering long lists
  • Optimize images and assets
// Memoize expensive calculations
const expensiveValue = useMemo(() => {
  return someExpensiveCalculation(a, b);
}, [a, b]);

// Memoize callback functions
const handlePress = useCallback(() => {
  // handle press logic
}, [dependency]);

Avoiding Common Pitfalls

  • Avoid defining functions inside render methods
  • Avoid creating new objects/arrays in render
  • Use proper dependency arrays in hooks
  • Minimize the use of useEffect

Updating Documentation

When making significant changes to the codebase:

  1. Update the Codebase Structure document if architecture changes
  2. Update component usage examples if APIs change
  3. Update this Contribution Guide if processes change
  4. Add documentation for new features

Troubleshooting

Common Issues and Solutions

  • Metro bundler issues: Clear cache with npx expo start --clear
  • Dependency conflicts: Check for version mismatches in package.json
  • TypeScript errors: Ensure types are correctly defined
  • React Native version issues: Ensure Expo SDK compatibility

Getting Help

If you encounter issues:

  1. Check existing documentation
  2. Search project issues on GitHub
  3. Ask in the team communication channel
  4. Create an issue if no solution is found
Clone this wiki locally