Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
86a8785
Add initial lessons
thgaskell May 12, 2025
1d6f866
Bump docusaurus packages
thgaskell May 12, 2025
3801b99
Update install step to suppress rc version error
thgaskell May 12, 2025
c9df972
Update serve url
thgaskell May 12, 2025
a4bbd67
Revise code snippets for lessons 1 and 2
thgaskell May 13, 2025
7afbff9
Update initial commit
thgaskell May 13, 2025
a3f1803
Update lesson-1.mdx
jaygiang May 19, 2025
ab59ad5
Split up code snippet
jaygiang May 19, 2025
5306cc2
Use canary release for counter start code block line numbering
jaygiang May 20, 2025
5fdb3d3
Use showLineNumber start
jaygiang May 20, 2025
598a729
Add in GridContainer and update snippet organization
jaygiang May 21, 2025
c1bc127
Fix headings for lesson-1 for docusaurus right sidebar readability
jaygiang May 27, 2025
89b3ae2
Cleanup and edit lesson 2
jaygiang May 27, 2025
7599728
Update docusaurus core to 3.8.0
thgaskell May 27, 2025
f113d34
Fix merge conflict
thgaskell May 27, 2025
a5fb080
Remove diff from GridContainer snippet copy
jaygiang May 29, 2025
b7d51e3
Fix type with formData
jaygiang May 29, 2025
63d5cad
Merge pull request #187 from NMFS-RADFish/lesson-2-cleanup
jaygiang May 29, 2025
1d1334e
Merge pull request #186 from NMFS-RADFish/lesson-1-cleanup
jaygiang May 29, 2025
b9dfb07
Update lesson-1 and lesson-2 for clarity and accuracy in code snippets
jaygiang Jun 1, 2025
e437431
Add model configuration explanation
jaygiang Jun 1, 2025
7cdeb22
Refactor lesson-3 to enhance trip data handling and navigation logic
jaygiang Jun 1, 2025
0fc7229
Add testing for data collection to lesson-2
jaygiang Jun 3, 2025
bc70f2f
Enhance lesson-2 and lesson-3 to clarify trip data handling
jaygiang Jun 3, 2025
b0f2ecd
Implement catch logging functionality in lesson-4, including RADFish …
jaygiang Jun 3, 2025
ff21e88
Refactor lesson-2 to improve form accessibility and clarity by adding…
jaygiang Jun 6, 2025
61303bb
Refactor lesson-3 to streamline trip data submission and navigation, …
jaygiang Jun 6, 2025
fe168ee
Merge branch 'lesson-3-cleanup' into lesson-4-cleanup
jaygiang Jun 8, 2025
8bd8aa2
Update lesson-2 and lesson-5 to enhance form validation by standardiz…
jaygiang Jun 9, 2025
ea0504b
Fix syntax
jaygiang Jun 9, 2025
e17c115
Update showLineNumber values
jaygiang Jun 10, 2025
647e849
Add missing model and component steps
jaygiang Jun 10, 2025
1713b57
Add multi-step warning
jaygiang Jun 11, 2025
4fe4a5a
Enhance lesson-6 and added screenshots
jaygiang Jun 12, 2025
9d5b27f
Fix markdown errors
jaygiang Jun 12, 2025
264eae2
Update lesson-6 to clarify navigation details for pre-built confirmat…
jaygiang Jun 13, 2025
dec3647
Enhance lesson-6 with detailed explanations of useEffect
jaygiang Jun 15, 2025
b2fd4c5
Add lesson-7: Implement server submission with offline support
jaygiang Jun 15, 2025
af00231
Update lesson-1.mdx
thgaskell Jun 17, 2025
3859e19
Update lesson 1
jaygiang Jun 17, 2025
6b290da
Update lesson 2
jaygiang Jun 17, 2025
708d72c
Update lesson 3 and 4
jaygiang Jun 17, 2025
e956429
Update lessons 1, 4, 5, 6, and 7 with improved explanations
jaygiang Jun 17, 2025
2d801bc
Update showLineNumbers
jaygiang Jun 17, 2025
8e91824
Change describedby id and fix diff highlight in reviewSubmit
jaygiang Jun 17, 2025
9442240
Update lesson-1.mdx
thgaskell Jun 17, 2025
bcf63f4
Update line numbers for model snippets
thgaskell Jun 18, 2025
2d657e2
Add introduction.md for RADFish tutorial
jaygiang Jun 25, 2025
f150a76
Enhance introduction and lesson 1 of RADFish tutorial
jaygiang Jun 25, 2025
2a98b8a
Merge pull request #200 from NMFS-RADFish/add-learn-intro
jaygiang Jun 27, 2025
1b3597c
Refactor import statements in lesson-1.mdx to include GridContainer a…
jaygiang Jul 13, 2025
2cbdb05
Update lesson-2.mdx to include enhance form structure
jaygiang Jul 13, 2025
cceaab2
Refactor handleSubmit function in lesson-2.mdx
jaygiang Jul 13, 2025
3f0b887
Enhance lesson-3.mdx by importing and utilizing useTripNavigation hooks
jaygiang Jul 13, 2025
a5853d3
Refactor handleSubmit function in lesson-2.mdx and lesson-3.mdx to re…
jaygiang Jul 14, 2025
f87dfc0
Update lesson-2.mdx and lesson-4.mdx to utilize trip data for form fi…
jaygiang Jul 14, 2025
abc01d7
Update lesson 2 and 3
jaygiang Jul 18, 2025
810805d
Update lesson 4 with hooks and updated sections
jaygiang Jul 20, 2025
f830a9b
Implement comprehensive validation for Start Trip form in lesson-5.md…
jaygiang Jul 21, 2025
11f324b
Update delete functionality in lesson-4.mdx.
jaygiang Jul 21, 2025
35872f5
Enhance error handling in lesson-6 handleSubmit
jaygiang Jul 21, 2025
d50ec2f
Refactor handleSubmit in lesson-6.mdx to improve code snippet diff
jaygiang Jul 21, 2025
4c680d8
Enhance handleSubmit in lesson-7.mdx with structured error handling
jaygiang Jul 21, 2025
002ffdb
Fix code snippet diffs
jaygiang Jul 21, 2025
2389f46
Refactor lessons 1-6 to incorporate Layout component for consistent s…
jaygiang Jul 21, 2025
9f18b52
Remove all showLineNumbers
jaygiang Jul 24, 2025
43a42a4
Enhance lesson-2.mdx by clarifying FormGroup usage, updating handleDa…
jaygiang Aug 8, 2025
a8dc2ae
Refactor StartTrip component in lesson-3.mdx to improve function decl…
jaygiang Aug 8, 2025
df0454f
Rename Form to TripForm and Catch to CatchForm
jaygiang Aug 14, 2025
6ef163d
Refactor lesson components to standardize naming conventions.
jaygiang Aug 15, 2025
bee5d0a
Remove unused imports for Grid and StepIndicator components.
jaygiang Aug 15, 2025
332a2c6
Update lesson-3.mdx to improve clarity on store and collection names.
jaygiang Aug 15, 2025
488dda8
Refactor lesson-3.mdx to standardize store naming, clarify trip data …
jaygiang Aug 15, 2025
f40895c
Enhance lesson-4.mdx by clarifying custom hooks.
jaygiang Aug 15, 2025
9c9cd21
Clarify useTripNavigation hook.
jaygiang Aug 15, 2025
44cfba5
Enhance lesson-4.mdx by summarizing the power of custom hooks and cla…
jaygiang Aug 17, 2025
0040671
Enhance lesson-2.mdx by clarifying the role of FormGroup.
jaygiang Aug 17, 2025
72c0daf
Refactor lesson-3.mdx and lesson-5.mdx to optimize imports, enhance e…
jaygiang Aug 18, 2025
f366d0c
Enhance lesson-5.mdx by implementing comprehensive error handling for…
jaygiang Aug 19, 2025
0f311d5
Enhance lesson-5.mdx by adding detailed validation and error display …
jaygiang Aug 19, 2025
0178435
Enhance lesson-5.mdx by adding comprehensive state management details.
jaygiang Aug 19, 2025
0b77ab0
Enhance lesson-6.mdx by adding import instructions for required utili…
jaygiang Aug 19, 2025
d45d000
Update lesson-7.mdx code snippets by adding more reference code.
jaygiang Aug 19, 2025
ef4f560
Enhance lesson-3.mdx by updating navigation instructions and adding a…
jaygiang Aug 20, 2025
b449bd4
Enhance lesson-6.mdx by updating offline functionality instructions, …
jaygiang Aug 20, 2025
f2b4e4e
Enhance lesson-7.mdx by adding detailed steps for online trip submiss…
jaygiang Aug 20, 2025
5a0e691
Update lesson-5.mdx by updating trip creation instructions to use tri…
jaygiang Aug 21, 2025
363c2b7
Refactor lesson-3.mdx to optimize import paths and clarify tripId usa…
jaygiang Aug 21, 2025
b848ef5
Clarify existing state management details in lesson-5.mdx by indicati…
jaygiang Aug 21, 2025
5c9de59
Remove commented-out "Learn" sidebar configuration from docusaurus.co…
jaygiang Aug 21, 2025
17f21ca
Update learning lessons
thgaskell Aug 23, 2025
9091fd8
Ignore diff-remove lines while copying
thgaskell Aug 23, 2025
39abedb
Synchronize expected documentation diffs with code diffs
thgaskell Aug 23, 2025
5e8a69f
Clean up
thgaskell Aug 23, 2025
a06d0f5
Update lesson 3 initial tripData
thgaskell Aug 23, 2025
d18486b
Update documentation
thgaskell Aug 26, 2025
6f0ed47
Bump node version
thgaskell Aug 26, 2025
937fbc8
Resolve package-lock conflicts
thgaskell Aug 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20

- name: Install dependencies
run: npm install
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20

- name: Install dependencies
run: npm install
Expand Down
78 changes: 78 additions & 0 deletions docs/learn/introduction.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
sidebar_position: 0
description: Learn to build an offline-first fisheries data collection app with RADFish
title: Introduction
---

# Learn RADFish

Welcome to the RADFish tutorial! In this comprehensive guide, you'll learn how to build a complete **Fisheries Trip Logging Application** using RADFish, NOAA's React framework for offline-first data collection.

## The App We're Building

Throughout this tutorial, you'll build a fisheries data collection application that commercial fishermen can use to log their trips and catches. This Progressive Web App (PWA) works offline and syncs data when connectivity is restored.

![Fisheries Trip Logging Application](./src/assets/intro.png)

### Key Features You'll Implement

- **🚢 Trip Management**: Start and end fishing trips with date, time, and weather conditions
- **🐟 Catch Logging**: Record detailed information about each fish caught (species, weight, length, coordinates, time)
- **📝 Dynamic Forms**: Build interactive forms with repeatable catch entry
- **📊 Data Review**: Display aggregated catch statistics organized by species using tables
- **📱 Offline-First**: Full functionality without internet connection using IndexedDB
- **🔄 Server Sync**: Send data to backend APIs when online using JSON server
- **⚡ Progressive Web App**: Offline-first and mobile-optimized

## What You'll Learn

By the end of this tutorial, you'll understand how to:

### RADFish Core Concepts
- **Offline Storage**: Use IndexedDB with RADFish schemas and collections
- **State Management**: Manage application state with RADFish hooks
- **Data Relationships**: Link related data across collections (trips and catches)

### React & USWDS Integration
- **Component Architecture**: Build accessible forms using Trussworks React USWDS components
- **Navigation**: Implement multi-step workflows with React Router
- **Form Validation**: Implement client-side validation with user-friendly error handling
- **Responsive Design**: Create mobile-first layouts following federal design standards

### Progressive Web App Features
- **Network Detection**: Provide dynamic UI feedback based on connectivity using `useOfflineStatus`
- **Data Synchronization**: Handle online/offline data persistence and sync patterns

## Learning Path

This tutorial is divided into 7 progressive lessons:

1. **Page Structure & Navigation** - Set up USWDS grid layouts and routing
2. **Start Trip Form Inputs** - Build date pickers, time pickers, and select components
3. **Form Submission** - Save data to offline storage with RADFish
4. **Dynamic Inputs** - Create repeatable catch logging forms with collection relationships
5. **Form Validation** - Implement validation rules and error handling across all forms
6. **Review & Tables** - Display aggregated data with computed fields and offline detection
7. **Server Submission** - Handle online/offline data synchronization with JSON server

Each lesson builds upon the previous one, gradually introducing new RADFish concepts and React patterns.

## Prerequisites

Before starting this tutorial, you should have:

- **React Knowledge**: Basic understanding of React components, hooks, and state management
- **JavaScript Fundamentals**: ES6+ syntax, async/await, and modern JavaScript concepts
- **Terminal Familiarity**: Comfortable running npm commands and navigating file systems

No prior experience with RADFish, PWAs, or offline-first development is required - we'll teach you everything you need to know!

## Ready to Start?

This tutorial takes a hands-on approach. You'll be writing code from the very first lesson, building features incrementally while learning RADFish concepts along the way.

The completed application demonstrates patterns designed for NOAA fisheries applications, making this tutorial valuable whether you're building data collection apps for scientific research, regulatory compliance, or commercial fishing operations.

---

*Having trouble? Check out our [developer documentation](/developer-documentation/getting-started) for additional RADFish resources and troubleshooting guides.*
170 changes: 170 additions & 0 deletions docs/learn/lesson-1.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import CodeBlock from "@theme/CodeBlock";

# Lesson 1: Page Structure and Navigation

Welcome to the RADFish tutorial! In this first lesson, we'll structure our main page using USWDS grid components and then implement navigation within the app by making the "Start New Trip" button functional.

## Prerequisites

Before you start, make sure you have the following installed:

- **Node.js** (v20.17.0 or later)
- **npm** (v10.8.2 or later)
- **git** (v2.0 or later)

You can verify your installations by running these commands in your terminal:

```bash
node --version
npm --version
git --version
```

## Getting Started

Clone the repository to your local machine and navigate to the project directory:

```bash
git clone https://github.com/NMFS-RADFish/learn-radfish.git
cd learn-radfish
```

Now let's build the application and serve it locally to see its current state.

1. **Install Dependencies:** Open your terminal in the project root directory and run:
```bash
npm install
```

2. **Start the Development Server:** Run the following command to start the application:
```bash
npm run start
```
This command will start the development server and make the application available at [http://localhost:3000](http://localhost:3000). Open this URL in your browser.

## Step 1: Structure the Page with USWDS Grid Components

We'll begin by structuring our `HomePage` using `GridContainer` and `Grid` components from the U.S. Web Design System (USWDS). This is a common practice in RADFish applications to ensure consistent layout, responsiveness, and alignment with USWDS standards. These components help center content and manage its maximum width.

For more detailed information on the grid components we are using, see these resources:

- **[Trussworks React USWDS Grid documentation](https://trussworks.github.io/react-uswds/?path=/docs/components-grid--docs)** - Detailed information on the React components (`GridContainer`, `Grid`) from `@trussworks/react-uswds`
- **[Official USWDS Layout Grid documentation](https://designsystem.digital.gov/utilities/layout-grid/)** - Understanding the foundational CSS grid system and principles upon which these components are built

### 1.1: Import Grid Components

In `src/pages/Home.jsx`, update your import statement from `@trussworks/react-uswds` to also include `GridContainer`. Your existing import for `Button` and `Grid` will be modified as follows:

```jsx title="src/pages/Home.jsx" showLineNumbers=5
import "../index.css";
import React, { useState, useEffect } from "react";
import { useApplication, useOfflineStatus } from "@nmfs-radfish/react-radfish";
import { useNavigate } from "react-router-dom";
//diff-remove-start
import { Button, Grid } from "@trussworks/react-uswds";
//diff-remove-end
//diff-add-start
import { Button, GridContainer, Grid } from "@trussworks/react-uswds";
//diff-add-end
```

### 1.2: Apply the Grid Structure

Next, modify the `return` statement of your `HomePage` component to incorporate the USWDS grid. You will wrap your main page content (everything inside the main `<>...</>` fragment, except for the sticky footer) with these components.

**Add the `GridContainer` structure around your main page content:**

```jsx title="src/pages/Home.jsx"
return (
<>
{/* Main Content - Basic structure without USWDS grid components */}
//diff-remove-start
<div className="padding-y-4 padding-x-2 text-center">
//diff-remove-end
//diff-add-start
<GridContainer className="padding-y-4 padding-x-2 text-center">
<Grid row>
<Grid col="fill">
//diff-add-end
{/* All your main page content (headings, lists, etc.) goes here */}
<h1 className="font-heading-xl text-center margin-0">Hi, Captain</h1>
<h2 className="font-heading-lg text-center margin-top-4 margin-bottom-2">
Recent Trips
</h2>
{/* Example: trips.map(...) or conditional messages */}
//diff-remove-start
</div>
//diff-remove-end
//diff-add-start
</Grid>
</Grid>
</GridContainer>
//diff-add-end

{/* Sticky footer remains outside the GridContainer */}
<footer className="position-fixed bottom-0 ...">
{/* ... footer content ... */}
</footer>
</>
);
```

**Why `GridContainer`?**

The `GridContainer` component from USWDS is crucial for maintaining a consistent layout. It centers your content on the page and applies a maximum width (e.g., 1024px on desktop by default), preventing content from stretching uncomfortably wide on larger screens. The `Grid row` serves as a necessary container for grid columns, and `Grid col="fill"` allows the column to expand and take up the available space within that row.

## Step 2: Implement "Start New Trip" Navigation

Currently, the "Start New Trip" button on the home page doesn't do anything. We need to make it navigate the user to the first step of the trip logging process, which will be at the `/start` route. We'll use the `useNavigate` hook from `react-router-dom` for this.

### Understanding React Router Navigation

React Router provides the `useNavigate` hook for programmatic navigation. Let's look at how it's already set up in your component:

**1. Import Statement:**

```jsx title="src/pages/Home.jsx"
import { useNavigate } from "react-router-dom";
```

**2. Hook Initialization:**

```jsx title="src/pages/Home.jsx"
const navigate = useNavigate();
```

The `useNavigate` hook returns a function that we store in the `navigate` variable. This function allows us to programmatically change the current route (URL) in our application.

### 2.1: Add the Navigation Handler

Now we'll use the `navigate` function to make the "Start New Trip" button functional. Find the `Button` component for "Start New Trip".

**Add the `onClick` handler code:**

```jsx title="src/pages/Home.jsx"
<Button
type="button"
className="bg-primary hover:bg-primary-darker width-full"
//diff-add-start
onClick={() => {
navigate("/start");
}}
//diff-add-end
>
Start New Trip
</Button>
```

**Explanation:**

- We're adding an `onClick` event handler to the `Button`.
- Inside the handler, we call the `navigate` function (which we get from the `useNavigate()` hook provided earlier in the component).
- We pass the string `"/start"` to `navigate`, telling React Router to change the URL to `/start` when the button is clicked. This will cause the `App` component to render the `StartTrip` page component associated with that route.

**Test Navigation:**

- Click the "Start New Trip" button. You should now be navigated to a new page (which is currently blank or basic, as we haven't built the `StartTrip` form yet).

## Conclusion

In this lesson, you learned how to structure your page using USWDS `GridContainer` and `Grid` components for a consistent layout. You also implemented the first navigation feature, linking the home page button to the start of the trip logging workflow using React Router. The application now has a better-structured main page and a functional starting point for logging a new trip.
Loading