Skip to content

kinshukkush/FARMER-EATS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Typing SVG

Expo React Native JavaScript Axios

Platform Navigation Screens API


πŸ“‹ Table of Contents


🌟 About the Project

About

FarmerEats is a full-featured mobile application built as part of a practical assignment for sowlab.com. It creates a direct bridge between local farmers and consumers, enabling farmers to register their business, set operating hours, upload verification documents, and manage their farm profile.

The app is built using React Native with Expo SDK 54, integrating REST APIs, multi-step registration flows, JWT authentication, and secure local storage β€” all with a premium, polished design.

🎯 Assignment Objectives Covered

  • βœ… Splash Screen with animated intro
  • βœ… 3-slide Onboarding carousel with animated dot indicators
  • βœ… Login with email/password + JWT token storage
  • βœ… 5-step Farmer Registration flow with data accumulation
  • βœ… Forgot Password β†’ OTP Verification β†’ Reset Password
  • βœ… Home Dashboard with user stats
  • βœ… Full API integration with sowlab.com/assignment
  • βœ… Custom reusable component library

✨ Features

Feature Description Status
πŸ” JWT Authentication Secure login with token persistence via AsyncStorage βœ… Done
πŸ“‹ 5-Step Registration Multi-screen form with shared state via module-level object βœ… Done
πŸ“± Onboarding Carousel Horizontal FlatList with animated expanding dots βœ… Done
πŸ”‘ Forgot Password Flow Mobile OTP β†’ 6-digit verify β†’ reset with strength meter βœ… Done
πŸ“„ Document Upload Business registration proof via expo-document-picker βœ… Done
πŸ• Business Hours Day-by-day time slot selector with schedule summary βœ… Done
πŸ—ΊοΈ State Dropdown All 50 US states with custom dropdown (no external lib) βœ… Done
πŸ’ͺ Password Strength Real-time visual strength indicator (weak/medium/strong) βœ… Done
🎨 Custom Components Reusable CustomInput, CustomButton, StepIndicator βœ… Done
🌿 Brand Design System Consistent colors, fonts (BeVietnamPro), spacing tokens βœ… Done

πŸ—οΈ App Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    index.js                          β”‚
β”‚            registerRootComponent(App)                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     App.js                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Fonts Loader  β”‚   β”‚  GestureHandlerRootView  β”‚  β”‚
β”‚  β”‚ (BeVietnamPro) β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚    AuthProvider      β”‚ β”‚  β”‚
β”‚                       β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚ β”‚  β”‚
β”‚                       β”‚  β”‚  β”‚  AppNavigator  β”‚  β”‚ β”‚  β”‚
β”‚                       β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ β”‚  β”‚
β”‚                       β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚  β”‚
β”‚                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Stack Navigator (12 screens)            β”‚
β”‚                                                      β”‚
β”‚  Splash β†’ Onboarding β†’ Login β†’ Register(1β†’5)        β”‚
β”‚  ForgotPassword β†’ OTP β†’ ResetPassword β†’ Home        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Data Layer                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ AuthContext β”‚  β”‚  authApi  β”‚  β”‚ registerData β”‚  β”‚
β”‚  β”‚ (JWT token) β”‚  β”‚  (axios)  β”‚  β”‚ (shared obj) β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“± Screen Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     2.8s      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    swipe/skip
β”‚  SPLASH  β”‚ ──────────── β–Άβ”‚  ONBOARDING β”‚ ──────────────▢
β”‚  🌿      β”‚               β”‚ 3 slides    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                    β”‚
                                                    β–Ό
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚                    LOGIN                         β”‚
     β”‚  email + password β†’ POST /user/login β†’ JWT      β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                         β”‚
         REGISTER                 FORGOT PASSWORD
              β”‚                         β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚   Register Step 1 β”‚     β”‚  Forgot Password  β”‚
     β”‚   Personal Info   β”‚     β”‚  Mobile Number    β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                         β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚   Register Step 2 β”‚     β”‚    OTP Screen     β”‚
     β”‚   Farm/Business   β”‚     β”‚   6-digit verify  β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                         β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚   Register Step 3 β”‚     β”‚  Reset Password   β”‚
     β”‚   Document Upload β”‚     β”‚  Strength meter   β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚   Register Step 4 β”‚
     β”‚   Business Hours  β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚   Register Step 5 β”‚ ──────▢│    HOME     β”‚
     β”‚   Review+Submit   β”‚        β”‚  Dashboard  β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ Tech Stack

Core Framework

React Native Expo JavaScript

Navigation & UI

React Navigation Gesture Handler Linear Gradient

Fonts & Assets

BeVietnamPro Vector Icons

Networking & Storage

Axios AsyncStorage

File & Media

Document Picker Image Picker


πŸ“ Project Structure

FarmerEatsApp/
β”‚
β”œβ”€β”€ πŸ“„ index.js                    # Entry point (registerRootComponent)
β”œβ”€β”€ πŸ“„ App.js                      # Root: fonts + providers + navigator
β”œβ”€β”€ πŸ“„ app.json                    # Expo config (name, icons, splash)
β”œβ”€β”€ πŸ“„ babel.config.js             # Babel transpiler config
β”œβ”€β”€ πŸ“„ package.json                # Dependencies
β”‚
β”œβ”€β”€ πŸ“‚ assets/                     # App icons, splash, adaptive icons
β”‚
└── πŸ“‚ src/
    β”‚
    β”œβ”€β”€ πŸ“‚ api/
    β”‚   └── authApi.js             # All REST API calls (axios)
    β”‚       β”œβ”€β”€ loginUser()
    β”‚       β”œβ”€β”€ registerUser()
    β”‚       β”œβ”€β”€ forgotPassword()
    β”‚       β”œβ”€β”€ verifyOTP()
    β”‚       └── resetPassword()
    β”‚
    β”œβ”€β”€ πŸ“‚ context/
    β”‚   └── AuthContext.js         # JWT token state, login/logout
    β”‚
    β”œβ”€β”€ πŸ“‚ navigation/
    β”‚   └── AppNavigator.js        # Stack navigator, screen definitions
    β”‚
    β”œβ”€β”€ πŸ“‚ theme/
    β”‚   └── colors.js              # Design token: primary, secondary, etc.
    β”‚
    β”œβ”€β”€ πŸ“‚ components/             # Reusable UI components
    β”‚   β”œβ”€β”€ CustomButton.js        # Primary/outline/secondary variants
    β”‚   β”œβ”€β”€ CustomInput.js         # Input with icon, error, eye toggle
    β”‚   └── StepIndicator.js       # Progress dots for registration
    β”‚
    └── πŸ“‚ screens/                # 12 screens
        β”œβ”€β”€ SplashScreen.js        # Animated logo entry (2.8s)
        β”œβ”€β”€ OnboardingScreen.js    # 3-slide horizontal onboarding
        β”œβ”€β”€ LoginScreen.js         # Email/password login
        β”œβ”€β”€ RegisterStep1Screen.js # Personal info + shared registerData{}
        β”œβ”€β”€ RegisterStep2Screen.js # Farm/business info + US state picker
        β”œβ”€β”€ RegisterStep3Screen.js # Document upload (expo-document-picker)
        β”œβ”€β”€ RegisterStep4Screen.js # Business hours (day Γ— time slot grid)
        β”œβ”€β”€ RegisterStep5Screen.js # Review + FormData multipart submit
        β”œβ”€β”€ ForgotPasswordScreen.js# Mobile number input
        β”œβ”€β”€ OTPScreen.js           # 6-box OTP input with auto-focus
        β”œβ”€β”€ ResetPasswordScreen.js # New password + strength indicator
        └── HomeScreen.js          # Dashboard with stats and quick actions

πŸš€ Getting Started

Prerequisites

node >= 18.x
npm >= 9.x
Expo Go app on your Android/iOS device

Installation

# 1. Clone the repo (or navigate to project folder)
cd "FarmerEatsApp"

# 2. Install dependencies
npm install --legacy-peer-deps

# 3. Start Metro bundler with cleared cache
npx expo start --clear

# 4. Scan the QR code with Expo Go app
#    OR press 'a' for Android, 'w' for web

Common Issues & Fixes

Problem Solution
White screen on Expo Go Ensure newArchEnabled: false in app.json
babel-preset-expo not found Run npm install babel-preset-expo --save-dev
Terminal hangs on press a Old Expo process still running β€” open new terminal
Cannot find module 'worklets' Don't use react-native-reanimated@^4.x with Expo Go
Fonts not loading Clear cache: npx expo start --clear

πŸ”Œ API Reference

Base URL: https://sowlab.com/assignment

Endpoint Method Description Auth
/user/login POST Login with email + password ❌
/user/register POST Register new farmer (multipart) ❌
/user/forgot-password POST Send OTP to mobile ❌
/user/verify-otp POST Verify 6-digit OTP ❌
/user/reset-password POST Set new password with token ❌

Login Request Body

{
  "email": "farmer@example.com",
  "password": "password123",
  "role": "farmer",
  "device_token": "expo_device_token",
  "type": "email"
}

Register (FormData fields)

full_name, email, phone, password, role,
business_name, informal_name, address, city,
state, zip_code, business_hours (JSON string),
device_token, type, registration_proof (file)

🎨 Design System

Color Palette

Token Hex Usage
primary #D5715B Buttons, active states, brand
secondary #F2C94C Highlights, accents
tertiary #5EA25F Success, green badges
dark #261C12 Body text, headings
white #FFFFFF Backgrounds
inputBg rgba(38,28,18,0.08) Input field backgrounds
error #E53935 Error states, validation

Typography

All text uses BeVietnamPro (Google Fonts) with 4 weights:

Weight Font Name Usage
400 BeVietnamPro_400Regular Body text, subtitles
500 BeVietnamPro_500Medium Labels, secondary text
600 BeVietnamPro_600SemiBold Links, emphasized text
700 BeVietnamPro_700Bold Headings, buttons, brand

πŸ‘¨β€πŸ’» Developer

Kinshuk Saxena

Typing SVG

GitHub LinkedIn Portfolio Email Phone


Made with ❀️ and 🌿 by Kinshuk Saxena

⭐ Star this repo if you found it helpful! ⭐

Followers

About

🌿 FarmerEats - Farm-to-Table Mobile Marketplace App | React Native + Expo SDK 54 | Complete authentication flow with 5-step farmer registration, JWT authentication, document upload, business hours selector, and OTP verification. Built for sowlab.com assignment with clean architecture and professional UI.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors