Skip to content

Repository files navigation

Todo App

A small React Native todo app, themed with the Coinbase palette and built with a lightweight functional core (Result and Option monads).

Features

  • Create / complete / delete todos
  • Inline edit — tap the ✎ pencil to edit a title in place (save on submit/blur, ✓ to confirm, ✕ to cancel)
  • Drag to reorder — drag the ☰ handle up or down; other rows slide to show the drop target (built on PanResponder + Animated, no extra native deps)
  • Validation with feedback — empty or over-long (>100 char) titles are rejected with an inline message instead of being silently dropped
  • Per-item creation timestamp
  • Coinbase theme — Coinbase Blue (#0052FF) accents, navy text, cool grays

Tech stack

  • React Native 0.86, React 19, TypeScript (strict mode)
  • Metro bundler (RN default)
  • react-native-safe-area-context

Project structure

App.tsx                     # Root: SafeAreaProvider + StatusBar
src/
  TodoApp.tsx               # Screen: state, add, validation, list
  DraggableTodoList.tsx     # Drag-to-reorder list (PanResponder + Animated)
  TodoItem.tsx              # Row: checkbox, inline edit, drag handle, delete
  types.ts                  # Todo type
  result.ts                 # Result<E,A> (Either) monad
  option.ts                 # Option<A> (Maybe) monad
  validateTitle.ts          # Title rules composed via Result.flatMap

Functional core

The domain model avoids null/undefined:

  • Result<E, A> (src/result.ts) — success or failure. validateTitle composes validation rules with flatMap, short-circuiting on the first error.
  • Option<A> (src/option.ts) — presence or absence. Used for nullable state (validation error, drag state) so absence is explicit.

JSX "render nothing" sentinels ({cond ? <X/> : null}) and library-required nullish values are intentionally left as-is — they're framework idioms, not domain nulls.

Getting started

Prerequisites

  • Node ≥ 22.11 — Metro requires Node 20+. This repo pins Node 24 via .nvmrc:
    nvm use        # picks up .nvmrc → Node 24
  • Android: Android SDK + an emulator (or device). Native builds require NDK 27.1.12297006 and CMake 3.22.x (the versions RN 0.86 expects — newer NDKs are not compatible). Install via Android Studio's SDK Manager (enable Show Package Details to pick the exact NDK version) or:
    sdkmanager "ndk;27.1.12297006" "cmake;3.22.1"

Run

Start Metro, then build to a device/emulator:

npm start              # Metro dev server (port 8081)
npm run android        # build + install + launch on Android
# npm run ios          # iOS (requires Xcode + `bundle exec pod install`)

Edits hot-reload via Fast Refresh.

Scripts

npm start              # Metro
npm run android        # run on Android
npm run ios            # run on iOS
npm test               # Jest
npm run lint           # ESLint
npx tsc --noEmit       # typecheck

Troubleshooting

  • configs.toReversed is not a function when starting Metro → Node is too old. Run nvm use (Node 24).
  • NDK ... did not have a source.properties file / [CXX1101] → corrupt or missing NDK. Reinstall ndk;27.1.12297006.
  • clang: error: unsupported option '-arch' during the C++ build → wrong NDK version installed. RN 0.86 needs exactly 27.1.12297006.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages